📄 mp3player2.c
字号:
//// EasyMP3(VS1001K) + MMC/SD MP3 Player//// 2nd Version//// MCU: ATmega8 FUSE bit: D1EFh (external clock)// Compiler: AVR-GCC//// 2004.1.16 KAWAKAMI Yukio//#include <avr/io.h>#include <avr/signal.h>#include <avr/interrupt.h>#include <avr/pgmspace.h>#define LF 10#define ON 1#define OFF 0#define TRUE 1#define FALSE 0#define NOP asm volatile("nop\n"::)#define WDR asm volatile("wdr\n"::)#define SLEEP asm volatile("sleep\n"::)typedef unsigned char uchar;typedef unsigned int uint;typedef unsigned long ulong;//#define VS1001_CLOCK 14318180 // EasyMP3デフォルト#define VS1001_CLOCK 12000000 // VS1001のクロック(Hz)#define SPI_CS 2 // PORTB#define SPI_DIN 3#define SPI_CLK 5#define SPI_DOUT 4//#define MP3_SO 1 // PORTB#define MP3_SI 7 // PORTD#define MP3_SCLK 6#define MP3_CS 5#define MP3_BSYNC 4#define MP3_DCLK 3#define MP3_DREQ 2// スイッチフラグの侠妄ビット#define SW_START 0#define SW_STOP 0#define SW_REW 1#define SW_FF 2#define SW_VOLDOWN 3#define SW_VOLUP 4// スイッチの湿妄ビット#define SW_PORT_START 3 // PINC#define SW_PORT_STOP 3 // == SW_PORT_START#define SW_PORT_REW 2 // PINC#define SW_PORT_FF 1 // PINC#define SW_PORT_VOLDOWN 0 // PINC#define SW_PORT_VOLUP 0 // PINB#define POWER 4 // PORTC 排富ロック#define VOLTAGE 5 // 排糜排暗卢年#define MUTE 1 // PORTB 不兰叫蜗ミュ〖ト#define LED 1 // PORTD == TxD POWER LED#define BEEP_HIGH 0#define BEEP_LOW 1// EEPROM アドレス#define EEPROM_MUSIC 1 // 浩栏面の妒戎规#define EEPROM_CLUSTER_L 2 // 浩栏面のクラスタ(LOW)#define EEPROM_CLUSTER_H 3 // 》 (HIGH)#define EEPROM_REMAIN1 4 // 浩栏面の妒の荒りセクタ眶#define EEPROM_REMAIN2 5#define EEPROM_REMAIN3 6#define EEPROM_SIZE1 8 // 浩栏面の妒デ〖タの墓さ#define EEPROM_SIZE2 9 // SDカ〖ドが蛤垂されたかどうか#define EEPROM_SIZE3 10 // 冉侍するのに蝗う#define EEPROM_SIZE4 11#define EEPROM_VOLUME 12 // ボリュ〖ム#define EEPROM_RUNNING_TIME_H 13 // 附哼の排糜の苍漂箕粗(箕)#define EEPROM_RUNNING_TIME_M 14 // 》 (尸)#define EEPROM_RUNNING_TIME_OLD_H 15 // 涟の排糜の苍漂箕粗(箕)#define EEPROM_RUNNING_TIME_OLD_M 16 // 》 (尸)#define EEPROM_BATTLOG 17 // 排暗ログ倡幌// バッテリ〖排暗 V * 200 - 12 (悸卢による)#define BATT_START 410 // 弹瓢排暗 腆2.1V#define BATT_SHUTDOWN 380 // シャットダウン排暗 腆2.0V#define BATT_LOW 428 // ロ〖バッテリ〖浮叫 腆2.2V#define BATT_26 508 // 2.6V#define BATT_25 488 // 2.5V#define BATT_24 468 // 2.4V#define BATT_23 448 // 2.3V#define BATT_22 428 // 2.2Vuchar InitCard(void);uchar SPI_read_open(ulong adrs);void SPI_read_close(void);uchar SPI_command(uchar com, ulong arg);uchar SPI_in(void);void SPI_out(uchar data);void SPI_dummy_clock(void);void SPI_wait(void);void InitWait(void);void read_32(ulong addr);uchar read_VFAT_info(void);uint search_MP3(uint num);char play_music(uint n, uint clst, long remainbyte);uint next_cluster(uint c, ulong sec, uint remain);uint read_word(ulong addr);void beep(uchar n, char err);void MP3_sin(PGM_VOID_P data);void MP3_init(void);void MP3_command(uchar addr, uint arg);void MP3_com_write(uchar data);uint MP3_command_read(uchar addr);void shutdown(char flag);int check_batt(void);void write_eeprom(uchar adrs, uchar data);uchar read_eeprom(uchar adrs);void switch_wait(void);uchar ReadCom(void);void WriteCom(uchar data);void WriteComMsg(PGM_VOID_P msg);void WriteComStr(uchar *msg);void WriteHex(uchar data);void print_sector(ulong sec);// テスト脱息鲁赖腹侨叫蜗デ〖タ Beepとして蝗うPROGMEM uchar BeepData[] = { 0x53, 0xEF, 0x6E, 0x31, 0, 0, 0, 0 }; // 1500HzPROGMEM uchar ErrorBeep[] = { 0x53, 0xEF, 0x6E, 0x35, 0, 0, 0, 0 }; // 500HzPROGMEM uchar BeepStop[] = { 0x45, 0x78, 0x69, 0x74, 0, 0, 0, 0 }; // 贿めるuint Cluster; // 附哼浩栏面のクラスタuint NextCluster; // 肌搀浩栏するクラスタuint PlayMusic; // 浩栏面の妒戎规uint MusicCount; // 附哼のカ〖ドに掐っている妒眶ulong MusicSize; // 浩栏面の妒のサイズlong RemainSec; // 浩栏面の妒の荒りセクタ眶char NoBusyRetry; // BUSYにならないのでリトライしたことを绩すフラグuchar FATtype; // 0:FAT12 1:FAT16uchar SectorsPerCluster; // 1クラスタのセクタ眶uint RootDirEntriesCount; // ル〖トディレクトリエントリ〖眶uint FATstart; // FAT倡幌セクタuint DIRstart; // ル〖トディレクトリ倡幌セクタulong DataStart; // デ〖タ挝拌倡幌セクタvolatile uchar Volume; // 不翁volatile int BattVolt; // タイマ〖充り哈みで艰评した排富排暗volatile uchar SwitchFlag; // タイマ〖充り哈みで艰评したスイッチの攫鼠volatile uchar StopSw; // START/STOPスイッチ掐蜗フラグvolatile uchar RewSw; // REWスイッチ掐蜗フラグvolatile uchar FfSw; // FFスイッチ掐蜗フラグvolatile uchar VolUpSw; // Vol upスイッチ掐蜗フラグvolatile uchar VolDownSw; // Vol downスイッチ掐蜗フラグvolatile uchar FlushTimer; // LED爬糖タイマvolatile uchar RunningTimeDS; // 苍漂箕粗(1/100擅)volatile uchar RunningTimeS; // 》 (擅)volatile uchar RunningTimeM; // 》 (尸)volatile uchar RunningTimeH; // 》 (箕)volatile uchar Timer; // 绕脱タイマuchar DataBuff[32]; // デ〖タバッファuchar FatCache[512]; // FATキャッシュulong FatCacheAddr; // キャッシュしているアドレスchar Debug; // デバッグフラグ//*********************************// タイマ〖0オ〖バ〖フロ〖充り哈み// 8MHz/1024/78=100.16 腆100Hz//*********************************SIGNAL(SIG_OVERFLOW0) { uchar old_sw; // 肌の充り哈み肋年 outp((uchar)(256-(78-1)), TCNT0); // 绕脱タイマ if (Timer){ --Timer; } // ロ〖バッテリ〖浮叫による爬糖 if (!Debug){ if (++FlushTimer >= 100){ if (BattVolt < BATT_LOW){ cbi(PORTD, LED); // LED OFF } FlushTimer = 0; } else if (FlushTimer == 50){ sbi(PORTD, LED); // LED ON } } // 苍漂箕粗淡峡 if (++RunningTimeDS >= 100){ RunningTimeDS = 0; if (++RunningTimeS >= 60){ RunningTimeS = 0; if (++RunningTimeM >= 60){ RunningTimeM = 0; ++RunningTimeH; } } } // スイッチチェック old_sw = SwitchFlag; SwitchFlag = 0; if (!(inp(PINC) & (1<<SW_PORT_STOP))){ if (old_sw & (1<<SW_STOP)){ if (++StopSw == 0) StopSw = 255; } else { StopSw = 1; } SwitchFlag = (1<<SW_STOP); } if (!(inp(PINC) & (1<<SW_PORT_REW))){ if (old_sw & (1<<SW_REW)){ if (++RewSw == 0) RewSw = 255; } else { RewSw = 1; } SwitchFlag |= (1<<SW_REW); } if (!(inp(PINC) & (1<<SW_PORT_FF))){ if (old_sw & (1<<SW_FF)){ if (++FfSw == 0) FfSw = 255; } else { FfSw = 1; } SwitchFlag |= (1<<SW_FF); } if (!(inp(PINC) & (1<<SW_PORT_VOLDOWN))){ if (++VolDownSw == 0) VolDownSw = 255; if (VolDownSw >= 20){ Volume += 8; if (Volume > 0xCF) Volume = 0xCF; MP3_command(11, ((uint)Volume << 8)|((uint)Volume)); // 不翁肋年 VolDownSw = 1; } SwitchFlag |= (1<<SW_VOLDOWN); } else { VolDownSw = 0; } if (!(inp(PINB) & (1<<SW_PORT_VOLUP))){ if (++VolUpSw == 0) VolUpSw = 255; if (VolUpSw >= 20){ Volume -= 8; if (Volume == 0xFF) Volume = 0x07; MP3_command(11, ((uint)Volume << 8)|((uint)Volume)); // 不翁肋年 VolUpSw = 1; } SwitchFlag |= (1<<SW_VOLUP); } else { VolUpSw = 0; } // A/D恃垂倡幌 プリスケ〖ラ 8MHz/64 = 125kHz outp((1<<ADEN)|(1<<ADSC)|(1<<ADIE)|6, ADCSRA);}//*********************************// A/D恃垂の充り哈みル〖チン//*********************************SIGNAL(SIG_ADC) { int volt; // A/D恃垂冯蔡呈羌 // ADCL ⅹ ADCH の界にアクセスする涩妥あり volt = (int)inp(ADCL); BattVolt = (((int)inp(ADCH) & 3) << 8); BattVolt |= volt; cbi(ADCSRA, ADEN); // A/D 排富OFF}//*********************************// INT0(EasyMP3 DREQ)充り哈みル〖チン//*********************************SIGNAL(SIG_INTERRUPT0) { // CPUを弹こすだけ ;}//*********************************// メインル〖チン//*********************************int main (void) { char r; outp((1<<SW_PORT_VOLUP)|(1<<SPI_CS)|(1<<SPI_DIN), PORTB); // PB0 pull up outp((1<<SPI_CS)|(1<<SPI_DIN)|(1<<SPI_CLK)|(1<<MUTE), DDRB); outp((1<<SW_PORT_STOP)|(1<<SW_PORT_REW)|(1<<SW_PORT_FF) |(1<<SW_PORT_VOLDOWN), PORTC); // PC3×0 pull up outp((1<<POWER), DDRC); // PC4 out outp(1, PORTD); // RxD pull up outp((1<<MP3_SI)|(1<<MP3_SCLK)|(1<<MP3_CS)|(1<<MP3_BSYNC)|(1<<MP3_DCLK), DDRD); if (inp(MCUCSR) & (1<<WDRF)){ // ウォッチドッグリセット shutdown(1); // シャットダウン } outp(0, MCUCSR); if (inp(PINC)&(1<<SW_PORT_START)){ Debug = 1; outp(0, UBRRH); // DEBUG脱 USART介袋步 outp(24, UBRRL); // 19200bps/8MHz outp(0x20, UCSRA); outp(0x18, UCSRB); // 流减慨钓材 } else { Debug = 0; // STARTスイッチで弹瓢した sbi(DDRD, LED); // LED叫蜗 sbi(PORTD, LED); // LED ON } WDR; outp(0x18, WDTCR); // WDCEとWDEを1にしてタイマ〖恃构をする outp(0x1F, WDTCR); // ウォッチドッグタイマ〖セット 腆2擅/3V outp(((1<<REFS1)|(1<<REFS0))|5, ADMUX); // 柒婶答洁排暗 2.56V, A/D ch5 outp((uchar)(256-(78-1)), TCNT0); // タイマ〖肋年猛 -78 outp(0x05, TCCR0); // タイマ〖プリスケ〖ラ 1/1024 sbi(TIMSK, TOIE0); // タイマ充り哈み钓材 outp(0x83, MCUCR); // INT0(EasyMP3 DREQ)惟ち惧がり充り哈み,スリ〖プ钓材 sbi(GICR, INT0); // 钓材 SwitchFlag = 0; BattVolt = 0; NoBusyRetry = 0; sei(); // 充り哈み钓材 while(BattVolt < BATT_START){ SLEEP; // 排暗が惮年猛に茫するまで略つ } sbi(PORTC, POWER); // 排富ロック & EasyMP3 リセット豺近 // EasyMP3のポップノイズをやり册ごす百のタイマ〖セット Timer = 40; // 腆400mS Volume = read_eeprom(EEPROM_VOLUME); if (Volume == 0xFF) Volume = 0x47; // EEPROMから涟搀浩栏していた妒攫鼠を艰评 PlayMusic = read_eeprom(EEPROM_MUSIC); Cluster = (uint)read_eeprom(EEPROM_CLUSTER_H)<<8; Cluster |= (uint)read_eeprom(EEPROM_CLUSTER_L); RemainSec = (long)read_eeprom(EEPROM_REMAIN3)<<16; RemainSec |= (long)read_eeprom(EEPROM_REMAIN2)<<8; RemainSec |= (long)read_eeprom(EEPROM_REMAIN1); MusicSize = (ulong)read_eeprom(EEPROM_SIZE4)<<24; MusicSize |= (ulong)read_eeprom(EEPROM_SIZE3)<<16; MusicSize |= (ulong)read_eeprom(EEPROM_SIZE2)<<8; MusicSize |= (ulong)read_eeprom(EEPROM_SIZE1); // 苍漂箕粗淡峡倡幌 RunningTimeDS = 0; RunningTimeS = 0; RunningTimeM = read_eeprom(EEPROM_RUNNING_TIME_M); RunningTimeH = read_eeprom(EEPROM_RUNNING_TIME_H); if (RunningTimeM == 0xFF){ RunningTimeM = 0; RunningTimeH = 0; } if (Debug){ // Debug箕に苍漂箕粗を山绩 WriteComMsg(PSTR(" \nRunning Time:\n")); WriteHex(RunningTimeH); WriteComMsg(PSTR("h(Hour) ")); WriteHex(RunningTimeM); WriteComMsg(PSTR("h(Min)\n")); WriteHex(read_eeprom(EEPROM_RUNNING_TIME_OLD_H)); WriteComMsg(PSTR("h(Hour) ")); WriteHex(read_eeprom(EEPROM_RUNNING_TIME_OLD_M)); WriteComMsg(PSTR("h(Min)\n")); } // REWを病しながら弹瓢したら动扩弄にその妒の呵介から浩栏する if (SwitchFlag & (1<<SW_REW)){ Cluster = 0; } // MMC/SD SPI介袋步 if (InitCard() == 0xFF){ // MMC/SDカ〖ドが痰い while(Timer) SLEEP; // EasyMP3のポップノイズの箕粗略ち sbi(PORTB, MUTE); // 不兰ミュ〖ト豺近 beep(3, BEEP_LOW); shutdown(1); // シャットダウン } while(Timer) SLEEP; // EasyMP3のポップノイズの箕粗略ち sbi(PORTB, MUTE); // 不兰ミュ〖ト豺近 WDR; beep(1, BEEP_HIGH); // BEEP不 // VFAT攫鼠粕み艰り if (read_VFAT_info()){ beep(2, BEEP_LOW); // VFAT攫鼠の佰撅 shutdown(1); } // カ〖ド柒の妒眶澄千 MusicCount = search_MP3(0xFFFF); if (MusicCount == 0){ // MP3ファイルが痰い beep(1, BEEP_LOW); shutdown(1); // シャットダウン } if (PlayMusic == 0) PlayMusic = 1; // MMC/SDカ〖ドが蛤垂されたかどうか拇べる search_MP3(PlayMusic); if (MusicSize != ((ulong)DataBuff[28] + ((ulong)DataBuff[29] << 8) + ((ulong)DataBuff[30] << 16) + ((ulong)DataBuff[31] << 24))){ // 遍琳する妒のサイズが佰なっていれば蛤垂されたとみなす PlayMusic = 1; Cluster = 0; } for(;;){ if (PlayMusic > MusicCount) PlayMusic = 1; switch_wait(); // スイッチが庶されるまで略つ // 浩栏 r = play_music(PlayMusic, Cluster, RemainSec); switch_wait(); // スイッチが庶されるまで略つ if (r < 0){ beep(-r, BEEP_LOW); // エラ〖券栏 shutdown(0); } else if (r == 1){ // 庞面でSTOPが病された if (StopSw > 100){ // 1擅笆惧の墓病しはバッテリ〖排暗チェック if (BattVolt > BATT_26){ beep(3, BEEP_HIGH); // 2.6V笆惧 光不3搀 } else if (BattVolt > BATT_25){ beep(2, BEEP_HIGH); // 2.5V笆惧 光不2搀 } else if (BattVolt > BATT_24){ beep(1, BEEP_HIGH); // 2.4V笆惧 光不1搀 } else if (BattVolt > BATT_23){ beep(1, BEEP_LOW); // 2.3V笆惧 你不1搀 } else if (BattVolt > BATT_22){ beep(2, BEEP_LOW); // 2.2V笆惧 你不2搀 } else { beep(3, BEEP_LOW); // それ笆布 你不3搀 } continue; // 鲁きから遍琳 } else { shutdown(0); // 排富を磊る } } else if (r == 3){ // REW if (RewSw > 100){ // 1擅笆惧の墓病しは呵介の妒 PlayMusic = 1; } else if (RewSw > 25){ // 250ms笆惧の墓病しは涟の妒
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -