📄 mp3player2.c
字号:
if (--PlayMusic == 0){ PlayMusic = MusicCount; } } Cluster = 0; // 妒の呵介から } else { // FF or その妒の浩栏姜位 PlayMusic++; // 肌の妒 Cluster = 0; } if (BattVolt < BATT_START){ beep(1, BEEP_LOW); // 弹瓢排暗笆布になったら妒粗に焚桂不 } }}//*********************************************************// スイッチが澄悸に庶されるまで略つ//*********************************************************void switch_wait(void){ sei(); for (;;) { WDR; SLEEP; SLEEP; if (!(SwitchFlag & ((1<<SW_FF)|(1<<SW_REW)|(1<<SW_STOP)))){ SLEEP; SLEEP; if (!(SwitchFlag & ((1<<SW_FF)|(1<<SW_REW)|(1<<SW_STOP)))){ break; } } }}//*********************************************************// MMC/SDカ〖ドの介袋步//*********************************************************uchar InitCard(void){ uchar c; outp(0x52, SPCR); // SPIマスタ, CPOL=0, クロック 8MHz/64=125kHz sbi(PORTB, SPI_CS); // CS=H // MMC/SD SPIモ〖ド败乖涟のクロック流慨 for (c=0; c < 10; c++){ SPI_in(); } // SPIモ〖ド败乖コマンド cbi(PORTB, SPI_CS); // CS=L c = SPI_command(0, 0); while ((c != 1)&&(c != 0xFF)){ SLEEP; c = SPI_command(0, 0); } while (c == 1){ c = SPI_command(1, 0); } sbi(PORTB, SPI_CS); // CS=H outp(0x50, SPCR); // SPIマスタ, CPOL=0, クロック 8MHz/4=2MHz sbi(SPSR, SPI2X); // クロックを2擒 4MHz return c;}//*********************************************************// VFAT攫鼠粕み艰り//*********************************************************uchar read_VFAT_info(void){ ulong sec; uint bpb; uint n; // VFAT攫鼠粕み艰り。セクタ墓は 512bytesで疯め虑ちしている read_32(446); // MBR粕み哈み bpb = (uint)DataBuff[8] + ((uint)DataBuff[9]<<8); // BPB黎片セクタ read_32((ulong)bpb * 512); // 粕み哈み n = (uint)DataBuff[11] + ((uint)DataBuff[12] << 8); // セクタ墓 if (n != 512){ return 2; // 1セクタが 512bytesでない } SectorsPerCluster = DataBuff[13]; // クラスタあたりのセクタ眶 FATstart = bpb + (uint)DataBuff[14] + ((uint)DataBuff[15] << 8); // 徒腆セクタ眶 RootDirEntriesCount = (uint)DataBuff[17] + ((uint)DataBuff[18] << 8); // ル〖トディレクトリエントリ眶 n = (uint)DataBuff[22] + ((uint)DataBuff[23] << 8); // FATのセクタ眶 if (n == 0){ return 1; // FAT32らしい } DIRstart = (uint)FATstart + (uint)DataBuff[16] * n; // FATの眶∵セクタ眶 n = RootDirEntriesCount / 16; // ル〖トディレクトリに涩妥なセクタ眶 if (RootDirEntriesCount % 16){ n++; // 前のため、途りが叫たら磊り惧げ。奶撅は稍妥だと蛔うが } DataStart = (ulong)DIRstart + (ulong)n; // デ〖タ呈羌挝拌 sec = (ulong)DataBuff[19] + ((ulong)DataBuff[20] << 8); // 另セクタ眶 if (sec == 0){ read_32((ulong)bpb * 512 + 32); // 粕み哈み sec = (ulong)DataBuff[0] + ((ulong)DataBuff[1] << 8) + ((ulong)DataBuff[2] << 16) + ((ulong)DataBuff[3] << 24); } sec -= FATstart; sec /= SectorsPerCluster; if (sec >= 0x1000){ FATtype = 1; // FAT16 } else { FATtype = 0; // FAT12 } return 0;}//*********************************************************// MP3ファイルを淋す// 苞眶¨// num この眶だけ斧つけたら提る// この眶笆布であってもディレクトリエントリを链て拇べ姜わったら提る// 提り猛¨// 斧つけた眶// DataBuff[0×31] 呵稿に斧つかった MP3のディレクトリ攫鼠//*********************************************************uint search_MP3(uint num){ uint ent; ulong sec; uchar i, j; uint n; n = 0; sec = (ulong)DIRstart * 512; for (ent = 0; ent < RootDirEntriesCount; ){ if (SPI_read_open(sec)) return n; for (i = 0; i < 16; i++){ for (j = 0; j < 32; j++){ DataBuff[j] = SPI_in(); } if (DataBuff[0] == 0) break; // 踏蝗脱挝拌浮叫 if (((DataBuff[26] != 0)||(DataBuff[27] != 0))&& // クラスタ戎规 (DataBuff[0] != 0xE5)&& // 猴近マ〖ク (!(DataBuff[11] & 0x18))&& // 奶撅ファイル (DataBuff[8]=='M')&&(DataBuff[9]=='P')&&(DataBuff[10]=='3')){ // 橙磨灰MP3 n++; if (--num == 0) break; } ent++; } for (++i; i < 16; i++){ for (j = 0; j < 32; j++){ SPI_in(); // セクタ尸の荒りを粕み嘉て } } SPI_read_close(); if (DataBuff[0] == 0) break; // 踏蝗脱挝拌浮叫 if (num == 0) break; sec += 512; // 肌のセクタ } return n;}//****************************************// MP3ファイルを浩栏// fn: 妒戎规// clst: 遍琳倡幌クラスタ。==0 の眷圭は呵介から// remainsec: 浩栏デ〖タ荒りセクタ眶//****************************************char play_music(uint fn, uint clst, long remainsec){ ulong sec; uint remain; uint cn; uint i; if (fn != search_MP3(fn)){ return -1; // 妒が痰い } MusicSize = (ulong)DataBuff[28] + ((ulong)DataBuff[29]<<8) + ((ulong)DataBuff[30]<<16) + ((ulong)DataBuff[31]<<24); if (clst){ // 庞面から浩栏 Cluster = clst; RemainSec = remainsec; remain = MusicSize - (remainsec * 512); } else { // 呵介から浩栏 Cluster = (uint)DataBuff[26] + ((uint)DataBuff[27] << 8); RemainSec = MusicSize / 512; remain = MusicSize % 512; } if ((Cluster == 0xFFFF)||(Cluster < 2)){ return -2; // クラスタ佰撅 } // 肌のクラスタを拇べておく NextCluster = next_cluster(Cluster, 0, 0); StopSw = 0; RewSw = 0; FfSw = 0; cn = SectorsPerCluster; sec = (((ulong)Cluster - 2) * (ulong)SectorsPerCluster + DataStart) * 512; MP3_init(); Timer = 100; // READYタイマ〖セット while (RemainSec > 0){ uchar data; char bit; if (SPI_read_open(sec)) return -2; cli(); // 充哈み敦贿 SPI_out(0xFF); // 1byte誊のクロック流叫 & WAIT for (i = 0; i < 512; i++){ while (!(inp(PIND)&(1<<MP3_DREQ))){ // VS1001 BUSYチェック WDR; // ウォッチドッグタイマ〖リセット Timer = 100; // READYタイマセット if (NextCluster == 0){ // 肌のクラスタを拇べる NextCluster = next_cluster(Cluster, sec, i); } else { sei(); // 充り哈み钓材 SLEEP; cli(); // 充哈み敦贿 } } data = inp(SPDR); outp(0xFF, SPDR); // SD/MMCカ〖ドへ肌のデ〖タリクエスト if (data & 0x80){ sbi(PORTD, MP3_SI); } else { cbi(PORTD, MP3_SI); } sbi(PORTD, MP3_BSYNC); // BSYNC = H sbi(PORTD, MP3_DCLK); data <<= 1; cbi(PORTD, MP3_DCLK); cbi(PORTD, MP3_BSYNC); // BSYNC = L for (bit = 0; bit < 7; bit++){ if (data & 0x80){ sbi(PORTD, MP3_SI); } else { cbi(PORTD, MP3_SI); } sbi(PORTD, MP3_DCLK); data <<= 1; cbi(PORTD, MP3_DCLK); } } sei(); // 充り哈み钓材 SPI_read_close(); --RemainSec; if (--cn > 0){ sec += 512; // 肌のセクタ if (Debug && (cn == 1)){ uint n; n = BattVolt; WriteHex(n>>8); WriteHex(n); WriteCom(' '); WriteHex(Cluster>>8); WriteHex(Cluster); WriteCom('\n'); } } else { // 肌のクラスタ if (NextCluster == 0){ Cluster = next_cluster(Cluster, 0, 0); } else { Cluster = NextCluster; NextCluster = 0; } if ((Cluster == 0xFFFF)||(Cluster < 2)){ // 佰撅クラスタが浮叫されたので动扩姜位 remain = 0; break; } sec = (((ulong)Cluster - 2) * (ulong)SectorsPerCluster + DataStart) * 512; cn = SectorsPerCluster; } check_batt(); // バッテリ〖チェック if (Timer == 0){ // READYタイムアウトしたら if (NoBusyRetry > 0){ // リトライしてもダメなら beep(1, BEEP_LOW); // 你不ビ〖プ1搀 NoBusyRetry = 0; FfSw = 0; return 2; // FF胺いで姜位 ⅹ 肌の妒へ } else { NoBusyRetry = 1; RewSw = 0; return 3; // REW胺いで姜位 ⅹ その妒の呵介からリトライ } } // STOP, FFボタンチェック if (StopSw > 2){ beep(1, BEEP_HIGH); NoBusyRetry = 0; return 1; } else if (FfSw > 2){ beep(1, BEEP_HIGH); NoBusyRetry = 0; return 2; } else if (RewSw > 2){ beep(1, BEEP_HIGH); NoBusyRetry = 0; return 3; } } NoBusyRetry = 0; // 1セクタ(512bytes)踏塔の尸を浩栏 if ((remain > 0)&&(remain < 512)){ uchar data; char bit; if (SPI_read_open(sec)) return -2; cli(); // 充哈み敦贿 SPI_out(0xFF); // 1byte誊のクロック流叫□WAIT for (i = 0; i < 512; i++){ data = inp(SPDR); outp(0xFF, SPDR); if (remain-- > 0){ while (!(inp(PIND)&(1<<MP3_DREQ))){ // VS1001 BUSY WDR; // ウォッチドッグタイマクリア sei(); // 充り哈み钓材 SLEEP; cli(); // 充哈み敦贿 } sbi(PORTD, MP3_BSYNC); // BSYNC = H for (bit=0; bit<8; bit++){ if (data & 0x80){ sbi(PORTD, MP3_SI); } else { cbi(PORTD, MP3_SI); } sbi(PORTD, MP3_DCLK); data <<= 1; cbi(PORTD, MP3_DCLK); cbi(PORTD, MP3_BSYNC); // BSYNC = L } } } sei(); // 充り哈み钓材 SPI_read_close(); } return 0;}//****************************************// 肌のクラスタを滇める//****************************************uint next_cluster(uint c, ulong sec, uint remain){ ulong addr; uint data; ulong fatadr; uint i; if (FATtype == 0){ // FAT12 addr = (ulong)FATstart * 512 + (ulong)c + (c >> 1); if ((addr & 511) == 511){ if (sec != 0){ // 粕み哈みオ〖プン面なら粕み嘉て for (i = remain; i < 512; i++) SPI_in(); SPI_read_close(); data = read_word(addr) & 0x00FF; data |= ((read_word(addr+1) & 0x00FF) << 8); // 浩刨オ〖プン、笆涟の疤弥まで粕み嘉て if (SPI_read_open(sec)) return 0; SPI_in(); for (i = 0; i < remain; i++) SPI_in(); } else { // セクタをまたぐ data = read_word(addr) & 0x00FF; data |= ((read_word(addr+1) & 0x00FF) << 8); } } else { fatadr = addr & 0xFFFFFE00; if ((sec != 0)&&(fatadr != FatCacheAddr)){ // 粕み哈みオ〖プン面で FATバッファ痰跟なら粕み嘉て for (i = remain; i < 512; i++) SPI_in(); SPI_read_close(); data = read_word(addr); // 浩刨オ〖プン、笆涟の疤弥まで粕み嘉て if (SPI_read_open(sec)) return 0xFFFF; SPI_in(); for (i = 0; i < remain; i++) SPI_in(); } else { data = read_word(addr); } } if (c & 1){ c = data >> 4; } else { c = data & 0x0fff; } if (c >= 0x0ff8) c = 0xFFFF; } else { // FAT16 addr = (ulong)FATstart * 512 + (ulong)c * 2; fatadr = addr & 0xFFFFFE00; if ((sec != 0)&&(fatadr != FatCacheAddr)){ // 粕み哈みオ〖プン面で FATバッファ痰跟なら粕み嘉て for (i = remain; i < 512; i++) SPI_in(); SPI_read_close(); c = read_word(addr); // 浩刨オ〖プン、笆涟の疤弥まで粕み嘉て if (SPI_read_open(sec)) return 0; SPI_in(); for (i = 0; i < remain; i++) SPI_in(); } else { c = read_word(addr); } if (c >= 0xFFF8) c = 0xFFFF; } return c;}//****************************************// MMC/SDカ〖ドから 2byteを粕む// セクタ董肠のアクセスはできないので// 惧疤供镍で雇胃すること//****************************************uint read_word(ulong addr){ uint w; uint b; uchar *p; b = addr & 511; addr &= 0xFFFFFE00; if (addr != FatCacheAddr){ if (SPI_read_open(addr)) return 0; for (p = FatCache; p < (FatCache + 512); ){ *p++ = SPI_in(); } SPI_read_close(); FatCacheAddr = addr; } w = (uint)FatCache[b++]; w |= ((uint)FatCache[b] << 8); return w;}//*******************************************************// バッテリ〖排暗を拇べ、你すぎればシャットダウンする//*******************************************************int check_batt(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -