[SOLVED]Audio codec shield with Arduino Due

[SOLVED]Audio codec shield with Arduino Due

Postby youthreewire » Tue Jun 09, 2015 8:08 pm

Hello,

I am working with the audio codec shield. I want to port the library to Arduino Due.Could some one please guide me how to do it? After Due I want to port it to Intel Edison and even pcDuino3.

Thanks
Last edited by youthreewire on Thu Aug 06, 2015 10:47 am, edited 1 time in total.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby guest » Tue Jun 09, 2015 8:45 pm

the codecshield requires I2C and I2S interfaces. so locate those pins for your microcontroller platform. from what ive heard, the I2S drivers arent written yet for the edison. the codecshield is hardwired as an I2S slave device, so you will also need a timer/counter clock input pin available. there are ways around this, but it involves modifying the PCB of the codecshield. the basic program flow is as follows:

1. set up registers via I2C
2. count clock cycles from codecshield
3. interrupt every N clock cycles to initiate an I2S data transfer
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Tue Jun 09, 2015 9:06 pm

I want to get this working first with the Due. I know that the I2C and SPI pins wont match the codec shield. So I have to manually wire it but is it possible to make the Library without using AVR specific code for the Due? I checked the library there is some ASM code and Timer specific code.So we have to change that and the rest is standard wire.h commands.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Tue Jun 09, 2015 9:08 pm

I tried running this on a Diecimilia and Maple but I want to stream the linein values over the serial port but the code appears to be crashing. Why can I not use Serial.print( ) functions with this library.Can the serial port issue be solved using a powerful microcontroller like the Due?
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Tue Jun 09, 2015 9:14 pm

Here is the Due timer library
https://github.com/ivanseidel/DueTimer

AVR specific assembly code which needs to be changed
Code: Select all
static inline void AudioCodecMega_data(int* _lin, int* _rin, int _lout, int _rout) {
  int _out_temp = _lout;
  PORTB |= (1<<PORTB0);  // toggle ss pina
  asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
  PORTB &= ~(1<<PORTB0); // toggle ss pin
  while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
  }
  asm volatile ("out %0, %A1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
  asm volatile ("in r3, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
  _out_temp = _rout;
  while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
  }
  asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
  asm volatile ("in r2, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
  asm volatile ("movw %0, r2" : "=r" (*_lin) : );
  while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
  }
  asm volatile ("out %0, %A1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
  asm volatile ("in r3, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
  while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
  }
  asm volatile ("in r2, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
  asm volatile ("movw %0, r2" : "=r" (*_rin) : );
}


More AVR specific code
Code: Select all
#elif ADCS == 1
  static inline void AudioCodecMega_ADC(unsigned int* _mod0value) {
    if (ADCSRA & (1 << ADIF)) { // check if sample ready
      _mod0temp += ADCL; // fetch ADCL first to freeze sample
      _mod0temp += (ADCH << 8); // add to temp register
      ADCSRA = 0xf7; // reset the interrupt flag
      if (--_i == 0) { // check if enough samples have been averaged
        // add in hysteresis to remove jitter
        if (((_mod0temp - *_mod0value) < HYST) || ((*_mod0value - _mod0temp) < HYST)) {
        }
        else {
          *_mod0value = _mod0temp; // move temp value
   }
        _mod0temp = 0x0000; // reset temp value
        _i = 64; // reset counter
      }
    }
  }
#elif ADCS == 2
  static inline void AudioCodecMega_ADC(unsigned int* _mod0value, unsigned int* _mod1value) {
    if (ADCSRA & (1 << ADIF)) { // check if sample ready
      --_i; // check which sample we are on
      if (_i == 129) { // do nothing, first sample after mux change
      }
      else if (_i >= 65) { // sample ADC0
        _mod0temp += ADCL; // fetch ADCL first to freeze sample
        _mod0temp += (ADCH << 8); // add to temp register
        if (_i == 65) { // check if enough samples have been averaged
          // add in hysteresis to remove jitter
          if (((_mod0temp - *_mod0value) < HYST) || ((*_mod0value - _mod0temp) < HYST)) {
          }
          else {
            *_mod0value = _mod0temp; // move temp value
       }
          _mod0temp = 0x0000; // reset temp value
          ADMUX = 0x41; // switch to ADC1
        }
      }
      else if (_i < 64) { // sample ADC1, first sample (64) after mux change ignored
        _mod1temp += ADCL; // fetch ADCL first to freeze sample
        _mod1temp += (ADCH << 8); // add to temp register
        if (_i == 0) { // check if enough samples have been averaged
          // add in hysteresis to remove jitter
          if (((_mod1temp - *_mod1value) < HYST) || ((*_mod1value - _mod1temp) < HYST)) {
          }
          else {
            *_mod1value = _mod1temp; // move temp value
       }
          _mod1temp = 0x0000; // reset temp value
          ADMUX = 0x40; // switch to ADC0
          _i = 130; // reset counter
        }
      }
      ADCSRA = 0xf7; // reset the interrupt flag
    }
  }
#endif
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Tue Jun 09, 2015 9:37 pm

I found some sample code which compiles for Due. But I do not know how to implement the examples like "fixed_delay" in the provided library.

Sample code here:
Code: Select all
#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;
int temp_spi[4];

//TC1 ch 0
void TC3_Handler()
{
        TC_GetStatus(TC1, 0);

        temp = random(65535);
        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);
        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(){
 
        Serial.begin(9600);
        AudioCodec_init();
        startTimer(TC1, 0, TC3_IRQn, 44100); //startTimer(TC1, 0, TC3_IRQn, 44100); //TC1 channel 0, the IRQ for that channel and the desired frequency
}

void loop(){
}
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Tue Jun 09, 2015 9:39 pm

Looking at the code I think there are 12C(wire) and SPI pins being used. So what could be the connection diagram between the Due and the Shield?
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby guest » Wed Jun 10, 2015 10:56 am

on the maple, USB conflicts with SPI data transfers, so it cant be used (it can be used, but causes glitches). you can transfer over serial on an UNO, but it requires your own code, as the serial library is not optimized for speed. if you are trying to transfer data, you will need:

16b/sample * 2 sample (stereo) * 44ksamples/second = 1.4Mbps

since there is overhead in serial, you will probably need at least 2Mbps to actually make it work.

awesome that you found code that works! and its doing it over the SPI as well (usually SPI ports will double as I2S ports, so it might be I2S on the low level). so if you want to implement different code, you keep the data transfer the same as they have it shown. your incoming data is:

left = (temp_spi[0] << 8) | temp_spi[1];
right = (temp_spi[2] << 8) | temp_spi[3];

so to do delay, you just make a buffer, and load those data in, and take the data out from a different address. the rest of the example code should stay the same.
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Wed Jun 10, 2015 9:39 pm

Now I have two microcontrollers on that works at 16 Mhz works at 2.5Mbaud and other at 84Mhz but works only at 1Mbaud. So which one should I use here? But I am assuming the codec shield will work better with the 84Mhz device as it has more RAM .
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Thu Jun 11, 2015 3:37 am

I ran this code but it crashes .I cant get the serial port to work with this program.I put anything to print the program crashes. If I disable the timer function in the setup then it prints otherwise it crashes. Could some one help me out here.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Next

Return to Audio Codec Shield

Who is online

Users browsing this forum: No registered users and 1 guest


cron