[SOLVED]Audio codec shield with Arduino Due

Re: Audio codec shield with Arduino Due

Postby youthreewire » Sat Jul 04, 2015 1:30 am

I also used attachinterrupt function but it is still slow.I think I might need to use assembly code to make it run faster. I am still surprised that the arduino 328/atmega2560 is able to track a 11Mhz CLKOUT signal and still is able to communicate over serial port. Due as per it specs is far ahead that arduino/atmel 328 but still I dont get the desired performance when it comes to tracking an external clock signal for interrupts.
Last edited by youthreewire on Sat Jul 04, 2015 3:56 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 youthreewire » Sat Jul 04, 2015 2:28 am

I check the effect on CLKOUT signal on the Mega arduino and the time period for a GPIO pin toggle on interrupt from CLKOUT is 3.7Khz. So I think Due should work as this interrupt based GPIO toggling is not the same frequency as CLKOUT frequency. Using Due I got a 76 Khz wave and 142Khz wave. I think at 3.7Khz there is enough time for the atmega328/atmega2560 to do serial communication.I think I might have to reduce the timer update to 3.7 khz on the Due and then serial communication might work. What do you say?
Last edited by youthreewire on Sat Jul 04, 2015 3:56 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 youthreewire » Sat Jul 04, 2015 3:55 am

So I think the right question would is can we set a clock divider when using an external clock for timer interrupt.If I can set the divider and make the interrupt fall around a time period of 3.7Khz then I can do serial communication easily with the Due.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Sat Jul 04, 2015 5:45 am

Code: Select all
#define TC2_CHANNEL_FOR_TCLK8 2  /* presumed to correspond to XC2 */

enum Phase
   {
      TC2_INTERNAL,
      PIOD_EXTERNAL,
      TC2_EXTERNAL,
      DONE
   };
   
  /* enum Phase
   {
      TC2_EXTERNAL,
      TC2_EXTERNAL,
      TC2_EXTERNAL,
      DONE
   };*/

Phase phase;
int pioIRQsServiced;
int tc2IRQsServiced[3];
unsigned int status;
int upflag = 0;
bool ledon,ledon1=0;
int oldmillis=0;

/****************************************************************/

void PIOD_Handler(void)
{
   /* clear interrupt */
   status = REG_PIOD_ISR;
   pioIRQsServiced++;
}


/****************************************************************/

void TC8_Handler()
{
  ledon1= !(ledon1);
    digitalWrite(13,ledon1);
  /* clear interrupt */
   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]++;
   }
}


/****************************************************************/

void SetupPIOD(void)
{
   int result;

   /* power on PIO ("Parallel Input/Output Controller") controller D */
   pmc_enable_periph_clk(ID_PIOD);
   /* enable interrupts for PIOD */
   NVIC_EnableIRQ(PIOD_IRQn);
   /* configure PD9 as general-purpose IO pin as opposed to the TCLK8 peripheral */
   result = PIO_Configure(PIOD, PIO_INPUT, PIO_PD9, PIO_IT_RISE_EDGE);
   printf("%d <- PIO_Configure\n", result);
   /* ensure we're interrupting on the rising edge of the external clock */
   REG_PIOD_AIMER = PIO_PD9;
   REG_PIOD_ESR = PIO_PD9;
   REG_PIOD_REHLSR = PIO_PD9;
   /* enable interrupts */
   REG_PIOD_IER = PIO_PD9;
}


/****************************************************************/

void TakeDownPIOD(void)
{
   TC_Stop(TC2, TC2_CHANNEL_FOR_TCLK8);
   TC_SetRC(TC2, TC2_CHANNEL_FOR_TCLK8, 0);
   REG_PIOD_IDR = PIO_PD9;
   NVIC_DisableIRQ(TC8_IRQn);
   pmc_disable_periph_clk(ID_PIOD);
}


/****************************************************************/

void SetupTC2(bool useInternalClock)
{
   int result;

   /* "The user must configure the Power Management Controller before any access to the input line information." per 34.4.2 */
   pmc_enable_periph_clk(ID_TC8);
   /* "Using the PIO Controller requires the NVIC to be programmed first." per 34.4.3 */
   NVIC_EnableIRQ(TC8_IRQn);
   result = PIO_Configure(PIOD, PIO_PERIPH_B, PIO_ABSR_P9, PIO_DEFAULT);
   printf("%d <- PIO_Configure\n", result);
   if (useInternalClock)
   {
      TC_Configure(TC2,
                TC2_CHANNEL_FOR_TCLK8,
                TC_CMR_TCCLKS_TIMER_CLOCK4 | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE);
   }
   else
   {
      TC_Configure(TC2,
                TC2_CHANNEL_FOR_TCLK8,
                (TC_CMR_TCCLKS_XC2 |
                 TC_CMR_EEVTEDG_RISING |
                 TC_CMR_EEVT_XC2 |
                 TC_CMR_ENETRG |
                 TC_CMR_WAVSEL_UP_RC |
                 TC_CMR_WAVE));
   }
   /* load counter register */
   TC_SetRC(TC2, TC2_CHANNEL_FOR_TCLK8, 13);
   /* start the timer */
   TC_Start(TC2, TC2_CHANNEL_FOR_TCLK8);
   /* enable the timer-specific interrupts */
   REG_TC2_IER2 = TC_IER_CPCS | TC_IER_ETRGS;
}


