📄 yampp7_usb.c
字号:
// check for buffer wrap
if ( outptr == (SectorBuffer+512) ) // buffer empty
{
outptr = SectorBuffer; // data pointer at begin of sector buffer
if (!usb_play)
load_sector(); // will load into SectorBuffer on YAMPP7
else
{
usb_response(0);
break;
}
}
// check if we're done
if (fileplayed >= filesize)
{
if (!usb_play)
isPlaying = 0; // the end is near
next_song(0);
return;
}
}
if (vol_decrease && (time_flag == 4)) // If fast forward volume downed
{
vs1001_setvolume(volume,balance); // Restore volume
vol_decrease = 0;
}
//------------------------ LCD VISUALISATION ----------------------------
if (scroll_flag >= SCROLL_SPEED && info_flag < 2)
{
u08 nTemp;
#ifndef ALTERNATE_SCROLL
static u08 scrollP;
#define scrollP_2 scrollP
#endif
scroll_flag = 0;
//
// scrolling artist and name
if (scroll_length > 14)
{
lcd_gotoxy(0, 1);
lcd_data_o(artistname[scroll_pos % scroll_length],scrollP);
for (nTemp = 1; nTemp < 15; nTemp++)
#ifdef ALTERNATE_SCROLL
lcd_putchar(artistname[scroll_pos + nTemp]);
if (scroll_pos + 14 == scroll_length)
scroll_dir -= 2;
if (scroll_pos == 0 && scrollP == 0)
scroll_dir++;
scrollP += ((signed char)scroll_dir / (10/SCROLL_SPEED)) * SCROLL_STEP;
if (scrollP == 6)
{
scrollP = 0;
scroll_pos++;
}
if (scrollP > 127)
{
scrollP = 6 - SCROLL_STEP;
scroll_pos--;
}
#else //ALTERNATE_SCROLL
lcd_putchar(artistname[(scroll_pos + nTemp) % scroll_length]);
#endif
}
lcd_gotoxy(0, 2);
if (scroll_length_2 > 14)
{
lcd_data_o(titlename[scroll_pos_2 % scroll_length_2],scrollP_2);
for (nTemp = 1; nTemp < 15; nTemp++)
#ifdef ALTERNATE_SCROLL
lcd_putchar(titlename[scroll_pos_2 + nTemp]);
if (scroll_pos_2 + 14 == scroll_length_2)
scroll_dir_2 -= 2;
if (scroll_pos_2 == 0 && scrollP_2 == 0)
scroll_dir_2++;
scrollP_2 += ((signed char)scroll_dir_2 / (10/SCROLL_SPEED)) * SCROLL_STEP;
if (scrollP_2 == 6)
{
scrollP_2 = 0;
scroll_pos_2++;
}
if (scrollP_2 > 127)
{
scrollP_2 = 6 - SCROLL_STEP;
scroll_pos_2--;
}
#else //ALTERNATE_SCROLL
lcd_putchar(titlename[(scroll_pos_2 + nTemp) % scroll_length_2]);
#endif
lcd_gotoxy(0,3);
lcd_data('#');
}
else
lcd_puts(titlename);
#ifndef ALTERNATE_SCROLL
scrollP += SCROLL_STEP;
if (scrollP == 6)
{
scrollP = 0;
scroll_pos++;
scroll_pos_2++;
}
#endif
}
if (time_flag >= 5 && info_flag < 2)
{
if(bLoudness)
vs1001_write(0x0D,bLoudness); // Rewrite loudness settings
// if VS1001 do selfreset
//
// display bar function
register u08 nSteps = (u08)((fileplayed * 82) / filesize);
lcd_gotoxy(0,4);
lcd_bar(nSteps,82);
status_display();
//
// printing song time
lcd_gotoxy(8,3); // time display position
u16 wPlayTime = vs1001_read(VS1001_PLAYTIME) + addtime;
if (timemode == 1)
{
wPlayTime = songtime - wPlayTime; // calculate time remain
if ((s16)wPlayTime < 0)
wPlayTime = 0;
}
printf("%3u:%02u", wPlayTime / 60, wPlayTime % 60); // print time on LCD
if (timemode == 1)
{
lcd_gotoxy(8 + (wPlayTime < 600),3);
lcd_putchar('-');
}
if (IsCharging()) // charging in progress ?
{
lobatt = 0;
lobatt_time = 0;
ledflash = !ledflash;
lcd_gotoxy(9,5);
lcd_wrdata(0);
if (ledflash)
puts(" ");
else
puts("\xB\xC");
}
if (!info_flag)
time_flag = 0;
}
if((time_flag > 30) && (menu_event != EV_IDLE)) // display overvrite timer ends
{
info_flag = 0; // enable status updating
menu_event = EV_IDLE;
Playlist_name(); // show Playlist name
}
//------------------------ LCD VISUALISATION END -------------------------
}//if (isPlaying)
else
{
if (IsCharging()) // charging in progress ?
{
sleepcount = 0; // power off blocking
ontime = 20; // LED 2 sec on / 0.2 sec off
offtime = 2; // until end charge.
lobatt = 0; // clear low battery status
lobatt_time = 0; // clear low battery timer
if (time_flag % 10 == 0)
{
if(!info_flag) // not in menu
{
lcd_gotoxy(0,4);
puts("Battery charge");
}
lcd_gotoxy(9,5);
lcd_wrdata(0);
puts(" ");
}
if (time_flag % 10 == 5)
status_display();
}
#if (BACKLIGHT_TIME == 0)
if (ledflash-- == 0)
{
if (bit_is_set(PORTB,LED_PIN)) // LED Flashing
{
cbi(PORTB,LED_PIN); // off
ledflash = offtime;
}
else
{
sbi(PORTB,LED_PIN); // on
ledflash = ontime;
}
}
#endif
if (!menu_event)
{
outp(0xA0,MCUCR); // choose idle mode
asm volatile ("sleep"); // go to sleep
asm volatile ("nop");
wdt_reset(); // reset the watchdog
}
if (sleepcount > DEEP_SLEEP_TIMEOUT)
PowerOff(); // Go to power off procedure and off player
if (! CARD_SW_Reset2()) // if card removed
PowerOff(); // power off
if (time_flag >= 30)
{
if (menu_event || (lobatt_time < 50 && offtime == 20))
set_event(EV_STOP); // if auto menu exit or end of battery charge
else
status_display();
menu_event = EV_IDLE;
time_flag = 0;
}
}
BatteryMeasure();
u16 off_time = lobatt_time;
if (lobatt == 2)
{
#if (BACKLIGHT_TIME == 0)
if (isPlaying && (off_time % 20) == 0) // while playing
cbi(PORTB,LED_PIN); // and battery level is low
if (isPlaying && (off_time % 20) == 10) // led blinks
sbi(PORTB,LED_PIN);
#endif
if ((off_time % 600) == 10) // and beeps in one minute interval
beep(SINE_2000,80);
if (off_time > 6050) // and power off after 10 minutes
{
send_sinewave_beeps();
PowerOff();
}
}
}
void play_song(void)
{
isPlaying = 1;
if (info_flag == 0)
Playlist_name();
YADL_SONG_BASE_ENTRY *pEntry = get_song_entry(get_offset_entry(curIndex));
if(pEntry->state != YADL_STATE_READY) // check for valid song entry
{
puts("\nSongBase Error !");
beep(SINE_500,500);
set_event(EV_STOP);
return;
}
// init randomizer from timer
seed += (inp(TCNT1H)<<8) + (inp(TCNT1L)) + 1;
addtime = 0;
bitrate = ((pEntry->bitrate) & 0x7fff); // get bitrate and mask VBR signature (MSB)
strcpy(artistname, pEntry->artist);
scroll_length = strlen(artistname);
#ifndef ALTERNATE_SCROLL
if (scroll_length > 14)
{
strcat(artistname, " >> "); // add ' >> ' sign
scroll_length += 4;
}
#endif
//
// calc number of VS1001 blocks
//
// u08 garbage = ((pEntry->bitrate & (~OPTION_BR_ID1_TAG)) != 0) ? 128 : 0;
// filesize = (pEntry->length - garbage) / 32;
// calculation number of blocks, 14 bit of
// bitrate indicate that file have ID3 tag
// and this may be excluded (last 128 bytes)
filesize = pEntry->length / 32;
fileplayed = 0;
ClusterCount = 0; // Reset Cluster counter
//
// preload buffers
//
init_load_sectors(pEntry->start);
// u08 i;
// for (i=0; i < (pEntry->start_offset / SECTORSIZE); i++)
// load_sector(); // skip first pEntry->start_offset of full buffers
outptr = SectorBuffer; // + (pEntry->start_offset % SECTORSIZE); // and rest of pEntry->start_offset
//
// start playing the song
//
#if (BACKLIGHT_TIME == 0)
sbi(PORTB, LED_PIN); // LED ON
#endif
vs1001_reset(0);
LoudSet();
}
void next_playlist(void)
{
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);
if(pListEntry->next_playlist != (u16)-1) // check for next playlist number
curPlaylist = pListEntry->next_playlist;
else
curPlaylist++;
if((curPlaylist == (u16)-1) || (curPlaylist >= playlist_qty))
curPlaylist = 0;
pListEntry = get_pl_entry(curPlaylist);
InitRnd(); // init randomizer table
curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : 0;
}
void prev_playlist(void)
{
if(--curPlaylist == (u16)-1) // playlist down
curPlaylist = playlist_qty - 1; // go to last playlist
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist); // update playlist data
InitRnd();
curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : pListEntry->entry_qty-1;
}
void next_song(u08 mode)
{
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);
if (Repeat == 3 && mode == 0) // repeat one song
goto GO_PLAY;
if (mode == 2)
{
#ifdef NEW_PREW
if(ClusterCount)
goto GO_PLAY;
else
#endif
curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : curIndex-1;
}
else
curIndex = (bRandom) ? do_rand(pListEntry->entry_qty) : curIndex+1;
if (curIndex < (pListEntry->entry_qty)) // if not End of playlist
goto GO_PLAY;
else
{
InitRnd(); // init randomizer table
if(Repeat == 2) // repeat playlist
{
if (bRandom)
curIndex = do_rand(pListEntry->entry_qty);
else
curIndex = 0;
goto GO_PLAY;
}
if(Repeat == 0)
{
set_event(EV_STOP); // normal play, stop after end of playlist
return;
}
if(Repeat == 1 || Repeat == 3) // normal play and repeat one song, next playlist after end of playlist
{ // fixed by Roger Nilson
if (mode == 2)
prev_playlist();
else
next_playlist();
GO_PLAY: play_song();
}
}
}
//----------------------------------------------------------------------------
void set_contrast(void)
{
event_e event = EV_IDLE;
u08 contrast = eeprom_rb(EEPROM_LCD_CONTRAST);
lcd_clrscr();
puts("Adjust contras\nt with volume \nkeys, STOP=End");
lcd_gotoxy(2,3);
lcd_bar((contrast-0x20),0x38);
status_display();
while(1)
{
wdt_reset(); // reset the watchdog
time_flag = 0;
sleepcount = 0; // power off blocking
event = get_event();
switch(event)
{
default:
case EV_IDLE:
break;
case EV_UP:
case EV_NEXT:
if (contrast < 0x58)
contrast++;
goto SETC;
case EV_DOWN:
case EV_PREV:
if (contrast > 0x20)
contrast--;
SETC:
lcd_gotoxy(2,3);
lcd_bar((contrast-0x20),0x38);
lcd_contrast(contrast);
break;
case EV_STOP:
eeprom_wb(EEPROM_LCD_CONTRAST,contrast);
lcd_clrscr();
set_event(EV_STOP);
return;
}
event = EV_IDLE;
}
}
#if defined (__AVR_ATmega162__)
void set_cpu_speed(u08 speed)
{
asm volatile("ldi r25, 128");
asm volatile("cli");
asm volatile("sts 0x61, r25");
asm volatile("sts 0x61, r24");
asm volatile("sei");
}
#endif
//----------------------------------------------------------------------------
// Main part
//----------------------------------------------------------------------------
int main(void)
{
//------------------------------
// Initialize
//------------------------------
//////////////////////////////////////////////////////////////////
// B - Port
//////////////////////////////////////////////////////////////////
cbi(PORTB,LED_PIN);
sbi(DDRB, LED_PIN); // pin PB0 is output for LED or backlight
sbi(PORTB,RESET_PIN); // RESET- hi
sbi(DDRB, RESET_PIN); // pin PB1 is output, RESET-
// PB2 is BSYNC pin to VS1001 and RST pin to FTDI chip
// PB3 is MP3 signal to VS1001
// PB4 is SCE signal for LCD dosplay
// PB5 (MOSI) is used for SPI
// PB6 (MISO) is used for SPI
// PB7 (SCK) is used for SPI
//////////////////////////////////////////////////////////////////
// D - Port
//////////////////////////////////////////////////////////////////
outp(0xFF,PORTD); // activate pullups
outp(0xC0,DDRD);
// pin PD0 is DREQ input
// pin PD1, PD4 and PD5 is keyboard input, enable pullup
// PD2 and PD3 are RXF and TXE input pins from FTDI
// PD6 and PD7 are WR and RD signals for CF and FTDI chip.
//////////////////////////////////////////////////////////////////
// E - Port
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -