We recently received our prototype design which incorporates an ATTiny817 with expectations that PC0 and PC1 would work out of the box with analogWrite to dim our PWM outputs on the aforementioned pins but to our dismay, it is not the case.
Upon further investigation, it appears this TCD0 timer is a bit unique and doesn't come pre-configured to to function as a PWM source nor does analogWrite accommodate these pins with PWM functionality either out of the box.
We're swimming a bit in the documentation of how to configure our ATTiny817 to get these two pins to generate a PWM waveform. Are there any concerns with using TCD0 as a PWM generator in order to output a waveform on PC0 and PC1? Is it possible for analogWrite to be used on these pins if and when TCD0 is configured properly?
I made a small demonstration of setting up TCD0 to output 50Hz on WOA and/or WOC
// =================================================================
// Demonstration of setting up TCD0 to output 50Hz on WOA and/or WOC
// Hans Meijdam, March 2024
// =================================================================
void setup() {
takeOverTCD0();// this will give control of the timer.
CCP = CCP_IOREG_gc; // enable write to protected IO registers (timed sequence)
/********* uncomment one of these 3 outputs to demonstrate output on WOA and/or WOC *******/
// TCD0_FAULTCTRL |= TCD_CMPAEN_bm;// // enable Waveform Output A (WOA) from TCD0 to PA6
// TCD0_FAULTCTRL |= TCD_CMPCEN_bm;// // enable Waveform Output C (WOC) from TCD0 to PC0
TCD0_FAULTCTRL |= TCD_CMPAEN_bm |TCD_CMPCEN_bm;// or on both at the same time
TCD0_CTRLB |= TCD_WGMODE_TWORAMP_gc; // Set timer to one ramp mode (=default)
TCD0_CTRLA |= TCD_CLKSEL_SYSCLK_gc; // Internal 16/20 MHz Oscillator (OSC20M)
TCD0_CTRLA |= TCD_CNTPRES_DIV32_gc; // Division factor (1, 4 or 32 possible)
TCD0_CTRLA |= TCD_SYNCPRES_DIV2_gc; // Division factor (1, 2, 4 or 8 possible)
TCD0_CTRLA |= TCD_ENABLE_bm; // enable TCD0
while (!(TCD0.STATUS & TCD_CMDRDY_bm));//wait for ready to receive a command in double buffer
TCD0_CMPASET = 4095 - 623; //310 gives 1000us pulse. 623 gives 2000us pulse. change the set value to define pulse
TCD0_CMPACLR = 4095; // do not change top value or frequency of ramp one will change
TCD0_CMPBCLR = 2095; // 2nd ramp lowering TOP from 4095 to 2095 gives 50Hz
TCD0_CTRLE |= TCD_SYNC_bm; // send synchronization command to load double buffer to TCD0
}
void loop() {}
How can we configure PC1 to simultaneously generate the same signal as PC0 per your demonstration logic instead of PA6? Would this be the only change needed?
// TCD0_FAULTCTRL |= TCD_CMPCEN_bm;// // enable Waveform Output C (WOC) from TCD0 to PC0
// TCD0_FAULTCTRL |= TCD_CMPDEN_bm;// // enable Waveform Output D (WOD) from TCD0 to PC1
TCD0_FAULTCTRL |= TCD_CMPCEN_bm | TCD_CMPDEN_bm; // enable both at the same time
Our output duty cycle will need to change from 1/2 brightness (50%) to full brightness (100%) based upon decision logic in the loop() function. Can analogWrite be used in the same fashion it is used for TCA and TCB PWM capable pins that work out of the box with the Arduino framework?
Why is this timer not configured in the same manner as TCA and TBC out of the box? Is there a reason the Arduino framework doesn't automatically configure this under the hood when analogWrite is used on PC0 or PC1?
I suggest if you want to manually configure the timer as per my demonstration sketch, you set the timer in one ramp mode and make the CMPASET and CMPBSET values tha same and also make the CMPACLR and CMPBCLR values the same. Then it would output the same signal on WOA and WOB or on WOC and WOD, depending on which output you activate in the TCD0_FAULTCTRL register.
You can give it a try by trying the menu option to change the PWM pins. PC0 and PC1 is a possible choice
I am able to see a dimming on PC1 for the LEDs but I'm still working through configuring the logic such that we can ensure PWM is output on PC0 and PC1 and as mentioned these can be controlled via analogWrite.
We are using Platformio in VS Code, so I do not have access to the same options that are available in the Tools menu in Arduino Studio. Is there a way I can perform this same operation in Platformio?
Here is some pseudo-code to help clarify what we are trying to accomplish:
I took your advice and moved over to the Arduino IDE and we're seeing a PWM signal on the two outputs we require. It doesn't appear the manual register configuration is required when using megaTinyCore. megaTinyCore