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

main.cpp

Committer:
tom_coxon
Date:
2010-07-03
Revision:
0:1f4b7aa80ab3
Child:
1:22c43c468a2f

File content as of revision 0:1f4b7aa80ab3:

/*
 Demo of Embedded Artists LPCXpresso baseboard SD card
 reader and audio facilities.

 WAVEplayer by Vlad Cazan/Stephan Rochon modified by Tom Coxon 
 to run correctly on the Embedded Artists LPCXpresso baseboard.
 
 Also modified to play 8 bit sample size in addition to 
 original 16 bit.
 
 Place suitable wav files with 8 or 16 bit sample sizes on the
 SD card and ensure the file names are 8.3 format.  Then change
 the main method below to the relevant file paths. 
 
 Please set all jumpers on board to the default case except for 
 the following:
 
 Audio setup:
 
 1. Insert a jumper in J31 to connect signal PIO1_2 to the low 
 pass filer as described in section 4.7.2. of base board users 
 guide.
 
 2. Insert three jumpers in J33 to connect PIO3_0, PIO3_1 and 
 PIO3_2 to control the amplifier as described in section 4.8
 of base board users guide.

 3. Insert a jumper in J32 and remove any from J34 to use the
 internal speaker as described in section 4.8
 of base board users guide.

 SD Card setup:
 
 4. Insert all five jumpers in J39 as described in section 4.3.3
 of base board users guide.
 
 5. Remove jumper marked "A" in J55 In order to connect PIO1_11 
 to CS signal of J40 (the SPI-SSEL signal)  as described in section 4.3.3
 of base board users guide.
*/

#include "mbed.h"
#include "SDFileSystem.h"

AnalogOut DACout(p18);
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
Ticker tick;
SDFileSystem sd(p5, p6, p7, p24, "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("\r\n--------------- Starting -----------------\r\n");
    
    play_wave("/sd/startup.wav"); //  8 bit sample size

    play_wave("/sd/baddonut.wav");  // 16 bit sample size
    
    play_wave("/sd/dduck.wav");  // 8 bit sample size

    play_wave("/sd/bbunny.wav");  // 8 bit sample size

    play_wave("/sd/clint16.wav"); //  16 bit sample size

    printf("<<<<<<<<<<<<<<<< All done >>>>>>>>>>>>>>>>\r\n");
    led1=1;
    wait(.5);
    led1=0;
    wait(.5);
    led1=1;
}

void play_wave(char *wavname) {
    unsigned chunk_id,chunk_size,channel;
    unsigned data,samp_int,i;
    short dac_data;
    char *slice_buf;
    short *data_sptr;
    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'\r\n",wavname);

    wavfile=fopen(wavname,"rb");
    if (!wavfile) {
        printf("Unable to open wav file '%s'\r\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\r\n",chunk_id,chunk_size);
        switch (chunk_id) {
            case 0x46464952:
                fread(&data,4,1,wavfile);
                printf("RIFF chunk\r\n");
                printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
                printf("  RIFF type 0x%x\r\n",data);
                break;
            case 0x20746d66:
                fread(&wav_format,sizeof(wav_format),1,wavfile);
                printf("FORMAT chunk\r\n");
                printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
                printf("  compression code %d\r\n",wav_format.comp_code);
                printf("  %d channels\r\n",wav_format.num_channels);
                printf("  %d samples/sec\r\n",wav_format.sample_rate);
                printf("  %d bytes/sec\r\n",wav_format.avg_Bps);
                printf("  block align %d\r\n",wav_format.block_align);
                printf("  %d bits per sample\r\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\r\n");
                printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
                printf("  %d slices\r\n",num_slices);
                printf("  Ideal sample interval=%d\r\n",(unsigned)(1000000.0/wav_format.sample_rate));
                samp_int=1000000/(wav_format.sample_rate);
                printf("  programmed interrupt tick interval=%d\r\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\r\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 );
                                    break;
                                case 8:
                                    dac_data+=(  ((int)(*data_sptr++)) +32768 <<8);
                                    break;                                        
                            }
                        } 
                        DAC_fifo[DAC_wptr]=dac_data;
                        DAC_wptr=(DAC_wptr+1) & 0xff;
                        while (DAC_wptr==DAC_rptr) {
                            led1=1;
                            wait_us(10);
                        }
                        led1=0;
                    }
                }
                DAC_on=0;
                led2=0;
                tick.detach();
                printf("Ticker detached\r\n");
                led3=1;
                free(slice_buf);
                break;
            case 0x5453494c:
                printf("INFO chunk, size %d\r\n",chunk_size);
                fseek(wavfile,chunk_size,SEEK_CUR);
                break;
            default:
                printf("unknown chunk type 0x%x, size %d\r\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 ++++++++++\r\n");
    fclose(wavfile);
    led1=0;
}


void dac_out() {
    if (DAC_on) {
        led4=1;
        DACout.write_u16(DAC_fifo[DAC_rptr]);
        DAC_rptr=(DAC_rptr+1) & 0xff;
        led4=0;
    }
}