Skip to content

Commit 37282f8

Browse files
committed
extmod/uos_dupterm: Update uos.dupterm() and helper funcs to have index.
The uos.dupterm() signature and behaviour is updated to reflect the latest enhancements in the docs. It has minor backwards incompatibility in that it no longer accepts zero arguments. The dupterm_rx helper function is moved from esp8266 to extmod and generalised to support multiple dupterm slots. A port can specify multiple slots by defining the MICROPY_PY_OS_DUPTERM config macro to an integer, being the number of slots it wants to have; 0 means to disable the dupterm feature altogether. The unix and esp8266 ports are updated to work with the new interface and are otherwise unchanged with respect to functionality.
1 parent e39fcda commit 37282f8

File tree

8 files changed

+95
-73
lines changed

8 files changed

+95
-73
lines changed

extmod/misc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@
3535
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
3636

3737
#if MICROPY_PY_OS_DUPTERM
38+
int mp_uos_dupterm_rx_chr(void);
3839
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
39-
void mp_uos_deactivate(const char *msg, mp_obj_t exc);
40+
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
4041
#else
4142
#define mp_uos_dupterm_tx_strn(s, l)
4243
#endif

extmod/uos_dupterm.c

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* The MIT License (MIT)
55
*
66
* Copyright (c) 2016 Paul Sokolovsky
7+
* Copyright (c) 2017 Damien P. George
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
910
* of this software and associated documentation files (the "Software"), to deal
@@ -31,61 +32,108 @@
3132
#include "py/objtuple.h"
3233
#include "py/objarray.h"
3334
#include "py/stream.h"
35+
#include "lib/utils/interrupt_char.h"
3436

3537
#if MICROPY_PY_OS_DUPTERM
3638

37-
void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
38-
mp_obj_t term = MP_STATE_PORT(term_obj);
39-
MP_STATE_PORT(term_obj) = NULL;
39+
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
40+
mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
41+
MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
4042
mp_printf(&mp_plat_print, msg);
4143
if (exc != MP_OBJ_NULL) {
4244
mp_obj_print_exception(&mp_plat_print, exc);
4345
}
4446
mp_stream_close(term);
4547
}
4648

49+
int mp_uos_dupterm_rx_chr(void) {
50+
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
51+
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
52+
continue;
53+
}
54+
55+
nlr_buf_t nlr;
56+
if (nlr_push(&nlr) == 0) {
57+
mp_obj_t readinto_m[3];
58+
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_readinto, readinto_m);
59+
readinto_m[2] = MP_STATE_VM(dupterm_arr_obj);
60+
mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
61+
if (res == mp_const_none) {
62+
nlr_pop();
63+
} else if (res == MP_OBJ_NEW_SMALL_INT(0)) {
64+
mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
65+
nlr_pop();
66+
} else {
67+
mp_buffer_info_t bufinfo;
68+
mp_get_buffer_raise(MP_STATE_VM(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
69+
nlr_pop();
70+
if (*(byte*)bufinfo.buf == mp_interrupt_char) {
71+
// Signal keyboard interrupt to be raised as soon as the VM resumes
72+
mp_keyboard_interrupt();
73+
return -2;
74+
}
75+
return *(byte*)bufinfo.buf;
76+
}
77+
} else {
78+
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
79+
}
80+
}
81+
82+
// No chars available
83+
return -1;
84+
}
85+
4786
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
48-
if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
87+
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
88+
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
89+
continue;
90+
}
4991
nlr_buf_t nlr;
5092
if (nlr_push(&nlr) == 0) {
5193
mp_obj_t write_m[3];
52-
mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m);
94+
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_write, write_m);
5395

54-
mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
96+
mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
5597
void *org_items = arr->items;
5698
arr->items = (void*)str;
5799
arr->len = len;
58-
write_m[2] = MP_STATE_PORT(dupterm_arr_obj);
100+
write_m[2] = MP_STATE_VM(dupterm_arr_obj);
59101
mp_call_method_n_kw(1, 0, write_m);
60-
arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
102+
arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
61103
arr->items = org_items;
62104
arr->len = 1;
63105
nlr_pop();
64106
} else {
65-
mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
107+
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
66108
}
67109
}
68110
}
69111

70112
STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
71-
if (n_args == 0) {
72-
if (MP_STATE_PORT(term_obj) == MP_OBJ_NULL) {
73-
return mp_const_none;
74-
} else {
75-
return MP_STATE_PORT(term_obj);
76-
}
113+
mp_int_t idx = 0;
114+
if (n_args == 2) {
115+
idx = mp_obj_get_int(args[1]);
116+
}
117+
118+
if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
119+
mp_raise_ValueError("invalid dupterm index");
120+
}
121+
122+
mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
123+
if (previous_obj == MP_OBJ_NULL) {
124+
previous_obj = mp_const_none;
125+
}
126+
if (args[0] == mp_const_none) {
127+
MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
77128
} else {
78-
if (args[0] == mp_const_none) {
79-
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
80-
} else {
81-
MP_STATE_PORT(term_obj) = args[0];
82-
if (MP_STATE_PORT(dupterm_arr_obj) == MP_OBJ_NULL) {
83-
MP_STATE_PORT(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
84-
}
129+
MP_STATE_VM(dupterm_objs[idx]) = args[0];
130+
if (MP_STATE_VM(dupterm_arr_obj) == MP_OBJ_NULL) {
131+
MP_STATE_VM(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
85132
}
86-
return mp_const_none;
87133
}
134+
135+
return previous_obj;
88136
}
89-
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 0, 1, mp_uos_dupterm);
137+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm);
90138

91139
#endif

ports/esp8266/esp_mphal.c

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -155,49 +155,14 @@ void mp_hal_signal_input(void) {
155155
#endif
156156
}
157157

158-
static int call_dupterm_read(void) {
159-
if (MP_STATE_PORT(term_obj) == NULL) {
160-
return -1;
161-
}
162-
163-
nlr_buf_t nlr;
164-
if (nlr_push(&nlr) == 0) {
165-
mp_obj_t readinto_m[3];
166-
mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_readinto, readinto_m);
167-
readinto_m[2] = MP_STATE_PORT(dupterm_arr_obj);
168-
mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
169-
if (res == mp_const_none) {
170-
nlr_pop();
171-
return -2;
172-
}
173-
if (res == MP_OBJ_NEW_SMALL_INT(0)) {
174-
mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
175-
nlr_pop();
176-
return -1;
177-
}
178-
mp_buffer_info_t bufinfo;
179-
mp_get_buffer_raise(MP_STATE_PORT(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
180-
nlr_pop();
181-
if (*(byte*)bufinfo.buf == mp_interrupt_char) {
182-
mp_keyboard_interrupt();
183-
return -2;
184-
}
185-
return *(byte*)bufinfo.buf;
186-
} else {
187-
mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
188-
}
189-
190-
return -1;
191-
}
192-
193158
STATIC void dupterm_task_handler(os_event_t *evt) {
194159
static byte lock;
195160
if (lock) {
196161
return;
197162
}
198163
lock = 1;
199164
while (1) {
200-
int c = call_dupterm_read();
165+
int c = mp_uos_dupterm_rx_chr();
201166
if (c < 0) {
202167
break;
203168
}

ports/esp8266/main.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ STATIC void mp_reset(void) {
5151
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
5252
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
5353
mp_obj_list_init(mp_sys_argv, 0);
54-
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
55-
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
5654
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
5755
extern void esp_native_code_init(void);
5856
esp_native_code_init();

ports/esp8266/modules/webrepl.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ def setup_conn(port, accept_handler):
3131
def accept_conn(listen_sock):
3232
global client_s
3333
cl, remote_addr = listen_sock.accept()
34-
if uos.dupterm():
34+
prev = uos.dupterm(None)
35+
uos.dupterm(prev)
36+
if prev:
3537
print("\nConcurrent WebREPL connection from", remote_addr, "rejected")
3638
cl.close()
3739
return

ports/unix/unix_mphal.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@ void mp_hal_stdio_mode_orig(void) {
108108
#endif
109109

110110
#if MICROPY_PY_OS_DUPTERM
111-
static int call_dupterm_read(void) {
111+
static int call_dupterm_read(size_t idx) {
112112
nlr_buf_t nlr;
113113
if (nlr_push(&nlr) == 0) {
114114
mp_obj_t read_m[3];
115-
mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
115+
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_read, read_m);
116116
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
117117
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
118118
if (res == mp_const_none) {
@@ -122,18 +122,18 @@ static int call_dupterm_read(void) {
122122
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
123123
if (bufinfo.len == 0) {
124124
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
125-
MP_STATE_PORT(term_obj) = NULL;
125+
MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
126126
return -1;
127127
}
128128
nlr_pop();
129129
return *(byte*)bufinfo.buf;
130130
} else {
131131
// Temporarily disable dupterm to avoid infinite recursion
132-
mp_obj_t save_term = MP_STATE_PORT(term_obj);
133-
MP_STATE_PORT(term_obj) = NULL;
132+
mp_obj_t save_term = MP_STATE_VM(dupterm_objs[idx]);
133+
MP_STATE_VM(dupterm_objs[idx]) = NULL;
134134
mp_printf(&mp_plat_print, "dupterm: ");
135135
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
136-
MP_STATE_PORT(term_obj) = save_term;
136+
MP_STATE_VM(dupterm_objs[idx]) = save_term;
137137
}
138138

139139
return -1;
@@ -143,10 +143,11 @@ static int call_dupterm_read(void) {
143143
int mp_hal_stdin_rx_chr(void) {
144144
unsigned char c;
145145
#if MICROPY_PY_OS_DUPTERM
146-
if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
146+
// TODO only support dupterm one slot at the moment
147+
if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) {
147148
int c;
148149
do {
149-
c = call_dupterm_read();
150+
c = call_dupterm_read(0);
150151
} while (c == -2);
151152
if (c == -1) {
152153
goto main_term;

py/mpstate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ typedef struct _mp_state_vm_t {
168168
// root pointers for extmod
169169

170170
#if MICROPY_PY_OS_DUPTERM
171-
mp_obj_t term_obj;
171+
mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM];
172172
mp_obj_t dupterm_arr_obj;
173173
#endif
174174

py/runtime.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ void mp_init(void) {
102102
MP_STATE_VM(mp_module_builtins_override_dict) = NULL;
103103
#endif
104104

105+
#if MICROPY_PY_OS_DUPTERM
106+
for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) {
107+
MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL;
108+
}
109+
MP_STATE_VM(dupterm_arr_obj) = MP_OBJ_NULL;
110+
#endif
111+
105112
#if MICROPY_FSUSERMOUNT
106113
// zero out the pointers to the user-mounted devices
107114
memset(MP_STATE_VM(fs_user_mount), 0, sizeof(MP_STATE_VM(fs_user_mount)));

0 commit comments

Comments
 (0)