📄 fileio.c
字号:
#include "fileio.h"#ifdef MMCunsigned char MMC_Read_Wrapper(unsigned long lba){ if (lba <= maxsect) return MMC_Read(lba); else return 1; // return error code}#endifint get_disk_parms(){ unsigned long pstart; struct boot_record *bs;#ifndef MMC if (CFIdentify()) // get CHS from cf card return 1;#else// if(MMC_Check())// {// if(MMC_Reset())// return 1;// } MMC_Check(); MMC_Reset(); maxsect = MMC_Capacity();#endif if (ReadSector(0)) // read MBR return 5;#ifndef MMC pstart = (((((unsigned int) secbuf[0x1c0] & 0xc0) << 2) + secbuf[0x1c1])* heads * sectors_per_track) + (secbuf[0x1bf] * sectors_per_track) + (secbuf[0x1c0] & 0x3f) -1;#else pstart = (unsigned int)secbuf [0x1c7] << 8 | secbuf[0x1c6];#endif if (ReadSector(pstart)) // read first fat sector return 3; bs = secbuf; fatstart = pstart + bs->reserved_sectors; secpercluster = bs->sectors_per_cluster; rootdir = fatstart + (bs->sec_per_fat * bs->number_of_fats); // start of root dir data = rootdir + (bs->root_direntries >> 4); // start of data area (Cluster area) return(0);}unsigned int get_next_cluster(unsigned int lastcl){ lastcl += 2; if (ReadSector((unsigned long) fatstart + (lastcl >> 8))) return 0xffff; return (unsigned int) secbuf[(((unsigned int) lastcl & 0xff) << 1)] - 2 + (((unsigned int) secbuf[(((unsigned int) lastcl & 0xff) << 1)+1]) << 8); // fetch next cluster}unsigned int get_next_direntry(unsigned int dircluster, unsigned int num, char dir, unsigned char type, unsigned char get_id3){ unsigned long sect, lastsec; struct entry *de; static char file_types[] PROGMEM = "MP3M3URGB"; // strings for file extensions sect = lastsec = 0; attrib = 1; do { num += dir; if (dircluster == 0) // is this the root directory? { sect = rootdir + (num >> 4); // yes, right after fat } else { sect = data + ((unsigned long) dircluster * secpercluster) + (num >> 4); // no, add offset } if (sect != lastsec) // did we already read sector? { ReadSector(sect); // no, get it lastsec = sect; // save read sector } de = secbuf + ((num << 5) - ((num >> 4) * 512)); // fill direntry structure attrib = de->attribute; // save attribute for main program if ((de->filename[0] == 0) && (dir > 0)) break; // empty filename -> last direntry if ((type == TYPE_DIR) && !(attrib & 0x10)) continue; // it`s not a directory but we`re looking for one if ((attrib & 0x10) && strncmp_P(de->filename, PSTR(". "), 2)) continue; // skip current directory if ((attrib != 0x0f) && ((de->filename[0] != 0xe5) && (de->filename[0] != 0x00))) // "normal" directory entry, go on! { if ((attrib & 0x10) && (de->filecluster == 0 && de->filesize == 0)) continue; // empty file -> continue strncpy(filename, de->filename, 8); // copy filename filename[8] = '.'; // set the dot strncpy(filename+9, de->ext, 3); // copy extension filename[12] = '\0'; // properly terminate filecluster = de->filecluster; // get first cluster if (filecluster != 0) filecluster -= 2; // correct cluster number dirfilesize = de->filesize; // get filesize if ((type < TYPE_ANY) && (strncmp_P(de->ext, file_types + (type*3), 3))) continue; // file extension doesn't get_lfn(num); // get long file name if ((attrib & 0x10) && (filecluster == 0) && (dirfilesize == 0)) // parent directory strncpy_P(filename, PSTR("<dir up>"), 10); else if (attrib & 0x10) // mark as folder strncpy_P(artalb, PSTR("<folder>"), 9); else if (get_id3) // mp3 file, get ID3 info get_id3_info(filecluster); return num; } } while (((num > 0) && (dir < 0)) || ((num < 512) && (dir > 0))); beep(80,100); // no suitable file found - hear it! return 0xffff; // return error value}unsigned char get_next_playlist_entry(unsigned char playlistid, char dir){ unsigned char ibuf[6]; unsigned char *p; register unsigned int readcl; register int i; register unsigned char ii; register char readsect, flag; artalb[0] = '\0'; p = artalb; readcl = playlistcl; i = playlistptr / ((unsigned int) secpercluster * 512); // determine cluster for playlistptr for (ii = 0;ii < i; ii++) readcl = get_next_cluster(readcl); // fetch that cluster... readsect = (playlistptr - ((unsigned int) secpercluster * 512 * i)) / 512; // determine sector inside cluster... ReadSector(data + (unsigned long) readcl * secpercluster + readsect); // and get it i = playlistptr - ((unsigned int) secpercluster * 512 * i) - (readsect * 512); if ((dir < 0) && (playlistptr > 0)) // direction back, rewind file two lines { i--; // jump over trailing linefeed playlistptr--; flag = 0; while (playlistptr > 0) { i--; // go back... if (i < 0) // bottom of sector buffer reached? { i = 511; // yes, set buffer readsect--; // get next sector if (readsect < 0) { readsect = secpercluster - 1; // new cluster needed readcl = filecluster; for (ii = 0; ii<(playlistptr / ((unsigned int) secpercluster * 512)); ii++) readcl = get_next_cluster(readcl); } ReadSector(data + (unsigned long) readcl * secpercluster + readsect); // finally get the sector } if (secbuf[i] == 0x0a) // linefeed, got the previous line { if (!flag) // jump back one more line flag = 1; else { i++; // here we are, two lines back break; // go ahead! } } playlistptr--; // rewind file pointer } } while (playlistptr < playlistlength) // now we`re going forward { lcd_upd = 0; // debugging stuff if (secbuf[i] == 0x0a) // line end? { *p++ = '\0'; // yes, terminate string break; // and out } if ((p-artalb) < 49) // some space left in line buffer? { *p++ = secbuf[i]; // yes, get next char } playlistptr++; // advance file pointer i++; if (i == 512) // new sector, same as above but forward { i = 0;// playlistptr++; readsect++; if (readsect == secpercluster) // new cluster... { readsect = 0; readcl = get_next_cluster(readcl); } ReadSector(data + (unsigned long) readcl * secpercluster + readsect); } } playlistptr++; // jump over linefeed if ((p-artalb) > 48) artalb[49] = '\0'; // terminate if (strlen(artalb) == 0) return 0xff; readcl = 0; cli(); // finding song may take som time, so no interrupts until then (i.e., disable timer) while (ii = strncmp(filename, artalb, 48) && (readcl != 0xffff)) // filename matching { readcl = get_next_direntry(dircluster, readcl, 1, TYPE_MP3, NOID3); } sei(); // re-enable interrupts if (readcl != 0xffff) // we got the file { get_id3_info(filecluster); // fetch ID3 tag return 0; } else return 0xfe; // not found :-( return 0; }unsigned char get_lfn(unsigned int dirid){ register unsigned long sect, lastsec; register unsigned int res, lfnentry; register unsigned char i; unsigned char *p; p = filename; lastsec = (0); while ((dirid > 0) && (p < (&filename[0] + 48))) { dirid--; if (dircluster == 0) // is this the root directory? { sect = rootdir + (dirid >> 4); // yes, right after fat } else { sect = data + ((unsigned long) dircluster * secpercluster) + (dirid >> 4); // no, add offset } if (sect != lastsec) { lastsec = sect; res = ReadSector(sect); } lfnentry = (dirid << 5) - ((dirid >> 4) * 512); if (secbuf[lfnentry+11] = 0x0f) { if (secbuf[lfnentry] & 0x40) dirid = 0; // last lfn entry for (i=1;i<32;i+=2) { if (p > (&filename[0]+48)) continue; if (i==11) i += 3; // attribute, type, checksum if (i==26) i += 2; // cluster *p++ = secbuf[lfnentry+i]; } } else return(0xff); // this is not an lfn entry } *p++='\0'; return 0;}void get_id3_info(unsigned int cl){ unsigned long tagsize, offset; unsigned int cluster; char id, length; unsigned char *p, *p2; register int i; char charbuf[30]; memset(artalb, 0, 30); artalbpos = titlepos = 0; artalbdir = titledir = 1; scrolltimer = SCROLLSPEED; lcd_upd = 0; tagsize = 0; id = ReadSector(data + (unsigned long) cl * secpercluster);// read next sector if (secbuf[0]=='I' && secbuf[1]=='D' && secbuf[2]=='3') { memset (filename, 0, 30); // clear filename, we've got an ID3 tag! tagsize = ((unsigned long ) secbuf[6]) << 21 | ((unsigned long) secbuf[7]) << 14 | ((unsigned long) secbuf[8]) << 7 | secbuf[9]; offset = 10; while ((offset < 502) && (id != -1)) { charbuf[0]='\0'; id = parse_tag(&offset, charbuf); if (strlen(charbuf) > 0) { p2 = NULL; switch (id) { case TPE1: p2 = artalb; case TRCK: if (p2== NULL) p2 = filename; if (strlen(p2)==0) // first part of concatennated string, nothing special { strncpy(p2, charbuf, 30); } else { length = strlen(charbuf)+3; // part1 + part2 > 50? if ((strlen(p2)+length)>49) length = 46-strlen(p2); // yes, cut string memmove(p2+length, p2, strlen(p2+1)); // move string to the end of new string memcpy(p2, charbuf, length-3); // prepend new string strncpy_P(p2+length-3, PSTR(" - "), 3); // insert separator } *(p2+49)='\0'; break; case TALB: p2 = artalb; case TIT2: if (p2 == NULL) p2 = filename; if (strlen(p2)==0) { strncpy(p2, charbuf, 30); } else {// length = 30;// if (strlen(p2)+strlen(charbuf)>46)// length = 46-strlen(p2); if (strlen(p2)>0) strlcat_P(p2, PSTR(" - "), 50); strlcat(p2, charbuf, 50); } *(p2+49)='\0'; break; } } } } cluster = cl; if (tagsize > 512) { for (i = 0;i < (tagsize / 512);i++) { cluster = get_next_cluster(cluster); } } tagsize = tagsize % 512; id = ReadSector(data + (unsigned long) cluster * secpercluster); // read next sector id =6 * ((secbuf[tagsize+2] >> 4) -1) + 3 * (1-((secbuf[tagsize+1] >> 3) & 0x01))+ (3- ((secbuf[tagsize+1] >> 1) & 0x03)); file_bitrate = PRG_RDB(&bitrate[id]); if (file_bitrate < 12) file_bitrate = 16;}// this routine parses a id3 tag// currently only artist, title, album and track no are implementedchar parse_tag(unsigned long * offs, unsigned char * buffer){ unsigned long tsize; char encoding, numid; char div; register int i, ii; char *p; static char valid_tags[] PROGMEM = "TPE1TALBTRCKTIT2"; // strings for tag types numid = 0; p=valid_tags; for (i=0; i<4; i++) // tag that we are aware of? { if (strncmp_P(&secbuf[*offs], p, 4) == 0) { numid = i+1; // yes! break; } p+=4; } *offs += 4; tsize = ((unsigned long) secbuf[*offs]) << 21 | ((unsigned long) secbuf[*offs+1]) << 14 | ((unsigned long) secbuf[*offs+2]) << 7 | (unsigned long) secbuf[*offs+3]; // fetch tag size if (tsize == 0) return -1; // length zero -> last frame *offs += 6; // jump over flags... ii = 0; if (numid != 0) { encoding = secbuf[*offs]; // tags might have different encodings... if (encoding == 0) {*offs += 1; tsize -= 1; div = 1; } // 1 byte per char else {*offs += 3; tsize -= 3; div = 2; } // 2 bytes per char (div=2) for (i=0; i<tsize; i++) // save tag info { if (ii >= 29) // sorry, no more than 29 chars... { i=tsize; } *buffer++ = secbuf[*offs+i]; if (encoding != 0) i++; } *buffer++='\0'; // terminate string properly } *offs += tsize; return numid;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -