-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathArduinoLowPower.cpp
105 lines (82 loc) · 2.53 KB
/
ArduinoLowPower.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#if defined(ARDUINO_ARCH_SAMD)
#include "ArduinoLowPower.h"
#include "WInterrupts.h"
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) {
SERIAL_PORT_USBVIRTUAL.flush();
USBDevice.standby();
} else {
USBDevice.detach();
restoreUSBDevice = true;
}
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
if (restoreUSBDevice) {
USBDevice.attach();
}
if (SERIAL_PORT_USBVIRTUAL) {
SERIAL_PORT_USBVIRTUAL.clear();
}
}
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, 0);
}
uint32_t now = rtc.getEpoch();
rtc.setAlarmEpoch(now + millis/1000);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
}
void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, uint32_t mode) {
EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI) {
// 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;
}
//pinMode(pin, INPUT_PULLUP);
attachInterrupt(pin, callback, mode);
// 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);
// Enable wakeup capability on pin in case being used during sleep
EIC->WAKEUP.reg |= (1 << in);
/* 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;
}
ArduinoLowPowerClass LowPower;
#endif // ARDUINO_ARCH_SAMD