2

WM8731 codec was successfully interfaced with Atmega328 like variants in Arduino. It was first done successfully by Open music labs who are the makers of the breakout board for WM8731. Taking this library as reference another library was developed for atmega2560 Arduino and it also works fine. But now I am trying to get it work with Arduino Due which unlike other AVR micro-controllers in the Arduino family is an ARM. I found some useful code.It compiles well and is able to communicate with the WM8731 codec in I2C. I will post the original library and also explain in parts how the code for Due is built.

Original library is here: http://cdn.sparkfun.com/datasheets/Dev/Arduino/Shields/AudioCodecNew.zip

My code split looking at the AudioCodec.h file.

#include <Wire.h>
#include <SPI.h>

#define LINVOL 23
#define RINVOL 23
#define LHPVOL 121
#define RHPVOL 121
#define ADCHPD 0
#define SIDEATT 0
#define SIDETONE 0
#define DACSEL 1
#define BYPASS 0
#define INSEL 0
#define MUTEMIC 1
#define MICBOOST 0
#define SAMPLE_RATE 44

volatile boolean l;

unsigned int temp = 0,temp1=0;
int temp_spi[4];
int m1[301],m2[301];
//TC1 ch 0
int left_in,right_in,left_out,right_out;
void TC0_Handler()
{
TC_GetStatus(TC0, 0);

    temp = random(65535);
    //temp = left_out;
    //temp1 = right_out;
    temp_spi[0] = SPI.transfer(10,highByte(temp),SPI_CONTINUE);
    temp_spi[1] = SPI.transfer(10,lowByte(temp),SPI_CONTINUE);
    temp_spi[2] = SPI.transfer(10,highByte(temp),SPI_CONTINUE);
    temp_spi[3] = SPI.transfer(10,lowByte(temp),SPI_LAST);
    //left_in - (temp_spi[0]<<8)|temp_spi[1];
    //right_in = (temp_spi[2]<<8)|temp_spi[3];
    /*Serial.println("Hello");
    Serial.println(temp_spi[0]);
    Serial.println(temp_spi[1]);
    Serial.println(temp_spi[2]);
    Serial.println(temp_spi[3]);*/
}

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t     frequency) {
    pmc_set_writeprotect(false);
    pmc_enable_periph_clk((uint32_t)irq);
    TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
    uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected TIMER_CLOCK4 above
    TC_SetRA(tc, channel, rc/2); //50% high, 50% low
    TC_SetRC(tc, channel, rc);
    TC_Start(tc, channel);
    tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
    tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
    NVIC_EnableIRQ(irq);
}

void AudioCodec_init() {
    randomSeed(analogRead(0));
    SPI.begin(10);
    SPI.setBitOrder(MSBFIRST);
    SPI.setClockDivider(10,21); // select to ss pin 10, 4 MHz
    SPI.setDataMode(10,SPI_MODE0);

    // setup i2c pins and configure codec
    // the new Wire library has trouble with 0x00, so (uint8_t) is added
    // To change the Wire interface speed, go to:
    // <path_from_arduino>\hardware\arduino\sam\libraries\Wire\Wire.h
    // and change the parameters TWI_CLOCK, RECV_TIMEOUT and XMIT_TIMEOUT
    // to the desire frequency.
    int temp_wire1;
    int temp_wire2;

    Wire.begin();
    Wire.beginTransmission(0x1a);
    Wire.write(0x0c); // power reduction register
    Wire.write((uint8_t)0x00); // turn everything on
    temp_wire1 = Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x0e); // digital data format
    Wire.write(0x03); // 16b SPI mode
    temp_wire2 = Wire.endTransmission();

    //Serial.println(temp_wire1);
    //Serial.println(temp_wire2);

    Wire.beginTransmission(0x1a);
    Wire.write((uint8_t)0x00); // left in setup register
    Wire.write((uint8_t)LINVOL);
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x02); // right in setup register
    Wire.write((uint8_t)RINVOL);
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x04); // left headphone out register
    Wire.write((uint8_t)LHPVOL);
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x06); // right headphone out register
    Wire.write((uint8_t)RHPVOL);
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x0a); // digital audio path configuration
    Wire.write((uint8_t)ADCHPD);
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x08); // analog audio pathway configuration
    Wire.write((uint8_t)((SIDEATT << 6)|(SIDETONE << 5)|(DACSEL << 4)|(BYPASS << 3)|(INSEL << 2)|(MUTEMIC << 1)|(MICBOOST << 0)));
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x10); // clock configuration
    #if SAMPLE_RATE == 88
      Wire.write(0xbc);
    #elif SAMPLE_RATE == 44
      Wire.write(0xa0);
    #elif SAMPLE_RATE == 22
      Wire.write(0xe0);
    #elif SAMPLE_RATE == 8
      Wire.write(0xac);
    #elif SAMPLE_RATE == 2
      Wire.write(0xce);
    #endif
    Wire.endTransmission();

    Wire.beginTransmission(0x1a);
    Wire.write(0x12); // codec enable
    Wire.write(0x01);
    Wire.endTransmission();

}

void setup(){

    pinMode(2,INPUT);
    pinMode(10,OUTPUT);
    Serial.begin(115200);
    Serial1.begin(9600);
    Serial.println("Hello");
AudioCodec_init();
startTimer(TC0, 0, TC0_IRQn, 2000); //startTimer(TC1, 0, TC3_IRQn,   44100); //TC1 channel 0, the IRQ for that channel and the desired frequency
}

void loop(){
//Serial.println("Hello");
/*for(int i =0;i<300;i++)
{
m1[i]=map(analogRead(0),300,800,-400,400);
m2[i]=map(analogRead(1),300,800,-400,400);
}*/
//for(int j =0;j<300;j++)
//{
/*Serial1.print("a");
Serial1.print(m1[j]);
Serial1.print("b");
Serial1.print(m2[j]);*/
//Serial1.println(left_in);
Serial.print(temp_spi[0]);
Serial.print(" ");
Serial.print(temp_spi[1]);
Serial.print(" ");
Serial.print(temp_spi[2]);
Serial.print(" ");
Serial.println(temp_spi[3]);
//Serial1.println("c");
//Serial.println("In loop");
//h23}
}

So on atmega328 the clockout from the WM8731 was give to T1 pin and on atmega2560 timer 5 was used and clockout was attached to pin T5. I am just starting with Due and I dont know much about ARM but I set the code to TC0,TC0 timer and pin 2.

As described here in this link: http://forum.arduino.cc/index.php?topic=130423.0

Some how the SPI part in this code and the timer is not working as I cannot get any voice out from the codec.I am also printing the temp_spi[x] variables over serial port and all of them are just zeros all the time. Could some one help me make this code work with the codec? The code compiles fine for Due in the arduino IDE.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.