|
|
@ -167,12 +167,49 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) { |
|
|
|
} |
|
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep); |
|
|
|
|
|
|
|
// These values are from the datasheet
|
|
|
|
#define ESP_TIMER_US_MIN (100) |
|
|
|
#define ESP_TIMER_US_MAX (0xfffffff) |
|
|
|
#define ESP_TIMER_MS_MAX (0x689d0) |
|
|
|
|
|
|
|
typedef struct _esp_timer_obj_t { |
|
|
|
mp_obj_base_t base; |
|
|
|
os_timer_t timer; |
|
|
|
uint32_t remain_ms; // if non-zero, remaining time to handle large periods
|
|
|
|
uint32_t period_ms; // if non-zero, periodic timer with a large period
|
|
|
|
mp_obj_t callback; |
|
|
|
} esp_timer_obj_t; |
|
|
|
|
|
|
|
STATIC void esp_timer_arm_ms(esp_timer_obj_t *self, uint32_t ms, bool repeat) { |
|
|
|
if (ms <= ESP_TIMER_MS_MAX) { |
|
|
|
self->remain_ms = 0; |
|
|
|
self->period_ms = 0; |
|
|
|
} else { |
|
|
|
self->remain_ms = ms - ESP_TIMER_MS_MAX; |
|
|
|
if (repeat) { |
|
|
|
repeat = false; |
|
|
|
self->period_ms = ms; |
|
|
|
} else { |
|
|
|
self->period_ms = 0; |
|
|
|
} |
|
|
|
ms = ESP_TIMER_MS_MAX; |
|
|
|
} |
|
|
|
os_timer_arm(&self->timer, ms, repeat); |
|
|
|
} |
|
|
|
|
|
|
|
STATIC void esp_timer_arm_us(esp_timer_obj_t *self, uint32_t us, bool repeat) { |
|
|
|
if (us < ESP_TIMER_US_MIN) { |
|
|
|
us = ESP_TIMER_US_MIN; |
|
|
|
} |
|
|
|
if (us <= ESP_TIMER_US_MAX) { |
|
|
|
self->remain_ms = 0; |
|
|
|
self->period_ms = 0; |
|
|
|
os_timer_arm_us(&self->timer, us, repeat); |
|
|
|
} else { |
|
|
|
esp_timer_arm_ms(self, us / 1000, repeat); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const mp_obj_type_t esp_timer_type; |
|
|
|
|
|
|
|
STATIC void esp_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { |
|
|
@ -189,7 +226,21 @@ STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz |
|
|
|
|
|
|
|
STATIC void esp_timer_cb(void *arg) { |
|
|
|
esp_timer_obj_t *self = arg; |
|
|
|
mp_sched_schedule(self->callback, self); |
|
|
|
if (self->remain_ms != 0) { |
|
|
|
// Handle periods larger than the maximum system period
|
|
|
|
uint32_t next_period_ms = self->remain_ms; |
|
|
|
if (next_period_ms > ESP_TIMER_MS_MAX) { |
|
|
|
next_period_ms = ESP_TIMER_MS_MAX; |
|
|
|
} |
|
|
|
self->remain_ms -= next_period_ms; |
|
|
|
os_timer_arm(&self->timer, next_period_ms, false); |
|
|
|
} else { |
|
|
|
mp_sched_schedule(self->callback, self); |
|
|
|
if (self->period_ms != 0) { |
|
|
|
// A periodic timer with a larger period: reschedule it
|
|
|
|
esp_timer_arm_ms(self, self->period_ms, true); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
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) { |
|
|
@ -225,30 +276,30 @@ STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, size_t n_args, cons |
|
|
|
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); |
|
|
|
esp_timer_arm_ms(self, (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); |
|
|
|
esp_timer_arm_us(self, (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); |
|
|
|
esp_timer_arm_us(self, 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); |
|
|
|
esp_timer_arm_ms(self, period, args[ARG_mode].u_int); |
|
|
|
} else if (hz == 1000000) { |
|
|
|
os_timer_arm_us(&self->timer, period, args[ARG_mode].u_int); |
|
|
|
esp_timer_arm_us(self, 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); |
|
|
|
esp_timer_arm_us(self, (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); |
|
|
|
esp_timer_arm_ms(self, (mp_int_t)(period_us / 1000), args[ARG_mode].u_int); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|