📄 yampp3_usb.c
字号:
j=8;
while(j--)
{
for (i = 0; i < 8; i++)
{
if (i >= j)
lcd_data1f();
else
lcd_data00();
}
}
// if(!info_flag)
// lcd_clrline(LCD_LINES - 1);
// else
Vlcd_gotoxy(0, LCD_LINES - 1);
#if (LCD_LINE_LENGTH > 16)
Vlcd_progputs(PSTR("Volume "));
#else
Vlcd_progputs(PSTR("Vol"));
#endif
for (i=0; i < 8; i++) // write volume bar
{
if(MIN_VOLUME - v >= i * (VOL_STEP*(NUM_VOL_STEPS/8)))
Vlcd_putchar(i);
else
Vlcd_putchar(' ');
}
if (v < 20) Vlcd_putchar(' ');
if (v > 1)
Vlcd_putchar('-');
else
Vlcd_putchar(' ');
lprintf("%udB",v/2);
}
#else //GRAPH_LCD
status_display(); // update status bar on Graphisc LCD
Vlcd_gotoxy(10+7*(LCD_TYPE == 8)-1*(v>19),LCD_TYPE-2);
if (v > 1)
Vlcd_putchar('-');
else
Vlcd_putchar(' ');
lprintf("%udB",v/2); // Volume Level
#endif // GRAPH_LCD
#endif // SATTELITE
#ifdef VOL_UP_RAMP
if(!volume_ramp)
#endif
eeprom_wb(EEPROM_VOLUME,v); // only after ramp ends (EEPROM write cycles save)
time_flag = 5; // prevent display overvriting for 2 second
info_flag = 1; // allow scroll data
}
//--------------------------------------------------------------------------
void setbalance(s08 b)
{
vs1001_setvolume(volume,b);
eeprom_wb(EEPROM_BALANCE,b);
#ifdef GRAPH_LCD
status_display(); // update status bar on Graphisc LCD
u08 i = b;
#if(LCD_TYPE == 7)
Vlcd_gotoxy(10,5);
#else
Vlcd_gotoxy(17,6);
#endif
Vlcd_putchar(' ');
if(b <= 0)
{
Vlcd_putchar('<');
i = 0-b;
}
else
Vlcd_putchar('-');
lprintf("%u",i/4);
Vlcd_putchar( (b >= 0) ? '>':'-');
#else //GRAPH_LCD
u08 i = b;
lcd_clrline(LCD_LINES - 1);
Vlcd_progputs(PSTR("Balance "));
if(b <= 0)
{
Vlcd_putchar(0x7f);
i = 0-b;
}
else
Vlcd_putchar('-');
lprintf("-%u-",i/4);
Vlcd_putchar( (b >= 0) ? 0x7e:'-');
#endif //GRAPH_LCD
info_flag = 2; // allow scroll data, balance mode
time_flag = 5; // prevent display overvriting for 2 second
}
//--------------------------------------------------------------------------
void eeprom_ww(u16 address, u16 value) // write word to eeprom
{
asm volatile("call eeprom_write_byte");
asm volatile("subi r24,lo8(-(1))");
asm volatile("sbci r25,hi8(-(1))");
asm volatile("mov r22,r23");
asm volatile("call eeprom_write_byte");
}
/************************************************************************
* RANDOM STUFF *
************************************************************************/
// Random stuff, maximum 32768 songs on the disk!
static u32 seed = 1;
// Init randomize table
void InitRnd(void)
{
memset(RANDOM_TAB,0,4096); // clear random table
}
u16 randcalc(u16 max) // assembler optimized randomizer function
{
// 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; // return result from R24:R25
}
u08 tabval(u16 num, u08 fn) // check random tabele for song status
{ // and mark as played if necessary
u16 index = 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 &= 0x7fff; // limit for lower RAM usage
for(num = 0; num < max; num++)
if(tabval(num,0) == 0)
break;
if (num == max)
num = -1;
else
{
do
{
// WDR;
num = randcalc(max);
} while (tabval(num,0) != 0); // check this song not be played piervously
tabval(num,1); // mark as just played
}
return num;
}
/************************************************************************
* FORMAT NEW DISK *
*************************************************************************/
u08 format_new_disk(void)
{
YADL_ROOT_SECTOR *pBoot; // Boot Sector struct
IDENTIFY_DATA *pID;
u08 i,c;
u32 sectors;
i = firmware_scan_tag[0]; // for compiler warning supression
// first get some drive data
IdentifyDrive(buffer1);
// flip and save the ModelNumber data
pID = (IDENTIFY_DATA *) buffer1;
strncpy(buffer1,(u08*)pID->ModelNumber,sizeof(pID->ModelNumber));
for (i=0;i<sizeof(pID->ModelNumber);i+=2)
{
c = buffer1[i];
buffer1[i] = buffer1[i+1];
buffer1[i+1] = c;
}
buffer1[sizeof(pID->ModelNumber)] = 0; // terminate entry
// get max sectors (disk size)
sectors = pID->UserAddressableSectors;
// clear buffer
pBoot = (YADL_ROOT_SECTOR *) buffer2; // use temp buffer for room
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_DISK;
pBoot->disk_version_major = DISK_LAYOUT_VERSION_MAJOR;
pBoot->disk_version_minor = DISK_LAYOUT_VERSION_MINOR;
strncpy_P(pBoot->model,model_txt, YADL_LEN_MODEL); // yampp model name
// copy the ModelNumber result from Identify Drive
strncpy(pBoot->disk_info, buffer1, YADL_LEN_DISK_INFO);
// section 2
strncpy_P(pBoot->build_timestamp, date_txt, YADL_LEN_BUILD_TIMESTAMP);
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 (ATA_Write(0,1,(u08*) pBoot));
}
/****************************************************************************************/
u32 songbase_start; // first songbase sector
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; // current sector number
u16 SectorsLd; // sectors in cluster counter
/****************************************************************************************/
//
// return the next FAT in a chain
//
u32 next_fat(u32 current_fat)
{
u16 fat_offset;
u32 fat_sector;
static u32 fat_in_cache = -1;
fat_sector = fat_start + current_fat / (SECTORSIZE / sizeof(CLUSTER));
fat_offset = current_fat % (SECTORSIZE / sizeof(CLUSTER));
if (fat_sector != fat_in_cache)
{
while(ATA_Read(fat_sector,1,(u08*)FAT_CACHE))
ATA_SW_Reset2();
fat_in_cache = fat_sector;
}
if(BackStepPos < MAX_REV_STEPS)
Rev_Table[++BackStepPos] = ((CLUSTER*)FAT_CACHE)[fat_offset];
return ((CLUSTER*)FAT_CACHE)[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_sectors(u08 *buffer)
{
while(ATA_Read( MySector, BUFFERSIZE / SECTORSIZE, buffer))
ATA_SW_Reset2();
MySector += BUFFERSIZE / SECTORSIZE;
SectorsLd += BUFFERSIZE / SECTORSIZE;
if (SectorsLd == YADL_SECTORS_PER_CLUSTER)
init_load_sectors(next_fat(MyCluster));
}
/****************************************************************************************/
static char firmver_txt[] __attribute__ ((progmem)) = "Firmware version";
void init_stuff(void)
{
u08 update = 0;
YADL_ROOT_SECTOR *pRoot; // Boot Sector struct
pRoot = (YADL_ROOT_SECTOR *) buffer1; // Allocate room from the temp buffer
while(ATA_Read(0,1,buffer1)) // read root sector
ATA_SW_Reset2();
if(pRoot->id[0] != 'Y' || pRoot->id[1] != 'A' ||
pRoot->id[2] != 'D' || pRoot->id[3] != 'L') // YADL signature not found
{
event_e event = EV_IDLE;
Vlcd_clrscr();
both_progputs(PSTR("Found not YADL\nor new disk !!\n"));
#if (LCD_LINES == 2)
delayms(5000);
Vlcd_clrscr();
#endif
both_progputs(PSTR("Press PLAY to\nformat the disk."));
uart_EOL();
while((event = get_event()) != EV_PLAY); // wait for PLAY key
Vlcd_clrscr();
both_progputs(PSTR("All data be lost\nAre you sure ?\n"));
while((event = get_event()) == EV_PLAY); // wait for release key
while((event = get_event()) != EV_PLAY); // wait for accept by PLAY key
#if (LCD_LINES == 2)
Vlcd_clrscr();
#endif
both_progputs(PSTR("Format"));
register u08 i = format_new_disk();
both_progputs((i) ? PSTR(" ERROR !") : PSTR("ing OK."));
wdt_enable(0x07);
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(ATA_Write(0,1,(u08*) pRoot))
ATA_SW_Reset2();
Vlcd_clrscr();
both_progputs((u08*)&firmver_txt);
both_progputs(PSTR("\ninfo updated.\n"));
delayms(4000);
}
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;
u16 *pData;
pData = (u16*) buffer1;
while(ATA_Read(app_start,1,buffer1)) // read first free sector
ATA_SW_Reset2();
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*)(buffer1+512))
{
app_start++;
while(ATA_Read(app_start,1,buffer1)) // read next sector with application datas
ATA_SW_Reset2();
pData = (u16*) buffer1; // new start address
}
vs1001_write(6,*pData++); // write firmware word to vs1001
}
}
/****************************************************************************************/
u16 curPlaylist = 0;
u16 curIndex = 0;
u16 selected_Playlist;
#ifdef SATTELITE
/****************************************************************************************/
YADL_PLAY_LIST_ENTRY *get_pl_entry(u16 index)
{
static u32 nLastSector = -1;
u32 nCurSector;
//
// find (and load) correct playlist sector
//
nCurSector = playlist_start + (index >> 3); // 64 bytes per one playlist entry
if (nCurSector != nLastSector)
{
while(ATA_Read(nCurSector,1,(u08*)PL_CACHE))
ATA_SW_Reset2();
nLastSector = nCurSector;
}
return &((YADL_PLAY_LIST_ENTRY *)PL_CACHE)[index % 8];
}
/****************************************************************************************/
YADL_SONG_BASE_ENTRY *get_song_entry(u16 index)
{
static u32 nLastSector = -1;
u32 nCurSector;
nCurSector = songbase_start + (index >> 2);
if (nCurSector != nLastSector)
{
while(ATA_Read(nCurSector,1,(u08*)SE_CACHE))
ATA_SW_Reset2();
nLastSector = nCurSector;
}
return &((YADL_SONG_BASE_ENTRY *)SE_CACHE)[index % 4];
}
/****************************************************************************************/
u16 get_offset_entry(u16 index, u16 Playlist)
{
static u32 nLastSector = -1;
YADL_PLAY_LIST_ENTRY *pListEntry = get_pl_entry(Playlist);
FOFFSET offset = pListEntry->offset;
// first compute desired start sector
u32 nCurSector = playlist_start + (offset / SECTORSIZE) + (index * sizeof(u16) / SECTORSIZE);
offset = offset % SECTORSIZE; // cut offset to rest inside one sector
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -