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

📄 file.c

📁 Hardware and firmware for a DSP based digital audio MP3 player with USB pen drive funtionality, usin
💻 C
字号:
/*
 * DSPdap-bootloader - DSP based Digital Audio Player, Bootloader
 * Copyright (C) 2004-2007 Roger Quadros <rogerquads @ yahoo . com>
 * http://dspdap.sourceforge.net
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: file.c,v 1.2 2007/06/03 08:54:03 Roger Exp $
 */

#include "file.h"
#include "CF.h"
#include "FAT32.h"

//Removes spaces after extension or last word and stores the string in 'dest'
void RemoveTrailingSpaces(const char* source, char *dest)
{
	int i;
	int lastNonSpacePos;

	// Find total string length of source string
	lastNonSpacePos = strlen(source);

	// Find last position in string which is not a space
	while (lastNonSpacePos != 0)
	{
		if (source[--lastNonSpacePos] != ' ')
			break;
	}

	//if lastNonSpacePos == 0 means entire string was filled with space
	//or string was null.
	if(lastNonSpacePos == 0)
	{
		i = 0;	//to make dest a null string.
	}
	else
	{
		// Copy from beginning of string upto last nonspace character
		for (i = 0; i <= lastNonSpacePos; i++)
			dest[i]=source[i];
	}
	dest[i] = '\0';
}


int strcmpNocase(const char* str1, const char* str2)
{
	int len;
	char c1, c2;	
	len = strlen(str1);
	if(len != strlen(str2))
	{
		//lengths don't match
		return 1;	//not equal
	}
	
	while(len > 0)
	{
		c1 = *str1++;
		c2 = *str2++;
		
		if(c1 >= 'A' && c1 <= 'Z')
		{
			c1 += 'a' - 'A';
		}
		
		if(c2 >= 'A' && c2 <= 'Z')
		{
			c2 += 'a' - 'A';
		}		   
		
		if(c1 != c2)
		{
			//not equal
			return 1;
		}
		len--;
	}
	//equal
	return 0;
}
            
//Compare two filenames to see if they match
//NOTE: This function truncates the original strings if they have any 
//trailing spaces.
int CompareFileNames(char* name1, char* name2)
{
	// Crop both strings for any trailing spaces
	RemoveTrailingSpaces(name1, name1);	//destination same as source
	RemoveTrailingSpaces(name2, name2);	//destination same as source
	
	// Compare both strings and return 1 if they match
	if (strcmpNocase(name1, name2) != 0) 
	{
		return 1;	//filenames not equal
	}
	else
		return 0;	//filenames equal
}

//converts a packed SFN file name entry into a normal file name
void Get8_3Filename(char* sfn, char* filename)
{
	int i,j, extEnd;
	
	//get first no space in filename backwards
	for(i=7; i>=0; i--)
	{
		if(sfn[i] != ' ')
			break;
	}
	i++;	//now i points to space
	
	//get first no space in extension backwards
	for(j=10; j>=8; j--)
	{
		if(sfn[j] != ' ')
			break;
	}
	
	extEnd = j;	

	//copy valid filename
	for(j=0; j<i; j++)
	{
		filename[j] = sfn[j];
	}	
	
	if(extEnd < 8)
	{
		//no extension
		filename[j] = 0;
	}
	else
	{
		filename[j++] = '.';
		//copy valid extension
		
		for(i=8; i<=extEnd; j++, i++)
		{
			filename[j] = sfn[i];
		}
		filename[j] = 0;
	}
}


//searches the given directory for the given file/directory name
//and returns the FAT32 record of the file/directory if a match is found
//returns non zero if sub directory/file of given name was not found
int GetMatchingRecord(UI32 dirCluster, char* nameToFind, DIR_ENTRY *pDirEntry)
{
	FILE fDir;
	static UI16 dirBuffer[256];	//512 bytes
	int recordIdx = 0;
	UI16* recordPtr;
	UI8 attribute;
	int i;

	fDir.feof = 0;	//mark not end of file
	fDir.startCluster = dirCluster;
	fDir.currentCluster = dirCluster;	
	fDir.currentSectorInCluster = 0;	//1st sector in cluster
	fDir.byteNum = 0;	//1st byte
	fDir.fileSize = 0xFFFFFFFF;	//set max. possible size

			
	while(1)
	{
		if(fread_sector(&fDir, dirBuffer, &i) != 0)
		{       
			//Either EOF or error
			return -2;
		}
		//start searching in the sector for the given directory entry	
		//there are 16 FAT32 records (32 bytes) in 1 sector (512 bytes)
		for(recordIdx = 0; recordIdx < 16; recordIdx++)
		{
			//get pointer to 1 FAT32 record at recordIdx
			recordPtr = &dirBuffer[recordIdx*16];	//*16 since 1 record is 32 bytes (i.e. 16 words)
			
			switch(Get8BitWord(recordPtr, 0))
			{
				case 0:
					//directory ended, stop searching
					return -3;

				case 0xE5:                  
					//directory entry is free so skip this entry and go to next
					continue;	//continue for loop next iteration.
				
				//can add invalid name checks here.
				
				default:
					//found a FAT32 record.. check if it is a valid entry
					//get attribute byte
					attribute = Get8BitWord(recordPtr, 11);
					
					if( (attribute & ATTR_LFN_MSK) == ATTR_LFN)
					{
						//long name entry.
						//do nothing
					}
					else if(attribute & ATTR_VOLID)
					{
						//volume ID so ignore
					}
					else
					{   
						//This is a Short name entry
						GetDirEntryFromBuffer(recordPtr, pDirEntry);					

							//if file entry (i.e. SFN) then convert 8.3 packed name to normal filename
							if( (pDirEntry->Attr & ATTR_DIR) == 0)
							{
								//it is a file
								Get8_3Filename((char *)pDirEntry->Name, (char *)pDirEntry->Name);
							}
							//check if the given name matches the name in record
							if(CompareFileNames((char*)pDirEntry->Name, nameToFind) == 0)
							{
								//found a matching entry...save it in output argument
								return 0;
							}
					}
			}
		}
	}
}


FILE file;	//static allocation.. should be made dynamic when multiple file support required.
//opens a file handle to the file in the given path.
//NOTE: Multiple file open not yet supported.
FILE *fopen(char* fileName)
{
	UI32 dirCluster;
	DIR_ENTRY dirEntry;

	FILE *fp;
	
	fp = &file;

	fp->feof = 0;	//mark not end of file
	fp->currentSectorInCluster = 0;	//1st sector in cluster
	fp->byteNum = 0;	//1st byte
	fp->bufferedWords = 0;	//read buffer empty
	fp->bufferIdx = 0;	//point to start of buffer
	
	//Get the root directory start cluster
	dirCluster = FAT32.root_begin_cluster;
	if(dirCluster == 0xFFFFFFFF)
	{
		//could not open directory
		return 0;
	}
	else
	{
		//Get to file record of the required file from the directory
		if(GetMatchingRecord(dirCluster, fileName, &dirEntry) != 0)
		{
			//did not find the required file
			return 0;
		}
		else
		{
			//update file pointer members	
			fp->startCluster = dirEntry.FirstCluster;
			fp->currentCluster = dirEntry.FirstCluster;
			fp->fileSize = dirEntry.FileSize;
		}
	}
	
	return fp;
}

//reads next sector from the file stream into the given buffer.
int fread_sector(FILE *fp, void* buffer, int* pBytesRead)
{
	  UI32 LBAtoRead;

	  if(fp->feof)
	  {
		*pBytesRead = 0;
	  	return -1;	//already end of file.
	  }
	  
	  // Get LBA of sector to read = cluster start LBA address + sector offset
	  LBAtoRead = FAT32_GetStartLBAofCluster(fp->currentCluster) + fp->currentSectorInCluster;
	  
	  //increment sector
	  fp->currentSectorInCluster++;
	  *pBytesRead = 512;	//will change it if last sector of file.
	  
	  if(fp->currentSectorInCluster == FAT32.sectors_per_cluster)
	  {
	  	//all sectors in current cluster exhausted.. find next cluster
	  	
	  	//reset parameters
	  	fp->currentSectorInCluster = 0;
	  	//find next cluster
	  	fp->currentCluster = FAT32_FindNextCluster(fp->currentCluster);
	  	if(fp->currentCluster == 0xFFFFFFFF)
	  	{
	  		//got end of file
	  		fp->feof = 1;	//mark EOF flag
	  		//bytesRead will be <= 512
	  		*pBytesRead = fp->fileSize - fp->byteNum;
	  	}
	  }	  
	  
	  //read the sector into buffer
	  if(CF_ReadSector(LBAtoRead, buffer))
	  	return -2;	//error reading sector
	  else
	  {
	  	fp->byteNum += *pBytesRead;
	  	return 0;	//success
	  }
}

//returns number of words read
int fread(FILE *fp, void* buffer, int wordsToRead)
{
	static UI databuf[256];	//data buffer used by fread()
	UI* ptr;
	int wordsRead = 0;
	int bytesRead;
	UI word;

	ptr = (UI*)buffer;
	if(fp->feof && (fp->bufferedWords == 0))
	{
		return 0;	//already end of file.
	}

	while(wordsRead < wordsToRead)
	{
		if(fp->bufferedWords == 0)
		{
			//read buffer empty..so refill it
			if(fread_sector(fp, databuf, &bytesRead))
			{
				//error or EOF
				break;
			}
			fp->bufferedWords = bytesRead/2;
			fp->bufferIdx = 0;
		}
		word = databuf[fp->bufferIdx++];
		*ptr++ = (word>>8)&0xFF | (word<<8)&0xFF00;	//swap bytes in word
		fp->bufferedWords--;
		wordsRead++;
	}	
	return wordsRead;
}

⌨️ 快捷键说明

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