From 98af89161084eec240f26015b35397b547abcbf8 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 31 Mar 2016 19:49:55 +0300 Subject: [PATCH] esp8266: Implement input part of dupterm handling. The idea is following: underlying interrupt-driven or push-style data source signals that more data is available for dupterm processing via call to mp_hal_signal_dupterm_input(). This triggers a task which pumps data between actual dupterm object (which may perform additional processing on data from low-level data source) and input ring buffer. --- esp8266/esp_mphal.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ esp8266/esp_mphal.h | 4 ++++ esp8266/main.c | 1 + 3 files changed, 62 insertions(+) diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c index c8a88c725e..7068d8e609 100644 --- a/esp8266/esp_mphal.c +++ b/esp8266/esp_mphal.c @@ -34,6 +34,7 @@ #include "py/obj.h" #include "py/mpstate.h" #include "extmod/misc.h" +#include "lib/utils/pyexec.h" extern void ets_wdt_disable(void); extern void wdt_feed(void); @@ -157,3 +158,59 @@ void __assert_func(const char *file, int line, const char *func, const char *exp void mp_hal_signal_input(void) { system_os_post(UART_TASK_ID, 0, 0); } + +static int call_dupterm_read(void) { + if (MP_STATE_PORT(term_obj) == NULL) { + return -1; + } + + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t read_m[3]; + mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); + read_m[2] = MP_OBJ_NEW_SMALL_INT(1); + mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); + if (res == mp_const_none) { + return -2; + } + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len == 0) { + mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); + MP_STATE_PORT(term_obj) = NULL; + return -1; + } + nlr_pop(); + return *(byte*)bufinfo.buf; + } else { + // Temporarily disable dupterm to avoid infinite recursion + mp_obj_t save_term = MP_STATE_PORT(term_obj); + MP_STATE_PORT(term_obj) = NULL; + mp_printf(&mp_plat_print, "dupterm: "); + mp_obj_print_exception(&mp_plat_print, nlr.ret_val); + MP_STATE_PORT(term_obj) = save_term; + } + + return -1; +} + +STATIC void dupterm_task_handler(os_event_t *evt) { + while (1) { + int c = call_dupterm_read(); + if (c < 0) { + break; + } + ringbuf_put(&input_buf, c); + } + mp_hal_signal_input(); +} + +STATIC os_event_t dupterm_evt_queue[4]; + +void dupterm_task_init() { + system_os_task(dupterm_task_handler, DUPTERM_TASK_ID, dupterm_evt_queue, MP_ARRAY_SIZE(dupterm_evt_queue)); +} + +void mp_hal_signal_dupterm_input(void) { + system_os_post(DUPTERM_TASK_ID, 0, 0); +} diff --git a/esp8266/esp_mphal.h b/esp8266/esp_mphal.h index bedf80b19f..6713e42551 100644 --- a/esp8266/esp_mphal.h +++ b/esp8266/esp_mphal.h @@ -36,6 +36,8 @@ extern const struct _mp_print_t mp_debug_print; extern ringbuf_t input_buf; // Call this after putting data to input_buf void mp_hal_signal_input(void); +// Call this when data is available in dupterm object +void mp_hal_signal_dupterm_input(void); void mp_hal_init(void); void mp_hal_rtc_init(void); @@ -47,7 +49,9 @@ void mp_hal_set_interrupt_char(int c); uint32_t mp_hal_get_cpu_freq(void); #define UART_TASK_ID 0 +#define DUPTERM_TASK_ID 1 void uart_task_init(); +void dupterm_task_init(); void ets_event_poll(void); #define ETS_POLL_WHILE(cond) { while (cond) ets_event_poll(); } diff --git a/esp8266/main.c b/esp8266/main.c index 4fc7757c81..bf68ebc96d 100644 --- a/esp8266/main.c +++ b/esp8266/main.c @@ -69,6 +69,7 @@ void init_done(void) { mp_reset(); mp_hal_stdout_tx_str("\r\n"); pyexec_event_repl_init(); + dupterm_task_init(); } void user_init(void) {