?? mp3player2_c.txt
字號:
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 + -