[问答] mp3

butterflydw ( 楼主 ) 2018-6-26 05:12:22  显示全部楼层
本帖最后由 一只耳朵怪 于 2018-6-26 10:21 编辑

//2008.9.1
//m8
//a13758777532编写

  //学习日本的科技,提高中国水平
#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
#define  VS1001_CLOCK 12000000

#define  SPI_CS  2
#define  SPI_DIN  3
#define  SPI_CLK  5
#define  SPI_DOUT 4

//#define  MP3_SO  1
#define  MP3_SI  7
#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 //
#define  VOLTAGE  5 //
#define  MUTE  1 //
#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.2V

uchar 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 }; // 1500Hz
PROGMEM uchar ErrorBeep[] = { 0x53, 0xEF, 0x6E, 0x35, 0, 0, 0, 0 }; // 500Hz
PROGMEM 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:FAT16
uchar 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笆惧の墓病しは涟の妒
    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

1个回复

whamy 发表于 2018-6-26 16:05:45
看一下 谢谢分享!
回复

举报 使用道具

您需要登录后才可以回帖 登录 | 注册

本版积分规则


关闭

站长推荐上一条 /9 下一条

小黑屋|手机版|Archiver|电子发烧友 ( 粤ICP备14022951号-2 )

GMT+8, 2018-7-18 20:41 , Processed in 0.627219 second(s), 24 queries , Memcache On.

Powered by 电子发烧友网

© 2015 bbs.elecfans.com

微信扫描
快速回复 返回顶部 返回列表