Setup outline for SAMD alarm module
This commit is contained in:
parent
fd9c3d17ee
commit
f748d66128
|
@ -154,9 +154,6 @@
|
|||
path = ports/espressif/esp-idf
|
||||
url = https://github.com/espressif/esp-idf.git
|
||||
branch = release/v4.3
|
||||
[submodule "ports/espressif/certificates/nina-fw"]
|
||||
path = ports/espressif/certificates/nina-fw
|
||||
url = https://github.com/adafruit/nina-fw.git
|
||||
[submodule "frozen/Adafruit_CircuitPython_ST7789"]
|
||||
path = frozen/Adafruit_CircuitPython_ST7789
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_ST7789
|
||||
|
|
|
@ -1771,6 +1771,7 @@ msgstr ""
|
|||
msgid "Only one TouchAlarm can be set in deep sleep."
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c
|
||||
#: ports/espressif/common-hal/alarm/time/TimeAlarm.c
|
||||
#: ports/nrf/common-hal/alarm/time/TimeAlarm.c
|
||||
#: ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c
|
||||
|
@ -1881,6 +1882,10 @@ msgstr ""
|
|||
msgid "Pin must support hardware interrupts"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
|
||||
msgid "PinAlarms not available"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/rgbmatrix/RGBMatrix.c
|
||||
#, c-format
|
||||
msgid ""
|
||||
|
@ -2091,6 +2096,7 @@ msgstr ""
|
|||
msgid "Size not supported"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/alarm/SleepMemory.c
|
||||
#: ports/raspberrypi/common-hal/alarm/SleepMemory.c
|
||||
msgid "Sleep Memory not available"
|
||||
msgstr ""
|
||||
|
@ -2245,6 +2251,7 @@ msgstr ""
|
|||
msgid "Total data to write is larger than %q"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c
|
||||
#: ports/raspberrypi/common-hal/alarm/touch/TouchAlarm.c
|
||||
#: ports/stm/common-hal/alarm/touch/TouchAlarm.c
|
||||
msgid "Touch alarms not available"
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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 <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/alarm/SleepMemory.h"
|
||||
|
||||
void alarm_sleep_memory_reset(void) {
|
||||
|
||||
}
|
||||
|
||||
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
|
||||
mp_raise_NotImplementedError(translate("Sleep Memory not available"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t *values, uint32_t len) {
|
||||
mp_raise_NotImplementedError(translate("Sleep Memory not available"));
|
||||
return false;
|
||||
}
|
||||
|
||||
void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t *values, uint32_t len) {
|
||||
mp_raise_NotImplementedError(translate("Sleep Memory not available"));
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} alarm_sleep_memory_obj_t;
|
||||
|
||||
extern void alarm_sleep_memory_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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/gc.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
|
||||
#include "shared-bindings/alarm/__init__.h"
|
||||
#include "shared-bindings/alarm/SleepMemory.h"
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/workflow.h"
|
||||
|
||||
// Singleton instance of SleepMemory.
|
||||
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
|
||||
.base = {
|
||||
.type = &alarm_sleep_memory_type,
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: make a custom enum to avoid weird values like PM_SLEEPCFG_SLEEPMODE_BACKUP_Val?
|
||||
|
||||
void alarm_reset(void) {
|
||||
// Reset the alarm flag
|
||||
SAMD_ALARM_FLAG = 0x00;
|
||||
alarm_pin_pinalarm_reset();
|
||||
alarm_time_timealarm_reset();
|
||||
}
|
||||
|
||||
samd_sleep_source_t alarm_get_wakeup_cause(void) {
|
||||
// If in light/fake sleep, check modules
|
||||
if (alarm_pin_pinalarm_woke_this_cycle()) {
|
||||
return SAMD_WAKEUP_GPIO;
|
||||
}
|
||||
if (alarm_time_timealarm_woke_this_cycle()) {
|
||||
return SAMD_WAKEUP_RTC;
|
||||
}
|
||||
// TODO: for deep sleep, manually determine how the chip woke up
|
||||
// TODO: try checking the interrupt flag tables for RTC TAMPER vs COMPARE
|
||||
return SAMD_WAKEUP_UNDEF;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_woken_from_sleep(void) {
|
||||
return alarm_get_wakeup_cause() != SAMD_WAKEUP_UNDEF;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
|
||||
// If woken from deep sleep, create a copy alarm similar to what would have
|
||||
// been passed in originally. Otherwise, just return none
|
||||
samd_sleep_source_t cause = alarm_get_wakeup_cause();
|
||||
switch (cause) {
|
||||
case SAMD_WAKEUP_RTC: {
|
||||
return alarm_time_timealarm_create_wakeup_alarm();
|
||||
}
|
||||
case SAMD_WAKEUP_GPIO: {
|
||||
return alarm_pin_pinalarm_create_wakeup_alarm();
|
||||
}
|
||||
case SAMD_WAKEUP_UNDEF:
|
||||
default:
|
||||
// Not a deep sleep reset.
|
||||
break;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// Set up light sleep or deep sleep alarms.
|
||||
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
|
||||
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
_setup_sleep_alarms(false, n_alarms, alarms);
|
||||
mp_obj_t wake_alarm = mp_const_none;
|
||||
|
||||
while (!mp_hal_is_interrupted()) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
// Detect if interrupt was alarm or ctrl-C interrupt.
|
||||
if (common_hal_alarm_woken_from_sleep()) {
|
||||
samd_sleep_source_t cause = alarm_get_wakeup_cause();
|
||||
switch (cause) {
|
||||
case SAMD_WAKEUP_RTC: {
|
||||
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
|
||||
break;
|
||||
}
|
||||
case SAMD_WAKEUP_GPIO: {
|
||||
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Should not reach this, if all light sleep types are covered correctly
|
||||
break;
|
||||
}
|
||||
shared_alarm_save_wake_alarm(wake_alarm);
|
||||
break;
|
||||
}
|
||||
// TODO: the SAMD implementation of this (purportedly) disables interrupts
|
||||
// Presumably this doesn't impact the RTC interrupts, somehow, or it would never wake up?
|
||||
// Will it prevent an external interrupt from waking?
|
||||
port_idle_until_interrupt();
|
||||
// Alternative would be `sleep(PM_SLEEPCFG_SLEEPMODE_IDLE2_Val)`, I think?
|
||||
}
|
||||
|
||||
if (mp_hal_is_interrupted()) {
|
||||
return mp_const_none; // Shouldn't be given to python code because exception handling should kick in.
|
||||
}
|
||||
|
||||
alarm_reset();
|
||||
return wake_alarm;
|
||||
}
|
||||
|
||||
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
_setup_sleep_alarms(true, n_alarms, alarms);
|
||||
}
|
||||
|
||||
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
|
||||
alarm_pin_pinalarm_prepare_for_deep_sleep();
|
||||
alarm_time_timealarm_prepare_for_deep_sleep();
|
||||
port_disable_tick(); // TODO: Required for SAMD?
|
||||
|
||||
// Set a flag in the backup registers to indicate sleep wakeup
|
||||
SAMD_ALARM_FLAG = 0x01;
|
||||
|
||||
// TODO: make sure this actually works, or replace with extracted register version
|
||||
// sleep(PM_SLEEPCFG_SLEEPMODE_BACKUP_Val);
|
||||
|
||||
// The above shuts down RAM, so we should never hit this
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_alarm_pretending_deep_sleep(void) {
|
||||
// TODO:
|
||||
// If tamper detect interrupts cannot be used to wake from the Idle tier of sleep,
|
||||
// This section will need to re-initialize the pins to allow the PORT peripheral
|
||||
// to generate external interrupts again. See STM32 for reference.
|
||||
}
|
||||
|
||||
void common_hal_alarm_gc_collect(void) {
|
||||
gc_collect_ptr(shared_alarm_get_wake_alarm());
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
|
||||
|
||||
#include "common-hal/alarm/SleepMemory.h"
|
||||
|
||||
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
|
||||
|
||||
// This is the first byte of the BKUP register bank.
|
||||
// It stores whether the last wakeup was because of an alarm.
|
||||
#define SAMD_ALARM_FLAG (RTC->MODE0.BKUP[0].reg)
|
||||
|
||||
typedef enum {
|
||||
SAMD_WAKEUP_UNDEF,
|
||||
SAMD_WAKEUP_GPIO,
|
||||
SAMD_WAKEUP_RTC
|
||||
} samd_sleep_source_t;
|
||||
|
||||
extern void alarm_set_wakeup_reason(samd_sleep_source_t reason);
|
||||
samd_sleep_source_t alarm_get_wakeup_cause(void);
|
||||
extern void alarm_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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/runtime.h"
|
||||
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
// This variable stores whether a PinAlarm woke in light sleep or fake deep sleep
|
||||
// It CANNOT detect if the program woke from deep sleep.
|
||||
STATIC bool woke_up;
|
||||
|
||||
// TODO: Create tables here reserving IRQ instances, and for the IRQ
|
||||
// callback to store what pin triggered the interrupt
|
||||
// STATIC bool reserved_alarms[SOME_VAL];
|
||||
// STATIC uint16_t triggered_pins[SOME_VAL];
|
||||
|
||||
STATIC void pin_alarm_callback(uint8_t num) { // parameters can be changed
|
||||
// TODO: This is responsible for resetting the IRQ (so it doesn't
|
||||
// go off constantly, and recording what pin was responsible for
|
||||
// the trigger. This will only work for light sleep/fake deep
|
||||
// sleep, in conjunction with the find_triggered_alarm function
|
||||
}
|
||||
|
||||
void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) {
|
||||
mp_raise_NotImplementedError(translate("PinAlarms not available"));
|
||||
// TODO: Catch edge or level mode if not supported
|
||||
// if (!edge) {
|
||||
// mp_raise_NotImplementedError(translate("Only edge detection is available on this hardware"));
|
||||
// }
|
||||
|
||||
// TODO: determine if pin has an interrupt channel available
|
||||
// TODO: set pin pull settings, input/output, etc
|
||||
// QUESTION: can PORT/EVSYS interrupts (lightsleep) coexist with RTC->TAMPER (deepsleep) settings?
|
||||
// Actual initialization of the interrupt should be delayed until set_alarm
|
||||
|
||||
self->pin = pin;
|
||||
self->value = value;
|
||||
self->pull = pull;
|
||||
}
|
||||
|
||||
const mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) {
|
||||
return self->pin;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) {
|
||||
return self->value;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) {
|
||||
// TODO: is SAMD edge or level only?
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
|
||||
return self->pull;
|
||||
}
|
||||
|
||||
bool alarm_pin_pinalarm_woke_this_cycle(void) {
|
||||
return woke_up;
|
||||
}
|
||||
|
||||
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
|
||||
continue;
|
||||
}
|
||||
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
|
||||
|
||||
// TODO: Determine whether any pins have been marked as
|
||||
// triggering the alarm (using the static vars at
|
||||
// start of file) and if so return that alarm.
|
||||
}
|
||||
// Return nothing if no matching alarms are found.
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) {
|
||||
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
|
||||
alarm->base.type = &alarm_pin_pinalarm_type;
|
||||
// TODO: Extract information about what pin woke the device.
|
||||
// Because this interrupt occurs in deep sleep, the callback
|
||||
// cannot be used to store this information. It must be extracted
|
||||
// from the registers, if possible. It may be impossible to
|
||||
// obtain, in which case return a dummy value.
|
||||
return alarm;
|
||||
}
|
||||
|
||||
void alarm_pin_pinalarm_reset(void) {
|
||||
// TODO: this is responsible for resetting ALL pinalarms. Make
|
||||
// sure to clear any reserved tables, deinit both PORT and TAMPER
|
||||
// settings, etc. If flags are set to indicate this module is in
|
||||
// use, reset them.
|
||||
}
|
||||
|
||||
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// The outer layer of this loop simply checks if there are any pin
|
||||
// alarms in the parameter array
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
|
||||
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
|
||||
if (deep_sleep) {
|
||||
// TODO: Set up deep sleep alarms.
|
||||
// For deep sleep alarms, first check if the
|
||||
// alarm pin value is valid for RTC->TAMPER. Ensure
|
||||
// that the PULL and VALUE values are possible to
|
||||
// implement with TAMPER, and throw value errors if
|
||||
// not.
|
||||
// A VM reset will occur before deep sleep
|
||||
// starts, so either init these settings now and
|
||||
// protect them with a `never_reset` function, or
|
||||
// store them all in static variables and only
|
||||
// actually implement the settings in
|
||||
// `alarm_pin_pinalarm_prepare_for_deep_sleep`
|
||||
// below.
|
||||
} // use else-if here if RTC-TAMPER can wake from IDLE
|
||||
|
||||
// TODO: Set up light sleep / fake deep sleep alarms.
|
||||
// PORT/EVSYS should have more valid pin combinations
|
||||
// than the TAMPER system. Check if there is a valid
|
||||
// PORT/EVSYS combination, set it up, and reserve it with
|
||||
// the tables at the start of this file so it can't be
|
||||
// reused. Also set up IRQ callbacks and any other
|
||||
// busywork.
|
||||
|
||||
// TODO: Might want to reserve or otherwise interact with
|
||||
// peripherals/sam_d5x/external_interrupts.c or events.c here
|
||||
|
||||
// TODO: Even if an alarm is being set for deep sleep, it
|
||||
// still needs to be able to wake from fake deep sleep,
|
||||
// which is actually just like a light sleep. If the
|
||||
// RTC Tamper IRQs are capable of waking from IDLE mode,
|
||||
// this isn't a big deal, and there can be a strict
|
||||
// if-else statement here. Otherwise, it will need to
|
||||
// either set PORT and TAMPER IRQs simultaniously, or if that
|
||||
// isn't possible, make a new function that can shunt fake deep
|
||||
// sleep setup to common_hal_alarm_pretending_deep_sleep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void alarm_pin_pinalarm_prepare_for_deep_sleep(void) {
|
||||
// TODO: This function is called after the VM reset, right before
|
||||
// the program actually enters deep sleep. If the VM reset
|
||||
// (see port_reset) resets any pins/EVSYS settings/RTC values
|
||||
// needed by the pinalarms, this function is responsible for setting them
|
||||
// back up again.
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t *pin;
|
||||
bool value;
|
||||
bool pull;
|
||||
} alarm_pin_pinalarm_obj_t;
|
||||
|
||||
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
|
||||
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void);
|
||||
|
||||
void alarm_pin_pinalarm_reset(void);
|
||||
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
|
||||
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
|
||||
bool alarm_pin_pinalarm_woke_this_cycle(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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/runtime.h"
|
||||
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
#include "supervisor/port.h"
|
||||
|
||||
STATIC volatile bool woke_up;
|
||||
STATIC uint32_t deep_sleep_ticks;
|
||||
|
||||
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
|
||||
// TODO: throw a ValueError if the input time exceeds the maximum
|
||||
// value of the Compare register. This must be calculated from the
|
||||
// setup values in port.c. Should be ~3 days. Give it some margin.
|
||||
self->monotonic_time = monotonic_time;
|
||||
}
|
||||
|
||||
mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timealarm_obj_t *self) {
|
||||
return self->monotonic_time;
|
||||
}
|
||||
|
||||
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// TODO: this function currently assumes you can only have a single TimeAlarm
|
||||
// If you want to support more, it will need to somehow detect which one went off.
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) {
|
||||
return alarms[i];
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
|
||||
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
|
||||
timer->base.type = &alarm_time_timealarm_type;
|
||||
// TODO: Set monotonic_time based on the RTC state.
|
||||
// Or don't, most of the other ports don't have this either.
|
||||
timer->monotonic_time = 0.0f;
|
||||
return timer;
|
||||
}
|
||||
|
||||
STATIC void timer_callback(void) {
|
||||
woke_up = true;
|
||||
}
|
||||
|
||||
bool alarm_time_timealarm_woke_this_cycle(void) {
|
||||
return woke_up;
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_reset(void) {
|
||||
woke_up = false;
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// Search through alarms for TimeAlarm instances, and check that there's only one
|
||||
bool timealarm_set = false;
|
||||
alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL;
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (!mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) {
|
||||
continue;
|
||||
}
|
||||
if (timealarm_set) {
|
||||
mp_raise_ValueError(translate("Only one alarm.time alarm can be set."));
|
||||
}
|
||||
timealarm = MP_OBJ_TO_PTR(alarms[i]);
|
||||
timealarm_set = true;
|
||||
}
|
||||
if (!timealarm_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
uint32_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs);
|
||||
uint32_t wakeup_in_ticks = wakeup_in_secs * 1024;
|
||||
|
||||
// In the deep sleep case, we can't start the timer until the USB delay has finished
|
||||
// (othersise it will go off while USB enumerates, and we'll risk entering deep sleep
|
||||
// without any way to wake up again)
|
||||
if (deep_sleep) {
|
||||
deep_sleep_ticks = wakeup_in_ticks;
|
||||
} else {
|
||||
deep_sleep_ticks = 0;
|
||||
}
|
||||
|
||||
// TODO: set up RTC->COMP[1] and create a callback pointing to
|
||||
// timer_callback. See atmel-samd/supervisor/port.c -> _port_interrupt_after_ticks()
|
||||
// for how to set this up. I don't know how you do the callback, though. You MUST use
|
||||
// COMP[1], since port.c uses COMP[0] already and needs to set that for
|
||||
// things like the USB enumeration delay.
|
||||
|
||||
// If true deep sleep is called, it will either ignore or overwrite the above setup depending on
|
||||
// whether it is shorter or longer than the USB delay
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_prepare_for_deep_sleep(void) {
|
||||
if (deep_sleep_ticks) {
|
||||
// TODO: set up RTC->COMP[1] again, since it needs to start AFTER the USB enumeration delay.
|
||||
// Just do the exact same setup as alarm_time_timealarm_set_alarms(). Note, this
|
||||
// is used for both fake and real deep sleep, so it still needs the callback.
|
||||
// See STM32 for reference.
|
||||
deep_sleep_ticks = 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
|
||||
} alarm_time_timealarm_obj_t;
|
||||
|
||||
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
|
||||
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);
|
||||
|
||||
bool alarm_time_timealarm_woke_this_cycle(void);
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
|
||||
void alarm_time_timealarm_reset(void);
|
||||
|
||||
void alarm_time_timealarm_prepare_for_deep_sleep(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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/alarm/touch/TouchAlarm.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
|
||||
void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) {
|
||||
mp_raise_NotImplementedError(translate("Touch alarms not available"));
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Lucian Copeland 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_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t *pin;
|
||||
} alarm_touch_touchalarm_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
|
|
@ -98,6 +98,7 @@ CIRCUITPY_TOUCHIO_USE_NATIVE = 0
|
|||
|
||||
# The ?='s allow overriding in mpconfigboard.mk.
|
||||
|
||||
CIRCUITPY_ALARM ?= 0
|
||||
CIRCUITPY_PS2IO ?= 1
|
||||
CIRCUITPY_SAMD ?= 1
|
||||
CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FULL_BUILD)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit f2a0e601b23212dda4fe305eab30af49a7c7fb41
|
Loading…
Reference in New Issue