Arduino Zero/M0 timer capture and compare

During an upload the bootloader normally activates the board's LEDs. However, some M0 boards turn on the LEDs by sourcing current to them, others by sinking current from them. Sinking current from an LED inverts the logic required to turn it on. This might explain why your board's LED is on all the time.

I upload the bootloader but the flash verifying fails anyway with this error.

Timestamp:	2021-08-26 11:27:34.238
Severity:		ERROR
ComponentId:	20000
StatusCode:	0

Verifying Flash...Failed! address=0x0000 expected=0xfc actual=0xff

It could have something to do with the bootloader protection fuse that's used to prevent the bootloader from being overwritten. I see from your fuses that the BOOTPROT is set to 16k. I'll have a look at the fuses on one of my old M0 based custom boards.

SOLUTION: set the BOOTPROT to 0, program the bootloader and then re-set it to 16K.
Now the led is fading.
Loaded the blink sketch. is working fine :slight_smile: thanks

Glad to hear that it's now working.

Sorry for the slight off topic, but the watchdog seems not enabled by default and so i cant manage it by sw. right?

The fuses should normally switch the WDT off. If it's switched on your board will keep continuously resetting and rebooting.

If you require the WDT, it can be programmed separately with software.

Sorry for annoying again @MartinL, but if i want to do some economy with timers, is possible to use TC3 for delay generation and also for generate the output pulse?
I think about to keep it in free run and when it reaches the delay time to count, it sets the output pin high and in its ISR load a new value to count that will be the actual+pulsewidth. When it reaches again the counter value it sets the output low.
In this way i do not use TCC0. What do you think? Could you suggest a code to implement?
Thanks

@ekjk Yes, it's possible by reversing the timer's output polarity, then setting the match compare for the delay time and period for the pulse width. This will cause the timer to output a 0 for the delay and a 1 for the pulse.

However, the TCC timers are much better suited to this role than the TC timers, since they offer driver control, which would pull the output back to 0, once the oneshot cycle has finished.

I'm not saying it can't be done with the TC timers, but it would require CPU intervention in an ISR, to hold the output at 0 at the end of the pulse.

There is the possibility to do that as you said with TCC instead of TC timer? Or the TCC timer shall be engaged from a TC timer as already done?

Using the TCC0 timer would free up TC3. If you'd prefer to give TC3 a try, it would free up TCC0, but at the expense of calling TC3's ISR for each and every pulse.

Anyway the timer shall call its ISR at the compare match to re-enable the interrupt event on D6 (as in the code requested to you before). So in that isr the cpu can pull down the output.

@MartinL Could you please help me to wrap that type of code (again)?
thanks

Here's an example that retriggers the TCC0 timer every second. The start of the timer's retrigger cycle is indicated on pin PA20 (D6) with a GPIO driven pulse. The timer output is on port pin PA21 (D7).

The polarity of the TCC0 is reversed so that initially, at the start of the cycle, the timer outputs a LOW that determines the delay. Upon a compare match (CC3) the timer outputs a HIGH generating the pulse. The pulse continues for the remainder duration of the timer cycle determined by the timer's period (PER). Once the oneshot pulse is complete the driver control pulls the output line low.

Here's the example code, it output a narrow pulse on D6 with the timer generating a 5ms delay, followed by a 15ms pulse:

// Generate timer TCC0 oneshot 5ms delay (low) followed by a 15ms pulse (high) on output D7 (PA21)
// Start of timer cycle indicated by a pulse on output D6 (PA20)
void setup() 
{
  PORT->Group[PORTA].DIRSET.reg = PORT_PA20;       // Set D6 as a TCC0 retrigger indicator output
  
  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(3) |          // Divide the 48MHz system clock by 3 = 16MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 4

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

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TCC0 and TCC1
                      GCLK_CLKCTRL_GEN_GCLK4 |     
                      GCLK_CLKCTRL_ID_TCC0_TCC1;  
  while (GCLK->STATUS.bit.SYNCBUSY);

  // Enable the port multiplexer on digital pin D7
  PORT->Group[PORTA].PINCFG[21].bit.PMUXEN = 1;
  
  // Set-up the pin as an TCC0 PWM output on D7
  PORT->Group[PORTA].PMUX[21 >> 1].reg |= PORT_PMUX_PMUXO_F;
  
  TCC0->WAVE.reg = TCC_WAVE_POL3 |                  // Reverse the polarity on channel 3 
                   TCC_WAVE_WAVEGEN_NPWM;           // Set the TCC0 timer counter to normal PWM mode (NPWM)
  while (TCC0->SYNCBUSY.bit.WAVE);                  // Wait for synchronization

  TCC0->PER.reg = 19999;                            // Set the timer delay plus pulse to 20ms
  while (TCC0->SYNCBUSY.bit.PER);                   // Wait for synchronization

  TCC0->CC[3].reg = 5000;                           // Set CC3 duty-cycle to 5ms pusle width
  while (TCC0->SYNCBUSY.bit.CC3);                   // Wait for synchronization

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;        // Enable oneshot operation
  while (TCC0->SYNCBUSY.bit.CTRLB);                 // Wait for synchronization
  
  TCC0->DRVCTRL.reg |= TCC_DRVCTRL_NRE7;            // Set the non-recoverable state output to 0 when inactive
  
  TCC0->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |     // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;      // Set prescaler to 16, 16MHz/16 = 1MHz
                    
  TCC0->CTRLA.bit.ENABLE = 1;                       // Enable timer TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);                // Wait for synchronization
}

