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-28
- Revision:
- 7:fb47ff047ac7
- Parent:
- 6:fd6ae534d120
- Child:
- 8:40f37287589a
File content as of revision 7:fb47ff047ac7:
// 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;
Timer t2;
#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;
short bufflen = 1;
int buffer[1];
int AudioFormat, NumChannels, SampleRate, BitsPerSample ;
char *slice_buf;
short *data_sptr;
unsigned char *data_bptr;
int *data_wptr;
unsigned channel;
int newvar;
long slice, num_slices;
int verbosity = 0;
int interrupt_condition = 1;
int sampling_freq = 48000;
short Buffer1[8];
short Buffer2[8];
short place_hold1 = 0;
short place_hold2 = 0;
int flag1 = 1;
int flag2 = 0;
int flag3 = 1;
int flag4 = 0;
short value[1];
//long long slice_value;
int slice_value[1];
FILE *my_wav;
FMT_STRUCT wav_format;
DATA_STRUCT wav_data;
Ticker flipper;
//test
void flip() {
led2 = !led2;
}
void isr()
{
//buffer[0] = (*data_sptr)>>1;
//myled = 1;
//int bufflen = sizeof(buffer);
if(verbosity){
printf("buffer data: %d \n\r",buffer);
printf("data_sptr data: %d",data_sptr);
short value = Buffer1[0];
printf("value: %d",value);
}
//t.start();
//t.stop();
//printf("The time taken was %f seconds\n", t.read());
//t.reset();
//myled = 0;
if(flag1 == 0)
{
//access double buffer pt1
value[0] = Buffer1[place_hold1];
i2s.write(value,1);//Send next PWM value to amp
place_hold1 = place_hold1 + 1;
if(place_hold1 == 8)
{
place_hold1 = 0;
place_hold2 = 0;
flag1 = 1;
flag2 = 0;
flag3 = 1;
}
if(verbosity == 1)
{
printf("value Buffer1: %d\n\r",value[0]);
}
}
else if(flag2 == 0)
{
//access double buffer pt2
value[0] = Buffer1[place_hold2];
i2s.write(value,1);//Send next PWM value to amp
place_hold2 = place_hold2 + 1;
if(place_hold2 == 8)
{
place_hold1 = 0;
place_hold2 = 0;
flag1 = 0;
flag2 = 1;
flag3 = 1;
}
if(verbosity == 1)
{
printf("value Buffer2: %d\n\r",value[0]);
}
}
}
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.
//my_wav = fopen("/sd/mydir/gp40_48K_quieter.wav", "rb");//i think that it is "w" for write, "r" for read.
//my_wav = fopen("/sd/mydir/gp40_8K.wav","rb");
//my_wav = fopen("/sd/mydir/gp40_8K_2018.wav","rb");
//my_wav = fopen("/sd/mydir/emd_645.wav", "rb");
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");
while(j <1000){
wm8731_configTEST();
j = j + 1;
}
//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));
printf("do we egt to this point:\n\r");
if (interrupt_condition == 1)
{
sampletick.attach(&isr,1.0/16000); //1/16000
}
slice_buf=(char *)malloc(wav_format.block_align);
while(1){
slice = 0;
while(flag3 == 1)
{
//for (slice=0;slice<num_slices;slice+=1)
while(slice<num_slices){
//t2.start();
fread(slice_buf,wav_format.block_align,1,my_wav);//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(my_wav)){
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[1]=0;
for (channel=0;channel<wav_format.num_channels;channel++) {
switch (wav_format.sig_bps) {
case 16:
//int mybuffer[1];
//mybuffer[0] = data_sptr[channel];// - 32768;
if(flag1 == 1)
{
Buffer1[place_hold1] = data_sptr[channel];
place_hold1 = place_hold1 + 1;
if(place_hold1 == 8)
{
flag4 = 1;
break;
}
}
else if(flag2 == 0)
{
Buffer2[place_hold2] = data_sptr[channel];
place_hold2 = place_hold2 + 1;
if(place_hold2 == 8)
{
flag4 = 1;
break;
}
}
if(interrupt_condition==1)
{
}
else
{
if(verbosity == 1)
{
t.start();
i2s.write(data_sptr,2);
t.stop();
printf("The time taken was %f seconds\n", t.read());
t.reset();
}
else
{
i2s.write(data_sptr,2);
}
if(sampling_freq == 48000)
{
wait_us(0.1);
}
else if(sampling_freq == 8000)
{
wait_us(2);
}
}
if (verbosity)
printf("16 bit channel %d data=%d\n\r ",channel,data_sptr[channel]);
slice_value[1]+=data_sptr[channel];
break;
case 32:
if (verbosity)
printf("32 bit channel %d data=%d ",channel,data_wptr[channel]);
slice_value[1]+=data_wptr[channel];
break;
case 8:
if (verbosity)
printf("8 bit channel %d data=%d ",channel,(int)data_bptr[channel]);
slice_value[1]+=data_bptr[channel];
break;
}
}
if(flag4 == 1)
{
flag4 = 0;
break;
}
slice_value[1]/=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[1]<<=8;
break;
case 16: slice_value[1]+=32768;
break;
case 32: slice_value[1]>>=16;
slice_value[1]+=32768;
break;
}
if (verbosity)
{
printf("data_sptr data: %d \n\r",data_sptr);
printf("slice_value data: %d \n\r",slice_value);
}
slice = slice + 1;
//i2s.write(data_sptr,2);
//t2.stop();
//printf("The time taken was %f seconds\n", t2.read());
//t2.reset();
}
printf("we must have filled the buffer");
}
}
/* 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) {
}
}*/
if(interrupt_condition == 1)
{
sampletick.detach();
}
i2s.stop();
fclose(my_wav);
printf("File is now closed.");
return 0;
}