Read an wav file from sdcard and play it through I2S on LPC4088 QSB platform

Dependencies:   EALib I2SSlave TLV320 mbed

Fork of playback by Daniel Worrall

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "TLV320.h"
00003 
00004 Serial pc(USBTX, USBRX);
00005  
00006 /******************************************************************************
00007  * Includes
00008  *****************************************************************************/
00009 #include "MCIFileSystem.h"
00010 
00011 /******************************************************************************
00012  * Typedefs and defines
00013  *****************************************************************************/
00014 
00015 typedef bool (*syncFunc)(const char* name, bool isDir);
00016 
00017 /******************************************************************************
00018  * Local variables
00019  *****************************************************************************/
00020 
00021 MCIFileSystem mcifs("mci");
00022 
00023 DigitalOut myled1(LED1);
00024 DigitalOut myled2(LED2);
00025 
00026 /******************************************************************************
00027  * Local functions
00028  *****************************************************************************/
00029 
00030 static void ledShowProgress()
00031 {
00032   static int state = 0;
00033   state = (state + 1) % 2;
00034   switch (state)
00035   {
00036     case 0:
00037       myled1 = 1;
00038       myled2 = 0;
00039       break;
00040 
00041     case 1:
00042     default:
00043       myled1 = 0;
00044       myled2 = 1;
00045   }
00046 }
00047 
00048 static void handleError(const char* msg)
00049 {
00050   printf(msg);
00051   while(true) {
00052     myled1 = 1;
00053     myled2 = 1;
00054     wait(0.3);
00055     myled1 = 0;
00056     myled2 = 0;
00057     wait(0.3);
00058   }
00059 }
00060 
00061 static bool recursiveProcessFS(char* buff, const char* name, syncFunc func, bool adding)
00062 {
00063   uint32_t len = strlen(buff);
00064   if (len > 0) {
00065     if (buff[len - 1] != '/') {
00066       buff[len++] = '/';
00067       buff[len] = '\0';
00068     }
00069   }
00070   strcat(buff, name);
00071   len += strlen(name);
00072   
00073   if (len > 60) {
00074     // ugly fix to avoid crashes that occurs when file name is larger than buffer 
00075     // in FATFileSystem.
00076     printf("skipped:   %s\n", buff);
00077     return true;
00078   }
00079 
00080   DIR *d = opendir(buff);
00081   bool result = true; // success
00082   if (d != NULL) {
00083     if (adding) {
00084       // when processing in adding mode folders must be created before it's content
00085       result = func(buff, true);
00086     }
00087     struct dirent *p;
00088     while (result && ((p = readdir(d)) != NULL)) {
00089       result = recursiveProcessFS(buff, p->d_name, func, adding);
00090       buff[len] = '\0';
00091     }
00092     closedir(d);
00093     if (result && !adding) {
00094       // when processing in removing mode folders must be deleted after it's content
00095       result = func(buff, true);
00096     }
00097   } else {
00098     // a file
00099     result = func(buff, false);
00100   }
00101   return result;
00102 }
00103 
00104 static uint32_t fileLen(FILE* f)
00105 {
00106   uint32_t pos = ftell(f);
00107   fseek(f, 0, SEEK_END);
00108   uint32_t size = ftell(f);
00109   fseek(f, pos, SEEK_SET);
00110   return size;
00111 }
00112 
00113 static bool copyFH(FILE* fSrc, FILE* fDst)
00114 {
00115   char buff[512];
00116   uint32_t left = fileLen(fSrc);
00117   uint32_t num;
00118   uint32_t chunk;
00119 
00120   fseek(fSrc, 0, SEEK_SET);
00121   do {
00122     chunk = (left < 512) ? left : 512;
00123     num = fread(buff, 1, chunk, fSrc);
00124     if (num > 0) {
00125       uint32_t tmp = fwrite(buff, 1, num, fDst);
00126       if (tmp != num) {
00127         // failed to write
00128         return false;
00129       }
00130       left -= num;
00131       ledShowProgress();
00132     }
00133   } while(num > 0 && left > 0);
00134 
00135   // copied entire file
00136   return true;
00137 }
00138 
00139 static bool copy(const char* fnameSrc, const char* fnameDest)
00140 {
00141   FILE* fhSrc = NULL;
00142   FILE* fhDest = NULL;
00143   bool success = false;
00144   
00145   do {
00146     fhSrc = fopen(fnameSrc, "r");
00147     if (fhSrc == NULL) {
00148       break;
00149     }
00150     
00151     fhDest = fopen(fnameDest, "w");
00152     if (fhDest == NULL) {
00153       break;
00154     }
00155     
00156     if (!copyFH(fhSrc, fhDest)) {
00157       break;
00158     }
00159     
00160     success = true;
00161   } while (false);
00162   
00163   if (fhSrc != NULL) {
00164     fclose(fhSrc);
00165   }
00166   if (fhDest != NULL) {
00167     fclose(fhDest);
00168   }
00169   
00170   return success;
00171 }
00172 
00173 static bool list(const char* name, bool isDir)
00174 {
00175   if (isDir) {
00176     printf("d:         %s\n", name);
00177   } else {
00178     FILE* f = fopen(name, "r");
00179     if (f != NULL) {
00180       uint32_t len = fileLen(f);
00181       printf("f: %7u %s\n", len, name);
00182       fclose(f);
00183     } else {
00184       printf("f:     ??? %s\n", name);
00185     }
00186   }
00187   return true;
00188 }
00189 
00190 static void recursiveList(const char* dirname)
00191 {
00192   printf("\nRecursive list of file and folders in %s\n", dirname);
00193   char* buff = (char*)malloc(512);
00194   if (buff != NULL)
00195   {
00196     buff[0] = '\0';
00197     recursiveProcessFS(buff, dirname, list, true);
00198     free(buff);
00199   }
00200 }
00201 
00202 static void testAppend(const char* filename)
00203 {
00204     FILE *fp = fopen(filename, "a");
00205     if (fp != NULL) {
00206         fprintf(fp, "Hello World!");
00207         fclose(fp);
00208     }
00209 }
00210 
00211 /******************************************************************************
00212  * TestSdCard function
00213  *****************************************************************************/
00214 
00215 int TestSdCard()
00216 {
00217   printf("\n-----------------\n\nWelcome to the MCI file system example...\n");
00218   
00219   if (!mcifs.cardInserted()) {
00220     printf("Please insert a SD/MMC card...\n");
00221     while (!mcifs.cardInserted()) {
00222       wait(0.5);
00223     }
00224     printf("Card detected!\n");
00225   }
00226 
00227   recursiveList("/mci/");
00228 
00229   copy("/mci/expanding.txt", "/mci/expanding.old");
00230   testAppend("/mci/expanding.txt");
00231 
00232   //recursiveList("/mci/");
00233   
00234   
00235       
00236       printf("Found SD/MMC card, writing to /mci/myfile.txt ...\n");
00237       
00238       Timer t;
00239       
00240       t.start();
00241       
00242       FILE *fp = fopen("/mci/myfile.txt", "w");
00243       if (fp != NULL) 
00244       {
00245           for (long i=0; i<100000L; i++)
00246           fprintf(fp, "Hello World!\n");
00247           fclose(fp);
00248           printf("Wrote to /mci/myfile.txt\n");
00249       } else {
00250           printf("Failed to open /mci/myfile.txt\n");
00251       }
00252     t.stop();
00253     
00254      printf("The time taken was %f seconds\n", t.read());
00255     
00256   
00257   handleError("Program completed!\n");  
00258   return 1;
00259 }
00260 
00261  
00262  
00263 TLV320 audio(p9, p10, 52, p11, p12, p13, p14, p16); //TLV320 object
00264 
00265 InterruptIn volumeSet(p17);                     
00266 AnalogIn aIn(p19); 
00267 FILE *infp;                                     //File pointer object
00268 /* Buffers */
00269 int circularBuffer[4096];    
00270 volatile int readPointer = 0;
00271 volatile int theta = 0;
00272 /* Wav file header data, for setting up the transfer protocol */
00273 short channels;
00274 long sampleRate;
00275 short wordWidth;
00276 /* Function to set volume*/
00277 void setVolume(void){
00278     audio.outputVolume(aIn, aIn);                
00279 }
00280 /* Function to read from circular buffer and send data to TLV320 */
00281 void play(void){ 
00282         audio.write(circularBuffer, readPointer, 8);      
00283         //Pointer fun :-)
00284         readPointer += 8;
00285         readPointer &= 0xfff;
00286         theta -= 8;
00287 }
00288 /* Function to load circular buffer from SD Card */
00289 void fillBuffer(void){
00290     while(!feof(infp)){                                         //fill the circular buffer until the end of the file
00291         static volatile int writePointer = 0;
00292         if(theta < 4096){
00293             fread(&circularBuffer[writePointer], 4, 4, infp);   //read 4 integers into the circular buffer at a time
00294             //More pointer fun :D
00295             theta+=4;
00296             writePointer+=4;
00297             writePointer &= 0xfff;
00298         }
00299     }
00300 }
00301 /* main */
00302 int main()
00303 {
00304     pc.baud(460800);
00305        
00306     infp = fopen("/mci/agnes.wav","rb");
00307         if(infp == NULL){                   //make sure it's been opened
00308         perror("Error opening file!");
00309         exit(1);
00310     }
00311     /* Parse wav file header */
00312     fseek(infp, 22, SEEK_SET);                      
00313     fread(&channels, 2, 1, infp);
00314     fseek(infp, 24, SEEK_SET);
00315     fread(&sampleRate, 4, 1, infp);
00316     fseek(infp, 34, SEEK_SET);
00317     fread(&wordWidth, 2, 1, infp);
00318     
00319     volumeSet.rise(&setVolume);             //attach set volume function to digital input
00320     audio.power(0x07);                      //power up TLV apart from analogue input
00321     audio.frequency(sampleRate);            //set sample frequency
00322     audio.format(wordWidth, (2-channels));  //set transfer protocol
00323     audio.attach(&play);                    //attach interrupt handler to send data to TLV320
00324     for(int j = 0; j < 4096; ++j){          //upon interrupt generation
00325         circularBuffer[j] = 0;              //clear circular buffer
00326     }
00327     audio.start(TRANSMIT);                  //interrupt come from the I2STXFIFO only
00328     fillBuffer();                           //continually fill circular buffer
00329 }