deep sleep working; deep sleep delay when connected
This commit is contained in:
parent
ef0830bfe2
commit
104a089677
82
main.c
82
main.c
@ -66,9 +66,6 @@
|
||||
|
||||
#include "boards/board.h"
|
||||
|
||||
// REMOVE ***********
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CIRCUITPY_ALARM
|
||||
#include "shared-bindings/alarm/__init__.h"
|
||||
#endif
|
||||
@ -98,12 +95,6 @@
|
||||
#include "common-hal/canio/CAN.h"
|
||||
#endif
|
||||
|
||||
// How long to wait for host to start connecting..
|
||||
#define CIRCUITPY_USB_CONNECTING_DELAY 1
|
||||
|
||||
// How long to flash errors on the RGB status LED before going to sleep (secs)
|
||||
#define CIRCUITPY_FLASH_ERROR_PERIOD 10
|
||||
|
||||
#if MICROPY_ENABLE_PYSTACK
|
||||
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
|
||||
#endif
|
||||
@ -259,17 +250,6 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
||||
}
|
||||
}
|
||||
|
||||
// Should we go into deep sleep when program finishes?
|
||||
// Normally we won't deep sleep if there was an error or if we are connected to a host
|
||||
// but either of those can be enabled.
|
||||
// It's ok to deep sleep if we're not connected to a host, but we need to make sure
|
||||
// we're giving enough time for USB to start to connect
|
||||
STATIC bool deep_sleep_allowed(void) {
|
||||
return
|
||||
(ok || supervisor_workflow_get_allow_deep_sleep_on_error()) &&
|
||||
!supervisor_workflow_connecting()
|
||||
(supervisor_ticks_ms64() > CIRCUITPY_USB_CONNECTING_DELAY * 1024);
|
||||
|
||||
STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
bool serial_connected_at_start = serial_connected();
|
||||
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
|
||||
@ -290,10 +270,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
new_status_color(MAIN_RUNNING);
|
||||
|
||||
static const char * const supported_filenames[] = STRING_LIST("code.txt", "code.py", "main.py", "main.txt");
|
||||
static const char * const supported_filenames[] = STRING_LIST(
|
||||
"code.txt", "code.py", "main.py", "main.txt");
|
||||
#if CIRCUITPY_FULL_BUILD
|
||||
static const char * const double_extension_filenames[] = STRING_LIST("code.txt.py", "code.py.txt", "code.txt.txt","code.py.py",
|
||||
"main.txt.py", "main.py.txt", "main.txt.txt","main.py.py");
|
||||
static const char * const double_extension_filenames[] = STRING_LIST(
|
||||
"code.txt.py", "code.py.txt", "code.txt.txt","code.py.py",
|
||||
"main.txt.py", "main.py.txt", "main.txt.txt","main.py.py");
|
||||
#endif
|
||||
|
||||
stack_resize();
|
||||
@ -319,7 +301,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
// Program has finished running.
|
||||
|
||||
// Display a different completion message if the user has no USB attached (cannot save files)
|
||||
if (!serial_connected_at_start && !deep_sleep_allowed()) {
|
||||
if (!serial_connected_at_start) {
|
||||
serial_write_compressed(translate("\nCode done running. Waiting for reload.\n"));
|
||||
}
|
||||
|
||||
@ -327,16 +309,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
bool refreshed_epaper_display = false;
|
||||
#endif
|
||||
|
||||
rgb_status_animation_t animation;
|
||||
bool ok = result.return_code != PYEXEC_EXCEPTION;
|
||||
|
||||
#if CIRCUITPY_ALARM
|
||||
// Enable pin or time alarms before sleeping.
|
||||
// If immediate_wake is true, then there's an alarm that would trigger immediately,
|
||||
// so don't sleep.
|
||||
bool immediate_wake = !common_hal_alarm_enable_deep_sleep_alarms();
|
||||
#endif
|
||||
|
||||
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
|
||||
while (true) {
|
||||
|
||||
@ -360,12 +334,10 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
if (!serial_connected_at_start) {
|
||||
print_code_py_status_message(safe_mode);
|
||||
}
|
||||
// We won't be going into the REPL if we're going to sleep.
|
||||
if (!deep_sleep_allowed()) {
|
||||
print_safe_mode_message(safe_mode);
|
||||
serial_write("\n");
|
||||
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
|
||||
}
|
||||
|
||||
print_safe_mode_message(safe_mode);
|
||||
serial_write("\n");
|
||||
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
|
||||
}
|
||||
if (serial_connected_before_animation && !serial_connected()) {
|
||||
serial_connected_at_start = false;
|
||||
@ -379,37 +351,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool animation_done = false;
|
||||
|
||||
if (deep_sleep_allowed() && ok) {
|
||||
// Skip animation if everything is OK.
|
||||
animation_done = true;
|
||||
} else {
|
||||
animation_done = tick_rgb_status_animation(&animation);
|
||||
}
|
||||
// Do an error animation only once before deep-sleeping.
|
||||
if (animation_done) {
|
||||
if (immediate_wake) {
|
||||
// Don't sleep, we are already supposed to wake up.
|
||||
return true;
|
||||
}
|
||||
if (deep_sleep_allowed()) {
|
||||
common_hal_mcu_deep_sleep();
|
||||
// Does not return.
|
||||
}
|
||||
|
||||
// Wake up every so often to flash the error code.
|
||||
if (!ok) {
|
||||
port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024);
|
||||
} else {
|
||||
int64_t remaining_connecting_wait =
|
||||
CIRCUITPY_USB_CONNECTING_DELAY * 1024 - supervisor_ticks_ms64();
|
||||
if (remaining_connecting_wait > 0) {
|
||||
port_interrupt_after_ticks(remaining_connecting_wait);
|
||||
}
|
||||
port_sleep_until_interrupt();
|
||||
}
|
||||
}
|
||||
tick_rgb_status_animation(&animation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,10 +84,6 @@ void common_hal_mcu_reset(void) {
|
||||
reset();
|
||||
}
|
||||
|
||||
void common_hal_mcu_deep_sleep(void) {
|
||||
//deep sleep call here
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
|
@ -81,10 +81,6 @@ void common_hal_mcu_reset(void) {
|
||||
boardctl(BOARDIOC_RESET, 0);
|
||||
}
|
||||
|
||||
void common_hal_mcu_deep_sleep(void) {
|
||||
//deep sleep call here
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART2_RXD), MP_ROM_PTR(&pin_UART2_RXD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART2_TXD), MP_ROM_PTR(&pin_UART2_TXD) },
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
@ -77,12 +77,10 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
}
|
||||
|
||||
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
STATIC void setup_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
bool time_alarm_set = false;
|
||||
alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_NULL;
|
||||
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) {
|
||||
mp_raise_NotImplementedError(translate("PinAlarm deep sleep not yet implemented"));
|
||||
@ -91,32 +89,32 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
|
||||
if (time_alarm_set) {
|
||||
mp_raise_ValueError(translate("Only one alarm.time alarm can be set."));
|
||||
}
|
||||
time_alarm = MP_OBJ_TO_PTR(alarms[i]);
|
||||
time_alarm_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
_deep_sleep_alarms = mp_obj_new_tuple(n_alarms, alarms);
|
||||
if (time_alarm != MP_OBJ_NULL) {
|
||||
// Compute how long to actually sleep, considering the time now.
|
||||
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);
|
||||
esp_sleep_enable_timer_wakeup((uint64_t) (wakeup_in_secs * 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
// Return false if we should wake up immediately because a time alarm is in the past
|
||||
// or otherwise already triggered.
|
||||
bool common_hal_alarm_enable_deep_sleep_alarms(void) {
|
||||
for (size_t i = 0; i < _deep_sleep_alarms->len; i++) {
|
||||
mp_obj_t alarm = _deep_sleep_alarms->items[i];
|
||||
if (MP_OBJ_IS_TYPE(alarm, &alarm_pin_pin_alarm_type)) {
|
||||
// TODO: handle pin alarms
|
||||
mp_raise_NotImplementedError(translate("PinAlarm deep sleep not yet implemented"));
|
||||
}
|
||||
else if (MP_OBJ_IS_TYPE(alarm, &alarm_time_time_alarm_type)) {
|
||||
alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_TO_PTR(alarm);
|
||||
mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f;
|
||||
// Compute how long to actually sleep, considering hte time now.
|
||||
mp_float_t wakeup_in_secs = time_alarm->monotonic_time - now_secs;
|
||||
if (wakeup_in_secs <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
esp_sleep_enable_timer_wakeup((uint64_t) (wakeup_in_secs * 1000000));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
setup_alarms(n_alarms, alarms);
|
||||
|
||||
// Shut down wifi cleanly.
|
||||
esp_wifi_stop();
|
||||
esp_light_sleep_start();
|
||||
return common_hal_alarm_get_wake_alarm();
|
||||
}
|
||||
|
||||
void common_hal_alarm_exit_and_deep_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
setup_alarms(n_alarms, alarms);
|
||||
|
||||
// Shut down wifi cleanly.
|
||||
esp_wifi_stop();
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
@ -81,12 +81,6 @@ void common_hal_mcu_reset(void) {
|
||||
while(1);
|
||||
}
|
||||
|
||||
void NORETURN common_hal_mcu_deep_sleep(void) {
|
||||
// Shut down wifi cleanly.
|
||||
esp_wifi_stop();
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
|
@ -89,10 +89,6 @@ void common_hal_mcu_reset(void) {
|
||||
while(1);
|
||||
}
|
||||
|
||||
void common_hal_mcu_deep_sleep(void) {
|
||||
//deep sleep call here
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
|
@ -86,10 +86,6 @@ void common_hal_mcu_reset(void) {
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void common_hal_mcu_deep_sleep(void) {
|
||||
//deep sleep call here
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
|
@ -95,10 +95,6 @@ void common_hal_mcu_reset(void) {
|
||||
reset_cpu();
|
||||
}
|
||||
|
||||
void common_hal_mcu_deep_sleep(void) {
|
||||
//deep sleep call here
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
|
@ -81,10 +81,6 @@ void common_hal_mcu_reset(void) {
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void common_hal_mcu_deep_sleep(void) {
|
||||
//deep sleep call here
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
|
||||
// It currently only has properties, and no state.
|
||||
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
|
||||
|
@ -54,12 +54,12 @@ FrameBuffer = Union[rgbmatrix.RGBMatrix]
|
||||
"""
|
||||
|
||||
Alarm = Union[
|
||||
alarm.pin.PinAlarm, alarm.time.DurationAlarm
|
||||
alarm.pin.PinAlarm, alarm.time.TimeAlarm
|
||||
]
|
||||
"""Classes that implement alarms for sleeping and asynchronous notification.
|
||||
|
||||
- `alarm.pin.PinAlarm`
|
||||
- `alarm.time.DurationAlarm`
|
||||
- `alarm.time.TimeAlarm`
|
||||
|
||||
You can use these alarms to wake from light or deep sleep.
|
||||
"""
|
||||
|
@ -30,6 +30,15 @@
|
||||
#include "shared-bindings/alarm/__init__.h"
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
#include "supervisor/shared/workflow.h"
|
||||
|
||||
// Wait this long to see if USB is being connected (enumeration starting).
|
||||
#define CIRCUITPY_USB_CONNECTING_DELAY 1
|
||||
// Wait this long before going into deep sleep if connected. This
|
||||
// allows the user to ctrl-C before deep sleep starts.
|
||||
#define CIRCUITPY_USB_CONNECTED_DEEP_SLEEP_DELAY 5
|
||||
|
||||
//| """Power-saving light and deep sleep. Alarms can be set to wake up from sleep.
|
||||
//|
|
||||
@ -44,16 +53,12 @@
|
||||
//| Deep sleep shuts down power to nearly all of the chip including the CPU and RAM. This can save
|
||||
//| a more significant amount of power, but CircuitPython must start ``code.py`` from the beginning when
|
||||
//| awakened.
|
||||
//| """
|
||||
|
||||
//|
|
||||
//| An error includes an uncaught exception, or sys.exit() called with a non-zero argument
|
||||
//|
|
||||
//| To set alarms for deep sleep use `alarm.set_deep_sleep_alarms()` they will apply to next deep sleep only."""
|
||||
//|
|
||||
//| wake_alarm: Alarm
|
||||
//| """The most recent alarm to wake us up from a sleep (light or deep.)"""
|
||||
//|
|
||||
|
||||
void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) {
|
||||
for (size_t i = 0; i < n_args; i++) {
|
||||
if (MP_OBJ_IS_TYPE(objs[i], &alarm_pin_pin_alarm_type) ||
|
||||
@ -88,12 +93,38 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarms_obj, 1, MP_OBJ_FUN_
|
||||
//| For time-base alarms, currently, an `alarm.time.TimeAlarm()` is created.
|
||||
//|
|
||||
//| If no alarms are specified, the microcontroller will deep sleep until reset.
|
||||
//|
|
||||
//| If CircuitPython is unconnected to a host computer, go into deep sleep immediately.
|
||||
//| But if it already connected or in the process of connecting to a host computer, wait at least
|
||||
//| five seconds after starting code.py before entering deep sleep.
|
||||
//| This allows interrupting a program that would otherwise go into deep sleep too quickly
|
||||
//| to interrupt from the keyboard.
|
||||
//| """
|
||||
//| ...
|
||||
//|
|
||||
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);
|
||||
common_hal_exit_and_deep_sleep_until_alarms(n_args, args);
|
||||
|
||||
int64_t connecting_delay_msec = CIRCUITPY_USB_CONNECTING_DELAY * 1024 - supervisor_ticks_ms64();
|
||||
if (connecting_delay_msec > 0) {
|
||||
common_hal_time_delay_ms(connecting_delay_msec * 1000 / 1024);
|
||||
}
|
||||
|
||||
// If connected, wait for the program to be running at least as long as
|
||||
// CIRCUITPY_USB_CONNECTED_DEEP_SLEEP_DELAY. This allows a user to ctrl-C the running
|
||||
// program in case it is in a tight deep sleep loop that would otherwise be difficult
|
||||
// or impossible to interrupt.
|
||||
// Indicate that we're delaying with the SAFE_MODE color.
|
||||
int64_t delay_before_sleeping_msec =
|
||||
supervisor_ticks_ms64() - CIRCUITPY_USB_CONNECTED_DEEP_SLEEP_DELAY * 1000;
|
||||
if (supervisor_workflow_connecting() && delay_before_sleeping_msec > 0) {
|
||||
temp_status_color(SAFE_MODE);
|
||||
common_hal_time_delay_ms(delay_before_sleeping_msec);
|
||||
clear_temp_status();
|
||||
}
|
||||
|
||||
common_hal_alarm_exit_and_deep_sleep_until_alarms(n_args, args);
|
||||
// Does not return.
|
||||
return mp_const_none;
|
||||
}
|
||||
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);
|
||||
|
@ -32,8 +32,7 @@
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
|
||||
extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
|
||||
extern bool common_hal_alarm_enable_deep_sleep_alarms(void);
|
||||
extern void common_hal_alarm_set_deep_sleep_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);
|
||||
|
||||
// Used by wake-up code.
|
||||
extern void common_hal_alarm_set_wake_alarm(mp_obj_t alarm);
|
||||
|
@ -41,7 +41,7 @@
|
||||
//| def __init__(self, *pins: microcontroller.Pin, value: bool, all_same_value: bool = False, 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.set_deep_sleep_alarms()`.
|
||||
//| `alarm.exit_and_deep_sleep_until_alarms()`.
|
||||
//|
|
||||
//| :param microcontroller.Pin \*pins: The pins to monitor. On some ports, the choice of pins
|
||||
//| may be limited due to hardware restrictions, particularly for deep-sleep alarms.
|
||||
|
@ -24,25 +24,32 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/board/__init__.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
|
||||
mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
|
||||
mp_raise_RuntimeError(translate("RTC is not supported on this board"));
|
||||
}
|
||||
#endif
|
||||
|
||||
//| class TimeAlarm:
|
||||
//| """Trigger an alarm when `time.monotonic()` reaches the given value."""
|
||||
//| """Trigger an alarm when the specified time is reached."""
|
||||
//|
|
||||
//| def __init__(self, monotonic_time: float) -> None:
|
||||
//| def __init__(self, monotonic_time: Optional[Float] = None, epoch_time: Optional[int] = None) -> None:
|
||||
//| """Create an alarm that will be triggered when `time.monotonic()` would equal
|
||||
//| ``monotonic_time``.
|
||||
//| ``monotonic_time``, or when `time.time()` would equal ``epoch_time``.
|
||||
//| Only one of the two arguments can be given.
|
||||
//| The alarm is not active until it is passed to an
|
||||
//| `alarm`-enabling function, such as `alarm.sleep_until_alarms()` or
|
||||
//| `alarm.set_deep_sleep_alarms()`.
|
||||
//| `alarm.exit_and_deep_sleep_until_alarms()`.
|
||||
//|
|
||||
//| If the given time is in the past when sleep occurs, the alarm will be triggered
|
||||
//| immediately.
|
||||
@ -50,21 +57,64 @@
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t alarm_time_time_alarm_make_new(const mp_obj_type_t *type,
|
||||
mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
mp_arg_check_num(n_args, kw_args, 1, 1, false);
|
||||
|
||||
mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
alarm_time_time_alarm_obj_t *self = m_new_obj(alarm_time_time_alarm_obj_t);
|
||||
self->base.type = &alarm_time_time_alarm_type;
|
||||
|
||||
mp_float_t secs = mp_obj_get_float(args[0]);
|
||||
enum { ARG_monotonic_time, ARG_epoch_time };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_monotonic_time, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_epoch_time, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
common_hal_alarm_time_time_alarm_construct(self, secs);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
bool have_monotonic = args[ARG_monotonic_time].u_obj != mp_const_none;
|
||||
bool have_epoch = args[ARG_epoch_time].u_obj != mp_const_none;
|
||||
|
||||
if (!(have_monotonic ^ have_epoch)) {
|
||||
mp_raise_ValueError(translate("Supply one of monotonic_time or epoch_time"));
|
||||
}
|
||||
|
||||
mp_float_t monotonic_time = 0; // To avoid compiler warning.
|
||||
if (have_monotonic) {
|
||||
monotonic_time = mp_obj_get_float(args[ARG_monotonic_time].u_obj);
|
||||
}
|
||||
|
||||
mp_float_t monotonic_time_now = common_hal_time_monotonic_ms() / 1000.0;
|
||||
|
||||
if (have_epoch) {
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
|
||||
mp_raise_ValueError(translate("epoch_time not supported on this board"));
|
||||
#else
|
||||
mp_uint_t epoch_time_secs = mp_obj_int_get_checked(args[ARG_epoch_time].u_obj);
|
||||
|
||||
timeutils_struct_time_t tm;
|
||||
struct_time_to_tm(rtc_get_time_source_time(), &tm);
|
||||
mp_uint_t epoch_secs_now = timeutils_seconds_since_epoch(tm.tm_year, tm.tm_mon, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
// How far in the future (in secs) is the requested time?
|
||||
mp_int_t epoch_diff = epoch_time_secs - epoch_secs_now;
|
||||
// Convert it to a future monotonic time.
|
||||
monotonic_time = monotonic_time_now + epoch_diff;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (monotonic_time < monotonic_time_now) {
|
||||
mp_raise_ValueError(translate("Time is in the past."));
|
||||
}
|
||||
|
||||
common_hal_alarm_time_time_alarm_construct(self, monotonic_time);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| monotonic_time: float
|
||||
//| """The time at which to trigger, based on the `time.monotonic()` clock."""
|
||||
//| """When this time is reached, the alarm will trigger, based on the `time.monotonic()` clock.
|
||||
//| The time may be given as ``epoch_time`` in the constructor, but it is returned
|
||||
//| by this property only as a `time.monotonic()` time.
|
||||
//| """
|
||||
//|
|
||||
STATIC mp_obj_t alarm_time_time_alarm_obj_get_monotonic_time(mp_obj_t self_in) {
|
||||
alarm_time_time_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
@ -43,8 +43,6 @@ extern void common_hal_mcu_enable_interrupts(void);
|
||||
extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
|
||||
extern void common_hal_mcu_reset(void);
|
||||
|
||||
extern void NORETURN common_hal_mcu_deep_sleep(void);
|
||||
|
||||
extern const mp_obj_dict_t mcu_pin_globals;
|
||||
|
||||
extern const mcu_processor_obj_t common_hal_mcu_processor_obj;
|
||||
|
Loading…
x
Reference in New Issue
Block a user