ATTiny817 | How do I enable PWM on PC0 and PC1? TCD0?

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?

Thanks in advance.

That's done in the TCD0_FAULTCTRL register

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() {}
1 Like

Thank you for your response! A couple questions:

  1. 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
  1. 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?

  2. 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?

  1. 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.

  2. You can give it a try by trying the menu option to change the PWM pins. PC0 and PC1 is a possible choice

  3. see answer on question 2

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:

void setup() {
  // Configure TCD0 for PWM output
}

void loop() {

if(buttonIsPressed) {

  analogWrite(PC0, 60);
  analogWrite(PC1, 60);

} else {

  analogWrite(PC0, 255);
  analogWrite(PC1, 255);

}

No, I think platformIO has a limited set of features

You can set a few parameters only.
I don't see the option for selecting the PWM pins.

Better do a portable install of the Arduino IDE and ditch PlatformIO

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

Yes, I tried that also to check if the PWM mapping worked. You don't even need to set the pins to OUTPUT yourself. Analogwrite will do that for you.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.