[SOLVED]Audio codec shield with Arduino Due

Re: Audio codec shield with Arduino Due

Postby guest » Sat Jul 11, 2015 10:28 am

SPI will not work unless you toggle the SS pin correctly. please read the datasheet for the WM8731:
http://wiki.openmusiclabs.com/wiki/Audi ... WM8731.pdf
page 35 - DSP mode, mode B.


you will need to connect the SPI clock pin, and the new SS pin (the one you are toggling manually) to your oscilloscope, and take a look at when they go high/low with respect to the first clock cycle of the SPI clock. when it goes high is not as critical as when it goes low. it needs to align with the first clock pulse.

also, im not sure what this code is doing, but it should be put after the SPI transfers:

Code: Select all
    status = TC_GetStatus(TC2, TC2_CHANNEL_FOR_TCLK8);
   if (status & TC_SR_CPCS)
   {
      if (phase == TC2_INTERNAL)
      {
         tc2IRQsServiced[0]++;
      }
      else
      {
         tc2IRQsServiced[1]++;
      }
   }
   if (status & TC_SR_ETRGS)
   {
      tc2IRQsServiced[2]++;
   }
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Sat Jul 11, 2015 7:49 pm

That piece of code just counts the ISR serviced. I removed it in my latest fix. But as you said a delay in the ISR should not effect the frequency at which ISR appears.It is strange.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Wed Jul 29, 2015 11:24 pm

Today I tried the Arudino Hifi I2S driver which uses the Due's SSC controller to communicate with the WM8731 codec over I2S mode. Note now I am using the Mikro audio codec shield and it has ADCLRC and DACLRC as separate pins.Now my I2C interface is just as the earlier one in the code that I posted but now I am using Hi-FI with it.I am just trying to echo data from the microphone to the headphones but I dont get any output.I am not sure if I am configuring the shield correctly over I2C. Could you help me figure out what the problem is?

