1
+ /*
2
+ ArduinoLowPower class for nRF52.
3
+
4
+ Written by Chiara Ruggeri ([email protected] )
5
+
6
+ Copyright (c) 2017 Arduino AG. All right reserved.
7
+
8
+ This library is free software; you can redistribute it and/or
9
+ modify it under the terms of the GNU Lesser General Public
10
+ License as published by the Free Software Foundation; either
11
+ version 2.1 of the License, or (at your option) any later version.
12
+
13
+ This library is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
+ See the GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public
19
+ License along with this library; if not, write to the Free Software
20
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ */
22
+
23
+ #if defined(ARDUINO_ARCH_NRF52)
24
+
25
+ #include " ArduinoLowPower.h"
26
+ #include " WInterrupts.h"
27
+ #include " nrf_rtc.h"
28
+
29
+ volatile bool event = false ;
30
+ void (*functionPointer)(void );
31
+ nrf_lpcomp_input_t aPin[]={NRF_LPCOMP_INPUT_1, NRF_LPCOMP_INPUT_2, NRF_LPCOMP_INPUT_4, NRF_LPCOMP_INPUT_5, NRF_LPCOMP_INPUT_6, NRF_LPCOMP_INPUT_7};
32
+
33
+ void wakeUpGpio (){
34
+ event = true ;
35
+ if (functionPointer)
36
+ functionPointer ();
37
+ }
38
+
39
+ void ArduinoLowPowerClass::idle () {
40
+ // nRF52 has just two low power modes. Call sleep if idle is called.
41
+ sleep ();
42
+ }
43
+
44
+ void ArduinoLowPowerClass::idle (uint32_t millis) {
45
+ setAlarmIn (millis);
46
+ idle ();
47
+ }
48
+
49
+ void ArduinoLowPowerClass::sleep () {
50
+ sd_power_mode_set (NRF_POWER_MODE_LOWPWR);
51
+ event=false ;
52
+ while (!event){
53
+ sd_app_evt_wait ();
54
+ }
55
+ }
56
+
57
+ void ArduinoLowPowerClass::sleep (uint32_t millis) {
58
+ setAlarmIn (millis);
59
+ sleep ();
60
+ }
61
+
62
+ void ArduinoLowPowerClass::deepSleep () {
63
+ // Enter in systemOff mode only when no EasyDMA transfer is active
64
+ // this is achieved by disabling all peripheral that use it
65
+ NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled; // disable UART
66
+ NRF_SAADC ->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos); // disable ADC
67
+ NRF_PWM0 ->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos); // disable all pwm instance
68
+ NRF_PWM1 ->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
69
+ NRF_PWM2 ->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
70
+ NRF_TWIM1 ->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); // disable TWI Master
71
+ NRF_TWIS1 ->ENABLE = (TWIS_ENABLE_ENABLE_Disabled << TWIS_ENABLE_ENABLE_Pos); // disable TWI Slave
72
+
73
+ // Enter in System OFF mode
74
+ sd_power_system_off ();
75
+
76
+ /* Only for debugging purpose, will not be reached without connected debugger*/
77
+ while (1 );
78
+ }
79
+
80
+ void ArduinoLowPowerClass::setAlarmIn (uint32_t millis) {
81
+ nrf_rtc_prescaler_set (NRF_RTC1, 32 );
82
+ // enable interrupt
83
+ NVIC_SetPriority (RTC1_IRQn, 2 ); // high priority
84
+ NVIC_ClearPendingIRQ (RTC1_IRQn);
85
+ NVIC_EnableIRQ (RTC1_IRQn);
86
+ nrf_rtc_event_clear (NRF_RTC1, NRF_RTC_EVENT_COMPARE_0);
87
+ nrf_rtc_int_enable (NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK);
88
+ // Tick every 1 ms
89
+ nrf_rtc_cc_set (NRF_RTC1, 0 , millis);
90
+
91
+ // start RTC
92
+ nrf_rtc_task_trigger (NRF_RTC1, NRF_RTC_TASK_START);
93
+ }
94
+
95
+ void ArduinoLowPowerClass::attachInterruptWakeup (uint32_t pin, voidFuncPtr callback, uint32_t mode) {
96
+ functionPointer = callback;
97
+
98
+ if (pin == RTC_ALARM_WAKEUP)
99
+ return ;
100
+
101
+ pinMode (pin, INPUT_PULLUP);
102
+ attachInterrupt (pin, wakeUpGpio, mode);
103
+ }
104
+
105
+ void ArduinoLowPowerClass::enableWakeupFrom (wakeup_reason peripheral, uint32_t pin, uint32_t event, uint32_t option){
106
+ if (peripheral == NFC_WAKEUP){
107
+ NRF_NFCT->TASKS_SENSE =1 ;
108
+ return ;
109
+ }
110
+ if (peripheral == ANALOG_COMPARATOR_WAKEUP){
111
+ detect_mode mode;
112
+ if (option == DOWN)
113
+ mode = DOWN;
114
+ else if (option == UP)
115
+ mode = UP;
116
+ else
117
+ mode = CROSS;
118
+ nrf_lpcomp_config_t config={(nrf_lpcomp_ref_t )event, (nrf_lpcomp_detect_t )mode};
119
+ nrf_lpcomp_configure (&config);
120
+ if (pin<14 && pin>19 )
121
+ return ; // no analog pin is choosen
122
+ nrf_lpcomp_input_select (aPin[pin-14 ]);
123
+ nrf_lpcomp_enable ();
124
+ nrf_lpcomp_task_trigger (NRF_LPCOMP_TASK_START);
125
+ while (!nrf_lpcomp_event_check (NRF_LPCOMP_EVENT_READY));
126
+ return ;
127
+ }
128
+ if (peripheral == GPIO_WAKEUP){
129
+ if (pin > 20 )// allow wake up only from digital and analog pins
130
+ return ;
131
+ if (event==LOW)
132
+ nrf_gpio_cfg_sense_input (g_APinDescription[pin].ulPin , NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
133
+ else
134
+ nrf_gpio_cfg_sense_input (g_APinDescription[pin].ulPin , NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
135
+ }
136
+ }
137
+
138
+ wakeup_reason ArduinoLowPowerClass::wakeupReason (){
139
+ uint32_t guilty;
140
+ sd_power_reset_reason_get (&guilty);
141
+ if (guilty & 0x10000 ){ // GPIO
142
+ // RESETREAS is a cumulative register. We need to clear it by writing 1 in the relative field
143
+ sd_power_reset_reason_clr (1 << 16 );
144
+ return GPIO_WAKEUP;
145
+ }
146
+ if (guilty & 0x80000 ){ // NFC
147
+ sd_power_reset_reason_clr (1 << 19 );
148
+ return NFC_WAKEUP;
149
+ }
150
+ if (guilty & 0x20000 ){ // COMP
151
+ sd_power_reset_reason_clr (1 << 17 );
152
+ return ANALOG_COMPARATOR_WAKEUP;
153
+ }
154
+ return OTHER_WAKEUP;
155
+ }
156
+
157
+
158
+ ArduinoLowPowerClass LowPower;
159
+
160
+ #ifdef __cplusplus
161
+ extern " C" {
162
+ #endif
163
+
164
+ void RTC1_IRQHandler (void )
165
+ {
166
+ event=true ;
167
+ nrf_rtc_event_clear (NRF_RTC1, NRF_RTC_EVENT_COMPARE_0);
168
+ nrf_rtc_task_trigger (NRF_RTC1, NRF_RTC_TASK_CLEAR);
169
+ nrf_rtc_task_trigger (NRF_RTC1, NRF_RTC_TASK_STOP);
170
+ if (functionPointer)
171
+ functionPointer ();
172
+ }
173
+
174
+ #ifdef __cplusplus
175
+ }
176
+ #endif
177
+
178
+ #endif // ARDUINO_ARCH_NRF52
0 commit comments