📄 yampp3.c
字号:
{
WDR; // Enable time to push data
nWrites = 0; // This count prevents indefinite
do // feed of data to VS1001 with no
{ // way to get control
// Amount of rest of data bursts
nBursts = (u08)(((pTemp = pPlayData) - pPlayBufStart) / 32);
while (nBursts < BUFFER_SIZE / 32 &&// While we have data and
bit_is_set(PINB, PB2)) // DREQ is high
{
vs1001_send_32(pPlayData); // Feed data to VS1001
pPlayData += 32; // Advance pointer
nBursts++;
}
dwPlayed += pPlayData - pTemp; // Count already pumped bytes
} while(++nWrites < MAX_CONS_WRITES && // We write not too many times
nBursts == BUFFER_SIZE / 32 && // and we didn't stop by DREQ
RetrieveMP3Data()); // and we read more data
if (bBuf1Empty && bBuf2Empty) // No more data to play
{ // Try to autoplay next song
bPlaying = false;
#ifdef ENABLE_CRC
UART_Printfu16(crc);
#endif
if (bRandom)
{
wSongNum = do_rand(wMaxSongs);
event = EV_PLAY;
}
else
event = EV_NEXT;
continue;
}
if (nScrollUpd >= 5) // Scroll song name every 500ms
{
lcd_gotoxy(0, 0);
for (nTemp = 0; nTemp < 16; nTemp++)
lcd_putchar(scroll_line[(scroll_pos + nTemp) % scroll_length]);
scroll_pos++;
nScrollUpd = 0;
}
if (nDispUpd >= 5) // Update other display info every 500ms
{
dispbar();
lcd_gotoxy(10,1);
dst = timestr;
if (tot_sw < 10) // 0-9
{
src = timestr;
wPlayTime = vs1001_read(VS1001_PLAYTIME);
divt = udiv(wPlayTime, 3600);
divt = udiv(divt.rem, 600);
*src++ = '0' + (u08)divt.quot;
divt = udiv(divt.rem, 60);
*src++ = '0' + (u08)divt.quot;
*src++ = ':';
divt = udiv(divt.rem, 10);
*src++ = '0' + (u08)divt.quot;
*src++ = '0' + (u08)divt.rem;
*src = 0;
}
else if (tot_sw < 12) // 10-11
{
*dst++ = '#';
src = pTrack;
while ((*dst = *src++)) dst++;
while (dst < ×tr[5])
*dst++ = ' ';
dst = timestr;
}
else if (tot_sw < 14) // 12-13
{
dst = randstr;
//while (*dst++ = *src++);
}
else if (tot_sw < 16) // 14-15
{
dst = loudstr;
//while (*dst++ = *src++);
}
tot_sw += 2;
if (tot_sw >= 16)
tot_sw = 0;
// lcd_puts(timestr);
lcd_puts(dst);
lcd_putchar(0); // Volume indicator
nDispUpd = 0;
} // if update time display
} // if (bPlaying)
} // while (true)
}
// Auxillary functions definitions
// converts 16 bit unsigned integer to string
// str[] should be 6 bytes at least. Function can return value != str
// and you have to use it as a output value start
u08* unsigned2str(u16 track, u08 *str)
{
register u08 i;
udiv_t divt;
for (i = 0; i < 5; i++) *str++ = ' ';
*str = '\0';
divt.quot = track;
do {
divt = udiv(divt.quot, 10u);
*(--str) = '0' + (u08)divt.rem;
} while (divt.quot);
return str;
}
#ifdef ENABLE_SERIAL
typedef struct pairUART // auxilliary structure for making
{ // of pairs table for select operator
u08 code, action;
} pairUART;
pairUART TableUART[] = {
{ 0, EV_IDLE },
{ 'g', EV_PLAY }, { 'G', EV_STOP },
{ 'p', EV_PREV }, { 'n', EV_NEXT },
{ 'P', EV_PREV10 }, { 'N', EV_NEXT10 },
{ 'V', EV_VOLUP }, { 'v', EV_VOLDN },
{ 'u', EV_NEUTRAL }, { 'm', EV_MUTE },
#ifdef ENABLE_NAV
{ 'l', EV_NEXTL }, { 'L', EV_PREVL },
#endif
{ 'r', EV_RANDOM }, { ' ', EV_PAUSE }
};
event_e get_char_event(void)
{
#ifdef HEXDUMP
static u32 dwLbaSector = 0;
static u32 dwTempAcc = 0;
#endif
register u08 i;
register u08 code = UART_ReceiveByte();
for (i = 0; i < sizeof(TableUART) / sizeof(TableUART[0]); i++)
if (TableUART[i].code == code)
return TableUART[i].action;
#ifdef HEXDUMP
if (code >= '0' && code <= '9')
dwTempAcc = dwTempAcc * 10 + code - '0';
if (code == 0x0d) // Enter
{
sectordump(dwLbaSector = dwTempAcc);
dwTempAcc = 0;
}
if (code == '+')
sectordump(++dwLbaSector);
if (code == '-')
sectordump(--dwLbaSector);
#endif // HEXDUMP
return EV_IDLE;
}
#endif // ENABLE_SERIAL
// get a remote control event
typedef struct pairIR
{
u16 code;
u08 action;
} pairIR;
pairIR TableIR[] = {
{ 0, EV_IDLE },
{ IR_PLAY, EV_PLAY }, { IR_STOP, EV_STOP },
{ IR_PREV, EV_PREV }, { IR_NEXT, EV_NEXT },
{ IR_PREV10, EV_PREV10 }, { IR_NEXT10, EV_NEXT10 },
{ IR_VOLUP, EV_VOLUP }, { IR_VOLDN, EV_VOLDN },
#ifdef ENABLE_NAV
{ IR_NEXTL, EV_NEXTL }, { IR_PREVL, EV_PREVL },
#endif
{ IR_RANDOM, EV_RANDOM }, { IR_PAUSE, EV_PAUSE }
};
event_e ir_event(void)
{
register u08 i;
u16 code = get_rec80();
for (i = 0; i < sizeof(TableIR) / sizeof(TableIR[0]); i++)
if (TableIR[i].code == code)
return TableIR[i].action;
return EV_IDLE;
}
// get a keyboard event - edhanced by MIS
u08 TableKbdShort[] = { EV_IDLE, EV_LOUDNESS, EV_PLAY, EV_PREV, EV_NEXT, EV_PREVL, EV_NEXTL, EV_VOLUP, EV_VOLDN };
u08 TableKbdLong[] = { EV_IDLE, EV_RANDOM, EV_STOP, EV_PREV10, EV_NEXT10, EV_PREVL, EV_NEXTL, EV_VOLUP, EV_VOLDN };
event_e get_key_event(void)
{
static u08 keydown = 0;
register u08 i;
event_e event = EV_IDLE;
cbi(MCUCR, SRE); // disable ExtRAM
outp(0xff, PORTA-1); // set port as output
outp(0, PORTA); // set all pins to 0
asm volatile("nop"); // allow time for port to activate
if (keydown) // if a key was pressed earlier
{
// see if it has been released
if (bit_is_set(PIND, PD3)) // check bit
{
// no key is down, return last key seen
if (nKeyTime < 8) // max 0.8 sec for shortpress
event = TableKbdShort[keydown]; // short keypress event
keydown = 0;
}
else
if ((nKeyTime & 0x7F) > 8) // long keypress ?
{
event = TableKbdLong[keydown]; // long keypress event
nKeyTime = 0x83; // 0.6 sec repeat time
}
}
else
{
if (bit_is_clear(PIND, PD3)) // check if a key is down
{
// a key is active, check which one
for (i = 0; i < 8; i++)
{
outp(~(1 << i), PORTA); // write bit mask
asm volatile("nop"); // wait a while
if (bit_is_clear(PIND, PD3)) // this bit ?
{
keydown = i + 1; // store the key
nKeyTime = 0; // clear keypress timer
break; // and exit
}
}
}
}
sbi(MCUCR, SRE); // enable ExtRAM
return event;
}
void send_sinewave_beeps(void)
{
static u08 buf[] = { 0x53, 0xEF, 0x6E , 0x30, 0x45, 0x78, 0x69, 0x74 };
register u08 i, j = 3;
while (j-- != 0)
{
for (i = 0; i < 4; i++)
vs1001_send_data(buf[i]);
vs1001_nulls(4);
delay10(10000); // delay 100ms
for (/*i = 4*/; i < 8; i++)
vs1001_send_data(buf[i]);
vs1001_nulls(4);
delay10(10000);
}
}
void userchars(void)
{
#ifdef ENABLE_LCD
static u08 data[] = { 0x10, 0x18, 0x1C, 0x1E, 0x1F };
register u08 i = 0;
lcd_command(0x48); // start at 2'nd definable character
while (i < 40)
lcd_data(data[i++ >> 3]); // eight times send each value
// 2 more user definable characters possible
#endif
}
void setvolume(u08 v)
{
register u08 i;
vs1001_setvolume(v, v);
eeprom_wb(EEPROM_VOLUME, v);
lcd_command(0x40);
for (i = 0; i < 8; i++)
{
if (v <= i * (VOL_STEP*(NUM_VOL_STEPS/8)))
lcd_data((1 << ((10 - i) / 2)) - 1); // Volume idicator mod
else
lcd_data(0x00);
}
}
void dispbar(void) // 10 bars of 5 steps each = 50 steps
{
register u08 i, a, nSteps = (u08)((dwPlayed * LCD_STEPS) / dwFileSize);
a = nSteps / 5; // # of full bars
lcd_gotoxy(0, 1);
for (i = 0; i < a; i++)
lcd_putchar(5);
if (a <= (LCD_STEPS / 5) - 1) // jman to fix display overwrite
lcd_putchar(1 + nSteps % 5);
}
void eeprom_ww(u08 address, u16 value)
{
union u16convert Data;
Data.value = value;
while (!eeprom_is_ready());
eeprom_wb(address, Data.bytes.low);
while (!eeprom_is_ready());
eeprom_wb(address + 1, Data.bytes.high);
while (!eeprom_is_ready());
}
bool RetrieveMP3Data(void)
{
// Buf1 Buf2 Action
// E E Read full, return true
// F E if (prep_read)
// E F return true
// else
// read_info
// F F prep_read
u08 nRes;
if (pPlayBufStart == BUFFER1P) // Check that we exhausted buffer
{
if (pPlayData == BUFFER1P + BUFFER_SIZE)
bBuf1Empty = true;
}
else // pPlayBufStart == BUFFER2P
{
if (pPlayData == BUFFER2P + BUFFER_SIZE)
bBuf2Empty = true;
}
if (bBuf1Empty && bBuf2Empty) // First case - both buffers empty
{ // unconditional read
if (CheckAndAdvanceCluster())
{
ReadBuffer(BUF1);
pPlayData = pPlayBufStart = BUFFER1P;
return true; // Need imeediate pump in
}
else
return false; // No more data for this file
}
if (!bBuf1Empty && !bBuf2Empty)// Both buffers filled, refresh FAT cache
return CheckAndAdvanceCluster() == FAT_READ;
if (bBuf1Empty)
{
if (pPlayBufStart == BUFFER1P) // Need to switch buffer
pPlayData = pPlayBufStart = BUFFER2P;
nRes = CheckAndAdvanceCluster();
if (nRes == NO_DATA)
return false;
if (nRes == DATA_EXIST)
ReadBuffer(BUF1);
return true; // Was disk operation, need pump in
}
if (bBuf2Empty)
{
if (pPlayBufStart == BUFFER2P) // Need to switch buffer
pPlayData = pPlayBufStart = BUFFER1P;
nRes = CheckAndAdvanceCluster();
if (nRes == NO_DATA)
return false;
if (nRes == DATA_EXIST)
ReadBuffer(BUF2);
return true; // Was disk operation, need pump in
}
}
#ifdef HEXDUMP
void HexDump(u08 *buffer, u16 len)
{
u16 i, j, k;
EOL();
for (i = 0, k = 0; i < len / 16; i++, k += 16)
{
UART_Printfu16(k);
UART_SendByte(' ');
for (j = 0; j < 16; j++)
{
UART_Printfu08(buffer[i * 16 + j]);
UART_SendByte(' ');
}
PRINT(" ");
for(j =0 ; j < 16; j++)
{
if (buffer[i * 16 + j] >= 0x20)
UART_SendByte(buffer[i * 16 + j]);
else
UART_SendByte('.');
}
EOL();
}
}
void sectordump(u32 sector)
{
if (ATA_ReadLBA0(sector, 1, TMP_SECTOR) == 0)
{
UART_Printfu32(sector);
HexDump(TMP_SECTOR, BPS);
}
else
PRINT("Dump failed\n");
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -