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.
diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c
index c8a88c7..7068d8e 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 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);
+}