Compare commits
No commits in common. '31e45f656dd498027ba7ad8bdd9ff9a7dbc96506' and '7a829687e873a2411e9b9b8b650f9db99c83c564' have entirely different histories.
31e45f656d
...
7a829687e8
3 changed files with 1 additions and 341 deletions
@ -1,225 +0,0 @@ |
|||||||
#if defined(ARDUINO_ARCH_SAMD) |
|
||||||
|
|
||||||
#include "ArduinoLowPower.h" |
|
||||||
|
|
||||||
static void configGCLK6() |
|
||||||
{ |
|
||||||
// enable EIC clock
|
|
||||||
GCLK->CLKCTRL.bit.CLKEN = 0; //disable GCLK module
|
|
||||||
while (GCLK->STATUS.bit.SYNCBUSY); |
|
||||||
|
|
||||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK6 | GCLK_CLKCTRL_ID( GCM_EIC )) ; //EIC clock switched on GCLK6
|
|
||||||
while (GCLK->STATUS.bit.SYNCBUSY); |
|
||||||
|
|
||||||
GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(6)); //source for GCLK6 is OSCULP32K
|
|
||||||
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); |
|
||||||
|
|
||||||
GCLK->GENCTRL.bit.RUNSTDBY = 1; //GCLK6 run standby
|
|
||||||
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); |
|
||||||
|
|
||||||
/* Errata: Make sure that the Flash does not power all the way down
|
|
||||||
* when in sleep mode. */ |
|
||||||
|
|
||||||
NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::idle() { |
|
||||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; |
|
||||||
PM->SLEEP.reg = 2; |
|
||||||
__DSB(); |
|
||||||
__WFI(); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::idle(uint32_t millis) { |
|
||||||
setAlarmIn(millis); |
|
||||||
idle(); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::sleep() { |
|
||||||
bool restoreUSBDevice = false; |
|
||||||
|
|
||||||
if (SERIAL_PORT_USBVIRTUAL) { |
|
||||||
USBDevice.standby(); |
|
||||||
} else { |
|
||||||
USBDevice.detach(); |
|
||||||
restoreUSBDevice = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Ralf
|
|
||||||
//USBDevice.detach();
|
|
||||||
//restoreUSBDevice = true;
|
|
||||||
//----------
|
|
||||||
|
|
||||||
// Disable systick interrupt: See https://www.avrfreaks.net/forum/samd21-samd21e16b-sporadically-locks-and-does-not-wake-standby-sleep-mode
|
|
||||||
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; |
|
||||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; |
|
||||||
__DSB(); |
|
||||||
__WFI(); |
|
||||||
// Enable systick interrupt
|
|
||||||
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; |
|
||||||
if (restoreUSBDevice) { |
|
||||||
USBDevice.attach(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::sleep(uint32_t millis) { |
|
||||||
setAlarmIn(millis); |
|
||||||
sleep(); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::deepSleep() { |
|
||||||
sleep(); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::deepSleep(uint32_t millis) { |
|
||||||
sleep(millis); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::setAlarmIn(uint32_t millis) { |
|
||||||
|
|
||||||
if (!rtc.isConfigured()) { |
|
||||||
attachInterruptWakeup(RTC_ALARM_WAKEUP, NULL, (irq_mode)0); |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t now = rtc.getEpoch(); |
|
||||||
rtc.setAlarmEpoch(now + millis/1000); |
|
||||||
rtc.enableAlarm(rtc.MATCH_YYMMDDHHMMSS); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, irq_mode mode) { |
|
||||||
|
|
||||||
if (pin > PINS_COUNT) { |
|
||||||
// check for external wakeup sources
|
|
||||||
// RTC library should call this API to enable the alarm subsystem
|
|
||||||
switch (pin) { |
|
||||||
case RTC_ALARM_WAKEUP: |
|
||||||
rtc.begin(false); |
|
||||||
rtc.attachInterrupt(callback); |
|
||||||
/*case UART_WAKEUP:*/ |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
EExt_Interrupts in = g_APinDescription[pin].ulExtInt; |
|
||||||
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI) |
|
||||||
return; |
|
||||||
|
|
||||||
//pinMode(pin, INPUT_PULLUP);
|
|
||||||
attachInterrupt(pin, callback, mode); |
|
||||||
|
|
||||||
configGCLK6(); |
|
||||||
|
|
||||||
// Enable wakeup capability on pin in case being used during sleep
|
|
||||||
EIC->WAKEUP.reg |= (1 << in); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::attachAdcInterrupt(uint32_t pin, voidFuncPtr callback, adc_interrupt mode, uint16_t lo, uint16_t hi) |
|
||||||
{ |
|
||||||
uint8_t winmode = 0; |
|
||||||
|
|
||||||
switch (mode) { |
|
||||||
case ADC_INT_BETWEEN: winmode = ADC_WINCTRL_WINMODE_MODE3; break; |
|
||||||
case ADC_INT_OUTSIDE: winmode = ADC_WINCTRL_WINMODE_MODE4; break; |
|
||||||
case ADC_INT_ABOVE_MIN: winmode = ADC_WINCTRL_WINMODE_MODE1; break; |
|
||||||
case ADC_INT_BELOW_MAX: winmode = ADC_WINCTRL_WINMODE_MODE2; break; |
|
||||||
default: return; |
|
||||||
} |
|
||||||
|
|
||||||
adc_cb = callback; |
|
||||||
|
|
||||||
configGCLK6(); |
|
||||||
|
|
||||||
// Configure ADC to use GCLK6 (OSCULP32K)
|
|
||||||
while (GCLK->STATUS.bit.SYNCBUSY) {} |
|
||||||
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_ADC |
|
||||||
| GCLK_CLKCTRL_GEN_GCLK6 |
|
||||||
| GCLK_CLKCTRL_CLKEN; |
|
||||||
while (GCLK->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Set ADC prescaler as low as possible
|
|
||||||
ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV4; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Configure window mode
|
|
||||||
ADC->WINLT.reg = lo; |
|
||||||
ADC->WINUT.reg = hi; |
|
||||||
ADC->WINCTRL.reg = winmode; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Enable window interrupt
|
|
||||||
ADC->INTENSET.bit.WINMON = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Enable ADC in standby mode
|
|
||||||
ADC->CTRLA.bit.RUNSTDBY = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Enable continuous conversions
|
|
||||||
ADC->CTRLB.bit.FREERUN = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Configure input mux
|
|
||||||
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Enable the ADC
|
|
||||||
ADC->CTRLA.bit.ENABLE = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Start continuous conversions
|
|
||||||
ADC->SWTRIG.bit.START = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Enable the ADC interrupt
|
|
||||||
NVIC_EnableIRQ(ADC_IRQn); |
|
||||||
} |
|
||||||
|
|
||||||
void ArduinoLowPowerClass::detachAdcInterrupt() |
|
||||||
{ |
|
||||||
// Disable the ADC interrupt
|
|
||||||
NVIC_DisableIRQ(ADC_IRQn); |
|
||||||
|
|
||||||
// Disable the ADC
|
|
||||||
ADC->CTRLA.bit.ENABLE = 0; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Disable continuous conversions
|
|
||||||
ADC->CTRLB.bit.FREERUN = 0; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Disable ADC in standby mode
|
|
||||||
ADC->CTRLA.bit.RUNSTDBY = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Disable window interrupt
|
|
||||||
ADC->INTENCLR.bit.WINMON = 1; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Disable window mode
|
|
||||||
ADC->WINCTRL.reg = ADC_WINCTRL_WINMODE_DISABLE; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Restore ADC prescaler
|
|
||||||
ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV512_Val; |
|
||||||
while (ADC->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
// Restore ADC clock
|
|
||||||
while (GCLK->STATUS.bit.SYNCBUSY) {} |
|
||||||
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_ADC |
|
||||||
| GCLK_CLKCTRL_GEN_GCLK0 |
|
||||||
| GCLK_CLKCTRL_CLKEN; |
|
||||||
while (GCLK->STATUS.bit.SYNCBUSY) {} |
|
||||||
|
|
||||||
adc_cb = nullptr; |
|
||||||
} |
|
||||||
|
|
||||||
void ADC_Handler() |
|
||||||
{ |
|
||||||
// Clear the interrupt flag
|
|
||||||
ADC->INTFLAG.bit.WINMON = 1; |
|
||||||
LowPower.adc_cb(); |
|
||||||
} |
|
||||||
|
|
||||||
ArduinoLowPowerClass LowPower; |
|
||||||
|
|
||||||
#endif // ARDUINO_ARCH_SAMD
|
|
||||||
@ -1,106 +0,0 @@ |
|||||||
#ifndef _ARDUINO_LOW_POWER_H_ |
|
||||||
#define _ARDUINO_LOW_POWER_H_ |
|
||||||
|
|
||||||
#include <Arduino.h> |
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_AVR |
|
||||||
#error The library is not compatible with AVR boards |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_SAMD |
|
||||||
#include "RTCZero.h" |
|
||||||
#endif |
|
||||||
|
|
||||||
#if defined(ARDUINO_SAMD_TIAN) || defined(ARDUINO_NRF52_PRIMO) |
|
||||||
// add here any board with companion chip which can be woken up
|
|
||||||
#define BOARD_HAS_COMPANION_CHIP |
|
||||||
#endif |
|
||||||
|
|
||||||
#define RTC_ALARM_WAKEUP 0xFF |
|
||||||
|
|
||||||
#ifdef ARDUINO_API_VERSION |
|
||||||
using irq_mode = PinStatus; |
|
||||||
#else |
|
||||||
using irq_mode = uint32_t; |
|
||||||
#endif |
|
||||||
|
|
||||||
//typedef void (*voidFuncPtr)( void ) ;
|
|
||||||
typedef void (*onOffFuncPtr)( bool ) ; |
|
||||||
|
|
||||||
typedef enum{ |
|
||||||
OTHER_WAKEUP = 0, |
|
||||||
GPIO_WAKEUP = 1, |
|
||||||
NFC_WAKEUP = 2, |
|
||||||
ANALOG_COMPARATOR_WAKEUP = 3 |
|
||||||
} wakeup_reason; |
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_SAMD |
|
||||||
enum adc_interrupt |
|
||||||
{ |
|
||||||
ADC_INT_BETWEEN, |
|
||||||
ADC_INT_OUTSIDE, |
|
||||||
ADC_INT_ABOVE_MIN, |
|
||||||
ADC_INT_BELOW_MAX, |
|
||||||
}; |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
class ArduinoLowPowerClass { |
|
||||||
public: |
|
||||||
void idle(void); |
|
||||||
void idle(uint32_t millis); |
|
||||||
void idle(int millis) { |
|
||||||
idle((uint32_t)millis); |
|
||||||
} |
|
||||||
|
|
||||||
void sleep(void); |
|
||||||
void sleep(uint32_t millis); |
|
||||||
void sleep(int millis) { |
|
||||||
sleep((uint32_t)millis); |
|
||||||
} |
|
||||||
|
|
||||||
void deepSleep(void); |
|
||||||
void deepSleep(uint32_t millis); |
|
||||||
void deepSleep(int millis) { |
|
||||||
deepSleep((uint32_t)millis); |
|
||||||
} |
|
||||||
|
|
||||||
void attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, irq_mode mode); |
|
||||||
|
|
||||||
#ifdef BOARD_HAS_COMPANION_CHIP |
|
||||||
void companionLowPowerCallback(onOffFuncPtr callback) { |
|
||||||
companionSleepCB = callback; |
|
||||||
} |
|
||||||
void companionSleep() { |
|
||||||
companionSleepCB(true); |
|
||||||
} |
|
||||||
void companionWakeup() { |
|
||||||
companionSleepCB(false); |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_NRF52 |
|
||||||
void enableWakeupFrom(wakeup_reason peripheral, uint32_t pin = 0xFF, uint32_t event = 0xFF, uint32_t option = 0xFF); |
|
||||||
wakeup_reason wakeupReason(); |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_SAMD |
|
||||||
void attachAdcInterrupt(uint32_t pin, voidFuncPtr callback, adc_interrupt mode, uint16_t lo, uint16_t hi); |
|
||||||
void detachAdcInterrupt(); |
|
||||||
#endif |
|
||||||
|
|
||||||
private: |
|
||||||
void setAlarmIn(uint32_t millis); |
|
||||||
#ifdef ARDUINO_ARCH_SAMD |
|
||||||
RTCZero rtc; |
|
||||||
voidFuncPtr adc_cb; |
|
||||||
friend void ADC_Handler(); |
|
||||||
#endif |
|
||||||
#ifdef BOARD_HAS_COMPANION_CHIP |
|
||||||
void (*companionSleepCB)(bool); |
|
||||||
#endif |
|
||||||
}; |
|
||||||
|
|
||||||
extern ArduinoLowPowerClass LowPower; |
|
||||||
|
|
||||||
#endif |
|
||||||
Loading…
Reference in new issue