📄 yampp7_usb.c
字号:
delayms(100);
for (j=0;j<3;j++)
{
beep(SINE_1000,100);
delayms(100);
}
}
//--------------------------------------------------------------------------
void lcd_clrline(u08 line) // clear single line of LCD
{
register u08 i=14;
lcd_gotoxy(0,line);
for(i=0; i < 14; i++)
lcd_putchar(' ');
lcd_gotoxy(0,line); // goto begin of line
}
//--------------------------------------------------------------------------
void status_display(void)
{
u08 i = 0;
lcd_gotoxy(0,5);
if (bRandom)
{
i=127;
lcd_invert();
}
lcd_wrdata(i);
puts("\x1\x2"); // Random signs
lcd_normal();
lcd_wrdata(i);
lcd_wrdata(0);
lcd_putchar(Repeat + 0x10); // Repeat sign L
lcd_putchar(Repeat + 0x14); // Repeat sign R
lcd_wrdata(0);
if (vs1001_fw)
{
lcd_wrdata(0);
lcd_putchar('L');
lcd_putchar((bLoudness > 9) ? bLoudness + ('A'-10) : bLoudness + '0');
}
else
{
i=0;
if (bLoudness)
{
i=127;
lcd_invert();
}
puts("\x3\x4"); // MegaBass signs
lcd_normal();
lcd_wrdata(i);
}
lcd_wrdata(0);
if ((keylock & 1) == 1)
{
puts("\x5\x6"); // locked sign
#if (BACKLIGHT_TIME != 0)
backlight_off(); // Backlight off in locked state
#endif
}
else
{
if (autolock)
puts("\xE\xF"); // autolock signs
else
puts(" ");
}
lcd_wrdata(0);
#ifndef BATT_MONITOR
if (lobatt > 1)
puts("\x8\x9"); // low battery signs
else
puts("\xB\xC"); // good battery signs
#else
if (lobatt < 3)
puts("\x8\x9"); // low battery signs
else
{
puts("\xB\xC"); // good battery signs
lcd_wrcmd(0x45); // ypos = 5
lcd_wrcmd(0xB9); // xpos = 57 pixel
for( i=12; i > lobatt ; i-- )
lcd_wrdata(0x22); // empty accu
if(i < 12 && i > 3)
{
lcd_wrdata(0x3E);
lcd_wrdata(0x3E);
}
lcd_wrcmd(0xC3); // xpos = 67 pixel
}
#endif
if(info_flag == 1)
{
i = balance;
if(balance <= 0)
{
lcd_putchar(0x1A);
i = 0-balance;
}
else
lcd_putchar(' ');
printf("%u",i/6);
lcd_putchar( (balance >= 0) ? 0x19 : ' ');
}
else
{
if (volume < MIN_VOLUME)
{
for (i=0; i<16; i++)
{
if(MIN_VOLUME - volume >= i * VOL_STEP * NUM_VOL_STEPS / 16)
lcd_wrdata(0xff << (8 - (i+1)/2));
else
lcd_wrdata(0);
}
}
else
{
vs1001_setvolume(254,0);
lcd_wrdata(0);
lcd_putchar(0x07); // speaker
lcd_wrdata(0);
lcd_wrdata(0);
lcd_putchar('x'); // off :)
}
}
}
//--------------------------------------------------------------------------
u08 lcd_card_logo(void)
{
u16 i;
if (CARD_SW_Reset2())
{
CARD_Read(YADL_SEC_SCRATCH); // read scrath sector
if (SectorBuffer[0] == 'y' && SectorBuffer[1] == 'W') // check for Logo Tag
{ // if present:
lcd_gotoxy(0,0); // begin at x=0, y=0
for (i = 2; i < 4*84+2; i++) // 4x84 bytes of logo bytes
lcd_wrdata(SectorBuffer[i]); // write to LCD
return 0; // return status: logo found
}
}
return (lcd_logo(0)); // check for EEPROM logo
}
//--------------------------------------------------------------------------
void eeprom_update(void)
{
union u16convert Data;
// save current settings to EEPROM
Data.value = curPlaylist;
eeprom_write_byte((u08 *)EEPROM_PLAYLIST, Data.bytes.low);
eeprom_write_byte((u08 *)EEPROM_PLAYLIST + 1, Data.bytes.high);
Data.value = curIndex; // save song number within current playlist
eeprom_write_byte((u08 *)EEPROM_SONGPOS, Data.bytes.low);
eeprom_write_byte((u08 *)EEPROM_SONGPOS + 1, Data.bytes.high);
eeprom_write_byte((u08 *)EEPROM_VOLUME,volume);
eeprom_write_byte((u08 *)EEPROM_BALANCE,balance);
eeprom_write_byte((u08 *)EEPROM_REPEAT,Repeat);
eeprom_write_byte((u08 *)EEPROM_RANDOM,bRandom);
eeprom_write_byte((u08 *)EEPROM_TIME,timemode);
eeprom_write_byte((u08 *)EEPROM_LOUDNESS, bLoudness);
eeprom_write_byte((u08 *)EEPROM_AUTOLOCK,autolock);
#if (BACKLIGHT_TIME != 0)
eeprom_write_byte((u08 *)EEPROM_BACKLIGHT,light_mode); // save backlight mode
#endif
}
//--------------------------------------------------------------------------
void PowerOff(void)
{
beep(SINE_500,150);
#if (BACKLIGHT_TIME != 0)
backlight_on();
#endif
lcd_clrscr();
if(lcd_card_logo())
lcd_gotoxy(2,2);
else
lcd_gotoxy(2,4);
puts("Goodbye !!");
u08 i =80;
while(i--)
{
lcd_gotoxy(0,5);
lcd_bar(i,82);
delayms(15);
}
eeprom_update();
ACSR |= _BV(ACD); // Disable Analog Comparator
GIMSK |= _BV(INT2); // enable external interrupt 2 on falling edge
wdt_disable(); // disable the watchdog
lcd_clrscr();
lcd_off();
// keep VS1001and FTDI reset
// Backlight off
PORTB &= ~(_BV(RESET_PIN) | _BV(PB2) | _BV(LED_PIN));
CHARGE_PORT &= ~ _BV(CHARGE_PIN); // disable pullup on charge input
CHARGE_DDR &= ~ _BV(CHARGE_PIN); // and switch to input for no current draw in sleep mode
#ifdef MMC_CARD
MMC_Off();
#endif
PORTA = 0;
DDRA = 0xFF; // PORTA Output and LOW
PORTC = 0x80; // Deselect CF Card
#ifndef FIXED_RESET
PORTD = 0x32; // WR and RD low to avoid powering FTDI chip via WR and RD signals
#else
PORTD = 0xB2; // RD high and and WR low to avoid powering FTDI chip via WR and RD signals,
#endif // but need to modyfi the board. High RD is for solving problems
// with accidentaly CF card "True IDE Mode" entering after card insert.
sei();
DDRD = 0xC0; // WR and RD as output
sldo:
MCUCR = 0x30; // enable deep sleep mode and disable EXT RAM
TCCR0 = 0; // stop timer0
TCCR1B = 0; // stop timer1
asm volatile("sleep"); // Enter to Sleep mode
asm volatile("nop");
// ***********************************
// wakeup going here
MCUCR = 0x20; // enable idle mode
TCCR1B = 4; // start timer1
time_flag = 0;
while(time_flag < 10)
{
asm volatile("sleep"); // Enter to idle mode
asm volatile("nop");
if bit_is_set(PINE,BUTTON_1) // Play key pressed ?
goto sldo; // No, go to deep sleep again
}
PORTD = 0xFF; // WR and RD high to avoid CF garbage
wdt_enable(1);
cli();
while (1);
}
// -----------------------------------------------------------------------------------
void lobat_shutdown(void)
{
#ifdef BATT_MONITOR
BatteryMeasure();
if(lobatt == 0) // battery voltage critical
#else
lobatt = 0;
BatteryMeasure();
if (lobatt) // low battery
#endif
{
isPlaying = 0;
lcd_gotoxy(0,logo);
puts("Low Battery !");
send_sinewave_beeps();
send_sinewave_beeps();
delayms(1000);
PowerOff();
}
}
/******************************************************************************
* KEYBOARD CONTROL FUNCTION *
******************************************************************************/
//
// button handling
//
//------------------------------------------------------------------------------------------
// Keyboard layout (while playing)
//
// BUTTON_1 BUTTON_2 BUTTON_3 BUTTON_4
u08 TableKbdShort[] = { EV_IDLE, EV_PLAY, EV_STOP, EV_NEXT, EV_PREV };
u08 TableKbdLong[] = { EV_IDLE, EV_FFWD, EV_MENU, EV_UP, EV_DOWN };
// Keyboard layout (On Stop)
// BUTTON_1 BUTTON_2 BUTTON_3 BUTTON_4
// ShortPress: PLAY STOP MBASS RANDOM
// LongPress: PWR.OFF MENU AU.LOCK, LCD Contrast
void check_keylock(void)
{
if (autolock)
{
// if automatic lock timer enabled and timeout -> Led blink
if (keylock_time > AUTOLOCK_TIME && keylock_time < AUTOLOCK_TIME+20)
goto KBLINK;
}
if (bit_is_clear(PIND,BUTTON_3) && bit_is_clear(PIND,BUTTON_4))
{ // if both top buttons down
wdt_disable(); // disable watchdog for prevent from bootloader entering
keylock |= 2; // mark as pressed
#if (BACKLIGHT_TIME != 0)
backlight_on();
#endif
if (nKeyTime == 10) // if pressed by 1 second
{
nKeyTime++;
keylock ^= 1; // flip keylock status (bit 0)
}
if (nKeyTime > 10) // signalise by Led blink
{
nKeyTime = 11;
KBLINK:
#if (BACKLIGHT_TIME == 0)
if ((time_flag & 3) == 2)
{
time_flag++;
if (bit_is_set(PORTB,LED_PIN)) // LED Flashing
PORTB &= ~_BV(LED_PIN);
else
PORTB |= _BV(LED_PIN);
}
#endif
return;
}
}
else
{
// both top buttons released and change occur
if (keylock > 1 && bit_is_set(PIND,BUTTON_3) && bit_is_set(PIND,BUTTON_4))
{
#if (BACKLIGHT_TIME == 0)
PORTB |= _BV(LED_PIN); // Led ON
#endif
nKeyTime = 0; // clear key timer
keylock_time = 0; // clear automatic lock timer
keylock &= 1; // clear marker
wdt_enable(6); // enable watchdog
}
if (keylock)
nKeyTime = 0;
}
}
void get_key(void)
{
static u08 keydown = 0;
u08 keyflag;
event_e event = EV_IDLE;
if (keydown) // if a key was pressed earlier
{
// see if it has been released
if (bit_is_set(PINE,BUTTON_1) && // if key up
bit_is_set(PIND,BUTTON_2) && // if key up
bit_is_set(PIND,BUTTON_3) && // if key up
bit_is_set(PIND,BUTTON_4) ) // if key up
{
// no key is down, return last key seen
if (nKeyTime < 8 && nKeyTime > 0) // max 0.8 sec for shortpress
event = TableKbdShort[keydown]; // short keypress event
keydown = 0;
}
else
if ((nKeyTime & 0x7F) >= 8) // long keypress ?
{
#if (BACKLIGHT_TIME != 0)
light_time = 0;
#endif
event = TableKbdLong[keydown]; // long keypress event
if (event == EV_UP || event == EV_DOWN || event == EV_FFWD)
nKeyTime = 0x86; // 0.2 sec repeat time for volume
else
nKeyTime = 0x80; // as long repeat as possible
}
}
else
{
keyflag = 0;
if (bit_is_clear(PINE,BUTTON_1)) // if key 1 down
keyflag = 1; // store it
if (bit_is_clear(PIND,BUTTON_2)) // if key 2 down
keyflag = 2; // store it
if (bit_is_clear(PIND,BUTTON_3)) // if key 3 down
keyflag = 3; // store it
if (bit_is_clear(PIND,BUTTON_4)) // if key 4 down
keyflag = 4; // store it
if (keyflag && nKeyTime > 0)
{
keydown = keyflag; // store it
keylock_time = 0;
#if (BACKLIGHT_TIME != 0)
backlight_on();
#endif
}
if (keyflag == 0)
nKeyTime = 0; // clear keypress timer
}
if (event != EV_IDLE)
set_event(event);
}
/******************************************************************
* RANDOM STUFF *
******************************************************************/
// Random stuff, maximum 512 songs
static u32 seed = 1;
u08 RANDOM_TAB[64]; // "True Random" table, maximum 512 songs
// Init randomize table
void InitRnd(void)
{
memset(RANDOM_TAB, 0, 64);
}
u16 randcalc(u16 max) // returned random value from 0 to max - 1
{
// return ((seed = seed * 1103515245L + 12345) % max); // get new song number
asm volatile ("push r24");
asm volatile ("push r25");
asm volatile ("lds r22,seed");
asm volatile ("lds r23,(seed)+1");
asm volatile ("lds r24,(seed)+2");
asm volatile ("lds r25,(seed)+3");
asm volatile ("ldi r18,lo8(1103515245)");
asm volatile ("ldi r19,hi8(1103515245)");
asm volatile ("ldi r20,hlo8(1103515245)");
asm volatile ("ldi r21,hhi8(1103515245)");
asm volatile ("call __mulsi3");
asm volatile ("subi r22,lo8(-(12345))");
asm volatile ("sbci r23,hi8(-(12345))");
asm volatile ("sbci r24,hlo8(-(12345))");
asm volatile ("sbci r25,hhi8(-(12345))");
asm volatile ("sts seed,r22");
asm volatile ("sts (seed)+1,r23");
asm volatile ("sts (seed)+2,r24");
asm volatile ("sts (seed)+3,r25");
asm volatile ("pop r19");
asm volatile ("pop r18");
asm volatile ("clr r20");
asm volatile ("clr r21");
asm volatile ("call __udivmodsi4");
asm volatile ("mov r25,r23");
asm volatile ("mov r24,r22");
return max;
}
u08 tabval(u16 num, u08 fn) // check random tabele for song status
{ // and mark as played if necessary
u08 index = (u08)(num >> 3);
u08 offset = 1 << (num % 8);
if(fn)
RANDOM_TAB[index] |= offset; // if fn=1 mark as played
return (RANDOM_TAB[index] & offset); // return status
}
// new random procedure
u16 do_rand(u16 max) // returned random value from 0 to max - 1
{
u16 num;
max &= 0x01ff; // limit to 512 songs for lower RAM usage
for(num = 0; num < max; num++) // check for all songs in playlist
if(tabval(num,0) == 0) // not be played yet
break;
if (num == max)
num = -1; // no more songs in current playlist
else
{
do
{
wdt_reset();
num = randcalc(max);
} while (tabval(num,0) != 0); // check this song not be played piervously
tabval(num,1); // mark as just played
}
return num;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -