SpenceKonde / megaTinyCore

Arduino core for the tinyAVR 0/1/2-series - Ones's digit 2,4,5,7 (pincount, 8,14,20,24), tens digit 0, 1, or 2 (featureset), preceded by flash in kb. Library maintainers: porting help available!
Other
564 stars 148 forks source link

Unexpected behaviour with timers #1044

Closed jonathanmlang closed 9 months ago

jonathanmlang commented 11 months ago

``//pins

define P_PUMP PIN_PA1

int pump_rawpulse_off=1000; int pump_rawpulse_on=5;

volatile int pump_rawpulse_incre=0;

//volatile bool onoff; volatile byte time_correction=0;

void setup(){

delay(2000);

//outputtest pinMode(P_PUMP,1);

TCA0.SINGLE.CMP0 = 78; // Set compare threshold TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV256_gc; // Enable timer with 1/256 prescaler TCA0.SINGLE.INTCTRL = TCA_SINGLE_CMP0_bm; // Enable compare

}

void loop(){

}

ISR(TCA0_CMP0_vect) { / Insert your TCA Compare 0 Interrupt handling code here /

if (pump_rawpulse_incre > pump_rawpulse_off) pump_rawpulse_incre = 0; else pump_rawpulse_incre++;

volatile bool onoff = (pump_rawpulse_incre <= pump_rawpulse_on) ? 1 : 0;

volatile bool time_leap;

if (time_correction >= 7) { //78.125 pulses in 10ms so leap pulse every 8 time_correction = 0; time_leap = 1; } else { time_correction++; time_leap = 0; }

TCA0.SINGLE.CMP0 = TCA0.SINGLE.CMP0 - (time_leap ? 79 : 78);

digitalWriteFast(P_PUMP, onoff);

/ The interrupt flag has to be cleared manually / TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP0_bm; }

``

In this code if I set TCA0.SINGLE.CMP0 = TCA0.SINGLE.CMP0 - 78 the code works as expected. The led connected to P_PUMP flashes correctly.

TCA0.SINGLE.CMP0 = TCA0.SINGLE.CMP0 - (time_leap ? 79 : 78); flashed the led once and never again. I have tried other ways of writing this such as

`TCA0.SINGLE.CMP0 -= 78 + 1; which also doesnt work but removing the +1 makes it work again.

Same applies for even doing it like this! if (time_leap) TCA0.SINGLE.CMP0 = TCA0.SINGLE.CMP0 - 79; else TCA0.SINGLE.CMP0 = TCA0.SINGLE.CMP0 - 78;

Does anyone know whats going on here?

Using attiny3226, arduino ide 1.8.13 and megatinycore 2.6.10

SpenceKonde commented 11 months ago

Call takeOverTCA0() as documented, before writing to any registers in TCA directly if you are going to configure the TCA with a custom configuration - this does two things. First, it tells the core machinery that the timer doesn't exist for pwm purposes, preventing analog and digital write functions from scribbling over your configuration (the main issue is the digitalWrites on the pins you've disabled PWM on) Secondly, it reinitializes the timer tothe POR state; we significantly reconfigure the timer, mainly by putting it into SPLIT mode in order to get 6 8-bit PWM channels (since the API quite clearly states that it only accepts 8-bit values, we might as well use split mode to double the number of PWM channels right?) Since unsetting that option is confusing to many users (and because of the other issue) we provide takeOverTCA0 (and takeOverTCD0 and takeOverTCA1 on parts that have those - though as there isn't a clean way to hard reset TCD, that unfortunately requires unpleasant manual reconfiguration - though a lot can be done to TCD0 without a full takeover (as documented in the core documentation - we have a whole document on TCD0 and what you can change without a takeover, since it's so unpleasant to work with). In no case can you call the takeOver function for the timer generating millis.

jonathanmlang commented 11 months ago

Interesting, thanks for that. There is a lot of documents and I seem to keep missing many of them unintentionally. Anyway in this program I need pwm on PA4 and PA5 only, and I also need millis() and micros(). Do you think I will hit any snags?

SpenceKonde commented 9 months ago

On a 3226? Nope nothing jumps out at me. Those are PWM pins in the configuration we provide by default (it can be changed with the tools submenu, if you need PWM to be on different pins). The default millis timer on the 3226 is TCB1; on megaTinyCore (unlike DxCore), the core does not use the scarce, incredibly useful and entirely too rare on tinyAVRs TCBs in "generate one measly 8-bit crappy PWM channel" mode; We have 6 outputs from the TCA, plus 1-series often has 2 more from the TCD. And TCBs are the timer everyone wants to take over because they are so simple.

SpenceKonde commented 9 months ago

Closing because at present there is no evidence here of any defect within the core.