⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fato.c

📁 一个用LP2148实现的MP3工程
💻 C
字号:
#define IN_FAT
#include "User.h"
#include "UNICODE.H"

#define MAX_DIR_NU_List 20
#define MAX_CACHE_SIZE 580


DIR_LIST *pF;
DIR_LIST Superior_Dir,Current_Dir;
FDI Valid_FDI;

struct QueueDL
{
	DIR_LIST Directory_List[MAX_DIR_NU_List];
	INT8U front,rear,len;
}QU_DIR_List;

struct QueueDC
{
	INT8U Buf[MAX_CACHE_SIZE];
	INT16U front,rear,len;
	INT16U MaxSize;
}Disk_Cache;

extern Disk_Info * GetDiskInfo(INT8U DriveID);

void IintQueueDL(struct QueueDL *Q)
{
	Q->front = 0;
	Q->rear = 0;
	Q->len = 0;
}

void EnQueueDL(struct QueueDL *Q, DIR_LIST *x)
{//向队列插入元素
	
	if((Q->rear  == Q->front) && Q->len != 0)
	{//队列满时将产生覆盖
		Q->front = (Q->front + 1) % MAX_DIR_NU_List; //使队首元素指向下一个位置
	}
	Q->Directory_List[Q->rear].FstClu = x->FstClu; 
	Q->Directory_List[Q->rear].FileSize = x->FileSize;
	Q->Directory_List[Q->rear].Attr = x->Attr;
	Q->rear = (Q->rear + 1) % MAX_DIR_NU_List;//求出新队尾
	if(Q->len < MAX_DIR_NU_List)
		Q->len += 1;//队列长度加1
}

DIR_LIST *GetElemQDL(struct QueueDL *Q,INT8U pos)
{//读取POS位置的元素
	
	if(pos < 1 || pos > MAX_DIR_NU_List)
		return((void *)0);
	return(&Q->Directory_List[(Q->front + pos - 1) % MAX_DIR_NU_List]);
}

void InitQueueDC(struct QueueDC *Q)
{
	Q->front = 0;
	Q->rear = 0;
	Q->len = 0;
	Q->MaxSize = 576;
}

void EnQueueDC(struct QueueDC *Q,INT8U x)
{//不考虑队列满的情况,实际使用中不出现这种情况
	
	Q->Buf[Q->rear] = x;//新值赋给队尾
	Q->rear = (Q->rear + 1) % Q->MaxSize;//求出队尾的下一个位置
	if(Q->len < Q->MaxSize)
		Q->len += 1;//队列长度+1
}

INT8U PeekQueueDC(struct QueueDC *Q)
{
	INT8U temp;
	temp = Q->Buf[Q->front];//取出队首元素
	Q->front = (Q->front + 1) % Q->MaxSize;//求出新队首位置
	if(Q->len >0)
		Q->len -= 1;//队列长度-1
	return(temp);
}

void Uincode_to_GB(INT16U * x)
{//UNICODE码转换为GB2313汉字编码

 	INT16U a,b,c;
 	if(((*x) >= 0x0020) && ((*x) <= 0x007E))
 	{
 		if((*x) >= 'a' && (*x) <= 'z')
 		(*x)-='a'-'A';
 		*x+=0xA380;
 		return;
 	}
 	if((*x)<Unicode[0][0])
 	{
 		*x=0x3F3F;
 		return;
 	}
 	if((*x)>Unicode[UNICODE_MAX-1][0])
 	{
 		*x=0x3F3F;
 		return;
 	}
 	a=0;
 	b=UNICODE_MAX-1;
 	do        //采用二分查表法,因为该表为顺序表
 	{
   		c=(a+b)/2;
   		if((*x)==Unicode[c][0])
   		{
   			*x=Unicode[c][1];
   			return;
   		}
   		if((*x)<Unicode[c][0])
   		{
   			b=(a+b)/2;
   		}
   		else 
   		{
   			a=(a+b+1)/2;
   		}
 	} while(a!=b);
 	if((*x)==Unicode[a][0])
 	{
 		*x=Unicode[a][1];
 		return;
 	}
 	*x=0x3F3F;  //如果找不到,则显示??
}

