Skip to content

Commit 6ace744

Browse files
committed
esp8266: Introduce multiterminal module for managing a secondary
serial connection such as WebREPL. Fixes adafruit#181.
1 parent 5d509ec commit 6ace744

File tree

10 files changed

+300
-12
lines changed

10 files changed

+300
-12
lines changed

esp8266/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ SRC_COMMON_HAL = \
116116
busio/__init__.c \
117117
busio/SPI.c \
118118
busio/UART.c \
119+
multiterminal/__init__.c \
119120
neopixel_write/__init__.c \
120121
os/__init__.c \
121122
storage/__init__.c \
@@ -139,6 +140,7 @@ SRC_SHARED_MODULE = \
139140
bitbangio/SPI.c \
140141
busio/I2C.c \
141142
busio/OneWire.c \
143+
multiterminal/__init__.c \
142144
os/__init__.c \
143145
random/__init__.c \
144146
storage/__init__.c \
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Paul Sokolovsky
7+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include "esp_mphal.h"
29+
30+
#include "shared-bindings/multiterminal/__init__.h"
31+
#include "shared-module/multiterminal/__init__.h"
32+
33+
void common_hal_multiterminal_schedule_secondary_terminal_read(mp_obj_t socket) {
34+
(void) socket;
35+
mp_hal_signal_dupterm_input();
36+
}
37+
38+
mp_obj_t common_hal_multiterminal_get_secondary_terminal() {
39+
return shared_module_multiterminal_get_secondary_terminal();
40+
}
41+
42+
void common_hal_multiterminal_set_secondary_terminal(mp_obj_t secondary_terminal) {
43+
shared_module_multiterminal_set_secondary_terminal(secondary_terminal);
44+
}
45+
46+
void common_hal_multiterminal_clear_secondary_terminal() {
47+
shared_module_multiterminal_clear_secondary_terminal();
48+
}

esp8266/modules/webrepl.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This module should be imported from REPL, not run from command line.
22
import socket
3-
import uos
3+
import multiterminal
44
import network
55
import websocket
66
import websocket_helper
@@ -31,7 +31,7 @@ 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+
if multiterminal.get_secondary_terminal():
3535
print("\nConcurrent WebREPL connection from", remote_addr, "rejected")
3636
cl.close()
3737
return
@@ -42,13 +42,13 @@ def accept_conn(listen_sock):
4242
ws = _webrepl._webrepl(ws)
4343
cl.setblocking(False)
4444
# notify REPL on socket incoming data
45-
cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify)
46-
uos.dupterm(ws)
45+
cl.setsockopt(socket.SOL_SOCKET, 20, multiterminal.schedule_secondary_terminal_read)
46+
multiterminal.set_secondary_terminal(ws)
4747

4848

4949
def stop():
5050
global listen_s, client_s
51-
uos.dupterm(None)
51+
multiterminal.clear_secondary_terminal()
5252
if client_s:
5353
client_s.close()
5454
if listen_s:

esp8266/mpconfigport.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ extern const struct _mp_obj_module_t pulseio_module;
169169
extern const struct _mp_obj_module_t busio_module;
170170
extern const struct _mp_obj_module_t bitbangio_module;
171171
extern const struct _mp_obj_module_t time_module;
172+
extern const struct _mp_obj_module_t multiterminal_module;
172173

173174
#define MICROPY_PORT_BUILTIN_MODULES \
174175
{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \
@@ -188,6 +189,7 @@ extern const struct _mp_obj_module_t time_module;
188189
{ MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \
189190
{ MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \
190191
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
192+
{ MP_OBJ_NEW_QSTR(MP_QSTR_multiterminal), (mp_obj_t)&multiterminal_module }, \
191193

192194
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
193195
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \

py/ringbuf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#ifndef __MICROPY_INCLUDED_PY_RINGBUF_H__
2727
#define __MICROPY_INCLUDED_PY_RINGBUF_H__
2828

29+
#include <stdint.h>
30+
2931
typedef struct _ringbuf_t {
3032
uint8_t *buf;
3133
uint16_t size;

shared-bindings/index.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ limited. For example, a microcontroller without analog features will not have
1212
Support Matrix
1313
---------------
1414

15-
=============== ========== ========= =========== ======= ======= =========== ================= ================ ======= ========= ======== ========= ======== ========= ======= =========
16-
Port `analogio` `audioio` `bitbangio` `board` `busio` `digitalio` `microcontroller` `neopixel_write` `os` `pulseio` `random` `storage` `time` `touchio` `uheap` `usb_hid`
17-
=============== ========== ========= =========== ======= ======= =========== ================= ================ ======= ========= ======== ========= ======== ========= ======= =========
18-
SAMD21 **Yes** No No **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** **Yes** **Yes** Debug **Yes**
19-
SAMD21 Express **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** Debug **Yes**
20-
ESP8266 **Yes** No **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** **Yes** No Debug No
21-
=============== ========== ========= =========== ======= ======= =========== ================= ================ ======= ========= ======== ========= ======== ========= ======= =========
15+
=============== ========== ========= =========== ======= ======= =========== ================= =============== ================ ======= ========= ======== ========= ======== ========= ======= =========
16+
Port `analogio` `audioio` `bitbangio` `board` `busio` `digitalio` `microcontroller` `multiterminal` `neopixel_write` `os` `pulseio` `random` `storage` `time` `touchio` `uheap` `usb_hid`
17+
=============== ========== ========= =========== ======= ======= =========== ================= =============== ================ ======= ========= ======== ========= ======== ========= ======= =========
18+
SAMD21 **Yes** No No **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** No **Yes** **Yes** **Yes** **Yes** Debug **Yes**
19+
SAMD21 Express **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** Debug **Yes**
20+
ESP8266 **Yes** No **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** **Yes** No **Yes** **Yes** **Yes** No Debug No
21+
=============== ========== ========= =========== ======= ======= =========== ================= =============== ================ ======= ========= ======== ========= ======== ========= ======= =========
2222

2323
Modules
2424
---------
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/obj.h"
28+
#include "py/mphal.h"
29+
#include "py/runtime.h"
30+
31+
#include "shared-bindings/multiterminal/__init__.h"
32+
33+
//| :mod:`multiterminal` --- Manage additional terminal sources
34+
//| ===========================================================
35+
//|
36+
//| .. module:: multiterminal
37+
//| :synopsis: Manage additional terminal sources
38+
//| :platform: ESP8266
39+
//|
40+
//| The `multiterminal` module allows you to configure an additional serial
41+
//| terminal source. Incoming characters are accepted from both the internal
42+
//| serial connection and the optional secondary connection.
43+
//|
44+
45+
//| .. function:: get_secondary_terminal()
46+
//|
47+
//| Returns the current secondary terminal.
48+
//|
49+
STATIC mp_obj_t multiterminal_obj_get_secondary_terminal() {
50+
return common_hal_multiterminal_get_secondary_terminal();
51+
}
52+
MP_DEFINE_CONST_FUN_OBJ_0(multiterminal_get_secondary_terminal_obj, multiterminal_obj_get_secondary_terminal);
53+
54+
//| .. function:: set_secondary_terminal(stream)
55+
//|
56+
//| Read additional input from the given stream and write out back to it.
57+
//| This doesn't replace the core stream (usually UART or native USB) but is
58+
//| mixed in instead.
59+
//|
60+
//| :param stream stream: secondary stream
61+
//|
62+
STATIC mp_obj_t multiterminal_obj_set_secondary_terminal(mp_obj_t secondary_terminal) {
63+
mp_obj_t write_m[3];
64+
mp_load_method_maybe(secondary_terminal, MP_QSTR_write, write_m);
65+
mp_obj_t readinto_m[3];
66+
mp_load_method_maybe(secondary_terminal, MP_QSTR_readinto, readinto_m);
67+
if (write_m[0] == MP_OBJ_NULL || readinto_m[0] == MP_OBJ_NULL) {
68+
mp_raise_ValueError("Stream missing readinto() or write() method.");
69+
return mp_const_none;
70+
}
71+
common_hal_multiterminal_set_secondary_terminal(secondary_terminal);
72+
return mp_const_none;
73+
}
74+
MP_DEFINE_CONST_FUN_OBJ_1(multiterminal_set_secondary_terminal_obj, multiterminal_obj_set_secondary_terminal);
75+
76+
//| .. function:: clear_secondary_terminal()
77+
//|
78+
//| Clears the secondary terminal.
79+
//|
80+
STATIC mp_obj_t multiterminal_obj_clear_secondary_terminal() {
81+
common_hal_multiterminal_clear_secondary_terminal();
82+
return mp_const_none;
83+
}
84+
MP_DEFINE_CONST_FUN_OBJ_0(multiterminal_clear_secondary_terminal_obj, multiterminal_obj_clear_secondary_terminal);
85+
86+
//| .. function:: schedule_secondary_terminal_read(socket)
87+
//|
88+
//| In cases where the underlying OS is doing task scheduling, this notifies
89+
//| the OS when more data is available on the socket to read. This is useful
90+
//| as a callback for lwip sockets.
91+
//|
92+
// TODO(tannewt): This is a funny API. Replace it with a direct call into the OS
93+
// by the lwip object.
94+
STATIC mp_obj_t multiterminal_obj_schedule_secondary_terminal_read(mp_obj_t socket) {
95+
common_hal_multiterminal_schedule_secondary_terminal_read(socket);
96+
return mp_const_none;
97+
}
98+
MP_DEFINE_CONST_FUN_OBJ_1(multiterminal_schedule_secondary_terminal_read_obj, multiterminal_obj_schedule_secondary_terminal_read);
99+
100+
// TODO(tannewt): Expose the internal serial connection as `primary_terminal`
101+
102+
STATIC const mp_rom_map_elem_t multiterminal_module_globals_table[] = {
103+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_multiterminal) },
104+
{ MP_ROM_QSTR(MP_QSTR_get_secondary_terminal), MP_ROM_PTR(&multiterminal_get_secondary_terminal_obj) },
105+
{ MP_ROM_QSTR(MP_QSTR_set_secondary_terminal), MP_ROM_PTR(&multiterminal_set_secondary_terminal_obj) },
106+
{ MP_ROM_QSTR(MP_QSTR_clear_secondary_terminal), MP_ROM_PTR(&multiterminal_clear_secondary_terminal_obj) },
107+
{ MP_ROM_QSTR(MP_QSTR_schedule_secondary_terminal_read), MP_ROM_PTR(&multiterminal_schedule_secondary_terminal_read_obj) },
108+
};
109+
110+
STATIC MP_DEFINE_CONST_DICT(multiterminal_module_globals, multiterminal_module_globals_table);
111+
112+
const mp_obj_module_t multiterminal_module = {
113+
.base = { &mp_type_module },
114+
.globals = (mp_obj_dict_t*)&multiterminal_module_globals,
115+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef SHARED_BINDINGS_MULTITERMINAL___INIT___H
28+
#define SHARED_BINDINGS_MULTITERMINAL___INIT___H
29+
30+
void common_hal_multiterminal_schedule_secondary_terminal_read(mp_obj_t socket);
31+
mp_obj_t common_hal_multiterminal_get_secondary_terminal();
32+
void common_hal_multiterminal_set_secondary_terminal(mp_obj_t secondary_terminal);
33+
void common_hal_multiterminal_clear_secondary_terminal();
34+
35+
#endif // SHARED_BINDINGS_MULTITERMINAL___INIT___H
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Paul Sokolovsky
7+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include "py/mpstate.h"
29+
30+
#include "shared-bindings/multiterminal/__init__.h"
31+
32+
mp_obj_t shared_module_multiterminal_get_secondary_terminal() {
33+
if (MP_STATE_PORT(term_obj) == MP_OBJ_NULL) {
34+
return mp_const_none;
35+
} else {
36+
return MP_STATE_PORT(term_obj);
37+
}
38+
}
39+
40+
void shared_module_multiterminal_set_secondary_terminal(mp_obj_t secondary_terminal) {
41+
MP_STATE_PORT(term_obj) = secondary_terminal;
42+
if (MP_STATE_PORT(dupterm_arr_obj) == MP_OBJ_NULL) {
43+
MP_STATE_PORT(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
44+
}
45+
}
46+
47+
void shared_module_multiterminal_clear_secondary_terminal() {
48+
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
49+
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
50+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef SHARED_MODULE_MULTITERMINAL___INIT___H
28+
#define SHARED_MODULE_MULTITERMINAL___INIT___H
29+
30+
mp_obj_t shared_module_multiterminal_get_secondary_terminal();
31+
void shared_module_multiterminal_set_secondary_terminal(mp_obj_t secondary_terminal);
32+
void shared_module_multiterminal_clear_secondary_terminal();
33+
34+
#endif // SHARED_MODULE_MULTITERMINAL___INIT___H

0 commit comments

Comments
 (0)