For the purpose of learning how the pin multiplexing register works I merged a modified version of one of Martin's PWM examples along with westfw's PinMux utility. The code compiles fine but I am not seeing the outputs I was expecting. If my code is correct, I should be seeing a PWM signal on all of the digital pins expect D8 and D9 (They are not capable of connecting to TCC0).
The problem is that I am only seeing the PWM on D0, D7, D12 and D13. The only common thread I see is that D0 and D12 are listed as TCC0/WO[3] while D7 and D13 are TCC0/WO[7].
Any ideas on why the other digital pins are not outputting the PWM signal despite being tied to TCC0?
#include <Wire.h>
#include <SPI.h>
#include "SAMD_pinmux_report.h"
#define mySerial SerialUSB
static char buffer[80];
void setup() {
mySerial.begin(9600);
while (!mySerial)
;
mySerial.println("SAMD Pin State Report");
mySerial.println();
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
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 TCC0 and TCC1
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Dual slope PWM operation: timers countinuously count up to PER register value then down 0
REG_TCC0_WAVE |= TCC_WAVE_POL(0xF) | // Reverse the output polarity on all TCC0 outputs
TCC_WAVE_WAVEGEN_DSBOTH; // Setup dual slope PWM on TCC0
while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization
// Each timer counts up to a maximum or TOP value set by the PER register,
// this determines the frequency of the PWM operation:
REG_TCC0_PER = 96; // Set the frequency of the PWM on TCC0 to 250kHz
while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
// Set the PWM signal to output 50% duty cycle
REG_TCC0_CC3 = 48; // TCC0 CC3 - on D7
while (TCC0->SYNCBUSY.bit.CC3); // Wait for synchronization
// Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the outputs
REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1
TCC_CTRLA_ENABLE; // Enable the TCC0 output
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
//D13
PORT->Group[PORTA].PINCFG[17].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[17 >> 1].bit.PMUXO = PORT_PMUX_PMUXO_F_Val;
//D12
PORT->Group[PORTA].PINCFG[19].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[19 >> 1].bit.PMUXO = PORT_PMUX_PMUXO_F_Val;
//D11
PORT->Group[PORTA].PINCFG[16].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[16 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_F_Val;
//D10
PORT->Group[PORTA].PINCFG[18].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[18 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_F_Val;
//D7
PORT->Group[PORTA].PINCFG[21].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[21 >> 1].bit.PMUXO = PORT_PMUX_PMUXO_F_Val;
//D6
PORT->Group[PORTA].PINCFG[20].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[20 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_F_Val;
//D5
PORT->Group[PORTA].PINCFG[15].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[15 >> 1].bit.PMUXO = PORT_PMUX_PMUXO_F_Val;
//D4
PORT->Group[PORTA].PINCFG[8].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[8 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_E_Val;
//D3
PORT->Group[PORTA].PINCFG[9].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[9 >> 1].bit.PMUXO = PORT_PMUX_PMUXO_E_Val;
//D2
PORT->Group[PORTA].PINCFG[14].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[14 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_F_Val;
//D1
PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[10 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_F_Val;
//D0
PORT->Group[PORTA].PINCFG[11].bit.PMUXEN = 1;
PORT->Group[PORTA].PMUX[11 >> 1].bit.PMUXO = PORT_PMUX_PMUXO_F_Val;
}
void loop() {
// put your main code here, to run repeatedly:
pinmux_report(PIN_LED_RXL, buffer, "RXL");
mySerial.println(buffer);
for (int pin = 0; pin < PINS_COUNT; pin++) { // For all defined pins
pinmux_report(pin, buffer, 0);
mySerial.println(buffer);
} // "pin" for loop
while (mySerial.read() < 0)
; // wait for character to run again.
mySerial.println("\nRunning again!\n");
}