Files
Boris Lovosevic 7ca7a402f3 Added build time option to start REPL in separate thread
Running REPL in thread may solve some issues with uasyncio
  and long running or infinite loops

Updated 'machine.UART' module
  - fixed bug when wrong parameter was returned to callback functions
  - added option to set inverted mode for Rx, Tx, CTS, RTS
  - enabled using hw flow controll if CTS and/or RTC pisn are defined
  - 'write_break()' function added whitch enits the break signal after data write

Updated 'sys' module
  Added 'sys.tz()' to get or set the time zone
  The time zone is saved in NVS string and time zone is set on boot
  The time zone can be now preserved on reset, power off or deepsleep wake up

Updated 'machine' module
  Added SetStackSize() function to set the MicroPython stack size
  Added SetHeapSize() function to set the MicroPython heap size
  Both heap an stack sizes are set as NVS variables and are read at boot time
    to set the sizes, so the sizes may now be different than the compiled ones

Updated 'machine.timer' module
  Changed function name 'reshot()' -> 'reshoot()'
2018-04-18 13:52:42 +02:00

699 lines
24 KiB
C

/*
* This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo
*
* The MIT License (MIT)
*
* Based on original 'machine-timer.c' from https://github.com/micropython/micropython-esp32
* completely rewritten and many new functions and features added
*
* Copyright (c) 2017 Boris Lovosevic (https://github.com/loboris)
*
* 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 <stdint.h>
#include <stdio.h>
#include "driver/timer.h"
#include "py/runtime.h"
#include "modmachine.h"
#define TIMER_INTR_SEL TIMER_INTR_LEVEL
#define TIMER_DIVIDER_KHZ 40000 // 500 us per tick, 1 kHz
#define TIMER_DIVIDER_MHZ 80 // 1 us per tick, 1 MHz
#define TIMER_SCALE_KHZ 2
#define TIMER_SCALE_MHZ 100
#define TIMER_RUNNING 1
#define TIMER_PAUSED 0
#define TIMER_TYPE_ONESHOT 0
#define TIMER_TYPE_PERIODIC 1
#define TIMER_TYPE_CHRONO 2
#define TIMER_TYPE_EXTBASE 3
#define TIMER_TYPE_EXT 4
#define TIMER_TYPE_MAX 5
#define TIMER_EXT_NUM 8
#define TIMER_FLAGS 0
typedef struct _machine_timer_obj_t {
mp_obj_base_t base;
uint8_t id;
uint8_t state;
uint8_t type;
int8_t debug_pin;
int8_t debug_pin_mode;
mp_uint_t repeat;
mp_uint_t period;
uint64_t event_num;
uint64_t cb_num;
mp_obj_t callback;
intr_handle_t handle;
uint64_t counter;
uint64_t alarm;
} machine_timer_obj_t;
const mp_obj_type_t machine_timer_type;
static machine_timer_obj_t * timers_used[4] = {NULL};
static machine_timer_obj_t * ext_timers[TIMER_EXT_NUM] = {NULL};
//----------------------------------------------
STATIC esp_err_t check_esp_err(esp_err_t code) {
if (code) {
mp_raise_OSError(code);
}
return code;
}
//----------------------------------------------------------------------------------------------
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
machine_timer_obj_t *self = self_in;
mp_printf(print, "Timer(%d) ", self->id);
if (self->type >= TIMER_TYPE_MAX) {
mp_printf(print, "Not initialized");
return;
}
char stype[16];
if (self->type == TIMER_TYPE_PERIODIC) sprintf(stype, "Periodic");
else if (self->type == TIMER_TYPE_ONESHOT) sprintf(stype, "One shot");
else if (self->type == TIMER_TYPE_CHRONO) sprintf(stype, "Chrono");
else if (self->type == TIMER_TYPE_EXTBASE) sprintf(stype, "Extended base");
else if (self->type == TIMER_TYPE_EXT) sprintf(stype, "Extended");
else sprintf(stype, "Unknown");
if (self->type == TIMER_TYPE_CHRONO) {
mp_printf(print, "Period: 1 us; ");
}
else if (self->type == TIMER_TYPE_EXT) {
mp_printf(print, "Period: %d ms; ", self->period);
}
else {
mp_printf(print, "Period: %d ms; ", self->period / 2);
}
if (self->type != TIMER_TYPE_CHRONO) {
mp_printf(print, "Repeat: %s; ", (self->repeat ? "True" : "False"));
}
mp_printf(print, "Type: %s; ", stype);
mp_printf(print, "Running: %s\n", (self->state == TIMER_RUNNING) ? "yes" : "no");
if ((self->type != TIMER_TYPE_CHRONO) && (self->type != TIMER_TYPE_EXTBASE)) {
mp_printf(print, " Events: %lu", self->event_num);
mp_printf(print, "; Callbacks: %lu; ", self->cb_num);
mp_printf(print, "Missed: %lu", self->event_num - self->cb_num);
}
if (self->debug_pin >= 0) {
mp_printf(print, "\n Debug output on gpio %d, ", self->debug_pin);
}
if (self->type == TIMER_TYPE_EXTBASE) {
machine_timer_obj_t *extmr;
mp_printf(print, " Handled extended timers:\n");
for (int i=0; i < TIMER_EXT_NUM; i++) {
extmr = ext_timers[i];
if (extmr) {
mp_printf(print, " %2d: Period: %d ms, %s", i+4, extmr->period, (extmr->state == TIMER_RUNNING) ? "Running" : "Paused");
}
}
}
}
//-----------------------------------------------------------------------------------------------------------------
STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args)
{
mp_arg_check_num(n_args, n_kw, 1, 1, false);
machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
self->base.type = &machine_timer_type;
self->callback = NULL;
self->handle = NULL;
self->event_num = 0;
self->cb_num = 0;
self->debug_pin = -1;
self->state = TIMER_PAUSED;
self->type = TIMER_TYPE_MAX;
int tmr = mp_obj_get_int(args[0]);
if ((tmr < 0) || (tmr > 11)) {
mp_raise_ValueError("Only base timers 0~3 and extended timers 4~11 can be used.");
}
if (tmr < 4) {
// Base hardware timer
if (timers_used[tmr] != NULL) {
mp_raise_ValueError("Timer already in use.");
}
timers_used[tmr] = self;
}
else {
// Extended timer
if ((timers_used[0] == NULL) || (timers_used[0]->type != TIMER_TYPE_EXTBASE)) {
mp_raise_ValueError("Timer 0 not configured as extended timer.");
}
if (ext_timers[(tmr-4)] != NULL) {
mp_raise_ValueError("Extended Timer already in use.");
}
ext_timers[(tmr-4)] = self;
}
self->id = tmr;
return self;
}
//----------------------------------------------------------
STATIC void machine_timer_disable(machine_timer_obj_t *self)
{
if ((self->id < 4) && (self->handle)) {
timer_pause((self->id >> 1) & 1, self->id & 1);
if (self->type != TIMER_TYPE_CHRONO) esp_intr_free(self->handle);
timers_used[self->id] = NULL;
}
else ext_timers[(self->id-4)] = NULL;
self->callback = NULL;
self->handle = NULL;
self->event_num = 0;
self->cb_num = 0;
self->debug_pin = -1;
self->state = TIMER_PAUSED;
self->type = TIMER_TYPE_MAX;
}
//------------------------------------------
STATIC void machine_timer_isr(void *self_in)
{
machine_timer_obj_t *self = (machine_timer_obj_t *)self_in;
if (self->id & 2) {
if (self->id & 1) TIMERG1.int_clr_timers.t1 = 1;
else TIMERG1.int_clr_timers.t0 = 1;
TIMERG1.hw_timer[self->id & 1].config.alarm_en = self->repeat;
}
else {
if (self->id & 1) TIMERG0.int_clr_timers.t1 = 1;
else TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[self->id & 1].config.alarm_en = self->repeat;
}
if (self->debug_pin >= 0) {
if (self->debug_pin_mode >= 0) gpio_set_level(self->debug_pin, (self->debug_pin_mode & 1));
else gpio_set_level(self->debug_pin, (self->event_num & 1));
}
self->event_num++;
if ((self->callback) && (mp_sched_schedule(self->callback, self, NULL))) self->cb_num++;
}
//----------------------------------------------
STATIC void machine_ext_timer_isr(void *self_in)
{
// extended timer interrupt is fired every 1 ms
machine_timer_obj_t *self = (machine_timer_obj_t *)self_in;
machine_timer_obj_t *extmr;
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
self->event_num++;
// test extended timers
for (int i=0; i < TIMER_EXT_NUM; i++) {
extmr = ext_timers[i];
if (extmr) {
// Extended timer exists
if (extmr->state == TIMER_RUNNING) {
// Timer is running, increment extended timer's counter
extmr->counter++;
if ((extmr->counter % extmr->period) == 0) {
// Extended timer's period elapsed, increment events number
extmr->event_num++;
if (extmr->counter == extmr->alarm) {
// Schedule the callback execution
if ((extmr->callback) && (mp_sched_schedule(extmr->callback, extmr, NULL))) {
extmr->cb_num++;
self->cb_num++;
}
if (extmr->repeat) extmr->counter = 0x00000000ULL;
}
}
}
}
}
}
//---------------------------------------------------------
STATIC void machine_timer_enable(machine_timer_obj_t *self)
{
if (self->id >= 4) {
ext_timers[(self->id-4)] = self;
return;
}
timer_config_t config;
config.counter_dir = TIMER_COUNT_UP;
config.intr_type = TIMER_INTR_LEVEL;
config.counter_en = TIMER_PAUSE;
if (self->type == TIMER_TYPE_CHRONO) {
config.alarm_en = TIMER_ALARM_DIS;
config.auto_reload = TIMER_AUTORELOAD_DIS;
config.divider = TIMER_DIVIDER_MHZ;
}
else {
config.alarm_en = TIMER_ALARM_EN;
config.auto_reload = self->repeat;
config.divider = TIMER_DIVIDER_KHZ;
}
check_esp_err(timer_init((self->id >> 1) & 1, self->id & 1, &config));
// Timer's counter will initially start from value below.
// Also, if auto_reload is set, this value will be automatically reload on alarm
check_esp_err(timer_set_counter_value((self->id >> 1) & 1, self->id & 1, 0x00000000ULL));
if (self->type != TIMER_TYPE_CHRONO) {
// Configure the alarm value and the interrupt on alarm.
check_esp_err(timer_set_alarm_value((self->id >> 1) & 1, self->id & 1, self->period));
// Enable timer interrupt
check_esp_err(timer_enable_intr((self->id >> 1) & 1, self->id & 1));
// Register interrupt callback
if (self->type == TIMER_TYPE_EXTBASE) {
check_esp_err(timer_isr_register((self->id >> 1) & 1, self->id & 1, machine_ext_timer_isr, (void*)self, TIMER_FLAGS, &self->handle));
}
else {
check_esp_err(timer_isr_register((self->id >> 1) & 1, self->id & 1, machine_timer_isr, (void*)self, TIMER_FLAGS, &self->handle));
}
check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1));
}
timers_used[self->id] = self;
}
//---------------------------------------------------------------------------------------------------------------------------------
STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
{
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 10} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_TYPE_PERIODIC} },
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_dbgpin, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_dbgpinmode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
machine_timer_disable(self);
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);
self->handle = NULL;
self->event_num = 0;
self->cb_num = 0;
self->debug_pin = -1;
if (self->id < 4) {
// Base hardware timer
self->type = args[1].u_int & 3;
if (self->type == TIMER_TYPE_EXTBASE) {
if (self->id != 0) {
mp_raise_ValueError("Only timer 0 can be used as extended timer.");
}
// Extended base timer types use an 2 kHz clock
// set the period to 1 ms, repeat mode, no callback
self->period = 2;
self->repeat = 1;
self->callback = NULL;
}
else if (self->type == TIMER_TYPE_CHRONO) {
// Chrono Timer uses an 1 MHz clock, no callback
// set period in us
self->period = 1;
self->repeat = 0;
self->callback = NULL;
}
else {
// Other timer types use an 2 kHz clock, convert period to ms.
if (args[0].u_int < 1) self->period = 2;
else self->period = args[0].u_int * 2;
self->repeat = args[1].u_int & 1;
if (args[2].u_obj != mp_const_none) self->callback = args[2].u_obj;
// set the debug gpio if used
if ((args[3].u_int >= 0) && (args[3].u_int < 34)) {
self->debug_pin = args[3].u_int;
self->debug_pin_mode = args[4].u_int;
gpio_pad_select_gpio(self->debug_pin);
gpio_set_direction(self->debug_pin, GPIO_MODE_OUTPUT);
gpio_set_level(self->debug_pin, 0);
}
}
// enable and start the timer
machine_timer_enable(self);
if (self->type != TIMER_TYPE_CHRONO) self->state = TIMER_RUNNING;
else self->state = TIMER_PAUSED;
}
else {
// Extended timer
uint8_t mode = args[1].u_int & 3;
if ((mode != TIMER_TYPE_PERIODIC) && (mode != TIMER_TYPE_ONESHOT)) {
mp_raise_ValueError("Wrong mode for extended timer.");
}
self->type = TIMER_TYPE_EXT;
if (args[0].u_int < 1) self->period = 1;
else self->period = args[0].u_int;
self->repeat = args[1].u_int & 1;
if (args[2].u_obj != mp_const_none) self->callback = args[2].u_obj;
self->counter = 0x00000000ULL;
self->alarm = self->period;
self->state = TIMER_RUNNING;
machine_timer_enable(self);
}
return mp_const_none;
}
//-------------------------------------------------------------------------------------------
STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
return machine_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
//----------------------------------------------------
STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
if ((self->id < 4) && (self->type == TIMER_TYPE_EXTBASE)) {
// Check if any extended timer exists
uint8_t num_ext = 0;
for (int i=0; i < TIMER_EXT_NUM; i++) {
if (ext_timers[i] != NULL) num_ext++;
}
if (num_ext) {
mp_raise_msg(&mp_type_OSError, "Can't deinit extended base timer, some timers running.");
}
}
machine_timer_disable(self_in);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
//---------------------------------------------------
STATIC mp_obj_t machine_timer_value(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
uint64_t result;
if (self->id < 4) {
// Base hardware timer
if (self->type == TIMER_TYPE_EXTBASE) result = self->event_num; // value in ms
else {
timer_get_counter_value((self->id >> 1) & 1, self->id & 1, &result);
if (self->type != TIMER_TYPE_CHRONO) result *= (self->period / 2); // value in us
}
}
else {
// Extended timer
result = self->counter; // value in ms
}
return mp_obj_new_int_from_ull(result);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_value_obj, machine_timer_value);
//---------------------------------------------------
STATIC mp_obj_t machine_timer_pause(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
if (self->id < 4) {
// Base hardware timer
if (self->type == TIMER_TYPE_EXTBASE) {
// Check if any extended timer is running
uint8_t num_ext = 0;
for (int i=0; i < TIMER_EXT_NUM; i++) {
if ((ext_timers[i] != NULL) && (ext_timers[i]->state == TIMER_RUNNING)) num_ext++;
}
if (num_ext) {
mp_raise_msg(&mp_type_OSError, "Can't pause extended base timer, some timers running.");
}
}
if (self->state == TIMER_RUNNING) {
check_esp_err(timer_pause((self->id >> 1) & 1, self->id & 1));
self->state = TIMER_PAUSED;
}
}
else self->state = TIMER_PAUSED;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_pause_obj, machine_timer_pause);
//----------------------------------------------------
STATIC mp_obj_t machine_timer_resume(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
if (self->id < 4) {
// Base hardware timer
if (self->state == TIMER_PAUSED) {
check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1));
self->state = TIMER_RUNNING;
}
}
else {
if ((timers_used[0] != NULL) && (timers_used[0]->state == TIMER_RUNNING)) self->state = TIMER_RUNNING;
else self->state = TIMER_PAUSED;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_resume_obj, machine_timer_resume);
//---------------------------------------------------
STATIC mp_obj_t machine_timer_start(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
if (self->type == TIMER_TYPE_CHRONO) {
if (self->state == TIMER_RUNNING) {
check_esp_err(timer_pause((self->id >> 1) & 1, self->id & 1));
}
self->event_num = 0;
check_esp_err(timer_set_counter_value((self->id >> 1) & 1, self->id & 1, 0x00000000ULL));
check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1));
self->state = TIMER_RUNNING;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_start_obj, machine_timer_start);
//---------------------------------------------------------------------
STATIC mp_obj_t machine_timer_shot(size_t n_args, const mp_obj_t *args)
{
machine_timer_obj_t *self = args[0];
if (self->type != TIMER_TYPE_ONESHOT) {
mp_raise_ValueError("Timer is not one_shot timer.");
}
int tmo = self->period;
if (n_args > 1) tmo = mp_obj_get_int(args[1]) * 2;
if (tmo < 1) tmo = self->period;
uint64_t cnt_val;
check_esp_err(timer_pause((self->id >> 1) & 1, self->id & 1));
check_esp_err(timer_get_counter_value((self->id >> 1) & 1, self->id & 1, &cnt_val));
check_esp_err(timer_set_alarm_value((self->id >> 1) & 1, self->id & 1, cnt_val+tmo));
check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1));
if (self->id & 2) {
TIMERG1.hw_timer[self->id & 1].config.alarm_en = 1;
}
else {
TIMERG0.hw_timer[self->id & 1].config.alarm_en = 1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_timer_shot_obj, 1, 2, machine_timer_shot);
//------------------------------------------------
STATIC mp_obj_t machine_timer_id(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(self->id);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_id_obj, machine_timer_id);
//----------------------------------------------------
STATIC mp_obj_t machine_timer_events(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
mp_obj_t tuple[2];
tuple[0] = mp_obj_new_int_from_ull(self->event_num);
tuple[1] = mp_obj_new_int_from_ull(self->cb_num);
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_events_obj, machine_timer_events);
//-------------------------------------------------------
STATIC mp_obj_t machine_timer_isrunning(mp_obj_t self_in)
{
machine_timer_obj_t *self = self_in;
if (self->state == TIMER_RUNNING) return mp_const_true;
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_isrunning_obj, machine_timer_isrunning);
//-----------------------------------------------------------------------
STATIC mp_obj_t machine_timer_period(size_t n_args, const mp_obj_t *args)
{
machine_timer_obj_t *self = args[0];
uint32_t period = 1;
if (n_args > 1) {
if (self->type == TIMER_TYPE_EXTBASE) return MP_OBJ_NEW_SMALL_INT(1);
uint8_t old_state = self->state;
// Pause timer
if (self->id < 4) {
// Base hardware timer
if (self->state == TIMER_RUNNING) {
check_esp_err(timer_pause((self->id >> 1) & 1, self->id & 1));
}
}
self->state = TIMER_PAUSED;
// Set new period
period = mp_obj_get_int(args[1]);
if (self->type == TIMER_TYPE_CHRONO) {
if (period < 10) period = 1;
else period /= 10;
}
else if (self->type == TIMER_TYPE_EXT) {
if (period < 1) period = 1;
self->counter = 0x00000000ULL;
self->alarm = period;
}
else {
if (period < 1) period = 2;
else period *= 2;
}
self->period = period;
if (self->id < 4) {
check_esp_err(timer_set_counter_value((self->id >> 1) & 1, self->id & 1, 0x00000000ULL));
check_esp_err(timer_set_alarm_value((self->id >> 1) & 1, self->id & 1, self->period));
}
if ((self->id < 4) && (old_state == TIMER_RUNNING)){
// Base hardware timer
check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1));
}
self->state = old_state;
}
if (self->type == TIMER_TYPE_CHRONO) period = self->period * 10;
else if (self->type == TIMER_TYPE_EXT) period = self->period;
else period = self->period / 2;
return MP_OBJ_NEW_SMALL_INT(period);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_timer_period_obj, 1, 2, machine_timer_period);
//-------------------------------------------------------------------------
STATIC mp_obj_t machine_timer_callback(size_t n_args, const mp_obj_t *args)
{
machine_timer_obj_t *self = args[0];
if (n_args == 1) {
if (self->callback == NULL) return mp_const_false;
return mp_const_true;
}
if ((self->type == TIMER_TYPE_EXTBASE) || (self->type == TIMER_TYPE_CHRONO)) return mp_const_false;
uint8_t old_state = self->state;
// Pause timer
if (self->id < 4) {
// Base hardware timer
if (self->state == TIMER_RUNNING) {
check_esp_err(timer_pause((self->id >> 1) & 1, self->id & 1));
}
}
self->state = TIMER_PAUSED;
if ((MP_OBJ_IS_FUN(args[1])) || (MP_OBJ_IS_METH(args[1]))) {
// Set new callback
self->counter = 0x00000000ULL;
self->alarm = self->period;
self->callback = args[1];
}
else self->callback = NULL;
if ((self->id < 4) && (old_state == TIMER_RUNNING)){
// Base hardware timer
check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1));
}
self->state = old_state;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_timer_callback_obj, 1, 2, machine_timer_callback);
//==============================================================
STATIC const mp_map_elem_t machine_timer_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), (mp_obj_t)&machine_timer_deinit_obj },
{ MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_timer_deinit_obj },
{ MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&machine_timer_init_obj },
{ MP_ROM_QSTR(MP_QSTR_value), (mp_obj_t)&machine_timer_value_obj },
{ MP_ROM_QSTR(MP_QSTR_events), (mp_obj_t)&machine_timer_events_obj },
{ MP_ROM_QSTR(MP_QSTR_reshoot), (mp_obj_t)&machine_timer_shot_obj },
{ MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&machine_timer_start_obj },
{ MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&machine_timer_pause_obj },
{ MP_ROM_QSTR(MP_QSTR_pause), (mp_obj_t)&machine_timer_pause_obj },
{ MP_ROM_QSTR(MP_QSTR_resume), (mp_obj_t)&machine_timer_resume_obj },
{ MP_ROM_QSTR(MP_QSTR_timernum), (mp_obj_t)&machine_timer_id_obj },
{ MP_ROM_QSTR(MP_QSTR_period), (mp_obj_t)&machine_timer_period_obj },
{ MP_ROM_QSTR(MP_QSTR_callback), (mp_obj_t)&machine_timer_callback_obj },
{ MP_ROM_QSTR(MP_QSTR_isrunning), (mp_obj_t)&machine_timer_isrunning_obj },
{ MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_TYPE_ONESHOT) },
{ MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_TYPE_PERIODIC) },
{ MP_ROM_QSTR(MP_QSTR_CHRONO), MP_ROM_INT(TIMER_TYPE_CHRONO) },
{ MP_ROM_QSTR(MP_QSTR_EXTBASE), MP_ROM_INT(TIMER_TYPE_EXTBASE) },
{ MP_ROM_QSTR(MP_QSTR_EXTENDED), MP_ROM_INT(TIMER_TYPE_EXTBASE) },
};
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
//========================================
const mp_obj_type_t machine_timer_type = {
{ &mp_type_type },
.name = MP_QSTR_Timer,
.print = machine_timer_print,
.make_new = machine_timer_make_new,
.locals_dict = (mp_obj_t)&machine_timer_locals_dict,
};