Skip to content

Commit 1ad49d9

Browse files
committed
Add alarm.pin that wakes on pin level
Fixes #3787
1 parent f2204d7 commit 1ad49d9

File tree

13 files changed

+361
-76
lines changed

13 files changed

+361
-76
lines changed

main.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,10 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
260260
STATIC bool run_code_py(safe_mode_t safe_mode) {
261261
bool serial_connected_at_start = serial_connected();
262262
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
263-
if (serial_connected_at_start) {
264-
serial_write("\n");
265-
print_code_py_status_message(safe_mode);
266-
}
263+
serial_write("\n");
264+
print_code_py_status_message(safe_mode);
265+
print_safe_mode_message(safe_mode);
266+
serial_write("\n");
267267
#endif
268268

269269
pyexec_result_t result;
@@ -307,16 +307,14 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
307307
if (result.return_code & PYEXEC_FORCED_EXIT) {
308308
return reload_requested;
309309
}
310-
}
311-
312-
// Program has finished running.
313310

314-
// Display a different completion message if the user has no USB attached (cannot save files)
315-
if (!serial_connected_at_start) {
311+
// Display a different completion message if the user has no USB attached (cannot save files)
316312
serial_write_compressed(translate("\nCode done running. Waiting for reload.\n"));
317313
}
318314

319-
bool serial_connected_before_animation = false;
315+
// Program has finished running.
316+
317+
bool serial_connected_before_animation = serial_connected();
320318
#if CIRCUITPY_DISPLAYIO
321319
bool refreshed_epaper_display = false;
322320
#endif

ports/esp32s2/common-hal/alarm/__init__.c

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@
4242

4343
#include "esp_sleep.h"
4444

45+
#include "components/soc/soc/esp32s2/include/soc/rtc_cntl_reg.h"
46+
#include "components/driver/include/driver/uart.h"
47+
4548
// Singleton instance of SleepMemory.
4649
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
4750
.base = {
4851
.type = &alarm_sleep_memory_type,
4952
},
5053
};
5154

52-
5355
void alarm_reset(void) {
5456
alarm_time_timealarm_reset();
57+
alarm_pin_pin_alarm_reset();
5558
alarm_sleep_memory_reset();
5659
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
5760
}
@@ -60,6 +63,9 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
6063
if (alarm_time_timealarm_woke_us_up()) {
6164
return ESP_SLEEP_WAKEUP_TIMER;
6265
}
66+
if (alarm_pin_pin_alarm_woke_us_up()) {
67+
return ESP_SLEEP_WAKEUP_GPIO;
68+
}
6369

6470
return esp_sleep_get_wakeup_cause();
6571
}
@@ -69,14 +75,16 @@ bool alarm_woken_from_sleep(void) {
6975
}
7076

7177
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
72-
switch (_get_wakeup_cause()) {
78+
esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
79+
switch (cause) {
7380
case ESP_SLEEP_WAKEUP_TIMER: {
7481
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
7582
}
7683

77-
case ESP_SLEEP_WAKEUP_EXT0: {
78-
// TODO: implement pin alarm wake.
79-
break;
84+
case ESP_SLEEP_WAKEUP_GPIO:
85+
case ESP_SLEEP_WAKEUP_EXT0:
86+
case ESP_SLEEP_WAKEUP_EXT1: {
87+
return alarm_pin_pin_alarm_get_wakeup_alarm(n_alarms, alarms);
8088
}
8189

8290
case ESP_SLEEP_WAKEUP_TOUCHPAD:
@@ -98,24 +106,8 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) {
98106

99107
// Set up light sleep or deep sleep alarms.
100108
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
101-
bool time_alarm_set = false;
102-
alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_NULL;
103-
104-
for (size_t i = 0; i < n_alarms; i++) {
105-
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) {
106-
mp_raise_NotImplementedError(translate("PinAlarm not yet implemented"));
107-
} else if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) {
108-
if (time_alarm_set) {
109-
mp_raise_ValueError(translate("Only one alarm.time alarm can be set."));
110-
}
111-
time_alarm = MP_OBJ_TO_PTR(alarms[i]);
112-
time_alarm_set = true;
113-
}
114-
}
115-
116-
if (time_alarm_set) {
117-
alarm_time_timealarm_set_alarm(time_alarm);
118-
}
109+
alarm_pin_pin_alarm_set_alarms(deep_sleep, n_alarms, alarms);
110+
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
119111
}
120112

121113
STATIC void _idle_until_alarm(void) {
@@ -134,18 +126,24 @@ STATIC void _idle_until_alarm(void) {
134126
// Is it safe to do a light sleep? Check whether WiFi is on or there are
135127
// other ongoing tasks that should not be shut down.
136128
STATIC bool _light_sleep_ok(void) {
137-
return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) && !supervisor_workflow_active();
129+
int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL);
130+
return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) &&
131+
!supervisor_workflow_active() &&
132+
connecting_delay_ticks <= 0;
138133
}
139134

140135
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
141136
_setup_sleep_alarms(false, n_alarms, alarms);
142137

143138
// Light sleep can break some functionality so only do it when possible. Otherwise we idle.
144139
if (_light_sleep_ok()) {
140+
// Flush the UART to complete the log line.
141+
uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);
145142
esp_light_sleep_start();
146143
} else {
147144
_idle_until_alarm();
148145
}
146+
149147
mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms);
150148
alarm_reset();
151149
return wake_alarm;
@@ -156,6 +154,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
156154
}
157155

158156
void NORETURN alarm_enter_deep_sleep(void) {
157+
alarm_pin_pin_alarm_prepare_for_deep_sleep();
159158
// The ESP-IDF caches the deep sleep settings and applies them before sleep.
160159
// We don't need to worry about resetting them in the interim.
161160
esp_deep_sleep_start();

0 commit comments

Comments
 (0)