summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/esp32/machine_timer.c41
-rw-r--r--ports/esp8266/main.c5
-rw-r--r--ports/esp8266/modmachine.c55
3 files changed, 90 insertions, 11 deletions
diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c
index eee77e482..7dca9e014 100644
--- a/ports/esp32/machine_timer.c
+++ b/ports/esp32/machine_timer.c
@@ -37,7 +37,9 @@
#include "mphalport.h"
#define TIMER_INTR_SEL TIMER_INTR_LEVEL
-#define TIMER_DIVIDER 40000
+#define TIMER_DIVIDER 8
+
+// TIMER_BASE_CLK is normally 80MHz. TIMER_DIVIDER ought to divide this exactly
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER)
#define TIMER_FLAGS 0
@@ -48,7 +50,8 @@ typedef struct _machine_timer_obj_t {
mp_uint_t index;
mp_uint_t repeat;
- mp_uint_t period;
+ // ESP32 timers are 64-bit
+ uint64_t period;
mp_obj_t callback;
@@ -131,10 +134,23 @@ STATIC void machine_timer_enable(machine_timer_obj_t *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) {
+ enum {
+ ARG_mode,
+ ARG_callback,
+ ARG_period,
+ ARG_tick_hz,
+ ARG_freq,
+ };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
+ { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
+#if MICROPY_PY_BUILTINS_FLOAT
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+#else
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
+#endif
};
machine_timer_disable(self);
@@ -142,10 +158,21 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n
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);
- // Timer uses an 80MHz base clock, which is divided by the divider/scalar, we then convert to ms.
- self->period = (args[0].u_int * TIMER_BASE_CLK) / (1000 * TIMER_DIVIDER);
- self->repeat = args[1].u_int;
- self->callback = args[2].u_obj;
+#if MICROPY_PY_BUILTINS_FLOAT
+ if (args[ARG_freq].u_obj != mp_const_none) {
+ self->period = (uint64_t)(TIMER_SCALE / mp_obj_get_float(args[ARG_freq].u_obj));
+ }
+#else
+ if (args[ARG_freq].u_int != 0xffffffff) {
+ self->period = TIMER_SCALE / ((uint64_t)args[ARG_freq].u_int);
+ }
+#endif
+ else {
+ self->period = (((uint64_t)args[ARG_period].u_int) * TIMER_SCALE) / args[ARG_tick_hz].u_int;
+ }
+
+ self->repeat = args[ARG_mode].u_int;
+ self->callback = args[ARG_callback].u_obj;
self->handle = NULL;
machine_timer_enable(self);
diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c
index 7e5034b04..55fd0e3a0 100644
--- a/ports/esp8266/main.c
+++ b/ports/esp8266/main.c
@@ -33,6 +33,10 @@
#include "py/mperrno.h"
#include "py/mphal.h"
#include "py/gc.h"
+
+// This needs to be defined before any ESP SDK headers are included
+#define USE_US_TIMER 1
+
#include "extmod/misc.h"
#include "lib/mp-readline/readline.h"
#include "lib/utils/pyexec.h"
@@ -126,6 +130,7 @@ soft_reset:
}
void user_init(void) {
+ system_timer_reinit();
system_init_done_cb(init_done);
}
diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c
index 7e5f6714b..1c1d902e5 100644
--- a/ports/esp8266/modmachine.c
+++ b/ports/esp8266/modmachine.c
@@ -30,6 +30,10 @@
#include "py/obj.h"
#include "py/runtime.h"
+
+// This needs to be set before we include the RTOS headers
+#define USE_US_TIMER 1
+
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
@@ -160,22 +164,65 @@ STATIC void esp_timer_cb(void *arg) {
}
STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum {
+ ARG_mode,
+ ARG_callback,
+ ARG_period,
+ ARG_tick_hz,
+ ARG_freq,
+ };
static const mp_arg_t allowed_args[] = {
-// { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
+ { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
+#if MICROPY_PY_BUILTINS_FLOAT
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+#else
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
+#endif
};
// parse args
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->callback = args[2].u_obj;
+ self->callback = args[ARG_callback].u_obj;
// Be sure to disarm timer before making any changes
os_timer_disarm(&self->timer);
os_timer_setfn(&self->timer, esp_timer_cb, self);
- os_timer_arm(&self->timer, args[0].u_int, args[1].u_int);
+
+#if MICROPY_PY_BUILTINS_FLOAT
+ if (args[ARG_freq].u_obj != mp_const_none) {
+ mp_float_t freq = mp_obj_get_float(args[ARG_freq].u_obj);
+ if (freq < 0.001) {
+ os_timer_arm(&self->timer, (mp_int_t)(1000 / freq), args[ARG_mode].u_int);
+ } else {
+ os_timer_arm_us(&self->timer, (mp_int_t)(1000000 / freq), args[ARG_mode].u_int);
+ }
+ }
+#else
+ if (args[ARG_freq].u_int != 0xffffffff) {
+ os_timer_arm_us(&self->timer, 1000000 / args[ARG_freq].u_int, args[ARG_mode].u_int);
+ }
+#endif
+ else {
+ mp_int_t period = args[ARG_period].u_int;
+ mp_int_t hz = args[ARG_tick_hz].u_int;
+ if (hz == 1000) {
+ os_timer_arm(&self->timer, period, args[ARG_mode].u_int);
+ } else if (hz == 1000000) {
+ os_timer_arm_us(&self->timer, period, args[ARG_mode].u_int);
+ } else {
+ // Use a long long to ensure that we don't either overflow or loose accuracy
+ uint64_t period_us = (((uint64_t)period) * 1000000) / hz;
+ if (period_us < 0x80000000ull) {
+ os_timer_arm_us(&self->timer, (mp_int_t)period_us, args[ARG_mode].u_int);
+ } else {
+ os_timer_arm(&self->timer, (mp_int_t)(period_us / 1000), args[ARG_mode].u_int);
+ }
+ }
+ }
return mp_const_none;
}