summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2020-12-01 20:01:14 -0500
committerDan Halbert <halbert@halwitz.org>2020-12-01 20:01:14 -0500
commit8b7c23c1ee5d3fbfbda9116d6689e99f44e3b95a (patch)
tree52d4423b7bc48524d609abc6f2c7391c41fb8009
parent28d9e9186e6a9a153217535bd2d9f144672846bb (diff)
address review comments
-rwxr-xr-xlib/utils/pyexec.c6
-rw-r--r--lib/utils/pyexec.h1
-rwxr-xr-xmain.c10
-rw-r--r--ports/atmel-samd/common-hal/microcontroller/Processor.c2
-rw-r--r--ports/cxd56/common-hal/microcontroller/Processor.c2
-rw-r--r--ports/esp32s2/common-hal/alarm/__init__.c43
-rw-r--r--ports/esp32s2/common-hal/alarm/pin/PinAlarm.c13
-rw-r--r--ports/esp32s2/common-hal/alarm/pin/PinAlarm.h2
-rw-r--r--ports/litex/common-hal/microcontroller/Processor.c2
-rw-r--r--ports/mimxrt10xx/common-hal/microcontroller/Processor.c2
-rw-r--r--ports/nrf/common-hal/microcontroller/Processor.c2
-rw-r--r--ports/stm/common-hal/microcontroller/Processor.c2
-rw-r--r--py/obj.h4
-rw-r--r--py/objexcept.c3
-rw-r--r--py/reload.c22
-rw-r--r--py/reload.h22
-rw-r--r--shared-bindings/alarm/__init__.c80
-rw-r--r--shared-bindings/alarm/__init__.h4
-rw-r--r--shared-bindings/alarm/pin/PinAlarm.c37
-rw-r--r--shared-bindings/alarm/pin/PinAlarm.h4
20 files changed, 160 insertions, 103 deletions
diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c
index 378fb6267..68a3710ce 100755
--- a/lib/utils/pyexec.c
+++ b/lib/utils/pyexec.c
@@ -101,7 +101,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
#endif
}
- // If the code was loaded from a file its likely to be running for a while so we'll long
+ // If the code was loaded from a file it's likely to be running for a while so we'll long
// live it and collect any garbage before running.
if (input_kind == MP_PARSE_FILE_INPUT) {
module_fun = make_obj_long_lived(module_fun, 6);
@@ -132,6 +132,10 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) {
// at the moment, the value of SystemExit is unused
ret = pyexec_system_exit;
+#if CIRCUITPY_ALARM
+ } else if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_DeepSleepRequest)) {
+ ret = PYEXEC_DEEP_SLEEP;
+#endif
} else {
if ((mp_obj_t) nlr.ret_val != MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
diff --git a/lib/utils/pyexec.h b/lib/utils/pyexec.h
index cef72a76c..4c773cd64 100644
--- a/lib/utils/pyexec.h
+++ b/lib/utils/pyexec.h
@@ -49,6 +49,7 @@ extern int pyexec_system_exit;
#define PYEXEC_FORCED_EXIT (0x100)
#define PYEXEC_SWITCH_MODE (0x200)
#define PYEXEC_EXCEPTION (0x400)
+#define PYEXEC_DEEP_SLEEP (0x800)
int pyexec_raw_repl(void);
int pyexec_friendly_repl(void);
diff --git a/main.c b/main.c
index dda439d6d..270c0eacf 100755
--- a/main.c
+++ b/main.c
@@ -291,11 +291,21 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
}
}
#endif
+
+ // TODO: on deep sleep, make sure display is refreshed before sleeping (for e-ink).
+
cleanup_after_vm(heap);
if (result.return_code & PYEXEC_FORCED_EXIT) {
return reload_requested;
}
+
+ #if CIRCUITPY_ALARM
+ if (result.return_code & PYEXEC_DEEP_SLEEP) {
+ common_hal_alarm_enter_deep_sleep();
+ // Does not return.
+ }
+ #endif
}
// Program has finished running.
diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c
index 995521265..8c288a352 100644
--- a/ports/atmel-samd/common-hal/microcontroller/Processor.c
+++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c
@@ -352,5 +352,5 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
- return RESET_REASON_POWER_ON;
+ return RESET_REASON_UNKNOWN;
}
diff --git a/ports/cxd56/common-hal/microcontroller/Processor.c b/ports/cxd56/common-hal/microcontroller/Processor.c
index bd778e80d..3cb187de6 100644
--- a/ports/cxd56/common-hal/microcontroller/Processor.c
+++ b/ports/cxd56/common-hal/microcontroller/Processor.c
@@ -50,5 +50,5 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
- return RESET_REASON_POWER_ON;
+ return RESET_REASON_UNKNOWN;
}
diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c
index e044103bc..11e173fe2 100644
--- a/ports/esp32s2/common-hal/alarm/__init__.c
+++ b/ports/esp32s2/common-hal/alarm/__init__.c
@@ -29,15 +29,16 @@
#include "py/objtuple.h"
#include "py/runtime.h"
-#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/time/__init__.h"
+#include "shared-bindings/wifi/__init__.h"
+
+#include "common-hal/alarm/__init__.h"
#include "esp_log.h"
#include "esp_sleep.h"
-#include "esp_wifi.h"
STATIC mp_obj_tuple_t *_deep_sleep_alarms;
@@ -101,7 +102,7 @@ STATIC void setup_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f;
mp_float_t wakeup_in_secs = MAX(0.0f, time_alarm->monotonic_time - now_secs);
const uint64_t sleep_for_us = (uint64_t) (wakeup_in_secs * 1000000);
- ESP_LOGI("ALARM", "Sleep for us: %lld", sleep_for_us);
+ ESP_LOGI("ALARM", "will sleep for us: %lld", sleep_for_us);
esp_sleep_enable_timer_wakeup(sleep_for_us);
}
}
@@ -157,25 +158,41 @@ mp_obj_t common_hal_alarm_wait_until_alarms(size_t n_alarms, const mp_obj_t *ala
return mp_const_none;
}
-mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
+// Is it safe to do a light sleep? Check whether WiFi is on or there are
+// other ongoing tasks that should not be shut down.
+static bool light_sleep_ok(void) {
+ return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj);
+}
+
+mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
if (n_alarms == 0) {
return mp_const_none;
}
- setup_sleep_alarms(n_alarms, alarms);
-
- // Shut down wifi cleanly.
- esp_wifi_stop();
- ESP_LOGI("ALARM", "start light sleep");
- esp_light_sleep_start();
- return common_hal_alarm_get_wake_alarm();
+ if (light_sleep_ok()) {
+ ESP_LOGI("ALARM", "start light sleep");
+ setup_sleep_alarms(n_alarms, alarms);
+ esp_light_sleep_start();
+ return common_hal_alarm_get_wake_alarm();
+ } else {
+ // Don't do an ESP32 light sleep.
+ return common_hal_alarm_wait_until_alarms(n_alarms, alarms);
+ }
}
void common_hal_alarm_exit_and_deep_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
setup_sleep_alarms(n_alarms, alarms);
- // Shut down wifi cleanly.
- esp_wifi_stop();
+ // Raise an exception, which will be processed in main.c.
+ mp_raise_arg1(&mp_type_DeepSleepRequest, NULL);
+}
+
+void common_hal_alarm_prepare_for_deep_sleep(void) {
+ // Turn off WiFi and anything else that should be shut down cleanly.
+ common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, false);
+}
+
+void NORETURN common_hal_alarm_enter_deep_sleep(void) {
ESP_LOGI("ALARM", "start deep sleep");
esp_deep_sleep_start();
}
diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c
index 438d6885d..582a66572 100644
--- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c
+++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c
@@ -29,26 +29,21 @@
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/Pin.h"
-void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, const mp_obj_t pins[], size_t num_pins, bool value, bool all_same_value, bool edge, bool pull) {
- self->pins = mp_obj_new_tuple(num_pins, pins);
+void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) {
+ self->pin = pin;
self->value = value;
- self->all_same_value = all_same_value;
self->edge = edge;
self->pull = pull;
}
-mp_obj_tuple_t *common_hal_alarm_pin_pin_alarm_get_pins(alarm_pin_pin_alarm_obj_t *self) {
- return self->pins;
+mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self) {
+ return self->pin;
}
bool common_hal_alarm_pin_pin_alarm_get_value(alarm_pin_pin_alarm_obj_t *self) {
return self->value;
}
-bool common_hal_alarm_pin_pin_alarm_get_all_same_value(alarm_pin_pin_alarm_obj_t *self) {
- return self->all_same_value;
-}
-
bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self) {
return self->edge;
}
diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h
index d7e7e2552..0eaa7777f 100644
--- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h
+++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h
@@ -29,7 +29,7 @@
typedef struct {
mp_obj_base_t base;
- mp_obj_tuple_t *pins;
+ mcu_pin_obj_t *pin;
bool value;
bool all_same_value;
bool edge;
diff --git a/ports/litex/common-hal/microcontroller/Processor.c b/ports/litex/common-hal/microcontroller/Processor.c
index 013a7ca03..4d4f88288 100644
--- a/ports/litex/common-hal/microcontroller/Processor.c
+++ b/ports/litex/common-hal/microcontroller/Processor.c
@@ -66,5 +66,5 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
- return RESET_REASON_POWER_ON;
+ return RESET_REASON_UNKNOWN;
}
diff --git a/ports/mimxrt10xx/common-hal/microcontroller/Processor.c b/ports/mimxrt10xx/common-hal/microcontroller/Processor.c
index 28fe67db7..efbde35d2 100644
--- a/ports/mimxrt10xx/common-hal/microcontroller/Processor.c
+++ b/ports/mimxrt10xx/common-hal/microcontroller/Processor.c
@@ -73,5 +73,5 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
- return RESET_REASON_POWER_ON;
+ return RESET_REASON_UNKNOWN;
}
diff --git a/ports/nrf/common-hal/microcontroller/Processor.c b/ports/nrf/common-hal/microcontroller/Processor.c
index e2695139c..ab5f29b5d 100644
--- a/ports/nrf/common-hal/microcontroller/Processor.c
+++ b/ports/nrf/common-hal/microcontroller/Processor.c
@@ -123,5 +123,5 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
- return RESET_REASON_POWER_ON;
+ return RESET_REASON_UNKNOWN;
}
diff --git a/ports/stm/common-hal/microcontroller/Processor.c b/ports/stm/common-hal/microcontroller/Processor.c
index d77d287a9..dd04c56dc 100644
--- a/ports/stm/common-hal/microcontroller/Processor.c
+++ b/ports/stm/common-hal/microcontroller/Processor.c
@@ -143,5 +143,5 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
- return RESET_REASON_POWER_ON;
+ return RESET_REASON_UNKNOWN;
}
diff --git a/py/obj.h b/py/obj.h
index e055c9750..066562cc4 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -640,6 +640,10 @@ extern const mp_obj_type_t mp_type_UnicodeError;
extern const mp_obj_type_t mp_type_ValueError;
extern const mp_obj_type_t mp_type_ViperTypeError;
extern const mp_obj_type_t mp_type_ZeroDivisionError;
+#if CIRCUITPY_ALARM
+extern const mp_obj_type_t mp_type_DeepSleepRequest;
+#endif
+
// Constant objects, globally accessible
// The macros are for convenience only
diff --git a/py/objexcept.c b/py/objexcept.c
index 01ba6da9c..afefee2ca 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -319,6 +319,9 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(UnicodeError, ValueError)
//TODO: Implement more UnicodeError subclasses which take arguments
#endif
+#if CIRCUITPY_ALARM
+ MP_DEFINE_EXCEPTION(DeepSleepRequest, BaseException)
+#endif
MP_DEFINE_EXCEPTION(MpyError, ValueError)
/*
MP_DEFINE_EXCEPTION(Warning, Exception)
diff --git a/py/reload.c b/py/reload.c
index 95305f2c9..f9f8a590a 100644
--- a/py/reload.c
+++ b/py/reload.c
@@ -1,6 +1,22 @@
-//
-// Created by Roy Hooper on 2018-05-14.
-//
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 by Roy Hooper
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#include "reload.h"
#include "py/mpstate.h"
diff --git a/py/reload.h b/py/reload.h
index 72e84e5ca..3e8928a32 100644
--- a/py/reload.h
+++ b/py/reload.h
@@ -1,6 +1,22 @@
-//
-// Created by Roy Hooper on 2018-05-14.
-//
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 by Roy Hooper
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
#ifndef CIRCUITPYTHON_RELOAD_H
#define CIRCUITPYTHON_RELOAD_H
diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c
index 195ec6374..c983130a1 100644
--- a/shared-bindings/alarm/__init__.c
+++ b/shared-bindings/alarm/__init__.c
@@ -43,19 +43,21 @@
//|
//| Provides alarms that trigger based on time intervals or on external events, such as pin
//| changes.
-//| The program can simply wait for these alarms, or go into a sleep state and
-//| and be awoken when they trigger.
+//| The program can simply wait for these alarms, or go to sleep and be awoken when they trigger.
//|
//| There are two supported levels of sleep: light sleep and deep sleep.
//|
-//| Light sleep leaves the CPU and RAM powered so the program can resume after sleeping.
-//|
-//| *However, note that on some platforms, light sleep will shut down some communications, including
-//| WiFi and/or Bluetooth.*
+//| Light sleep keeps sufficient state so the program can resume after sleeping.
+//| It does not shut down WiFi, BLE, or other communications, or ongoing activities such
+//| as audio playback. It reduces power consumption to the extent possible that leaves
+//| these continuing activities running. In some cases there may be no decrease in power consumption.
//|
//| Deep sleep shuts down power to nearly all of the microcontroller including the CPU and RAM. This can save
//| a more significant amount of power, but CircuitPython must restart ``code.py`` from the beginning when
//| awakened.
+//|
+//| For both light sleep and deep sleep, if CircuitPython is connected to a host computer,
+//| maintaining the connection takes priority and power consumption may not be reduced.
//| """
//|
@@ -75,45 +77,39 @@ void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) {
}
}
-//| def wait_until_alarms(*alarms: Alarm) -> Alarm:
-//| """Wait for one of the alarms to trigger. The triggering alarm is returned.
-//| is returned, and is also available as `alarm.wake_alarm`. Nothing is shut down
-//| or interrupted. Power consumption will be reduced if possible.
-//|
-//| If no alarms are specified, return immediately.
-//| """
-//| ...
-//|
-STATIC mp_obj_t alarm_wait_until_alarms(size_t n_args, const mp_obj_t *args) {
- validate_objs_are_alarms(n_args, args);
- common_hal_alarm_wait_until_alarms(n_args, args);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_wait_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_wait_until_alarms);
-
-//| def sleep_until_alarms(*alarms: Alarm) -> Alarm:
+//| def light_sleep_until_alarms(*alarms: Alarm) -> Alarm:
//| """Go into a light sleep until awakened one of the alarms. The alarm causing the wake-up
//| is returned, and is also available as `alarm.wake_alarm`.
//|
-//| Some functionality may be shut down during sleep. On ESP32-S2, WiFi is turned off,
-//| and existing connections are broken.
-//|
//| If no alarms are specified, return immediately.
//|
-//| **If CircuitPython is connected to a host computer,** `alarm.sleep_until_alarms()`
-//| **does not go into light sleep.**
-//| Instead, light sleep is simulated by doing `alarm.wait_until_alarms()`,
+//| **If CircuitPython is connected to a host computer, the connection will be maintained,
+//| and the microcontroller may not actually go into a light sleep.**
//| This allows the user to interrupt an existing program with ctrl-C,
-//| and to edit the files in CIRCUITPY, which would not be possible in true light sleep
+//| and to edit the files in CIRCUITPY, which would not be possible in true light sleep.
+//| Thus, to use light sleep and save significant power,
+// it may be necessary to disconnect from the host.
//| """
//| ...
//|
-STATIC mp_obj_t alarm_sleep_until_alarms(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t alarm_light_sleep_until_alarms(size_t n_args, const mp_obj_t *args) {
validate_objs_are_alarms(n_args, args);
- common_hal_alarm_sleep_until_alarms(n_args, args);
+
+ // See if we are connected to a host.
+ // Make sure we have been awake long enough for USB to connect (enumeration delay).
+ int64_t connecting_delay_msec = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - supervisor_ticks_ms64();
+ if (connecting_delay_msec > 0) {
+ common_hal_time_delay_ms(connecting_delay_msec * 1000 / 1024);
+ }
+
+ if (supervisor_workflow_active()) {
+ common_hal_alarm_wait_until_alarms(n_args, args);
+ } else {
+ common_hal_alarm_light_sleep_until_alarms(n_args, args);
+ }
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_sleep_until_alarms);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_light_sleep_until_alarms);
//| def exit_and_deep_sleep_until_alarms(*alarms: Alarm) -> None:
//| """Exit the program and go into a deep sleep, until awakened by one of the alarms.
@@ -130,11 +126,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarms_obj, 1, MP_OBJ_FUN_
//| If no alarms are specified, the microcontroller will deep sleep until reset.
//|
//| **If CircuitPython is connected to a host computer, `alarm.exit_and_deep_sleep_until_alarms()`
-//| does not go into deep sleep.**
-//| Instead, deep sleep is simulated by first doing `alarm.wait_until_alarms()`,
-//| and then, when an alarm triggers, by restarting CircuitPython.
+//| then the connection will be maintained, and the system will not go into deep sleep.**
//| This allows the user to interrupt an existing program with ctrl-C,
//| and to edit the files in CIRCUITPY, which would not be possible in true deep sleep.
+//| Thus, to use deep sleep and save significant power, you will need to disconnect from the host.
//|
//| Here is skeletal example that deep-sleeps and restarts every 60 seconds:
//|
@@ -156,6 +151,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarms_obj, 1, MP_OBJ_FUN_
STATIC mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_obj_t *args) {
validate_objs_are_alarms(n_args, args);
+ // Shut down WiFi, etc.
+ common_hal_alarm_prepare_for_deep_sleep();
+
+ // See if we are connected to a host.
// Make sure we have been awake long enough for USB to connect (enumeration delay).
int64_t connecting_delay_msec = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - supervisor_ticks_ms64();
if (connecting_delay_msec > 0) {
@@ -163,6 +162,7 @@ STATIC mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o
}
if (supervisor_workflow_active()) {
+ // Simulate deep sleep by waiting for an alarm and then restarting when done.
common_hal_alarm_wait_until_alarms(n_args, args);
reload_requested = true;
supervisor_set_run_reason(RUN_REASON_STARTUP);
@@ -175,9 +175,6 @@ STATIC mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_exit_and_deep_sleep_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_exit_and_deep_sleep_until_alarms);
-//| """The `alarm.pin` module contains alarm attributes and classes related to pins.
-//| """
-//|
STATIC const mp_map_elem_t alarm_pin_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin) },
@@ -191,9 +188,6 @@ STATIC const mp_obj_module_t alarm_pin_module = {
.globals = (mp_obj_dict_t*)&alarm_pin_globals,
};
-//| """The `alarm.time` module contains alarm attributes and classes related to time-keeping.
-//| """
-//|
STATIC const mp_map_elem_t alarm_time_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) },
@@ -213,7 +207,7 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = {
// wake_alarm is a mutable attribute.
{ MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none },
- { MP_ROM_QSTR(MP_QSTR_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_sleep_until_alarms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_light_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_light_sleep_until_alarms_obj) },
{ MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep_until_alarms),
MP_OBJ_FROM_PTR(&alarm_exit_and_deep_sleep_until_alarms_obj) },
diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h
index 26dbb2897..380c65ea8 100644
--- a/shared-bindings/alarm/__init__.h
+++ b/shared-bindings/alarm/__init__.h
@@ -32,8 +32,10 @@
#include "common-hal/alarm/__init__.h"
extern mp_obj_t common_hal_alarm_wait_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
-extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
+extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
extern void common_hal_alarm_exit_and_deep_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
+extern void common_hal_alarm_prepare_for_deep_sleep(void);
+extern NORETURN void common_hal_alarm_enter_deep_sleep(void);
// Used by wake-up code.
extern void common_hal_alarm_set_wake_alarm(mp_obj_t alarm);
diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c
index a6497d4cd..a435407ac 100644
--- a/shared-bindings/alarm/pin/PinAlarm.c
+++ b/shared-bindings/alarm/pin/PinAlarm.c
@@ -38,18 +38,16 @@
//| class PinAlarm:
//| """Trigger an alarm when a pin changes state."""
//|
-//| def __init__(self, *pins: microcontroller.Pin, value: bool, all_same_value: bool = False, edge: bool = False, pull: bool = False) -> None:
+//| def __init__(self, pin: microcontroller.Pin, value: bool, edge: bool = False, pull: bool = False) -> None:
//| """Create an alarm triggered by a `microcontroller.Pin` level. The alarm is not active
//| until it is passed to an `alarm`-enabling function, such as `alarm.sleep_until_alarms()` or
//| `alarm.exit_and_deep_sleep_until_alarms()`.
//|
-//| :param microcontroller.Pin \*pins: The pins to monitor. On some ports, the choice of pins
+//| :param microcontroller.Pin pin: The pin to monitor. On some ports, the choice of pin
//| may be limited due to hardware restrictions, particularly for deep-sleep alarms.
//| :param bool value: When active, trigger when the pin value is high (``True``) or low (``False``).
//| On some ports, multiple `PinAlarm` objects may need to have coordinated values
//| for deep-sleep alarms.
-//| :param bool all_same_value: If ``True``, all pins listed must be at ``value`` to trigger the alarm.
-//| If ``False``, any one of the pins going to ``value`` will trigger the alarm.
//| :param bool edge: If ``True``, trigger only when there is a transition to the specified
//| value of ``value``. If ``True``, if the alarm becomes active when the pin value already
//| matches ``value``, the alarm is not triggered: the pin must transition from ``not value``
@@ -65,47 +63,44 @@
STATIC mp_obj_t alarm_pin_pin_alarm_make_new(const mp_obj_type_t *type, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
alarm_pin_pin_alarm_obj_t *self = m_new_obj(alarm_pin_pin_alarm_obj_t);
self->base.type = &alarm_pin_pin_alarm_type;
- enum { ARG_value, ARG_all_same_value, ARG_edge, ARG_pull };
+ enum { ARG_pin, ARG_value, ARG_edge, ARG_pull };
static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_BOOL },
- { MP_QSTR_all_same_value, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_edge, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_pull, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- for (size_t i = 0; i < n_args; i ++) {
- validate_obj_is_free_pin(pos_args[i]);
- }
+ mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
- common_hal_alarm_pin_pin_alarm_construct(
- self, pos_args, n_args,
+ common_hal_alarm_pin_pin_alarm_construct(self,
+ pin,
args[ARG_value].u_bool,
- args[ARG_all_same_value].u_bool,
args[ARG_edge].u_bool,
args[ARG_pull].u_bool);
return MP_OBJ_FROM_PTR(self);
}
-//| pins: Tuple[microcontroller.Pin]
-//| """The trigger pins."""
+//| pin: microcontroller.Pin
+//| """The trigger pin."""
//|
-STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_pins(mp_obj_t self_in) {
+STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_pin(mp_obj_t self_in) {
alarm_pin_pin_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return common_hal_alarm_pin_pin_alarm_get_pins(self);
+ return common_hal_alarm_pin_pin_alarm_get_pin(self);
}
-MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pin_alarm_get_pins_obj, alarm_pin_pin_alarm_obj_get_pins);
+MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pin_alarm_get_pin_obj, alarm_pin_pin_alarm_obj_get_pin);
-const mp_obj_property_t alarm_pin_pin_alarm_pins_obj = {
+const mp_obj_property_t alarm_pin_pin_alarm_pin_obj = {
.base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&alarm_pin_pin_alarm_get_pins_obj,
+ .proxy = {(mp_obj_t)&alarm_pin_pin_alarm_get_pin_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
-//| value: Tuple[microcontroller.Pin]
+//| value: bool
//| """The value on which to trigger."""
//|
STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_value(mp_obj_t self_in) {
@@ -122,7 +117,7 @@ const mp_obj_property_t alarm_pin_pin_alarm_value_obj = {
};
STATIC const mp_rom_map_elem_t alarm_pin_pin_alarm_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_pins), MP_ROM_PTR(&alarm_pin_pin_alarm_pins_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&alarm_pin_pin_alarm_pin_obj) },
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&alarm_pin_pin_alarm_value_obj) },
};
diff --git a/shared-bindings/alarm/pin/PinAlarm.h b/shared-bindings/alarm/pin/PinAlarm.h
index cb6946812..49ba71089 100644
--- a/shared-bindings/alarm/pin/PinAlarm.h
+++ b/shared-bindings/alarm/pin/PinAlarm.h
@@ -34,8 +34,8 @@
extern const mp_obj_type_t alarm_pin_pin_alarm_type;
-void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, const mp_obj_t pins[], size_t num_pins, bool value, bool all_same_value, bool edge, bool pull);
-extern mp_obj_tuple_t *common_hal_alarm_pin_pin_alarm_get_pins(alarm_pin_pin_alarm_obj_t *self);
+void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull);
+extern mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self);
extern bool common_hal_alarm_pin_pin_alarm_get_value(alarm_pin_pin_alarm_obj_t *self);
extern bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self);
extern bool common_hal_alarm_pin_pin_alarm_get_pull(alarm_pin_pin_alarm_obj_t *self);