-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PWM resolution increase in hardware timer #182
Comments
Yeah - of course. This requires:
void setDutyCycle(unt8_t channel, uint16_t duty) {
if (channel > 2) return;
if (duty == 0 || duty == 1) {
PORT_t* prt = portToPortStruct(PORTMUX.TCAROUTEA);
if (duty) {
prt->OUTSET = 1 << channel;
} else {
prt->OUTCLR = 1 << channel;
}
} else {
volatile uint16_t * t=&TCA0_SINGLE_CMP0BUF; //Using the buffering is more commonly the reason one does something like this than needing more resolution.
*(t+channel) = duty;
} (the buffering bit: If you use PER/CMP0/1/2 registers they take effect immediately and can result in glitches. If you use the ones ending in BUF, they are only updated at the start of the cycle to prevent glitches One challenge on MegaCoreX is that there's no function like TakeOverTCA0() on DxCore which tells the core to pretend that a timer doesn't exist, so there's no way to tell it to make analogWrite() treat it like it had no PWM, and hence not try to fiddle with the timer settings, nor make digitalWrite() to the pins where the PWM was originally located try to turn off PWM channels. This is fine if you haven't changed portmux. But if you have changed portmux, you have to use direct port access or fast I/O to access it on MCX DxC and mTC do have takeOverTCA0 (and takeOverTCA1 where appropriate) so on those cores you can skip the first 3 steps and instead call takeOverTCA0() and analogWrite() and digitalWrite() will not do anything funky no matter what you have also done to the portmux. I don't think MCX still uses the stock millis implementation. The stock implementation gives one extra PWM channel on some parts, at the cost reduced timekeeping accuracy, increased timekeeping overhead, and makes the dreaded reverse time travel in micros() (which has consequences only slightly less severe than reverse time travel in the physical realm) much harder to avoid. (basically, on my cores, the only time that TCBs are configured automatically to use the clock from a TCA is when they're in PWM mode, and PWM mode is not used for timekeeping - we instead set a TCB clocked from CLK_PER/2 in periodic interrupt mode and the period set so it overflows once per millisecond, and I think MCX adopted this method too. I hope so, at least. |
Sadly I am not that familiar with the Atmega4809 but do I understand you correctly? i would like to output more than 10b PWM on PC0, PC1, PC2 and PC3 is that possible? but if I also would like to use millis() it is not possible? And there is no function in MCX to utilize this feature? |
could one increase PWM resolution to more than 8bit in megacorex on the 4809?
"The TCAn.PER register defines the PWM resolution. The minimum resolution is 2 bits (TCA.PER = 0x0002), and the
maximum resolution is 16 bits (TCA.PER = MAX-1)"
https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega4808-4809-Data-Sheet-DS40002173A.pdf
page 191 to 194
The text was updated successfully, but these errors were encountered: