ButterflyMP3

main.c

Go to the documentation of this file.
00001 
00039 #include <avr/io.h>
00040 #include <avr/pgmspace.h>
00041 #include <avr/interrupt.h>
00042 #include "main.h"
00043 #include "types.h"
00044 #include "uart.h"
00045 #include "delay.h"
00046 #include "vs1001.h"
00047 #include "mmc.h"
00048 #include "avrfat16.h"
00049 #include "timer0.h"
00050 #include "button.h"
00051 #include "eeprom.h"
00052 #include "lcdgraphics.h"
00053 #include "power.h"
00054 #include "utils.h"
00055 #include "BCD.h" // for getnumbered song
00056 
00057 //#include "testing.h"
00058 
00060 const char  VERSIONINFO1[] PROGMEM = "ButterflyMP3_sf_net V0.7";        
00062 const char  VERSIONINFO2[] PROGMEM = __DATE__ __TIME__ ;
00063 
00064 
00065 #ifdef NOKIA
00066 extern  uint8 fbXY[];           
00067 #endif
00068 
00069 // player option variables
00070 uint8   gmusic_vol      = DEFAULT_MUSIC_VOLUME; 
00071 volatile uint8  gbass_boost     =0;     
00072 volatile uint8  gFastForward    =0;     
00073 
00074 // player state variables
00075 uint8   gMode           =0;     
00076 BOOL    gLCD_Refresh;           
00077 // @TODO: move these into file struct
00078 uint32  gFAT_entry      =0;     
00079 uint32  gCluster;               
00080 uint32  gFileSectorSize;        
00081 uint32  gFileSectorsPlayed;     
00082 BOOL    gFile_good;             
00083 char    cluster_pos=0;          
00084 char    buff_pos=16;            
00085 
00086 //volatile uint16 gBatteryVoltage;      ///< last ADC battery Voltage reading
00087 
00088 #if FAT_NumberedSong_EN
00089 uint8 gCurrentSongNum=0; 
00090 #endif
00091 
00092 volatile uint16 gPlayTimeSeconds; 
00093 uint8   gDisplayTimeOut=0;        
00094         
00096 const uint8     __attribute__ ((progmem)) volume_val[10] = {160,128,112, 96, 80, 64, 48, 32, 16, 0};
00097 
00098 // internal Function Prototypes
00099 //uint8 FAT_readRoot(uint32 filenumber);
00100 void    flush_decoder(char reset_type);
00101 void    cue_file(void);
00102 void    streaming (void);
00103 void    handle_interface(void);
00104 void    update_LCD(void);
00105 void    mainTimer(void);
00106 uint8   init_mmc_fat(void);
00107 uint8   handle_mmc(uint8 MMC_present);
00108 
00109 /* ..Removed to save space.
00110 void DumpGlobals(void)
00111 {
00112 #ifdef ALPHA
00113         extern volatile signed char gScroll;
00114         extern volatile char gScrollMode;
00115 #endif
00116         
00117         UART_Printfu08(gmusic_vol);EOL();
00118         UART_Printfu08(gbass_boost);EOL();
00119         UART_Printfu08(gMode);EOL();
00120         UART_Printfu08(gLCD_Refresh);EOL();
00121         UART_Printfu08(gFile_good);EOL();
00122         UART_Printfu08(gDisplayTimeOut);EOL();
00123 #ifdef ALPHA
00124         UART_Printfu08(gScroll);EOL();
00125         UART_Printfu08(gScrollMode);EOL();
00126 #endif
00127         UART_Printfu16(gPlayTimeSeconds);EOL();
00128         
00129         UART_Printfu32(gFAT_entry);EOL();
00130         UART_Printfu32(gCluster);EOL();
00131         UART_Printfu32(gFileSectorSize);EOL();
00132         UART_Printfu32(gFileSectorsPlayed);EOL();
00133 }
00134 */
00135 
00136 
00142 void    init_HW(void)
00143 {
00144         // boost IntRC to 8Mhz 
00145         //OSCCAL_calibration();
00146         CLKPR = (1<<CLKPCE);                // set Clock Prescaler Change Enable
00147         CLKPR = (0<<CLKPS1)|(0<<CLKPS0);    // set prescaler = 1, Internal RC 8Mhz   
00148 
00149         // Disable Analog Comparator (power save)
00150         ACSR = (1<<ACD);
00151 
00152         // Disable Analog to Digital converter (power save)
00153         //ADCSRA = 0;
00154 
00155         // Disable Digital input on PF0-7 (power save)
00156         DIDR1 = 0xFF; 
00157 
00158 #ifdef PWR_CHK_INTERVAL
00159         Power_Init();           // init power monitoring 
00160         // abort power up if battery is low.
00161         if (Power_check()<PWR_MIN_V) { 
00162                 //Jump to Bootloader
00163                 WDTCR = (1<<WDCE) | (1<<WDE);     //Enable Watchdog Timer to give reset
00164                 while(1);   
00165         }
00166 #endif
00167         
00168         // setup IO
00169         UART_Init();            // init RS-232 link
00170         /* enable interrupts */
00171         sei();
00172         SpiInit();              // init spi pins (mmc & VS1001)
00173         vs1001_init_io();       // init IO pins
00174         vs1001_init_chip();     // Reset Chip
00175         Timer0_Init();          // setup timers for debounce and scroll
00176         Button_Init();          // setup joystick.
00177         LCD_Initialize();       // SETUP lcd
00178         
00179         //register  timer routine 
00180         Timer0_RegisterCallbackFunction(mainTimer);
00181         
00182         // Read settings (volume and stuff from eeprom or flash)
00183         load_player_options();
00184         vs_1001_setvolume(pgm_read_byte(volume_val+gmusic_vol), pgm_read_byte(volume_val+gmusic_vol));
00185         
00186 
00187         
00188         // say hello on Serial 
00189         PRINT("AVR ButterflyMP3 Player  "__DATE__" "__TIME__);EOL();    
00190         
00191         // set up the FAT variables
00192         FAT_buffer = mmc_sbuf;  // 512 byte buffer for sector reads/writes
00193         FAT_scratch = mmc_scratch; 
00194         FAT_read = MMC_Read; // pointer to read block function 
00195         //FAT_write = MMC_Write;// pointer to write block function 
00196         FAT16_entryMAX =-1;
00197         FAT16_entryMIN = 0;
00198 } 
00199 
00200 
00201 
00202 void mainTimer(void)
00203 {
00204         static uint16 timeout_count=0; 
00205         static uint16 second_timer=TIMER0_TICKSPERSECOND;
00206 #ifdef PWR_CHK_INTERVAL
00207         static uint8 power_timer=PWR_CHK_INTERVAL;
00208         uint16 batteryVoltage;
00209 #endif
00210         extern unsigned char gButtonTimeout;    // Variable from "button.c" to prevent button-bouncing
00211 
00212         
00213         
00214         
00215         /**************** Button timeout for the button.c, START ****************/
00216     if(!gButtonTimeout)
00217     {
00218         timeout_count++;
00219         
00220         if(timeout_count > BUTTON_TIMEOUT_VALUE) 
00221         {            
00222             // UART_Printfu08(timeout_count);EOL();
00223             timeout_count = 0;
00224                         // long_timeout_count=0;
00225             gButtonTimeout = TRUE;
00226         }
00227                 
00228     }
00229         /*
00230          if(!gButtonLongTimeout){ // start the hold down timer
00231      long_timeout_count++;
00232      
00233      if(long_timeout_count > 1000){
00234      gButtonLongTimeout = TRUE;
00235      KEY_SHIFT=TRUE;
00236      KEY_VALID=TRUE;
00237      timeout_count = 0;
00238      long_timeout_count=0;
00239      }
00240      
00241          }*/
00242         
00243         /**************** Button timeout for the button.c, END ******************/
00244     
00245 
00246     // RA Sewell - other half a second
00247     if (second_timer == TIMER0_TICKSPERSECOND/2)
00248     {
00249       gLCD_Refresh = TRUE;
00250     }
00251 
00252         if (!second_timer--){
00253                 second_timer=TIMER0_TICKSPERSECOND;
00254                 if (gMode != MODE_PLAY){
00255                         gPowerSaveTimer++;
00256                         //UART_Printfu08(gPowerSaveTimer);EOL();
00257                 }else{
00258                         gPlayTimeSeconds++;                     
00259                 }
00260       gLCD_Refresh = TRUE;
00261         
00262 #ifdef PWR_CHK_INTERVAL
00263                 if ((power_timer--)==0){
00264                         power_timer = PWR_CHK_INTERVAL;
00265                         batteryVoltage = Power_check();
00266                         if (batteryVoltage>PWR_GOOD_V){
00267                                 //PRINT("Battery GOOD");
00268                                 //EOL();
00269                         }else if (batteryVoltage>PWR_LOW_V){
00270                                 //PRINT("Battery OK");
00271                                 //EOL();
00272                         }else if (batteryVoltage>PWR_MIN_V){
00273                                 //PRINT("Battery LOW");
00274                                 //EOL();
00275                         }else if (batteryVoltage>PWR_ABS_MIN_V){
00276                                 //PRINT("Battery FLAT");
00277                                 //EOL();
00278                         }else {
00279                                 PRINT("LOW BTRY PWR DWN");
00280                                 EOL();
00281                                 // stop playing and power down
00282                                 gMode = MODE_PAUSE;
00283                                 // save everything to eeprom
00284                                 //save current settings
00285                                 save_player_options();
00286                                 
00287                                 //TODO: Write MMC Serial Number to EEPROM
00288                                 
00289                                 //write current song to EEPROM
00290                                 save_player_state();
00291                                                                 
00292                                 gPowerSaveTimer=AUTOPOWEROFF_TIMEOUT;
00293                         }
00294                 }
00295 #endif
00296         
00297                 if(gDisplayTimeOut){
00298                         if (gDisplayTimeOut==1){
00299                                 #ifdef ALPHA
00300                                 // Display back to normal
00301                                 LCD_FileName(TRUE);
00302                                 #endif  
00303                                 gDisplayTimeOut = 0;
00304                         }else{ 
00305                                 // continue the count down
00306                                 gDisplayTimeOut--;
00307                         }
00308                 }
00309                 
00310         }
00311 
00312 }
00313 
00314 uint8 open_Dir(uint32 dir_lba){
00315         uint8 files =0;
00316         
00317         // display mode on LCD
00318         LCD_Scanning();
00319         
00320         files = FAT_scanDir_lba(dir_lba);
00321         
00322         gFAT_entry= FAT16_entryMIN;
00323         cue_file(); // load the file into memory
00324         
00325         // Display back to normal
00326         LCD_FileName(TRUE);
00327         
00328         //PRINT("1ST FLE @ ");UART_Printfu16(FAT16_entryMIN);
00329         //PRINT("  LST FLE @ ");UART_Printfu16(FAT16_entryMAX);EOL();
00330         //UART_Printfu08(files);PRINT("files");EOL();
00331         
00332         return files;
00333 }
00334 
00341 uint8 restore_player(void)
00342 {
00343         uint8   MMC_present,mode;
00344         uint16  time;
00345         uint32  file,sector,played,dir;
00346         
00347         mode=0; file=0; sector=0;       played=0;       time=0;
00348 
00349         // check for an mmc on startup
00350         MMC_present = handle_mmc(FALSE);
00351         
00352         if (!MMC_present){ //Can't restore no MMC  
00353                 //PRINT("NO MMC. Rstre abortd");EOL();
00354                 return MMC_present; 
00355         }
00356         
00357         // read last song details from EEPROM
00358         load_player_state(&mode,&file,&sector,&played,&time,&dir);
00359 
00360                 // Debug loading info
00361 //              PRINT("Loaded from EEPROM");EOL();
00362 //              UART_Printfu08(mode);EOL();
00363 //              UART_Printfu32(file);EOL();
00364 //              UART_Printfu16(time);EOL();
00365 //              UART_Printfu32(sector);EOL();
00366 //              UART_Printfu32(played);EOL();
00367 //              UART_Printfu32(dir);EOL();
00368         
00369         if ((mode != MODE_PAUSE)&&( mode != MODE_IDLE)){ // nothing to restore
00370                 //PRINT("MODE != PAUSE");EOL();
00371                 return MMC_present;
00372         }
00373         
00374         // todo: check if mmc is same mmc
00375         
00376         // check song is available
00377         if ( FAT_getNextSong(file-1,dir) == file){ // song found
00378                 open_Dir( dir);
00379                 gFAT_entry = file; // select file
00380                 cue_file(); // load the file into memory
00381                 gMode = mode;
00382                 gCluster = sector; // move to last played position
00383                 gFileSectorsPlayed = played;
00384                 gPlayTimeSeconds = time;
00385                 gLCD_Refresh=TRUE;
00386         }else{ // song not found
00387                 gFAT_entry =FAT16_entryMIN;
00388         }
00389         return MMC_present;
00390 }
00391 
00392 
00393 
00401 uint8   init_mmc_fat(void)
00402 { 
00403         uint8 result;
00404         
00405         //DumpGlobals();
00406         gFAT_entry = 0;
00407         FAT16_entryMIN = 0;
00408         FAT16_entryMAX = -1;
00409         
00410         result =  MMC_Reset();                          // init mmc
00411         if (result) return result;
00412         
00413         result = FAT_initFat16();
00414         if (result) return result; // abort on non-zero reply 
00415         
00416         UART_Printfu32(FAT16_root_dir_first_sector);EOL();
00417         
00418         result = open_Dir(FAT16_root_dir_first_sector);
00419         
00420         //return 0 if files found, 1 if 0 files
00421         return !result;
00422 }
00423 
00424 
00425 
00432 void    flush_decoder(char reset_type)
00433 {
00434         uint16 buf[2];
00435         
00436         // reset VS1001 and set clock doubler
00437         vs1001_reset(reset_type);
00438 
00439         // send VS1001 settings
00440         vs_1001_setvolume(pgm_read_byte(volume_val+gmusic_vol), pgm_read_byte(volume_val+gmusic_vol));
00441         
00442     vs1001_read(SCI_MODE, 1, buf);
00443     
00444     // this whole bass boost thing is wrong.... has it ever worked???
00445 #ifdef VS1001
00446         buf[0] &= ~SM_MP12;
00447         if (gbass_boost){
00448                 buf[0] |= SM_BASS;
00449         }else{
00450                 buf[0] &= ~SM_BASS;
00451         }
00452 //      if (gFastForward){
00453 //              buf[0] != SM_FFWD;      
00454 //      }else{
00455 //              buf[0] &= ~SM_FFWD;
00456 //      }
00457 #endif
00458 
00459 #ifdef VS1000_NEW
00460     buf[0] |= SM_SDINEW ;
00461 #endif
00462         vs1001_write(SCI_MODE,1,buf);
00463         
00464         if (gFastForward){
00465                 buf[0] = 0x8600;
00466         }else   {
00467                 buf[0] = 0x9800;}
00468         vs1001_write(SCI_CLOCKF,1,buf); 
00469 
00470 }
00471     
00472 
00481 void    cue_file(void)
00482 {
00483         uint8 check;
00484 //      uint8 temp;
00485         uint32 ID3index;
00486         uint8 i;
00487         uint16 j;
00488         uint32 offset;
00489         uint16 ID3_Bytes;
00490         uint32 ID3_clusters;
00491         uint16 ID3_sectors;
00492         uint32 nextCluster=0;
00493         
00494         
00495         // read file data and check gFAT_entry is aValid file entry.
00496         check = FAT_readFile(gFAT_entry,FAT16_dir_first_sector);
00497         if (check) return;
00498         
00499         if (FAT16_filetype & FILE_TYPE_DIR) return;
00500 /*
00501         //skip or recurse Directories
00502         if (FAT16_filetype & FILE_TYPE_DIR){
00503                 if (RECURSE_DIRECTORIES){
00504                         // scan a new directory....
00505                         // get cluster address from fat entry
00506                         gCluster = FAT_scratch[13];
00507                         gCluster <<= 8;
00508                         gCluster += FAT_scratch[14];
00509                         gCluster <<= 8;
00510                         gCluster += FAT_scratch[15];
00511                         gCluster <<= 8;
00512                         gCluster += FAT_scratch[16];
00513                         
00514                         // check for files and exit on no files(always 2 entries . and ..)
00515                         //if (open_Dir(gCluster)<3) {
00516                         //      return;
00517                         //}
00518                         
00519                         nextCluster = FAT_readFile(FAT16_entryMIN,FAT16_dir_first_sector);
00520                         
00521                 }else{
00522                         if (PLAY_NEXT_SONG){ // cue up next song and play it.
00523                                 nextCluster = FAT_getNextSong(gFAT_entry,FAT16_dir_first_sector);
00524                                 if(nextCluster){// play next song
00525                                         gFAT_entry = nextCluster;
00526                                         gLCD_Refresh=TRUE;
00527                                         gMode = MODE_PLAY;
00528                                 }else if(PLAY_REPEAT_ALL){
00529                                         gFAT_entry = FAT16_entryMIN;
00530                                         gLCD_Refresh=TRUE;
00531                                         gMode = MODE_PLAY;
00532                                 }
00533                         }
00534                 }
00535         }
00536         */
00537         nextCluster=0;
00538         
00539         // get first Cluster 
00540         FAT_Scratch2Cluster();
00541 //      gCluster = FAT_scratch[13];
00542 //      gCluster <<= 8;
00543 //      gCluster += FAT_scratch[14];
00544 //      gCluster <<= 8;
00545 //      gCluster += FAT_scratch[15];
00546 //      gCluster <<= 8;
00547 //      gCluster += FAT_scratch[16];
00548 
00549         //get fileSize in whole sectors
00550         /*
00551         *((char *)&gFileSectorSize+2) = FAT_scratch[17];
00552         *((char *)&gFileSectorSize+1)= FAT_scratch[18];
00553         *((char *)&gFileSectorSize+0) = FAT_scratch[19];
00554 
00555 */
00556         
00557         gFileSectorSize += FAT_scratch[17];
00558         gFileSectorSize <<= 8;
00559         gFileSectorSize += FAT_scratch[18];
00560         gFileSectorSize <<= 8;
00561         gFileSectorSize += FAT_scratch[19];
00562 
00563         cluster_pos = 0;
00564         buff_pos = 0;
00565         FAT_readCluster(gCluster,0);
00566         
00567         gFile_good = TRUE;
00568         gFileSectorsPlayed = 0;
00569         
00570         // Detect and Skip ID3 Info at start of file
00571         // (we ignore tags at end of file)
00572         
00573         // Version 1.x 
00574         if (FAT_buffer[0] == 'T' && FAT_buffer[1] == 'A' && FAT_buffer[2]=='G') {
00575                 //PRINT("ID3 v1 TAG");EOL();
00576                 // jump to byte 128
00577                 buff_pos = 4; 
00578         }else
00579                 
00580         // Version 2.x - now with very basic interpretation!
00581         if (FAT_buffer[0] == 'I' && FAT_buffer[1] == 'D' 
00582                           && FAT_buffer[2]=='3'){ 
00583                 //PRINT("ID3 v2.");
00584                 //UART_Printfu08(FAT_buffer[5]);
00585                 //UART_Printfu08(FAT_buffer[4]);
00586                 //PRINT(" TAG");
00587 
00588       
00589                 /*
00590                 An ID3v2 tag can be detected with the following pattern:
00591                 $49 44 33 yy yy xx zz zz zz zz
00592                 Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80.
00593                 z = ID3 tag length.
00594                  */
00595                 
00596                 offset = 0;
00597                 for(i=6;i<10;i++){
00598                         offset <<= 7; // only shift by 7 as MSB is unused.
00599                         offset += FAT_buffer[i];
00600                 }
00601 
00602 
00603 
00604       
00605                 offset += 10; //include length of header
00606                 //UART_Printfu32(offset);PRINT("B");EOL();
00607 
00608       // offset is now equal to the the length of the TAG
00609       ID3index = 10; // skip header
00610 
00611 #if ID3_EN
00612       switch (FAT_buffer[3])
00613       {
00614          case 2:
00615             // Search for song / artist frame and replace long filename with them
00616             while ((ID3index < offset) && (ID3index < 512))
00617             {
00618                if (FAT_buffer[ID3index] == 'T' &&
00619                    FAT_buffer[ID3index+1] == 'T' &&
00620                    FAT_buffer[ID3index+2] == '2')
00621                {
00622                   //PRINT(" SONG");          
00623 
00624                   // For some reason, all strings have a Null at the front of the 
00625                   // name - I think this indicates the encoding type - we'll assume
00626                   // its always 00, string! (this is what the -1 is for)
00627                   // other -1 is for the null on the end of the string
00628                   for (i=0; (i<FAT_buffer[ID3index+5]-1) && (i<LFN_TITLE_LENGTH-1); i++)
00629                   {
00630                      FAT16_longfilename[LFN_TITLE_INDEX+i] = FAT_buffer[ID3index+7+i]; 
00631                   }
00632                   FAT16_longfilename[LFN_TITLE_INDEX+i] = '\0';
00633 
00634                   // Recalculate string length / add a blank
00635                   FAT16_LFNTitleLen = strLen(FAT16_longfilename+LFN_TITLE_INDEX);
00636 
00637                   // Indicate TITLE found
00638                   FAT16_longfilename[LFN_TYPE_INDEX] |= LFN_TYPE_ID3_TITLE;
00639                }
00640                else if (FAT_buffer[ID3index] == 'T' &&
00641                         FAT_buffer[ID3index+1] == 'P' &&
00642                         FAT_buffer[ID3index+2] == '1')
00643                {
00644                   //PRINT(" ARTIST");
00645                   for (i=0; (i<FAT_buffer[ID3index+5]-1) && (i<LFN_ARTIST_LENGTH-1); i++)
00646                   {
00647                      FAT16_longfilename[LFN_ARTIST_INDEX+i] = FAT_buffer[ID3index+7+i]; 
00648                   }
00649                   FAT16_longfilename[LFN_ARTIST_INDEX+i] = '\0';
00650 
00651                   // Recalculate string length / add a blank
00652                   FAT16_LFNArtistLen = strLen(FAT16_longfilename+LFN_ARTIST_INDEX);
00653 
00654                   // Indicate ARTIST found
00655                   FAT16_longfilename[LFN_TYPE_INDEX] |= LFN_TYPE_ID3_ARTIST;
00656                }
00657                
00658                // Skip to next ID3 'frame'
00659                ID3index += FAT_buffer[ID3index+5] + 6;
00660                //PRINT(" I:");
00661                //UART_Printfu08(ID3index);
00662             }
00663 
00664 
00665             break;
00666             
00667          case 3:
00668          case 4:
00669 
00670             // Search for song / artist frame and replace long filename with them
00671             while ((ID3index < offset) && (ID3index < 512))
00672             {
00673                if (FAT_buffer[ID3index] == 'T' &&
00674                    FAT_buffer[ID3index+1] == 'I' &&
00675                    FAT_buffer[ID3index+2] == 'T' &&
00676                    FAT_buffer[ID3index+3] == '2')
00677                {
00678                   //PRINT(" SONG");          
00679 
00680                   // For some reason, all strings have a Null at the front of the 
00681                   // name - I think this indicates the encoding type - we'll assume
00682                   // its always 00, string! (this is what the -1 is for)
00683                   // other -1 is for the null on the end of the string
00684                   for (i=0; (i<FAT_buffer[ID3index+7]-1) && (i<LFN_TITLE_LENGTH-1); i++)
00685                   {
00686                      FAT16_longfilename[LFN_TITLE_INDEX+i] = FAT_buffer[ID3index+11+i]; 
00687                   }
00688                   FAT16_longfilename[LFN_TITLE_INDEX+i] = '\0';
00689 
00690                   // Recalculate string length / add a blank
00691                   FAT16_LFNTitleLen = strLen(FAT16_longfilename+LFN_TITLE_INDEX);
00692 
00693                   // Indicate TITLE found
00694                   FAT16_longfilename[LFN_TYPE_INDEX] |= LFN_TYPE_ID3_TITLE;
00695                }
00696                else if (FAT_buffer[ID3index] == 'T' &&
00697                         FAT_buffer[ID3index+1] == 'P' &&
00698                         FAT_buffer[ID3index+2] == 'E' &&
00699                         FAT_buffer[ID3index+3] == '1')
00700                {
00701                   //PRINT(" ARTIST");
00702                   for (i=0; (i<FAT_buffer[ID3index+7]-1) && (i<LFN_ARTIST_LENGTH-1); i++)
00703                   {
00704                      FAT16_longfilename[LFN_ARTIST_INDEX+i] = FAT_buffer[ID3index+11+i]; 
00705                   }
00706                   FAT16_longfilename[LFN_ARTIST_INDEX+i] = '\0';
00707 
00708                   // Recalculate string length / add a blank
00709                   FAT16_LFNArtistLen = strLen(FAT16_longfilename+LFN_ARTIST_INDEX);
00710 
00711                   // Indicate ARTIST found
00712                   FAT16_longfilename[LFN_TYPE_INDEX] |= LFN_TYPE_ID3_ARTIST;
00713                }
00714                
00715                // Skip to next ID3 'frame'
00716                ID3index += FAT_buffer[ID3index+7] + 10;
00717                //PRINT(" I:");
00718                //UART_Printfu08(ID3index);
00719             }
00720 
00721 
00722             break;
00723          default:
00724             ; // Unknown version, do nothing
00725       }
00726 #endif
00727                 // skip through to end of ID3 
00728                 ID3_clusters = (offset/512) / FAT16_sectors_per_cluster;
00729                 ID3_sectors = (offset/512) % FAT16_sectors_per_cluster;
00730                 ID3_Bytes = offset % 512;
00731                 
00732                 //UART_Printfu32(ID3_clusters);EOL();
00733                 //UART_Printfu16(ID3_sectors);EOL();
00734                 //UART_Printfu16(ID3_Bytes);EOL();
00735                 
00736                 // find first cluster of actual song
00737                 for (j=0;j<ID3_clusters;j++){
00738                         
00739                         nextCluster = FAT_NextCluster(gCluster);
00740                 //      UART_Printfu16(j);UART_SendByte(0x09);
00741                 //      UART_Printfu32(nextCluster);EOL();
00742                         if (nextCluster == 0xffffffff){
00743                                 gFile_good = FALSE;
00744                                 PRINT("EOF: ID3 Tag @ Clstr ");
00745                                 UART_Printfu32(gCluster);
00746                                 EOL();
00747                                 return;
00748                         }
00749                         gCluster = nextCluster;
00750                 }
00751 
00752                 
00753                 // Adjust variables for new position.
00754                 gFileSectorsPlayed = (offset / 512);
00755                 buff_pos = (ID3_Bytes/32);
00756                 cluster_pos = ID3_sectors;
00757 
00758                 /*
00759                 while(FAT_readCluster(gCluster,cluster_pos)){
00760                         MMC_Reset();    
00761                 }
00762                 */      
00763                 
00764                 /*PRINT("ID3 Tag skipped. First ten bytes of MP3 stream are ... ");
00765                 for (i=0;i<10;i++){
00766                         UART_Printfu08(FAT_buffer[i+ID3_Bytes]);
00767                 }
00768                 EOL();
00769                 */
00770                 j=ID3_Bytes % 32;
00771                 if (j){//we need to play(skip;) some bytes
00772                         buff_pos++; // skips to next 32 byte chunk of buffer
00773                 }
00774         }else{ //dump  first 10 bytes of file
00775                 /*
00776                 for (i=0;i<10;i++){
00777                         UART_Printfu08(FAT_buffer[i]);
00778                 }
00779                 EOL();
00780                  */
00781         }
00782         
00783         // send params to vs1001k
00784         flush_decoder(SOFT_RESET);      
00785         
00786         //reset play timer...
00787         gPlayTimeSeconds = 0;
00788         return;
00789 }
00790 
00791 
00798 void    streaming (void)
00799 {
00800 //      uint16 c;
00801         uint8   abort=0;
00802 //      uint16 tmp=0;
00803 //      uint16 state[2];
00804         uint32 nextfile;
00805 
00806         
00807         if (!gFile_good) return; // only run if we have a valid file.
00808         
00809         if (buff_pos>15) { // we need to get a new sector
00810 
00811                 gFileSectorsPlayed++;
00812                 
00813                 if (cluster_pos>FAT16_sectors_per_cluster-1){ // need new cluster
00814                         cluster_pos=0;
00815                         gCluster = FAT_NextCluster(gCluster);
00816 
00817                 }
00818                 
00819                 if (gCluster == 0xffffffff) { // finished song. on to next ?
00820                         
00821                         // Stop all playing and reset everything
00822                         gFile_good = FALSE;
00823                         gMode = MODE_STOP;
00824                         MMC_Reset();
00825                         flush_decoder(SOFT_RESET);
00826 
00827 #if SAMPLEMODE_UNINTERUPTIBLE && SAMPLEMODE_CONTROLOUT_EN
00828             SAMPLEMODE_CONTROLOUT_PORT &= ~(1<<SAMPLEMODE_CONTROLOUT_PIN ) ;        // clear  sample interupted output 
00829 #endif
00830 
00831                         if (PLAY_NEXT_SONG){ // cue up next song and play it.
00832                                 nextfile = FAT_getNextSong(gFAT_entry,FAT16_dir_first_sector);
00833                                 if (RECURSE_DIRECTORIES == 0){ // then skip directories 
00834                                         while (FAT16_filetype & FILE_TYPE_DIR) {
00835                                                 nextfile = FAT_getNextSong(nextfile,FAT16_dir_first_sector);
00836                                         }
00837                                 }
00838                                 if(nextfile){// play next song
00839                                         gFAT_entry = nextfile;
00840                                         gLCD_Refresh=TRUE;
00841                                         cue_file();
00842                                         gMode = MODE_PLAY;
00843                                 }else if(PLAY_REPEAT_ALL){
00844                                         gFAT_entry = FAT16_entryMIN;
00845                                         gLCD_Refresh=TRUE;
00846                                         cue_file();
00847                                         gMode = MODE_PLAY;
00848                                 }
00849                         }
00850                         return;
00851                 }
00852                 
00853                 // read sector from MMC up to 255 times
00854                 while (FAT_readCluster(gCluster,cluster_pos)&& (--abort)){
00855                         MMC_Reset(); // reset if read failed.
00856                 }
00857                 
00858                 buff_pos=0;
00859                 cluster_pos++; // increment for next time
00860         }
00861         
00862         // need to send data to mp3?
00863         // send at most the rest of sector in memory.
00864         while (bit_is_set(DREQ_PORT,DREQ_PIN) && (buff_pos<16)){
00865                 vs1001_send_32(FAT_buffer+(32*buff_pos++));
00866         }
00867         
00868         return;
00869 }
00870     
00871 
00881 uint8 handle_mmc(uint8 MMC_present)
00882 {
00883         uint16  c;
00884 //      uint32  mmc_size=0;
00885 //      uint32  nextfile;
00886         
00887         #ifdef SW_MMC_IDENTIFY
00888         if (MMC_present == FALSE) {
00889                 MMC_Reset();
00890         }
00891         c = (((MMC_Check() & 0xFF00) == 0) ? TRUE : FALSE);
00892         #else
00893         c =  MMC_Detect();                      // detect mmc
00894         #endif
00895         
00896         if (c && ( MMC_present == FALSE) ){ // mmc just inserted
00897                 gPowerSaveTimer=0; // don't time out I just put a card in.
00898                 
00899                 // startup mmc, FAT and find first File
00900                 if (!init_mmc_fat()){ // mmc and Fat init okay..
00901                         MMC_present = TRUE;
00902                         //mmc_size = MMC_Capacity(); // get capacity in Bytes
00903                         //PRINT("MMC :");UART_Printfu32(mmc_size); 
00904                         //update_LCD();
00905                         gLCD_Refresh=TRUE;
00906                         
00907                         if((FAT16_entryMIN==0) && (FAT16_entryMAX==-1)){// NO SONGS!
00908                                 gMode= MODE_IDLE;
00909                                 PRINT("NO MP3");EOL();
00910                                 //FAT_tester();
00911                         }else{
00912                                 gFAT_entry = FAT16_entryMIN;
00913                                 gMode= MODE_STOP;
00914                         }
00915 
00916                 }
00917                 
00918                 
00919         }else if ((c == FALSE) && MMC_present ){        //mmc just removed
00920                 //      PRINT("No MMC\t");UART_Printfu16(c);EOL();
00921                 //      gFAT_entry=0; // reset FAT to beginning
00922                 gMode = MODE_IDLE;
00923                 gLCD_Refresh=TRUE;
00924                 gFile_good= FALSE;
00925                 MMC_present = FALSE;
00926                 //update_LCD();
00927                 gPowerSaveTimer=0; //don't time out we're changing cards
00928         }
00929 
00930         return MMC_present;
00931 }
00932 
00933 
00940 void play_track_number( uint8 num )
00941 {
00942 #if FAT_NumberedSong_EN
00943     uint32 nextfile;
00944    
00945     #if SAMPLEMODE_UNINTERUPTIBLE
00946         if (gMode != MODE_PLAY){
00947         #if SAMPLEMODE_CONTROLOUT_EN
00948             SAMPLEMODE_CONTROLOUT_PORT &= ~(1<<SAMPLEMODE_CONTROLOUT_PIN ) ;        // clear  sample interupted output 
00949         #endif
00950     #endif
00951 
00952     nextfile = FAT_getNumberedSong(CHAR2BCD2( num),FAT16_dir_first_sector);
00953     if(nextfile){// get next song
00954         gCurrentSongNum = num;
00955         gFAT_entry = nextfile;
00956         gLCD_Refresh=TRUE;      
00957         cue_file();
00958         gMode = MODE_PLAY;
00959     }
00960 
00961     #if SAMPLEMODE_UNINTERUPTIBLE
00962         }else{ // signal sample currently playing
00963         #if SAMPLEMODE_CONTROLOUT_EN
00964             SAMPLEMODE_CONTROLOUT_PORT |= (1<<SAMPLEMODE_CONTROLOUT_PIN)  ;         //set sample interupted output  
00965         #endif
00966         }
00967     #endif
00968     
00969 #endif
00970 }
00971    
00972 
00973 void volume_up(void)
00974 {
00975     gmusic_vol++;
00976     if (gmusic_vol>9)
00977         gmusic_vol=9;
00978     vs_1001_setvolume(pgm_read_byte(volume_val+gmusic_vol), pgm_read_byte(volume_val+gmusic_vol));
00979     gLCD_Refresh=TRUE;
00980 }
00981 
00982 void volume_down(void)
00983 {
00984     gmusic_vol--;
00985     if (gmusic_vol>9) // overflow to 255
00986         gmusic_vol=0;
00987     vs_1001_setvolume(pgm_read_byte(volume_val+gmusic_vol), pgm_read_byte(volume_val+gmusic_vol));
00988     gLCD_Refresh=TRUE;
00989 }
00990 
00991 
00997 void    handle_interface(void)
00998 {
00999         char c;
01000         uint32 nextfile;
01001         //uint16 buf[2];
01002         
01003 
01004         c = getkey(); // get key press
01005         
01006         if (c == KEY_NULL && UART_HasChar() ){ // check for serial
01007                 c = UART_ReceiveByte();
01008                 switch(c){
01009                         case 'j': c = KEY_PREV;         break;
01010                         case 'k': c = KEY_MINUS;        break;
01011                         case 'l': c = KEY_NEXT;         break;
01012                         case 'i': c = KEY_PLUS;         break;
01013                         case ' ': c = KEY_ENTER;        break;
01014 #ifdef SERIAL_EXTENDED                
01015             case '0': case '1': case '2': case '3': case '4': 
01016             case '5': case '6': case '7': case '8': case '9': 
01017                     play_track_number(c-'0'); 
01018                     c = KEY_NULL;               
01019                     break;
01020             case '+':volume_up(); c = KEY_NULL; break;
01021             case '-':volume_down(); c = KEY_NULL; break;
01022             case 't':vs1001_sine_test(); c= KEY_NULL;break;
01023 #endif
01024             default : c = KEY_NULL;             break;
01025                 }       
01026                 
01027         }
01028 
01029         if (c != KEY_NULL){ // check for button press
01030                 gPowerSaveTimer = 0;                // Reset the Auto Power Down timer
01031                 
01032                 PRINT("KEY: ")  ;UART_Printfu08(c);EOL();
01033                 if ((c>KEY_JOYSTICKMAX) || SAMPLEMODE_ALLBUTONS){ // just play track #c
01034             play_track_number(c); 
01035         }else{
01036             switch (c){
01037                 case KEY_ENTER : 
01038                     // change mode.
01039                     if (gMode == MODE_PLAY){// currently playing
01040                         gMode = MODE_PAUSE; // stop
01041                     }else if (gMode == MODE_PAUSE){
01042                         UART_Printfu08(FAT16_filetype);
01043                         UART_Printfu08(FILE_TYPE_DIR);EOL();
01044                         if (FAT16_filetype & FILE_TYPE_DIR){
01045                             //PRINT("DIR");EOL();
01046                             
01047                             // scan a new directory....
01048                             FAT_readFile(gFAT_entry,FAT16_dir_first_sector);
01049                              
01050                             // get cluster address from fat entry
01051                             FAT_Scratch2Cluster();
01052                             
01053                             // check for files and exit on no files(always 2 entries . and ..)
01054                             open_Dir(FAT_cluster2lba(gCluster));
01055                             
01056                             //  return;
01057                             gFAT_entry = FAT16_entryMIN;
01058                             
01059                         }else{
01060                             gMode = MODE_PLAY;
01061                         }
01062                         
01063                     }else if (gMode == MODE_STOP){
01064                         if (FAT16_filetype & FILE_TYPE_DIR){
01065                             // PRINT("DIR");EOL();
01066                             // scan a new directory....
01067                             FAT_readFile(gFAT_entry,FAT16_dir_first_sector);
01068                             
01069                             // get cluster address from fat entry
01070                             FAT_Scratch2Cluster();
01071                             
01072                             // check for files and exit on no files(always 2 entries . and ..)
01073                             open_Dir(FAT_cluster2lba(gCluster));
01074                             
01075                             //  return;
01076                             gFAT_entry = FAT16_entryMIN;
01077                             
01078                         }else{
01079                             gMode = MODE_PLAY;
01080                             cue_file();
01081                         }
01082                         
01083                     }else if ((gMode == MODE_IDLE) && gFile_good){
01084                         gMode = MODE_STOP;
01085                     }
01086                     
01087                     // decoder will have shut down if stream has stoped.
01088                     // so we need to  restart
01089                     flush_decoder(SOFT_RESET); 
01090                     gLCD_Refresh=TRUE;
01091                     
01092                     // TODO: add long short presses.
01093                     
01094                     break;
01095                     
01096                 case KEY_NEXT : // find next file
01097                     if (SCAN_JUMPTOSTART && (gFAT_entry==FAT16_entryMAX)){
01098                         gFAT_entry=FAT16_entryMIN;
01099                         gLCD_Refresh = TRUE;
01100                         cue_file();
01101                     }else{
01102                         nextfile = FAT_getNextSong(gFAT_entry,FAT16_dir_first_sector);
01103                         if(nextfile){// get next song
01104                             gFAT_entry = nextfile;
01105                             gLCD_Refresh=TRUE;  
01106                             cue_file();
01107                         }
01108                     }
01109                     break;
01110                     
01111                 case KEY_PREV ://find previous file 
01112     #if EXPERIMENTAL_FF==1
01113                     gFastForward = !gFastForward;
01114                     flush_decoder(SOFT_RESET);  
01115     #else
01116                     if (SCAN_JUMPTOSTART && (gFAT_entry==FAT16_entryMIN)){
01117                         gFAT_entry=FAT16_entryMAX;
01118                         gLCD_Refresh = TRUE;
01119                         cue_file();
01120                     }else{
01121                         nextfile = FAT_getPrevSong(gFAT_entry,FAT16_dir_first_sector);
01122                         if(nextfile){// play next song
01123                             gFAT_entry = nextfile;
01124                             gLCD_Refresh = TRUE;
01125                             cue_file();
01126                         }
01127                     }
01128     #endif      
01129                     break;
01130                     
01131                 case KEY_PLUS:
01132                     //if (gMode == MODE_PAUSE && !(FAT16_filetype & FILE_TYPE_DIR)){    // toggle Bass boost
01133                     //  gbass_boost = !gbass_boost;
01134                     //  gLCD_Refresh=TRUE;
01135                     //}else 
01136             
01137                         // no mmc? then go to options
01138                     if(gMode == MODE_PLAY){                                     // increase the volume
01139                         volume_up();
01140                     
01141                     }else {//if(((gMode == MODE_PAUSE) || (gMode == MODE_IDLE)) ){
01142                         //  && (FAT16_filetype & FILE_TYPE_DIR) ){
01143                         // go up a directory?
01144                         
01145                         // NOTE: gCluster is an lba here not a cluster address 
01146                         if ((FAT_getParentDir(FAT16_dir_first_sector)) != 0x00){        
01147                             gCluster =FAT_getParentDir(FAT16_dir_first_sector);
01148                             open_Dir(gCluster);
01149                             //PRINT("fdg");EOL();
01150                             gFAT_entry = FAT16_entryMIN;
01151                             cue_file();
01152                         }
01153                     }
01154                     break;
01155                     
01156                 case KEY_MINUS:
01157                     if ((gMode == MODE_PAUSE) || (gMode == MODE_IDLE)|| 
01158                         (gMode == MODE_STOP)){  // Power OFF
01159                         Power_off();
01160                     }else {
01161                         volume_down();
01162                     }
01163                     break;
01164                     
01165                 default :       break;
01166             }
01167         }
01168         }
01169 }
01170    
01171 
01172 
01180 void    update_LCD(void)
01181 {
01182         uint16  voltage;
01183         uint8   percentage;
01184         static uint8 vol = -1,mode = -1,second = -1;
01185         static uint16 file = -1;
01186         
01187 #ifdef ALPHA
01188         if (gLCD_Refresh){
01189     //  LCD_Blank();                                                            // clear LCD
01190 
01191                 if (gMode == MODE_PLAY){
01192                         if (file!=(uint16) gFAT_entry) LCD_FileName(FALSE);
01193                         if (mode!=gMode) LCD_Play();
01194                         if (vol !=gmusic_vol) LCD_Vol(gmusic_vol, gbass_boost);
01195                         if (second !=(uint8) gPlayTimeSeconds) LCD_Time(gPlayTimeSeconds);
01196 
01197                 }else if (gMode == MODE_PAUSE){
01198                         if (file!= (uint16) gFAT_entry) LCD_FileName(FALSE);
01199                         if (mode!=gMode) LCD_Pause();
01200                         if (vol !=gmusic_vol) LCD_Vol(gmusic_vol, gbass_boost);
01201 
01202                 }else if (gMode == MODE_STOP){
01203                         if (file!= (uint16) gFAT_entry) LCD_FileName(FALSE);
01204                         if (mode!=gMode) LCD_Stop();
01205                         if (vol !=gmusic_vol) LCD_Vol(gmusic_vol, gbass_boost);
01206          
01207                 }else if (gMode == MODE_IDLE){
01208                    if (mode!=gMode) {
01209                         LCD_Blank();                                            // clear LCD
01210                         LCD_Tester();                                           // Print the welcome screen and info.
01211                         
01212                         //display battery status
01213                         voltage = Power_check();
01214                         
01215                         percentage = Power_pcnt(voltage);
01216                         //UART_Printfu08(percentage);EOL();
01217                         LCD_Battery(percentage);
01218                         
01219                         // revert to filname after seconds 
01220                         gDisplayTimeOut=(2*STAT_DISPLAY_TIME)+1;
01221                         }
01222                 }
01223                 
01224                 mode=gMode;
01225                 vol=gmusic_vol;
01226                 file= (uint16) gFAT_entry;
01227                 second =(uint8) gPlayTimeSeconds;
01228 
01229                 
01230                 gLCD_Refresh =FALSE;
01231         }
01232 
01233 #endif // ALPHA
01234 
01235 #ifdef NOKIA
01236 
01237         if (gLCD_Refresh){
01238 
01239            if ((mode!=gMode) || (file!=(uint16) gFAT_entry)) LCD_Blank(); // clear LCD
01240 
01241                 // Always display battery status
01242                 voltage = Power_check();
01243                 percentage = Power_pcnt(voltage);
01244                 LCD_Battery(percentage);
01245 
01246 
01247                 if (gMode == MODE_PLAY){
01248                         LCD_FileName((file!=(uint16) gFAT_entry));
01249                         LCD_Play();
01250                         LCD_Vol(gmusic_vol, gbass_boost);
01251                         LCD_Time(gPlayTimeSeconds);
01252 
01253                 }else if (gMode == MODE_PAUSE){
01254                         LCD_FileName((file!=(uint16) gFAT_entry));
01255                         LCD_Pause();
01256                         LCD_Vol(gmusic_vol, gbass_boost);
01257                         LCD_Time(gPlayTimeSeconds);
01258 
01259                 }else if (gMode == MODE_STOP){
01260                         LCD_FileName((file!=(uint16) gFAT_entry));
01261                         LCD_Stop();
01262                         LCD_Vol(gmusic_vol, gbass_boost);
01263          
01264                 }else if (gMode == MODE_IDLE){
01265                         // Print the welcome screen and info.
01266                         LCD_Tester();           
01267                         
01268                         // revert to filname after seconds 
01269                         gDisplayTimeOut=(2*STAT_DISPLAY_TIME)+1;
01270                         
01271                 }
01272 
01273       
01274                 mode=gMode;
01275                 vol=gmusic_vol;
01276                 file= (uint16) gFAT_entry;
01277                 second =(uint8) gPlayTimeSeconds;
01278 
01279                 
01280                 gLCD_Refresh =FALSE;
01281         }
01282 #endif // NOKIA
01283 
01284 }
01285 
01286 
01294 int     main(void) 
01295 {
01296         uint8   MMC_present,j;
01297         
01298         //********************************
01299         //*             Initialize 
01300         //********************************
01301         init_HW();              // Do hardware Initialization.
01302         gMode=MODE_IDLE;
01303         gLCD_Refresh=TRUE;
01304         update_LCD();           // make sure NOKIA screen displayed b4 scanning MMC
01305         gLCD_Refresh=TRUE;
01306         MMC_present = restore_player(); // Restore saved position.
01307         gPowerSaveTimer =0;
01308         
01309         //********************************
01310         //*             Main Loop 
01311         //********************************
01312         while (1)
01313         {       
01314                 // check for button press
01315                 handle_interface();
01316                 
01317                 // update lcd
01318                 update_LCD();
01319 
01320                 // check for MMC removal or insertion.
01321                 MMC_present = handle_mmc(MMC_present);
01322                 
01323                 if (MMC_present){
01324 
01325                         // check mode ie playing idle sleep nommc
01326                         if(gMode == MODE_PLAY){ 
01327                                 // keep streaming if mp3 decoder can take it 
01328                                 // (up to 40 sectors at a time).
01329                                 j=40;
01330                                 while (bit_is_set(DREQ_PORT,DREQ_PIN) && j--)
01331                                         streaming();
01332                         }
01333                         else{
01334                                 Power_idle();
01335                 #if (AUTOPOWEROFF_TIMEOUT>0)
01336                                 if (gPowerSaveTimer >= AUTOPOWEROFF_TIMEOUT)
01337                                         Power_off();
01338                 #endif
01339                         }
01340                 }
01341                 else{
01342                         Power_idle();
01343             #if (AUTOPOWEROFF_TIMEOUT>0)
01344                         if (gPowerSaveTimer >= AUTOPOWEROFF_TIMEOUT)
01345                                 Power_off();
01346             #endif
01347                 }
01348 
01349         }
01350         return 0;
01351 }
01352 
01353 
 All Files Functions Variables Typedefs Enumerations Enumerator Defines