File content as of revision 0:143457f10e26:
//todo red button and light sensor
#include "mbed.h"
#include "SDFileSystem.h"
AnalogOut DACout(p18);
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
DigitalOut digout(p8);
Ticker tick;
SDFileSystem sd(p5, p6, p7, p13, "sd");
#define SAMPLE_FREQ 40000
#define BUF_SIZE (SAMPLE_FREQ/10)
#define SLICE_BUF_SIZE 1
void dac_out(void);
void play_wave(char *);
void cleanup(char *);
void fill_adc_buf(short *, unsigned);
void swapword(unsigned *);
// a FIFO for the DAC
short DAC_fifo[256];
short DAC_wptr;
short DAC_rptr;
short DAC_on;
typedef struct uFMT_STRUCT {
short comp_code;
short num_channels;
unsigned sample_rate;
unsigned avg_Bps;
short block_align;
short sig_bps;
} FMT_STRUCT;
int main() {
led1=0; wait(.5); led1=1; wait(.5); led1=0;
printf("Hello, world!\n");
play_wave("/sd/baddonut.wav");
printf("Back from play_wave()\n");
play_wave("/sd/clint16.wav");
printf("Back from play_wave()\n");
printf("Goodbye, world!\n");
}
void play_wave(char *wavname)
{
unsigned chunk_id,chunk_size,channel;
unsigned *data_wptr,data,samp_int,i;
short dac_data;
char *slice_buf;
short *data_sptr;
char *data_bptr;
FMT_STRUCT wav_format;
FILE *wavfile;
long slice,num_slices;
DAC_wptr=0;
DAC_rptr=0;
for (i=0;i<256;i+=2) {
DAC_fifo[i]=0;
DAC_fifo[i+1]=3000;
}
DAC_wptr=4;
DAC_on=0;
led1=led2=led3=led4=0;
printf("Playing wave file '%s'\n",wavname);
wavfile=fopen(wavname,"rb");
if (!wavfile) {
printf("Unable to open wav file '%s'\n",wavname);
exit(1);
}
fread(&chunk_id,4,1,wavfile);
fread(&chunk_size,4,1,wavfile);
while (!feof(wavfile)) {
printf("Read chunk ID 0x%x, size 0x%x\n",chunk_id,chunk_size);
switch (chunk_id) {
case 0x46464952:
fread(&data,4,1,wavfile);
printf("RIFF chunk\n");
printf(" chunk size %d (0x%x)\n",chunk_size,chunk_size);
printf(" RIFF type 0x%x\n",data);
break;
case 0x20746d66:
fread(&wav_format,sizeof(wav_format),1,wavfile);
printf("FORMAT chunk\n");
printf(" chunk size %d (0x%x)\n",chunk_size,chunk_size);
printf(" compression code %d\n",wav_format.comp_code);
printf(" %d channels\n",wav_format.num_channels);
printf(" %d samples/sec\n",wav_format.sample_rate);
printf(" %d bytes/sec\n",wav_format.avg_Bps);
printf(" block align %d\n",wav_format.block_align);
printf(" %d bits per sample\n",wav_format.sig_bps);
if (chunk_size > sizeof(wav_format))
fseek(wavfile,chunk_size-sizeof(wav_format),SEEK_CUR);
// create a slice buffer large enough to hold multiple slices
slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
if (!slice_buf) {
printf("Unable to malloc slice buffer");
exit(1);
}
break;
case 0x61746164:
slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
if (!slice_buf) {
printf("Unable to malloc slice buffer");
exit(1);
} num_slices=chunk_size/wav_format.block_align;
printf("DATA chunk\n");
printf(" chunk size %d (0x%x)\n",chunk_size,chunk_size);
printf(" %d slices\n",num_slices);
printf(" Ideal sample interval=%d\n",(unsigned)(1000000.0/wav_format.sample_rate));
samp_int=1000000/(wav_format.sample_rate);
printf(" programmed interrupt tick interval=%d\n",samp_int);
// starting up ticker to write samples out -- no printfs until tick.detach is called
tick.attach_us(&dac_out, samp_int);
DAC_on=1;
led2=1;
for (slice=0;slice<num_slices;slice+=SLICE_BUF_SIZE) {
fread(slice_buf,wav_format.block_align*SLICE_BUF_SIZE,1,wavfile);
if (feof(wavfile)) {
printf("Oops -- not enough slices in the wave file\n");
exit(1);
}
data_sptr=(short *)slice_buf;
for (i=0;i<SLICE_BUF_SIZE;i++) {
dac_data=0;
// for a stereo wave file average the two channels.
for (channel=0;channel<wav_format.num_channels;channel++) {
switch (wav_format.sig_bps) {
case 16:
dac_data+=( ((int)(*data_sptr++)) +32768)>>5;
break;
}
}
dac_data>>=1;
DAC_fifo[DAC_wptr]=dac_data;
DAC_wptr=(DAC_wptr+1) & 0xff;
while (DAC_wptr==DAC_rptr) {
led1=1;
}
led1=0;
}
}
DAC_on=0;
led2=0;
tick.detach();
printf("Ticker detached\n");
led3=1;
free(slice_buf);
break;
case 0x5453494c:
printf("INFO chunk, size %d\n",chunk_size);
fseek(wavfile,chunk_size,SEEK_CUR);
break;
default:
printf("unknown chunk type 0x%x, size %d\n",chunk_id,chunk_size);
data=fseek(wavfile,chunk_size,SEEK_CUR);
break;
}
fread(&chunk_id,4,1,wavfile);
fread(&chunk_size,4,1,wavfile);
}
printf("Done with wave file\n");
fclose(wavfile);
led1=0;
}
void dac_out()
{
if (DAC_on) {
digout=1;
DACout.write(DAC_fifo[DAC_rptr]);
DAC_rptr=(DAC_rptr+1) & 0xff;
digout=0;
}
}