Here is my newer code:
Code: Select all
/*
  This example uses the HiFi library to connect with a Cirrus CS4271 audio
  codec.  The codec has been configured to generate all the clocks and the
  Arduino will sync to them.  The codec is using I2S mode to communicate
  with the SSC peripheral.
 
  The sketch takes any data is receives from the codec and sends it right
  back out.
 
  This sketch is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <HiFi.h>
#include <Wire.h>
#define LINVOL 23
#define RINVOL 23
#define LHPVOL 100
#define RHPVOL 100
#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

void codecTxReadyInterrupt(HiFiChannelID_t);
void codecRxReadyInterrupt(HiFiChannelID_t);

static uint32_t ldat = 0;
static uint32_t rdat = 0;


void AudioCodec_init() {
        /*randomSeed(analogRead(0));
        SPI.begin(10);
        SPI.setBitOrder(MSBFIRST);
        SPI.setClockDivider(10,84); // select to ss pin 10, 4 MHz// favourable values 11,21,84
        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() {
 
  // set codec into reset
  pinMode(7, OUTPUT);
  digitalWrite(7, LOW);
  Serial.begin(38400);
  AudioCodec_init();
  HiFi.begin();
 
  // Configure transmitter for 2 channels, external TK/TF clocks, 32 bit per
  // channel (data less than 32-bit is left justified in the 32 bit word, but
  // codec config needs 32 clocks per channel).
  HiFi.configureTx(HIFI_AUDIO_MODE_STEREO, HIFI_CLK_MODE_USE_EXT_CLKS, 32);
 
  // Same config as above, except sync the receiver to transmitter (RK/RF
  // clock signals not needed)
  HiFi.configureRx(HIFI_AUDIO_MODE_STEREO, HIFI_CLK_MODE_USE_TK_RK_CLK, 32);

  // Since we've decided to sync the receiver to the transmitter, we could
  // handle both reading and writing in a single interrupt (receive or
  // transmit).  This example uses both just for demonstration purposes.
  HiFi.onTxReady(codecTxReadyInterrupt);
  HiFi.onRxReady(codecRxReadyInterrupt);
 
  // release codec from reset
  digitalWrite(7, HIGH);
 
  // Enable both receiver and transmitter.
  HiFi.enableRx(true);
  HiFi.enableTx(true);
}

void loop() {

Serial.print(ldat);
Serial.print(" ");
Serial.println(rdat);

}



void codecTxReadyInterrupt(HiFiChannelID_t channel)
{
  if (channel == HIFI_CHANNEL_ID_1)
  {
    // Left channel
    HiFi.write(ldat); 
  }
  else
  {
    // Right channel
    HiFi.write(rdat);
  }
}

void codecRxReadyInterrupt(HiFiChannelID_t channel)
{
  if (channel == HIFI_CHANNEL_ID_1)
  {
    // Left channel
    ldat = HiFi.read();
  }
  else
  {
    // Right channel
    rdat = HiFi.read();
  }
}
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Wed Jul 29, 2015 11:25 pm

I remember you telling me that the codec in your shield is working in DSP mode B. How do I set it to I2S mode ?
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Thu Jul 30, 2015 4:10 am

I read the data sheet of WM8731 and as per page 39 I changed the code here for the register "audio data interface format" but still I am not getting any data from the codec.
Code: Select all
Wire.beginTransmission(0x1a);
        Wire.write(0x0e); // digital data format
        //Wire.write(0x03); // 16b SPI mode
        Wire.write(0x02);


My connections to the codec shield and the Due are as in this table.
connctions.jpg
connctions.jpg (63.45 KiB) Viewed 7239 times
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby guest » Thu Jul 30, 2015 10:54 am

on the codecshield, there is only 1 BCK and 1 LRCK, but the DUE has 2 of each. how are you connecting these up? also, be sure to setup the DUE as I2S master. then take a look at the signals on the scope to see if they look right (match the format shown in the datasheet).
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Thu Jul 30, 2015 11:34 pm

Back to the old code(not using the Hi-Fi ibrary) ,I am attaching the scope plots. The yellow one is the SS (slave select) pin wave and the green one is the SPI clock.Their units are also different.One is in micro seconds where as the other is in nano seconds.I dont know if the graphs are right and mean what you mentioned that the SS pin cycle needs to match with the first clock cycle of the SPI.
IMG_20150731_121925.jpg
IMG_20150731_121925.jpg (200.75 KiB) Viewed 7231 times

zoomed in
IMG_20150731_121942.jpg
IMG_20150731_121942.jpg (180.91 KiB) Viewed 7231 times

zoomed out.
IMG_20150731_123200.jpg
IMG_20150731_123200.jpg (193.95 KiB) Viewed 7231 times

The SS pin high (yellow) appears to come before the SPI transfers(green) but I do not know what the alignment should look like
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Fri Jul 31, 2015 2:04 am

Should it look like this?I dont know what correspond to what? Is the LRC the SS pin wave? And BCLK the SPI Clock?
clock wm8732 DSP mode B.jpg
clock wm8732 DSP mode B.jpg (40.25 KiB) Viewed 7229 times
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Fri Jul 31, 2015 2:12 am

I look at your library and it appears you are toggiling the SS pin and waiting for one transfer and then you are toggling the pin again and then the rest of the transfer takes place.

Your code from the library.
Code: Select all
 int _out_temp = _lout;
  PORTB |= (1<<PORTB2);  // toggle ss pina
  asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
  PORTB &= ~(1<<PORTB2); // toggle ss pin
  while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
  }

To get such an effect I might have to dig into the C code to do the SPI transfers and toggle the pin at the falling edge of the SCK.Am I right in all this?

By the way what are you doing here in this line:
Code: Select all
asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Fri Jul 31, 2015 3:24 am

I looked at this code from the Maple library.It appears you have set the SS pin high all during the first byte transfer.Should the SS pin be high at the first byte transfer and then made low or should it be high for the first bit transfer (out of the first 8 bits in the first byte leftour or right out etc).
Code: Select all
static inline void AudioCodec_data(int16* _lin, int16* _rin, int16 _lout, int16 _rout) {

  GPIOA_BASE->BSRR = 0x00000010; // set ss high
  SPI1_BASE->DR = _lout; // send out left data
  asm volatile ("nop"); // delay for appropriate timing
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  asm volatile ("nop");
  GPIOA_BASE->BSRR = 0x00100000; // set ss low
  while (!(SPI1_BASE->SR & (1 << SPI_SR_TXE_BIT))) { // wait for data to be sent
  }
  SPI1_BASE->DR = _rout; // send out right data
  while (!(SPI1_BASE->SR & (1 << SPI_SR_RXNE_BIT))) { // wait for data to arrive
  }
  *_lin = SPI1_BASE->DR; // recieve left data
  while (!(SPI1_BASE->SR & (1 << SPI_SR_RXNE_BIT))) { // wait for data to arrive
  }
  *_rin = SPI1_BASE->DR; // recieve right data
}
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

PreviousNext

Return to Audio Codec Shield

Who is online

Users browsing this forum: No registered users and 2 guests