PPM signal generation on a SAMD21 arduino (mkr, zero, etc...)

Hi,
I am switching from an arduino mega to arduino mkr. I need to generate a PPM signal, and I used this firmware with the Mega. However, The timer configuration and interrupts on the MKR are different and this code will not compile for a mkr board.

Is there an available code for PPM generation, or at least timer compare interrupts configuration that will work with SAMD21 based arduino?

Thanks!

I've deleted your other cross post @endrew.

Cross posting is against the rules of the forum. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend 15 minutes writing a detailed answer on this thread, without knowing that someone else already did the same in the other thread.

Repeated cross posting will result in a suspension from the forum.

In the future, please take some time to pick the forum section that best suits the topic of your question and then only post once to that forum section. This is basic forum etiquette, as explained in the sticky "How to use this forum - please read." post you will find at the top of every forum section. It contains a lot of other useful information. Please read it.

Thanks for your cooperation.

Could you please delete this post and un-delete the other one? I have posted it in the other forum since I thought it is unlikely I’ll get a reply in this one…

Sorry, and thanks.

I moved this thread to the MKR1000 forum board, where your deleted thread was posted to. In the future, if you need to have a thread moved, please just click the "Report to moderator" link and ask us to do it.

Well, if anyone is interested, I implemented a code that generates PPM signal on a mkr wifi 1010 based on the example given by @MartinL in this thread.

Thanks MartinL!

long prev;
bool pulse_state=false; // true false
int ppm[8];
byte ppm_ch=0;
int ppm_sum=0;
void setup() {
  pinMode(0, OUTPUT);
  ppm[0]=1500;
  ppm[1]=1500;
  ppm[2]=1500;
  ppm[3]=1500;
  ppm[4]=1500;
  ppm[5]=1500;
  ppm[6]=1500;
  ppm[7]=1500;
  
  // Set up the generic clock (GCLK4) used to clock timers
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz clock source by divisor 3: 48MHz/3=16MHz
                    GCLK_GENDIV_ID(4);            // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |         // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);          // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Feed GCLK4 to TC4 and TC5
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TC4 and TC5
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TC4_TC5;     // Feed the GCLK4 to TC4 and TC5
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
  
  REG_TC4_CTRLA |= TC_CTRLA_MODE_COUNT16;           // Set the counter to 8-bit mode
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);        // Wait for synchronization 

  REG_TC4_COUNT16_CC1 = 0xAA;                      // Set the TC4 CC1 register to some arbitary value
  while (TC4->COUNT8.STATUS.bit.SYNCBUSY);        // Wait for synchronization

  //NVIC_DisableIRQ(TC4_IRQn);
  //NVIC_ClearPendingIRQ(TC4_IRQn);
  NVIC_SetPriority(TC4_IRQn, 0);    // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) 
  NVIC_EnableIRQ(TC4_IRQn);         // Connect TC4 to Nested Vector Interrupt Controller (NVIC) 

  REG_TC4_INTFLAG |= TC_INTFLAG_MC1 | TC_INTFLAG_MC0 | TC_INTFLAG_OVF;        // Clear the interrupt flags
//  REG_TC4_INTENSET = TC_INTENSET_MC1 | TC_INTENSET_MC0 | TC_INTENSET_OVF;     // Enable TC4 interrupts
  REG_TC4_INTENSET = TC_INTENSET_MC1 ;     // Enable TC4 interrupts
  // REG_TC4_INTENCLR = TC_INTENCLR_MC1 | TC_INTENCLR_MC0 | TC_INTENCLR_OVF;     // Disable TC4 interrupts
  
  REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV64 |     // Set prescaler to 64, 16MHz/64 = 256kHz
                   TC_CTRLA_ENABLE;               // Enable TC4
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);        // Wait for synchronization
}

void loop() {
  ppm[0]+=100;
  ppm[1]+=100;
  ppm[2]+=100;
  ppm[3]+=100;
  ppm[4]+=100;
  if (ppm[2]>1950){
  ppm[0]=1000;
  ppm[1]=1000;
  ppm[2]=1000;
  ppm[3]=1000;
  ppm[4]=1000;
  }
  delay (500);
}
void TC4_Handler()                              // Interrupt Service Routine (ISR) for timer TC4
{     
  if (pulse_state == false)
    digitalWrite (0,HIGH);
  else
    digitalWrite (0,LOW);
  if (pulse_state == false){
    REG_TC4_COUNT16_CC1=REG_TC4_COUNT16_CC1+(400*0.74939);//3/4-1;
    pulse_state = true;
    ppm_sum+=400;
  } else if (ppm_ch<8){
    ppm_sum+=(ppm[ppm_ch]-400);
    REG_TC4_COUNT16_CC1=REG_TC4_COUNT16_CC1+((ppm[ppm_ch]-400)*0.74939);
    ppm_ch++;
    pulse_state = false;
  }else{
    int remain;
    pulse_state = false;
    ppm_ch=0;
    remain = 22000-ppm_sum;
    Serial.println(ppm_sum);
    if (remain<500)
      remain = 500;
    REG_TC4_COUNT16_CC1=REG_TC4_COUNT16_CC1+(remain*0.74939);
    ppm_sum=0;
  }
    REG_TC4_INTFLAG = TC_INTFLAG_MC1;        // Clear the MC1 interrupt flag 
}