/****************************************************************/

void TakeDownTC2(void)
{
   TC_Stop(TC2, TC2_CHANNEL_FOR_TCLK8);
   TC_SetRC(TC2, TC2_CHANNEL_FOR_TCLK8, 0);
   REG_TC2_IDR2 = TC_IER_CPCS | TC_IER_ETRGS;
   NVIC_DisableIRQ(TC8_IRQn);
   pmc_disable_periph_clk(ID_TC8);
}


/****************************************************************/

void setup(void)

   pinMode(12,OUTPUT);
   pinMode(13,OUTPUT);
   Serial.begin(9600);
   printf("start with TC2 internal\n");
   SetupTC2(true);
}


/****************************************************************/

void loop(void)
{
 
       
       
  //phase=TC2_EXTERNAL;
  //Serial.println(phase);
   switch (phase)
   {
      case TC2_INTERNAL:
         if (tc2IRQsServiced[0] > 250000)
         {
            phase = PIOD_EXTERNAL;
            TakeDownTC2();
            printf("PASSED\nswitch to PIOD\n");
            SetupPIOD();
         }
         break;
      case PIOD_EXTERNAL:
         if (pioIRQsServiced > 20)
         {
            phase = TC2_EXTERNAL;
            TakeDownTC2();
            printf("PASSED\nswitch to TC2 external\n");
            SetupTC2(false);
         }
         break;
      case TC2_EXTERNAL:
         if (tc2IRQsServiced[1] > 20)
         {
            printf("PASSED!!!\n");
            for ( ; ; );
         }
         break;
      default:
         break;
   }
   //delay(1000);
   printf("PIO IRQs: %d, CPCS internal IRQs: %d, CPCS external IRQs: %d, ETRGS external IRQs: %d, status: %08x, CV2: %d\n", pioIRQsServiced, tc2IRQsServiced[0], tc2IRQsServiced[1], tc2IRQsServiced[2], status, REG_TC2_CV2);
   if (Serial.available() > 0)
   {
      char choice = Serial.read();
      if (choice == 'z')
      {
         REG_TC2_BCR = TC_BCR_SYNC;
      }
   }
}

code for toggle led on pin13 with external interrupt.I tried chaning TC_setRC and TC_setRA to change the width(timeperiod) of the signal but showed no effect.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Sat Jul 04, 2015 6:07 am

In the latest test which I conducted over 30-40 iterations I am getting the timer period as 6us. So the frequency of the wave is 1000000/6 = 166khz. I think it is too high and not giving time for the serial comm in the main loop to finish.

I am able to set it to internal clock and vary the time period and frequency but I am not able to do so with the external clock signal given as timer interrupt..
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Sat Jul 04, 2015 11:12 pm

Code: Select all
uint32_t rc = (11111111/44100); //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_SetRA(TC2,TC2_CHANNEL_FOR_TCLK8,rc/2);     
   TC_SetRC(TC2, TC2_CHANNEL_FOR_TCLK8,rc);
   /* start the timer */
   TC_Start(TC2, TC2_CHANNEL_FOR_TCLK8);
   /* enable the timer-specific interrupts */
   REG_TC2_IER2 = TC_IER_CPCS | TC_IER_ETRGS;
   TC2->TC_CHANNEL[TC2_CHANNEL_FOR_TCLK8].TC_IER=TC_IER_CPCS;
   TC2->TC_CHANNEL[TC2_CHANNEL_FOR_TCLK8].TC_IDR=~TC_IER_CPCS;


After adding these and adjusting SetRA and SetRC and rc I am able to see the interrupt toggling the LED and also able to communicate with serial port. I will put this again on the oscilloscope and check the time period and see if it falls around 3.7khz.But the interrupt counter becomes slow when in serial port comm but faster when it works alone.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby guest » Sun Jul 05, 2015 9:17 pm

so, is TC_SetRA the clock divider? does the pin toggle at 11MHz/TC_SetRA? if you apply a slower clock to that pin (instead of the codecshield clock), does it reduce rate accordingly (this will verify that the counter is responding to the external clock, and not an internal one).
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Sun Jul 05, 2015 10:03 pm

Even in Atmega328 or Arduino uno the pin does not toggle at 11Mhz. The ISR works at 3.7Khz. Now I did something new and I am able to toggle the LED at 3.67Khz.So I am hoping that it will work now.I had to set the baud at 1000000 bps and this changes the time period of the ISR toggle. Now I will invert the SS pin and see if I am able to read the sound data.
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby youthreewire » Mon Jul 06, 2015 8:39 am

I just got SPI synced with external clock.
IMG_20150706_210437.jpg
IMG_20150706_210437.jpg (61.72 KiB) Viewed 8686 times
youthreewire
 
Posts: 117
Joined: Tue Jun 09, 2015 8:06 pm

Re: Audio codec shield with Arduino Due

Postby guest » Mon Jul 06, 2015 9:10 am

glad to hear the SPI is now working. are you able to pass data?

also, the output rate should be ~11MHz/256 = 44.1kHz. i think the input clock is divided down to 5.6MHz, so the divide ratio is actually 128 to get a 44.1kHz interrupt rate.

also, digitalwrite() may be too slow for toggling the SS pin. if this ends up being the case, you should look into direct pin manipulation.
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

PreviousNext

Return to Audio Codec Shield

Who is online

Users browsing this forum: No registered users and 1 guest


cron