int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! cli(); // attach interrupts _wakeUp1Interrupt = interrupt1; _wakeUp2Interrupt = interrupt2; if (interrupt1 != INVALID_INTERRUPT_NUM) attachInterrupt(interrupt1, wakeUp1, mode1); if (interrupt2 != INVALID_INTERRUPT_NUM) attachInterrupt(interrupt2, wakeUp2, mode2); if (ms>0) { // sleep for defined time hwInternalSleep(ms); } else { // sleep until ext interrupt triggered hwPowerDown(SLEEP_FOREVER); } // Assure any interrupts attached, will get detached when they did not occur. if (interrupt1 != INVALID_INTERRUPT_NUM) detachInterrupt(interrupt1); if (interrupt2 != INVALID_INTERRUPT_NUM) detachInterrupt(interrupt2); // Return what woke the mcu. int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up if (interruptWakeUp()) ret = static_cast<int8_t>(_wokeUpByInterrupt); // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; }
int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, uint32_t ms) { // ATMega328P supports following modes to wake from sleep: LOW, CHANGE, RISING, FALLING // Datasheet states only LOW can be used with INT0/1 to wake from sleep, which is incorrect. // Ref: http://gammon.com.au/interrupts // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! cli(); // attach interrupts _wakeUp1Interrupt = interrupt1; _wakeUp2Interrupt = interrupt2; // Attach external interrupt handlers, and clear any pending interrupt flag // to prevent waking immediately again. // Ref: https://forum.arduino.cc/index.php?topic=59217.0 if (interrupt1 != INVALID_INTERRUPT_NUM) { clearPendingInterrupt(interrupt1); attachInterrupt(interrupt1, wakeUp1, mode1); } if (interrupt2 != INVALID_INTERRUPT_NUM) { clearPendingInterrupt(interrupt2); attachInterrupt(interrupt2, wakeUp2, mode2); } if (ms > 0u) { // sleep for defined time hwInternalSleep(ms); } else { // sleep until ext interrupt triggered hwPowerDown(WDTO_SLEEP_FOREVER); } // Assure any interrupts attached, will get detached when they did not occur. if (interrupt1 != INVALID_INTERRUPT_NUM) { detachInterrupt(interrupt1); } if (interrupt2 != INVALID_INTERRUPT_NUM) { detachInterrupt(interrupt2); } // Return what woke the mcu. // Default: no interrupt triggered, timer wake up int8_t ret = MY_WAKE_UP_BY_TIMER; if (interruptWakeUp()) { ret = static_cast<int8_t>(_wokeUpByInterrupt); } // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; }
int8_t hwSleep(uint32_t ms) { // Return what woke the mcu. // Default: no interrupt triggered, timer wake up int8_t ret = MY_WAKE_UP_BY_TIMER; if (ms > 0u) { // sleep for defined time hwInternalSleep(ms); } else { // sleep until ext interrupt triggered hwPowerDown(WDTO_SLEEP_FOREVER); } if (interruptWakeUp()) { ret = static_cast<int8_t>(_wokeUpByInterrupt); } // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; }
int8_t hwSleep(unsigned long ms) { hwInternalSleep(ms); return MY_WAKE_UP_BY_TIMER; }