void Print_DIR_List(INT16U SecOfDir,INT32U FistDirSecNum)
{//显示目录项
	INT16U i,j,k;
	INT8U Sname[18];
	INT8U temp8u,List_NU=0;
	SDIR sSDIR;
	DIR_LIST DIR_LISTx;
	SDIR *pSD;
	INT8U Data_Buf[512];
	Disk_Info *pDI;
	Disk_RW_Parameter DP;
	
	pSD = &sSDIR;
	pDI = GetDiskInfo('A');
	for(i = 0;i < SecOfDir;i++)
	{
		DP.SectorIndex = FistDirSecNum + i;
		DP.Buf = Data_Buf;
		(* pDI->DiskDrive)(ReadSec, &DP);
		for(j=0;j<512;(j+=32))
		{
			pSD->SName[0] = Data_Buf[j + OFSDIR_SName];
			pSD->SName[1] = Data_Buf[j + OFSDIR_SName + 1];
			pSD->Attr = Data_Buf[j + OFSDIR_Attr];
			if(((pSD->Attr & ATTR_LONG_NAME_MASK) != ATTR_LONG_NAME) && (pSD->SName[0] != 0xE5) && (pSD->SName[0] != 0))
			{//找到一个活动的短目录项
				
				if((pSD->Attr & ATTR_VOLUME) == 0)
				{//找到一个文件或子目录
					
					if((pSD->SName[0] != '.') && (pSD->SName[1] != '.'))
					{
						List_NU++;
						for(k=2;k<=10;k++)
						{
							pSD -> SName[k] = Data_Buf[j + OFSDIR_SName + k];
						}
						if(List_NU/100 != 0)
							Sname[0] = List_NU/100 + 48;
						else
							Sname[0] = ' ';
						temp8u = List_NU%100;
						if(List_NU/10 != 0)
							Sname[1] = temp8u/10 + 48;
						else
							Sname[1] = ' ';
						Sname[2] = temp8u % 10 + 48;
						Sname[3] = '-';
						temp8u=4;
						for(k=0;k<=10;k++)
						{
							if(pSD -> SName[k] != 0x20)
							{
								if(k == 8)
								{
									Sname[temp8u] = '.';
									temp8u++;
								}
								Sname[temp8u] = pSD->SName[k];
								temp8u++;
							}
						}
						Sname[temp8u] = '\n';
						Sname[temp8u+1] = '\0';
						Sname[16] = '\n';
						Sname[17] = '\0';
						pSD->FstCluH = Data_Buf[j + OFSDIR_FstCluH + 1]*256 + 
									   Data_Buf[j + OFSDIR_FstCluH];
						pSD->FstCluL = Data_Buf[j + OFSDIR_FstCluL +1 ]*256 + 
									   Data_Buf[j + OFSDIR_FstCluL];
						pSD->FileSize =  ((INT32U)Data_Buf[j + OFSDIR_FileSize + 3] << 24) | 
										 ((INT32U)Data_Buf[j + OFSDIR_FileSize + 2] << 16) | 
										 ((INT32U)Data_Buf[j + OFSDIR_FileSize + 1] << 8)  | 
										 ((INT32U)Data_Buf[j + OFSDIR_FileSize]);
						DIR_LISTx.FstClu = ((INT32U)pSD->FstCluH << 16) | pSD->FstCluL;
						DIR_LISTx.FileSize = pSD->FileSize;
						DIR_LISTx.Attr = pSD->Attr;
						EnQueueDL(&QU_DIR_List,&DIR_LISTx);
						uar_putchar(Sname);
					}
					else if(pSD->SName[1] == '.')
					{//指向上层目录
						
						pSD->FstCluH = Data_Buf[j + OFSDIR_FstCluH + 1]*256 + 
									   Data_Buf[j + OFSDIR_FstCluH];
						pSD->FstCluL = Data_Buf[j + OFSDIR_FstCluL +1 ]*256 + 
									   Data_Buf[j + OFSDIR_FstCluL];
						pSD->FileSize =  ((INT32U)Data_Buf[j + OFSDIR_FileSize + 3] << 24) | 
										 ((INT32U)Data_Buf[j + OFSDIR_FileSize + 2] << 16) | 
										 ((INT32U)Data_Buf[j + OFSDIR_FileSize + 1] << 8)  | 
										 ((INT32U)Data_Buf[j + OFSDIR_FileSize]);
						Superior_Dir.FstClu = ((INT32U)pSD->FstCluH << 16) | pSD->FstCluL;
						Superior_Dir.FileSize = pSD->FileSize;
						Superior_Dir.Attr = pSD->Attr;
					}
				}
			}
			else if(pSD->SName[0] == 0x00)
			{//此目录为空,并且后续的磁盘空间都为空
				
				i = 0xFFF0;
				break;
			}
		}
	} 
}

INT32U GetNextClu(INT32U Index)
{
	INT32U  FATOffset;
	INT32U  NextClu;                //下一个簇号
	INT32U  ThisFATSceNum;			//FAT表中包含该簇号N的扇区号
	INT16U  ThisFATEntOffset;		//该簇号N位于FAT表中FAT项的偏移量
	INT8U   Data_Buf[512];
	Disk_Info *pDI;
	Disk_RW_Parameter DP;
	
	pDI = GetDiskInfo('A');
	switch(pDI->FilSysType)
	{
		case FAT16:
			FATOffset = Index * 2;
			ThisFATSceNum = FATOffset / pDI->BytsPerSec + pDI->RsvdSecCnt + pDI->RelaStaSect;
			DP.SectorIndex = ThisFATSceNum;
			DP.Buf = Data_Buf;
			(* pDI->DiskDrive)(ReadSec, &DP);
			ThisFATEntOffset = FATOffset % pDI->BytsPerSec;
			NextClu = Data_Buf[ThisFATEntOffset] | (Data_Buf[ThisFATEntOffset + 1] << 8);
	        break;
	}
	return(NextClu);
}

