I have 2 questions about the Nano 33 IOT which really are just for my understanding...
After doing much reading and testing, I think I understand that during dual-slope PWM and in the normal case (TOP < MAX/2) that only one of the two match compares generates an actual interrupt and that depends on whether the chip has been setup for the up ramp (normal) or the down ramp. Is there any other way where TOP < MAX/2 where both match compares can generate an interrupt?
I was looking at DSCRITICAL thinking that this might solve the question above but it does not, if I understand correctly. But I didn't understand the documentation for how one would code an example using it.
Using dual slope PWM it's possible to activate interrupts at the the TOP (DSTOP), ZERO (DSBOTTOM) or BOTH (DSBOTH). As you mention, when the TOP value is less than MAX/2, the CC match compare interrupt is triggered rising timer ramp if its Most Significant Bit (MSB) is 0, and conversly on the descending ramp if the MSB is 1.
Critical dual slope PWM (DSCRITICAL) allows for non-aligned centre pulses, using CC channel pairs to control the compare match on both the rising and falling timer ramps. CC0 is paired with CC2 and CC1 with CC3.
Here's some DSCRITCAL example code, it's for the Arduino Zero so you might have to change the pins numbers for the Nano 33 IoT:
// Set-up TCC0 for Dual-Slope Critical PWM shift on D2 and D5 at 100Hz
void setup()
{
// Feed GCLK0 to TCC0 and TCC1
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0
GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 at 48MHz
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Enable the port multiplexer for the PWM channel TCC0 WO[0] on D2 and D5
PORT->Group[g_APinDescription[2].ulPort].PINCFG[g_APinDescription[2].ulPin].bit.PMUXEN = 1;
PORT->Group[g_APinDescription[5].ulPort].PINCFG[g_APinDescription[5].ulPin].bit.PMUXEN = 1;
// Connect the TCC0 timer to the port outputs - port pins are paired odd PMUO and even PMUXE
// F & E specify the timers: TCC0, TCC1 and TCC0
PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;
// Interleave TCC0 two PWM signals on to a single channel using the CC and PER circular buffers
TCC0->WAVE.reg = TCC_WAVE_POL(0xF) | // Reverse the output polarity on all TCC0 outputs
TCC_WAVE_WAVEGEN_DSCRITICAL; // Set the PWM output to dual-slope critical PWM mode
while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization
TCC0->PER.reg = 239999; // Set the frequency of the PWM on PER to 100Hz
while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
// CC0 and CC2 pair on channel 0, 50% duty-cycle
TCC0->CC[0].reg = 1; // Set the duty-cycle to 0%
while (TCC0->SYNCBUSY.bit.CC0); // Wait for synchronization
TCC0->CC[2].reg = 239998; // Set the duty-cycle to 50%
while (TCC0->SYNCBUSY.bit.CC2); // Wait for synchronization
// CC1 and CC3 pair on channel 1, 50% duty-cycle
TCC0->CC[1].reg = 120000; // Set the duty-cycle to 25%
while (TCC0->SYNCBUSY.bit.CC1); // Wait for synchronization
TCC0->CC[3].reg = 120000; // Set the duty-cycle to 25%
while (TCC0->SYNCBUSY.bit.CC3); // Wait for synchronization
TCC0->CTRLA.bit.ENABLE = 1; // Enable the TCC0 counter
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void loop() {}