does not work yet. Sound starts but then stops after a few seconds, whole thing hangs. Published so as I can import through mbed CLI.
Dependencies: mbed sinelookup SDFileSystem_Copy_of_mbed_version I2S
wolfson_3_wav.cpp
- Committer:
- roryhand
- Date:
- 2018-10-01
- Revision:
- 2:05b426733282
- Parent:
- 1:ec4e2020522c
- Child:
- 3:6fba0a044d85
File content as of revision 2:05b426733282:
// 24/03/2018 update - I appear to be able to address the device and write something, as I am getting an ACK returned from the i2c write() function. //however if i use the write function with 4 arguments (as opposed to just 1 argument) then it doesnt work //only works with the 1 argument version!!! //THIS VERSION WORKED, CHANGED SOME THINGS, THEN CHANGED THEM BACK. NOW IT NO LONGER WORKS!!!! #include "mbed.h" #include "sinelookup.h" #include "I2S.h" #define sample_freq 48000 DigitalOut myled(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); Ticker sampletick; Timer t; #include "SDFileSystem.h" #include "WOLFSON_config.h" Serial pc(USBTX, USBRX); // tx, rx //FOR DEBUGGING PROGRAM USING GNU SCREEN DigitalOut cs(p8); I2S i2s(I2S_TRANSMIT,p5,p6,p7); I2C i2c(p9, p10); SDFileSystem sd(p11, p12, p13, p8, "sd"); // the new pinout that i am using typedef struct uFMT_STRUCT{ short comp_code; short num_channels; unsigned sample_rate; unsigned avg_Bps; short block_align; short sig_bps; } FMT_STRUCT; typedef struct uDATA_STRUCT { unsigned subchunk2_ID; unsigned subchunk2_size; char * data_buf; }DATA_STRUCT; short hello; int i = 0; int h = 0; int bufflen = 1; int buffer[1]; int AudioFormat, NumChannels, SampleRate, BitsPerSample ; char *slice_buf; int *data_sptr; int newvar; //long long slice_value; int slice_value; FILE *my_wav; FMT_STRUCT wav_format; DATA_STRUCT wav_data; Ticker flipper; //test void flip() { led2 = !led2; } void isr() { //buffer[0] = (int*)data_sptr; //buffer[0] = newvar; //buffer[0] = sine16lookup[i];//>>1;//sine16lookup[i];//scale down volume a bit on amp//how would this scale down the volume a bit?? //buffer[0] = *fp; //printf("value: %d",data_sptr); //i2s.write(buffer, 2);//Send next PWM value to amp } void wm8731_setup(int chip_addr, int addr, int cmd){ addr = addr << 1; addr = addr|((cmd >> 8 ))& 0x01;//mess around with order of operations cmd = cmd&0xFF; i2c.start(); i2c.write( chip_addr ); i2c.write( addr ); i2c.write( cmd ); i2c.stop(); } void wm8731_config(void){ wm8731_setup( WM8731_ADDRESS, WM8731_REG_RESET, _WM8731_RESET );//1 wm8731_setup( WM8731_ADDRESS, WM8731_REG_LLINE_IN, _WM8731_LEFT_LINEIN );//2 wm8731_setup( WM8731_ADDRESS, WM8731_REG_RLINE_IN, _WM8731_RIGHT_LINEIN );//3 wm8731_setup( WM8731_ADDRESS, WM8731_REG_LHPHONE_OUT, _WM8731_LEFT_HP );//4 wm8731_setup( WM8731_ADDRESS, WM8731_REG_RHPHONE_OUT, _WM8731_RIGHT_HP );//5 wm8731_setup( WM8731_ADDRESS, WM8731_REG_ANALOG_PATH, _WM8731_ANALOGAUDIO );//6 wm8731_setup( WM8731_ADDRESS, WM8731_REG_DIGITAL_PATH, _WM8731_DIGITALAUDIO );//7 wm8731_setup( WM8731_ADDRESS, WM8731_REG_PDOWN_CTRL, _WM8731_POWER );//8 wm8731_setup( WM8731_ADDRESS, WM8731_REG_DIGITAL_IF, _WM8731_DAIF );//9 wm8731_setup( WM8731_ADDRESS, WM8731_REG_SAMPLING_CTRL, _WM8731_SAMPLING );//10 } void wm8731_configTEST(void){ int addr = WM8731_REG_RESET; int cmd = _WM8731_RESET; addr = addr << 1; addr = addr|((cmd >> 8 ))& 0x01;//mess around with order of operations cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS ); i2c.write( addr ); i2c.write( cmd ); i2c.stop(); addr = WM8731_REG_LLINE_IN; cmd = _WM8731_LEFT_LINEIN; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//take Fergus' suggestion and declare these to known values EARLIER in program i2c.write( addr ); i2c.write( cmd ); i2c.stop(); addr = WM8731_REG_RLINE_IN; cmd = _WM8731_RIGHT_LINEIN; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//take Fergus' suggestion and declare these to known values EARLIER in program i2c.write( addr ); i2c.write( cmd ); i2c.stop(); //4 addr = WM8731_REG_LHPHONE_OUT; cmd = _WM8731_LEFT_HP; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS ); i2c.write( addr );//WM8731_REG_LHPHONE_OUT, _WM8731_LEFT_HP i2c.write(cmd); i2c.stop(); //5 addr = WM8731_REG_RHPHONE_OUT; cmd = _WM8731_RIGHT_HP; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//WM8731_REG_RHPHONE_OUT, _WM8731_RIGHT_HP i2c.write( addr ); i2c.write( cmd ); i2c.stop(); //6 addr = WM8731_REG_ANALOG_PATH; cmd = _WM8731_ANALOGAUDIO; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//WM8731_REG_ANALOG_PATH, _WM8731_ANALOGAUDIO i2c.write( addr ); i2c.write( cmd ); i2c.stop(); //7 addr = WM8731_REG_DIGITAL_PATH; cmd = _WM8731_DIGITALAUDIO; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//WM8731_REG_DIGITAL_PATH, _WM8731_DIGITALAUDIO i2c.write( addr ); i2c.write( cmd ); i2c.stop(); //8 addr = WM8731_REG_PDOWN_CTRL; cmd = _WM8731_POWER; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//WM8731_REG_PDOWN_CTRL, _WM8731_POWER) i2c.write( addr ); i2c.write( cmd ); i2c.stop(); //9 addr = WM8731_REG_DIGITAL_IF; cmd = _WM8731_DAIF; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS ); i2c.write( addr );//WM8731_REG_DIGITAL_IF, _WM8731_DAIF i2c.write( cmd ); i2c.stop(); //10 addr = WM8731_REG_SAMPLING_CTRL; cmd = _WM8731_SAMPLING; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//WM8731_REG_SAMPLING_CTRL, _WM8731_SAMPLING i2c.write( addr ); i2c.write( cmd ); i2c.stop(); //11 addr = WM8731_REG_ACTIVE_CTRL; cmd = _WM8731_ACTIVATE; addr = addr << 1; addr = addr|((cmd >> 8 )) & 0x01; cmd = cmd&0xFF; i2c.start(); i2c.write( WM8731_ADDRESS );//WM8731_REG_SAMPLING_CTRL, _WM8731_SAMPLING i2c.write( addr ); i2c.write( cmd );//there is also a deactive version!! i2c.stop(); } int main() { FMT_STRUCT wav_format; char data[2]; pc.printf("Beginning of program\n"); data[0] = 0x0F; data[1] = 0x00; FILE *my_wav; //my_wav = fopen("/sd/mydir/gp40.wav", "rb");//i think that it is "w" for write, "r" for read. my_wav = fopen("/sd/mydir/gp40_48K.wav", "rb");//i think that it is "w" for write, "r" for read. fseek(my_wav, 20, SEEK_SET); // set pointer to byte 20 fread(&AudioFormat, 2, 1, my_wav); // check file is PCM if (AudioFormat==0x01) { printf("Wav file is PCM data\n\r"); } else { printf("Wav file is not PCM data\n\r"); } fseek (my_wav,20,SEEK_SET); fread(&wav_format,sizeof(wav_format),1,my_wav); printf("%d block align\n",wav_format.block_align); printf(" %d channels\n",wav_format.num_channels); fseek(my_wav, 36, SEEK_SET); fread(&wav_data.subchunk2_ID,4,1,my_wav); fseek(my_wav, 40, SEEK_SET); fread(&wav_data.subchunk2_size,4,1,my_wav); printf("DATA chunck\n"); printf(" %d subchunk 2 ID\n",wav_data.subchunk2_ID); printf(" %d subchunk 2 size\n",wav_data.subchunk2_size); i2c.frequency(100000); long j = 0; printf("set up the codec\n\r"); wm8731_configTEST(); //i2s audio data transfer code?? i2s.stereomono(I2S_STEREO); i2s.masterslave(I2S_MASTER);//MASTER definitely works! i2s.frequency(sample_freq); int yes = i2s.setup_ok(); pc.printf("Setup went ok?: %d\n", yes);//0 = ack, 1 = Nack*/ printf("can we get to this point? 1\n\r"); led3 = 1; //myled = 1; led2 = 1; printf("can we get to this point? 2\n\r"); myled = 1; i2s.start(); //while (1) { fread(&wav_format,sizeof(wav_format),1,my_wav); printf("wav_format %d\n\r",wav_format); fseek(my_wav,20,SEEK_SET); fread(&wav_format,sizeof(wav_format),1,my_wav); fseek(my_wav,36,SEEK_SET); fread(&wav_data,sizeof(wav_data),1,my_wav); int num_slices = wav_data.subchunk2_size/wav_format.block_align; printf("wav_data.subchunk2_size: %d\n\r",wav_data.subchunk2_size); printf("wav_format.block_align: %d\n\r",wav_format.block_align); printf("num_slices: %d\n\r",num_slices); printf("num_slices*wav_format.block_align %d\n\r",num_slices*wav_format.block_align); printf("wav_format.num_channels*wav_format.sig_bps/8: %d\n\r",wav_format.num_channels*wav_format.sig_bps/8); printf("chunk_size - sizeof(wav_format) %d\n\r",wav_data.subchunk2_size-sizeof(wav_format)); printf("sizeof(wav_format): %d\n\r",sizeof(wav_format)); //sampletick.attach(&isr,1/96000); //while(!feof(my_wav)){ //while(1){ //if (wav_data.subchunk2_size > sizeof(wav_format)){ //fseek(my_wav,wav_data.subchunk2_size-sizeof(wav_format),SEEK_CUR); /*if(wav_data.subchunk2_size > (num_slices*wav_format.block_align)){ fseek(my_wav,wav_data.subchunk2_size - (num_slices*wav_format.block_align),SEEK_CUR); printf("chunk_size - sizeof(wav_format) %d\n\r",wav_data.subchunk2_size-sizeof(wav_format)); printf("sizeof(wav_format): %d\n\r",sizeof(wav_format)); } else { break; }*/ // slice_buf=(char *)malloc(wav_format.block_align); for (slice=0;slice<num_slices;slice+=1) { fread(slice_buf,wav_format.block_align,1,wavefile);//THIS IS WHERE HE READS IN THE DATA, TO SLICE_BUF. BUT USES WAV_FORMAT.BLOCKALIGN AS HIS SIZE GUIDE //I do not understand why he is not "seeking" through the file first though... if (feof(wavefile)) { printf("Oops -- not enough slices in the wave file\n"); exit(1); } data_sptr=(short *)slice_buf; // 16 bit samples data_bptr=(unsigned char *)slice_buf; // 8 bit samples data_wptr=(int *)slice_buf; // 32 bit samples slice_value=0; for (channel=0;channel<wav_format.num_channels;channel++) { switch (wav_format.sig_bps) { case 16: if (verbosity) printf("16 bit channel %d data=%d ",channel,data_sptr[channel]); slice_value+=data_sptr[channel]; break; case 32: if (verbosity) printf("32 bit channel %d data=%d ",channel,data_wptr[channel]); slice_value+=data_wptr[channel]; break; case 8: if (verbosity) printf("8 bit channel %d data=%d ",channel,(int)data_bptr[channel]); slice_value+=data_bptr[channel]; break; } } slice_value/=wav_format.num_channels; // slice_value is now averaged. Next it needs to be scaled to an unsigned 16 bit value // with DC offset so it can be written to the DAC. switch (wav_format.sig_bps) { case 8: slice_value<<=8; break; case 16: slice_value+=32768; break; case 32: slice_value>>=16; slice_value+=32768; break; } dac_data=(short unsigned)slice_value; if (verbosity) printf("sample %d wptr %d slice_value %d dac_data %u\n",slice,DAC_wptr,(int)slice_value,dac_data); DAC_fifo[DAC_wptr]=dac_data; DAC_wptr=(DAC_wptr+1) & 0xff; while (DAC_wptr==DAC_rptr) { } } DAC_on=0; tick.detach(); free(slice_buf); break; case 0x5453494c: if (verbosity) printf("INFO chunk, size %d\n",chunk_size); fseek(wavefile,chunk_size,SEEK_CUR); break; default: printf("unknown chunk type 0x%x, size %d\n",chunk_id,chunk_size); data=fseek(wavefile,chunk_size,SEEK_CUR); break; } fread(&chunk_id,4,1,wavefile); fread(&chunk_size,4,1,wavefile); } } sampletick.detach(); i2s.stop(); fclose(my_wav); printf("File is now closed."); return 0; }