PWM RAMP2 Operation

Hi darkhawk,

How would I go about fixing this?

The reason why RAMP2 operation it's not working on these pins, is that for digital pins 11 and 13 you have to use the TCC2 timer on channels 0 (WO[0]) and 1 (WO[1]):

// Output 50Hz using timer TCC2 interleaved PWM outputs on D11 and D13 (RAMP2 Operation)
void setup()
{
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(3) |          // 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

  // Enable the port multiplexer for the digital pins D11 and D13
  PORT->Group[g_APinDescription[11].ulPort].PINCFG[g_APinDescription[11].ulPin].bit.PMUXEN = 1;       
  PORT->Group[g_APinDescription[13].ulPort].PINCFG[g_APinDescription[13].ulPin].bit.PMUXEN = 1;    
    
  // Connect the TCC2 timer to the port output D11 and D13 - port pins are paired odd PMUXO and even PMUXE
  // Peripherals E & F specify the timers: TCC2, TCC1 and TCC2
  PORT->Group[g_APinDescription[11].ulPort].PMUX[g_APinDescription[11].ulPin >> 1].reg = PORT_PMUX_PMUXO_E | PORT_PMUX_PMUXE_E;
  
  // Feed GCLK4 to TCC2 and TC3
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC2 and TC3
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC2_TC3;    // Feed GCLK4 to TCC2 and TC3
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Normal (single slope) PWM operation: timers countinuously count up to PER register value and then is reset to 0
  REG_TCC2_WAVE |= /*TCC_WAVE_CIPEREN |*/         // Set up circular PER/PERB buffer for inteleaved waveform frequency
    TCC_WAVE_RAMP_RAMP2 |                         // Set up RAMP2 operation to interleave channels CC0 and CC1
    TCC_WAVE_WAVEGEN_NPWM/* |                       // Setup single slope (normal) PWM on TCC2
    TCC_WAVE_POL0 |                               // Reverse the polarity of channel CC0
    TCC_WAVE_POL1*/;                                // Reverse the polarity of channel CC1
  while (TCC2->SYNCBUSY.bit.WAVE);                // Wait for synchronization

  // Invert the drivers on TCC2/WO[0] (channel 0) and TCC2/WO[1] (channel 1)
  //REG_TCC2_DRVCTRL |= TCC_DRVCTRL_INVEN0 |      // Invert the driver on D2/D4
  //                    TCC_DRVCTRL_INVEN1;       // Invert the driver on D3
  
  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the frequency of the PWM operation:
  // Formula: (GCLK_FREQUENCY / (TIMER_PRESCALER * PWM_FREQUENCY) - 1) / 2
  // (16MHz / (16 * 50) - 1) / 2 = 9999
  REG_TCC2_PER = 9999;                            // Set the frequency of the PWM on TCC2 to 50Hz
  while(TCC2->SYNCBUSY.bit.PER);                  // Wait for synchronization
 
  // Set the PWM signal to output 50% duty cycle on D2/D4
  REG_TCC2_CCB0 = 9999;                           // TCC2 CCB0 - on output on D2/D4 
  while(TCC2->SYNCBUSY.bit.CCB0);                 // Wait for synchronization

  // Set the PWM signal to output 25% duty cycle on D3
  REG_TCC2_CCB1 = 4999;                           // TCC2 CCB1 - on output on D3 
  while(TCC2->SYNCBUSY.bit.CCB1);                 // Wait for synchronization
 
  // Divide the 16MHz signal by 16 giving a 1MHz (1.0us) TCC2 timer tick and enable the outputs
  REG_TCC2_CTRLA |= TCC_CTRLA_PRESCALER_DIV16 |   // Divide GCLK4 by 16
                    TCC_CTRLA_ENABLE;             // Enable the TCC2 output
  while (TCC2->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
  delay(2000);                                    // Wait for 2 seconds 
}

void loop(){    
  // Test the PWM outputs
  
  // Using the buffered CC0B and CCB1 registers allows the outputs to be changed on the next timer cycle
  // This prevents glitches that would occur with an instantaneous change using the CC0 and CC1 registers directly
  
  // Change the duty cycle to 25% on D2/D4 using the CCB0 buffered register
  REG_TCC2_CCB0 = 4999;                           // Load the CCB0 register with 25% of the PERB value
  while(TCC2->SYNCBUSY.bit.CCB0);                 // Wait for synchronization
  delay(2000);                                    // Wait for 2 seconds

  // Change the duty cycle to 37.5% on D3 using the CCB1 buffered register
  REG_TCC2_CCB1 = 7499;                           // Load the CCB1 register with 75% of the PERB value
  while(TCC2->SYNCBUSY.bit.CCB1);                 // Wait for synchronization
  delay(2000);                                    // Wait for 2 seconds
  
  // Change the duty cycle to 37.5% on D2/D4 using the CCB0 buffered register
  REG_TCC2_CCB0 = 7499;                          // Load the CCB0 register with 75% of the PERB value
  while(TCC2->SYNCBUSY.bit.CCB0);                 // Wait for synchronization
  delay(2000);                                    // Wait for 2 seconds

  // Change the duty cycle to 25% on D3 using the CCB1 buffered register
  REG_TCC2_CCB1 = 4999;                          // Load the CCB1 register with 50% of the PERB value
  while(TCC2->SYNCBUSY.bit.CCB1);                 // Wait for synchronization
  delay(2000);                                    // Wait for 2 seconds
}