What I've found is that on both those pins only function E, for TCC0, works. Trying to initialize function F results in no PWM output and also seems to wedge the processor, requiring a reboot before allowing USB communications.
One thing I notice is that both these ports use higher values for the wo[] register -- 2 and 3 -- than the other pin mappings which work fine and all use 0 or 1 for wo[]. That may be just a red herring, but I thought it was interesting.
I'm wondering if the Trinket isn't setting these pins up to do something else that blocks function F.
Attached is some code showing this. Has anyone experienced this, or have any insight into it?
Thanks!
Code: Select all
/*
The Trinket M0 has these pins, mapped to these timers:
Digital 0 PA08, SAMD pin 11, E=TCC0/W0[0], F=TCC1/WO[2]
Digital 1 PA02, SAMD pin 3, no timers
Digital 2 PA09, SAMD pin 12, E=TCC0/WO[1], F=TCC1/WO[3]
Digital 3 PA07, SAMD pin 8, E=TCC1/WO[1], F= N/A
Digital 4 PA06, SAMD pin 7, E=TCC1/WO[0], F= N/A
Digital 13 (LED) PA10, SAMD pin 13, E=TCC1/WO[0], F = TCC0/WO[2]
*/
uint8_t map_d0_tcc1() { // NOTE: this doesn't seem to work
/* D0 is PA08 */
/* Configure pin as output. */
PORT->Group[0].DIRSET.reg = PORT_PA08;
PORT->Group[0].OUTCLR.reg = PORT_PA08;
/* Enable the peripheral multiplexer. */
PORT->Group[0].PINCFG[8].reg |= PORT_PINCFG_PMUXEN;
/* Set PA08's function to function F -- TCC1/WO[2]
* Function E is TCC0/WO[0].
* Because it's an even numbered pin the PMUX is E
* (even) and the PMUX index is pin number / 2, so 4.
*/
PORT->Group[0].PMUX[4].reg = PORT_PMUX_PMUXE_F;
return 2;
}
uint8_t map_d2_tcc1() { // NOTE: this doesn't seem to work
/* D2 is PA09 */
/* Configure pin as output. */
PORT->Group[0].DIRSET.reg = PORT_PA09;
PORT->Group[0].OUTCLR.reg = PORT_PA09;
/* Enable the peripheral multiplexer. */
PORT->Group[0].PINCFG[9].reg |= PORT_PINCFG_PMUXEN;
/* Set PA09's function to function F. Function F is
* TCC1/WO[3] for PA09. Function E is TCC0/WO[1].
* Because it's an even numbered pin the PMUX is E
* (even) and the PMUX index is pin number / 2, so 4.
*/
PORT->Group[0].PMUX[4].reg = PORT_PMUX_PMUXO_F;
return 3;
}
void setup() {
PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1;
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |
GCLK_CLKCTRL_GEN_GCLK1 |
GCLK_CLKCTRL_ID_TCC0_TCC1;
while (GCLK->STATUS.bit.SYNCBUSY) {};
TCC1->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV16_Val);
TCC1->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;
while (TCC1->SYNCBUSY.bit.WAVE) {};
uint32_t period = 512;
TCC1->PER.reg = period;
while (TCC1->SYNCBUSY.bit.PER) {};
// functions return the wo[] register number
// that's needed to set the CC register to
// set the duty cycle
uint8_t w1 = map_d0_tcc1(); // doesn't work
//nt8_t w1 = map_d2_tcc1(); // doesn't work
TCC1->CC[w1].reg = period / 2;
while (TCC1->SYNCBUSY.bit.CC2) {};
TCC1->CTRLA.reg |= (TCC_CTRLA_ENABLE);
while (TCC1->SYNCBUSY.bit.ENABLE) {};
}
void loop() {
// put your main code here, to run repeatedly:
}