forked from Arduino/metronom
The tube library calls delay(100) after every display write and the BME280 library calls delay(100) when re-initializing after a failed transfer. Inside the TC3 timer ISR the SysTick interrupt is blocked, so micros() stops advancing past ~1ms and delay() can spin forever when its start sample lands exactly at the bottom of the micros() sawtooth. All clocks derive from the same 48MHz source, so the ISR phase is locked and one specific code path (display update on a falling temperature reading) hits the fatal window reproducibly. ISRs now only raise flags; sensor reads, display updates and timer rescheduling run from loop(), where delay() works normally. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
34 lines
1.1 KiB
C++
34 lines
1.1 KiB
C++
volatile unsigned long lastButtonPress = millis();
|
|
|
|
// Debouncing using timer:
|
|
// https://github.com/khoih-prog/TimerInterrupt/blob/master/examples/SwitchDebounce/SwitchDebounce.ino
|
|
void initButton() {
|
|
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
|
// Order of ISRs matter: RISING should be invoked first
|
|
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISRtime, CHANGE);
|
|
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISRstate, RISING);
|
|
}
|
|
|
|
// FIXME: runMetronome ISR should be started/stopped by button. Otherwise fraction of first PERIOD_MS is lost from countdown.
|
|
void buttonISRstate() {
|
|
if ((millis() - lastButtonPress) > 100) {
|
|
if (countdown < 0)
|
|
// TODO: enable metronome timer
|
|
countdown = 0;
|
|
else if (countdown == 0) {
|
|
// TODO: restart metronome timer to align countdown
|
|
countdown = COUNTDOWN;
|
|
displayNeedsUpdate = true;
|
|
} else {
|
|
countdown = -1;
|
|
digitalWrite(BUTTON_LED_PIN, LOW);
|
|
displayNeedsUpdate = true;
|
|
// TODO: disable metronome timer
|
|
}
|
|
}
|
|
}
|
|
|
|
void buttonISRtime() {
|
|
lastButtonPress = millis();
|
|
}
|