Initial commit.
This commit is contained in:
parent
261b077209
commit
e6350ff834
3
main.c
3
main.c
|
@ -214,6 +214,7 @@ STATIC bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec
|
|||
decompress(compressed, decompressed);
|
||||
mp_hal_stdout_tx_str(decompressed);
|
||||
pyexec_file(filename, exec_result);
|
||||
dbg_printf("pyexec_file end result=(code=%d, line=%d)\r\n", exec_result->return_code, exec_result->exception_line);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -259,6 +260,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
|||
}
|
||||
|
||||
STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
dbg_printf("run_code_py (%d)\r\n", (int)safe_mode);
|
||||
bool serial_connected_at_start = serial_connected();
|
||||
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
|
||||
serial_write("\n");
|
||||
|
@ -434,6 +436,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
|||
FIL* boot_output_file;
|
||||
|
||||
STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||
dbg_printf("run_boot_py (%d)\r\n", (int)safe_mode);
|
||||
// If not in safe mode, run boot before initing USB and capture output in a
|
||||
// file.
|
||||
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
|
||||
|
|
|
@ -87,6 +87,7 @@ INC += -I../../supervisor/shared/usb
|
|||
#Debugging/Optimization
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -ggdb3
|
||||
CFLAGS += -DNDEBUG
|
||||
OPTIMIZATION_FLAGS = -Og
|
||||
else
|
||||
OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions
|
||||
|
@ -94,6 +95,13 @@ else
|
|||
CFLAGS += -flto -flto-partition=none
|
||||
endif
|
||||
|
||||
ifeq ($(MY_DBG), 1)
|
||||
CFLAGS += -DMY_DBG
|
||||
endif
|
||||
ifeq ($(MY_DEBUGUART), 1)
|
||||
CFLAGS += -DMY_DEBUGUART=1
|
||||
endif
|
||||
|
||||
# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
|
||||
CFLAGS += $(OPTIMIZATION_FLAGS)
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 microDev
|
||||
* 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 <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "common-hal/alarm/SleepMemory.h"
|
||||
|
||||
//static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH];
|
||||
|
||||
void alarm_sleep_memory_reset(void) {
|
||||
}
|
||||
|
||||
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
|
||||
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) {
|
||||
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) {
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
// not implemented yet
|
||||
#define SLEEP_MEMORY_LENGTH (4)
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} alarm_sleep_memory_obj_t;
|
||||
|
||||
extern void alarm_sleep_memory_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
|
||||
* 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/gc.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/runtime.h"
|
||||
#include <stdio.h>
|
||||
#include <string.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/alarm/touch/TouchAlarm.h"
|
||||
|
||||
//#include "shared-bindings/wifi/__init__.h"
|
||||
//#include "shared-bindings/microcontroller/__init__.h"
|
||||
|
||||
#include "supervisor/port.h"
|
||||
|
||||
#include "nrf.h"
|
||||
#include "nrf_power.h"
|
||||
#include "nrfx.h"
|
||||
#include "nrfx_gpiote.h"
|
||||
|
||||
extern void _debug_print(const char* s);
|
||||
extern void _xxx_dumpRTC(void);//XXXX
|
||||
|
||||
#define DEBUG_LED_PIN (NRF_GPIO_PIN_MAP(1, 11)) // P1_11 = LED
|
||||
void _debug_led_init(void) {
|
||||
nrf_gpio_cfg_output(DEBUG_LED_PIN);
|
||||
}
|
||||
void _debug_led_set(int v) {
|
||||
nrf_gpio_pin_write(DEBUG_LED_PIN, v);
|
||||
}
|
||||
|
||||
|
||||
// Singleton instance of SleepMemory.
|
||||
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
|
||||
.base = {
|
||||
.type = &alarm_sleep_memory_type,
|
||||
},
|
||||
};
|
||||
|
||||
void alarm_reset(void) {
|
||||
//alarm_sleep_memory_reset();
|
||||
alarm_pin_pinalarm_reset();
|
||||
alarm_time_timealarm_reset();
|
||||
//alarm_touch_touchalarm_reset();
|
||||
}
|
||||
|
||||
extern uint32_t reset_reason_saved;
|
||||
STATIC uint32_t _get_wakeup_cause(void) {
|
||||
if (alarm_pin_pinalarm_woke_us_up()) {
|
||||
return NRF_SLEEP_WAKEUP_GPIO;
|
||||
}
|
||||
if (alarm_time_timealarm_woke_us_up()) {
|
||||
return NRF_SLEEP_WAKEUP_TIMER;
|
||||
}
|
||||
#if 0
|
||||
if (alarm_touch_touchalarm_woke_us_up()) {
|
||||
return ESP_SLEEP_WAKEUP_TOUCHPAD;
|
||||
}
|
||||
return esp_sleep_get_wakeup_cause();
|
||||
#endif
|
||||
if (reset_reason_saved & NRF_POWER_RESETREAS_RESETPIN_MASK) {
|
||||
return NRF_SLEEP_WAKEUP_RESETPIN;
|
||||
}
|
||||
else if (reset_reason_saved & NRF_POWER_RESETREAS_OFF_MASK) {
|
||||
return NRF_SLEEP_WAKEUP_GPIO;
|
||||
}
|
||||
else if (reset_reason_saved & NRF_POWER_RESETREAS_VBUS_MASK) {
|
||||
return NRF_SLEEP_WAKEUP_VBUS;
|
||||
}
|
||||
return NRF_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
|
||||
bool alarm_woken_from_sleep(void) {
|
||||
uint32_t cause = _get_wakeup_cause();
|
||||
return (cause == NRF_SLEEP_WAKEUP_GPIO || cause == NRF_SLEEP_WAKEUP_TIMER
|
||||
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD
|
||||
|| cause == NRF_SLEEP_WAKEUP_RESETPIN);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
uint32_t cause = _get_wakeup_cause();
|
||||
if (cause & 0x80000000) {
|
||||
printf("wakeup cause = 0x%08X\r\n", (int)cause);
|
||||
}
|
||||
switch (cause) {
|
||||
case NRF_SLEEP_WAKEUP_TIMER: {
|
||||
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
|
||||
}
|
||||
case NRF_SLEEP_WAKEUP_TOUCHPAD: {
|
||||
return mp_const_none;
|
||||
}
|
||||
case NRF_SLEEP_WAKEUP_GPIO: {
|
||||
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
|
||||
mp_obj_t obj = _get_wake_alarm(0, NULL);
|
||||
//_xxx_dumpRTC();//XXX
|
||||
return obj;
|
||||
}
|
||||
|
||||
// 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);
|
||||
#if 0
|
||||
alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
|
||||
#endif
|
||||
//_xxx_dumpRTC();
|
||||
}
|
||||
|
||||
STATIC void _idle_until_alarm(void) {
|
||||
int ct = 40;
|
||||
// Poll for alarms.
|
||||
while (!mp_hal_is_interrupted()) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
// Allow ctrl-C interrupt.
|
||||
if (alarm_woken_from_sleep()) {
|
||||
alarm_save_wake_alarm();
|
||||
int cause = _get_wakeup_cause();
|
||||
printf("wakeup(%d)\r\n", cause); //XXX
|
||||
return;
|
||||
}
|
||||
port_idle_until_interrupt();
|
||||
if (ct > 0) {
|
||||
printf("_"); --ct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
mp_obj_t r_obj = mp_const_none;
|
||||
_setup_sleep_alarms(false, n_alarms, alarms);
|
||||
_debug_print("\r\nsleep...");
|
||||
|
||||
_idle_until_alarm();
|
||||
|
||||
if (mp_hal_is_interrupted()) {
|
||||
_debug_print("mp_hal_is_interrupted\r\n");
|
||||
r_obj = mp_const_none;
|
||||
}
|
||||
else {
|
||||
r_obj = _get_wake_alarm(n_alarms, alarms);
|
||||
alarm_reset();
|
||||
}
|
||||
return r_obj;
|
||||
}
|
||||
|
||||
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 nrf_deep_sleep_start(void) {
|
||||
_debug_print("go system off..\r\n");
|
||||
sd_power_system_off();
|
||||
}
|
||||
|
||||
void NORETURN alarm_enter_deep_sleep(void) {
|
||||
alarm_pin_pinalarm_prepare_for_deep_sleep();
|
||||
//alarm_touch_touchalarm_prepare_for_deep_sleep();
|
||||
|
||||
nrf_deep_sleep_start();
|
||||
|
||||
// should not reach here..
|
||||
while(1) ;
|
||||
}
|
||||
|
||||
void common_hal_alarm_gc_collect(void) {
|
||||
void* p = alarm_get_wake_alarm();
|
||||
gc_collect_ptr(p);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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_NRF_COMMON_HAL_ALARM__INIT__H
|
||||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H
|
||||
|
||||
#include "common-hal/alarm/SleepMemory.h"
|
||||
|
||||
typedef enum {
|
||||
NRF_SLEEP_WAKEUP_UNDEFINED,
|
||||
NRF_SLEEP_WAKEUP_GPIO,
|
||||
NRF_SLEEP_WAKEUP_TIMER,
|
||||
NRF_SLEEP_WAKEUP_TOUCHPAD,
|
||||
NRF_SLEEP_WAKEUP_VBUS,
|
||||
NRF_SLEEP_WAKEUP_RESETPIN,
|
||||
} nrf_sleep_source_t;
|
||||
|
||||
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
|
||||
|
||||
extern void alarm_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
|
||||
* 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/runtime.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
#include "nrfx.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrfx_gpiote.h"
|
||||
#include "nrf_soc.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "supervisor/serial.h" // dbg_print
|
||||
|
||||
#define WPIN_UNUSED 0xFF
|
||||
volatile char _pinhandler_gpiote_count;
|
||||
volatile nrfx_gpiote_pin_t _pinhandler_ev_pin;
|
||||
#define MYGPIOTE_EV_PIN_UNDEF 0xFF
|
||||
|
||||
void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) {
|
||||
#if 0
|
||||
if (edge) {
|
||||
mp_raise_ValueError(translate("Cannot wake on pin edge. Only level."));
|
||||
}
|
||||
|
||||
if (pull && !GPIO_IS_VALID_OUTPUT_GPIO(pin->number)) {
|
||||
mp_raise_ValueError(translate("Cannot pull on input-only pin."));
|
||||
}
|
||||
#endif
|
||||
self->pin = pin;
|
||||
self->value = value;
|
||||
self->pull = pull;
|
||||
}
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
|
||||
return self->pull;
|
||||
}
|
||||
|
||||
|
||||
static void pinalarm_gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
||||
++_pinhandler_gpiote_count;
|
||||
_pinhandler_ev_pin = pin;
|
||||
}
|
||||
|
||||
bool alarm_pin_pinalarm_woke_us_up(void) {
|
||||
return (_pinhandler_gpiote_count > 0 && _pinhandler_ev_pin != MYGPIOTE_EV_PIN_UNDEF);
|
||||
}
|
||||
|
||||
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// First, check to see if we match any given 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]);
|
||||
if (alarm->pin->number == _pinhandler_ev_pin) {
|
||||
return alarms[i];
|
||||
}
|
||||
}
|
||||
|
||||
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
|
||||
alarm->base.type = &alarm_pin_pinalarm_type;
|
||||
alarm->pin = NULL;
|
||||
// Map the pin number back to a pin object.
|
||||
for (size_t i = 0; i < mcu_pin_globals.map.used; i++) {
|
||||
const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value);
|
||||
if ((size_t) pin_obj->number == _pinhandler_ev_pin) {
|
||||
alarm->pin = mcu_pin_globals.map.table[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return alarm;
|
||||
}
|
||||
|
||||
// These must be static because we need to configure pulls later, right before
|
||||
// deep sleep.
|
||||
static uint64_t high_alarms = 0;
|
||||
static uint64_t low_alarms = 0;
|
||||
static uint64_t pull_pins = 0;
|
||||
|
||||
void alarm_pin_pinalarm_reset(void) {
|
||||
for (size_t i = 0; i < 64; i++) {
|
||||
uint64_t mask = 1ull << i;
|
||||
bool high = (high_alarms & mask) != 0;
|
||||
bool low = (low_alarms & mask) != 0;
|
||||
if (!(high || low)) {
|
||||
continue;
|
||||
}
|
||||
reset_pin_number(i);
|
||||
nrfx_gpiote_in_event_disable((nrfx_gpiote_pin_t)i);
|
||||
nrfx_gpiote_in_uninit((nrfx_gpiote_pin_t)i);
|
||||
}
|
||||
|
||||
high_alarms = 0;
|
||||
low_alarms = 0;
|
||||
pull_pins = 0;
|
||||
}
|
||||
|
||||
void _setup2(void) {
|
||||
nrfx_gpiote_in_config_t cfg = {
|
||||
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
|
||||
.pull = NRF_GPIO_PIN_PULLUP,
|
||||
.is_watcher = false,
|
||||
.hi_accuracy = true,
|
||||
.skip_gpio_setup = false
|
||||
};
|
||||
for(size_t i = 0; i < 64; ++i) {
|
||||
uint64_t mask = 1ull << i;
|
||||
int pull = 0;
|
||||
int sense = 0;
|
||||
if (((high_alarms & mask) == 0) && ((low_alarms & mask) == 0)) {
|
||||
continue;
|
||||
}
|
||||
if (((high_alarms & mask) != 0) && ((low_alarms & mask) == 0)) {
|
||||
cfg.sense = NRF_GPIOTE_POLARITY_LOTOHI;
|
||||
cfg.pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_NOPULL;
|
||||
pull = -1; sense = 1;
|
||||
}
|
||||
else
|
||||
if (((high_alarms & mask) == 0) && ((low_alarms & mask) != 0)) {
|
||||
cfg.sense = NRF_GPIOTE_POLARITY_HITOLO;
|
||||
cfg.pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL;
|
||||
pull = 1; sense = -1;
|
||||
}
|
||||
else {
|
||||
cfg.sense = NRF_GPIOTE_POLARITY_TOGGLE;
|
||||
cfg.pull = NRF_GPIO_PIN_NOPULL;
|
||||
sense = 9;
|
||||
}
|
||||
nrfx_gpiote_in_init((nrfx_gpiote_pin_t)i, &cfg, pinalarm_gpiote_handler);
|
||||
nrfx_gpiote_in_event_enable((nrfx_gpiote_pin_t)i, true);
|
||||
printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
|
||||
}
|
||||
}
|
||||
|
||||
void _setup_pin1_for_lightsleep(void) {
|
||||
if ( nrfx_gpiote_is_init() ) {
|
||||
nrfx_gpiote_uninit();
|
||||
}
|
||||
nrfx_gpiote_init(NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
|
||||
|
||||
_pinhandler_gpiote_count = 0;
|
||||
_pinhandler_ev_pin = MYGPIOTE_EV_PIN_UNDEF;
|
||||
_setup2();
|
||||
}
|
||||
|
||||
void _setup_pin1_for_deepsleep(void) {
|
||||
for(size_t i = 0; i < 64; ++i) {
|
||||
uint64_t mask = 1ull << i;
|
||||
int pull = 0;
|
||||
int sense = 0;
|
||||
if (((high_alarms & mask) == 0) && ((low_alarms & mask) == 0)) {
|
||||
continue;
|
||||
}
|
||||
if (((high_alarms & mask) != 0) && ((low_alarms & mask) == 0)) {
|
||||
pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_NOPULL;
|
||||
nrf_gpio_cfg_input((uint32_t)i, (nrf_gpio_pin_pull_t)pull);
|
||||
nrf_gpio_cfg_sense_set((uint32_t)i, NRF_GPIO_PIN_SENSE_HIGH);
|
||||
sense = NRF_GPIO_PIN_SENSE_HIGH;
|
||||
}
|
||||
else
|
||||
if (((high_alarms & mask) == 0) && ((low_alarms & mask) != 0)) {
|
||||
pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL;
|
||||
nrf_gpio_cfg_input((uint32_t)i, (nrf_gpio_pin_pull_t)pull);
|
||||
nrf_gpio_cfg_sense_set((uint32_t)i, NRF_GPIO_PIN_SENSE_LOW);
|
||||
sense = NRF_GPIO_PIN_SENSE_LOW;
|
||||
}
|
||||
printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
|
||||
}
|
||||
#if 0
|
||||
uint32_t pin_number = 2;
|
||||
NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
|
||||
dbg_printf(" 2 PIN_CNF=0x%08X\r\n", (unsigned int)(reg->PIN_CNF[pin_number]));
|
||||
pin_number = 28;
|
||||
reg = nrf_gpio_pin_port_decode(&pin_number);
|
||||
dbg_printf("28 PIN_CNF=0x%08X\r\n", (unsigned int)(reg->PIN_CNF[pin_number]));
|
||||
#endif
|
||||
}
|
||||
|
||||
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// Bitmask of wake up settings.
|
||||
size_t high_count = 0;
|
||||
size_t low_count = 0;
|
||||
int pin_number = -1;
|
||||
|
||||
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]);
|
||||
|
||||
pin_number = alarm->pin->number;
|
||||
dbg_printf("alarm_pin_pinalarm_set_alarms(pin#=%d, val=%d, pull=%d)\r\n", pin_number, alarm->value, alarm->pull);
|
||||
if (alarm->value) {
|
||||
high_alarms |= 1ull << pin_number;
|
||||
high_count++;
|
||||
} else {
|
||||
low_alarms |= 1ull << pin_number;
|
||||
low_count++;
|
||||
}
|
||||
if (alarm->pull) {
|
||||
pull_pins |= 1ull << pin_number;
|
||||
}
|
||||
}
|
||||
if (pin_number != -1) {
|
||||
if (!deep_sleep) {
|
||||
_setup_pin1_for_lightsleep();
|
||||
}
|
||||
else {
|
||||
//_setup_pin1_for_deepsleep(pin_number);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dbg_printf("alarm_pin_pinalarm_set_alarms() no valid pins\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void alarm_pin_pinalarm_prepare_for_deep_sleep(void) {
|
||||
_setup_pin1_for_deepsleep();
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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/objtuple.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
mcu_pin_obj_t *pin;
|
||||
bool value;
|
||||
bool pull;
|
||||
} alarm_pin_pinalarm_obj_t;
|
||||
|
||||
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);
|
||||
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
|
||||
bool alarm_pin_pinalarm_woke_us_up(void);
|
|
@ -0,0 +1,38 @@
|
|||
//#include "shared-bindings/alarm_io/__init__.h"
|
||||
|
||||
//#include "esp_sleep.h"
|
||||
//#include "driver/rtc_io.h"
|
||||
|
||||
mp_obj_t common_hal_alarm_io_pin_state (alarm_io_obj_t *self_in) {
|
||||
#if 0
|
||||
if (!rtc_gpio_is_valid_gpio(self_in->gpio)) {
|
||||
mp_raise_ValueError(translate("io must be rtc io"));
|
||||
}
|
||||
|
||||
if (self_in->pull && !self_in->level) {
|
||||
for (uint8_t i = 0; i<=4; i+=2) {
|
||||
if (self_in->gpio == i) {
|
||||
mp_raise_ValueError(translate("IOs 0, 2 & 4 do not support internal pullup in sleep"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(esp_sleep_enable_ext0_wakeup(self_in->gpio, self_in->level)) {
|
||||
case ESP_ERR_INVALID_ARG:
|
||||
mp_raise_ValueError(translate("trigger level must be 0 or 1"));
|
||||
case ESP_ERR_INVALID_STATE:
|
||||
mp_raise_RuntimeError(translate("wakeup conflict"));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (self_in->pull) { (self_in->level) ? rtc_gpio_pulldown_en(self_in->gpio) : rtc_gpio_pullup_en(self_in->gpio); }
|
||||
#endif
|
||||
return self_in;
|
||||
}
|
||||
|
||||
void common_hal_alarm_io_disable (void) {
|
||||
#if 0
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0 | ESP_SLEEP_WAKEUP_EXT1);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 "esp_sleep.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
//#include "supervisor/esp_port.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
|
||||
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_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// First, check to see if we match
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
|
||||
return alarms[i];
|
||||
}
|
||||
}
|
||||
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.
|
||||
timer->monotonic_time = 0.0f;
|
||||
return timer;
|
||||
}
|
||||
|
||||
extern volatile int rtc_woke_up_counter;
|
||||
bool alarm_time_timealarm_woke_us_up(void) {
|
||||
return rtc_woke_up_counter;
|
||||
}
|
||||
|
||||
extern void port_disable_interrupt_after_ticks_ch(uint32_t channel);
|
||||
void alarm_time_timealarm_reset(void) {
|
||||
port_disable_interrupt_after_ticks_ch(1);
|
||||
rtc_woke_up_counter = 0;
|
||||
}
|
||||
|
||||
extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks);//XXX in port.c
|
||||
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
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;
|
||||
mp_float_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs);
|
||||
int wsecs = (int)(wakeup_in_secs);
|
||||
if (wsecs > 510) { //XXX
|
||||
mp_raise_ValueError(translate("Alarm time is too far."));
|
||||
}
|
||||
|
||||
uint32_t wakeup_in_ticks = (uint32_t)(wakeup_in_secs * 1024.0f);
|
||||
//printf("alarm_time_timealarm_set_alarms() %d secs 0x%08X ticks\r\n", wsecs, (int)wakeup_in_ticks);
|
||||
port_interrupt_after_ticks_ch(1, wakeup_in_ticks);
|
||||
rtc_woke_up_counter = 0;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
|
||||
} alarm_time_timealarm_obj_t;
|
||||
|
||||
// Find the alarm object that caused us to wake up or create an equivalent one.
|
||||
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
|
||||
// Check for the wake up alarm from pretend deep sleep.
|
||||
bool alarm_time_timealarm_woke_us_up(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);
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 microDev
|
||||
*
|
||||
* 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"
|
||||
|
||||
//#include "esp_sleep.h"
|
||||
//#include "peripherals/touch.h"
|
||||
//#include "supervisor/esp_port.h"
|
||||
|
||||
static uint16_t touch_channel_mask;
|
||||
static volatile bool woke_up = false;
|
||||
|
||||
void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) {
|
||||
#if 0
|
||||
if (pin->touch_channel == TOUCH_PAD_MAX) {
|
||||
mp_raise_ValueError(translate("Invalid pin"));
|
||||
}
|
||||
claim_pin(pin);
|
||||
#endif
|
||||
self->pin = pin;
|
||||
}
|
||||
|
||||
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// First, check to see if we match any given alarms.
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_touch_touchalarm_type)) {
|
||||
return alarms[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Create TouchAlarm object.
|
||||
alarm_touch_touchalarm_obj_t *alarm = m_new_obj(alarm_touch_touchalarm_obj_t);
|
||||
alarm->base.type = &alarm_touch_touchalarm_type;
|
||||
alarm->pin = NULL;
|
||||
#if 0
|
||||
touch_pad_t wake_channel = touch_pad_get_current_meas_channel();
|
||||
if (wake_channel == TOUCH_PAD_MAX) {
|
||||
return alarm;
|
||||
}
|
||||
|
||||
// Map the pin number back to a pin object.
|
||||
for (size_t i = 0; i < mcu_pin_globals.map.used; i++) {
|
||||
const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value);
|
||||
if (pin_obj->touch_channel == wake_channel) {
|
||||
alarm->pin = mcu_pin_globals.map.table[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return alarm;
|
||||
}
|
||||
|
||||
// This is used to wake the main CircuitPython task.
|
||||
void touch_interrupt(void *arg) {
|
||||
(void) arg;
|
||||
#if 0
|
||||
woke_up = true;
|
||||
BaseType_t task_wakeup;
|
||||
vTaskNotifyGiveFromISR(circuitpython_task, &task_wakeup);
|
||||
if (task_wakeup) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) {
|
||||
#if 0
|
||||
bool touch_alarm_set = false;
|
||||
alarm_touch_touchalarm_obj_t *touch_alarm = MP_OBJ_NULL;
|
||||
|
||||
for (size_t i = 0; i < n_alarms; i++) {
|
||||
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_touch_touchalarm_type)) {
|
||||
if (deep_sleep && touch_alarm_set) {
|
||||
mp_raise_ValueError(translate("Only one TouchAlarm can be set in deep sleep."));
|
||||
}
|
||||
touch_alarm = MP_OBJ_TO_PTR(alarms[i]);
|
||||
touch_channel_mask |= 1 << touch_alarm->pin->number;
|
||||
touch_alarm_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!touch_alarm_set) {
|
||||
return;
|
||||
}
|
||||
|
||||
// configure interrupt for pretend to deep sleep
|
||||
// this will be disabled if we actually deep sleep
|
||||
|
||||
// reset touch peripheral
|
||||
peripherals_touch_reset();
|
||||
peripherals_touch_never_reset(true);
|
||||
|
||||
for (uint8_t i = 1; i <= 14; i++) {
|
||||
if ((touch_channel_mask & 1 << i) != 0) {
|
||||
touch_pad_t touch_channel = (touch_pad_t)i;
|
||||
// intialize touchpad
|
||||
peripherals_touch_init(touch_channel);
|
||||
|
||||
// wait for touch data to reset
|
||||
mp_hal_delay_ms(10);
|
||||
|
||||
// configure trigger threshold
|
||||
uint32_t touch_value;
|
||||
touch_pad_read_benchmark(touch_channel, &touch_value);
|
||||
touch_pad_set_thresh(touch_channel, touch_value * 0.1); //10%
|
||||
}
|
||||
}
|
||||
|
||||
// configure touch interrupt
|
||||
touch_pad_timeout_set(true, SOC_TOUCH_PAD_THRESHOLD_MAX);
|
||||
touch_pad_isr_register(touch_interrupt, NULL, TOUCH_PAD_INTR_MASK_ALL);
|
||||
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
|
||||
}
|
||||
|
||||
void alarm_touch_touchalarm_prepare_for_deep_sleep(void) {
|
||||
if (!touch_channel_mask) {
|
||||
return;
|
||||
}
|
||||
|
||||
touch_pad_t touch_channel = TOUCH_PAD_MAX;
|
||||
for (uint8_t i = 1; i <= 14; i++) {
|
||||
if ((touch_channel_mask & 1 << i) != 0) {
|
||||
touch_channel = (touch_pad_t)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reset touch peripheral
|
||||
peripherals_touch_never_reset(false);
|
||||
peripherals_touch_reset();
|
||||
|
||||
// intialize touchpad
|
||||
peripherals_touch_init(touch_channel);
|
||||
|
||||
// configure touchpad for sleep
|
||||
touch_pad_sleep_channel_enable(touch_channel, true);
|
||||
touch_pad_sleep_channel_enable_proximity(touch_channel, false);
|
||||
|
||||
// wait for touch data to reset
|
||||
mp_hal_delay_ms(10);
|
||||
|
||||
// configure trigger threshold
|
||||
uint32_t touch_value;
|
||||
touch_pad_sleep_channel_read_smooth(touch_channel, &touch_value);
|
||||
touch_pad_sleep_set_threshold(touch_channel, touch_value * 0.1); //10%
|
||||
|
||||
// enable touchpad wakeup
|
||||
esp_sleep_enable_touchpad_wakeup();
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool alarm_touch_touchalarm_woke_us_up(void) {
|
||||
return woke_up;
|
||||
}
|
||||
|
||||
void alarm_touch_touchalarm_reset(void) {
|
||||
woke_up = false;
|
||||
touch_channel_mask = 0;
|
||||
// peripherals_touch_never_reset(false);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 microDev
|
||||
*
|
||||
* 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_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
|
||||
#define MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t *pin;
|
||||
} alarm_touch_touchalarm_obj_t;
|
||||
|
||||
// Find the alarm object that caused us to wake up or create an equivalent one.
|
||||
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms);
|
||||
// Check for the wake up alarm from pretend deep sleep.
|
||||
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
|
||||
void alarm_touch_touchalarm_prepare_for_deep_sleep(void);
|
||||
bool alarm_touch_touchalarm_woke_us_up(void);
|
||||
void alarm_touch_touchalarm_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
|
|
@ -42,6 +42,9 @@ CIRCUITPY_FRAMEBUFFERIO ?= 1
|
|||
CIRCUITPY_COUNTIO = 0
|
||||
CIRCUITPY_WATCHDOG ?= 1
|
||||
|
||||
# Sleep and Wakeup
|
||||
CIRCUITPY_ALARM = 1
|
||||
|
||||
# nRF52840-specific
|
||||
|
||||
ifeq ($(MCU_CHIP),nrf52840)
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
|
||||
// GPIO interrupt
|
||||
#define NRFX_GPIOTE_ENABLED 1
|
||||
#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1
|
||||
#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 2
|
||||
#define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 7
|
||||
|
||||
// NVM controller
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#include <stdint.h>
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/board.h"
|
||||
#ifdef MY_DEBUGUART
|
||||
#include "supervisor/serial.h" // dbg_printf()
|
||||
extern void _debug_uart_init(void);
|
||||
#endif
|
||||
|
||||
#include "nrfx/hal/nrf_clock.h"
|
||||
#include "nrfx/hal/nrf_power.h"
|
||||
|
@ -90,6 +94,9 @@ static volatile struct {
|
|||
uint32_t suffix;
|
||||
} overflow_tracker __attribute__((section(".uninitialized")));
|
||||
|
||||
uint32_t reset_reason_saved = 0;
|
||||
volatile int rtc_woke_up_counter = 0;
|
||||
|
||||
void rtc_handler(nrfx_rtc_int_type_t int_type) {
|
||||
if (int_type == NRFX_RTC_INT_OVERFLOW) {
|
||||
// Our RTC is 24 bits and we're clocking it at 32.768khz which is 32 (2 ** 5) subticks per
|
||||
|
@ -100,9 +107,25 @@ void rtc_handler(nrfx_rtc_int_type_t int_type) {
|
|||
supervisor_tick();
|
||||
} else if (int_type == NRFX_RTC_INT_COMPARE0) {
|
||||
nrfx_rtc_cc_set(&rtc_instance, 0, 0, false);
|
||||
} else if (int_type == NRFX_RTC_INT_COMPARE1) {
|
||||
// used in light sleep
|
||||
++rtc_woke_up_counter;
|
||||
nrfx_rtc_cc_set(&rtc_instance, 1, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
void _xxx_dumpRTC(void) {
|
||||
dbg_printf("\r\nRTC2\r\n");
|
||||
NRF_RTC_Type *r = rtc_instance.p_reg;
|
||||
dbg_printf("PRESCALER=%08X, ", (int)r->PRESCALER);
|
||||
dbg_printf("COUNTER=%08X ", (int)r->COUNTER);
|
||||
dbg_printf("INTENSET=%08X ", (int)r->INTENSET);
|
||||
dbg_printf("EVTENSET=%08X\r\n", (int)r->EVTENSET);
|
||||
dbg_printf("EVENTS_COMPARE[0..3]=%X,%X,%X,%X ", (int)r->EVENTS_COMPARE[0], (int)r->EVENTS_COMPARE[1], (int)r->EVENTS_COMPARE[2], (int)r->EVENTS_COMPARE[3]);
|
||||
dbg_printf("CC[0..3]=%08X,%08X,%08X,%08X\r\n", (int)r->CC[0], (int)r->CC[1], (int)r->CC[2], (int)r->CC[3]);
|
||||
dbg_printf("woke_up=%d\r\n", rtc_woke_up_counter);
|
||||
}
|
||||
|
||||
void tick_init(void) {
|
||||
if (!nrf_clock_lf_is_running(NRF_CLOCK)) {
|
||||
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART);
|
||||
|
@ -124,6 +147,7 @@ void tick_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
safe_mode_t port_init(void) {
|
||||
nrf_peripherals_clocks_init();
|
||||
|
||||
|
@ -153,6 +177,8 @@ safe_mode_t port_init(void) {
|
|||
analogin_init();
|
||||
#endif
|
||||
|
||||
reset_reason_saved = NRF_POWER->RESETREAS;
|
||||
|
||||
// If the board was reset by the WatchDogTimer, we may
|
||||
// need to boot into safe mode. Reset the RESETREAS bit
|
||||
// for the WatchDogTimer so we don't encounter this the
|
||||
|
@ -171,6 +197,7 @@ safe_mode_t port_init(void) {
|
|||
return NO_SAFE_MODE;
|
||||
}
|
||||
|
||||
|
||||
void reset_port(void) {
|
||||
#ifdef CIRCUITPY_GAMEPAD_TICKS
|
||||
gamepad_reset();
|
||||
|
@ -219,6 +246,10 @@ void reset_port(void) {
|
|||
#endif
|
||||
|
||||
reset_all_pins();
|
||||
|
||||
#ifdef MY_DEBUGUART
|
||||
_debug_uart_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void reset_to_bootloader(void) {
|
||||
|
@ -295,7 +326,7 @@ void port_disable_tick(void) {
|
|||
nrfx_rtc_tick_disable(&rtc_instance);
|
||||
}
|
||||
|
||||
void port_interrupt_after_ticks(uint32_t ticks) {
|
||||
void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks) {
|
||||
uint32_t current_ticks = nrfx_rtc_counter_get(&rtc_instance);
|
||||
uint32_t diff = 3;
|
||||
if (ticks > diff) {
|
||||
|
@ -304,7 +335,15 @@ void port_interrupt_after_ticks(uint32_t ticks) {
|
|||
if (diff > 0xffffff) {
|
||||
diff = 0xffffff;
|
||||
}
|
||||
nrfx_rtc_cc_set(&rtc_instance, 0, current_ticks + diff, true);
|
||||
nrfx_rtc_cc_set(&rtc_instance, channel, current_ticks + diff, true);
|
||||
}
|
||||
|
||||
void port_disable_interrupt_after_ticks_ch(uint32_t channel) {
|
||||
nrfx_rtc_cc_disable(&rtc_instance, channel);
|
||||
}
|
||||
|
||||
void port_interrupt_after_ticks(uint32_t ticks) {
|
||||
port_interrupt_after_ticks_ch(0, ticks);
|
||||
}
|
||||
|
||||
void port_idle_until_interrupt(void) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
|
@ -47,4 +48,6 @@ char serial_read(void);
|
|||
bool serial_bytes_available(void);
|
||||
bool serial_connected(void);
|
||||
|
||||
int dbg_printf(const char *fmt, ...)__attribute__((format (printf, 1, 2)));
|
||||
|
||||
#endif // MICROPY_INCLUDED_SUPERVISOR_SERIAL_H
|
||||
|
|
|
@ -36,6 +36,103 @@
|
|||
|
||||
#include "tusb.h"
|
||||
|
||||
#ifdef MY_DEBUGUART
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "nrfx.h"
|
||||
#include "nrf_uart.h"
|
||||
#include "nrfx_uart.h"
|
||||
const nrfx_uarte_t _dbg_uart_inst = NRFX_UARTE_INSTANCE(1);
|
||||
static int _dbg_uart_initialized = 0;
|
||||
#define DBG_PBUF_LEN 80
|
||||
static char _dbg_pbuf[DBG_PBUF_LEN+1];
|
||||
|
||||
void _debug_uart_init(void) {
|
||||
//if (_dbg_uart_initialized) return;
|
||||
nrfx_uarte_config_t config = {
|
||||
.pseltxd = 26,
|
||||
.pselrxd = 15,
|
||||
.pselcts = NRF_UARTE_PSEL_DISCONNECTED,
|
||||
.pselrts = NRF_UARTE_PSEL_DISCONNECTED,
|
||||
.p_context = NULL,
|
||||
.baudrate = NRF_UART_BAUDRATE_115200,
|
||||
.interrupt_priority = 7,
|
||||
.hal_cfg = {
|
||||
.hwfc = NRF_UARTE_HWFC_DISABLED,
|
||||
.parity = NRF_UARTE_PARITY_EXCLUDED
|
||||
}
|
||||
};
|
||||
nrfx_uarte_init(&_dbg_uart_inst, &config, NULL);
|
||||
// drive config
|
||||
nrf_gpio_cfg(config.pseltxd,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_PULLUP, // orig=NOPULL
|
||||
NRF_GPIO_PIN_H0H1, // orig=S0S1
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
_dbg_uart_initialized = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
void _debug_printbuf(char* data) {
|
||||
int siz, l;
|
||||
while((l = strlen(data)) != 0) {
|
||||
if (l <= DBG_PBUF_LEN) {
|
||||
siz = l;
|
||||
}
|
||||
else {
|
||||
siz = DBG_PBUF_LEN;
|
||||
}
|
||||
memcpy(_dbg_pbuf, data, siz);
|
||||
_dbg_pbuf[siz] = 0;
|
||||
nrfx_uarte_tx(&_dbg_uart_inst, (uint8_t const*)_dbg_pbuf, siz);
|
||||
data += siz;
|
||||
}
|
||||
}
|
||||
|
||||
void _debug_print_substr(const char* text, uint32_t length) {
|
||||
char* data = (char*)text;
|
||||
int siz;
|
||||
while(length != 0) {
|
||||
if (length <= DBG_PBUF_LEN) {
|
||||
siz = length;
|
||||
}
|
||||
else {
|
||||
siz = DBG_PBUF_LEN;
|
||||
}
|
||||
memcpy(_dbg_pbuf, data, siz);
|
||||
_dbg_pbuf[siz] = 0;
|
||||
nrfx_uarte_tx(&_dbg_uart_inst, (uint8_t const*)_dbg_pbuf, siz);
|
||||
data += siz;
|
||||
length -= siz;
|
||||
}
|
||||
}
|
||||
|
||||
void _debug_print(const char* s) {
|
||||
_debug_printbuf((char*)s);
|
||||
}
|
||||
|
||||
void _debug_uart_deinit(void) {
|
||||
nrfx_uarte_uninit(&_dbg_uart_inst);
|
||||
}
|
||||
|
||||
int dbg_printf(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int ret = vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern void _debug_led_init(void);
|
||||
extern void _debug_led_set(int v);
|
||||
#else /*!MY_DEBUGUART*/
|
||||
int dbg_printf(const char *fmt, ...) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Note: DEBUG_UART currently only works on STM32,
|
||||
* enabling on another platform will cause a crash.
|
||||
|
@ -63,10 +160,19 @@ void serial_early_init(void) {
|
|||
buf_array, true);
|
||||
common_hal_busio_uart_never_reset(&debug_uart);
|
||||
#endif
|
||||
|
||||
#ifdef MY_DEBUGUART
|
||||
_debug_uart_init();
|
||||
_debug_led_init();
|
||||
_debug_print("\r\ndebug_uart start\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void serial_init(void) {
|
||||
usb_init();
|
||||
#ifdef MY_DEBUGUART
|
||||
_debug_uart_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool serial_connected(void) {
|
||||
|
@ -144,6 +250,10 @@ void serial_write_substring(const char* text, uint32_t length) {
|
|||
int uart_errcode;
|
||||
common_hal_busio_uart_write(&debug_uart, (const uint8_t*) text, length, &uart_errcode);
|
||||
#endif
|
||||
|
||||
#ifdef MY_DEBUGUART
|
||||
_debug_print_substr(text, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
void serial_write(const char* text) {
|
||||
|
|
Loading…
Reference in New Issue