summaryrefslogtreecommitdiff
path: root/shared-bindings
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2021-03-02 15:17:12 -0500
committerDan Halbert <halbert@halwitz.org>2021-03-02 15:17:12 -0500
commitf31b4723093637ebd2566684dc3d1f61944d9e61 (patch)
treeac99e66ee83bfe2be37f2f92288eef555af6fba5 /shared-bindings
parent9939c59caa4e13011e9d1f63079cb4a7942cfcc4 (diff)
parente4f0e47d9f0bb620f56b93c649197b16105ab5b2 (diff)
Merge remote-tracking branch 'adafruit/main' into rp2040-i2c-short-writes
Diffstat (limited to 'shared-bindings')
-rw-r--r--shared-bindings/_bleio/CharacteristicBuffer.c4
-rw-r--r--shared-bindings/bitmaptools/__init__.c256
-rw-r--r--shared-bindings/bitmaptools/__init__.h42
-rw-r--r--shared-bindings/bitops/__init__.c101
-rw-r--r--shared-bindings/bitops/__init__.h32
-rw-r--r--shared-bindings/busio/SPI.c2
-rw-r--r--shared-bindings/busio/UART.c15
-rw-r--r--shared-bindings/displayio/Group.c25
-rw-r--r--shared-bindings/displayio/Group.h2
-rwxr-xr-xshared-bindings/supervisor/Runtime.c47
-rwxr-xr-xshared-bindings/supervisor/Runtime.h8
-rw-r--r--shared-bindings/usb_cdc/Serial.c293
-rw-r--r--shared-bindings/usb_cdc/Serial.h53
-rw-r--r--shared-bindings/usb_cdc/__init__.c59
-rw-r--r--shared-bindings/usb_cdc/__init__.h32
15 files changed, 919 insertions, 52 deletions
diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c
index 4d6c836c1..333b275ff 100644
--- a/shared-bindings/_bleio/CharacteristicBuffer.c
+++ b/shared-bindings/_bleio/CharacteristicBuffer.c
@@ -231,8 +231,8 @@ STATIC const mp_stream_p_t characteristic_buffer_stream_p = {
.write = bleio_characteristic_buffer_write,
.ioctl = bleio_characteristic_buffer_ioctl,
.is_text = false,
- // Match PySerial when possible, such as disallowing optional length argument for .readinto()
- .pyserial_compatibility = true,
+ // Disallow readinto() size parameter.
+ .pyserial_readinto_compatibility = true,
};
diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c
new file mode 100644
index 000000000..cf48d12dc
--- /dev/null
+++ b/shared-bindings/bitmaptools/__init__.c
@@ -0,0 +1,256 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Kevin Matocha
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/Bitmap.h"
+#include "shared-bindings/bitmaptools/__init__.h"
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+//| """Collection of bitmap manipulation tools"""
+//|
+
+STATIC int16_t validate_point(mp_obj_t point, int16_t default_value) {
+ // Checks if point is None and returns default_value, otherwise decodes integer value
+ if ( point == mp_const_none ) {
+ return default_value;
+ }
+ return mp_obj_get_int(point);
+}
+
+STATIC void extract_tuple(mp_obj_t xy_tuple, int16_t *x, int16_t *y, int16_t x_default, int16_t y_default) {
+ // Helper function for rotozoom
+ // Extract x,y values from a tuple or default if None
+ if ( xy_tuple == mp_const_none ) {
+ *x = x_default;
+ *y = y_default;
+ } else if ( !MP_OBJ_IS_OBJ(xy_tuple) ) {
+ mp_raise_ValueError(translate("clip point must be (x,y) tuple"));
+ } else {
+ mp_obj_t* items;
+ mp_obj_get_array_fixed_n(xy_tuple, 2, &items);
+ *x = mp_obj_get_int(items[0]);
+ *y = mp_obj_get_int(items[1]);
+ }
+}
+
+STATIC void validate_clip_region(displayio_bitmap_t *bitmap, mp_obj_t clip0_tuple, int16_t *clip0_x, int16_t *clip0_y,
+ mp_obj_t clip1_tuple, int16_t *clip1_x, int16_t *clip1_y) {
+ // Helper function for rotozoom
+ // 1. Extract the clip x,y points from the two clip tuples
+ // 2. Rearrange values such that clip0_ < clip1_
+ // 3. Constrain the clip points to within the bitmap
+
+ extract_tuple(clip0_tuple, clip0_x, clip0_y, 0, 0);
+ extract_tuple(clip1_tuple, clip1_x, clip1_y, bitmap->width, bitmap->height);
+
+ // Ensure the value for clip0 is less than clip1 (for both x and y)
+ if ( *clip0_x > *clip1_x ) {
+ int16_t temp_value = *clip0_x; // swap values
+ *clip0_x = *clip1_x;
+ *clip1_x = temp_value;
+ }
+ if ( *clip0_y > *clip1_y ) {
+ int16_t temp_value = *clip0_y; // swap values
+ *clip0_y = *clip1_y;
+ *clip1_y = temp_value;
+ }
+
+ // Constrain the clip window to within the bitmap boundaries
+ if (*clip0_x < 0) {
+ *clip0_x = 0;
+ }
+ if (*clip0_y < 0) {
+ *clip0_y = 0;
+ }
+ if (*clip0_x > bitmap->width) {
+ *clip0_x = bitmap->width;
+ }
+ if (*clip0_y > bitmap->height) {
+ *clip0_y = bitmap->height;
+ }
+ if (*clip1_x < 0) {
+ *clip1_x = 0;
+ }
+ if (*clip1_y < 0) {
+ *clip1_y = 0;
+ }
+ if (*clip1_x > bitmap->width) {
+ *clip1_x = bitmap->width;
+ }
+ if (*clip1_y > bitmap->height) {
+ *clip1_y = bitmap->height;
+ }
+
+}
+
+//|
+//| def rotozoom(
+//| dest_bitmap: displayio.Bitmap, source_bitmap: displayio.Bitmap,
+//| *,
+//| ox: int, oy: int, dest_clip0: Tuple[int, int], dest_clip1: Tuple[int, int],
+//| px: int, py: int, source_clip0: Tuple[int, int], source_clip1: Tuple[int, int],
+//| angle: float, scale: float, skip_index: int) -> None:
+//| """Inserts the source bitmap region into the destination bitmap with rotation
+//| (angle), scale and clipping (both on source and destination bitmaps).
+//|
+//| :param bitmap dest_bitmap: Destination bitmap that will be copied into
+//| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be copied
+//| :param int ox: Horizontal pixel location in destination bitmap where source bitmap
+//| point (px,py) is placed
+//| :param int oy: Vertical pixel location in destination bitmap where source bitmap
+//| point (px,py) is placed
+//| :param Tuple[int,int] dest_clip0: First corner of rectangular destination clipping
+//| region that constrains region of writing into destination bitmap
+//| :param Tuple[int,int] dest_clip1: Second corner of rectangular destination clipping
+//| region that constrains region of writing into destination bitmap
+//| :param int px: Horizontal pixel location in source bitmap that is placed into the
+//| destination bitmap at (ox,oy)
+//| :param int py: Vertical pixel location in source bitmap that is placed into the
+//| destination bitmap at (ox,oy)
+//| :param Tuple[int,int] source_clip0: First corner of rectangular source clipping
+//| region that constrains region of reading from the source bitmap
+//| :param Tuple[int,int] source_clip1: Second corner of rectangular source clipping
+//| region that constrains region of reading from the source bitmap
+//| :param float angle: Angle of rotation, in radians (positive is clockwise direction)
+//| :param float scale: Scaling factor
+//| :param int skip_index: Bitmap palette index in the source that will not be copied,
+//| set to None to copy all pixels"""
+//| ...
+//|
+STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){
+ enum {ARG_dest_bitmap, ARG_source_bitmap,
+ ARG_ox, ARG_oy, ARG_dest_clip0, ARG_dest_clip1,
+ ARG_px, ARG_py, ARG_source_clip0, ARG_source_clip1,
+ ARG_angle, ARG_scale, ARG_skip_index};
+
+ static const mp_arg_t allowed_args[] = {
+ {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
+ {MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
+
+ {MP_QSTR_ox, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to destination->width / 2
+ {MP_QSTR_oy, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to destination->height / 2
+ {MP_QSTR_dest_clip0, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ {MP_QSTR_dest_clip1, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+
+ {MP_QSTR_px, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->width / 2
+ {MP_QSTR_py, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->height / 2
+ {MP_QSTR_source_clip0, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ {MP_QSTR_source_clip1, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+
+ {MP_QSTR_angle, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to 0.0
+ {MP_QSTR_scale, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to 1.0
+ {MP_QSTR_skip_index, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj=mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap
+
+ displayio_bitmap_t *source = MP_OBJ_TO_PTR(args[ARG_source_bitmap].u_obj); // the source bitmap
+
+ // ensure that the destination bitmap has at least as many `bits_per_value` as the source
+ if (destination->bits_per_value < source->bits_per_value) {
+ mp_raise_ValueError(translate("source palette too large"));
+ }
+
+ // Confirm the destination location target (ox,oy); if None, default to bitmap midpoint
+ int16_t ox, oy;
+ ox = validate_point(args[ARG_ox].u_obj, destination->width / 2);
+ oy = validate_point(args[ARG_oy].u_obj, destination->height / 2);
+
+ // Confirm the source location target (px,py); if None, default to bitmap midpoint
+ int16_t px, py;
+ px = validate_point(args[ARG_px].u_obj, source->width / 2);
+ py = validate_point(args[ARG_py].u_obj, source->height / 2);
+
+ // Validate the clipping regions for the destination bitmap
+ int16_t dest_clip0_x, dest_clip0_y, dest_clip1_x, dest_clip1_y;
+
+ validate_clip_region(destination, args[ARG_dest_clip0].u_obj, &dest_clip0_x, &dest_clip0_y,
+ args[ARG_dest_clip1].u_obj, &dest_clip1_x, &dest_clip1_y);
+
+ // Validate the clipping regions for the source bitmap
+ int16_t source_clip0_x, source_clip0_y, source_clip1_x, source_clip1_y;
+
+ validate_clip_region(source, args[ARG_source_clip0].u_obj, &source_clip0_x, &source_clip0_y,
+ args[ARG_source_clip1].u_obj, &source_clip1_x, &source_clip1_y);
+
+ // Confirm the angle value
+ float angle=0.0;
+ if ( args[ARG_angle].u_obj != mp_const_none ) {
+ angle = mp_obj_get_float(args[ARG_angle].u_obj);
+ }
+
+ // Confirm the scale value
+ float scale=1.0;
+ if ( args[ARG_scale].u_obj != mp_const_none ) {
+ scale = mp_obj_get_float(args[ARG_scale].u_obj);
+ }
+ if (scale < 0) { // ensure scale >= 0
+ scale = 1.0;
+ }
+
+ uint32_t skip_index;
+ bool skip_index_none; // Flag whether input skip_value was None
+ if (args[ARG_skip_index].u_obj == mp_const_none ) {
+ skip_index = 0;
+ skip_index_none = true;
+ } else {
+ skip_index = mp_obj_get_int(args[ARG_skip_index].u_obj);
+ skip_index_none = false;
+ }
+
+ common_hal_bitmaptools_rotozoom(destination, ox, oy,
+ dest_clip0_x, dest_clip0_y,
+ dest_clip1_x, dest_clip1_y,
+ source, px, py,
+ source_clip0_x, source_clip0_y,
+ source_clip1_x, source_clip1_y,
+ angle,
+ scale,
+ skip_index, skip_index_none);
+
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_rotozoom_obj, 0, bitmaptools_obj_rotozoom);
+// requires at least 2 arguments (destination bitmap and source bitmap)
+
+
+STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_rotozoom), MP_ROM_PTR(&bitmaptools_rotozoom_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globals_table);
+
+
+const mp_obj_module_t bitmaptools_module = {
+ .base = {&mp_type_module },
+ .globals = (mp_obj_dict_t*)&bitmaptools_module_globals,
+};
diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h
new file mode 100644
index 000000000..e2bb6938b
--- /dev/null
+++ b/shared-bindings/bitmaptools/__init__.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Kevin Matocha
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
+
+#include "py/obj.h"
+
+void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy,
+ int16_t dest_clip0_x, int16_t dest_clip0_y,
+ int16_t dest_clip1_x, int16_t dest_clip1_y,
+ displayio_bitmap_t *source, int16_t px, int16_t py,
+ int16_t source_clip0_x, int16_t source_clip0_y,
+ int16_t source_clip1_x, int16_t source_clip1_y,
+ float angle,
+ float scale,
+ uint32_t skip_index, bool skip_index_none);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
diff --git a/shared-bindings/bitops/__init__.c b/shared-bindings/bitops/__init__.c
new file mode 100644
index 000000000..3c567b8ed
--- /dev/null
+++ b/shared-bindings/bitops/__init__.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/bitops/__init__.h"
+
+//| """Routines for low-level manipulation of binary data"""
+//|
+//|
+
+//| def bit_transpose(input: ReadableBuffer, output: WriteableBuffer, width:int = 8) -> WriteableBuffer:
+//| """"Transpose" a buffer by assembling each output byte with bits taken from each of ``width`` different input bytes.
+//|
+//| This can be useful to convert a sequence of pixel values into a single
+//| stream of bytes suitable for sending via a parallel conversion method.
+//|
+//| The number of bytes in the input buffer must be a multiple of the width,
+//| and the width can be any value from 2 to 8. If the width is fewer than 8,
+//| then the remaining (less significant) bits of the output are set to zero.
+//|
+//| Let ``stride = len(input)//width``. Then the first byte is made out of the
+//| most significant bits of ``[input[0], input[stride], input[2*stride], ...]``.
+//| The second byte is made out of the second bits, and so on until the 8th output
+//| byte which is made of the first bits of ``input[1], input[1+stride,
+//| input[2*stride], ...]``.
+//|
+//| The required output buffer size is ``len(input) * 8 // width``.
+//|
+//| Returns the output buffer."""
+//| ...
+
+STATIC mp_obj_t bit_transpose(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_input, ARG_output, ARG_width };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_input, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_output, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_width, MP_ARG_INT, { .u_int = 8 } },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ int width = args[ARG_width].u_int;
+ if (width < 2 || width > 8) {
+ mp_raise_ValueError_varg(translate("width must be from 2 to 8 (inclusive), not %d"), width);
+ }
+
+ mp_buffer_info_t input_bufinfo;
+ mp_get_buffer_raise(args[ARG_input].u_obj, &input_bufinfo, MP_BUFFER_READ);
+ int inlen = input_bufinfo.len;
+ if (inlen % width != 0) {
+ mp_raise_ValueError_varg(translate("Input buffer length (%d) must be a multiple of the strand count (%d)"), inlen, width);
+ }
+
+ mp_buffer_info_t output_bufinfo;
+ mp_get_buffer_raise(args[ARG_output].u_obj, &output_bufinfo, MP_BUFFER_WRITE);
+ int avail = output_bufinfo.len;
+ int outlen = 8 * (inlen / width);
+ if (avail < outlen) {
+ mp_raise_ValueError_varg(translate("Output buffer must be at least %d bytes"), outlen);
+ }
+ common_hal_bitops_bit_transpose(output_bufinfo.buf, input_bufinfo.buf, inlen, width);
+ return args[ARG_output].u_obj;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitops_bit_transpose_obj, 1, bit_transpose);
+
+STATIC const mp_rom_map_elem_t bitops_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitops) },
+ { MP_ROM_QSTR(MP_QSTR_bit_transpose), MP_ROM_PTR(&bitops_bit_transpose_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bitops_module_globals, bitops_module_globals_table);
+
+const mp_obj_module_t bitops_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&bitops_module_globals,
+};
diff --git a/shared-bindings/bitops/__init__.h b/shared-bindings/bitops/__init__.h
new file mode 100644
index 000000000..6654cac5e
--- /dev/null
+++ b/shared-bindings/bitops/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Jeff Epler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdlib.h>
+
+void common_hal_bitops_bit_transpose(uint8_t *result, const uint8_t *src, size_t inlen, size_t num_strands);
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index e47564c8c..cbc6b5c08 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -57,7 +57,7 @@
//|
//| """Construct an SPI object on the given pins.
//|
-//| ..note:: The SPI peripherals allocated in order of desirability, if possible,
+//| .. note:: The SPI peripherals allocated in order of desirability, if possible,
//| such as highest speed and not shared use first. For instance, on the nRF52840,
//| there is a single 32MHz SPI peripheral, and multiple 8MHz peripherals,
//| some of which may also be used for I2C. The 32MHz SPI peripheral is returned
diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c
index bf0b7e721..06647e779 100644
--- a/shared-bindings/busio/UART.c
+++ b/shared-bindings/busio/UART.c
@@ -55,7 +55,7 @@
//| :param ~microcontroller.Pin rs485_dir: the output pin for rs485 direction setting, or ``None`` if rs485 not in use.
//| :param bool rs485_invert: rs485_dir pin active high when set. Active low otherwise.
//| :param int baudrate: the transmit and receive speed.
-//| :param int bits: the number of bits per byte, 7, 8 or 9.
+//| :param int bits: the number of bits per byte, 5 to 9.
//| :param Parity parity: the parity used for error checking.
//| :param int stop: the number of stop bits, 1 or 2.
//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds.
@@ -82,7 +82,7 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co
// This is needed to avoid crashes with certain UART implementations which
// cannot accomodate being moved after creation. (See
// https://github.com/adafruit/circuitpython/issues/1056)
- busio_uart_obj_t *self = m_new_ll_obj(busio_uart_obj_t);
+ busio_uart_obj_t *self = m_new_ll_obj_with_finaliser(busio_uart_obj_t);
self->base.type = &busio_uart_type;
enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size,
ARG_rts, ARG_cts, ARG_rs485_dir,ARG_rs485_invert};
@@ -110,10 +110,10 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co
mp_raise_ValueError(translate("tx and rx cannot both be None"));
}
- uint8_t bits = args[ARG_bits].u_int;
- if (bits < 7 || bits > 9) {
- mp_raise_ValueError(translate("bits must be 7, 8 or 9"));
+ if (args[ARG_bits].u_int < 5 || args[ARG_bits].u_int > 9) {
+ mp_raise_ValueError(translate("bits must be in range 5 to 9"));
}
+ uint8_t bits = args[ARG_bits].u_int;
busio_uart_parity_t parity = BUSIO_UART_PARITY_NONE;
if (args[ARG_parity].u_obj == &busio_uart_parity_even_obj) {
@@ -387,6 +387,7 @@ const mp_obj_type_t busio_uart_parity_type = {
};
STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&busio_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busio_uart___exit___obj) },
@@ -415,8 +416,8 @@ STATIC const mp_stream_p_t uart_stream_p = {
.write = busio_uart_write,
.ioctl = busio_uart_ioctl,
.is_text = false,
- // Match PySerial when possible, such as disallowing optional length argument for .readinto()
- .pyserial_compatibility = true,
+ // Disallow optional length argument for .readinto()
+ .pyserial_readinto_compatibility = true,
};
const mp_obj_type_t busio_uart_type = {
diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c
index 386e270ab..c1c05504d 100644
--- a/shared-bindings/displayio/Group.c
+++ b/shared-bindings/displayio/Group.c
@@ -42,7 +42,7 @@
//| """Create a Group of a given size and scale. Scale is in one dimension. For example, scale=2
//| leads to a layer's pixel being 2x2 pixels when in the group.
//|
-//| :param int max_size: The maximum group size.
+//| :param int max_size: Ignored. Will be removed in 7.x.
//| :param int scale: Scale of layer pixels in one dimension.
//| :param int x: Initial x position within the parent.
//| :param int y: Initial y position within the parent."""
@@ -59,11 +59,6 @@ STATIC mp_obj_t displayio_group_make_new(const mp_obj_type_t *type, size_t n_arg
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_int_t max_size = args[ARG_max_size].u_int;
- if (max_size < 1) {
- mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_max_size);
- }
-
mp_int_t scale = args[ARG_scale].u_int;
if (scale < 1) {
mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_scale);
@@ -71,7 +66,7 @@ STATIC mp_obj_t displayio_group_make_new(const mp_obj_type_t *type, size_t n_arg
displayio_group_t *self = m_new_obj(displayio_group_t);
self->base.type = &displayio_group_type;
- common_hal_displayio_group_construct(self, max_size, scale, args[ARG_x].u_int, args[ARG_y].u_int);
+ common_hal_displayio_group_construct(self, scale, args[ARG_x].u_int, args[ARG_y].u_int);
return MP_OBJ_FROM_PTR(self);
}
@@ -328,6 +323,21 @@ STATIC mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t valu
return mp_const_none;
}
+//| def sort(self, key: function, reverse: bool) -> None:
+//| """Sort the members of the group."""
+//| ...
+//|
+STATIC mp_obj_t displayio_group_obj_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ displayio_group_t *self = native_group(pos_args[0]);
+ mp_obj_t *args = m_new(mp_obj_t, n_args);
+ for (size_t i = 1; i < n_args; ++i) {
+ args[i] = pos_args[i];
+ }
+ args[0] = MP_OBJ_FROM_PTR(self->members);
+ return mp_obj_list_sort(n_args, pos_args, kw_args);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(displayio_group_sort_obj, 1, displayio_group_obj_sort);
+
STATIC const mp_rom_map_elem_t displayio_group_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_hidden), MP_ROM_PTR(&displayio_group_hidden_obj) },
{ MP_ROM_QSTR(MP_QSTR_scale), MP_ROM_PTR(&displayio_group_scale_obj) },
@@ -338,6 +348,7 @@ STATIC const mp_rom_map_elem_t displayio_group_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&displayio_group_index_obj) },
{ MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&displayio_group_pop_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&displayio_group_remove_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sort), MP_ROM_PTR(&displayio_group_sort_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_group_locals_dict, displayio_group_locals_dict_table);
diff --git a/shared-bindings/displayio/Group.h b/shared-bindings/displayio/Group.h
index 942a207f2..69c73bf4d 100644
--- a/shared-bindings/displayio/Group.h
+++ b/shared-bindings/displayio/Group.h
@@ -33,7 +33,7 @@ extern const mp_obj_type_t displayio_group_type;
displayio_group_t* native_group(mp_obj_t group_obj);
-void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y);
+void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t scale, mp_int_t x, mp_int_t y);
uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self);
void common_hal_displayio_group_set_scale(displayio_group_t* self, uint32_t scale);
bool common_hal_displayio_group_get_hidden(displayio_group_t* self);
diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c
index 8e0259a3b..283c8a1d6 100755
--- a/shared-bindings/supervisor/Runtime.c
+++ b/shared-bindings/supervisor/Runtime.c
@@ -55,59 +55,46 @@ STATIC supervisor_run_reason_t _run_reason;
//| serial_connected: bool
//| """Returns the USB serial communication status (read-only)."""
//|
-
-STATIC mp_obj_t supervisor_get_serial_connected(mp_obj_t self){
- if (!common_hal_get_serial_connected()) {
- return mp_const_false;
- }
- else {
- return mp_const_true;
- }
+STATIC mp_obj_t supervisor_runtime_get_serial_connected(mp_obj_t self){
+ return mp_obj_new_bool(common_hal_supervisor_runtime_get_serial_connected());
}
-MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_serial_connected_obj, supervisor_get_serial_connected);
+MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_serial_connected_obj, supervisor_runtime_get_serial_connected);
-const mp_obj_property_t supervisor_serial_connected_obj = {
+const mp_obj_property_t supervisor_runtime_serial_connected_obj = {
.base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&supervisor_get_serial_connected_obj,
+ .proxy = {(mp_obj_t)&supervisor_runtime_get_serial_connected_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
-
//| serial_bytes_available: int
//| """Returns the whether any bytes are available to read
//| on the USB serial input. Allows for polling to see whether
//| to call the built-in input() or wait. (read-only)"""
//|
-STATIC mp_obj_t supervisor_get_serial_bytes_available(mp_obj_t self){
- if (!common_hal_get_serial_bytes_available()) {
- return mp_const_false;
- }
- else {
- return mp_const_true;
- }
+STATIC mp_obj_t supervisor_runtime_get_serial_bytes_available(mp_obj_t self){
+ return mp_obj_new_bool(common_hal_supervisor_runtime_get_serial_bytes_available());
}
-MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_serial_bytes_available_obj, supervisor_get_serial_bytes_available);
+MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_serial_bytes_available_obj, supervisor_runtime_get_serial_bytes_available);
-const mp_obj_property_t supervisor_serial_bytes_available_obj = {
+const mp_obj_property_t supervisor_runtime_serial_bytes_available_obj = {
.base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&supervisor_get_serial_bytes_available_obj,
+ .proxy = {(mp_obj_t)&supervisor_runtime_get_serial_bytes_available_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
-
//| run_reason: RunReason
//| """Returns why CircuitPython started running this particular time."""
//|
-STATIC mp_obj_t supervisor_get_run_reason(mp_obj_t self) {
+STATIC mp_obj_t supervisor_runtime_get_run_reason(mp_obj_t self) {
return cp_enum_find(&supervisor_run_reason_type, _run_reason);
}
-MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_run_reason_obj, supervisor_get_run_reason);
+MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_run_reason_obj, supervisor_runtime_get_run_reason);
-const mp_obj_property_t supervisor_run_reason_obj = {
+const mp_obj_property_t supervisor_runtime_run_reason_obj = {
.base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&supervisor_get_run_reason_obj,
+ .proxy = {(mp_obj_t)&supervisor_runtime_get_run_reason_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
@@ -117,9 +104,9 @@ void supervisor_set_run_reason(supervisor_run_reason_t run_reason) {
}
STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_serial_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_serial_bytes_available_obj) },
- { MP_ROM_QSTR(MP_QSTR_run_reason), MP_ROM_PTR(&supervisor_run_reason_obj) },
+ { MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_runtime_serial_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_runtime_serial_bytes_available_obj) },
+ { MP_ROM_QSTR(MP_QSTR_run_reason), MP_ROM_PTR(&supervisor_runtime_run_reason_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table);
diff --git a/shared-bindings/supervisor/Runtime.h b/shared-bindings/supervisor/Runtime.h
index 51ed7604d..6874ac744 100755
--- a/shared-bindings/supervisor/Runtime.h
+++ b/shared-bindings/supervisor/Runtime.h
@@ -36,12 +36,12 @@ extern const mp_obj_type_t supervisor_runtime_type;
void supervisor_set_run_reason(supervisor_run_reason_t run_reason);
-bool common_hal_get_serial_connected(void);
+bool common_hal_supervisor_runtime_get_serial_connected(void);
-bool common_hal_get_serial_bytes_available(void);
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void);
//TODO: placeholders for future functions
-//bool common_hal_get_repl_active(void);
-//bool common_hal_get_usb_enumerated(void);
+//bool common_hal_get_supervisor_runtime_repl_active(void);
+//bool common_hal_get_supervisor_runtime_usb_enumerated(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SUPERVISOR_RUNTIME_H
diff --git a/shared-bindings/usb_cdc/Serial.c b/shared-bindings/usb_cdc/Serial.c
new file mode 100644
index 000000000..c813dce5b
--- /dev/null
+++ b/shared-bindings/usb_cdc/Serial.c
@@ -0,0 +1,293 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "shared-bindings/usb_cdc/Serial.h"
+#include "shared-bindings/util.h"
+
+#include "py/ioctl.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+
+//| class Serial:
+//| """Receives cdc commands over USB"""
+//|
+//| def __init__(self) -> None:
+//| """You cannot create an instance of `usb_cdc.Serial`.
+//|
+//| Serial objects are pre-constructed for each CDC device in the USB
+//| descriptor and added to the ``usb_cdc.ports`` tuple."""
+//| ...
+//|
+
+//| def read(self, size: int = 1) -> bytes:
+//| """Read at most ``size`` bytes. If ``size`` exceeds the internal buffer size
+//| only the bytes in the buffer will be read. If `timeout` is > 0 or ``None``,
+//| and fewer than ``size`` bytes are available, keep waiting until the timeout
+//| expires or ``size`` bytes are available.
+//|
+//| :return: Data read
+//| :rtype: bytes"""
+//| ...
+//|
+//| def readinto(self, buf: WriteableBuffer) -> int:
+//| """Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
+//| that many bytes, subject to `timeout`. Otherwise, read at most ``len(buf)`` bytes.
+//|
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: bytes"""
+//| ...
+//|
+//| def write(self, buf: ReadableBuffer) -> int:
+//| """Write as many bytes as possible from the buffer of bytes.
+//|
+//| :return: the number of bytes written
+//| :rtype: int"""
+//| ...
+//|
+//| def flush(self) -> None:
+//| """Force out any unwritten bytes, waiting until they are written."""
+//| ...
+//|
+
+// These three methods are used by the shared stream methods.
+STATIC mp_uint_t usb_cdc_serial_read_stream(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ byte *buf = buf_in;
+
+ // make sure we want at least 1 char
+ if (size == 0) {
+ return 0;
+ }
+
+ return common_hal_usb_cdc_serial_read(self, buf, size, errcode);
+}
+
+STATIC mp_uint_t usb_cdc_serial_write_stream(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ const byte *buf = buf_in;
+
+ return common_hal_usb_cdc_serial_write(self, buf, size, errcode);
+}
+
+STATIC mp_uint_t usb_cdc_serial_ioctl_stream(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t ret = 0;
+ switch (request) {
+ case MP_IOCTL_POLL: {
+ mp_uint_t flags = arg;
+ ret = 0;
+ if ((flags & MP_IOCTL_POLL_RD) && common_hal_usb_cdc_serial_get_in_waiting(self) > 0) {
+ ret |= MP_IOCTL_POLL_RD;
+ }
+ if ((flags & MP_IOCTL_POLL_WR) && common_hal_usb_cdc_serial_get_out_waiting(self) == 0) {
+ ret |= MP_IOCTL_POLL_WR;
+ }
+ break;
+ }
+
+ case MP_STREAM_FLUSH:
+ common_hal_usb_cdc_serial_flush(self);
+ break;
+
+ default:
+ *errcode = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+//| connected: bool
+//| """True if this Serial is connected to a host. (read-only)"""
+//|
+STATIC mp_obj_t usb_cdc_serial_get_connected(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(common_hal_usb_cdc_serial_get_connected(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_connected_obj, usb_cdc_serial_get_connected);
+
+const mp_obj_property_t usb_cdc_serial_connected_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&usb_cdc_serial_get_connected_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| in_waiting: int
+//| """Returns the number of bytes waiting to be read on the USB serial input. (read-only)"""
+//|
+STATIC mp_obj_t usb_cdc_serial_get_in_waiting(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_int(common_hal_usb_cdc_serial_get_in_waiting(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_in_waiting_obj, usb_cdc_serial_get_in_waiting);
+
+const mp_obj_property_t usb_cdc_serial_in_waiting_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&usb_cdc_serial_get_in_waiting_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| out_waiting: int
+//| """Returns the number of bytes waiting to be written on the USB serial output. (read-only)"""
+//|
+STATIC mp_obj_t usb_cdc_serial_get_out_waiting(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_int(common_hal_usb_cdc_serial_get_out_waiting(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_out_waiting_obj, usb_cdc_serial_get_out_waiting);
+
+const mp_obj_property_t usb_cdc_serial_out_waiting_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&usb_cdc_serial_get_out_waiting_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| def reset_input_buffer(self) -> None:
+//| """Clears any unread bytes."""
+//| ...
+//|
+STATIC mp_obj_t usb_cdc_serial_reset_input_buffer(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_usb_cdc_serial_reset_input_buffer(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_reset_input_buffer_obj, usb_cdc_serial_reset_input_buffer);
+
+//| def reset_output_buffer(self) -> None:
+//| """Clears any unwritten bytes."""
+//| ...
+//|
+STATIC mp_obj_t usb_cdc_serial_reset_output_buffer(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_usb_cdc_serial_reset_output_buffer(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_reset_output_buffer_obj, usb_cdc_serial_reset_output_buffer);
+
+//| timeout: Optional[float]
+//| """The initial value of `timeout` is ``None``. If ``None``, wait indefinitely to satisfy
+//| the conditions of a read operation. If 0, do not wait. If > 0, wait only ``timeout`` seconds."""
+//|
+STATIC mp_obj_t usb_cdc_serial_get_timeout(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_float_t timeout = common_hal_usb_cdc_serial_get_timeout(self);
+ return (timeout < 0.0f) ? mp_const_none : mp_obj_new_float(self->timeout);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_timeout_obj, usb_cdc_serial_get_timeout);
+
+STATIC mp_obj_t usb_cdc_serial_set_timeout(mp_obj_t self_in, mp_obj_t timeout_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_usb_cdc_serial_set_timeout(self,
+ timeout_in == mp_const_none ? -1.0f : mp_obj_get_float(timeout_in));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(usb_cdc_serial_set_timeout_obj, usb_cdc_serial_set_timeout);
+
+const mp_obj_property_t usb_cdc_serial_timeout_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&usb_cdc_serial_get_timeout_obj,
+ (mp_obj_t)&usb_cdc_serial_set_timeout_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| write_timeout: Optional[float]
+//| """The initial value of `write_timeout` is ``None``. If ``None``, wait indefinitely to finish
+//| writing all the bytes passed to ``write()``.If 0, do not wait.
+//| If > 0, wait only ``write_timeout`` seconds."""
+//|
+STATIC mp_obj_t usb_cdc_serial_get_write_timeout(mp_obj_t self_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_float_t write_timeout = common_hal_usb_cdc_serial_get_write_timeout(self);
+ return (write_timeout < 0.0f) ? mp_const_none : mp_obj_new_float(self->write_timeout);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_write_timeout_obj, usb_cdc_serial_get_write_timeout);
+
+STATIC mp_obj_t usb_cdc_serial_set_write_timeout(mp_obj_t self_in, mp_obj_t write_timeout_in) {
+ usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_usb_cdc_serial_set_write_timeout(self,
+ write_timeout_in == mp_const_none ? -1.0f : mp_obj_get_float(write_timeout_in));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(usb_cdc_serial_set_write_timeout_obj, usb_cdc_serial_set_write_timeout);
+
+const mp_obj_property_t usb_cdc_serial_write_timeout_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&usb_cdc_serial_get_write_timeout_obj,
+ (mp_obj_t)&usb_cdc_serial_set_write_timeout_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+STATIC const mp_rom_map_elem_t usb_cdc_serial_locals_dict_table[] = {
+ // Standard stream methods.
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
+ { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)},
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+
+ // Other pyserial-inspired attributes.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&usb_cdc_serial_in_waiting_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_out_waiting), MP_ROM_PTR(&usb_cdc_serial_out_waiting_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&usb_cdc_serial_reset_input_buffer_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_reset_output_buffer), MP_ROM_PTR(&usb_cdc_serial_reset_output_buffer_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&usb_cdc_serial_timeout_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write_timeout), MP_ROM_PTR(&usb_cdc_serial_write_timeout_obj) },
+
+ // Not in pyserial protocol.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_connected), MP_ROM_PTR(&usb_cdc_serial_connected_obj) },
+
+
+
+};
+STATIC MP_DEFINE_CONST_DICT(usb_cdc_serial_locals_dict, usb_cdc_serial_locals_dict_table);
+
+STATIC const mp_stream_p_t usb_cdc_serial_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
+ .read = usb_cdc_serial_read_stream,
+ .write = usb_cdc_serial_write_stream,
+ .ioctl = usb_cdc_serial_ioctl_stream,
+ .is_text = false,
+ .pyserial_read_compatibility = true,
+ .pyserial_readinto_compatibility = true,
+ .pyserial_dont_return_none_compatibility = true,
+};
+
+const mp_obj_type_t usb_cdc_serial_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Serial,
+ .getiter = mp_identity_getiter,
+ .iternext = mp_stream_unbuffered_iter,
+ .protocol = &usb_cdc_serial_stream_p,
+ .locals_dict = (mp_obj_dict_t*)&usb_cdc_serial_locals_dict,
+};
diff --git a/shared-bindings/usb_cdc/Serial.h b/shared-bindings/usb_cdc/Serial.h
new file mode 100644
index 000000000..cdf5c3a91
--- /dev/null
+++ b/shared-bindings/usb_cdc/Serial.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC_SERIAL_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC_SERIAL_H
+
+#include "shared-module/usb_cdc/Serial.h"
+
+extern const mp_obj_type_t usb_cdc_serial_type;
+
+extern size_t common_hal_usb_cdc_serial_read(usb_cdc_serial_obj_t *self, uint8_t *data, size_t len, int *errcode);
+extern size_t common_hal_usb_cdc_serial_write(usb_cdc_serial_obj_t *self, const uint8_t *data, size_t len, int *errcode);
+
+extern uint32_t common_hal_usb_cdc_serial_get_in_waiting(usb_cdc_serial_obj_t *self);
+extern uint32_t common_hal_usb_cdc_serial_get_out_waiting(usb_cdc_serial_obj_t *self);
+
+extern void common_hal_usb_cdc_serial_reset_input_buffer(usb_cdc_serial_obj_t *self);
+extern uint32_t common_hal_usb_cdc_serial_reset_output_buffer(usb_cdc_serial_obj_t *self);
+
+extern uint32_t common_hal_usb_cdc_serial_flush(usb_cdc_serial_obj_t *self);
+
+extern bool common_hal_usb_cdc_serial_get_connected(usb_cdc_serial_obj_t *self);
+
+extern mp_float_t common_hal_usb_cdc_serial_get_timeout(usb_cdc_serial_obj_t *self);
+extern void common_hal_usb_cdc_serial_set_timeout(usb_cdc_serial_obj_t *self, mp_float_t timeout);
+
+extern mp_float_t common_hal_usb_cdc_serial_get_write_timeout(usb_cdc_serial_obj_t *self);
+extern void common_hal_usb_cdc_serial_set_write_timeout(usb_cdc_serial_obj_t *self, mp_float_t write_timeout);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC_SERIAL_H
diff --git a/shared-bindings/usb_cdc/__init__.c b/shared-bindings/usb_cdc/__init__.c
new file mode 100644
index 000000000..eb9c25e00
--- /dev/null
+++ b/shared-bindings/usb_cdc/__init__.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Dan Halbertfor Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/usb_cdc/__init__.h"
+#include "shared-bindings/usb_cdc/Serial.h"
+
+#include "py/runtime.h"
+
+//| """USB CDC Serial streams
+//|
+//| The `usb_cdc` module allows access to USB CDC (serial) communications."""
+//|
+//| serials: Tuple[Serial, ...]
+//| """Tuple of all CDC streams. Each item is a `Serial`.
+//| ``serials[0]`` is the USB REPL connection.
+//| ``serials[1]`` is a second USB serial connection, unconnected to the REPL.
+//| """
+//|
+
+static const mp_map_elem_t usb_cdc_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_cdc) },
+ { MP_ROM_QSTR(MP_QSTR_Serial), MP_OBJ_FROM_PTR(&usb_cdc_serial_type) },
+ { MP_ROM_QSTR(MP_QSTR_serials), MP_OBJ_FROM_PTR(&usb_cdc_serials_tuple) },
+};
+
+static MP_DEFINE_CONST_DICT(usb_cdc_module_globals, usb_cdc_module_globals_table);
+
+const mp_obj_module_t usb_cdc_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&usb_cdc_module_globals,
+};
diff --git a/shared-bindings/usb_cdc/__init__.h b/shared-bindings/usb_cdc/__init__.h
new file mode 100644
index 000000000..e81d243e6
--- /dev/null
+++ b/shared-bindings/usb_cdc/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC___INIT___H
+
+#include "shared-module/usb_cdc/__init__.h"
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_CDC___INIT___H