summaryrefslogtreecommitdiff
path: root/shared-bindings
diff options
context:
space:
mode:
Diffstat (limited to 'shared-bindings')
-rw-r--r--shared-bindings/_typing/__init__.pyi14
-rw-r--r--shared-bindings/alarm/__init__.c233
-rw-r--r--shared-bindings/alarm/__init__.h43
-rw-r--r--shared-bindings/alarm/pin/PinAlarm.c131
-rw-r--r--shared-bindings/alarm/pin/PinAlarm.h43
-rw-r--r--shared-bindings/alarm/time/TimeAlarm.c143
-rw-r--r--shared-bindings/alarm/time/TimeAlarm.h39
-rw-r--r--shared-bindings/audiopwmio/__init__.h6
-rw-r--r--shared-bindings/i2cperipheral/I2CPeripheral.c8
-rw-r--r--shared-bindings/microcontroller/Processor.c18
-rw-r--r--shared-bindings/microcontroller/Processor.h2
-rw-r--r--shared-bindings/microcontroller/ResetReason.c77
-rw-r--r--shared-bindings/microcontroller/ResetReason.h45
-rw-r--r--shared-bindings/microcontroller/__init__.c11
-rw-r--r--shared-bindings/microcontroller/__init__.h4
-rw-r--r--shared-bindings/random/__init__.h2
-rw-r--r--shared-bindings/supervisor/RunReason.c62
-rw-r--r--shared-bindings/supervisor/RunReason.h36
-rwxr-xr-xshared-bindings/supervisor/Runtime.c27
-rwxr-xr-xshared-bindings/supervisor/Runtime.h3
-rw-r--r--shared-bindings/supervisor/__init__.c9
-rw-r--r--shared-bindings/time/__init__.c5
-rw-r--r--shared-bindings/time/__init__.h2
23 files changed, 935 insertions, 28 deletions
diff --git a/shared-bindings/_typing/__init__.pyi b/shared-bindings/_typing/__init__.pyi
index 48e68a8d5..cc4a0a439 100644
--- a/shared-bindings/_typing/__init__.pyi
+++ b/shared-bindings/_typing/__init__.pyi
@@ -2,6 +2,9 @@
from typing import Union
+import alarm
+import alarm.pin
+import alarm.time
import array
import audiocore
import audiomixer
@@ -52,3 +55,14 @@ FrameBuffer = Union[rgbmatrix.RGBMatrix]
- `rgbmatrix.RGBMatrix`
"""
+
+Alarm = Union[
+ alarm.pin.PinAlarm, alarm.time.TimeAlarm
+]
+"""Classes that implement alarms for sleeping and asynchronous notification.
+
+ - `alarm.pin.PinAlarm`
+ - `alarm.time.TimeAlarm`
+
+ You can use these alarms to wake up from light or deep sleep.
+"""
diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c
new file mode 100644
index 000000000..c983130a1
--- /dev/null
+++ b/shared-bindings/alarm/__init__.c
@@ -0,0 +1,233 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 "py/obj.h"
+#include "py/reload.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/supervisor/Runtime.h"
+#include "shared-bindings/time/__init__.h"
+#include "supervisor/shared/autoreload.h"
+#include "supervisor/shared/workflow.h"
+
+// Wait this long imediately after startup to see if we are connected to USB.
+#define CIRCUITPY_USB_CONNECTED_SLEEP_DELAY 5
+
+//| """Alarms and sleep
+//|
+//| 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 to sleep and be awoken when they trigger.
+//|
+//| There are two supported levels of sleep: light sleep and deep sleep.
+//|
+//| 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.
+//| """
+
+//|
+//| wake_alarm: Alarm
+//| """The most recently triggered alarm. If CircuitPython was sleeping, the alarm the woke it from sleep."""
+//|
+
+// wake_alarm is implemented as a dictionary entry, so there's no code here.
+
+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) ||
+ MP_OBJ_IS_TYPE(objs[i], &alarm_time_time_alarm_type)) {
+ continue;
+ }
+ mp_raise_TypeError_varg(translate("Expected an 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`.
+//|
+//| If no alarms are specified, return immediately.
+//|
+//| **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.
+//| Thus, to use light sleep and save significant power,
+// it may be necessary to disconnect from the host.
+//| """
+//| ...
+//|
+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);
+
+ // 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_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.
+//| This function does not return.
+//|
+//| When awakened, the microcontroller will restart and will run ``boot.py`` and ``code.py``
+//| from the beginning.
+//|
+//| After restart, an alarm *equivalent* to the one that caused the wake-up
+//| will be available as `alarm.wake_alarm`.
+//| Its type and/or attributes may not correspond exactly to the original alarm.
+//| 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 connected to a host computer, `alarm.exit_and_deep_sleep_until_alarms()`
+//| 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:
+//|
+//| .. code-block:: python
+//|
+//| import alarm
+//| import time
+//|
+//| print("Waking up")
+//|
+//| # Set an alarm for 60 seconds from now.
+//| time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 60)
+//|
+//| # Deep sleep until the alarm goes off. Then restart the program.
+//| alarm.exit_and_deep_sleep_until_alarms(time_alarm)
+//| """
+//| ...
+//|
+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) {
+ common_hal_time_delay_ms(connecting_delay_msec * 1000 / 1024);
+ }
+
+ 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);
+ mp_raise_reload_exception();
+ } else {
+ 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);
+
+STATIC const mp_map_elem_t alarm_pin_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin) },
+
+ { MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pin_alarm_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(alarm_pin_globals, alarm_pin_globals_table);
+
+STATIC const mp_obj_module_t alarm_pin_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&alarm_pin_globals,
+};
+
+STATIC const mp_map_elem_t alarm_time_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) },
+
+ { MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_time_alarm_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(alarm_time_globals, alarm_time_globals_table);
+
+STATIC const mp_obj_module_t alarm_time_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&alarm_time_globals,
+};
+
+STATIC mp_map_elem_t alarm_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) },
+
+ // wake_alarm is a mutable attribute.
+ { MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none },
+
+ { 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) },
+
+ { MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module) },
+ { MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module) }
+
+};
+STATIC MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table);
+
+void common_hal_alarm_set_wake_alarm(mp_obj_t alarm) {
+ // Equivalent of:
+ // alarm.wake_alarm = alarm
+ mp_map_elem_t *elem =
+ mp_map_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_wake_alarm), MP_MAP_LOOKUP);
+ if (elem) {
+ elem->value = alarm;
+ }
+}
+
+const mp_obj_module_t alarm_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&alarm_module_globals,
+};
diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h
new file mode 100644
index 000000000..380c65ea8
--- /dev/null
+++ b/shared-bindings/alarm/__init__.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H
+
+#include "py/obj.h"
+
+#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_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);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H
diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c
new file mode 100644
index 000000000..7a5617142
--- /dev/null
+++ b/shared-bindings/alarm/pin/PinAlarm.c
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 "shared-bindings/board/__init__.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/alarm/pin/PinAlarm.h"
+
+#include "py/nlr.h"
+#include "py/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+//| class PinAlarm:
+//| """Trigger an alarm when a pin changes state."""
+//|
+//| 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.light_sleep_until_alarms()` or
+//| `alarm.exit_and_deep_sleep_until_alarms()`.
+//|
+//| :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 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``
+//| to ``value`` to trigger the alarm. On some ports, edge-triggering may not be available,
+//| particularly for deep-sleep alarms.
+//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to the level opposite
+//| that of ``value``. For instance, if ``value`` is set to ``True``, setting ``pull``
+//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal
+//| pulls it high.
+//| """
+//| ...
+//|
+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_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_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);
+
+ mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
+
+ common_hal_alarm_pin_pin_alarm_construct(self,
+ pin,
+ args[ARG_value].u_bool,
+ args[ARG_edge].u_bool,
+ args[ARG_pull].u_bool);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| pin: microcontroller.Pin
+//| """The trigger pin."""
+//|
+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_pin(self);
+}
+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_pin_obj = {
+ .base.type = &mp_type_property,
+ .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: bool
+//| """The value on which to trigger."""
+//|
+STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_value(mp_obj_t self_in) {
+ alarm_pin_pin_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(common_hal_alarm_pin_pin_alarm_get_value(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pin_alarm_get_value_obj, alarm_pin_pin_alarm_obj_get_value);
+
+const mp_obj_property_t alarm_pin_pin_alarm_value_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&alarm_pin_pin_alarm_get_value_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t alarm_pin_pin_alarm_locals_dict_table[] = {
+ { 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) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(alarm_pin_pin_alarm_locals_dict, alarm_pin_pin_alarm_locals_dict_table);
+
+const mp_obj_type_t alarm_pin_pin_alarm_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PinAlarm,
+ .make_new = alarm_pin_pin_alarm_make_new,
+ .locals_dict = (mp_obj_t)&alarm_pin_pin_alarm_locals_dict,
+};
diff --git a/shared-bindings/alarm/pin/PinAlarm.h b/shared-bindings/alarm/pin/PinAlarm.h
new file mode 100644
index 000000000..49ba71089
--- /dev/null
+++ b/shared-bindings/alarm/pin/PinAlarm.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H
+
+#include "py/obj.h"
+#include "py/objtuple.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/alarm/pin/PinAlarm.h"
+
+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, 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);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H
diff --git a/shared-bindings/alarm/time/TimeAlarm.c b/shared-bindings/alarm/time/TimeAlarm.c
new file mode 100644
index 000000000..1c4d976ad
--- /dev/null
+++ b/shared-bindings/alarm/time/TimeAlarm.c
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 "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 the specified time is reached."""
+//|
+//| 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``, 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.light_sleep_until_alarms()` or
+//| `alarm.exit_and_deep_sleep_until_alarms()`.
+//|
+//| If the given time is in the past when sleep occurs, the alarm will be triggered
+//| immediately.
+//| """
+//| ...
+//|
+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 *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;
+
+ 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} },
+ };
+
+ 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
+//| """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);
+ return mp_obj_new_float(common_hal_alarm_time_time_alarm_get_monotonic_time(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(alarm_time_time_alarm_get_monotonic_time_obj, alarm_time_time_alarm_obj_get_monotonic_time);
+
+const mp_obj_property_t alarm_time_time_alarm_monotonic_time_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&alarm_time_time_alarm_get_monotonic_time_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t alarm_time_time_alarm_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_monotonic_time), MP_ROM_PTR(&alarm_time_time_alarm_monotonic_time_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(alarm_time_time_alarm_locals_dict, alarm_time_time_alarm_locals_dict_table);
+
+const mp_obj_type_t alarm_time_time_alarm_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_TimeAlarm,
+ .make_new = alarm_time_time_alarm_make_new,
+ .locals_dict = (mp_obj_t)&alarm_time_time_alarm_locals_dict,
+};
diff --git a/shared-bindings/alarm/time/TimeAlarm.h b/shared-bindings/alarm/time/TimeAlarm.h
new file mode 100644
index 000000000..ceb3291c9
--- /dev/null
+++ b/shared-bindings/alarm/time/TimeAlarm.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_MONOTONIC_TIME_ALARM_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_MONOTINIC_TIME_ALARM_H
+
+#include "py/obj.h"
+
+#include "common-hal/alarm/time/TimeAlarm.h"
+
+extern const mp_obj_type_t alarm_time_time_alarm_type;
+
+extern void common_hal_alarm_time_time_alarm_construct(alarm_time_time_alarm_obj_t *self, mp_float_t monotonic_time);
+extern mp_float_t common_hal_alarm_time_time_alarm_get_monotonic_time(alarm_time_time_alarm_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_MONOTONIC_TIME_ALARM_H
diff --git a/shared-bindings/audiopwmio/__init__.h b/shared-bindings/audiopwmio/__init__.h
index e4b7067d1..d7956d31e 100644
--- a/shared-bindings/audiopwmio/__init__.h
+++ b/shared-bindings/audiopwmio/__init__.h
@@ -24,11 +24,11 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO___INIT___H
#include "py/obj.h"
// Nothing now.
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO___INIT___H
diff --git a/shared-bindings/i2cperipheral/I2CPeripheral.c b/shared-bindings/i2cperipheral/I2CPeripheral.c
index b5ac861b4..b5c268eb5 100644
--- a/shared-bindings/i2cperipheral/I2CPeripheral.c
+++ b/shared-bindings/i2cperipheral/I2CPeripheral.c
@@ -166,7 +166,7 @@ STATIC mp_obj_t i2cperipheral_i2c_peripheral_request(size_t n_args, const mp_obj
if (timeout_ms == 0) {
forever = true;
} else if (timeout_ms > 0) {
- timeout_end = common_hal_time_monotonic() + timeout_ms;
+ timeout_end = common_hal_time_monotonic_ms() + timeout_ms;
}
int last_error = 0;
@@ -200,7 +200,7 @@ STATIC mp_obj_t i2cperipheral_i2c_peripheral_request(size_t n_args, const mp_obj
}
return mp_obj_new_i2cperipheral_i2c_peripheral_request(self, address, is_read, is_restart);
- } while (forever || common_hal_time_monotonic() < timeout_end);
+ } while (forever || common_hal_time_monotonic_ms() < timeout_end);
if (timeout_ms > 0) {
mp_raise_OSError(MP_ETIMEDOUT);
@@ -322,8 +322,8 @@ STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_read(size_t n_args, const m
int i = 0;
uint8_t *buffer = NULL;
- uint64_t timeout_end = common_hal_time_monotonic() + 10 * 1000;
- while (common_hal_time_monotonic() < timeout_end) {
+ uint64_t timeout_end = common_hal_time_monotonic_ms() + 10 * 1000;
+ while (common_hal_time_monotonic_ms() < timeout_end) {
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c
index 8c703891d..90cc02fe3 100644
--- a/shared-bindings/microcontroller/Processor.c
+++ b/shared-bindings/microcontroller/Processor.c
@@ -67,6 +67,23 @@ const mp_obj_property_t mcu_processor_frequency_obj = {
},
};
+//| reset_reason: microcontroller.ResetReason
+//| """The reason the microcontroller started up from reset state."""
+//|
+STATIC mp_obj_t mcu_processor_get_reset_reason(mp_obj_t self) {
+ return cp_enum_find(&mcu_reset_reason_type, common_hal_mcu_processor_get_reset_reason());
+}
+
+MP_DEFINE_CONST_FUN_OBJ_1(mcu_processor_get_reset_reason_obj, mcu_processor_get_reset_reason);
+
+const mp_obj_property_t mcu_processor_reset_reason_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&mcu_processor_get_reset_reason_obj, // getter
+ (mp_obj_t)&mp_const_none_obj, // no setter
+ (mp_obj_t)&mp_const_none_obj, // no deleter
+ },
+};
+
//| temperature: Optional[float]
//| """The on-chip temperature, in Celsius, as a float. (read-only)
//|
@@ -128,6 +145,7 @@ const mp_obj_property_t mcu_processor_voltage_obj = {
STATIC const mp_rom_map_elem_t mcu_processor_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&mcu_processor_frequency_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset_reason), MP_ROM_PTR(&mcu_processor_reset_reason_obj) },
{ MP_ROM_QSTR(MP_QSTR_temperature), MP_ROM_PTR(&mcu_processor_temperature_obj) },
{ MP_ROM_QSTR(MP_QSTR_uid), MP_ROM_PTR(&mcu_processor_uid_obj) },
{ MP_ROM_QSTR(MP_QSTR_voltage), MP_ROM_PTR(&mcu_processor_voltage_obj) },
diff --git a/shared-bindings/microcontroller/Processor.h b/shared-bindings/microcontroller/Processor.h
index 0f520f940..98d479087 100644
--- a/shared-bindings/microcontroller/Processor.h
+++ b/shared-bindings/microcontroller/Processor.h
@@ -30,10 +30,12 @@
#include "py/obj.h"
#include "common-hal/microcontroller/Processor.h"
+#include "shared-bindings/microcontroller/ResetReason.h"
extern const mp_obj_type_t mcu_processor_type;
uint32_t common_hal_mcu_processor_get_frequency(void);
+mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void);
float common_hal_mcu_processor_get_temperature(void);
void common_hal_mcu_processor_get_uid(uint8_t raw_id[]);
float common_hal_mcu_processor_get_voltage(void);
diff --git a/shared-bindings/microcontroller/ResetReason.c b/shared-bindings/microcontroller/ResetReason.c
new file mode 100644
index 000000000..61891934a
--- /dev/null
+++ b/shared-bindings/microcontroller/ResetReason.c
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 "py/obj.h"
+#include "py/enum.h"
+
+#include "shared-bindings/microcontroller/ResetReason.h"
+
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, POWER_ON, RESET_REASON_POWER_ON);
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, BROWNOUT, RESET_REASON_BROWNOUT);
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, SOFTWARE, RESET_REASON_SOFTWARE);
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, DEEP_SLEEP_ALARM, RESET_REASON_DEEP_SLEEP_ALARM);
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, RESET_PIN, RESET_REASON_RESET_PIN);
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, WATCHDOG, RESET_REASON_WATCHDOG);
+MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, UNKNOWN, RESET_REASON_UNKNOWN);
+
+//| class ResetReason:
+//| """The reason the microntroller was last reset"""
+//|
+//| POWER_ON: object
+//| """The microntroller was started from power off."""
+//|
+//| BROWNOUT: object
+//| """The microntroller was reset due to too low a voltage."""
+//|
+//| SOFTWARE: object
+//| """The microntroller was reset from software."""
+//|
+//| DEEP_SLEEP_ALARM: object
+//| """The microntroller was reset for deep sleep and restarted by an alarm."""
+//|
+//| RESET_PIN: object
+//| """The microntroller was reset by a signal on its reset pin. The pin might be connected to a reset button."""
+//|
+//| WATCHDOG: object
+//| """The microcontroller was reset by its watchdog timer."""
+//|
+//| UNKNOWN: object
+//| """The microntroller restarted for an unknown reason."""
+//|
+MAKE_ENUM_MAP(mcu_reset_reason) {
+ MAKE_ENUM_MAP_ENTRY(reset_reason, POWER_ON),
+ MAKE_ENUM_MAP_ENTRY(reset_reason, BROWNOUT),
+ MAKE_ENUM_MAP_ENTRY(reset_reason, SOFTWARE),
+ MAKE_ENUM_MAP_ENTRY(reset_reason, DEEP_SLEEP_ALARM),
+ MAKE_ENUM_MAP_ENTRY(reset_reason, RESET_PIN),
+ MAKE_ENUM_MAP_ENTRY(reset_reason, WATCHDOG),
+ MAKE_ENUM_MAP_ENTRY(reset_reason, UNKNOWN),
+};
+STATIC MP_DEFINE_CONST_DICT(mcu_reset_reason_locals_dict, mcu_reset_reason_locals_table);
+
+MAKE_PRINTER(alarm, mcu_reset_reason);
+
+MAKE_ENUM_TYPE(alarm, ResetReason, mcu_reset_reason);
diff --git a/shared-bindings/microcontroller/ResetReason.h b/shared-bindings/microcontroller/ResetReason.h
new file mode 100644
index 000000000..8ed5e4831
--- /dev/null
+++ b/shared-bindings/microcontroller/ResetReason.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 MICROPY_INCLUDED_SHARED_BINDINGS_MCU_RESET_REASON__H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_MCU_RESET_REASON__H
+
+#include "py/obj.h"
+#include "py/enum.h"
+
+typedef enum {
+ RESET_REASON_POWER_ON,
+ RESET_REASON_BROWNOUT,
+ RESET_REASON_SOFTWARE,
+ RESET_REASON_DEEP_SLEEP_ALARM,
+ RESET_REASON_RESET_PIN,
+ RESET_REASON_WATCHDOG,
+ RESET_REASON_UNKNOWN,
+} mcu_reset_reason_t;
+
+extern const mp_obj_type_t mcu_reset_reason_type;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MCU_RESET_REASON__H
diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c
index 2e58bdcc2..8a77d1df5 100644
--- a/shared-bindings/microcontroller/__init__.c
+++ b/shared-bindings/microcontroller/__init__.c
@@ -39,7 +39,6 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/Processor.h"
-#include "py/runtime.h"
#include "supervisor/shared/translate.h"
//| """Pin references and cpu functionality
@@ -148,16 +147,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
//| This object is the sole instance of `watchdog.WatchDogTimer` when available or ``None`` otherwise."""
//|
-
-//| """:mod:`microcontroller.pin` --- Microcontroller pin names
-//| --------------------------------------------------------
-//|
-//| .. module:: microcontroller.pin
-//| :synopsis: Microcontroller pin names
-//| :platform: SAMD21
-//|
-//| References to pins as named by the microcontroller"""
-//|
const mp_obj_module_t mcu_pin_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mcu_pin_globals,
diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h
index 8abdff763..ac71de424 100644
--- a/shared-bindings/microcontroller/__init__.h
+++ b/shared-bindings/microcontroller/__init__.h
@@ -28,11 +28,11 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H
-#include "py/mpconfig.h"
#include "py/obj.h"
+#include "py/mpconfig.h"
#include "common-hal/microcontroller/Processor.h"
-
+#include "shared-bindings/microcontroller/ResetReason.h"
#include "shared-bindings/microcontroller/RunMode.h"
extern void common_hal_mcu_delay_us(uint32_t);
diff --git a/shared-bindings/random/__init__.h b/shared-bindings/random/__init__.h
index b5011b1a8..9e058051f 100644
--- a/shared-bindings/random/__init__.h
+++ b/shared-bindings/random/__init__.h
@@ -29,7 +29,7 @@
// This depends on shared_module because nearly all functionality is port
// agnostic. The random module only depends on the common_hal_os_urandom or
-// common_hal_time_monotonic to seed it initially.
+// common_hal_time_monotonic_ms to seed it initially.
void shared_modules_random_seed(mp_uint_t seed);
mp_uint_t shared_modules_random_getrandbits(uint8_t n);
diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c
new file mode 100644
index 000000000..a2a5fe13e
--- /dev/null
+++ b/shared-bindings/supervisor/RunReason.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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 "py/enum.h"
+
+#include "shared-bindings/supervisor/RunReason.h"
+
+MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP);
+MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTO_RELOAD, RUN_REASON_AUTO_RELOAD);
+MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD);
+MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD);
+
+//| class RunReason:
+//| """The reason that CircuitPython started running."""
+//|
+//| STARTUP: object
+//| """CircuitPython started the microcontroller started up. See `microcontroller.Processor.reset_reason`
+//| for more detail on why the microcontroller was started."""
+//|
+//| AUTO_RELOAD: object
+//| """CircuitPython restarted due to an external write to the filesystem."""
+//|
+//| SUPERVISOR_RELOAD: object
+//| """CircuitPython restarted due to a call to `supervisor.reload()`."""
+//|
+//| REPL_RELOAD: object
+//| """CircuitPython started due to the user typing CTRL-D in the REPL."""
+//|
+MAKE_ENUM_MAP(supervisor_run_reason) {
+ MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP),
+ MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD),
+ MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD),
+ MAKE_ENUM_MAP_ENTRY(run_reason, REPL_RELOAD),
+};
+STATIC MP_DEFINE_CONST_DICT(supervisor_run_reason_locals_dict, supervisor_run_reason_locals_table);
+
+MAKE_PRINTER(supervisor, supervisor_run_reason);
+
+MAKE_ENUM_TYPE(supervisor, RunReason, supervisor_run_reason);
diff --git a/shared-bindings/supervisor/RunReason.h b/shared-bindings/supervisor/RunReason.h
new file mode 100644
index 000000000..391e6d306
--- /dev/null
+++ b/shared-bindings/supervisor/RunReason.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * 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.
+ */
+
+#pragma once
+
+typedef enum {
+ RUN_REASON_STARTUP,
+ RUN_REASON_AUTO_RELOAD,
+ RUN_REASON_SUPERVISOR_RELOAD,
+ RUN_REASON_REPL_RELOAD,
+} supervisor_run_reason_t;
+
+extern const mp_obj_type_t supervisor_run_reason_type;
diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c
index bfca6e7b1..8e0259a3b 100755
--- a/shared-bindings/supervisor/Runtime.c
+++ b/shared-bindings/supervisor/Runtime.c
@@ -25,9 +25,16 @@
*/
#include <stdbool.h>
+#include "py/obj.h"
+#include "py/enum.h"
+#include "py/runtime.h"
#include "py/objproperty.h"
+
+#include "shared-bindings/supervisor/RunReason.h"
#include "shared-bindings/supervisor/Runtime.h"
+STATIC supervisor_run_reason_t _run_reason;
+
//TODO: add USB, REPL to description once they're operational
//| class Runtime:
//| """Current status of runtime objects.
@@ -90,9 +97,29 @@ const mp_obj_property_t supervisor_serial_bytes_available_obj = {
};
+//| run_reason: RunReason
+//| """Returns why CircuitPython started running this particular time."""
+//|
+STATIC mp_obj_t supervisor_get_run_reason(mp_obj_t self) {
+ return cp_enum_find(&supervisor_run_reason_type, _run_reason);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_run_reason_obj, supervisor_get_run_reason);
+
+const mp_obj_property_t supervisor_run_reason_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&supervisor_get_run_reason_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+void supervisor_set_run_reason(supervisor_run_reason_t run_reason) {
+ _run_reason = run_reason;
+}
+
STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_serial_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_serial_bytes_available_obj) },
+ { MP_ROM_QSTR(MP_QSTR_run_reason), MP_ROM_PTR(&supervisor_run_reason_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table);
diff --git a/shared-bindings/supervisor/Runtime.h b/shared-bindings/supervisor/Runtime.h
index 2dc59c3ab..51ed7604d 100755
--- a/shared-bindings/supervisor/Runtime.h
+++ b/shared-bindings/supervisor/Runtime.h
@@ -30,9 +30,12 @@
#include <stdbool.h>
#include "py/obj.h"
+#include "shared-bindings/supervisor/RunReason.h"
extern const mp_obj_type_t supervisor_runtime_type;
+void supervisor_set_run_reason(supervisor_run_reason_t run_reason);
+
bool common_hal_get_serial_connected(void);
bool common_hal_get_serial_bytes_available(void);
diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c
index bc6fdbff5..aaecdcbeb 100644
--- a/shared-bindings/supervisor/__init__.c
+++ b/shared-bindings/supervisor/__init__.c
@@ -32,7 +32,9 @@
#include "supervisor/shared/rgb_led_status.h"
#include "supervisor/shared/stack.h"
#include "supervisor/shared/translate.h"
+#include "supervisor/shared/workflow.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/Runtime.h"
@@ -88,6 +90,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_s
//|
STATIC mp_obj_t supervisor_reload(void) {
reload_requested = true;
+ supervisor_set_run_reason(RUN_REASON_SUPERVISOR_RELOAD);
mp_raise_reload_exception();
return mp_const_none;
}
@@ -111,9 +114,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_next_stack_limit_obj, supervisor_set_ne
STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },
+ { MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) },
+ { MP_ROM_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) },
{ MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_next_stack_limit), MP_ROM_PTR(&supervisor_set_next_stack_limit_obj) },
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index 44f82c62e..2624384af 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -51,9 +51,8 @@
//| ...
//|
STATIC mp_obj_t time_monotonic(void) {
- uint64_t time64 = common_hal_time_monotonic();
- // 4294967296 = 2^32
- return mp_obj_new_float(((uint32_t) (time64 >> 32) * 4294967296.0f + (uint32_t) (time64 & 0xffffffff)) / 1000.0f);
+ uint64_t ticks_ms = common_hal_time_monotonic_ms();
+ return mp_obj_new_float(uint64_to_float(ticks_ms) / 1000.0f);
}
MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic);
diff --git a/shared-bindings/time/__init__.h b/shared-bindings/time/__init__.h
index ec96aea24..4e716e9df 100644
--- a/shared-bindings/time/__init__.h
+++ b/shared-bindings/time/__init__.h
@@ -35,7 +35,7 @@
extern mp_obj_t struct_time_from_tm(timeutils_struct_time_t *tm);
extern void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm);
-extern uint64_t common_hal_time_monotonic(void);
+extern uint64_t common_hal_time_monotonic_ms(void);
extern uint64_t common_hal_time_monotonic_ns(void);
extern void common_hal_time_delay_ms(uint32_t);