Demo of Embedded Artists LPCXpresso baseboard SD card reader and audio facilities. Updated to put wav file player in a separate library and use the high capacity SD card library provided by Klaus Bu.

Dependencies:   mbed

Committer:
tom_coxon
Date:
Fri Jul 09 14:25:50 2010 +0000
Revision:
1:22c43c468a2f
Parent:
0:1f4b7aa80ab3
Child:
2:affcc36a50b4

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tom_coxon 0:1f4b7aa80ab3 1 /*
tom_coxon 1:22c43c468a2f 2 Demo of Embedded Artists LPCXpresso baseboard SD card reader and audio facilities.
tom_coxon 0:1f4b7aa80ab3 3
tom_coxon 1:22c43c468a2f 4 Based on WAVEplayer by Vlad Cazan/Stephan Rochon modified by Tom Coxon to run correctly on
tom_coxon 1:22c43c468a2f 5 the Embedded Artists LPCXpresso baseboard.
tom_coxon 0:1f4b7aa80ab3 6
tom_coxon 1:22c43c468a2f 7 Also modified to play 8 bit sample size in addition to original 16 bit and to be more fault tolerant
tom_coxon 1:22c43c468a2f 8 when playing wav files.
tom_coxon 0:1f4b7aa80ab3 9
tom_coxon 1:22c43c468a2f 10 Place suitable uncompressed wav files with 8 or 16 bit sample sizes on the SD card and ensure the
tom_coxon 1:22c43c468a2f 11 file names are 8.3 format. Then change the main method below to the relevant file paths.
tom_coxon 0:1f4b7aa80ab3 12
tom_coxon 1:22c43c468a2f 13 Please set all jumpers on board to the default case except for the following:
tom_coxon 0:1f4b7aa80ab3 14
tom_coxon 0:1f4b7aa80ab3 15 Audio setup:
tom_coxon 0:1f4b7aa80ab3 16
tom_coxon 0:1f4b7aa80ab3 17 1. Insert a jumper in J31 to connect signal PIO1_2 to the low
tom_coxon 0:1f4b7aa80ab3 18 pass filer as described in section 4.7.2. of base board users
tom_coxon 0:1f4b7aa80ab3 19 guide.
tom_coxon 0:1f4b7aa80ab3 20
tom_coxon 0:1f4b7aa80ab3 21 2. Insert three jumpers in J33 to connect PIO3_0, PIO3_1 and
tom_coxon 0:1f4b7aa80ab3 22 PIO3_2 to control the amplifier as described in section 4.8
tom_coxon 0:1f4b7aa80ab3 23 of base board users guide.
tom_coxon 0:1f4b7aa80ab3 24
tom_coxon 0:1f4b7aa80ab3 25 3. Insert a jumper in J32 and remove any from J34 to use the
tom_coxon 0:1f4b7aa80ab3 26 internal speaker as described in section 4.8
tom_coxon 0:1f4b7aa80ab3 27 of base board users guide.
tom_coxon 0:1f4b7aa80ab3 28
tom_coxon 0:1f4b7aa80ab3 29 SD Card setup:
tom_coxon 0:1f4b7aa80ab3 30
tom_coxon 0:1f4b7aa80ab3 31 4. Insert all five jumpers in J39 as described in section 4.3.3
tom_coxon 0:1f4b7aa80ab3 32 of base board users guide.
tom_coxon 0:1f4b7aa80ab3 33
tom_coxon 0:1f4b7aa80ab3 34 5. Remove jumper marked "A" in J55 In order to connect PIO1_11
tom_coxon 0:1f4b7aa80ab3 35 to CS signal of J40 (the SPI-SSEL signal) as described in section 4.3.3
tom_coxon 0:1f4b7aa80ab3 36 of base board users guide.
tom_coxon 0:1f4b7aa80ab3 37 */
tom_coxon 0:1f4b7aa80ab3 38
tom_coxon 0:1f4b7aa80ab3 39 #include "mbed.h"
tom_coxon 0:1f4b7aa80ab3 40 #include "SDFileSystem.h"
tom_coxon 0:1f4b7aa80ab3 41
tom_coxon 0:1f4b7aa80ab3 42 AnalogOut DACout(p18);
tom_coxon 0:1f4b7aa80ab3 43 DigitalOut led1(LED1);
tom_coxon 0:1f4b7aa80ab3 44 DigitalOut led2(LED2);
tom_coxon 0:1f4b7aa80ab3 45 DigitalOut led3(LED3);
tom_coxon 0:1f4b7aa80ab3 46 DigitalOut led4(LED4);
tom_coxon 0:1f4b7aa80ab3 47 Ticker tick;
tom_coxon 0:1f4b7aa80ab3 48 SDFileSystem sd(p5, p6, p7, p24, "sd");
tom_coxon 0:1f4b7aa80ab3 49
tom_coxon 0:1f4b7aa80ab3 50 #define SAMPLE_FREQ 40000
tom_coxon 0:1f4b7aa80ab3 51 #define BUF_SIZE (SAMPLE_FREQ/10)
tom_coxon 0:1f4b7aa80ab3 52 #define SLICE_BUF_SIZE 1
tom_coxon 0:1f4b7aa80ab3 53
tom_coxon 0:1f4b7aa80ab3 54 void dac_out(void);
tom_coxon 0:1f4b7aa80ab3 55 void play_wave(char *);
tom_coxon 0:1f4b7aa80ab3 56 void cleanup(char *);
tom_coxon 0:1f4b7aa80ab3 57 void fill_adc_buf(short *, unsigned);
tom_coxon 0:1f4b7aa80ab3 58 void swapword(unsigned *);
tom_coxon 0:1f4b7aa80ab3 59
tom_coxon 0:1f4b7aa80ab3 60 // a FIFO for the DAC
tom_coxon 0:1f4b7aa80ab3 61 short DAC_fifo[256];
tom_coxon 0:1f4b7aa80ab3 62 short DAC_wptr;
tom_coxon 0:1f4b7aa80ab3 63 short DAC_rptr;
tom_coxon 0:1f4b7aa80ab3 64 short DAC_on;
tom_coxon 0:1f4b7aa80ab3 65
tom_coxon 0:1f4b7aa80ab3 66 typedef struct uFMT_STRUCT {
tom_coxon 0:1f4b7aa80ab3 67 short comp_code;
tom_coxon 0:1f4b7aa80ab3 68 short num_channels;
tom_coxon 0:1f4b7aa80ab3 69 unsigned sample_rate;
tom_coxon 0:1f4b7aa80ab3 70 unsigned avg_Bps;
tom_coxon 0:1f4b7aa80ab3 71 short block_align;
tom_coxon 0:1f4b7aa80ab3 72 short sig_bps;
tom_coxon 0:1f4b7aa80ab3 73 } FMT_STRUCT;
tom_coxon 0:1f4b7aa80ab3 74
tom_coxon 0:1f4b7aa80ab3 75
tom_coxon 0:1f4b7aa80ab3 76 int main() {
tom_coxon 0:1f4b7aa80ab3 77 led1=0;
tom_coxon 0:1f4b7aa80ab3 78 wait(.5);
tom_coxon 0:1f4b7aa80ab3 79 led1=1;
tom_coxon 0:1f4b7aa80ab3 80 wait(.5);
tom_coxon 0:1f4b7aa80ab3 81 led1=0;
tom_coxon 0:1f4b7aa80ab3 82 printf("\r\n--------------- Starting -----------------\r\n");
tom_coxon 0:1f4b7aa80ab3 83
tom_coxon 0:1f4b7aa80ab3 84 play_wave("/sd/startup.wav"); // 8 bit sample size
tom_coxon 0:1f4b7aa80ab3 85
tom_coxon 0:1f4b7aa80ab3 86 play_wave("/sd/baddonut.wav"); // 16 bit sample size
tom_coxon 0:1f4b7aa80ab3 87
tom_coxon 0:1f4b7aa80ab3 88 play_wave("/sd/dduck.wav"); // 8 bit sample size
tom_coxon 0:1f4b7aa80ab3 89
tom_coxon 0:1f4b7aa80ab3 90 play_wave("/sd/bbunny.wav"); // 8 bit sample size
tom_coxon 0:1f4b7aa80ab3 91
tom_coxon 0:1f4b7aa80ab3 92 play_wave("/sd/clint16.wav"); // 16 bit sample size
tom_coxon 0:1f4b7aa80ab3 93
tom_coxon 0:1f4b7aa80ab3 94 printf("<<<<<<<<<<<<<<<< All done >>>>>>>>>>>>>>>>\r\n");
tom_coxon 0:1f4b7aa80ab3 95 led1=1;
tom_coxon 0:1f4b7aa80ab3 96 wait(.5);
tom_coxon 0:1f4b7aa80ab3 97 led1=0;
tom_coxon 0:1f4b7aa80ab3 98 wait(.5);
tom_coxon 0:1f4b7aa80ab3 99 led1=1;
tom_coxon 0:1f4b7aa80ab3 100 }
tom_coxon 0:1f4b7aa80ab3 101
tom_coxon 0:1f4b7aa80ab3 102 void play_wave(char *wavname) {
tom_coxon 0:1f4b7aa80ab3 103 unsigned chunk_id,chunk_size,channel;
tom_coxon 0:1f4b7aa80ab3 104 unsigned data,samp_int,i;
tom_coxon 0:1f4b7aa80ab3 105 short dac_data;
tom_coxon 0:1f4b7aa80ab3 106 char *slice_buf;
tom_coxon 0:1f4b7aa80ab3 107 short *data_sptr;
tom_coxon 0:1f4b7aa80ab3 108 FMT_STRUCT wav_format;
tom_coxon 0:1f4b7aa80ab3 109 FILE *wavfile;
tom_coxon 0:1f4b7aa80ab3 110 long slice,num_slices;
tom_coxon 0:1f4b7aa80ab3 111 DAC_wptr=0;
tom_coxon 0:1f4b7aa80ab3 112 DAC_rptr=0;
tom_coxon 1:22c43c468a2f 113
tom_coxon 1:22c43c468a2f 114 size_t result;
tom_coxon 1:22c43c468a2f 115
tom_coxon 0:1f4b7aa80ab3 116 for (i=0;i<256;i+=2) {
tom_coxon 0:1f4b7aa80ab3 117 DAC_fifo[i]=0;
tom_coxon 0:1f4b7aa80ab3 118 DAC_fifo[i+1]=3000;
tom_coxon 0:1f4b7aa80ab3 119 }
tom_coxon 0:1f4b7aa80ab3 120 DAC_wptr=4;
tom_coxon 0:1f4b7aa80ab3 121 DAC_on=0;
tom_coxon 0:1f4b7aa80ab3 122
tom_coxon 0:1f4b7aa80ab3 123 led1=led2=led3=led4=0;
tom_coxon 0:1f4b7aa80ab3 124
tom_coxon 0:1f4b7aa80ab3 125 printf("Playing wave file '%s'\r\n",wavname);
tom_coxon 0:1f4b7aa80ab3 126
tom_coxon 0:1f4b7aa80ab3 127 wavfile=fopen(wavname,"rb");
tom_coxon 0:1f4b7aa80ab3 128 if (!wavfile) {
tom_coxon 0:1f4b7aa80ab3 129 printf("Unable to open wav file '%s'\r\n",wavname);
tom_coxon 0:1f4b7aa80ab3 130 exit(1);
tom_coxon 0:1f4b7aa80ab3 131 }
tom_coxon 0:1f4b7aa80ab3 132
tom_coxon 0:1f4b7aa80ab3 133 fread(&chunk_id,4,1,wavfile);
tom_coxon 0:1f4b7aa80ab3 134 fread(&chunk_size,4,1,wavfile);
tom_coxon 0:1f4b7aa80ab3 135 while (!feof(wavfile)) {
tom_coxon 0:1f4b7aa80ab3 136 printf("Read chunk ID 0x%x, size 0x%x\r\n",chunk_id,chunk_size);
tom_coxon 0:1f4b7aa80ab3 137 switch (chunk_id) {
tom_coxon 0:1f4b7aa80ab3 138 case 0x46464952:
tom_coxon 0:1f4b7aa80ab3 139 fread(&data,4,1,wavfile);
tom_coxon 0:1f4b7aa80ab3 140 printf("RIFF chunk\r\n");
tom_coxon 0:1f4b7aa80ab3 141 printf(" chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
tom_coxon 0:1f4b7aa80ab3 142 printf(" RIFF type 0x%x\r\n",data);
tom_coxon 0:1f4b7aa80ab3 143 break;
tom_coxon 0:1f4b7aa80ab3 144 case 0x20746d66:
tom_coxon 0:1f4b7aa80ab3 145 fread(&wav_format,sizeof(wav_format),1,wavfile);
tom_coxon 0:1f4b7aa80ab3 146 printf("FORMAT chunk\r\n");
tom_coxon 0:1f4b7aa80ab3 147 printf(" chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
tom_coxon 0:1f4b7aa80ab3 148 printf(" compression code %d\r\n",wav_format.comp_code);
tom_coxon 0:1f4b7aa80ab3 149 printf(" %d channels\r\n",wav_format.num_channels);
tom_coxon 0:1f4b7aa80ab3 150 printf(" %d samples/sec\r\n",wav_format.sample_rate);
tom_coxon 0:1f4b7aa80ab3 151 printf(" %d bytes/sec\r\n",wav_format.avg_Bps);
tom_coxon 0:1f4b7aa80ab3 152 printf(" block align %d\r\n",wav_format.block_align);
tom_coxon 0:1f4b7aa80ab3 153 printf(" %d bits per sample\r\n",wav_format.sig_bps);
tom_coxon 0:1f4b7aa80ab3 154 if (chunk_size > sizeof(wav_format))
tom_coxon 0:1f4b7aa80ab3 155 fseek(wavfile,chunk_size-sizeof(wav_format),SEEK_CUR);
tom_coxon 0:1f4b7aa80ab3 156 // create a slice buffer large enough to hold multiple slices
tom_coxon 0:1f4b7aa80ab3 157 slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
tom_coxon 0:1f4b7aa80ab3 158 if (!slice_buf) {
tom_coxon 0:1f4b7aa80ab3 159 printf("Unable to malloc slice buffer");
tom_coxon 0:1f4b7aa80ab3 160 exit(1);
tom_coxon 0:1f4b7aa80ab3 161 }
tom_coxon 0:1f4b7aa80ab3 162 break;
tom_coxon 0:1f4b7aa80ab3 163 case 0x61746164:
tom_coxon 0:1f4b7aa80ab3 164 slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
tom_coxon 0:1f4b7aa80ab3 165 if (!slice_buf) {
tom_coxon 0:1f4b7aa80ab3 166 printf("Unable to malloc slice buffer");
tom_coxon 0:1f4b7aa80ab3 167 exit(1);
tom_coxon 0:1f4b7aa80ab3 168 }
tom_coxon 0:1f4b7aa80ab3 169 num_slices=chunk_size/wav_format.block_align;
tom_coxon 0:1f4b7aa80ab3 170 printf("DATA chunk\r\n");
tom_coxon 0:1f4b7aa80ab3 171 printf(" chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
tom_coxon 0:1f4b7aa80ab3 172 printf(" %d slices\r\n",num_slices);
tom_coxon 0:1f4b7aa80ab3 173 printf(" Ideal sample interval=%d\r\n",(unsigned)(1000000.0/wav_format.sample_rate));
tom_coxon 0:1f4b7aa80ab3 174 samp_int=1000000/(wav_format.sample_rate);
tom_coxon 0:1f4b7aa80ab3 175 printf(" programmed interrupt tick interval=%d\r\n",samp_int);
tom_coxon 0:1f4b7aa80ab3 176
tom_coxon 0:1f4b7aa80ab3 177 // starting up ticker to write samples out -- no printfs until tick.detach is called
tom_coxon 0:1f4b7aa80ab3 178 tick.attach_us(&dac_out, samp_int);
tom_coxon 0:1f4b7aa80ab3 179 DAC_on=1;
tom_coxon 0:1f4b7aa80ab3 180 led2=1;
tom_coxon 0:1f4b7aa80ab3 181 for (slice=0;slice<num_slices;slice+=SLICE_BUF_SIZE) {
tom_coxon 1:22c43c468a2f 182
tom_coxon 1:22c43c468a2f 183 result = fread(slice_buf,wav_format.block_align*SLICE_BUF_SIZE,1,wavfile);
tom_coxon 0:1f4b7aa80ab3 184 if (feof(wavfile)) {
tom_coxon 0:1f4b7aa80ab3 185 printf("Oops -- not enough slices in the wave file\r\n");
tom_coxon 1:22c43c468a2f 186
tom_coxon 1:22c43c468a2f 187 break;
tom_coxon 0:1f4b7aa80ab3 188 }
tom_coxon 1:22c43c468a2f 189
tom_coxon 0:1f4b7aa80ab3 190 data_sptr=(short *)slice_buf;
tom_coxon 0:1f4b7aa80ab3 191 for (i=0;i<SLICE_BUF_SIZE;i++) {
tom_coxon 0:1f4b7aa80ab3 192 dac_data=0;
tom_coxon 0:1f4b7aa80ab3 193
tom_coxon 0:1f4b7aa80ab3 194 // for a stereo wave file average the two channels.
tom_coxon 0:1f4b7aa80ab3 195 for (channel=0;channel<wav_format.num_channels;channel++) {
tom_coxon 0:1f4b7aa80ab3 196 switch (wav_format.sig_bps) {
tom_coxon 0:1f4b7aa80ab3 197 case 16:
tom_coxon 0:1f4b7aa80ab3 198 dac_data+=( ((int)(*data_sptr++)) +32768 );
tom_coxon 0:1f4b7aa80ab3 199 break;
tom_coxon 0:1f4b7aa80ab3 200 case 8:
tom_coxon 0:1f4b7aa80ab3 201 dac_data+=( ((int)(*data_sptr++)) +32768 <<8);
tom_coxon 0:1f4b7aa80ab3 202 break;
tom_coxon 0:1f4b7aa80ab3 203 }
tom_coxon 0:1f4b7aa80ab3 204 }
tom_coxon 0:1f4b7aa80ab3 205 DAC_fifo[DAC_wptr]=dac_data;
tom_coxon 0:1f4b7aa80ab3 206 DAC_wptr=(DAC_wptr+1) & 0xff;
tom_coxon 0:1f4b7aa80ab3 207 while (DAC_wptr==DAC_rptr) {
tom_coxon 0:1f4b7aa80ab3 208 led1=1;
tom_coxon 0:1f4b7aa80ab3 209 wait_us(10);
tom_coxon 0:1f4b7aa80ab3 210 }
tom_coxon 0:1f4b7aa80ab3 211 led1=0;
tom_coxon 0:1f4b7aa80ab3 212 }
tom_coxon 0:1f4b7aa80ab3 213 }
tom_coxon 0:1f4b7aa80ab3 214 DAC_on=0;
tom_coxon 0:1f4b7aa80ab3 215 led2=0;
tom_coxon 0:1f4b7aa80ab3 216 tick.detach();
tom_coxon 0:1f4b7aa80ab3 217 printf("Ticker detached\r\n");
tom_coxon 0:1f4b7aa80ab3 218 led3=1;
tom_coxon 0:1f4b7aa80ab3 219 free(slice_buf);
tom_coxon 0:1f4b7aa80ab3 220 break;
tom_coxon 0:1f4b7aa80ab3 221 case 0x5453494c:
tom_coxon 0:1f4b7aa80ab3 222 printf("INFO chunk, size %d\r\n",chunk_size);
tom_coxon 0:1f4b7aa80ab3 223 fseek(wavfile,chunk_size,SEEK_CUR);
tom_coxon 0:1f4b7aa80ab3 224 break;
tom_coxon 0:1f4b7aa80ab3 225 default:
tom_coxon 0:1f4b7aa80ab3 226 printf("unknown chunk type 0x%x, size %d\r\n",chunk_id,chunk_size);
tom_coxon 0:1f4b7aa80ab3 227 data=fseek(wavfile,chunk_size,SEEK_CUR);
tom_coxon 0:1f4b7aa80ab3 228 break;
tom_coxon 0:1f4b7aa80ab3 229 }
tom_coxon 0:1f4b7aa80ab3 230 fread(&chunk_id,4,1,wavfile);
tom_coxon 0:1f4b7aa80ab3 231 fread(&chunk_size,4,1,wavfile);
tom_coxon 0:1f4b7aa80ab3 232 }
tom_coxon 0:1f4b7aa80ab3 233 printf("++++++++++++ Done with wave file ++++++++++\r\n");
tom_coxon 0:1f4b7aa80ab3 234 fclose(wavfile);
tom_coxon 0:1f4b7aa80ab3 235 led1=0;
tom_coxon 0:1f4b7aa80ab3 236 }
tom_coxon 0:1f4b7aa80ab3 237
tom_coxon 0:1f4b7aa80ab3 238
tom_coxon 0:1f4b7aa80ab3 239 void dac_out() {
tom_coxon 0:1f4b7aa80ab3 240 if (DAC_on) {
tom_coxon 0:1f4b7aa80ab3 241 led4=1;
tom_coxon 0:1f4b7aa80ab3 242 DACout.write_u16(DAC_fifo[DAC_rptr]);
tom_coxon 0:1f4b7aa80ab3 243 DAC_rptr=(DAC_rptr+1) & 0xff;
tom_coxon 0:1f4b7aa80ab3 244 led4=0;
tom_coxon 0:1f4b7aa80ab3 245 }
tom_coxon 0:1f4b7aa80ab3 246 }
tom_coxon 0:1f4b7aa80ab3 247
tom_coxon 0:1f4b7aa80ab3 248