1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 Damien P. George
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 <stdio.h>
28 #include <stdint.h>
29 #include <string.h>
30 
31 #include "py/runtime.h"
32 #include "py/stream.h"
33 #include "py/mperrno.h"
34 #include "modmachine.h"
35 
36 #include "ulog/ulog.h"
37 #include "aos_hal_uart.h"
38 
39 #define LOG_TAG "machine_uart"
40 
41 enum {
42   UART_NUM_0,
43   UART_NUM_1,
44   UART_NUM_2,
45   UART_NUM_3,
46   UART_NUM_MAX
47 };
48 
49 enum {
50     e_DATA_WIDTH_5BIT = 5,
51     e_DATA_WIDTH_6BIT,
52     e_DATA_WIDTH_7BIT,
53     e_DATA_WIDTH_8BIT,
54     e_DATA_WIDTH_9BIT
55 };
56 
57 enum {
58     e_STOP_BITS_1 = 1,
59     e_STOP_BITS_2
60 };
61 
62 typedef struct _machine_uart_obj_t {
63     mp_obj_base_t base;
64     uint8_t uart_num;
65     bool uart_inited;
66     uart_dev_t dev;
67     uint16_t timeout;       // timeout waiting for first char (in ms)
68     uint16_t timeout_char;  // timeout waiting between chars (in ms)
69 } machine_uart_obj_t;
70 
71 STATIC const char *_parity_name[]   = {"None", "Odd", "Even"};
72 STATIC const char *_flowctrl_name[] = {"Disable", "CTS", "RTS", "CTS_RTS"};
73 STATIC const char *_mode_name[]     = {"Tx", "Rx", "Tx_Rx"};
74 STATIC const uint8_t _bits[]        = {e_DATA_WIDTH_5BIT, e_DATA_WIDTH_6BIT, e_DATA_WIDTH_7BIT, e_DATA_WIDTH_8BIT, e_DATA_WIDTH_9BIT};
75 
76 const mp_obj_type_t machine_uart_type;
77 
78 /******************************************************************************/
79 // MicroPython bindings for UART
80 
machine_uart_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)81 STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
82     machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
83     mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, flow_ctrl=%s, mode=%s, timeout=%u, timeout_char=%u)",
84         self->uart_num, self->dev.config.baud_rate, _bits[self->dev.config.data_width],
85         _parity_name[self->dev.config.parity], self->dev.config.stop_bits,
86         _flowctrl_name[self->dev.config.flow_control], _mode_name[self->dev.config.mode],
87         self->timeout, self->timeout_char);
88 }
89 
machine_uart_init_helper(machine_uart_obj_t * self,size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)90 STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
91     enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char, ARG_invert };
92     static const mp_arg_t allowed_args[] = {
93         { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 115200} },
94         { MP_QSTR_bits, MP_ARG_INT, {.u_int = e_DATA_WIDTH_8BIT} },
95         { MP_QSTR_parity, MP_ARG_OBJ, {.u_int = NO_PARITY} },
96         { MP_QSTR_stop, MP_ARG_INT, {.u_int = e_STOP_BITS_1} },
97         { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
98         { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
99         { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
100         { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
101         { MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
102         { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
103         { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
104         { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
105         { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
106     };
107     mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
108     mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
109 
110     uart_dev_t *dev = &self->dev;
111 
112     // wait for all data to be transmitted before changing settings
113     // TODO
114 
115     // set baudrate
116     int32_t baudrate = args[ARG_baudrate].u_int;
117     if (baudrate <= 0) {
118         mp_raise_ValueError(MP_ERROR_TEXT("baud rate error"));
119     } else {
120         dev->config.baud_rate = baudrate;
121     }
122 
123     // set flow_control
124     uint32_t rts = args[ARG_rts].u_int;
125     uint32_t cts = args[ARG_cts].u_int;
126     if(rts && cts) {
127       dev->config.flow_control = FLOW_CONTROL_CTS_RTS;
128     } else if(cts) {
129       dev->config.flow_control = FLOW_CONTROL_CTS;
130     } else if(rts) {
131       dev->config.flow_control = FLOW_CONTROL_RTS;
132     } else {
133       dev->config.flow_control = FLOW_CONTROL_DISABLED;
134     }
135 
136     // set data bits
137     uint8_t data_width = args[ARG_bits].u_int;
138     switch(data_width) {
139         case e_DATA_WIDTH_5BIT:
140             dev->config.data_width = DATA_WIDTH_5BIT;
141             break;
142 
143         case e_DATA_WIDTH_6BIT:
144             dev->config.data_width = DATA_WIDTH_6BIT;
145             break;
146 
147         case e_DATA_WIDTH_7BIT:
148             dev->config.data_width = DATA_WIDTH_7BIT;
149             break;
150 
151         case e_DATA_WIDTH_8BIT:
152             dev->config.data_width = DATA_WIDTH_8BIT;
153             break;
154 
155         case e_DATA_WIDTH_9BIT:
156             dev->config.data_width = DATA_WIDTH_9BIT;
157             break;
158 
159         default:
160             mp_raise_ValueError(MP_ERROR_TEXT("invalid data bits"));
161     }
162 
163     // set parity
164     if (args[ARG_parity].u_obj != MP_OBJ_NULL) {
165         if (args[ARG_parity].u_obj == mp_const_none) {
166             dev->config.parity = NO_PARITY;
167         } else {
168             mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj);
169             if (parity & 1) {
170                 dev->config.parity = ODD_PARITY;
171             } else {
172                 dev->config.parity = EVEN_PARITY;
173             }
174         }
175     }
176 
177     // set stop bits
178     uint8_t stop_bits = args[ARG_stop].u_int;
179     switch(stop_bits) {
180         case e_STOP_BITS_1:
181           dev->config.stop_bits = STOP_BITS_1;
182           break;
183 
184         case e_STOP_BITS_2:
185           dev->config.stop_bits = STOP_BITS_2;
186           break;
187 
188         default:
189           mp_raise_ValueError(MP_ERROR_TEXT("invalid stop bits"));
190     }
191 
192     // set timeout
193     self->timeout = args[ARG_timeout].u_int;
194 
195     // set timeout_char
196     // make sure it is at least as long as a whole character (13 bits to be safe)
197     self->timeout_char = args[ARG_timeout_char].u_int;
198     uint32_t min_timeout_char = 13000 / baudrate + 1;
199     if (self->timeout_char < min_timeout_char) {
200         self->timeout_char = min_timeout_char;
201     }
202 }
203 
machine_uart_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)204 STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
205     mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
206 
207     // get uart id
208     mp_int_t uart_num = mp_obj_get_int(args[0]);
209     if (uart_num < 0 || uart_num >= UART_NUM_MAX) {
210         mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) does not exist"), uart_num);
211     }
212 
213     // Attempts to use UART0 from Python has resulted in all sorts of fun errors.
214     // FIXME: UART0 is disabled for now.
215     if (uart_num == UART_NUM_0) {
216         mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) is disabled (dedicated to REPL)"), uart_num);
217     }
218 
219     // create instance
220     machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t);
221     self->base.type = &machine_uart_type;
222     self->dev.port = uart_num;
223     self->dev.config.baud_rate = 115200;
224     self->dev.config.data_width = DATA_WIDTH_8BIT;
225     self->dev.config.parity = NO_PARITY;
226     self->dev.config.stop_bits = STOP_BITS_1;
227     self->dev.config.flow_control = FLOW_CONTROL_DISABLED;
228     self->dev.config.mode = MODE_TX_RX;
229     self->dev.priv = NULL;
230     self->timeout = 0;
231     self->timeout_char = 0;
232     self->uart_inited = false;
233 
234     mp_map_t kw_args;
235     mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
236     machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
237 
238     return MP_OBJ_FROM_PTR(self);
239 }
240 
machine_uart_init(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)241 STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
242     machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
243     return mp_const_none;
244 }
245 MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
246 
machine_uart_deinit(mp_obj_t self_in)247 STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
248     machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
249     if(self->uart_inited == true) {
250         aos_hal_uart_finalize(&self->dev);
251     }
252     return mp_const_none;
253 }
254 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit);
255 
machine_uart_any(mp_obj_t self_in)256 STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
257     machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
258     mp_raise_NotImplementedError(MP_ERROR_TEXT("attenuation not supported"));
259     return MP_OBJ_NEW_SMALL_INT(0);
260 }
261 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
262 
machine_uart_sendbreak(mp_obj_t self_in)263 STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
264     machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
265     mp_raise_NotImplementedError(MP_ERROR_TEXT("attenuation not supported"));
266     return mp_const_none;
267 }
268 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
269 
270 STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
271     { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
272     { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
273     { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
274     { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
275     { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
276     { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
277     { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
278     { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
279 };
280 
281 STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
282 
uart_init(machine_uart_obj_t * self)283 STATIC mp_int_t uart_init(machine_uart_obj_t *self) {
284     // init uart if not
285     if(self->uart_inited == false) {
286         int status = aos_hal_uart_init(&self->dev);
287         if(status != 0) {
288             LOGE(LOG_TAG, "Failed to init uart, status = %d\n", status);
289             return -status;
290         } else {
291             self->uart_inited = true;
292         }
293     }
294 
295     return 0;
296 }
297 
machine_uart_read(mp_obj_t self_in,void * buf_in,mp_uint_t size,int * errcode)298 STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
299     machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
300 
301     // make sure we want at least 1 char
302     if (size == 0) {
303         return 0;
304     }
305 
306     int status = uart_init(self);
307     if(status != 0) {
308         return status;
309     }
310 
311     mp_uint_t bytes_read = 0;
312     MP_THREAD_GIL_EXIT();
313     status = aos_hal_uart_recv_II(&self->dev, buf_in, size, &bytes_read, self->timeout);
314     MP_THREAD_GIL_ENTER();
315 
316     if (status != 0) {
317         LOGW(LOG_TAG, "uart read failed with status=%d", status);
318         *errcode = MP_EAGAIN;
319         return MP_STREAM_ERROR;
320     }
321 
322     return bytes_read;
323 }
324 
machine_uart_write(mp_obj_t self_in,const void * buf_in,mp_uint_t size,int * errcode)325 STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
326     machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
327 
328     // init uart if not
329     int status = uart_init(self);
330     if(status != 0) {
331         return status;
332     }
333 
334     MP_THREAD_GIL_EXIT();
335     status = aos_hal_uart_send(&self->dev, buf_in, size, self->timeout);
336     MP_THREAD_GIL_ENTER();
337 
338     if (status != 0) {
339         *errcode = MP_EAGAIN;
340         return MP_STREAM_ERROR;
341     }
342 
343     // return number of bytes written
344     return size;
345 }
346 
machine_uart_ioctl(mp_obj_t self_in,mp_uint_t request,uintptr_t arg,int * errcode)347 STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
348     machine_uart_obj_t *self = self_in;
349     mp_uint_t ret;
350     if (request == MP_STREAM_POLL) {
351         mp_uint_t flags = arg;
352         ret = 0;
353         size_t rxbufsize = 0;
354         // uart_get_buffered_data_len(self->uart_num, &rxbufsize);
355         if ((flags & MP_STREAM_POLL_RD) && rxbufsize > 0) {
356             ret |= MP_STREAM_POLL_RD;
357         }
358         if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num)
359             ret |= MP_STREAM_POLL_WR;
360         }
361     } else {
362         *errcode = MP_EINVAL;
363         ret = MP_STREAM_ERROR;
364     }
365     return ret;
366 }
367 
368 STATIC const mp_stream_p_t uart_stream_p = {
369     .read = machine_uart_read,
370     .write = machine_uart_write,
371     .ioctl = machine_uart_ioctl,
372     .is_text = false,
373 };
374 
375 const mp_obj_type_t machine_uart_type = {
376     { &mp_type_type },
377     .name = MP_QSTR_UART,
378     .print = machine_uart_print,
379     .make_new = machine_uart_make_new,
380     .getiter = mp_identity_getiter,
381     .iternext = mp_stream_unbuffered_iter,
382     .protocol = &uart_stream_p,
383     .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict,
384 };
385