?? fat.c
字號:
// gets part of a file
// this function is dumb and does not check for errors.
// dont use on its own
// used by fget & co.
void fat_get_file_section(FILE *stream, u16 size, u08 *data)
{ // determine the sector that we need to read and which dword defines our next cluster address
u16 myh = stream->file_current_clusterh;
u16 myl = stream->file_current_clusterl;
u08 i = 0;
myl += first_data_sectorl;
if(myl < first_data_sectorl) myh++;
// get the data
MMC_get_part_sec_start(myh, myl,stream->file_offset,size);
for(;i<size;i++) data[i] = MMC_get_sec_next();
MMC_get_sec_stop();
// fine
};
// used to get info from the current directoy
// modes :
// FAT_FILENAME - 0x02 - find file by name
// FAT_DIRNAME - 0x03 - find dir by name
// FAT_FILENUM - 0x04 - find file by number 0 based
// FAT_DIRNUM - 0x05 - find dir by number 0 based
bool fat_dir_ctl(u08 mode, FILE *stream, DIR *dir, u08* name, u08 count)
{
// the sector that we are on
u16 myhfat;
u16 mylfat;
u16 myh;
u16 myl;
u08 mysec = 0;
// how many files/dirs were foud
u08 index = 0;
// is there data worth looking for in another sector ?
u08 loop = 1;
// how many entries were read from this sector
u08 len = 0;
myhfat = directory.dir_currenth;
mylfat = directory.dir_currentl;
do
{ myl = mylfat;
myh = myhfat;
// calc cluster to sectors
cluster_to_sector(&myh, &myl);
// add Data section offset
myl += first_data_sectorl+mysec;
if(myl < first_data_sectorl) myh++;
// start getting the data from the mmc
MMC_get_sec_start(myh, myl);
// there are 16 directory entries in each directory sector
// checkout the msdoc of fat for info
len = 0;
while (len < 16)
{ u08 tmp[32];
u08 i;
// get next entry
for(i =0; i< 32; i++)
tmp[i] = MMC_get_sec_next();
if(tmp[0] == 0x00) loop = 0; // no more directory entries
// make sure that there is an entry and that we want to process it and that it is valid
if((tmp[0] > 0x0) && (tmp[0] != 0xE5))
{ // check if this is a long dir entry
if ((tmp[11]&FAT_LONG_NAME) == FAT_LONG_NAME)
{
#ifdef LFN_SUPPORT
// is this the first entry
if(tmp[0] > 0x40)
{ tmp[0]-= 0x40;
for(tmp[2] = 0; tmp[2] < 13*LFN_MAX_BLOCK; tmp[2]++)
{ lfn_tmp[tmp[2]] = 0x00;
};
};
if(tmp[0] <= LFN_MAX_BLOCK)
{ // we can use a unicode 0 as a tmp var
tmp[2] = (tmp[0] - 1) * 13;
for(i=1; i<10; i+=2)
{ lfn_tmp[tmp[2]++] = tmp[i];
};
for(i=14; i<31; i+=2)
{ if(i != 26) lfn_tmp[tmp[2]++] = tmp[i];
};
};
#endif
}
// check if it is a file
else if(((tmp[11]&(FAT_DIRECTORY|FAT_VOL_ID)) == 0x00))
{ // do we want to print ?
if(mode == FAT_PRINT)
{ /*
printf("Filename: '");
for(i=0; i<11; i++)
{ if(tmp[i] != ' ')
printf("%c", tmp[i]);
if(i==7) printf(".");
}
printf("'\n");
*/
}
else if((mode == FAT_FILENUM)&&(loop))
{ // is this the file we are looking for ?
if(index == count)
{ // check if we are supposed to use a mask
if(name)
{ if(fat_cmp_names(tmp, name, &name[8]))
{ fat_load_file_ptr(tmp, stream);
loop = 0;
};
}
else
{ fat_load_file_ptr(tmp, stream);
loop = 0;
};
}
else
{ if(!name)
{ index++;
}
else
{ if(fat_cmp_names(tmp, name, &name[8]))
{ index++;
};
}
};
}
else if(mode == FAT_FILENAME)
{ if(fat_cmp_names(tmp, name, &name[8]))
{ fat_load_file_ptr(tmp, stream);
loop = 0;
};
};
#ifdef LFN_SUPPORT
lfn_tmp[0] = 0x00;
#endif
// check if this is a volume id
}
else if((tmp[11]&FAT_VOL_ID)==FAT_VOL_ID)
{ /*
printf("Vol-ID: '");
for(i=0; i<11; i++)
{ if(tmp[i] != ' ')
printf("%c", tmp[i]);
}
printf("'\n");
*/
}
// check if this is a pointer to another directory
else if ((tmp[11]&FAT_DIRECTORY)==FAT_DIRECTORY)
{ // do we want to print ?
//printf("Entry is a dir\n");
if(mode == FAT_PRINT)
{ /*
printf("Dirname: '");
for(i=0; i<11; i++)
{ if(tmp[i] != ' ')
printf("%c", tmp[i]);
if(i==7) printf(".");
}
printf("'\n");
*/
}
else if((mode == FAT_DIRNUM)&&(loop))
{ // is this the file we are looking for ?
if(index == count)
{ // check if we are supposed to use a mask
if(name)
{ if(fat_cmp_names(tmp, name, 0x00))
{ fat_load_dir_ptr(tmp, dir);
loop = 0;
};
}
else
{ fat_load_dir_ptr(tmp,dir);
loop = 0;
};
}
else
{ if(!name)
{ index++;
}
else
{ if(fat_cmp_names(tmp, name, 0x00))
{ index++;
};
}
};
}
else if((mode == FAT_DIRNAME)&&(loop))
{ if(fat_cmp_names(tmp, name, 0x00))
{ fat_load_dir_ptr(tmp, dir);
loop = 0;
};
};
#ifdef LFN_SUPPORT
lfn_tmp[0] = 0x00;
#endif
};
};
// inc loop counter
len++;
//getch();
};
// stop the reading process+
MMC_get_sec_stop();
if (mysec < sec_per_clus-1)
mysec++;
else
{ FAT_get_next_clus_addr(&myhfat, &mylfat);
mysec=0;
}
//loop = 0;
} while((myhfat!=0x0fff)&&(mylfat!=0xfffd)&&(loop));
// if we just did some directory listing, we always return true
if(mode == FAT_DIRNAME)
return true;
// we were looking for some file/directory. if loop is true, no data was found
if(loop)
return false;
return true;
};
/*------------------ FIO API LAYER --------------*/
// only the 'r' mode is supported so far
bool fopen(u08 *filename, u08 mode, FILE *stream)
{ if(mode=='r')
return fat_dir_ctl(FAT_FILENAME, stream, 0x00, filename, 0);
return false;
};
// only the 'r' mode is supported so far
bool fopenc(u08 count, u08 mode, u08 *mask, FILE *stream)
{ if(mode=='r')
return fat_dir_ctl(FAT_FILENUM, stream, 0x00, mask, count);
return false;
};
// closes a filestream this is not really neccesarry, but alot tidier
void fclose(FILE *stream)
{ stream->file_first_clusterl =
stream->file_first_clusterh =
stream->file_current_clusterl =
stream->file_current_clusterh =
stream->file_current_sector =
stream->file_sizel =
stream->file_sizeh =
stream->file_offset = 0x00;
};
// has the end of the file been reached ?
bool feof(FILE *stream)
{ return (stream->file_current_clusterh==0x0fff) &&
(stream->file_current_clusterl>=0xfff8);
};
// checks if a file is open
bool fisopen(FILE *stream)
{ return (stream->file_first_clusterl == 0x00) &&
(stream->file_first_clusterh == 0x00) &&
(stream->file_current_clusterl == 0x00) &&
(stream->file_current_clusterh == 0x00) &&
(stream->file_current_sector == 0x00) &&
(stream->file_sizel == 0x00) &&
(stream->file_sizeh == 0x00) &&
(stream->file_offset == 0x00);
};
// gets data from a file
u08* fget(FILE *stream, u16 size)
{ // make sure the FILE is open
if((stream->file_current_clusterh==0x0)&&(stream->file_current_clusterl==0x0)) return 0x00;
// are we at the end of a sector ?
if(stream->file_offset == 0x200)
{ // load next sector
if (stream->file_current_sector >= sec_per_clus-1)
{ FAT_get_next_clus_addr(&stream->file_current_clusterh, &stream->file_current_clusterl);
if(feof(stream)) return 0x00;
stream->file_current_sector = 0;
}
else
{ stream->file_current_sector++;
}
stream->file_offset = 0x00;
}
// make sure we are not reading in more than the max data buffer
if(size > FAT_RD_BUF_SIZE) size = FAT_RD_BUF_SIZE;
// make sure we are not reading past the end of a file
if((stream->file_sizeh == 0) && (stream->file_sizel < size)) size = stream->file_sizel;
// is all the data in this sector? or do we have to split over two sectors
if((stream->file_offset+size) < 0x200)
{ // all in one
fat_get_file_section(stream, size, fat_buf);
stream->file_offset += size;
}
else
{ // workout where we need to split
u08 split_pos = 0x200 - stream->file_offset;
size -= split_pos;
// get first half
fat_get_file_section(stream, split_pos, fat_buf);
// get second half
if (stream->file_current_sector >= sec_per_clus-1)
{ FAT_get_next_clus_addr(&stream->file_current_clusterh, &stream->file_current_clusterl);
stream->file_current_sector = 0;
}
else
{ stream->file_current_sector++;
}
fat_get_file_section(stream, size, &fat_buf[split_pos]);
stream->file_offset = size;
size += split_pos;
};
// update the stream struct
if(stream->file_sizel < size)
{ // save as we checked for zero earlier
stream->file_sizeh--;
};
stream->file_sizel = size - stream->file_sizel;
fat_buf[size] = '\0';
return fat_buf;
};
bool fplay_sector(FILE *stream)
{ u16 myh = stream->file_current_clusterh;
u16 myl = stream->file_current_clusterl;
// make sure the FILE is open
if((stream->file_current_clusterh==0x0)&&(stream->file_current_clusterl==0x0)) return false;
// make sure, that we are not past the last cluster of the file
if((stream->file_current_clusterh==0x0fff)&&(stream->file_current_clusterl>=0xfff8)) return false;
cluster_to_sector(&myh, &myl);
myl += first_data_sectorl;
if(myl < first_data_sectorl) myh++;
u16 length;
u08 tmp;
u08 sec;
for(sec=0; sec<sec_per_clus; sec++)
{ // start getting the data
MMC_get_sec_start(myh, myl);
length=0;
tmp = spi_io(0xff);
// disable the MMC to receive data
MMC_disable();
while(length<512)
{ if((512%32) == 0) VS1001_WHILE_NEEDS_NO_DATA;
VS_BSYNC_HI;
outp(tmp, SPDR); // send data
NOP;
NOP;
NOP;
VS_BSYNC_LO;
// wait for data to be sent
while(((inp(SPSR))&(1<<SPIF))== 0x00){};
tmp = inp(SPDR);
length++;
};
// enables the MMC to receive data again
MMC_enable();
// get the 2nd CRC bytes
spi_io(0xff);
// give enough time
MMC_cleanup();
myl++;
if (myl==0) myh++;
}
FAT_get_next_clus_addr(&stream->file_current_clusterh, &stream->file_current_clusterl);
return true;
};
// step into a subfolder of the current folder
// if dirname is null function sets the root folder
bool dir_enter(u08 *dirname, DIR *dir)
{ if(!dir) dir = &directory;
// set a folder
if(dirname)
{ return fat_dir_ctl(FAT_DIRNAME, 0x00, dir, dirname, 0);
}
//set root folder ?
else
{ dir_root(dir);
return true;
};
}
// step into a subfolder of the current folder
bool dir_leave(DIR *dir)
{ u08 tmp[9] = ".. ";
return dir_enter(tmp, dir);
};
// list the current directory
void dir_list(DIR *dir)
{ if(!dir) dir = &directory;
fat_dir_ctl(FAT_PRINT, 0x00, 0x00, 0x00, 0);
}
// sets the dir to root
void dir_root(DIR *dir)
{ if(!dir) dir = &directory;
dir->dir_currentl = 0x00;
dir->dir_currenth = 0x00;
};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -