📄 yampp7_usb.c
字号:
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
/////////////////////////////////
u32 MyCluster; // current cluster number
u32 MySector = 2; // current sector number
u16 SectorsLd; // sectors in cluster counter
//
// return the next FAT in a chain
//
u32 next_fat(void)
{
u32 fat_sector = fat_start + MyCluster / (SECTORSIZE / sizeof(CLUSTER));
u16 fat_offset = MyCluster % (SECTORSIZE / sizeof(CLUSTER));
while (CARD_Read(fat_sector))
CARD_SW_Reset2();
ClusterCount++; // counter for F.Forward file sizing
return ((CLUSTER*)SectorBuffer)[fat_offset];
}
void init_load_sectors(u32 cluster)
{
MyCluster = cluster;
MySector = sector_cluster_offset + YADL_SECTORS_PER_CLUSTER * MyCluster;
SectorsLd = 0;
}
//
// load a bufferfull of data
//
void load_sector(void)
{
if (SectorsLd == YADL_SECTORS_PER_CLUSTER)
init_load_sectors(next_fat());
while(CARD_Read(MySector))
CARD_SW_Reset2();
MySector++;
SectorsLd++;
}
/****************************************************************************************/
void init_stuff(void)
{
u08 i,update = 0;
YADL_ROOT_SECTOR *pRoot; // Boot Sector struct
pRoot = (YADL_ROOT_SECTOR *) SectorBuffer; // Allocate room from the temp buffer
while (CARD_Read(YADL_SEC_ROOT)) // read root sector
CARD_SW_Reset2();
if(pRoot->id[0] != 'Y' || pRoot->id[1] != 'A' ||
pRoot->id[2] != 'D' || pRoot->id[3] != 'L') // YADL signature not found
{
lcd_clrscr();
puts("Unknown Card,\nPress STOP for\nformat to YADL\n");
static u08 tones[]= {SINE_300,SINE_500,SINE_800,SINE_1000};
for (i=0; i<4; i++)
{
beep(tones[i],200);
delayms(10);
}
do{
get_key();
i = check_event();
wdt_reset();
}while(i != EV_STOP);
if(format_new_disk() == 0) // format Card with YADL f.s.
{
puts("Formatting OK.");
beep(SINE_1500,100);
}
else
{
puts("Format ERROR !");
beep(SINE_500,200);
}
wdt_enable(6); // time for text displaying
while(1); // reset player by watchdog
}
if(pRoot->firmware_version_major != YAMPP_FIRMWARE_VERSION_MAJOR)
{
pRoot->firmware_version_major = YAMPP_FIRMWARE_VERSION_MAJOR;
update = 1;
}
if(pRoot->firmware_version_minor != YAMPP_FIRMWARE_VERSION_MINOR)
{
pRoot->firmware_version_minor = YAMPP_FIRMWARE_VERSION_MINOR;
update = 1;
}
if(strcmp_P(pRoot->build_timestamp, date_txt))
{
strcpy_P(pRoot->build_timestamp, date_txt);
update = 1;
}
if (update)
{
while(CARD_Write(YADL_SEC_ROOT))
CARD_SW_Reset2();
lcd_clrscr();
puts("\nFirmware vers.n\ninfo updated!\n");
delayms(100);
beep(SINE_1500,80);
beep(SINE_2000,80);
delayms(1000);
}
sector_cluster_offset = pRoot->sector_cluster_offset;
songbase_start = pRoot->songbase_start; // SECTOR !!
songbase_qty = pRoot->songbase_qty;
playlist_start = sector_cluster_offset + YADL_SECTORS_PER_CLUSTER * pRoot->playlist_start; // SECTOR !!!
playlist_qty = pRoot->playlist_qty;
fat_start = pRoot->fat_start;
//
// VS1001 User Software Loader
//
u32 app_start = pRoot->wasteland_start;
vs1001_fw = 0;
if (app_start != 0)
{
u16 *pData;
pData = (u16*) SectorBuffer;
CARD_Read(app_start); // read first free sector
if(*pData++ != 0x4679 || *pData++ != 0x776D) // Firmware signature ('yFmw') not found
return; // exit
u16 DataLen = *pData++; // length of firmware in words (firmware only)
vs1001_fw = *pData++; // address to enter into VS1001 register A1ADDR
// for application running.
vs1001_write(7,vs1001_fw + 0x4000); // write to VS1001 register WRAMADDR
while(DataLen--) // data length in words
{
if (pData == (u16*)(SectorBuffer+512))
{
app_start++;
CARD_Read(app_start); // read next sector with application datas
pData = (u16*) SectorBuffer; // new start address
}
vs1001_write(6,*pData++); // write firmware word to vs1001
}
}
}
/****************************************************************************************/
YADL_PLAY_LIST_ENTRY *get_pl_entry(u16 index)
{
u32 nCurSector;
//
// find (and load) correct playlist sector
//
nCurSector = playlist_start + (index >> 3); // 64 bytes per one playlist entry
while(CARD_Read(nCurSector))
CARD_SW_Reset2();
return &((YADL_PLAY_LIST_ENTRY *)SectorBuffer)[index % 8];
}
YADL_SONG_BASE_ENTRY *get_song_entry(u16 index)
{
u32 nCurSector;
nCurSector = songbase_start + (index >> 2);
while(CARD_Read(nCurSector))
CARD_SW_Reset2();
return &((YADL_SONG_BASE_ENTRY *)SectorBuffer)[index % 4];
}
// Nilrog: Rewrote this function since it couldn't properly handle
// the fact that a playlist can begin in one sector and the
// index pointed to a position which was located in the next
// sector.
u16 get_offset_entry(u16 index)
{
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);
FOFFSET offset = pListEntry->offset;
/* calculate absolute position from start of playlistfile */
u16 pos = offset + index * sizeof(u16);
/* calculate if the current playlist position wraps into another sector */
u08 wraps = pos / SECTORSIZE;
/* calculate which sector to read */
u32 nCurSector = playlist_start + wraps;
/* if playlist wraps we need to re-calculate index and offset */
if (wraps)
{
index = (pos - wraps * SECTORSIZE) / sizeof(u16);
offset = 0;
}
/* if no wrap ocurred 'index' and 'offset' are clear to use as is */
while(CARD_Read(nCurSector))
CARD_SW_Reset2();
u16 *pList = (u16*) ( (u08*)SectorBuffer + offset);
return pList[index];
}
//********************************************************************************
void Playlist_name(void)
{
u08 *src;
udiv_t divt;
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);
u16 tmp = (pListEntry->entry_qty);
lcd_clrscr();
lcd_invert();
u08 j = strlen(pListEntry->name);
if (j<14)
{
j = (14-j)*3;
while(j--)
lcd_wrdata(127);
}
lcd_puts(pListEntry->name); // playlist name
j=8;
while(j--)
lcd_putchar(' ');
lcd_normal();
YADL_SONG_BASE_ENTRY *pEntry = get_song_entry(get_offset_entry(curIndex));
strcpy(titlename, pEntry->title);
src = titlename + strlen(titlename);
*src++ = ' ';
*src++ = '(';
songtime = pEntry->play_time;
divt = udiv(songtime, 600);
u08 s = (u08)divt.quot % 10;
if (s)
*src++ = '0' + s; // song time up to 99 min
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++ = ')';
#ifndef ALTERNATE_SCROLL
if (src-titlename > 14)
*((u32*)src)++ = 0x203E3E20L; // adding " >> " sign
#else
scroll_dir = scroll_dir_2 = 0;
scrollP = scrollP_2 = 0;
#endif
*src = 0;
scroll_length_2 = src-titlename;
scroll_pos = scroll_pos_2 = 0;
printf("\n%s \n%s\n#%u/%u", pEntry->artist, titlename, curIndex+1, tmp);
status_display();
CARD_Read(MySector-1);
time_flag = 5;
scroll_flag = 2;
}
// ******************************************************************************
// this is in assembler procedure because c not propper handle
// pointers array located in program memory (in this case)
u08* PRG_RDW(u08* addr)
{
asm volatile ("movw r30,r24");
asm volatile ("LPM r24,Z+");
asm volatile ("LPM r25,Z");
return addr;
}
#define SONGS_D 0
#define MENU_D 1
u16 browse_list(u16 index, u16 min, u16 max, u08 func)
{
u08 i,j = 0;
event_e event;
while (1)
{
for (i=0; i < 2 + 2*func; i++)
{
if (func)
{
lcd_clrline(1 + i);
if (index+i < max)
{
lcd_putchar((i==j) ? 0x18 : ' ');
lcd_progputs(PRG_RDW((u08*)&function_name[index+i])); // menu print on LCD
}
}
else
{
lcd_clrline(2 + 2*i);
lcd_clrline(1 + 2*i);
if (index+i < max)
{
YADL_SONG_BASE_ENTRY *pEntry = get_song_entry(get_offset_entry(index+i));
lcd_putchar((i==j) ? 0x18 : ' ');
lcd_puts(pEntry->artist);
lcd_putchar('\n');
lcd_putchar((i==j) ? 0x18 : ' ');
lcd_puts(pEntry->title); // print title
}
CARD_Read(MySector-1);
idle();
}
}
do
{
time_flag = 0;
sleepcount = 0; // power off blocking
event = get_event();
switch (event)
{
case EV_NEXT:
case EV_UP:
if ( index+j > min )
{
if(j)
j--;
else
index--;
}
break;
case EV_PREV:
case EV_DOWN:
if ( index+j+1 < max )
{
if(j < 2*func + 1)
j++;
else
index++;
}
break;
case EV_PLAY:
info_flag = 3;
return index+j;
case EV_STOP:
info_flag = 3;
return -1;
}
}
while (event == EV_IDLE);
}
}
// ***************************************************************************************
u16 browse_songs(void)
{
lcd_gotoxy(0,0);
lcd_invert();
puts(" SELECT SONG: ");
lcd_normal();
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(curPlaylist);
return (browse_list(curIndex, 0, pListEntry->entry_qty, SONGS_D));
}
/***********************************************************************************/
u16 browse_menu(void)
{
lcd_gotoxy(0,0);
lcd_invert();
u08 i = 3;
while(i--)
lcd_wrdata(127);
puts(" - M E N U - ");
lcd_normal();
return (browse_list(menu_event ? menu_event-1 : 0, 0,10 + (BACKLIGHT_TIME != 0),MENU_D));
}
/***********************************************************************************/
#ifdef PCB_REV_D
u08 IsCharging(void)
{
u08 b = 0;
u08 c = inp(MCUCR);
outp(0, MCUCR); // disable external memory interface
cbi(CHARGE_PORT-1,CHARGE_PIN); // set pin as input
sbi(CHARGE_PORT,CHARGE_PIN); // activate pullup
asm volatile("nop");
asm volatile("nop");
if (bit_is_clear(CHARGE_PORT-2,CHARGE_PIN)) // if charging
b = 1;
outp(c, MCUCR); // restore control register setting
return b;
}
#else // PCB older than D
u08 IsCharging(void)
{
return (bit_is_clear(CHARGE_PORT-2,CHARGE_PIN));
}
#endif // PCB_REV_D
void BatteryMeasure(void)
{
if (!IsCharging()) // no charging in progress
{
cbi(PORTB, PB3); // PB3 as analog comparator input
cbi(DDRB, PB3); // for battery level measure
delay(80);
if (bit_is_set(ACSR,ACO)) // low battery
{
if (!lobatt)
{
lobatt = 1;
lobatt_time = 0;
}
else
lobatt = 2;
}
sbi(PORTB, PB3);
sbi(DDRB, PB3);
}
}
//********************************************************************************
//
// Run this as often as possible
// preferably every time around the main loop
//
void idle(void)
{
static u08 ledflash = 1;
u08 ContWrites = 250; // counter for prevent infinite vs1001 writing
u08 offtime = 20;
u08 ontime = (lobatt > 1) ? 8 : 1;
wdt_reset(); // reset the watchdog
usb_handler();
if(usb_link == 0) // usb link disables other control
{
if (isPlaying) // && !sleepenabled) // only during playing
check_keylock();
else
keylock = 0;
if (!keylock) // if keylock active
get_key(); // check keyboard
}
else
return;
if (isPlaying)
{
sleepcount = 0; // power off blocking
// pump some data to the decoder
while (bit_is_set(PIND, DREQ_PIN)) // while DREQ is hi
{
vs1001_send32(outptr); // send data on SPI bus
outptr += 32; // advance data pointer
fileplayed++;
if (--ContWrites == 0) // if vs1001 needs to more data
{
wdt_reset(); // reset the watchdog
cbi(PORTB, RESET_PIN); // VS1001 hardware reset
delayms(1);
sbi(PORTB, RESET_PIN); // VS1001 reset
delayms(10);
vs1001_reset(0);
LoudSet();
ContWrites = 250;
break; // let's take some time for system
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -