|
楼主 |
发表于 2008-11-17 02:30:32
|
显示全部楼层
以下是一段MP3播放器的FAT16文件模块,使用本C编译器编译。由于PIC16Fxx芯片内存太少,
且功能受限(不搜索子目录)。主要目的是提示如何使用本编译器。
///////////////////////////////////////////////////////////////////////////////
//
// Name: MMCFILE.C
//
// NOTE: this file system only supports FAT(16) format!
//
///////////////////////////////////////////////////////////////////////////////
#include <16f887.h>
#include "define.h"
#include "mmcspi.h"
#include "mmcfile.h"
#include "lcd3310.h"
/* --- --- */
#define SIGNATURE1 0x55 // signature(1) of file system
#define SIGNATURE2 0xaa // signature(2) of file system
typedef enum {FAT12, FAT16, FAT_UNKNOWN} FAT_TYPE;
#define HOT_CLUSTER(c) ((FILE_entry.fatType == FAT12)? ((c) && (c) < 0xff6): ((c) && (c) < 0xfff6))
#define END_CLUSTER(c) ((FILE_entry.fatType == FAT12)? ((c)>= 0x0ff8): ((c)>= 0xfff8))
#define IS_SUBDIR(c) ((c & 0x3c) == 0x10)
#define IS_ARCHIV(c) ((c & 0x3c) == 0x20)
typedef struct {
char seqNum;
char name1[10];
unsigned char attrib;
unsigned char reserve;
unsigned char chkSum;
char name2[12];
unsigned int startCluster;
char name3[4];
} LFNDirEntry_t; // VFAT long file name entry
// globally available buffer
bank2 unsigned char FILE_tempBuf1[MMC_SECTOR_SIZE/8];
bank3 FileDesc_t fileDesc;
bank3 FileEntry_t FILE_entry;
///////////////////////////////////////////////////////////////////////////////
char FILE_InitEntry (void) @ bank2
{
BootSector_t bank2 *pp = FILE_tempBuf1;
if ( MMC_ReadSegOffset (FILE_tempBuf1, 0, 510) == MMC_OK )
{
if ( FILE_tempBuf1[0] == SIGNATURE1 && FILE_tempBuf1[1] == SIGNATURE2 )
{
if ( MMC_ReadSegOffset (FILE_tempBuf1, 0, 446) != MMC_OK )
return FILE_ERR_FMT;
Partition_t bank2 *p = FILE_tempBuf1;
if ( !(p->bootType & 0x7f) &&
( p->fileSysType == 0x04 || p->fileSysType == 0x06 ) )
{
FILE_entry.startSector = p->firstSector; // only access partition-1 !!!
}
else
{
FILE_entry.startSector = 0;
}
if ( MMC_ReadSegOffset (FILE_tempBuf1, FILE_entry.startSector, 0) != MMC_OK )
return FILE_ERR_FMT;
if ( pp->numOfFAT == 2 &&
pp->sectorPerCluster && pp->sectorSize == MMC_SECTOR_SIZE )
{
FILE_entry.sectorPerCluster = pp->sectorPerCluster;
FILE_entry.fatStart = FILE_entry.startSector + pp->reserveSectors;
FILE_entry.numOfFAT = pp->numOfFAT;
FILE_entry.sectorPerFAT= pp->sectorPerFAT;
FILE_entry.rootEntries = pp->rootEntries;
FILE_entry.rootStart = FILE_entry.fatStart + FILE_entry.numOfFAT * FILE_entry.sectorPerFAT;
FILE_entry.dataStart = FILE_entry.rootStart + (pp->rootEntries + 15) / 16;
return FILE_OK;
}
}
}
return FILE_ERR_FMT;
}
#define FILE_ClusterFatSector(cluster) (FILE_entry.fatStart + cluster/256)
#define FILE_ClusterFatOffset(cluster) ((cluster & 0xff) << 1)
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static unsigned int FILE_NextCluster (unsigned int cluster)
{
if ( cluster < 2 || cluster>= 0xfff0 )
return 0xffff;
unsigned long sector = FILE_ClusterFatSector (cluster);
unsigned int offset = FILE_ClusterFatOffset (cluster);
if ( MMC_ReadSegOffset (FILE_tempBuf1, sector, offset) != MMC_OK )
return 0xffff;
return *((unsigned int bank2 *)FILE_tempBuf1);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static unsigned long FILE_GetDataSector (unsigned int cluster)
{
// unsigned long c = cluster - 2;
return FILE_entry.dataStart + (cluster - 2) * FILE_entry.sectorPerCluster;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
char FILE_EntryType (DirEntry_t bank2 *dir)
{
#if 0
char bank2 *p = dir; // problem in v1.13!!!
char c = dir->fileName[0];//*p;
if ( c == 0xe5 || c == 0x00 || c == '.' )
return NULL_ENTRY;
char attr = dir->attrib;
if ( MEMCMP_ROM (dir->fileExt, "MP3", 3) && (attr == 0x01 || attr == 0x20) )
return MP3_FILE;
if ( attr == 0x10 )
return SUB_DIR;
#else
unsigned char c = dir->fileName[0];
if ( c == 0xe5 || c == 0x00 || c == '.' )
return NULL_ENTRY;
unsigned char attr = dir->attrib & 0x3f;
if ( MEMCMP_ROM (dir->fileExt, "MP3", 3) && (attr == 0x01 || attr == 0x20) )
return MP3_FILE;
if ( attr == 0x10 )
return SUB_DIR;
#endif
return UNKNOWN_ENTRY;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static FileDesc_t bank2* FILE_ReturnFileHandle (DirEntry_t bank2 *dir)
{
MEMCPY (fileDesc.fileName, dir->fileName, 11); // get filename+ext
fileDesc.size = dir->fileSize; // get file size
fileDesc.cluster = dir->startCluster; // get file (start) cluster)
fileDesc.sector = 0;
fileDesc.segment = 0;
return &fileDesc;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
FileDesc_t *FILE_FindFile (unsigned int index)
{
unsigned long sector = FILE_entry.rootStart;
while ( sector < FILE_entry.dataStart )
{
unsigned char i, seg;
for (seg = 0; seg < 8; seg++)
{
if ( MMC_ReadSegment (FILE_tempBuf1, sector, seg) != MMC_OK )
return NULL;
for (i = 0; i < MMC_SECTOR_SIZE/8; i += DIR_ENTRY_SIZE)
{
DirEntry_t bank2 *dir = (DirEntry_t *)&FILE_tempBuf1;
if ( FILE_EntryType (dir) == MP3_FILE ) // it's an MP3 file!
{
if ( --index == 0 )
return FILE_ReturnFileHandle (dir);
}
}
}
sector++;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
unsigned char *readFileSector (FileDesc_t bank2 *file)
{
unsigned char seg = file->segment;
unsigned long sector;
if ( seg == 0 || seg>= 8 )
{
file->segment = 0;
if ( file->sector>= FILE_entry.sectorPerCluster )
{
file->cluster = FILE_NextCluster (file->cluster);
file->sector = 0;
}
if ( file->cluster>= 0xfff0 )
return NULL;
if ( file->sector == 0 )
file->startSector = FILE_GetDataSector (file->cluster);
sector = file->startSector + file->sector;
file->sector++;
}
if ( MMC_ReadSegment (FILE_tempBuf1, sector, file->segment++) != MMC_OK )
return NULL;
return FILE_tempBuf1;
}
///////////////////////////////////////////////////////////////////////////////
char nextFileSector (FileDesc_t bank2 *file)
{
if ( file->sector>= FILE_entry.sectorPerCluster )
{
file->cluster = FILE_NextCluster (file->cluster);
file->sector = 0;
}
if ( file->cluster>= 0xfff0 )
return 0;
if ( file->sector == 0 )
file->startSector = FILE_GetDataSector (file->cluster);
file->sector++;
return -1;
}
///////////////////////////////////////////////////////////////////////////////
unsigned int FILE_searchMP3Files (void)
{
unsigned long sector = FILE_entry.rootStart;
// unsigned long sector = FILE_entry.fatStart;
unsigned int cnt = 0;
while ( sector < FILE_entry.dataStart )
{
unsigned char seg, i;
for (seg = 0; seg < 8; seg++)
{
// if ( MMC_ReadSegOffset (FILE_tempBuf1, sector, seg*64) != MMC_OK )
if ( MMC_ReadSegment (FILE_tempBuf1, sector, seg) != MMC_OK )
return cnt;
for (i = 0; i < MMC_SECTOR_SIZE/8; i += DIR_ENTRY_SIZE)
{
DirEntry_t bank2 *dir = &FILE_tempBuf1;
if ( FILE_EntryType (dir) == MP3_FILE ) // it's an MP3 file!
cnt++;
}
}
sector++;
}
return cnt;
} |
|