void DIR(DIR_LIST *Directory_List)
{
	INT32U	FirstSectorOfCluster;	//给定一个簇号N,该簇的第一个扇区
	INT16U  NextCluOfFAT16,temp;
	Disk_Info *pDI;
	
	pDI = GetDiskInfo('A');
	
	if((Directory_List == NULL) || (Directory_List->FstClu == 0))  
	{//进入根目录   
		
		if(pDI->FilSysType == FAT16)
		{
			pDI->FistRootDirSecNum = pDI->RsvdSecCnt + (pDI->NumFATs * pDI->FATSz16) + pDI->RelaStaSect;
			Print_DIR_List(pDI->RootDirSectors,pDI->FistRootDirSecNum);
		}
	}
	else if(Directory_List != NULL)
	{//进入子目录
	
		if(pDI->FilSysType == FAT16)
		{
			FirstSectorOfCluster = ((Directory_List->FstClu - 2) * pDI->SecPerClus) + pDI->FirstDataSector;
			NextCluOfFAT16 = (INT16U)GetNextClu(Directory_List->FstClu);
			do
			{
				Print_DIR_List(pDI->SecPerClus,FirstSectorOfCluster);
				FirstSectorOfCluster = ((NextCluOfFAT16 - 2) * pDI->SecPerClus) + pDI->FirstDataSector;
				temp = NextCluOfFAT16;
				NextCluOfFAT16 = (INT16U)GetNextClu(temp);
			} while((NextCluOfFAT16 >= 0x0002) && (NextCluOfFAT16 <= 0xFFEF));
		}
	}
}

void ChDir(DIR_LIST *pList)
{//改变当前目录

	IintQueueDL(&QU_DIR_List);
	DIR(pList);
}

void ReadFile(DIR_LIST *pList)
{//读取文件,一次读取512个数据
	
	INT32U  SurplusLen,temp;
	INT8U   Data_Buf[512];
	Disk_Info *pDI;
	Disk_RW_Parameter DP;
	
	pDI = GetDiskInfo('A');
	if(pDI->FilSysType == FAT16)
	{
		if(Valid_FDI.Read_Flag == 0)
		{
			Valid_FDI.FirstSectorOfCluster = ((pList->FstClu - 2) * pDI->SecPerClus) + pDI->FirstDataSector;
			Valid_FDI.NextCluOfFAT16 = (INT16U)GetNextClu(pList->FstClu);
			Valid_FDI.FileLen = 0;
			Valid_FDI.OffsetCluSce = 0;
			Valid_FDI.Read_Flag = 1;
		}
		if(Valid_FDI.FileLen < pList->FileSize)
		{
			if(Valid_FDI.OffsetCluSce < pDI->SecPerClus)
			{
				DP.SectorIndex = Valid_FDI.FirstSectorOfCluster + Valid_FDI.OffsetCluSce;
				DP.Buf = Data_Buf;
				(* pDI->DiskDrive)(ReadSec, &DP);
				Valid_FDI.OffsetCluSce += 1;
				SurplusLen = pList->FileSize - Valid_FDI.FileLen;
				if(SurplusLen >= 512)
				{
					UART_print(Data_Buf,512);
					Valid_FDI.FileLen += 512;
				}
				else
				{
					UART_print(Data_Buf,SurplusLen);
					Valid_FDI.FileLen += SurplusLen;
					Valid_FDI.Read_Flag = 0;
					return;
				}
			}
			else if((Valid_FDI.NextCluOfFAT16 >= 0x0002) && (Valid_FDI.NextCluOfFAT16 <= 0xFFEF))
			{
				Valid_FDI.OffsetCluSce = 0;
				temp = Valid_FDI.NextCluOfFAT16;
				Valid_FDI.FirstSectorOfCluster = (temp - 2) * pDI->SecPerClus + pDI->FirstDataSector;
				Valid_FDI.NextCluOfFAT16 = (INT16U)GetNextClu(temp);
			}
			else uar_putchar((void *)("file end "));
		}
	}
}

DIR_LIST *OpenFile(INT8U File_ID)
{//打开文件

	return(GetElemQDL(&QU_DIR_List,File_ID));
}

void FileOperation(INT8U List_NU)
{
	
	if(List_NU == '/')
	{//显示根目录
		ChDir(NULL);
		return;
	}
	else if(List_NU == '*')
	{//返回上层目录
		ChDir(&Superior_Dir);
		return;
	}
	else if(List_NU == '.')
	{//显示当前目录
		ChDir(&Current_Dir);
		return;
	}
	else if(List_NU == 'c')
	{//继续读取文件中数据
		if(pF != NULL)
		 ReadFile(pF);
	}
	else
	{
		pF = OpenFile(List_NU);
		if((pF->Attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0x00)
		{//读收文件中数据
			
			Valid_FDI.Read_Flag = 0;
			InitQueueDC(&Disk_Cache);
			if(pF != NULL)
				ReadFile(pF);
		}
		else if((pF->Attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == ATTR_DIRECTORY)
		{//改变当前目录
			
			Current_Dir.Attr = pF->Attr;
			Current_Dir.FstClu = pF->FstClu;
			Current_Dir.FileSize = pF->FileSize;
			ChDir(pF);
		}
	}
}










⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -