📄 yampp7_usb.c
字号:
void lcd_clrline(u08 line) // clear single line of LCD
{
register u08 i = 15;
lcd_gotoxy(4,line);
while(i--)
lcd_putchar(' ');
lcd_gotoxy(4,line); // goto begin of line
}
void lcd_clricon(u08 objc)
{
lcd_color(colors[objc], colors[objc+16]);
lcd_clrline(ICONS_YPOS+2);
lcd_clrline(ICONS_YPOS);
}
//--------------------------------------------------------------------------
#define IMAGES_COUNT 6
u08 icon_cache[6]; // max 6 avaliable icons at the same time
void clr_icon_cache(void)
{
memset(icon_cache, 255, 6);
}
void lcd_image(u08 number)
{
u08 i;
clr_icon_cache();
number *= 32;
lcd_window(0,0,127,127);
wdt_reset();
cbi(PORTB,LCD_CS);
lcd_wrcmd(LCD_CMD_RAMWR);
sbi(PORTB,LCD_CS);
u16 j;
for(i=0; i<32; i++)
{
pump_audio();
#if (CLKDIV > 0)
set_cpu_speed(CLKDIV>>1); // Cpu speed * 2
#endif
CARD_Read(lcd_data_start + number); // read sector
number++;
cbi(PORTB,LCD_CS);
for(j=0; j<512; j++)
lcd_wrdata(SectorBuffer[j]);
sbi(PORTB,LCD_CS);
}
pump_audio();
}
void lcd_icon(u08 number, u08 xpos)
{
if(icon_cache[xpos] != number)
{
icon_cache[xpos] = number;
xpos = xpos*18 + 5;
lcd_window(xpos,ICONS_YPOS,xpos+15,ICONS_YPOS+15);
// read data, 256 bytes/icon, starting after last image
CARD_Read(lcd_data_start + number/2 + (32*IMAGES_COUNT)); // read sector
cbi(PORTB,LCD_CS);
lcd_wrcmd(LCD_CMD_RAMWR);
u08 *p = (number % 2) ? SectorBuffer+256 : SectorBuffer;
u08 i = 0;
while (--i)
lcd_wrdata(*p++);
sbi(PORTB,LCD_CS);
pump_audio();
}
}
//--------------------------------------------------------------------------
void status_display(void)
{
u08 i,j,v;
lcd_icon(bRandom ? 2:1 ,0); // icon 1 or 2 - random status
lcd_icon(Repeat + 3 ,1); // icon 3 to 6 - repeat status
lcd_icon(bLoudness + 13 ,2); // icon 13 to 25 - loudness status
if ((keylock & 1) == 1)
lcd_icon(7 ,3); // icon 7 - keys locked
else
{
if (autolock)
{
i = keylock_time*8 / AUTOLOCK_TIME;
lcd_icon(26 + ((i>7) ? 7:i) ,3); // icons 26 to 33 - autolock timer ON - animation
}
else
lcd_icon(8 ,3); // icon 8 - keys UnLocked
}
if(!IsCharging())
lcd_icon((lobatt > 1) ? 10:9 ,4); // icon 9 or 10 - batt full, empty
lcd_color(colors[BALANCE_INDICATOR], colors[BALANCE_INDICATOR+16]);
if(info_flag == 1)
{
lcd_gotoxy(97,ICONS_YPOS);
i = balance;
if(balance <= 0)
{
lcd_putchar(31);
i = 0-balance;
}
else
lcd_putchar(' ');
printf("%u",i/6);
lcd_putchar( (balance >= 0) ? 30 : ' ');
}
else
{
if (volume < MIN_VOLUME)
{
lcd_window(95,ICONS_YPOS, 122,ICONS_YPOS+15);
cbi(PORTB,LCD_CS);
lcd_wrcmd(LCD_CMD_RAMWR);
for (i=0; i<16; i++)
{
v = 28*(16-i) / 16;
for(j=0; j<28; j++)
{
if(j>v && MIN_VOLUME - volume >= j * VOL_STEP * NUM_VOL_STEPS / 28)
lcd_wrdata(colors[VOLUME_BAR+1]);
else
lcd_wrdata(colors[VOLUME_BAR]);
}
}
sbi(PORTB,LCD_CS);
}
}
}
//--------------------------------------------------------------------------
void eeprom_update(void)
{
union u16convert Data;
// save current settings to EEPROM
Data.value = curPlaylist;
eeprom_wb(EEPROM_PLAYLIST, Data.bytes.low);
eeprom_wb(EEPROM_PLAYLIST + 1, Data.bytes.high);
Data.value = curIndex; // save song number within current playlist
eeprom_wb(EEPROM_SONGPOS, Data.bytes.low);
eeprom_wb(EEPROM_SONGPOS + 1, Data.bytes.high);
eeprom_wb(EEPROM_VOLUME,volume);
eeprom_wb(EEPROM_BALANCE,balance);
eeprom_wb(EEPROM_REPEAT,Repeat);
eeprom_wb(EEPROM_RANDOM,bRandom);
eeprom_wb(EEPROM_TIME,timemode);
eeprom_wb(EEPROM_LOUDNESS, bLoudness);
eeprom_wb(EEPROM_AUTOLOCK,autolock);
eeprom_wb(EEPROM_BACKLIGHT,light_mode); // save backlight mode
}
//--------------------------------------------------------------------------
void PowerOff(void)
{
beep(SINE_500,150);
backlight_on();
if(CARD_SW_Reset2())
lcd_image(4);
u08 i = POWER_OFF_BAR_LEN;
union u16convert Data;
while(i-=2)
{
lcd_gotoxy(POWER_OFF_BAR_XPOS, POWER_OFF_BAR_YPOS);
Data.bytes.high = colors[POWER_OFF_BAR];
Data.bytes.low = colors[POWER_OFF_BAR+1];
lcd_bar((POWER_OFF_BAR_LEN + 2)<<8 | i, Data.value);
delayms(10);
}
eeprom_update();
sbi(ACSR,ACD); // Disable Analog Comparator
sbi(GIMSK,INT2); // enable external interrupt 2 on falling edge
wdt_disable(); // disable the watchdog
TCCR0 = 0; // Disable Timer 0
sbi(DDRB, LED_PIN);
cbi(PORTB, LED_PIN); // Backlight off
cbi(PORTB, RESET_PIN); // keep VS1001 reset
lcd_off();
cbi(CHARGE_PORT,CHARGE_PIN); // disable pullup on charge input
cbi(CHARGE_DDR,CHARGE_PIN); // and switch to input for no current draw in sleep mode
#ifdef MMC_CARD
MMC_Off();
// sbi(MMC_PORT,MMC_CS); // MMC CS HIGH
// sbi(MMC_DDR,MMC_CS);
#endif
PORTA = 0;
DDRA = 0xff; // PORTA Output and LOW
PORTC = 0x80; // Deselect CF Card
cbi(PORTB, PB2); // FTDI reset
#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(); // global interrupt enable
DDRD = 0xC0; // WR and RD as output
sldo:
MCUCR = 0x30; // enable deep sleep mode and disable EXT RAM
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
sleepcount = 0;
while(sleepcount < 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);
while (1); // reset player by watchdog
}
/******************************************************************************
* 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 (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 (nKeyTime == 2) // if pressed by 0.3 second
backlight_on();
if (nKeyTime == 10) // if pressed by 1 second
{
nKeyTime++;
keylock_time = 0;
keylock ^= 1; // flip keylock status (bit 0)
}
return;
}
else
{
// both top buttons released and change occur
if (keylock > 1 && bit_is_set(PIND,BUTTON_3) && bit_is_set(PIND,BUTTON_4))
{
nKeyTime = 0; // clear key timer
keylock &= 1; // clear marker
wdt_enable(6); // enable watchdog
if(keylock)
backlight_off(); // Backlight off in locked state
}
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 ?
{
light_time = BACKLIGHT_TIME;
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;
backlight_on();
}
if (keyflag == 0)
nKeyTime = 0; // clear keypress timer
}
if (event != EV_IDLE)
set_event(event);
}
/******************************************************************
* RANDOM STUFF *
******************************************************************/
// Random stuff, maximum 512 songs
u08 RANDOM_TAB[64]; // "True Random" table, maximum 512 songs
// Init randomizer table
void InitRnd(void)
{
memset(RANDOM_TAB,0,sizeof(RANDOM_TAB)); // one bit in table represent one song
}
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 to lower RAM usage
for(num = 0; num < max; num++) // check if all songs in playlist has been played
if(tabval(num,0) == 0) // this one not be played yet
break; // break loop
if (num == max) // if all has been played
num = -1; // no more songs in current playlist
else
{
do
{
wdt_reset(); // kick the dog
num = (TCNT1 + TCNT0 + SectorBuffer[32]) % max; // get a random number
} while (tabval(num,0) != 0); // loop if this song has already been played
tabval(num,1); // else, mark as played
}
return num; // return song # to play
}
/************************************************************************
* FORMAT NEW DISK *
*************************************************************************/
u08 format_new_disk(void)
{
YADL_ROOT_SECTOR *pBoot; // Boot Sector struct
u32 sectors;
#ifndef MMC_CARD
IDENTIFY_DATA *pID;
u08 i,c;
u08 tmpSectorBuffer[sizeof(pID->ModelNumber)];
// first get some drive data
CARD_Identify();
// flip and save the ModelNumber data
pID = (IDENTIFY_DATA *) SectorBuffer;
strncpy(tmpSectorBuffer,(u08*)pID->ModelNumber,sizeof(pID->ModelNumber));
for (i=0;i<sizeof(pID->ModelNumber);i+=2)
{
c = tmpSectorBuffer[i];
tmpSectorBuffer[i] = tmpSectorBuffer[i+1];
tmpSectorBuffer[i+1] = c;
}
tmpSectorBuffer[sizeof(pID->ModelNumber)] = 0; // terminate entry
// get max sectors (disk size)
sectors = pID->UserAddressableSectors;
#else
u08 tmpSectorBuffer[8];
MMC_Name();
strncpy(tmpSectorBuffer, SectorBuffer, 7);
tmpSectorBuffer[7] = 0; // terminate entry
sectors = MMC_Capacity();
#endif
// clear buffer
pBoot = (YADL_ROOT_SECTOR *) SectorBuffer; // use temp buffer for room
strcpy_P(pBoot->model,firmware_scan_tag); // for compiler warning supression...
// I don't know why, but it decrease code size too
memset(pBoot,0,512);
// section 1
strncpy(pBoot->id,"YADL",4);
pBoot->disk_size = sectors;
pBoot->unmount_state = YADL_STATE_NEW;
pBoot->media_type = YADL_MEDIA_FLASH;
pBoot->disk_version_major = DISK_LAYOUT_VERSION_MAJOR;
pBoot->disk_version_minor = DISK_LAYOUT_VERSION_MINOR;
strcpy_P(pBoot->model,model_txt); // yampp model name
// copy the ModelNumber result from Identify Drive
strcpy(pBoot->disk_info,tmpSectorBuffer);
// section 2
strcpy_P(pBoot->build_timestamp,date_txt);
pBoot->build_timestamp[YADL_LEN_BUILD_TIMESTAMP-1] = 0; // make sure it's terminated
pBoot->firmware_version_major = YAMPP_FIRMWARE_VERSION_MAJOR;
pBoot->firmware_version_minor = YAMPP_FIRMWARE_VERSION_MINOR;
// section 3
// section 4
// section 5
// write the sector
// and return result
return CARD_Write(YADL_SEC_ROOT);
}
//////////////////////////////////
u32 songbase_start;
u16 songbase_qty; // number of songs
u32 fat_start; // first fat sector
u32 sector_cluster_offset; // add to cluster -> sector conversions
u32 playlist_start; // first playlist sector
u16 playlist_qty; // number of playlists
/////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -