Go Down

Topic: Converting PCM library for Zero Using timer compare and interrupt (Read 160 times) previous topic - next topic

tohfa_haque

I am trying to build my own library which can play PCM data using the flash memory of Arduino Zero. 
A PCM library is available for the Arduino Uno board. I am using Zero board for this I need a library that can use PCM data. For that, I will be needed a timer interrupt library and an alternative for pgmspace.h. Can anyone please suggest how can I get these libraries for Arduino Zero?

I am attaching the file which is excessing timer/counter 3 and timer/counter controller 2. That could give you a clear idea what I am missing. 

tohfa_haque




I have used this file as a sketch and it worked that means arduino.h can use in zero timer purpose. But my library is not building at all.
int state;

void TcConfig(int sampleRate)
{

  //First configure Generic Clock(GENCTRL related Setting)
  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |  //50-50 Duty(Though,it will not reflect on any output pin)
                      GCLK_GENCTRL_GENEN |        //Enable generic clock generator
                      GCLK_GENCTRL_SRC_DFLL48M |  //48MHz clock PLL clock as the input
                      GCLK_GENCTRL_ID(4);         //Select GCLK 4
  while (GCLK->STATUS.bit.SYNCBUSY);

  SerialUSB.println("Braekpoint1");

  //Configure Divisor of Input Clock for GENCTRL(GENDIV Related Settings)
  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(48) |         //Select clock divisor as 48 i.e GCLK4 output will be 48/48 = 1MHz
                     GCLK_GENDIV_ID(4);           //GCLK4
 
  SerialUSB.println("Braekpoint2");

  //Now configure GCLK4 & Feed it's output to TC5(CLKCTRL related settings)
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Enable Generic Clock
                      GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                      GCLK_CLKCTRL_ID(GCM_TC4_TC5);  //Feed GCLK4 output to TC5

  SerialUSB.println("Braekpoint3");

  TC5->COUNT16.CTRLA.reg = TC_CTRLA_PRESCSYNC_PRESC | // Overflow on prescaler clock
                           TC_CTRLA_MODE_COUNT16 |  //16 Bit Mode
                           TC_CTRLA_PRESCALER_DIV1024  | //1024 Prescaler
                           TC_CTRLA_WAVEGEN_MFRQ;  //Match Frequency Mode

  SerialUSB.println("Braekpoint4");

  TC5->COUNT16.CC[0].reg = 500;// Set the CC register
  while (TC5->COUNT16.STATUS.bit.SYNCBUSY);

  SerialUSB.println("Braekpoint5");

  TC5->COUNT16.CTRLA.bit.ENABLE = 1;  //Enable TC5
  while (TC5->COUNT16.STATUS.bit.SYNCBUSY);// Wait for sync

  SerialUSB.println("Braekpoint6");

  NVIC_DisableIRQ(TC5_IRQn);
  NVIC_ClearPendingIRQ(TC5_IRQn);
  NVIC_SetPriority(TC5_IRQn, 0);
  NVIC_EnableIRQ(TC5_IRQn);

  SerialUSB.println("Braekpoint7");

  TC5->COUNT16.INTENSET.bit.OVF = 1;

  SerialUSB.println("Braekpoint8");
}

void TcStart(void)
{
  TC5->COUNT16.CTRLA.bit.ENABLE = 1; //set the CTRLA register
  while (TC5->COUNT16.STATUS.bit.SYNCBUSY);
}


void TC5_Handler (void) {
  //YOUR CODE HERE
  if (state == true) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
  state = !state;
  // END OF YOUR CODE
  TC5->COUNT16.INTFLAG.bit.OVF = 1; //Writing a 1 to INTFLAG.bit.OVF clears the interrupt so that it will run again
}


void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  SerialUSB.begin(115200);
  while (!SerialUSB);
  TcConfig(500);
  TcStart(); //starts the timer
}

void loop() {
}

MartinL

Hi tohfa_haque,

To mimic the Arduino Uno's (Atmega328P's) timers using the SAMD21, it's possible to set up the generic clock to generate a 16MHz timer clock source:

Code: [Select]
/GCLK->GENDIV.reg = GCLK_GENDIV_DIV(3) |         // Select clock divisor as 48 i.e GCLK4 output will be 48/3 = 16MHz
                     GCLK_GENDIV_ID(4);          // GCLK4

One of the SAMD21's TC timers can then be configured for 16-bit operation in Match Frequency (MFRQ) mode (as in your example), to act as the Uno's 16-bit timer 1. The TC timer's CC[0] period register replacing the Uno's ICR1/OCRA1 as the timer 1's TOP value.

A second TC timer can be set up in the same way, but with the CC[0] period register set to 0xFF, to replace the Uno's 8-bit timer 2.

Go Up