possibly fix wasted power in idle mode

arduino uses TCA timer to do its things. it doesn't need to do anything
while the MCU is in low power sleep. disable TCA whenever entering sleep
from user code.

note that the prior "working" demo commented using the rgb_run_next sleep
loop in the program. was still diagnosing issues with TCB0 interrupt.
if there's still issues waking from idle with TCB interrupt, then things
will still need to be addressed...

this fix is untested.
This commit is contained in:
true 2025-04-28 20:19:36 -07:00
parent 4d58a3df74
commit cf209fce4d
2 changed files with 18 additions and 17 deletions

View File

@ -79,19 +79,17 @@ uint8_t rgbprog_idx = 0;
void idle_cpu()
void sleep_cpu(uint8_t sleep_type)
{
SLPCTRL.CTRLA = SLPCTRL_SMODE_IDLE_gc | SLPCTRL_SEN_bm;
// TCA interrupt is used by arduino timing routines
// needs to be disabled while asleep to save power
TCA0.SPLIT.CTRLA &= ~TCA_SPLIT_ENABLE_bm;
// configure for idle mode, then idle
SLPCTRL.CTRLA = sleep_type | SLPCTRL_SEN_bm;
__asm("sleep");
}
void sleep_cpu()
{
SLPCTRL.CTRLA = SLPCTRL_SMODE_STDBY_gc | SLPCTRL_SEN_bm;
__asm("sleep");
}
// mcu init
void setup() {
// configure PA2 as falling edge interrupt for button
@ -120,19 +118,22 @@ void setup() {
// mcu program loop
void loop() {
// if something other than TCB0 or PA2 going low wakes us, we don't care
// sleep with prior sleep settings until we're ready to run next rgb prog step
while (!rgb_run_next) {
// __asm("sleep");
__asm("sleep");
}
// re-enable TCA0 since arduino core uses it
TCA0.SPLIT.CTRLA |= TCA_SPLIT_ENABLE_bm;
// clear run flag for next go
rgb_run_next = 0;
switch (run_rgbprog) {
case RGB_INIT: { // just started running a program
digitalWrite(PIN_LED_PWRENA, HIGH); // enable LED power supply,
delay(15); // wait a moment for LEDs to stabilize,
/*for (uint16_t i = 0; i < (8000000UL / 4 / 1000) * 20; i++) {
asm("nop");
}*/
rgbprog_idx++; // select the next program in sequence,
if (rgbprog_idx >= PROG_COUNT) {
@ -144,7 +145,7 @@ void loop() {
enable_rgb_timer(); // then start the RGB program timebase.
idle_cpu(); // we can idle CPU after running the program
sleep_cpu(SLPCTRL_SMODE_IDLE_gc); // we can idle CPU after running the program
break;
}
@ -157,7 +158,7 @@ void loop() {
break;
}
idle_cpu(); // we can idle CPU after running the program
sleep_cpu(SLPCTRL_SMODE_IDLE_gc); // we can idle CPU after running the program
break;
}
@ -166,7 +167,7 @@ void loop() {
rgb.show(); // send final updates to the led
run_rgbprog = RGB_IDLE;
idle_cpu(); // we can idle CPU after running the program
sleep_cpu(SLPCTRL_SMODE_IDLE_gc); // we can idle CPU after running the program
break;
}
@ -176,7 +177,7 @@ void loop() {
digitalWrite(PIN_LED_PWRENA, LOW); // disable LED power supply,
run_rgbprog = RGB_IDLE; // and clear run_rgbprog.
sleep_cpu(); // finally, go to sleep in standby mode
sleep_cpu(SLPCTRL_SMODE_STDBY_gc); // finally, go to sleep in standby mode
break;
}