Read an wav file from sdcard and play it through I2S on LPC4088 QSB platform
Dependencies: EALib I2SSlave TLV320 mbed
Fork of playback by
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 }
Generated on Fri Jul 29 2022 00:44:58 by 1.7.2