void loop() 
{
  PORT->Group[PORTA].OUTSET.reg = PORT_PA20;             // Generate pulse on D6 to indicate the start of the TCC0 retrigger
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;       // Retrigger ONESHOT operation on TCC0
  while (TCC0->SYNCBUSY.bit.CTRLB);                      // Wait for synchronization
  PORT->Group[PORTA].OUTCLR.reg = PORT_PA20;              
  delay(1000);                                           // Wait 1 second
}

@ekjk Looking into things a bit further, implementing a similar scheme for the TC timer is more problematic, since it lacks the TCC's driver control functionality.

This means that with the TC timer output inverted, (it doesn't have the TCC's polarity option), it's not possible to drive the timer output low at the end of the timer cycle.

HI @MartinL i have tried your sketch of post 33 but is not working. No output pulses are generated. I tried to comment out the detach and attach of input D6 but this change nothing.
Any suggestions?
thanks

Hi @ekjk

My apologies, looking back at my post (#33), I didn't explain it very well.

In this example code, both D6 and D7 are outputs. (This sketch doesn't include any pulse width and period code and just shows how TCC0 can be used to combine both delay and pulse generation).

D6 generates a narrow pulse. This acts as a marker that indicates the start of the TCC0 timer cycle and can be used to trigger an oscilloscope.

D7 is the combined TCC0 delay and pulse output that occurs after D6, in this case it will generate a 5ms low for the delay, followed by a 15ms high.

In your pulse width and period sketch, the TC3 and TCC0 code can be removed and replaced with this TCC0 example code instead. TCC0 being software retriggered in the TC4_Handler() ISR function.

Hi @MartinL ,
2 problems.

  1. i have tried the sketch to disable and enable interrupt on D6 (post 26 and 29). I have integrated it in my working code but now is not working anymore.
    Here the code updated
// Setup timer TC4/TC5 to trigger on input event and set time delay for TCC0 output pulse, (TCC1 test output)
// Input: PA20 (D6), Pulse Output: PA21 (D7)
volatile boolean periodComplete;
volatile uint32_t isrPeriod;
volatile uint32_t isrPulsewidth;
uint32_t period;
uint32_t pulsewidth;

void setup()
{
  // Native Serial Port ////////////////////////////////////////////////////////////////////////////////

  SerialUSB.begin(115200);                         // Initialise the native serial port
 // while(!SerialUSB);                               // Wait for the console to open
  
  // Generic Clocks (GCLK) //////////////////////////////////////////////////////////////////////////////
  
  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(3) |          // Divide the 48MHz system clock by 3 = 16MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 5 

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

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TCC0 and TCC1
                      GCLK_CLKCTRL_GEN_GCLK4 |     
                      GCLK_CLKCTRL_ID_TCC0_TCC1;
  
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TCC2 and TC3
                      GCLK_CLKCTRL_GEN_GCLK4 |    
                      GCLK_CLKCTRL_ID_TCC2_TC3; 
 
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TC4 and TCC5
                      GCLK_CLKCTRL_GEN_GCLK4 |    
                      GCLK_CLKCTRL_ID_TC4_TC5;    

  // Port Multiplexing //////////////////////////////////////////////////////////////////////////////////
  
  // Enable the port multiplexer on PA20 (D6)(Input) and PA21(D7)(Pulse output)
  PORT->Group[PORTA].PINCFG[20].bit.PMUXEN = 1;
  PORT->Group[PORTA].PINCFG[21].bit.PMUXEN = 1;
  
  // Set-up the pin multiplexers
  PORT->Group[PORTA].PMUX[20 >> 1].reg |= PORT_PMUX_PMUXE_A;
  PORT->Group[PORTA].PMUX[21 >> 1].reg |= PORT_PMUX_PMUXO_F;

  // External Interrupt Controller (EIC) (Input) ///////////////////////////////////////////////////////////
  
  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO4;               // Enable event output on external interrupt 4
  EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;          // Set event detecting a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT4;              // Clear the interrupt flag on channel 4
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                      // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);                      // Wait for synchronization

  // Event System /////////////////////////////////////////////////////////////////////////////////////////
  
  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;                                   // Switch on the event system peripheral

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |                                // Attach the event user (receiver) to channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);                // Set the event user (receiver) as timer TC4 event
  
  EVSYS->USER.reg = EVSYS_USER_CHANNEL(2) |                                // Attach the event user (receiver) to channel 1 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_0);              // Set the event user (receiver) as timer TCC0, event 0

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) |    // Set event generator (sender) as external interrupt 4
                       EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0
  
  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_TC3_OVF) |         // Set event generator (sender) as TC3 overflow
                       EVSYS_CHANNEL_CHANNEL(1);                           // Attach the generator (sender) to channel 1

  TC3->COUNT16.EVCTRL.reg = TC_EVCTRL_OVFEO;                // Output event on overflow                     
                           
  TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |                // Enable the TC event input
                            //TC_EVCTRL_TCINV |             // Invert the event input 
                            TC_EVCTRL_EVACT_PPW;            // Set up the timer for capture: CC0 period, CC1 pulsewidth
  
  TCC0->EVCTRL.reg = //TCC_EVCTRL_TCEI1 |                     // Enable the TCC event 1 input
                     TCC_EVCTRL_TCEI0 |                     // Enable the TCC event 0 input
                     //TCC_EVCTRL_TCINV1 |                    // Invert the event 1 input
                     //TCC_EVCTRL_TCINV0 |                    // Invert the event 0 input                     
                     TCC_EVCTRL_EVACT0_RETRIGGER;           // Set event 0 to count the incoming events




  // Timer TC4 (Period Timer) //////////////////////////////////////////////////////////////////////////////////

  TC4->COUNT32.CTRLC.reg = //TC_CTRLC_CPTEN1 |               // Enable capture on CC1
                           TC_CTRLC_CPTEN0;                // Enable capture on CC0
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);           // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)
 
  TC4->COUNT32.INTENSET.reg = //TC_INTENSET_MC1 |            // Enable compare channel 1 (CC1) interrupts
                              TC_INTENSET_MC0;             // Enable compare channel 0 (CC0) interrupts
  
  TC4->COUNT32.CTRLA.reg = TC_CTRLA_PRESCSYNC_PRESC |      // Reload timer on the next prescaler clock
                           TC_CTRLA_PRESCALER_DIV16 |      // Set prescaler to 16, 16MHz/16 = 1MHz
                           TC_CTRLA_WAVEGEN_NFRQ |         // Set TC4 to normal frequency mode (NFRQ)
                           TC_CTRLA_MODE_COUNT32;          // Set TC4/TC5 to 32-bit timer mode
                          
  TC4->COUNT32.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  // Timer TC3 (Delay Timer) //////////////////////////////////////////////////////////////////////////////////

  TC3->COUNT16.CC[0].reg = 100;                           // Set the delay to 100us
  while (TC3->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization
  
  TC3->COUNT16.CTRLBSET.reg = TC_CTRLBSET_ONESHOT;         // Enable oneshot operation
  while (TC3->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization
  
  TC3->COUNT16.CTRLA.reg = TC_CTRLA_PRESCSYNC_PRESC |      // Reload timer on the next prescaler clock
                           TC_CTRLA_PRESCALER_DIV16 |      // Set prescaler to 16, 16MHz/16 = 1MHz
                           TC_CTRLA_WAVEGEN_MFRQ |         // Set TC3 to match frequency mode (MFRQ)
                           TC_CTRLA_MODE_COUNT16;          // Set TC3 to 16-bit timer mode
  
  TC3->COUNT16.CTRLA.bit.ENABLE = 1;                       // Enable TC3
  while (TC3->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  // Timer TCC0 (Pulse Output) /////////////////////////////////////////////////////////////////////////////////

  TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;             // Set the TCC0 timer counter to normal PWM mode (NPWM)
  while (TCC0->SYNCBUSY.bit.WAVE);                    // Wait for synchronization

  TCC0->CC[3].reg = 200;                             // Set pulse width to 200us on channel 3
  while (TCC0->SYNCBUSY.bit.CC3);     //cc1                // Wait for synchronization

  TCC0->PER.reg = 0xFFFFFF;                           // Set period to the timer's maximum value (2^24)
  while (TCC0->SYNCBUSY.bit.PER);                     // Wait for synchronization

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;          // Enable oneshot operation
  while (TCC0->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  TCC0->DRVCTRL.reg |= TCC_DRVCTRL_NRE7;   //1           // Set the non-recoverable state output to 0 when inactive
                                                                                      
  TCC0->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |       // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;        // Set prescaler to 16, 16MHz/16 = 1MHz

  NVIC_SetPriority(TCC0_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TCC0 to 0 (highest)
  NVIC_EnableIRQ(TCC0_IRQn);           // Connect the TCC0 timer to the Nested Vector Interrupt Controller (NVIC)
 
  TCC0->INTENSET.reg = TCC_INTENSET_MC3;             // Enable match compare channel 3 (MC3) interrupts
  
  TCC0->CTRLA.bit.ENABLE = 1;                         // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization
}

void loop() 
{
  if (periodComplete)                             // Check if the period is complete
  {
    period = isrPeriod;                  
    SerialUSB.print("P us: ");
    SerialUSB.println(period);
    periodComplete = false;                       // Start a new period
  }
}

void TC4_Handler()                                // Interrupt Service Routine (ISR) for timer TC4
{    
  
  // Check for match counter 0 (MC0) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC0)            
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x18);      // Offset address of the CC0 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPeriod = TC4->COUNT32.CC[0].reg;                    // Copy the period  
    periodComplete = true;                                 // Indicate that the period is complete

    EIC->CONFIG[0].bit.SENSE4 = 0;           // Switch off interrupts on D6
    
    /////////////////////////////////////////////////////////////////////////////////////////////
    
    // Calculate the output pulse delay here... 

      TC3->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER; // Retrigger ONESHOT operation on TC3, pulse automatically output on TCC0 after delay
      //TC3->COUNT16.CTRLA.bit.ENABLE = 1;
      
      TC3->COUNT16.CC[0].reg = 100;                       // Set the delay in us
      while (TC3->COUNT16.STATUS.bit.SYNCBUSY);            // Wait for synchronization
    }

}

void TCC0_Handler()                                 // Interrupt Service Routine (ISR) for timer TCC0
{     
  if (TCC0->INTFLAG.bit.MC3)                        // Check for match counter 3 (MC3) interrupt
  {   
    TCC0->INTFLAG.bit.MC3 = 1;                      // Clear the interrupt flag
    EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;   // Set event detecting a HIGH level
  }
}
  1. i have merged the code you wrote to add a second delay timer and pulse generator (on D8). I think in your last reply you mention the last code you have posted but i meant the code you posted in post 31.
    Here the code merged with the original one working that is now not working anymore.
// Setup timer TC4/TC5 to trigger on input event and set time delay for TCC0 output pulse, (TCC1 test output)
// Input: PA20 (D6), Pulse Output1: PA21 (D7) Pulse Output2: PA06 (D8)
volatile boolean periodComplete;
volatile uint32_t isrPeriod;
volatile uint32_t isrPulsewidth;
uint32_t period;
uint32_t pulsewidth;

void setup()
{
  // Native Serial Port ////////////////////////////////////////////////////////////////////////////////

  SerialUSB.begin(115200);                         // Initialise the native serial port
 // while(!SerialUSB);                               // Wait for the console to open
  
  // Generic Clocks (GCLK) //////////////////////////////////////////////////////////////////////////////
  
  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(3) |          // Divide the 48MHz system clock by 3 = 16MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 5 

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

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TCC0 and TCC1
                      GCLK_CLKCTRL_GEN_GCLK4 |     
                      GCLK_CLKCTRL_ID_TCC0_TCC1;
  
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TCC2 and TC3
                      GCLK_CLKCTRL_GEN_GCLK4 |    
                      GCLK_CLKCTRL_ID_TCC2_TC3; 
 
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TC4 and TCC5
                      GCLK_CLKCTRL_GEN_GCLK4 |    
                      GCLK_CLKCTRL_ID_TC4_TC5;    

  // Port Multiplexing //////////////////////////////////////////////////////////////////////////////////
  
  // Enable the port multiplexer on PA20 (D6)(Input) and PA21(D7)(Pulse output) PA06 (D8) (second Pulse outptu)
  PORT->Group[PORTA].PINCFG[20].bit.PMUXEN = 1;
  PORT->Group[PORTA].PINCFG[21].bit.PMUXEN = 1;
  PORT->Group[PORTA].PINCFG[6].bit.PMUXEN = 1;                   
  
  // Set-up the pin multiplexers
  PORT->Group[PORTA].PMUX[20 >> 1].reg |= PORT_PMUX_PMUXE_A;
  PORT->Group[PORTA].PMUX[21 >> 1].reg |= PORT_PMUX_PMUXO_F;
  PORT->Group[PORTA].PMUX[6 >> 1].reg |= PORT_PMUX_PMUXE_E;     // Configure PA06 as a TCC1 timer output on channel 0
  
  // External Interrupt Controller (EIC) (Input) ///////////////////////////////////////////////////////////
  
  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO4;               // Enable event output on external interrupt 4
  EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;          // Set event detecting a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT4;              // Clear the interrupt flag on channel 4
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                      // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);                      // Wait for synchronization

  // Event System /////////////////////////////////////////////////////////////////////////////////////////
  
  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;                                   // Switch on the event system peripheral

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |                                // Attach the event user (receiver) to channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);                // Set the event user (receiver) as timer TC4 event
  
  EVSYS->USER.reg = EVSYS_USER_CHANNEL(2) |                                // Attach the event user (receiver) to channel 1 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_0);              // Set the event user (receiver) as timer TCC0, event 0

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(3) |                                // Attach the event user (receiver) to channel 2 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TCC1_EV_0);              // Set the event user (receiver) as timer TCC1, event 0
                    
  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) |    // Set event generator (sender) as external interrupt 4
                       EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0
  
  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_TC3_OVF) |         // Set event generator (sender) as TC3 overflow
                       EVSYS_CHANNEL_CHANNEL(1);                           // Attach the generator (sender) to channel 1

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_TCC2_MCX_0) |      // Set event generator (sender) as TCC2 match compare on channel 2
                       EVSYS_CHANNEL_CHANNEL(2);                           // Attach the generator (sender) to channel 2

  TCC2->EVCTRL.reg = TCC_EVCTRL_MCEO0;                      // Output event on match compare on channel 0
  
  TC3->COUNT16.EVCTRL.reg = TC_EVCTRL_OVFEO;                // Output event on overflow                     
                           
  TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |                // Enable the TC event input
                            //TC_EVCTRL_TCINV |             // Invert the event input 
                            TC_EVCTRL_EVACT_PPW;            // Set up the timer for capture: CC0 period, CC1 pulsewidth
  
  TCC0->EVCTRL.reg = //TCC_EVCTRL_TCEI1 |                     // Enable the TCC event 1 input
                     TCC_EVCTRL_TCEI0 |                     // Enable the TCC event 0 input
                     //TCC_EVCTRL_TCINV1 |                    // Invert the event 1 input
                     //TCC_EVCTRL_TCINV0 |                    // Invert the event 0 input                     
                     TCC_EVCTRL_EVACT0_RETRIGGER;           // Set event 0 to count the incoming events




  // Timer TC4 (Period Timer) //////////////////////////////////////////////////////////////////////////////////

  TC4->COUNT32.CTRLC.reg = //TC_CTRLC_CPTEN1 |               // Enable capture on CC1
                           TC_CTRLC_CPTEN0;                // Enable capture on CC0
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);           // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)
 
  TC4->COUNT32.INTENSET.reg = //TC_INTENSET_MC1 |            // Enable compare channel 1 (CC1) interrupts
                              TC_INTENSET_MC0;             // Enable compare channel 0 (CC0) interrupts
  
  TC4->COUNT32.CTRLA.reg = TC_CTRLA_PRESCSYNC_PRESC |      // Reload timer on the next prescaler clock
                           TC_CTRLA_PRESCALER_DIV16 |      // Set prescaler to 16, 16MHz/16 = 1MHz
                           TC_CTRLA_WAVEGEN_NFRQ |         // Set TC4 to normal frequency mode (NFRQ)
                           TC_CTRLA_MODE_COUNT32;          // Set TC4/TC5 to 32-bit timer mode
                          
  TC4->COUNT32.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  // Timer TC3 (Delay Timer) //////////////////////////////////////////////////////////////////////////////////

  TC3->COUNT16.CC[0].reg = 100;                           // Set the delay to 100us
  while (TC3->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization
  
  TC3->COUNT16.CTRLBSET.reg = TC_CTRLBSET_ONESHOT;         // Enable oneshot operation
  while (TC3->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization
  
  TC3->COUNT16.CTRLA.reg = TC_CTRLA_PRESCSYNC_PRESC |      // Reload timer on the next prescaler clock
                           TC_CTRLA_PRESCALER_DIV16 |      // Set prescaler to 16, 16MHz/16 = 1MHz
                           TC_CTRLA_WAVEGEN_MFRQ |         // Set TC3 to match frequency mode (MFRQ)
                           TC_CTRLA_MODE_COUNT16;          // Set TC3 to 16-bit timer mode
  
  TC3->COUNT16.CTRLA.bit.ENABLE = 1;                       // Enable TC3
  while (TC3->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  // Timer TCC0 (Pulse Output) /////////////////////////////////////////////////////////////////////////////////

  NVIC_SetPriority(TCC0_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TCC0 to 0 (highest)
  NVIC_EnableIRQ(TCC0_IRQn);           // Connect the TCC0 timer to the Nested Vector Interrupt Controller (NVIC)

  TCC0->INTENSET.reg = TCC_INTENSET_MC3;             // Enable match compare channel 3 (MC3) interrupts
  
  TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;             // Set the TCC0 timer counter to normal PWM mode (NPWM)
  while (TCC0->SYNCBUSY.bit.WAVE);                    // Wait for synchronization

  TCC0->CC[3].reg = 200;                             // Set pulse width to 200us on channel 3
  while (TCC0->SYNCBUSY.bit.CC3);                     // Wait for synchronization

  TCC0->PER.reg = 0xFFFFFF;                           // Set period to the timer's maximum value (2^24)
  while (TCC0->SYNCBUSY.bit.PER);                     // Wait for synchronization

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;          // Enable oneshot operation
  while (TCC0->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  TCC0->DRVCTRL.reg |= TCC_DRVCTRL_NRE7;              // Set the non-recoverable state output to 0 when inactive
                                                                                      
  TCC0->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |       // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;        // Set prescaler to 16, 16MHz/16 = 1MHz
  
  TCC0->CTRLA.bit.ENABLE = 1;                         // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization



  // Timer TCC2 (Delay Timer) /////////////////////////////////////////////////////////////////////////////////

  TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NFRQ;             // Set the TCC2 timer counter to normal frequency mode (NFRQ)
  while (TCC2->SYNCBUSY.bit.WAVE);                    // Wait for synchronization
  
  TCC2->PER.reg = 0xFFFF;                             // Set period to the timer's maximum value (2^16)
  while (TCC2->SYNCBUSY.bit.PER);                     // Wait for synchronization
  
  TCC2->CC[0].reg = 100;                              // Set the delay to 1ms
  while (TCC2->SYNCBUSY.bit.CC0);                     // Wait for synchronization
  
  TCC2->CTRLBSET.reg = TC_CTRLBSET_ONESHOT;           // Enable oneshot operation
  while (TCC2->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization
  
  TCC2->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |       // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;        // Set prescaler to 16, 16MHz/16 = 1MHz                         
                           
  TCC2->CTRLA.bit.ENABLE = 1;                         // Enable TCC2
  while (TCC2->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization

// Timer TCC1 (Pulse Output) /////////////////////////////////////////////////////////////////////////////////

  TCC1->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;             // Set the TCC1 timer counter to normal PWM mode (NPWM)
  while (TCC1->SYNCBUSY.bit.WAVE);                    // Wait for synchronization

  TCC1->CC[0].reg = 200;                              // Set pulse width to 1.5ms on channel 0
  while (TCC1->SYNCBUSY.bit.CC0);                     // Wait for synchronization

  TCC1->PER.reg = 0xFFFFFF;                           // Set period to the timer's maximum value (2^24)
  while (TCC1->SYNCBUSY.bit.PER);                     // Wait for synchronization

  TCC1->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;          // Enable oneshot operation
  while (TCC1->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  TCC1->DRVCTRL.reg |= TCC_DRVCTRL_NRE0;              // Set the non-recoverable state output to 0 when inactive
                                                                                      
  TCC1->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |       // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;        // Set prescaler to 16, 16MHz/16 = 1MHz
  
  TCC1->CTRLA.bit.ENABLE = 1;                         // Enable TCC1
  while (TCC1->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization
  
}

void loop() 
{
  if (periodComplete)                             // Check if the period is complete
  {
    period = isrPeriod;                  
    SerialUSB.print("P us: ");
    SerialUSB.println(period);
    periodComplete = false;                       // Start a new period
  }
}

void TC4_Handler()                                // Interrupt Service Routine (ISR) for timer TC4
{    
  
  // Check for match counter 0 (MC0) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC0)            
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x18);      // Offset address of the CC0 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPeriod = TC4->COUNT32.CC[0].reg;                    // Copy the period  
    periodComplete = true;                                 // Indicate that the period is complete 
    
    /////////////////////////////////////////////////////////////////////////////////////////////
    
    // Calculate the output pulse delay here... 

      TC3->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER; // Retrigger ONESHOT operation on TC3, pulse automatically output on TCC0 after delay
      //TC3->COUNT16.CTRLA.bit.ENABLE = 1;
      
      TC3->COUNT16.CC[0].reg = 100;                       // Set the delay in us
      while (TC3->COUNT16.STATUS.bit.SYNCBUSY);            // Wait for synchronization

      TCC2->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;       // Retrigger ONESHOT operation on TCC2, pulse automatically output on TCC0 after delay
      while (TCC2->SYNCBUSY.bit.CTRLB);                      // Wait for synchronization
    }

}

Thanks

Hi @ekjk

I've merged the TCC0 and TCC1 code that frees up timers TCC2 and TC3.

Here's the code with the (TC4) input on D6, (TCC0) output on D7 and (TCC1) output on D8:

// Setup timer TC4/TC5 to trigger on input event and set time delay and pulse time for TCC0 output pulse, (TCC1 test output)
// Input: PA20 (D6), Pulse Output1: PA21 (D7) Pulse Output2: PA06 (D8)

volatile boolean periodComplete;
volatile uint32_t isrPeriod;
uint32_t period;

void setup()
{
  // Native Serial Port ////////////////////////////////////////////////////////////////////////////////

  SerialUSB.begin(115200);                         // Initialise the native serial port
  while(!SerialUSB);                               // Wait for the console to open
  
  // Generic Clocks (GCLK) //////////////////////////////////////////////////////////////////////////////
  
  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(3) |          // Divide the 48MHz system clock by 3 = 16MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 5 

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

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TCC0 and TCC1
                      GCLK_CLKCTRL_GEN_GCLK4 |     
                      GCLK_CLKCTRL_ID_TCC0_TCC1;
 
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TC4 and TCC5
                      GCLK_CLKCTRL_GEN_GCLK4 |    
                      GCLK_CLKCTRL_ID_TC4_TC5;    

  // Port Multiplexing //////////////////////////////////////////////////////////////////////////////////
  
  // Enable the port multiplexer on PA20 (D6)(Input) and PA21(D7)(Pulse output) PA06 (D8) (second Pulse outptu)
  PORT->Group[PORTA].PINCFG[20].bit.PMUXEN = 1;
  PORT->Group[PORTA].PINCFG[21].bit.PMUXEN = 1;
  PORT->Group[PORTA].PINCFG[6].bit.PMUXEN = 1;                   
  
  // Set-up the pin multiplexers
  PORT->Group[PORTA].PMUX[20 >> 1].reg |= PORT_PMUX_PMUXE_A;
  PORT->Group[PORTA].PMUX[21 >> 1].reg |= PORT_PMUX_PMUXO_F;
  PORT->Group[PORTA].PMUX[6 >> 1].reg |= PORT_PMUX_PMUXE_E;     // Configure PA06 as a TCC1 timer output on channel 0
  
  // External Interrupt Controller (EIC) (Input) ///////////////////////////////////////////////////////////
  
  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO4;               // Enable event output on external interrupt 4
  EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;          // Set event detecting a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT4;              // Clear the interrupt flag on channel 4
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                      // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);                      // Wait for synchronization

  // Event System /////////////////////////////////////////////////////////////////////////////////////////
  
  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;                                   // Switch on the event system peripheral

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |                                // Attach the event user (receiver) to channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);                // Set the event user (receiver) as timer TC4 event
                    
  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) |    // Set event generator (sender) as external interrupt 4
                       EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0              
                           
  TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |                               // Enable the TC event input
                            //TC_EVCTRL_TCINV |                            // Invert the event input 
                            TC_EVCTRL_EVACT_PPW;                           // Set up the timer for capture: CC0 period, CC1 pulsewidth
  
  // Timer TC4 (Period Timer) //////////////////////////////////////////////////////////////////////////////////

  TC4->COUNT32.CTRLC.reg = //TC_CTRLC_CPTEN1 |               // Enable capture on CC1
                           TC_CTRLC_CPTEN0;                // Enable capture on CC0
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);           // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)
 
  TC4->COUNT32.INTENSET.reg = //TC_INTENSET_MC1 |            // Enable compare channel 1 (CC1) interrupts
                              TC_INTENSET_MC0;             // Enable compare channel 0 (CC0) interrupts
  
  TC4->COUNT32.CTRLA.reg = TC_CTRLA_PRESCSYNC_PRESC |      // Reload timer on the next prescaler clock
                           TC_CTRLA_PRESCALER_DIV16 |      // Set prescaler to 16, 16MHz/16 = 1MHz
                           TC_CTRLA_WAVEGEN_NFRQ |         // Set TC4 to normal frequency mode (NFRQ)
                           TC_CTRLA_MODE_COUNT32;          // Set TC4/TC5 to 32-bit timer mode
                          
  TC4->COUNT32.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  // Timer TCC0 (Delay and Pulse Output) //////////////////////////////////////////////////////////////////////

  //NVIC_SetPriority(TCC0_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TCC0 to 0 (highest)
  //NVIC_EnableIRQ(TCC0_IRQn);           // Connect the TCC0 timer to the Nested Vector Interrupt Controller (NVIC)

  //TCC0->INTENSET.reg = TCC_INTENSET_MC3;              // Enable match compare channel 3 (MC3) interrupts
  
  TCC0->WAVE.reg = TCC_WAVE_POL3 |                    // Reverse the polarity on channel 3 
                   TCC_WAVE_WAVEGEN_NPWM;             // Set the TCC0 timer counter to normal PWM mode (NPWM)
  while (TCC0->SYNCBUSY.bit.WAVE);                    // Wait for synchronization

  TCC0->CC[3].reg = 200;                              // Set pulse width to 200us on channel 3
  while (TCC0->SYNCBUSY.bit.CC3);                     // Wait for synchronization

  TCC0->PER.reg = 800;                                // Set period to delay + pulse width: 800us - 200us = 600us pulse width
  while (TCC0->SYNCBUSY.bit.PER);                     // Wait for synchronization

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;          // Enable oneshot operation
  while (TCC0->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  TCC0->DRVCTRL.reg |= TCC_DRVCTRL_NRE7;              // Set the non-recoverable state output to 0 when inactive
                                                                                      
  TCC0->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |       // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;        // Set prescaler to 16, 16MHz/16 = 1MHz
  
  TCC0->CTRLA.bit.ENABLE = 1;                         // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization

// Timer TCC1 (Delay and Pulse Output) ///////////////////////////////////////////////////////////////////////

  TCC1->WAVE.reg = TCC_WAVE_POL0 |                    // Reverse the polarity on channel 0 
                   TCC_WAVE_WAVEGEN_NPWM;             // Set the TCC1 timer counter to normal PWM mode (NPWM)
  while (TCC1->SYNCBUSY.bit.WAVE);                    // Wait for synchronization

  TCC1->CC[0].reg = 400;                              // Set pulse width to 400us on channel 0
  while (TCC1->SYNCBUSY.bit.CC0);                     // Wait for synchronization

  TCC1->PER.reg = 800;                                // Set period to delay + pulse width: 800us - 400us = 400us pulse width
  while (TCC1->SYNCBUSY.bit.PER);                     // Wait for synchronization

  TCC1->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;          // Enable oneshot operation
  while (TCC1->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  TCC1->DRVCTRL.reg |= TCC_DRVCTRL_NRE0;              // Set the non-recoverable state output to 0 when inactive
                                                                                      
  TCC1->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC |       // Reload timer on the next prescaler clock
                    TCC_CTRLA_PRESCALER_DIV16;        // Set prescaler to 16, 16MHz/16 = 1MHz
  
  TCC1->CTRLA.bit.ENABLE = 1;                         // Enable TCC1
  while (TCC1->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization
}

void loop() 
{
  if (periodComplete)                                 // Check if the period is complete
  {
    noInterrupts();                                   // Turn off interrupts
    period = isrPeriod;                               // Copy the ISR period to the loop() period variable
    interrupts();                                     // Turn on interrupts                  
    SerialUSB.print(F("P us: "));                     // Display the new results  
    SerialUSB.println(period);
    periodComplete = false;                           // Start a new period
  }
}

void TC4_Handler()                                    // Interrupt Service Routine (ISR) for timer TC4
{    
  // Check for match counter 0 (MC0) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC0)            
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |      // Enable a read request
                               TC_READREQ_ADDR(0x18); // Offset address of the CC0 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);         // Wait for (read) synchronization
    isrPeriod = TC4->COUNT32.CC[0].reg;               // Copy the period  
    periodComplete = true;                            // Indicate that the period is complete 
    
    /////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Calculate the output pulse delay here... 
    //
    /////////////////////////////////////////////////////////////////////////////////////////////

    TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;       // Retrigger ONESHOT operation on TCC0, timer to output delay and pulse
    while (TCC0->SYNCBUSY.bit.CTRLB);                      // Wait for synchronization

    TCC1->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;       // Retrigger ONESHOT operation on TCC1, timer to output delay and pulse
    while (TCC1->SYNCBUSY.bit.CTRLB);                      // Wait for synchronization
  }
}

Here's the result on my scope. My Arduino Due input signal D6 (yellow) showing the rising edge of a 1.5ms pulse every 50Hz (20ms) at the end of the last period. The TCC0 output D7 (light blue) with a 200us delay followed by a 600us pulse. The TCC1 output D8 (purple) with a 400us delay followed by a 400us pulse.

Very nice job @MartinL , thanks a lot.
Remains only the issue about detach and attach the D6 input event. I will try to merge the code of it in your last sketch and let you now.
thanks :slight_smile: