summaryrefslogtreecommitdiff
path: root/shared-bindings
diff options
context:
space:
mode:
authorDavePutz <dwputz@gmail.com>2020-09-14 16:50:40 -0500
committerGitHub <noreply@github.com>2020-09-14 16:50:40 -0500
commit2a2a8d64571bf93e2a166626841555fe1753a565 (patch)
treea4b7ba795a6e17d4d0b32abd942af380b1c36e57 /shared-bindings
parent4a3be4df91837a1c71fcbd62e041f7c45cd4dd4b (diff)
parent3d8bac50e41acc286cefbde9e052c5ccb335101e (diff)
Merge pull request #28 from adafruit/main
Merge from adafruit/main
Diffstat (limited to 'shared-bindings')
-rw-r--r--shared-bindings/_bleio/Adapter.c88
-rw-r--r--shared-bindings/_bleio/Adapter.h7
-rw-r--r--shared-bindings/_bleio/Address.c6
-rw-r--r--shared-bindings/_bleio/Characteristic.c32
-rw-r--r--shared-bindings/_bleio/Characteristic.h10
-rw-r--r--shared-bindings/_bleio/Connection.c9
-rw-r--r--shared-bindings/_bleio/Descriptor.c15
-rw-r--r--shared-bindings/_bleio/Service.c24
-rw-r--r--shared-bindings/_bleio/Service.h6
-rw-r--r--shared-bindings/_bleio/UUID.c6
-rw-r--r--shared-bindings/_bleio/UUID.h4
-rw-r--r--shared-bindings/_bleio/__init__.c105
-rw-r--r--shared-bindings/_bleio/__init__.h4
-rw-r--r--shared-bindings/_eve/__init__.c581
-rw-r--r--shared-bindings/_pew/PewPew.c22
-rw-r--r--shared-bindings/_pixelbuf/PixelBuf.c64
-rw-r--r--shared-bindings/_pixelbuf/PixelBuf.h2
-rw-r--r--shared-bindings/_pixelbuf/__init__.c2
-rw-r--r--shared-bindings/_stage/Layer.c6
-rw-r--r--shared-bindings/_stage/Text.c6
-rw-r--r--shared-bindings/_stage/__init__.c7
-rw-r--r--shared-bindings/_typing/__init__.pyi54
-rw-r--r--shared-bindings/aesio/aes.c4
-rw-r--r--shared-bindings/audiobusio/I2SOut.c4
-rw-r--r--shared-bindings/audiocore/RawSample.c2
-rw-r--r--shared-bindings/audiocore/WaveFile.c4
-rw-r--r--shared-bindings/audiocore/__init__.c7
-rw-r--r--shared-bindings/audioio/AudioOut.c4
-rw-r--r--shared-bindings/audiomixer/Mixer.c4
-rw-r--r--shared-bindings/audiomixer/MixerVoice.c4
-rw-r--r--shared-bindings/audiomp3/MP3Decoder.c6
-rw-r--r--shared-bindings/audiopwmio/PWMAudioOut.c4
-rw-r--r--shared-bindings/bitbangio/I2C.c12
-rw-r--r--shared-bindings/bitbangio/SPI.c4
-rw-r--r--shared-bindings/busio/I2C.c10
-rw-r--r--shared-bindings/busio/SPI.c10
-rw-r--r--shared-bindings/displayio/Bitmap.c105
-rw-r--r--shared-bindings/displayio/Bitmap.h3
-rw-r--r--shared-bindings/displayio/Display.c35
-rw-r--r--shared-bindings/displayio/EPaperDisplay.c10
-rw-r--r--shared-bindings/displayio/Group.c14
-rw-r--r--shared-bindings/fontio/Glyph.c2
-rw-r--r--shared-bindings/framebufferio/FramebufferDisplay.c17
-rw-r--r--shared-bindings/gnss/PositionFix.h2
-rw-r--r--shared-bindings/gnss/SatelliteSystem.h2
-rw-r--r--shared-bindings/help.rst2
-rw-r--r--shared-bindings/i2cperipheral/I2CPeripheral.c9
-rw-r--r--shared-bindings/ipaddress/IPv4Address.c198
-rw-r--r--shared-bindings/ipaddress/IPv4Address.h38
-rw-r--r--shared-bindings/ipaddress/__init__.c113
-rw-r--r--shared-bindings/ipaddress/__init__.h36
-rw-r--r--shared-bindings/microcontroller/__init__.c7
-rw-r--r--shared-bindings/multiterminal/__init__.c2
-rw-r--r--shared-bindings/neopixel_write/__init__.c4
-rw-r--r--shared-bindings/network/__init__.c2
-rw-r--r--shared-bindings/nvm/ByteArray.c2
-rw-r--r--shared-bindings/os/__init__.c14
-rw-r--r--shared-bindings/ps2io/Ps2.c2
-rw-r--r--shared-bindings/pulseio/PulseOut.c39
-rw-r--r--shared-bindings/pulseio/PulseOut.h8
-rw-r--r--shared-bindings/pulseio/__init__.c31
-rw-r--r--shared-bindings/pwmio/PWMOut.c (renamed from shared-bindings/pulseio/PWMOut.c)104
-rw-r--r--shared-bindings/pwmio/PWMOut.h (renamed from shared-bindings/pulseio/PWMOut.h)30
-rw-r--r--shared-bindings/pwmio/__init__.c73
-rw-r--r--shared-bindings/pwmio/__init__.h34
-rw-r--r--shared-bindings/rgbmatrix/RGBMatrix.c7
-rw-r--r--shared-bindings/rgbmatrix/RGBMatrix.h21
-rw-r--r--shared-bindings/rotaryio/__init__.c3
-rw-r--r--shared-bindings/sdcardio/SDCard.c4
-rw-r--r--shared-bindings/sdioio/SDCard.c6
-rw-r--r--shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c92
-rw-r--r--shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h34
-rw-r--r--shared-bindings/sharpdisplay/__init__.c47
-rw-r--r--shared-bindings/sharpdisplay/__init__.h0
-rw-r--r--shared-bindings/socket/__init__.c49
-rw-r--r--shared-bindings/socketpool/Socket.c468
-rw-r--r--shared-bindings/socketpool/Socket.h43
-rw-r--r--shared-bindings/socketpool/SocketPool.c162
-rw-r--r--shared-bindings/socketpool/SocketPool.h55
-rw-r--r--shared-bindings/socketpool/__init__.c53
-rw-r--r--shared-bindings/socketpool/__init__.h30
-rw-r--r--shared-bindings/ssl/SSLContext.c95
-rw-r--r--shared-bindings/ssl/SSLContext.h41
-rw-r--r--shared-bindings/ssl/__init__.c66
-rw-r--r--shared-bindings/ssl/__init__.h34
-rw-r--r--shared-bindings/storage/__init__.c6
-rw-r--r--shared-bindings/struct/__init__.c8
-rw-r--r--shared-bindings/supervisor/__init__.c10
-rw-r--r--shared-bindings/support_matrix.rst15
-rw-r--r--shared-bindings/terminalio/__init__.c3
-rw-r--r--shared-bindings/time/__init__.c6
-rw-r--r--shared-bindings/usb_hid/Device.c26
-rw-r--r--shared-bindings/usb_midi/__init__.c20
-rw-r--r--shared-bindings/vectorio/VectorShape.c4
-rw-r--r--shared-bindings/watchdog/WatchDogMode.h2
-rw-r--r--shared-bindings/wifi/Network.c107
-rw-r--r--shared-bindings/wifi/Network.h42
-rw-r--r--shared-bindings/wifi/Radio.c224
-rw-r--r--shared-bindings/wifi/Radio.h60
-rw-r--r--shared-bindings/wifi/ScannedNetworks.c73
-rw-r--r--shared-bindings/wifi/ScannedNetworks.h39
-rw-r--r--shared-bindings/wifi/__init__.c70
-rw-r--r--shared-bindings/wifi/__init__.h38
-rw-r--r--shared-bindings/wiznet/wiznet5k.c2
104 files changed, 3397 insertions, 745 deletions
diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c
index f898d404a..682177093 100644
--- a/shared-bindings/_bleio/Adapter.c
+++ b/shared-bindings/_bleio/Adapter.c
@@ -48,29 +48,76 @@
#define WINDOW_DEFAULT (0.1f)
//| class Adapter:
-//| """BLE adapter
-//|
-//| The Adapter manages the discovery and connection to other nearby Bluetooth Low Energy devices.
+//| """
+//| The BLE Adapter object manages the discovery and connection to other nearby Bluetooth Low Energy devices.
//| This part of the Bluetooth Low Energy Specification is known as Generic Access Profile (GAP).
//|
//| Discovery of other devices happens during a scanning process that listens for small packets of
//| information, known as advertisements, that are broadcast unencrypted. The advertising packets
//| have two different uses. The first is to broadcast a small piece of data to anyone who cares and
-//| and nothing more. These are known as Beacons. The second class of advertisement is to promote
+//| and nothing more. These are known as beacons. The second class of advertisement is to promote
//| additional functionality available after the devices establish a connection. For example, a
-//| BLE keyboard may advertise that it can provide key information, but not what the key info is.
+//| BLE heart rate monitor would advertise that it provides the standard BLE Heart Rate Service.
//|
-//| The built-in BLE adapter can do both parts of this process: it can scan for other device
+//| The Adapter can do both parts of this process: it can scan for other device
//| advertisements and it can advertise its own data. Furthermore, Adapters can accept incoming
//| connections and also initiate connections."""
//|
-//| def __init__(self) -> None:
-//| """You cannot create an instance of `_bleio.Adapter`.
-//| Use `_bleio.adapter` to access the sole instance available."""
+//| def __init__(self, *, uart: busio.UART, rts: digitalio.DigitalInOut, cts: digitalio.DigitalInOut) -> None:
+//| """On boards that do not have native BLE, you can use an HCI co-processor.
+//| Pass the uart and pins used to communicate with the co-processor, such as an Adafruit AirLift.
+//| The co-processor must have been reset and put into BLE mode beforehand
+//| by the appropriate pin manipulation.
+//| The ``uart``, ``rts``, and ``cts`` objects are used to
+//| communicate with the HCI co-processor in HCI mode.
+//| The `Adapter` object is enabled during this call.
+//|
+//| After instantiating an Adapter, call `_bleio.set_adapter()` to set `_bleio.adapter`
+//|
+//| On boards with native BLE, you cannot create an instance of `_bleio.Adapter`;
+//| this constructor will raise `NotImplementedError`.
+//| Use `_bleio.adapter` to access the sole instance already available.
+//| """
//| ...
//|
+STATIC mp_obj_t bleio_adapter_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+#if CIRCUITPY_BLEIO_HCI
+ bleio_adapter_obj_t *self = common_hal_bleio_allocate_adapter_or_raise();
+
+ enum { ARG_uart, ARG_rts, ARG_cts };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_uart, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
+ };
+
+ 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);
+
+ busio_uart_obj_t *uart = args[ARG_uart].u_obj;
+ if (!MP_OBJ_IS_TYPE(uart, &busio_uart_type)) {
+ mp_raise_ValueError(translate("Expected a UART"));
+ }
+
+ digitalio_digitalinout_obj_t *rts = args[ARG_rts].u_obj;
+ digitalio_digitalinout_obj_t *cts = args[ARG_cts].u_obj;
+ if (!MP_OBJ_IS_TYPE(rts, &digitalio_digitalinout_type) ||
+ !MP_OBJ_IS_TYPE(cts, &digitalio_digitalinout_type)) {
+ mp_raise_ValueError(translate("Expected a DigitalInOut"));
+ }
+
+ // Will enable the adapter.
+ common_hal_bleio_adapter_construct_hci_uart(self, uart, rts, cts);
+
+ return MP_OBJ_FROM_PTR(self);
+#else
+ mp_raise_NotImplementedError(translate("Cannot create a new Adapter; use _bleio.adapter;"));
+ return mp_const_none;
+#endif // CIRCUITPY_BLEIO_HCI
+}
+//|
//| enabled: bool
//| """State of the BLE adapter."""
//|
@@ -96,7 +143,7 @@ const mp_obj_property_t bleio_adapter_enabled_obj = {
};
//| address: Address
-//| """MAC address of the BLE adapter. (read-only)"""
+//| """MAC address of the BLE adapter."""
//|
STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address(self));
@@ -104,10 +151,18 @@ STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address);
+STATIC mp_obj_t bleio_adapter_set_address(mp_obj_t self, mp_obj_t new_address) {
+ if (!common_hal_bleio_adapter_set_address(self, new_address)) {
+ mp_raise_bleio_BluetoothError(translate("Could not set address"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(bleio_adapter_set_address_obj, bleio_adapter_set_address);
+
const mp_obj_property_t bleio_adapter_address_obj = {
.base.type = &mp_type_property,
.proxy = { (mp_obj_t)&bleio_adapter_get_address_obj,
- (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&bleio_adapter_set_address_obj,
(mp_obj_t)&mp_const_none_obj },
};
@@ -145,8 +200,8 @@ const mp_obj_property_t bleio_adapter_name_obj = {
//| .. note: If you set ``anonymous=True``, then a timeout must be specified. If no timeout is
//| specified, then the maximum allowed timeout will be selected automatically.
//|
-//| :param buf data: advertising data packet bytes
-//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed.
+//| :param ~_typing.ReadableBuffer data: advertising data packet bytes
+//| :param ~_typing.ReadableBuffer scan_response: scan response data packet bytes. ``None`` if no scan response is needed.
//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral.
//| :param bool anonymous: If `True` then this device's MAC address is randomized before advertising.
//| :param int timeout: If set, we will only advertise for this many seconds.
@@ -219,7 +274,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapt
//| """Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are
//| filtered and returned separately.
//|
-//| :param sequence prefixes: Sequence of byte string prefixes to filter advertising packets
+//| :param ~_typing.ReadableBuffer prefixes: Sequence of byte string prefixes to filter advertising packets
//| with. A packet without an advertising structure that matches one of the prefixes is
//| ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated.
//| :param int buffer_size: the maximum number of advertising bytes to buffer.
@@ -334,7 +389,7 @@ const mp_obj_property_t bleio_adapter_connected_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| connections: tuple
+//| connections: Tuple[Connection]
//| """Tuple of active connections including those initiated through
//| :py:meth:`_bleio.Adapter.connect`. (read-only)"""
//|
@@ -354,7 +409,7 @@ const mp_obj_property_t bleio_adapter_connections_obj = {
//| """Attempts a connection to the device with the given address.
//|
//| :param Address address: The address of the peripheral to connect to
-//| :param float timeout: Try to connect for timeout seconds."""
+//| :param float/int timeout: Try to connect for timeout seconds."""
//| ...
//|
STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -418,5 +473,6 @@ STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict
const mp_obj_type_t bleio_adapter_type = {
.base = { &mp_type_type },
.name = MP_QSTR_Adapter,
+ .make_new = bleio_adapter_make_new,
.locals_dict = (mp_obj_t)&bleio_adapter_locals_dict,
};
diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h
index 39147b6eb..ac7e216d8 100644
--- a/shared-bindings/_bleio/Adapter.h
+++ b/shared-bindings/_bleio/Adapter.h
@@ -35,13 +35,18 @@
#include "py/objstr.h"
#include "shared-module/_bleio/Address.h"
-const mp_obj_type_t bleio_adapter_type;
+extern const mp_obj_type_t bleio_adapter_type;
+
+#if CIRCUITPY_BLEIO_HCI
+void common_hal_bleio_adapter_construct_hci_uart(bleio_adapter_obj_t *self, busio_uart_obj_t *uart, digitalio_digitalinout_obj_t *rts, digitalio_digitalinout_obj_t *cts);
+#endif // CIRCUITPY_BLEIO_HCI
extern bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self);
extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self);
extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled);
extern bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self);
extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self);
+extern bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address);
extern mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self);
extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name);
diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c
index 94994fb70..04c667db4 100644
--- a/shared-bindings/_bleio/Address.c
+++ b/shared-bindings/_bleio/Address.c
@@ -42,7 +42,7 @@
//| """Create a new Address object encapsulating the address value.
//| The value itself can be one of:
//|
-//| :param buf address: The address value to encapsulate. A buffer object (bytearray, bytes) of 6 bytes.
+//| :param ~_typing.ReadableBuffer address: The address value to encapsulate. A buffer object (bytearray, bytes) of 6 bytes.
//| :param int address_type: one of the integer values: `PUBLIC`, `RANDOM_STATIC`,
//| `RANDOM_PRIVATE_RESOLVABLE`, or `RANDOM_PRIVATE_NON_RESOLVABLE`."""
//| ...
@@ -86,7 +86,7 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
//| or use `str()` on the :py:class:`~_bleio.Attribute` object itself, the address will be printed
//| in the expected order. For example:
//|
-//| .. code-block:: pycon
+//| .. code-block:: python
//|
//| >>> import _bleio
//| >>> _bleio.adapter.address
@@ -128,7 +128,7 @@ const mp_obj_property_t bleio_address_type_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| def __eq__(self, other: Address) -> bool:
+//| def __eq__(self, other: object) -> bool:
//| """Two Address objects are equal if their addresses and address types are equal."""
//| ...
//|
diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c
index 557a356b6..5e384a44c 100644
--- a/shared-bindings/_bleio/Characteristic.c
+++ b/shared-bindings/_bleio/Characteristic.c
@@ -63,7 +63,7 @@
//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
//| number of data bytes that fit in a single BLE 4.x ATT packet.
//| :param bool fixed_length: True if the characteristic value is of fixed length.
-//| :param buf initial_value: The initial value for this characteristic. If not given, will be
+//| :param ~_typing.ReadableBuffer initial_value: The initial value for this characteristic. If not given, will be
//| filled with zeros.
//|
//| :return: the new Characteristic."""
@@ -109,11 +109,14 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_
const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
common_hal_bleio_attribute_security_mode_check_valid(write_perm);
- const mp_int_t max_length = args[ARG_max_length].u_int;
+ const mp_int_t max_length_int = args[ARG_max_length].u_int;
+ if (max_length_int <= 0) {
+ mp_raise_ValueError(translate("max_length must be > 0"));
+ }
+ const size_t max_length = (size_t) max_length_int;
const bool fixed_length = args[ARG_fixed_length].u_bool;
mp_obj_t initial_value = args[ARG_initial_value].u_obj;
- // Length will be validated in common_hal.
mp_buffer_info_t initial_value_bufinfo;
if (initial_value == mp_const_none) {
if (fixed_length && max_length > 0) {
@@ -122,7 +125,12 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_
initial_value = mp_const_empty_bytes;
}
}
+
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
+ if (initial_value_bufinfo.len > max_length ||
+ (fixed_length && initial_value_bufinfo.len != max_length)) {
+ mp_raise_ValueError(translate("initial_value length is wrong"));
+ }
bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
characteristic->base.type = &bleio_characteristic_type;
@@ -212,26 +220,14 @@ const mp_obj_property_t bleio_characteristic_value_obj = {
};
//| descriptors: Descriptor
-//| """A tuple of :py:class:`Descriptor` that describe this characteristic. (read-only)"""
+//| """A tuple of :py:class:`Descriptor` objects related to this characteristic. (read-only)"""
//|
STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Return list as a tuple so user won't be able to change it.
- bleio_descriptor_obj_t *descriptors = common_hal_bleio_characteristic_get_descriptor_list(self);
- bleio_descriptor_obj_t *head = descriptors;
- size_t len = 0;
- while (head != NULL) {
- len++;
- head = head->next;
- }
- mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL));
- head = descriptors;
- for (size_t i = len - 1; i >= 0; i--) {
- t->items[i] = MP_OBJ_FROM_PTR(head);
- head = head->next;
- }
- return MP_OBJ_FROM_PTR(t);
+ return MP_OBJ_FROM_PTR(common_hal_bleio_characteristic_get_descriptors(self));
}
+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors);
const mp_obj_property_t bleio_characteristic_descriptors_obj = {
diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h
index c4356fd4b..e28d61e1f 100644
--- a/shared-bindings/_bleio/Characteristic.h
+++ b/shared-bindings/_bleio/Characteristic.h
@@ -36,14 +36,14 @@
extern const mp_obj_type_t bleio_characteristic_type;
-extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
-extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len);
-extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self);
-extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self);
-extern bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self);
+extern mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self);
extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self);
+extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self);
+extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len);
extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor);
+extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate);
+extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c
index ed480ec04..b5eeaa906 100644
--- a/shared-bindings/_bleio/Connection.c
+++ b/shared-bindings/_bleio/Connection.c
@@ -31,7 +31,6 @@
#include <string.h>
#include <stdio.h>
-#include "ble_drv.h"
#include "py/objarray.h"
#include "py/objproperty.h"
#include "py/objstr.h"
@@ -111,12 +110,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_pair_obj, 1, bleio_connection
//| def discover_remote_services(self, service_uuids_whitelist: Optional[Iterable[UUID]] = None) -> Tuple[Service, ...]:
//| """Do BLE discovery for all services or for the given service UUIDS,
-//| to find their handles and characteristics, and return the discovered services.
-//| `Connection.connected` must be True.
+//| to find their handles and characteristics, and return the discovered services.
+//| `Connection.connected` must be True.
//|
//| :param iterable service_uuids_whitelist:
//|
-//| an iterable of :py:class:~`UUID` objects for the services provided by the peripheral
+//| an iterable of :py:class:`UUID` objects for the services provided by the peripheral
//| that you want to use.
//|
//| The peripheral may provide more services, but services not listed are ignored
@@ -126,7 +125,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_pair_obj, 1, bleio_connection
//| slow.
//|
//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
-//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
+//| you must have already created a :py:class:`UUID` object for that UUID in order for the
//| service or characteristic to be discovered. Creating the UUID causes the UUID to be
//| registered for use. (This restriction may be lifted in the future.)
//|
diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c
index e24751f75..c313007c6 100644
--- a/shared-bindings/_bleio/Descriptor.c
+++ b/shared-bindings/_bleio/Descriptor.c
@@ -46,7 +46,7 @@
//| as part of remote Characteristics in the remote Services that are discovered."""
//|
//| @classmethod
-//| def add_to_characteristic(characteristic: Characteristic, uuid: UUID, *, read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, max_length = 20, fixed_length: bool = False, initial_value: ReadableBuffer = b'') -> Descriptor:
+//| def add_to_characteristic(cls, characteristic: Characteristic, uuid: UUID, *, read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, max_length: int = 20, fixed_length: bool = False, initial_value: ReadableBuffer = b'') -> Descriptor:
//| """Create a new Descriptor object, and add it to this Service.
//|
//| :param Characteristic characteristic: The characteristic that will hold this descriptor
@@ -61,7 +61,7 @@
//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
//| number of data bytes that fit in a single BLE 4.x ATT packet.
//| :param bool fixed_length: True if the descriptor value is of fixed length.
-//| :param buf initial_value: The initial value for this descriptor.
+//| :param ~_typing.ReadableBuffer initial_value: The initial value for this descriptor.
//|
//| :return: the new Descriptor."""
//| ...
@@ -100,11 +100,14 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o
const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
common_hal_bleio_attribute_security_mode_check_valid(write_perm);
- const mp_int_t max_length = args[ARG_max_length].u_int;
+ const mp_int_t max_length_int = args[ARG_max_length].u_int;
+ if (max_length_int <= 0) {
+ mp_raise_ValueError(translate("max_length must be > 0"));
+ }
+ const size_t max_length = (size_t) max_length_int;
const bool fixed_length = args[ARG_fixed_length].u_bool;
mp_obj_t initial_value = args[ARG_initial_value].u_obj;
- // Length will be validated in common_hal.
mp_buffer_info_t initial_value_bufinfo;
if (initial_value == mp_const_none) {
if (fixed_length && max_length > 0) {
@@ -114,6 +117,10 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o
}
}
mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
+ if (initial_value_bufinfo.len > max_length ||
+ (fixed_length && initial_value_bufinfo.len != max_length)) {
+ mp_raise_ValueError(translate("initial_value length is wrong"));
+ }
bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
descriptor->base.type = &bleio_descriptor_type;
diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c
index f410b1798..2ddf1a712 100644
--- a/shared-bindings/_bleio/Service.c
+++ b/shared-bindings/_bleio/Service.c
@@ -79,9 +79,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args,
//|
STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) {
bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
- // Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *char_list = common_hal_bleio_service_get_characteristic_list(self);
- return mp_obj_new_tuple(char_list->len, char_list->items);
+ return MP_OBJ_FROM_PTR(common_hal_bleio_service_get_characteristics(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics);
@@ -151,7 +149,7 @@ STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) },
{ MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) },
{ MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) },
- { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) },
+ { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table);
@@ -173,21 +171,3 @@ const mp_obj_type_t bleio_service_type = {
.print = bleio_service_print,
.locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict
};
-
-// Helper for classes that store lists of services.
-mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services) {
- // Return list as a tuple so user won't be able to change it.
- bleio_service_obj_t *head = services;
- size_t len = 0;
- while (head != NULL) {
- len++;
- head = head->next;
- }
- mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL));
- head = services;
- for (int32_t i = len - 1; i >= 0; i--) {
- t->items[i] = MP_OBJ_FROM_PTR(head);
- head = head->next;
- }
- return t;
-}
diff --git a/shared-bindings/_bleio/Service.h b/shared-bindings/_bleio/Service.h
index 273c6bd98..44d11f60d 100644
--- a/shared-bindings/_bleio/Service.h
+++ b/shared-bindings/_bleio/Service.h
@@ -34,18 +34,16 @@
#include "py/objtuple.h"
-const mp_obj_type_t bleio_service_type;
+extern const mp_obj_type_t bleio_service_type;
// Private version that doesn't allocate on the heap
extern uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list);
extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary);
extern void common_hal_bleio_service_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t* connection, bleio_uuid_obj_t *uuid, bool is_secondary);
extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self);
-extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self);
+extern mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self);
extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self);
extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self);
extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo);
-mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services);
-
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c
index 6d92cf793..fe045f385 100644
--- a/shared-bindings/_bleio/UUID.c
+++ b/shared-bindings/_bleio/UUID.c
@@ -48,7 +48,7 @@
//| temporary 16-bit UUID that can be used in place of the full 128-bit UUID.
//|
//| :param value: The uuid value to encapsulate
-//| :type value: int or typing.ByteString"""
+//| :type value: int, ~_typing.ReadableBuffer or str"""
//| ...
//|
STATIC mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -248,7 +248,7 @@ STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//| def __eq__(self, other: UUID) -> bool:
+//| def __eq__(self, other: object) -> bool:
//| """Two UUID objects are equal if their values match and they are both 128-bit or both 16-bit."""
//| ...
//|
@@ -283,7 +283,7 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
mp_printf(print, "UUID(0x%04x)", common_hal_bleio_uuid_get_uuid16(self));
} else {
uint8_t uuid128[16];
- (void) common_hal_bleio_uuid_get_uuid128(self, uuid128);
+ common_hal_bleio_uuid_get_uuid128(self, uuid128);
mp_printf(print, "UUID('"
"%02x%02x%02x%02x-"
"%02x%02x-"
diff --git a/shared-bindings/_bleio/UUID.h b/shared-bindings/_bleio/UUID.h
index 1490737a7..b10cce67f 100644
--- a/shared-bindings/_bleio/UUID.h
+++ b/shared-bindings/_bleio/UUID.h
@@ -34,9 +34,9 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
extern const mp_obj_type_t bleio_uuid_type;
-extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[]);
+extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]);
extern uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self);
-extern bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]);
+extern void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]);
extern uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self);
void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf);
diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c
index 3002ecd18..3d9084dd5 100644
--- a/shared-bindings/_bleio/__init__.c
+++ b/shared-bindings/_bleio/__init__.c
@@ -41,7 +41,8 @@
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
-//| """
+//| """Bluetooth Low Energy (BLE) communication
+//|
//| The `_bleio` module provides necessary low-level functionality for communicating
//| using Bluetooth Low Energy (BLE). The '_' prefix indicates this module is meant
//| for internal use by libraries but not by the end user. Its API may change incompatibly
@@ -50,12 +51,12 @@
//| `adafruit_ble <https://circuitpython.readthedocs.io/projects/ble/en/latest/>`_
//| CircuitPython library instead, which builds on `_bleio`, and
//| provides higher-level convenience functionality, including predefined beacons, clients,
-//| servers.
-//|
-//| .. attribute:: adapter
+//| servers."""
//|
-//| BLE Adapter used to manage device discovery and connections.
-//| This object is the sole instance of `_bleio.Adapter`."""
+
+//| adapter: Adapter
+//| """BLE Adapter used to manage device discovery and connections.
+//| This object is the sole instance of `_bleio.Adapter`."""
//|
//| class BluetoothError(Exception):
@@ -107,43 +108,95 @@ NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* fmt, ...)
// Called when _bleio is imported.
STATIC mp_obj_t bleio___init__(void) {
+// HCI cannot be enabled on import, because we need to setup the HCI adapter first.
+#if !CIRCUITPY_BLEIO_HCI
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true);
+#endif
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(bleio___init___obj, bleio___init__);
+// Need a forward reference due to mutual references.
+#if CIRCUITPY_BLEIO_HCI
+STATIC mp_obj_dict_t bleio_module_globals;
+#endif
+
+//| def set_adapter(adapter: Optional[_bleio.Adapter]) -> None:
+//| """Set the adapter to use for BLE, such as when using an HCI adapter.
+//| Raises `NotImplementedError` when the adapter is a singleton and cannot be set."""
+//| ...
+//|
+mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj) {
+#if CIRCUITPY_BLEIO_HCI
+ if (adapter_obj != mp_const_none && !MP_OBJ_IS_TYPE(adapter_obj, &bleio_adapter_type)) {
+ mp_raise_TypeError_varg(translate("Expected a %q"), bleio_adapter_type.name);
+ }
+
+ // Equivalent of:
+ // bleio.adapter = adapter_obj
+ mp_map_elem_t *elem = mp_map_lookup(&bleio_module_globals.map, MP_ROM_QSTR(MP_QSTR_adapter), MP_MAP_LOOKUP);
+ if (elem) {
+ elem->value = adapter_obj;
+ }
+#else
+ mp_raise_NotImplementedError(translate("Not settable"));
+#endif
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_set_adapter_obj, bleio_set_adapter);
+
+#if CIRCUITPY_BLEIO_HCI
+// Make the module dictionary be in RAM, so that _bleio.adapter can be set.
+// Use a local macro to define how table entries should be converted.
+#define OBJ_FROM_PTR MP_OBJ_FROM_PTR
+STATIC mp_map_elem_t bleio_module_globals_table[] = {
+#else
+#define OBJ_FROM_PTR MP_ROM_PTR
STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
+#endif
// Name must be the first entry so that the exception printing below is correct.
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__bleio) },
- { MP_ROM_QSTR(MP_QSTR_Adapter), MP_ROM_PTR(&bleio_adapter_type) },
- { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
- { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) },
- { MP_ROM_QSTR(MP_QSTR_Connection), MP_ROM_PTR(&bleio_connection_type) },
- { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
- { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) },
- { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
- { MP_ROM_QSTR(MP_QSTR_PacketBuffer), MP_ROM_PTR(&bleio_packet_buffer_type) },
- { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
- { MP_ROM_QSTR(MP_QSTR_ScanResults), MP_ROM_PTR(&bleio_scanresults_type) },
- { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
- { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
-
- // Properties
+ { MP_ROM_QSTR(MP_QSTR_Adapter), OBJ_FROM_PTR(&bleio_adapter_type) },
+ { MP_ROM_QSTR(MP_QSTR_Address), OBJ_FROM_PTR(&bleio_address_type) },
+ { MP_ROM_QSTR(MP_QSTR_Attribute), OBJ_FROM_PTR(&bleio_attribute_type) },
+ { MP_ROM_QSTR(MP_QSTR_Connection), OBJ_FROM_PTR(&bleio_connection_type) },
+ { MP_ROM_QSTR(MP_QSTR_Characteristic), OBJ_FROM_PTR(&bleio_characteristic_type) },
+ { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), OBJ_FROM_PTR(&bleio_characteristic_buffer_type) },
+ { MP_ROM_QSTR(MP_QSTR_Descriptor), OBJ_FROM_PTR(&bleio_descriptor_type) },
+ { MP_ROM_QSTR(MP_QSTR_PacketBuffer), OBJ_FROM_PTR(&bleio_packet_buffer_type) },
+ { MP_ROM_QSTR(MP_QSTR_ScanEntry), OBJ_FROM_PTR(&bleio_scanentry_type) },
+ { MP_ROM_QSTR(MP_QSTR_ScanResults), OBJ_FROM_PTR(&bleio_scanresults_type) },
+ { MP_ROM_QSTR(MP_QSTR_Service), OBJ_FROM_PTR(&bleio_service_type) },
+ { MP_ROM_QSTR(MP_QSTR_UUID), OBJ_FROM_PTR(&bleio_uuid_type) },
+
+#if CIRCUITPY_BLEIO_HCI
+ // For HCI, _bleio.adapter is settable, and starts as None.
+ { MP_ROM_QSTR(MP_QSTR_adapter), mp_const_none },
+ { MP_ROM_QSTR(MP_QSTR_set_adapter), (mp_obj_t) &bleio_set_adapter_obj },
+#else
+ // For non-HCI _bleio.adapter is a fixed singleton, and is not settable.
+ // _bleio.set_adapter will raise NotImplementedError.
{ MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
+ { MP_ROM_QSTR(MP_QSTR_set_adapter), MP_ROM_PTR(&bleio_set_adapter_obj) },
+#endif
// Errors
- { MP_ROM_QSTR(MP_QSTR_BluetoothError), MP_ROM_PTR(&mp_type_bleio_BluetoothError) },
- { MP_ROM_QSTR(MP_QSTR_ConnectionError), MP_ROM_PTR(&mp_type_bleio_ConnectionError) },
- { MP_ROM_QSTR(MP_QSTR_RoleError), MP_ROM_PTR(&mp_type_bleio_RoleError) },
- { MP_ROM_QSTR(MP_QSTR_SecurityError), MP_ROM_PTR(&mp_type_bleio_SecurityError) },
+ { MP_ROM_QSTR(MP_QSTR_BluetoothError), OBJ_FROM_PTR(&mp_type_bleio_BluetoothError) },
+ { MP_ROM_QSTR(MP_QSTR_ConnectionError), OBJ_FROM_PTR(&mp_type_bleio_ConnectionError) },
+ { MP_ROM_QSTR(MP_QSTR_RoleError), OBJ_FROM_PTR(&mp_type_bleio_RoleError) },
+ { MP_ROM_QSTR(MP_QSTR_SecurityError), OBJ_FROM_PTR(&mp_type_bleio_SecurityError) },
// Initialization
- { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&bleio___init___obj) },
-
+ { MP_ROM_QSTR(MP_QSTR___init__), OBJ_FROM_PTR(&bleio___init___obj) },
};
+#if CIRCUITPY_BLEIO_HCI
+// Module dict is mutable to allow setting _bleio.adapter.
+STATIC MP_DEFINE_MUTABLE_DICT(bleio_module_globals, bleio_module_globals_table);
+#else
STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table);
+#endif
void bleio_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h
index 5256bdaa0..588b1f197 100644
--- a/shared-bindings/_bleio/__init__.h
+++ b/shared-bindings/_bleio/__init__.h
@@ -55,15 +55,17 @@ extern const mp_obj_type_t mp_type_bleio_ConnectionError;
extern const mp_obj_type_t mp_type_bleio_RoleError;
extern const mp_obj_type_t mp_type_bleio_SecurityError;
+extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj);
+
NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t* msg, ...);
NORETURN void mp_raise_bleio_ConnectionError(const compressed_string_t* msg, ...);
NORETURN void mp_raise_bleio_RoleError(const compressed_string_t* msg);
NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* msg, ...);
+bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void);
void common_hal_bleio_check_connected(uint16_t conn_handle);
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
-mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device);
void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist);
size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len);
diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c
index 51d3d65ae..0f628b6fb 100644
--- a/shared-bindings/_eve/__init__.c
+++ b/shared-bindings/_eve/__init__.c
@@ -41,6 +41,9 @@
//| buffers and appending basic graphics commands."""
//|
+//| class _EVE:
+//|
+
typedef struct _mp_obj__EVE_t {
mp_obj_base_t base;
common_hal__eve_t _eve;
@@ -51,6 +54,9 @@ STATIC const mp_obj_type_t _EVE_type;
#define EVEHAL(s) \
(&((mp_obj__EVE_t*)mp_instance_cast_to_native_base((s), &_EVE_type))->_eve)
+//| def register(self, o: object) -> None:
+//| ...
+//|
STATIC mp_obj_t _register(mp_obj_t self, mp_obj_t o) {
common_hal__eve_t *eve = EVEHAL(self);
mp_load_method(o, MP_QSTR_write, eve->dest);
@@ -58,11 +64,11 @@ STATIC mp_obj_t _register(mp_obj_t self, mp_obj_t o) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(register_obj, _register);
-//| def flush(self) -> None:
-//| """Send any queued drawing commands directly to the hardware.
+//| def flush(self) -> None:
+//| """Send any queued drawing commands directly to the hardware.
//|
-//| :param int width: The width of the grid in tiles, or 1 for sprites."""
-//| ...
+//| :param int width: The width of the grid in tiles, or 1 for sprites."""
+//| ...
//|
STATIC mp_obj_t _flush(mp_obj_t self) {
common_hal__eve_flush(EVEHAL(self));
@@ -70,11 +76,11 @@ STATIC mp_obj_t _flush(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(flush_obj, _flush);
-//| def cc(self, b: ReadableBuffer) -> None:
-//| """Append bytes to the command FIFO.
+//| def cc(self, b: ReadableBuffer) -> None:
+//| """Append bytes to the command FIFO.
//|
-//| :param bytes b: The bytes to add"""
-//| ...
+//| :param ~_typing.ReadableBuffer b: The bytes to add"""
+//| ...
//|
STATIC mp_obj_t _cc(mp_obj_t self, mp_obj_t b) {
mp_buffer_info_t buffer_info;
@@ -86,14 +92,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc_obj, _cc);
//{
-//| def AlphaFunc(self, func: int, ref: int) -> None:
-//| """Set the alpha test function
+//| def AlphaFunc(self, func: int, ref: int) -> None:
+//| """Set the alpha test function
//|
-//| :param int func: specifies the test function, one of ``NEVER``, ``LESS``, ``LEQUAL``, ``GREATER``, ``GEQUAL``, ``EQUAL``, ``NOTEQUAL``, or ``ALWAYS``. Range 0-7. The initial value is ALWAYS(7)
-//| :param int ref: specifies the reference value for the alpha test. Range 0-255. The initial value is 0
+//| :param int func: specifies the test function, one of ``NEVER``, ``LESS``, ``LEQUAL``, ``GREATER``, ``GEQUAL``, ``EQUAL``, ``NOTEQUAL``, or ``ALWAYS``. Range 0-7. The initial value is ALWAYS(7)
+//| :param int ref: specifies the reference value for the alpha test. Range 0-255. The initial value is 0
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _alphafunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -104,13 +110,13 @@ STATIC mp_obj_t _alphafunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(alphafunc_obj, _alphafunc);
-//| def Begin(self, prim: int) -> None:
-//| """Begin drawing a graphics primitive
+//| def Begin(self, prim: int) -> None:
+//| """Begin drawing a graphics primitive
//|
-//| :param int prim: graphics primitive.
+//| :param int prim: graphics primitive.
//|
-//| Valid primitives are ``BITMAPS``, ``POINTS``, ``LINES``, ``LINE_STRIP``, ``EDGE_STRIP_R``, ``EDGE_STRIP_L``, ``EDGE_STRIP_A``, ``EDGE_STRIP_B`` and ``RECTS``."""
-//| ...
+//| Valid primitives are ``BITMAPS``, ``POINTS``, ``LINES``, ``LINE_STRIP``, ``EDGE_STRIP_R``, ``EDGE_STRIP_L``, ``EDGE_STRIP_A``, ``EDGE_STRIP_B`` and ``RECTS``."""
+//| ...
//|
STATIC mp_obj_t _begin(mp_obj_t self, mp_obj_t a0) {
@@ -120,11 +126,11 @@ STATIC mp_obj_t _begin(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(begin_obj, _begin);
-//| def BitmapExtFormat(self, format: int) -> None:
-//| """Set the bitmap format
+//| def BitmapExtFormat(self, format: int) -> None:
+//| """Set the bitmap format
//|
-//| :param int format: bitmap pixel format."""
-//| ...
+//| :param int format: bitmap pixel format."""
+//| ...
//|
STATIC mp_obj_t _bitmapextformat(mp_obj_t self, mp_obj_t a0) {
@@ -134,13 +140,13 @@ STATIC mp_obj_t _bitmapextformat(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmapextformat_obj, _bitmapextformat);
-//| def BitmapHandle(self, handle: int) -> None:
-//| """Set the bitmap handle
+//| def BitmapHandle(self, handle: int) -> None:
+//| """Set the bitmap handle
//|
-//| :param int handle: bitmap handle. Range 0-31. The initial value is 0
+//| :param int handle: bitmap handle. Range 0-31. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaphandle(mp_obj_t self, mp_obj_t a0) {
@@ -150,12 +156,12 @@ STATIC mp_obj_t _bitmaphandle(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaphandle_obj, _bitmaphandle);
-//| def BitmapLayoutH(self, linestride: int, height: int) -> None:
-//| """Set the source bitmap memory format and layout for the current handle. high bits for large bitmaps
+//| def BitmapLayoutH(self, linestride: int, height: int) -> None:
+//| """Set the source bitmap memory format and layout for the current handle. high bits for large bitmaps
//|
-//| :param int linestride: high part of bitmap line stride, in bytes. Range 0-7
-//| :param int height: high part of bitmap height, in lines. Range 0-3"""
-//| ...
+//| :param int linestride: high part of bitmap line stride, in bytes. Range 0-7
+//| :param int height: high part of bitmap height, in lines. Range 0-3"""
+//| ...
//|
STATIC mp_obj_t _bitmaplayouth(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -166,13 +172,13 @@ STATIC mp_obj_t _bitmaplayouth(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaplayouth_obj, _bitmaplayouth);
-//| def BitmapLayout(self, format: int, linestride: int, height: int) -> None:
-//| """Set the source bitmap memory format and layout for the current handle
+//| def BitmapLayout(self, format: int, linestride: int, height: int) -> None:
+//| """Set the source bitmap memory format and layout for the current handle
//|
-//| :param int format: bitmap pixel format, or GLFORMAT to use BITMAP_EXT_FORMAT instead. Range 0-31
-//| :param int linestride: bitmap line stride, in bytes. Range 0-1023
-//| :param int height: bitmap height, in lines. Range 0-511"""
-//| ...
+//| :param int format: bitmap pixel format, or GLFORMAT to use BITMAP_EXT_FORMAT instead. Range 0-31
+//| :param int linestride: bitmap line stride, in bytes. Range 0-1023
+//| :param int height: bitmap height, in lines. Range 0-511"""
+//| ...
//|
STATIC mp_obj_t _bitmaplayout(size_t n_args, const mp_obj_t *args) {
@@ -184,12 +190,12 @@ STATIC mp_obj_t _bitmaplayout(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaplayout_obj, 4, 4, _bitmaplayout);
-//| def BitmapSizeH(self, width: int, height: int) -> None:
-//| """Set the screen drawing of bitmaps for the current handle. high bits for large bitmaps
+//| def BitmapSizeH(self, width: int, height: int) -> None:
+//| """Set the screen drawing of bitmaps for the current handle. high bits for large bitmaps
//|
-//| :param int width: high part of drawn bitmap width, in pixels. Range 0-3
-//| :param int height: high part of drawn bitmap height, in pixels. Range 0-3"""
-//| ...
+//| :param int width: high part of drawn bitmap width, in pixels. Range 0-3
+//| :param int height: high part of drawn bitmap height, in pixels. Range 0-3"""
+//| ...
//|
STATIC mp_obj_t _bitmapsizeh(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -200,15 +206,15 @@ STATIC mp_obj_t _bitmapsizeh(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmapsizeh_obj, _bitmapsizeh);
-//| def BitmapSize(self, filter: int, wrapx: int, wrapy: int, width: int, height: int) -> None:
-//| """Set the screen drawing of bitmaps for the current handle
+//| def BitmapSize(self, filter: int, wrapx: int, wrapy: int, width: int, height: int) -> None:
+//| """Set the screen drawing of bitmaps for the current handle
//|
-//| :param int filter: bitmap filtering mode, one of ``NEAREST`` or ``BILINEAR``. Range 0-1
-//| :param int wrapx: bitmap :math:`x` wrap mode, one of ``REPEAT`` or ``BORDER``. Range 0-1
-//| :param int wrapy: bitmap :math:`y` wrap mode, one of ``REPEAT`` or ``BORDER``. Range 0-1
-//| :param int width: drawn bitmap width, in pixels. Range 0-511
-//| :param int height: drawn bitmap height, in pixels. Range 0-511"""
-//| ...
+//| :param int filter: bitmap filtering mode, one of ``NEAREST`` or ``BILINEAR``. Range 0-1
+//| :param int wrapx: bitmap :math:`x` wrap mode, one of ``REPEAT`` or ``BORDER``. Range 0-1
+//| :param int wrapy: bitmap :math:`y` wrap mode, one of ``REPEAT`` or ``BORDER``. Range 0-1
+//| :param int width: drawn bitmap width, in pixels. Range 0-511
+//| :param int height: drawn bitmap height, in pixels. Range 0-511"""
+//| ...
//|
STATIC mp_obj_t _bitmapsize(size_t n_args, const mp_obj_t *args) {
@@ -222,11 +228,11 @@ STATIC mp_obj_t _bitmapsize(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapsize_obj, 6, 6, _bitmapsize);
-//| def BitmapSource(self, addr: int) -> None:
-//| """Set the source address for bitmap graphics
+//| def BitmapSource(self, addr: int) -> None:
+//| """Set the source address for bitmap graphics
//|
-//| :param int addr: Bitmap start address, pixel-aligned. May be in SRAM or flash. Range 0-16777215"""
-//| ...
+//| :param int addr: Bitmap start address, pixel-aligned. May be in SRAM or flash. Range 0-16777215"""
+//| ...
//|
STATIC mp_obj_t _bitmapsource(mp_obj_t self, mp_obj_t a0) {
@@ -236,14 +242,14 @@ STATIC mp_obj_t _bitmapsource(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmapsource_obj, _bitmapsource);
-//| def BitmapSwizzle(self, r: int, g: int, b: int, a: int) -> None:
-//| """Set the source for the r,g,b and a channels of a bitmap
+//| def BitmapSwizzle(self, r: int, g: int, b: int, a: int) -> None:
+//| """Set the source for the r,g,b and a channels of a bitmap
//|
-//| :param int r: red component source channel. Range 0-7
-//| :param int g: green component source channel. Range 0-7
-//| :param int b: blue component source channel. Range 0-7
-//| :param int a: alpha component source channel. Range 0-7"""
-//| ...
+//| :param int r: red component source channel. Range 0-7
+//| :param int g: green component source channel. Range 0-7
+//| :param int b: blue component source channel. Range 0-7
+//| :param int a: alpha component source channel. Range 0-7"""
+//| ...
//|
STATIC mp_obj_t _bitmapswizzle(size_t n_args, const mp_obj_t *args) {
@@ -256,16 +262,16 @@ STATIC mp_obj_t _bitmapswizzle(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapswizzle_obj, 5, 5, _bitmapswizzle);
-//| def BitmapTransformA(self, p: int, v: int) -> None:
-//| """Set the :math:`a` component of the bitmap transform matrix
+//| def BitmapTransformA(self, p: int, v: int) -> None:
+//| """Set the :math:`a` component of the bitmap transform matrix
//|
-//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
-//| :param int v: The :math:`a` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256
+//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
+//| :param int v: The :math:`a` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256
//|
-//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0.
+//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0.
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaptransforma(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -276,16 +282,16 @@ STATIC mp_obj_t _bitmaptransforma(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforma_obj, _bitmaptransforma);
-//| def BitmapTransformB(self, p: int, v: int) -> None:
-//| """Set the :math:`b` component of the bitmap transform matrix
+//| def BitmapTransformB(self, p: int, v: int) -> None:
+//| """Set the :math:`b` component of the bitmap transform matrix
//|
-//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
-//| :param int v: The :math:`b` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0
+//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
+//| :param int v: The :math:`b` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0
//|
-//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0.
+//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0.
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaptransformb(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -296,13 +302,13 @@ STATIC mp_obj_t _bitmaptransformb(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformb_obj, _bitmaptransformb);
-//| def BitmapTransformC(self, v: int) -> None:
-//| """Set the :math:`c` component of the bitmap transform matrix
+//| def BitmapTransformC(self, v: int) -> None:
+//| """Set the :math:`c` component of the bitmap transform matrix
//|
-//| :param int v: The :math:`c` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0
+//| :param int v: The :math:`c` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0) {
@@ -312,16 +318,16 @@ STATIC mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformc_obj, _bitmaptransformc);
-//| def BitmapTransformD(self, p: int, v: int) -> None:
-//| """Set the :math:`d` component of the bitmap transform matrix
+//| def BitmapTransformD(self, p: int, v: int) -> None:
+//| """Set the :math:`d` component of the bitmap transform matrix
//|
-//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
-//| :param int v: The :math:`d` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0
+//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
+//| :param int v: The :math:`d` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0
//|
-//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0.
+//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0.
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaptransformd(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -332,16 +338,16 @@ STATIC mp_obj_t _bitmaptransformd(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformd_obj, _bitmaptransformd);
-//| def BitmapTransformE(self, p: int, v: int) -> None:
-//| """Set the :math:`e` component of the bitmap transform matrix
+//| def BitmapTransformE(self, p: int, v: int) -> None:
+//| """Set the :math:`e` component of the bitmap transform matrix
//|
-//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
-//| :param int v: The :math:`e` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256
+//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0
+//| :param int v: The :math:`e` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256
//|
-//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0.
+//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0.
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaptransforme(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -352,13 +358,13 @@ STATIC mp_obj_t _bitmaptransforme(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforme_obj, _bitmaptransforme);
-//| def BitmapTransformF(self, v: int) -> None:
-//| """Set the :math:`f` component of the bitmap transform matrix
+//| def BitmapTransformF(self, v: int) -> None:
+//| """Set the :math:`f` component of the bitmap transform matrix
//|
-//| :param int v: The :math:`f` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0
+//| :param int v: The :math:`f` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0) {
@@ -368,14 +374,14 @@ STATIC mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformf_obj, _bitmaptransformf);
-//| def BlendFunc(self, src: int, dst: int) -> None:
-//| """Set pixel arithmetic
+//| def BlendFunc(self, src: int, dst: int) -> None:
+//| """Set pixel arithmetic
//|
-//| :param int src: specifies how the source blending factor is computed. One of ``ZERO``, ``ONE``, ``SRC_ALPHA``, ``DST_ALPHA``, ``ONE_MINUS_SRC_ALPHA`` or ``ONE_MINUS_DST_ALPHA``. Range 0-7. The initial value is SRC_ALPHA(2)
-//| :param int dst: specifies how the destination blending factor is computed, one of the same constants as **src**. Range 0-7. The initial value is ONE_MINUS_SRC_ALPHA(4)
+//| :param int src: specifies how the source blending factor is computed. One of ``ZERO``, ``ONE``, ``SRC_ALPHA``, ``DST_ALPHA``, ``ONE_MINUS_SRC_ALPHA`` or ``ONE_MINUS_DST_ALPHA``. Range 0-7. The initial value is SRC_ALPHA(2)
+//| :param int dst: specifies how the destination blending factor is computed, one of the same constants as **src**. Range 0-7. The initial value is ONE_MINUS_SRC_ALPHA(4)
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _blendfunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -386,11 +392,11 @@ STATIC mp_obj_t _blendfunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(blendfunc_obj, _blendfunc);
-//| def Call(self, dest: int) -> None:
-//| """Execute a sequence of commands at another location in the display list
+//| def Call(self, dest: int) -> None:
+//| """Execute a sequence of commands at another location in the display list
//|
-//| :param int dest: display list address. Range 0-65535"""
-//| ...
+//| :param int dest: display list address. Range 0-65535"""
+//| ...
//|
STATIC mp_obj_t _call(mp_obj_t self, mp_obj_t a0) {
@@ -400,13 +406,13 @@ STATIC mp_obj_t _call(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(call_obj, _call);
-//| def Cell(self, cell: int) -> None:
-//| """Set the bitmap cell number for the vertex2f command
+//| def Cell(self, cell: int) -> None:
+//| """Set the bitmap cell number for the vertex2f command
//|
-//| :param int cell: bitmap cell number. Range 0-127. The initial value is 0
+//| :param int cell: bitmap cell number. Range 0-127. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _cell(mp_obj_t self, mp_obj_t a0) {
@@ -416,13 +422,13 @@ STATIC mp_obj_t _cell(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cell_obj, _cell);
-//| def ClearColorA(self, alpha: int) -> None:
-//| """Set clear value for the alpha channel
+//| def ClearColorA(self, alpha: int) -> None:
+//| """Set clear value for the alpha channel
//|
-//| :param int alpha: alpha value used when the color buffer is cleared. Range 0-255. The initial value is 0
+//| :param int alpha: alpha value used when the color buffer is cleared. Range 0-255. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _clearcolora(mp_obj_t self, mp_obj_t a0) {
@@ -432,15 +438,15 @@ STATIC mp_obj_t _clearcolora(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(clearcolora_obj, _clearcolora);
-//| def ClearColorRGB(self, red: int, green: int, blue: int) -> None:
-//| """Set clear values for red, green and blue channels
+//| def ClearColorRGB(self, red: int, green: int, blue: int) -> None:
+//| """Set clear values for red, green and blue channels
//|
-//| :param int red: red value used when the color buffer is cleared. Range 0-255. The initial value is 0
-//| :param int green: green value used when the color buffer is cleared. Range 0-255. The initial value is 0
-//| :param int blue: blue value used when the color buffer is cleared. Range 0-255. The initial value is 0
+//| :param int red: red value used when the color buffer is cleared. Range 0-255. The initial value is 0
+//| :param int green: green value used when the color buffer is cleared. Range 0-255. The initial value is 0
+//| :param int blue: blue value used when the color buffer is cleared. Range 0-255. The initial value is 0
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _clearcolorrgb(size_t n_args, const mp_obj_t *args) {
@@ -452,13 +458,13 @@ STATIC mp_obj_t _clearcolorrgb(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clearcolorrgb_obj, 4, 4, _clearcolorrgb);
-//| def Clear(self, c: int, s: int, t: int) -> None:
-//| """Clear buffers to preset values
+//| def Clear(self, c: int, s: int, t: int) -> None:
+//| """Clear buffers to preset values
//|
-//| :param int c: clear color buffer. Range 0-1
-//| :param int s: clear stencil buffer. Range 0-1
-//| :param int t: clear tag buffer. Range 0-1"""
-//| ...
+//| :param int c: clear color buffer. Range 0-1
+//| :param int s: clear stencil buffer. Range 0-1
+//| :param int t: clear tag buffer. Range 0-1"""
+//| ...
//|
STATIC mp_obj_t _clear(size_t n_args, const mp_obj_t *args) {
@@ -470,13 +476,13 @@ STATIC mp_obj_t _clear(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clear_obj, 1, 4, _clear);
-//| def ClearStencil(self, s: int) -> None:
-//| """Set clear value for the stencil buffer
+//| def ClearStencil(self, s: int) -> None:
+//| """Set clear value for the stencil buffer
//|
-//| :param int s: value used when the stencil buffer is cleared. Range 0-255. The initial value is 0
+//| :param int s: value used when the stencil buffer is cleared. Range 0-255. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _clearstencil(mp_obj_t self, mp_obj_t a0) {
@@ -486,12 +492,12 @@ STATIC mp_obj_t _clearstencil(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(clearstencil_obj, _clearstencil);
-//| def ClearTag(self, s: int) -> None:
-//| """Set clear value for the tag buffer
+//| def ClearTag(self, s: int) -> None:
+//| """Set clear value for the tag buffer
//|
-//| :param int s: value used when the tag buffer is cleared. Range 0-255. The initial value is 0
+//| :param int s: value used when the tag buffer is cleared. Range 0-255. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
//|
STATIC mp_obj_t _cleartag(mp_obj_t self, mp_obj_t a0) {
@@ -501,13 +507,13 @@ STATIC mp_obj_t _cleartag(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cleartag_obj, _cleartag);
-//| def ColorA(self, alpha: int) -> None:
-//| """Set the current color alpha
+//| def ColorA(self, alpha: int) -> None:
+//| """Set the current color alpha
//|
-//| :param int alpha: alpha for the current color. Range 0-255. The initial value is 255
+//| :param int alpha: alpha for the current color. Range 0-255. The initial value is 255
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _colora(mp_obj_t self, mp_obj_t a0) {
@@ -517,16 +523,16 @@ STATIC mp_obj_t _colora(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(colora_obj, _colora);
-//| def ColorMask(self, r: int, g: int, b: int, a: int) -> None:
-//| """Enable and disable writing of frame buffer color components
+//| def ColorMask(self, r: int, g: int, b: int, a: int) -> None:
+//| """Enable and disable writing of frame buffer color components
//|
-//| :param int r: allow updates to the frame buffer red component. Range 0-1. The initial value is 1
-//| :param int g: allow updates to the frame buffer green component. Range 0-1. The initial value is 1
-//| :param int b: allow updates to the frame buffer blue component. Range 0-1. The initial value is 1
-//| :param int a: allow updates to the frame buffer alpha component. Range 0-1. The initial value is 1
+//| :param int r: allow updates to the frame buffer red component. Range 0-1. The initial value is 1
+//| :param int g: allow updates to the frame buffer green component. Range 0-1. The initial value is 1
+//| :param int b: allow updates to the frame buffer blue component. Range 0-1. The initial value is 1
+//| :param int a: allow updates to the frame buffer alpha component. Range 0-1. The initial value is 1
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _colormask(size_t n_args, const mp_obj_t *args) {
@@ -539,15 +545,15 @@ STATIC mp_obj_t _colormask(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(colormask_obj, 5, 5, _colormask);
-//| def ColorRGB(self, red: int, green: int, blue: int) -> None:
-//| """Set the drawing color
+//| def ColorRGB(self, red: int, green: int, blue: int) -> None:
+//| """Set the drawing color
//|
-//| :param int red: red value for the current color. Range 0-255. The initial value is 255
-//| :param int green: green for the current color. Range 0-255. The initial value is 255
-//| :param int blue: blue for the current color. Range 0-255. The initial value is 255
+//| :param int red: red value for the current color. Range 0-255. The initial value is 255
+//| :param int green: green for the current color. Range 0-255. The initial value is 255
+//| :param int blue: blue for the current color. Range 0-255. The initial value is 255
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _colorrgb(size_t n_args, const mp_obj_t *args) {
@@ -559,9 +565,9 @@ STATIC mp_obj_t _colorrgb(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(colorrgb_obj, 4, 4, _colorrgb);
-//| def Display(self) -> None:
-//| """End the display list"""
-//| ...
+//| def Display(self) -> None:
+//| """End the display list"""
+//| ...
STATIC mp_obj_t _display(mp_obj_t self) {
@@ -570,11 +576,11 @@ STATIC mp_obj_t _display(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_obj, _display);
-//| def End(self) -> None:
-//| """End drawing a graphics primitive
+//| def End(self) -> None:
+//| """End drawing a graphics primitive
//|
-//| :meth:`Vertex2ii` and :meth:`Vertex2f` calls are ignored until the next :meth:`Begin`."""
-//| ...
+//| :meth:`Vertex2ii` and :meth:`Vertex2f` calls are ignored until the next :meth:`Begin`."""
+//| ...
//|
STATIC mp_obj_t _end(mp_obj_t self) {
@@ -584,11 +590,11 @@ STATIC mp_obj_t _end(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(end_obj, _end);
-//| def Jump(self, dest: int) -> None:
-//| """Execute commands at another location in the display list
+//| def Jump(self, dest: int) -> None:
+//| """Execute commands at another location in the display list
//|
-//| :param int dest: display list address. Range 0-65535"""
-//| ...
+//| :param int dest: display list address. Range 0-65535"""
+//| ...
//|
STATIC mp_obj_t _jump(mp_obj_t self, mp_obj_t a0) {
@@ -598,13 +604,13 @@ STATIC mp_obj_t _jump(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(jump_obj, _jump);
-//| def LineWidth(self, width: int) -> None:
-//| """Set the width of rasterized lines
+//| def LineWidth(self, width: int) -> None:
+//| """Set the width of rasterized lines
//|
-//| :param int width: line width in :math:`1/16` pixel. Range 0-4095. The initial value is 16
+//| :param int width: line width in :math:`1/16` pixel. Range 0-4095. The initial value is 16
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _linewidth(mp_obj_t self, mp_obj_t a0) {
@@ -614,11 +620,11 @@ STATIC mp_obj_t _linewidth(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(linewidth_obj, _linewidth);
-//| def Macro(self, m: int) -> None:
-//| """Execute a single command from a macro register
+//| def Macro(self, m: int) -> None:
+//| """Execute a single command from a macro register
//|
-//| :param int m: macro register to read. Range 0-1"""
-//| ...
+//| :param int m: macro register to read. Range 0-1"""
+//| ...
//|
STATIC mp_obj_t _macro(mp_obj_t self, mp_obj_t a0) {
@@ -628,9 +634,9 @@ STATIC mp_obj_t _macro(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(macro_obj, _macro);
-//| def Nop(self) -> None:
-//| """No operation"""
-//| ...
+//| def Nop(self) -> None:
+//| """No operation"""
+//| ...
//|
STATIC mp_obj_t _nop(mp_obj_t self) {
@@ -640,13 +646,13 @@ STATIC mp_obj_t _nop(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(nop_obj, _nop);
-//| def PaletteSource(self, addr: int) -> None:
-//| """Set the base address of the palette
+//| def PaletteSource(self, addr: int) -> None:
+//| """Set the base address of the palette
//|
-//| :param int addr: Address in graphics SRAM, 2-byte aligned. Range 0-4194303. The initial value is 0
+//| :param int addr: Address in graphics SRAM, 2-byte aligned. Range 0-4194303. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _palettesource(mp_obj_t self, mp_obj_t a0) {
@@ -656,13 +662,13 @@ STATIC mp_obj_t _palettesource(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(palettesource_obj, _palettesource);
-//| def PointSize(self, size: int) -> None:
-//| """Set the radius of rasterized points
+//| def PointSize(self, size: int) -> None:
+//| """Set the radius of rasterized points
//|
-//| :param int size: point radius in :math:`1/16` pixel. Range 0-8191. The initial value is 16
+//| :param int size: point radius in :math:`1/16` pixel. Range 0-8191. The initial value is 16
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _pointsize(mp_obj_t self, mp_obj_t a0) {
@@ -672,9 +678,9 @@ STATIC mp_obj_t _pointsize(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pointsize_obj, _pointsize);
-//| def RestoreContext(self) -> None:
-//| """Restore the current graphics context from the context stack"""
-//| ...
+//| def RestoreContext(self) -> None:
+//| """Restore the current graphics context from the context stack"""
+//| ...
//|
STATIC mp_obj_t _restorecontext(mp_obj_t self) {
@@ -684,9 +690,9 @@ STATIC mp_obj_t _restorecontext(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(restorecontext_obj, _restorecontext);
-//| def Return(self) -> None:
-//| """Return from a previous call command"""
-//| ...
+//| def Return(self) -> None:
+//| """Return from a previous call command"""
+//| ...
//|
STATIC mp_obj_t _return(mp_obj_t self) {
@@ -696,9 +702,9 @@ STATIC mp_obj_t _return(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(return_obj, _return);
-//| def SaveContext(self) -> None:
-//| """Push the current graphics context on the context stack"""
-//| ...
+//| def SaveContext(self) -> None:
+//| """Push the current graphics context on the context stack"""
+//| ...
//|
STATIC mp_obj_t _savecontext(mp_obj_t self) {
@@ -708,14 +714,14 @@ STATIC mp_obj_t _savecontext(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(savecontext_obj, _savecontext);
-//| def ScissorSize(self, width: int, height: int) -> None:
-//| """Set the size of the scissor clip rectangle
+//| def ScissorSize(self, width: int, height: int) -> None:
+//| """Set the size of the scissor clip rectangle
//|
-//| :param int width: The width of the scissor clip rectangle, in pixels. Range 0-4095. The initial value is hsize
-//| :param int height: The height of the scissor clip rectangle, in pixels. Range 0-4095. The initial value is 2048
+//| :param int width: The width of the scissor clip rectangle, in pixels. Range 0-4095. The initial value is hsize
+//| :param int height: The height of the scissor clip rectangle, in pixels. Range 0-4095. The initial value is 2048
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _scissorsize(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -726,14 +732,14 @@ STATIC mp_obj_t _scissorsize(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(scissorsize_obj, _scissorsize);
-//| def ScissorXY(self, x: int, y: int) -> None:
-//| """Set the top left corner of the scissor clip rectangle
+//| def ScissorXY(self, x: int, y: int) -> None:
+//| """Set the top left corner of the scissor clip rectangle
//|
-//| :param int x: The :math:`x` coordinate of the scissor clip rectangle, in pixels. Range 0-2047. The initial value is 0
-//| :param int y: The :math:`y` coordinate of the scissor clip rectangle, in pixels. Range 0-2047. The initial value is 0
+//| :param int x: The :math:`x` coordinate of the scissor clip rectangle, in pixels. Range 0-2047. The initial value is 0
+//| :param int y: The :math:`y` coordinate of the scissor clip rectangle, in pixels. Range 0-2047. The initial value is 0
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _scissorxy(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -744,15 +750,15 @@ STATIC mp_obj_t _scissorxy(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(scissorxy_obj, _scissorxy);
-//| def StencilFunc(self, func: int, ref: int, mask: int) -> None:
-//| """Set function and reference value for stencil testing
+//| def StencilFunc(self, func: int, ref: int, mask: int) -> None:
+//| """Set function and reference value for stencil testing
//|
-//| :param int func: specifies the test function, one of ``NEVER``, ``LESS``, ``LEQUAL``, ``GREATER``, ``GEQUAL``, ``EQUAL``, ``NOTEQUAL``, or ``ALWAYS``. Range 0-7. The initial value is ALWAYS(7)
-//| :param int ref: specifies the reference value for the stencil test. Range 0-255. The initial value is 0
-//| :param int mask: specifies a mask that is ANDed with the reference value and the stored stencil value. Range 0-255. The initial value is 255
+//| :param int func: specifies the test function, one of ``NEVER``, ``LESS``, ``LEQUAL``, ``GREATER``, ``GEQUAL``, ``EQUAL``, ``NOTEQUAL``, or ``ALWAYS``. Range 0-7. The initial value is ALWAYS(7)
+//| :param int ref: specifies the reference value for the stencil test. Range 0-255. The initial value is 0
+//| :param int mask: specifies a mask that is ANDed with the reference value and the stored stencil value. Range 0-255. The initial value is 255
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _stencilfunc(size_t n_args, const mp_obj_t *args) {
@@ -764,13 +770,13 @@ STATIC mp_obj_t _stencilfunc(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stencilfunc_obj, 4, 4, _stencilfunc);
-//| def StencilMask(self, mask: int) -> None:
-//| """Control the writing of individual bits in the stencil planes
+//| def StencilMask(self, mask: int) -> None:
+//| """Control the writing of individual bits in the stencil planes
//|
-//| :param int mask: the mask used to enable writing stencil bits. Range 0-255. The initial value is 255
+//| :param int mask: the mask used to enable writing stencil bits. Range 0-255. The initial value is 255
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _stencilmask(mp_obj_t self, mp_obj_t a0) {
@@ -780,14 +786,14 @@ STATIC mp_obj_t _stencilmask(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(stencilmask_obj, _stencilmask);
-//| def StencilOp(self, sfail: int, spass: int) -> None:
-//| """Set stencil test actions
+//| def StencilOp(self, sfail: int, spass: int) -> None:
+//| """Set stencil test actions
//|
-//| :param int sfail: specifies the action to take when the stencil test fails, one of ``KEEP``, ``ZERO``, ``REPLACE``, ``INCR``, ``INCR_WRAP``, ``DECR``, ``DECR_WRAP``, and ``INVERT``. Range 0-7. The initial value is KEEP(1)
-//| :param int spass: specifies the action to take when the stencil test passes, one of the same constants as **sfail**. Range 0-7. The initial value is KEEP(1)
+//| :param int sfail: specifies the action to take when the stencil test fails, one of ``KEEP``, ``ZERO``, ``REPLACE``, ``INCR``, ``INCR_WRAP``, ``DECR``, ``DECR_WRAP``, and ``INVERT``. Range 0-7. The initial value is KEEP(1)
+//| :param int spass: specifies the action to take when the stencil test passes, one of the same constants as **sfail**. Range 0-7. The initial value is KEEP(1)
//|
-//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _stencilop(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
@@ -798,13 +804,13 @@ STATIC mp_obj_t _stencilop(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(stencilop_obj, _stencilop);
-//| def TagMask(self, mask: int) -> None:
-//| """Control the writing of the tag buffer
+//| def TagMask(self, mask: int) -> None:
+//| """Control the writing of the tag buffer
//|
-//| :param int mask: allow updates to the tag buffer. Range 0-1. The initial value is 1
+//| :param int mask: allow updates to the tag buffer. Range 0-1. The initial value is 1
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _tagmask(mp_obj_t self, mp_obj_t a0) {
@@ -814,13 +820,13 @@ STATIC mp_obj_t _tagmask(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(tagmask_obj, _tagmask);
-//| def Tag(self, s: int) -> None:
-//| """Set the current tag value
+//| def Tag(self, s: int) -> None:
+//| """Set the current tag value
//|
-//| :param int s: tag value. Range 0-255. The initial value is 255
+//| :param int s: tag value. Range 0-255. The initial value is 255
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _tag(mp_obj_t self, mp_obj_t a0) {
@@ -830,13 +836,13 @@ STATIC mp_obj_t _tag(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(tag_obj, _tag);
-//| def VertexTranslateX(self, x: int) -> None:
-//| """Set the vertex transformation's x translation component
+//| def VertexTranslateX(self, x: int) -> None:
+//| """Set the vertex transformation's x translation component
//|
-//| :param int x: signed x-coordinate in :math:`1/16` pixel. Range 0-131071. The initial value is 0
+//| :param int x: signed x-coordinate in :math:`1/16` pixel. Range 0-131071. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _vertextranslatex(mp_obj_t self, mp_obj_t a0) {
@@ -846,13 +852,13 @@ STATIC mp_obj_t _vertextranslatex(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatex_obj, _vertextranslatex);
-//| def VertexTranslateY(self, y: int) -> None:
-//| """Set the vertex transformation's y translation component
+//| def VertexTranslateY(self, y: int) -> None:
+//| """Set the vertex transformation's y translation component
//|
-//| :param int y: signed y-coordinate in :math:`1/16` pixel. Range 0-131071. The initial value is 0
+//| :param int y: signed y-coordinate in :math:`1/16` pixel. Range 0-131071. The initial value is 0
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
@@ -863,13 +869,13 @@ STATIC mp_obj_t _vertextranslatey(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatey_obj, _vertextranslatey);
-//| def VertexFormat(self, frac: int) -> None:
-//| """Set the precision of vertex2f coordinates
+//| def VertexFormat(self, frac: int) -> None:
+//| """Set the precision of vertex2f coordinates
//|
-//| :param int frac: Number of fractional bits in X,Y coordinates, 0-4. Range 0-7. The initial value is 4
+//| :param int frac: Number of fractional bits in X,Y coordinates, 0-4. Range 0-7. The initial value is 4
//|
-//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
-//| ...
+//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`."""
+//| ...
//|
STATIC mp_obj_t _vertexformat(mp_obj_t self, mp_obj_t a0) {
@@ -879,14 +885,14 @@ STATIC mp_obj_t _vertexformat(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertexformat_obj, _vertexformat);
-//| def Vertex2ii(self, x: int, y: int, handle: int, cell: int) -> None:
-//| """:param int x: x-coordinate in pixels. Range 0-511
-//| :param int y: y-coordinate in pixels. Range 0-511
-//| :param int handle: bitmap handle. Range 0-31
-//| :param int cell: cell number. Range 0-127
+//| def Vertex2ii(self, x: int, y: int, handle: int, cell: int) -> None:
+//| """:param int x: x-coordinate in pixels. Range 0-511
+//| :param int y: y-coordinate in pixels. Range 0-511
+//| :param int handle: bitmap handle. Range 0-31
+//| :param int cell: cell number. Range 0-127
//|
-//| This method is an alternative to :meth:`Vertex2f`."""
-//| ...
+//| This method is an alternative to :meth:`Vertex2f`."""
+//| ...
//|
STATIC mp_obj_t _vertex2ii(size_t n_args, const mp_obj_t *args) {
@@ -954,12 +960,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii);
// Hand-written functions {
-//| def Vertex2f(self, b: float) -> None:
-//| """Draw a point.
+//| def Vertex2f(self, b: float) -> None:
+//| """Draw a point.
//|
-//| :param float x: pixel x-coordinate
-//| :param float y: pixel y-coordinate"""
-//| ...
+//| :param float x: pixel x-coordinate
+//| :param float y: pixel y-coordinate"""
+//| ...
//|
STATIC mp_obj_t _vertex2f(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) {
mp_float_t x = mp_obj_get_float(a0);
@@ -973,14 +979,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(vertex2f_obj, _vertex2f);
#define ADD_X(self, x) \
common_hal__eve_add(EVEHAL(self), sizeof(x), &(x));
-//| def cmd0(self, n: int) -> None:
-//| """Append the command word n to the FIFO
+//| def cmd0(self, n: int) -> None:
+//| """Append the command word n to the FIFO
//|
-//| :param int n: The command code
+//| :param int n: The command code
//|
-//| This method is used by the ``eve`` module to efficiently add
-//| commands to the FIFO."""
-//| ...
+//| This method is used by the ``eve`` module to efficiently add
+//| commands to the FIFO."""
+//| ...
//|
STATIC mp_obj_t _cmd0(mp_obj_t self, mp_obj_t n) {
@@ -990,18 +996,19 @@ STATIC mp_obj_t _cmd0(mp_obj_t self, mp_obj_t n) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cmd0_obj, _cmd0);
-//| def cmd(self, n: int, fmt: str, args: tuple) -> None:
-//| """Append a command packet to the FIFO.
+//| def cmd(self, n: int, fmt: str, args: Tuple[str, ...]) -> None:
+//| """Append a command packet to the FIFO.
//|
-//| :param int n: The command code
-//| :param str fmt: The command format `struct` layout
-//| :param tuple args: The command's arguments
+//| :param int n: The command code
+//| :param str fmt: The command format `struct` layout
+//| :param args: The command's arguments
+//| :type args: tuple(str, ...)
//|
-//| Supported format codes: h, H, i, I.
+//| Supported format codes: h, H, i, I.
//|
-//| This method is used by the ``eve`` module to efficiently add
-//| commands to the FIFO."""
-//| ...
+//| This method is used by the ``eve`` module to efficiently add
+//| commands to the FIFO."""
+//| ...
//|
STATIC mp_obj_t _cmd(size_t n_args, const mp_obj_t *args) {
mp_obj_t self = args[0];
diff --git a/shared-bindings/_pew/PewPew.c b/shared-bindings/_pew/PewPew.c
index 0563181d9..a8a43e157 100644
--- a/shared-bindings/_pew/PewPew.c
+++ b/shared-bindings/_pew/PewPew.c
@@ -48,26 +48,8 @@
//| def __init__(
//| self,
//| buffer: ReadableBuffer,
-//| rows: List[
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| ],
-//| cols: List[
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| digitalio.DigitalInOut,
-//| ],
+//| rows: List[digitalio.DigitalInOut],
+//| cols: List[digitalio.DigitalInOut],
//| buttons: digitalio.DigitalInOut,
//| ) -> None:
//| """Initializes matrix scanning routines.
diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c
index abfe190d8..88e8aa801 100644
--- a/shared-bindings/_pixelbuf/PixelBuf.c
+++ b/shared-bindings/_pixelbuf/PixelBuf.c
@@ -40,6 +40,10 @@
#include "shared-module/_pixelbuf/PixelBuf.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
+#ifdef CIRCUITPY_ULAB
+#include "extmod/ulab/code/ndarray.h"
+#endif
+
extern const int32_t colorwheel(float pos);
static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t* parsed);
@@ -58,12 +62,12 @@ static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t
//| brightness (0.0-1.0) and will enable a Dotstar compatible 1st byte for each
//| pixel.
//|
-//| :param ~int size: Number of pixels
-//| :param ~str byteorder: Byte order string (such as "RGB", "RGBW" or "PBGR")
-//| :param ~float brightness: Brightness (0 to 1.0, default 1.0)
-//| :param ~bool auto_write: Whether to automatically write pixels (Default False)
-//| :param bytes header: Sequence of bytes to always send before pixel values.
-//| :param bytes trailer: Sequence of bytes to always send after pixel values."""
+//| :param int size: Number of pixels
+//| :param str byteorder: Byte order string (such as "RGB", "RGBW" or "PBGR")
+//| :param float brightness: Brightness (0 to 1.0, default 1.0)
+//| :param bool auto_write: Whether to automatically write pixels (Default False)
+//| :param ~_typing.ReadableBuffer header: Sequence of bytes to always send before pixel values.
+//| :param ~_typing.ReadableBuffer trailer: Sequence of bytes to always send after pixel values."""
//| ...
//|
STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -257,7 +261,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_show(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_show_obj, pixelbuf_pixelbuf_show);
-//| def fill(self, color: Union[int, Tuple[int, int, int]]) -> None:
+//| def fill(self, color: Union[int, Tuple[int, int, int], Tuple[int, int, int, float]]) -> None:
//| """Fills the given pixelbuf with the given color."""
//| ...
//|
@@ -270,18 +274,20 @@ STATIC mp_obj_t pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t value) {
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_fill_obj, pixelbuf_pixelbuf_fill);
//| @overload
-//| def __getitem__(self, index: slice) -> Tuple[Tuple, ...]: ...
-//| def __getitem__(self, index: int) -> Tuple:
+//| def __getitem__(self, index: slice) -> Union[Tuple[Tuple[int, int, int], ...], Tuple[Tuple[int, int, int, float], ...]]: ...
+//| @overload
+//| def __getitem__(self, index: int) -> Union[Tuple[int, int, int], Tuple[int, int, int, float]]:
//| """Returns the pixel value at the given index as a tuple of (Red, Green, Blue[, White]) values
//| between 0 and 255. When in PWM (DotStar) mode, the 4th tuple value is a float of the pixel
//| intensity from 0-1.0."""
//| ...
//|
//| @overload
-//| def __setitem__(self, index: slice, value: Tuple[Union[int, Tuple, List], ...]) -> None: ...
+//| def __setitem__(self, index: slice, value: Tuple[Union[int, Tuple[float, ...], List[float]], ...]) -> None: ...
+//| @overload
+//| def __setitem__(self, index: slice, value: List[Union[int, Tuple[float, ...], List[float]]]) -> None: ...
//| @overload
-//| def __setitem__(self, index: slice, value: List[Union[int, Tuple, List]]) -> None: ...
-//| def __setitem__(self, index: int, value: Union[int, Tuple, List]) -> None:
+//| def __setitem__(self, index: int, value: Union[int, Tuple[float, ...], List[float]]) -> None:
//| """Sets the pixel value at the given index. Value can either be a tuple or integer. Tuples are
//| The individual (Red, Green, Blue[, White]) values between 0 and 255. If given an integer, the
//| red, green and blue values are packed into the lower three bytes (0xRRGGBB).
@@ -303,6 +309,16 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
size_t length = common_hal__pixelbuf_pixelbuf_get_len(self_in);
mp_seq_get_fast_slice_indexes(length, index_in, &slice);
+ static mp_obj_tuple_t flat_item_tuple = {
+ .base = {&mp_type_tuple},
+ .len = 0,
+ .items = {
+ mp_const_none,
+ mp_const_none,
+ mp_const_none,
+ mp_const_none,
+ }
+ };
size_t slice_len;
if (slice.step > 0) {
@@ -324,27 +340,13 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
} else { // Set
#if MICROPY_PY_ARRAY_SLICE_ASSIGN
- if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple))) {
- mp_raise_ValueError(translate("tuple/list required on RHS"));
- }
+ size_t num_items = mp_obj_get_int(mp_obj_len(value));
- mp_obj_t *src_objs;
- size_t num_items;
- if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
- mp_obj_list_t *t = MP_OBJ_TO_PTR(value);
- num_items = t->len;
- src_objs = t->items;
- } else {
- mp_obj_tuple_t *l = MP_OBJ_TO_PTR(value);
- num_items = l->len;
- src_objs = l->items;
+ if (num_items != slice_len && num_items != (slice_len * common_hal__pixelbuf_pixelbuf_get_bpp(self_in))) {
+ mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."), slice_len, num_items);
}
- if (num_items != slice_len) {
- mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."),
- slice_len, num_items);
- }
-
- common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.step, slice_len, src_objs);
+ common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.step, slice_len, value,
+ num_items != slice_len ? &flat_item_tuple : mp_const_none);
return mp_const_none;
#else
return MP_OBJ_NULL; // op not supported
diff --git a/shared-bindings/_pixelbuf/PixelBuf.h b/shared-bindings/_pixelbuf/PixelBuf.h
index 0b09a5771..d41082059 100644
--- a/shared-bindings/_pixelbuf/PixelBuf.h
+++ b/shared-bindings/_pixelbuf/PixelBuf.h
@@ -47,6 +47,6 @@ void common_hal__pixelbuf_pixelbuf_fill(mp_obj_t self, mp_obj_t item);
void common_hal__pixelbuf_pixelbuf_show(mp_obj_t self);
mp_obj_t common_hal__pixelbuf_pixelbuf_get_pixel(mp_obj_t self, size_t index);
void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self, size_t index, mp_obj_t item);
-void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values);
+void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values, mp_obj_tuple_t *flatten_to);
#endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c
index c714cade4..c61acc939 100644
--- a/shared-bindings/_pixelbuf/__init__.c
+++ b/shared-bindings/_pixelbuf/__init__.c
@@ -33,7 +33,7 @@
#include "shared-bindings/_pixelbuf/PixelBuf.h"
-//| """A fast RGB(W) pixel buffer library for like NeoPixel and DotStar.
+//| """A fast RGB(W) pixel buffer library for like NeoPixel and DotStar
//|
//| The `_pixelbuf` module provides the :py:class:`PixelBuf` class to accelerate
//| RGB(W) strip/matrix manipulation, such as DotStar and Neopixel.
diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c
index 269005ccf..612323a4e 100644
--- a/shared-bindings/_stage/Layer.c
+++ b/shared-bindings/_stage/Layer.c
@@ -40,9 +40,9 @@
//|
//| :param int width: The width of the grid in tiles, or 1 for sprites.
//| :param int height: The height of the grid in tiles, or 1 for sprites.
-//| :param bytearray graphic: The graphic data of the tiles.
-//| :param bytearray palette: The color palette to be used.
-//| :param bytearray grid: The contents of the grid map.
+//| :param ~_typing.ReadableBuffer graphic: The graphic data of the tiles.
+//| :param ~_typing.ReadableBuffer palette: The color palette to be used.
+//| :param ~_typing.ReadableBuffer grid: The contents of the grid map.
//|
//| This class is intended for internal use in the ``stage`` library and
//| it shouldn't be used on its own."""
diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c
index 464af1b98..d1e50fa23 100644
--- a/shared-bindings/_stage/Text.c
+++ b/shared-bindings/_stage/Text.c
@@ -40,9 +40,9 @@
//|
//| :param int width: The width of the grid in tiles, or 1 for sprites.
//| :param int height: The height of the grid in tiles, or 1 for sprites.
-//| :param bytearray font: The font data of the characters.
-//| :param bytearray palette: The color palette to be used.
-//| :param bytearray chars: The contents of the character grid.
+//| :param ~_typing.ReadableBuffer font: The font data of the characters.
+//| :param ~_typing.ReadableBuffer palette: The color palette to be used.
+//| :param ~_typing.ReadableBuffer chars: The contents of the character grid.
//|
//| This class is intended for internal use in the ``stage`` library and
//| it shouldn't be used on its own."""
diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c
index 6651b3e0b..f173147e3 100644
--- a/shared-bindings/_stage/__init__.c
+++ b/shared-bindings/_stage/__init__.c
@@ -39,15 +39,16 @@
//| The `_stage` module contains native code to speed-up the ```stage`` Library
//| <https://github.com/python-ugame/circuitpython-stage>`_."""
//|
-//| def render(x0: int, y0: int, x1: int, y1: int, layers: list, buffer: WriteableBuffer, display: displayio.Display, scale: int, background: int) -> None:
+//| def render(x0: int, y0: int, x1: int, y1: int, layers: List[Layer], buffer: WriteableBuffer, display: displayio.Display, scale: int, background: int) -> None:
//| """Render and send to the display a fragment of the screen.
//|
//| :param int x0: Left edge of the fragment.
//| :param int y0: Top edge of the fragment.
//| :param int x1: Right edge of the fragment.
//| :param int y1: Bottom edge of the fragment.
-//| :param list layers: A list of the :py:class:`~_stage.Layer` objects.
-//| :param bytearray buffer: A buffer to use for rendering.
+//| :param layers: A list of the :py:class:`~_stage.Layer` objects.
+//| :type layers: list[Layer]
+//| :param ~_typing.WriteableBuffer buffer: A buffer to use for rendering.
//| :param ~displayio.Display display: The display to use.
//| :param int scale: How many times should the image be scaled up.
//| :param int background: What color to display when nothing is there.
diff --git a/shared-bindings/_typing/__init__.pyi b/shared-bindings/_typing/__init__.pyi
new file mode 100644
index 000000000..48e68a8d5
--- /dev/null
+++ b/shared-bindings/_typing/__init__.pyi
@@ -0,0 +1,54 @@
+"""Types for the C-level protocols"""
+
+from typing import Union
+
+import array
+import audiocore
+import audiomixer
+import audiomp3
+import rgbmatrix
+import ulab
+
+ReadableBuffer = Union[
+ bytes, bytearray, memoryview, array.array, ulab.array, rgbmatrix.RGBMatrix
+]
+"""Classes that implement the readable buffer protocol
+
+ - `bytes`
+ - `bytearray`
+ - `memoryview`
+ - `array.array`
+ - `ulab.array`
+ - `rgbmatrix.RGBMatrix`
+"""
+
+WriteableBuffer = Union[
+ bytearray, memoryview, array.array, ulab.array, rgbmatrix.RGBMatrix
+]
+"""Classes that implement the writeable buffer protocol
+
+ - `bytearray`
+ - `memoryview`
+ - `array.array`
+ - `ulab.array`
+ - `rgbmatrix.RGBMatrix`
+"""
+
+AudioSample = Union[
+ audiocore.WaveFile, audiocore.RawSample, audiomixer.Mixer, audiomp3.MP3Decoder
+]
+"""Classes that implement the audiosample protocol
+
+ - `audiocore.WaveFile`
+ - `audiocore.RawSample`
+ - `audiomixer.Mixer`
+ - `audiomp3.MP3Decoder`
+
+ You can play these back with `audioio.AudioOut`, `audiobusio.I2SOut` or `audiopwmio.PWMAudioOut`.
+"""
+
+FrameBuffer = Union[rgbmatrix.RGBMatrix]
+"""Classes that implement the framebuffer protocol
+
+ - `rgbmatrix.RGBMatrix`
+"""
diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c
index 7c10693fe..a121845e3 100644
--- a/shared-bindings/aesio/aes.c
+++ b/shared-bindings/aesio/aes.c
@@ -15,10 +15,10 @@
//| def __init__(self, key: ReadableBuffer, mode: int = 0, iv: Optional[ReadableBuffer] = None, segment_size: int = 8) -> None:
//| """Create a new AES state with the given key.
//|
-//| :param bytearray key: A 16-, 24-, or 32-byte key
+//| :param ~_typing.ReadableBuffer key: A 16-, 24-, or 32-byte key
//| :param int mode: AES mode to use. One of: AES.MODE_ECB, AES.MODE_CBC, or
//| AES.MODE_CTR
-//| :param bytearray iv: Initialization vector to use for CBC or CTR mode
+//| :param ~_typing.ReadableBuffer iv: Initialization vector to use for CBC or CTR mode
//|
//| Additional arguments are supported for legacy reasons.
//|
diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c
index 797d782d5..25b536c34 100644
--- a/shared-bindings/audiobusio/I2SOut.c
+++ b/shared-bindings/audiobusio/I2SOut.c
@@ -155,11 +155,11 @@ STATIC mp_obj_t audiobusio_i2sout_obj___exit__(size_t n_args, const mp_obj_t *ar
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_i2sout___exit___obj, 4, 4, audiobusio_i2sout_obj___exit__);
-//| def play(self, sample: audiocore._AudioSample, *, loop: bool = False) -> None:
+//| def play(self, sample: _typing.AudioSample, *, loop: bool = False) -> None:
//| """Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`.
//|
//| The sample itself should consist of 8 bit or 16 bit samples."""
//| ...
diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c
index fd8652c14..df31ee2e0 100644
--- a/shared-bindings/audiocore/RawSample.c
+++ b/shared-bindings/audiocore/RawSample.c
@@ -44,7 +44,7 @@
//| first sample will be for channel 1, the second sample will be for channel two, the third for
//| channel 1 and so on.
//|
-//| :param ReadableBuffer buffer: A buffer with samples
+//| :param ~_typing.ReadableBuffer buffer: A buffer with samples
//| :param int channel_count: The number of channels in the buffer
//| :param int sample_rate: The desired playback sample rate
//|
diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c
index 89c731c68..3b4c9fd97 100644
--- a/shared-bindings/audiocore/WaveFile.c
+++ b/shared-bindings/audiocore/WaveFile.c
@@ -40,11 +40,11 @@
//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
//| an internal buffer."""
//|
-//| def __init__(self, file: typing.BinaryIO, buffer: ReadableBuffer) -> None:
+//| def __init__(self, file: typing.BinaryIO, buffer: WriteableBuffer) -> None:
//| """Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
//| :param typing.BinaryIO file: Already opened wave file
-//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally.
+//| :param ~_typing.WriteableBuffer buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally.
//|
//|
//| Playing a wave file from flash::
diff --git a/shared-bindings/audiocore/__init__.c b/shared-bindings/audiocore/__init__.c
index a27dcefa4..b400b9454 100644
--- a/shared-bindings/audiocore/__init__.c
+++ b/shared-bindings/audiocore/__init__.c
@@ -38,13 +38,6 @@
//| """Support for audio samples"""
//|
-//| _AudioSample = Union[audiocore.WaveFile, audiocore.RawSample, audiomixer.Mixer, audiomp3.MP3Decoder]
-//| """An audio sample for playback with `audioio.AudioOut`, `audiobusio.I2SOut` or `audiopwmio.PWMAudioOut`.
-//|
-//| Supported sources are :py:class:`audiocore.WaveFile`, :py:class:`audiocore.RawSample`,
-//| :py:class:`audiomixer.Mixer` and :py:class:`audiomp3.MP3Decoder`."""
-//|
-
STATIC const mp_rom_map_elem_t audiocore_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiocore) },
{ MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) },
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index 25620a491..0d479be09 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -146,11 +146,11 @@ STATIC mp_obj_t audioio_audioout_obj___exit__(size_t n_args, const mp_obj_t *arg
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_audioout___exit___obj, 4, 4, audioio_audioout_obj___exit__);
-//| def play(self, sample: audiocore._AudioSample, *, loop: bool = False) -> None:
+//| def play(self, sample: _typing.AudioSample, *, loop: bool = False) -> None:
//| """Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`.
//|
//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output
//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit
diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c
index 9a78c7fad..293b19b05 100644
--- a/shared-bindings/audiomixer/Mixer.c
+++ b/shared-bindings/audiomixer/Mixer.c
@@ -211,11 +211,11 @@ const mp_obj_property_t audiomixer_mixer_voice_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| def play(self, sample: audiocore._AudioSample, *, voice: int = 0, loop: bool = False) -> None:
+//| def play(self, sample: _typing.AudioSample, *, voice: int = 0, loop: bool = False) -> None:
//| """Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`.
//|
//| The sample must match the Mixer's encoding settings given in the constructor."""
//| ...
diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c
index 335949bb6..af00e1055 100644
--- a/shared-bindings/audiomixer/MixerVoice.c
+++ b/shared-bindings/audiomixer/MixerVoice.c
@@ -56,11 +56,11 @@ STATIC mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t
return MP_OBJ_FROM_PTR(self);
}
-//| def play(self, sample: audiocore._AudioSample, *, loop: bool = False) -> None:
+//| def play(self, sample: _typing.AudioSample, *, loop: bool = False) -> None:
//| """Plays the sample once when ``loop=False``, and continuously when ``loop=True``.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audiocore.WaveFile`, `audiomixer.Mixer` or `audiocore.RawSample`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`.
//|
//| The sample must match the `audiomixer.Mixer`'s encoding settings given in the constructor."""
//| ...
diff --git a/shared-bindings/audiomp3/MP3Decoder.c b/shared-bindings/audiomp3/MP3Decoder.c
index 0e427951c..85073bf89 100644
--- a/shared-bindings/audiomp3/MP3Decoder.c
+++ b/shared-bindings/audiomp3/MP3Decoder.c
@@ -42,7 +42,7 @@
//| """Load a .mp3 file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
//| :param typing.BinaryIO file: Already opened mp3 file
-//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two buffers are allocated internally. The specific buffer size required depends on the mp3 file.
+//| :param ~_typing.WriteableBuffer buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two buffers are allocated internally. The specific buffer size required depends on the mp3 file.
//|
//|
//| Playing a mp3 file from flash::
@@ -106,7 +106,7 @@ STATIC void check_for_deinit(audiomp3_mp3file_obj_t *self) {
}
}
-//| def __enter__(self) -> MP3:
+//| def __enter__(self) -> MP3Decoder:
//| """No-op used by Context Managers."""
//| ...
//|
@@ -124,7 +124,7 @@ STATIC mp_obj_t audiomp3_mp3file_obj___exit__(size_t n_args, const mp_obj_t *arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomp3_mp3file___exit___obj, 4, 4, audiomp3_mp3file_obj___exit__);
-//| file: file
+//| file: typing.BinaryIO
//| """File to play back."""
//|
STATIC mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) {
diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c
index 74545a4eb..06571fae1 100644
--- a/shared-bindings/audiopwmio/PWMAudioOut.c
+++ b/shared-bindings/audiopwmio/PWMAudioOut.c
@@ -148,11 +148,11 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_obj___exit__(size_t n_args, const mp_obj_
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiopwmio_pwmaudioout___exit___obj, 4, 4, audiopwmio_pwmaudioout_obj___exit__);
-//| def play(self, sample: audiocore._AudioSample, *, loop: bool = False) -> None:
+//| def play(self, sample: _typing.AudioSample, *, loop: bool = False) -> None:
//| """Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`.
//|
//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output
//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit
diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c
index 28ccb4746..17005f63a 100644
--- a/shared-bindings/bitbangio/I2C.c
+++ b/shared-bindings/bitbangio/I2C.c
@@ -120,7 +120,7 @@ static void check_lock(bitbangio_i2c_obj_t *self) {
}
}
-//| def scan(self) -> list:
+//| def scan(self) -> List[int]:
//| """Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of
//| those that respond. A device responds if it pulls the SDA line low after
//| its address (including a read bit) is sent on the bus."""
@@ -175,7 +175,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
//| ``buf[start:end]`` will so it saves memory.
//|
//| :param int address: 7-bit device address
-//| :param bytearray buffer: buffer to write into
+//| :param ~_typing.WriteableBuffer buffer: buffer to write into
//| :param int start: Index to start writing at
//| :param int end: Index to write up to but not include"""
//| ...
@@ -230,7 +230,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea
//| to poll for the existence of a device.
//|
//| :param int address: 7-bit device address
-//| :param bytearray buffer: buffer containing the bytes to write
+//| :param ~_typing.ReadableBuffer buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
//| :param int end: Index to read up to but not include"""
//| ...
@@ -274,7 +274,7 @@ STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, m
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);
-//| def writeto_then_readfrom(self, address: int, out_buffer: WriteableBuffer, in_buffer: ReadableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
+//| def writeto_then_readfrom(self, address: int, out_buffer: ReadableBuffer, in_buffer: ReadableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
//| """Write the bytes from ``out_buffer`` to the device selected by ``address``, generate no stop
//| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and
//| ``in_buffer`` can be the same buffer because they are used sequentially.
@@ -284,8 +284,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_wr
//| will so it saves memory.
//|
//| :param int address: 7-bit device address
-//| :param bytearray out_buffer: buffer containing the bytes to write
-//| :param bytearray in_buffer: buffer to write into
+//| :param ~_typing.ReadableBuffer out_buffer: buffer containing the bytes to write
+//| :param ~_typing.WriteableBuffer in_buffer: buffer to write into
//| :param int out_start: Index to start writing from
//| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)``
//| :param int in_start: Index to start writing at
diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c
index 3e071ed74..fea88bbd4 100644
--- a/shared-bindings/bitbangio/SPI.c
+++ b/shared-bindings/bitbangio/SPI.c
@@ -254,8 +254,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_spi_readinto_obj, 2, 2, bitbangio_
//| must be equal.
//| If buffer slice lengths are both 0, nothing happens.
//|
-//| :param bytearray buffer_out: Write out the data in this buffer
-//| :param bytearray buffer_in: Read data into this buffer
+//| :param ~_typing.ReadableBuffer buffer_out: Write out the data in this buffer
+//| :param ~_typing.WriteableBuffer buffer_in: Read data into this buffer
//| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]``
//| :param int out_end: End of the slice; this index is not included. Defaults to ``len(buffer_out)``
//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]``
diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c
index 4a5d39c52..157e779fd 100644
--- a/shared-bindings/busio/I2C.c
+++ b/shared-bindings/busio/I2C.c
@@ -125,7 +125,7 @@ static void check_lock(busio_i2c_obj_t *self) {
}
}
-//| def scan(self) -> list:
+//| def scan(self) -> List[int]:
//| """Scan all I2C addresses between 0x08 and 0x77 inclusive and return a
//| list of those that respond.
//|
@@ -185,7 +185,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
//| ``buf[start:end]`` will so it saves memory.
//|
//| :param int address: 7-bit device address
-//| :param bytearray buffer: buffer to write into
+//| :param ~_typing.WriteableBuffer buffer: buffer to write into
//| :param int start: Index to start writing at
//| :param int end: Index to write up to but not include. Defaults to ``len(buffer)``"""
//| ...
@@ -239,7 +239,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in
//| to poll for the existence of a device.
//|
//| :param int address: 7-bit device address
-//| :param bytearray buffer: buffer containing the bytes to write
+//| :param ~_typing.ReadbleBuffer buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
//| :param int end: Index to read up to but not include. Defaults to ``len(buffer)``"""
//| ...
@@ -291,8 +291,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto);
//| will so it saves memory.
//|
//| :param int address: 7-bit device address
-//| :param bytearray out_buffer: buffer containing the bytes to write
-//| :param bytearray in_buffer: buffer to write into
+//| :param ~_typing.ReadbleBuffer out_buffer: buffer containing the bytes to write
+//| :param ~_typing.WriteableBuffer in_buffer: buffer to write into
//| :param int out_start: Index to start writing from
//| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)``
//| :param int in_start: Index to start writing at
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index 93dc64d50..aefe4f5a7 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -232,7 +232,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock);
//| """Write the data contained in ``buffer``. The SPI object must be locked.
//| If the buffer is empty, nothing happens.
//|
-//| :param bytearray buffer: Write out the data in this buffer
+//| :param ~_typing.ReadableBuffer buffer: Write out the data in this buffer
//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]``
//| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``"""
//| ...
@@ -275,7 +275,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write);
//| The SPI object must be locked.
//| If the number of bytes to read is 0, nothing happens.
//|
-//| :param bytearray buffer: Read data into this buffer
+//| :param ~_typing.WriteableBuffer buffer: Read data into this buffer
//| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]``
//| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``
//| :param int write_value: Value to write while reading. (Usually ignored.)"""
@@ -314,15 +314,15 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 2, busio_spi_readinto);
-//| def write_readinto(self, buffer_out: ReadableBuffer, buffer_in: ReadableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
+//| def write_readinto(self, buffer_out: ReadableBuffer, buffer_in: WriteableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
//| """Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
//| The SPI object must be locked.
//| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]``
//| must be equal.
//| If buffer slice lengths are both 0, nothing happens.
//|
-//| :param bytearray buffer_out: Write out the data in this buffer
-//| :param bytearray buffer_in: Read data into this buffer
+//| :param ~_typing.ReadableBuffer buffer_out: Write out the data in this buffer
+//| :param ~_typing.WriteableBuffer buffer_in: Read data into this buffer
//| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]``
//| :param int out_end: End of the slice; this index is not included. Defaults to ``len(buffer_out)``
//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]``
diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c
index 0a45bbdfd..5a2fc785f 100644
--- a/shared-bindings/displayio/Bitmap.c
+++ b/shared-bindings/displayio/Bitmap.c
@@ -172,7 +172,109 @@ STATIC mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t val
return mp_const_none;
}
-//| def fill(self, value: int) -> None:
+//| def blit(self, x: int, y: int, source_bitmap: bitmap, *, x1: int, y1: int, x2: int, y2: int, skip_index: int) -> None:
+//| """Inserts the source_bitmap region defined by rectangular boundaries
+//| (x1,y1) and (x2,y2) into the bitmap at the specified (x,y) location.
+//|
+//| :param int x: Horizontal pixel location in bitmap where source_bitmap upper-left
+//| corner will be placed
+//| :param int y: Vertical pixel location in bitmap where source_bitmap upper-left
+//| corner will be placed
+//| :param bitmap source_bitmap: Source bitmap that contains the graphical region to be copied
+//| :param int x1: Minimum x-value for rectangular bounding box to be copied from the source bitmap
+//| :param int y1: Minimum y-value for rectangular bounding box to be copied from the source bitmap
+//| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be copied from the source bitmap
+//| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be copied from the source bitmap
+//| :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 displayio_bitmap_obj_blit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){
+ enum {ARG_x, ARG_y, ARG_source, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_skip_index};
+ static const mp_arg_t allowed_args[] = {
+ {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT},
+ {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT},
+ {MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
+ {MP_QSTR_x1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ {MP_QSTR_y1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ {MP_QSTR_x2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->width
+ {MP_QSTR_y2, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to source->height
+ {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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ displayio_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ int16_t x = args[ARG_x].u_int;
+ int16_t y = args[ARG_y].u_int;
+
+ displayio_bitmap_t *source = MP_OBJ_TO_PTR(args[ARG_source].u_obj);
+
+ // ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
+ if (self->bits_per_value < source->bits_per_value) {
+ mp_raise_ValueError(translate("source palette too large"));
+ }
+
+ int16_t x1 = args[ARG_x1].u_int;
+ int16_t y1 = args[ARG_y1].u_int;
+ int16_t x2, y2;
+ // if x2 or y2 is None, then set as the maximum size of the source bitmap
+ if ( args[ARG_x2].u_obj == mp_const_none ) {
+ x2 = source->width;
+ } else {
+ x2 = mp_obj_get_int(args[ARG_x2].u_obj);
+ }
+ //int16_t y2;
+ if ( args[ARG_y2].u_obj == mp_const_none ) {
+ y2 = source->height;
+ } else {
+ y2 = mp_obj_get_int(args[ARG_y2].u_obj);
+ }
+
+ // Check x,y are within self (target) bitmap boundary
+ if ( (x < 0) || (y < 0) || (x > self->width) || (y > self->height) ) {
+ mp_raise_ValueError(translate("out of range of target"));
+ }
+ // Check x1,y1,x2,y2 are within source bitmap boundary
+ if ( (x1 < 0) || (x1 > source->width) ||
+ (y1 < 0) || (y1 > source->height) ||
+ (x2 < 0) || (x2 > source->width) ||
+ (y2 < 0) || (y2 > source->height) ) {
+ mp_raise_ValueError(translate("out of range of source"));
+ }
+
+ // Ensure x1 < x2 and y1 < y2
+ if (x1 > x2) {
+ int16_t temp=x2;
+ x2=x1;
+ x1=temp;
+ }
+ if (y1 > y2) {
+ int16_t temp=y2;
+ y2=y1;
+ y1=temp;
+ }
+
+ uint32_t skip_index;
+ bool skip_index_none; // flag whether 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_displayio_bitmap_blit(self, x, y, source, x1, y1, x2, y2, skip_index, skip_index_none);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(displayio_bitmap_blit_obj, 4, displayio_bitmap_obj_blit);
+// `displayio_bitmap_obj_blit` requires at least 4 arguments
+
+//| def fill(self, value: Any) -> None:
//| """Fills the bitmap with the supplied palette index value."""
//| ...
//|
@@ -192,6 +294,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_bitmap_fill_obj, displayio_bitmap_obj_fill);
STATIC const mp_rom_map_elem_t displayio_bitmap_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_bitmap_height_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_bitmap_width_obj) },
+ { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&displayio_bitmap_blit_obj) },
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&displayio_bitmap_fill_obj) },
};
diff --git a/shared-bindings/displayio/Bitmap.h b/shared-bindings/displayio/Bitmap.h
index 46c337329..00cd98b0a 100644
--- a/shared-bindings/displayio/Bitmap.h
+++ b/shared-bindings/displayio/Bitmap.h
@@ -40,6 +40,9 @@ uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self);
uint16_t common_hal_displayio_bitmap_get_width(displayio_bitmap_t *self);
uint32_t common_hal_displayio_bitmap_get_bits_per_value(displayio_bitmap_t *self);
void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *bitmap, int16_t x, int16_t y, uint32_t value);
+void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16_t y, displayio_bitmap_t *source,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2,
+ uint32_t skip_index, bool skip_index_none);
uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *bitmap, int16_t x, int16_t y);
void common_hal_displayio_bitmap_fill(displayio_bitmap_t *bitmap, uint32_t value);
diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c
index 70e29ff3e..f36aeed18 100644
--- a/shared-bindings/displayio/Display.c
+++ b/shared-bindings/displayio/Display.c
@@ -81,8 +81,8 @@
//| of the display to minimize tearing artifacts.
//|
//| :param display_bus: The bus that the display is connected to
-//| :type display_bus: FourWire, ParallelBus or I2CDisplay
-//| :param buffer init_sequence: Byte-packed initialization sequence.
+//| :type _DisplayBus: FourWire, ParallelBus or I2CDisplay
+//| :param ~_typing.ReadableBuffer init_sequence: Byte-packed initialization sequence.
//| :param int width: Width in pixels
//| :param int height: Height in pixels
//| :param int colstart: The index if the first visible column
@@ -215,28 +215,33 @@ STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in)
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_show_obj, displayio_display_obj_show);
-//| def refresh(self, *, target_frames_per_second: int = 60, minimum_frames_per_second: int = 1) -> bool:
+//| def refresh(self, *, target_frames_per_second: Optional[int] = None, minimum_frames_per_second: int = 1) -> bool:
//| """When auto refresh is off, waits for the target frame rate and then refreshes the display,
//| returning True. If the call has taken too long since the last refresh call for the given
//| target frame rate, then the refresh returns False immediately without updating the screen to
//| hopefully help getting caught up.
//|
//| If the time since the last successful refresh is below the minimum frame rate, then an
-//| exception will be raised. Set minimum_frames_per_second to 0 to disable.
+//| exception will be raised. Set ``minimum_frames_per_second`` to 0 to disable.
+//|
+//| When auto refresh is off, ``display.refresh()`` or ``display.refresh(target_frames_per_second=None)``
+//| will update the display immediately.
//|
//| When auto refresh is on, updates the display immediately. (The display will also update
//| without calls to this.)
//|
//| :param int target_frames_per_second: How many times a second `refresh` should be called and the screen updated.
+//| Set to `None` for immediate refresh.
//| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second."""
//| ...
//|
STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_target_frames_per_second, ARG_minimum_frames_per_second };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_target_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 60} },
+ { MP_QSTR_target_frames_per_second, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
{ MP_QSTR_minimum_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
};
+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -246,8 +251,18 @@ STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos
if (minimum_frames_per_second > 0) {
maximum_ms_per_real_frame = 1000 / minimum_frames_per_second;
}
- return mp_obj_new_bool(common_hal_displayio_display_refresh(self, 1000 / args[ARG_target_frames_per_second].u_int, maximum_ms_per_real_frame));
+
+ uint32_t target_ms_per_frame;
+ if (args[ARG_target_frames_per_second].u_obj == mp_const_none) {
+ target_ms_per_frame = 0xffffffff;
+ }
+ else {
+ target_ms_per_frame = 1000 / mp_obj_get_int(args[ARG_target_frames_per_second].u_obj);
+ }
+
+ return mp_obj_new_bool(common_hal_displayio_display_refresh(self, target_ms_per_frame, maximum_ms_per_real_frame));
}
+
MP_DEFINE_CONST_FUN_OBJ_KW(displayio_display_refresh_obj, 1, displayio_display_obj_refresh);
//| auto_refresh: bool
@@ -344,7 +359,7 @@ const mp_obj_property_t displayio_display_auto_brightness_obj = {
//| width: int
-//| Gets the width of the board
+//| """Gets the width of the board"""
//|
STATIC mp_obj_t displayio_display_obj_get_width(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
@@ -360,7 +375,7 @@ const mp_obj_property_t displayio_display_width_obj = {
};
//| height: int
-//| """Gets the height of the board"""
+//| """Gets the height of the board"""
//|
STATIC mp_obj_t displayio_display_obj_get_height(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
@@ -399,7 +414,7 @@ const mp_obj_property_t displayio_display_rotation_obj = {
};
//| bus: _DisplayBus
-//| """The bus being used by the display"""
+//| """The bus being used by the display"""
//|
//|
STATIC mp_obj_t displayio_display_obj_get_bus(mp_obj_t self_in) {
@@ -420,7 +435,7 @@ const mp_obj_property_t displayio_display_bus_obj = {
//| """Extract the pixels from a single row
//|
//| :param int y: The top edge of the area
-//| :param bytearray buffer: The buffer in which to place the pixel data"""
+//| :param ~_typing.WriteableBuffer buffer: The buffer in which to place the pixel data"""
//| ...
//|
STATIC mp_obj_t displayio_display_obj_fill_row(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c
index ee1586fe6..8be4ee4c4 100644
--- a/shared-bindings/displayio/EPaperDisplay.c
+++ b/shared-bindings/displayio/EPaperDisplay.c
@@ -60,9 +60,9 @@
//| begin a new command definition.
//|
//| :param display_bus: The bus that the display is connected to
-//| :type display_bus: displayio.FourWire or displayio.ParallelBus
-//| :param buffer start_sequence: Byte-packed initialization sequence.
-//| :param buffer stop_sequence: Byte-packed initialization sequence.
+//| :type _DisplayBus: displayio.FourWire or displayio.ParallelBus
+//| :param ~_typing.ReadableBuffer start_sequence: Byte-packed initialization sequence.
+//| :param ~_typing.ReadableBuffer stop_sequence: Byte-packed initialization sequence.
//| :param int width: Width in pixels
//| :param int height: Height in pixels
//| :param int ram_width: RAM width in pixels
@@ -238,7 +238,7 @@ const mp_obj_property_t displayio_epaperdisplay_width_obj = {
};
//| height: int
-//| """Gets the height of the display in pixels"""
+//| """Gets the height of the display in pixels"""
//|
STATIC mp_obj_t displayio_epaperdisplay_obj_get_height(mp_obj_t self_in) {
displayio_epaperdisplay_obj_t *self = native_display(self_in);
@@ -254,7 +254,7 @@ const mp_obj_property_t displayio_epaperdisplay_height_obj = {
};
//| bus: _DisplayBus
-//| """The bus being used by the display"""
+//| """The bus being used by the display"""
//|
STATIC mp_obj_t displayio_epaperdisplay_obj_get_bus(mp_obj_t self_in) {
displayio_epaperdisplay_obj_t *self = native_display(self_in);
diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c
index a7810df5f..386e270ab 100644
--- a/shared-bindings/displayio/Group.c
+++ b/shared-bindings/displayio/Group.c
@@ -190,7 +190,7 @@ const mp_obj_property_t displayio_group_y_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| def append(self, layer: Union[vectorio.Shape, Group, TileGrid]) -> None:
+//| def append(self, layer: Union[vectorio.VectorShape, Group, TileGrid]) -> None:
//| """Append a layer to the group. It will be drawn above other layers."""
//| ...
//|
@@ -201,7 +201,7 @@ STATIC mp_obj_t displayio_group_obj_append(mp_obj_t self_in, mp_obj_t layer) {
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_append_obj, displayio_group_obj_append);
-//| def insert(self, index: int, layer: Union[vectorio.Shape, Group, TileGrid]) -> None:
+//| def insert(self, index: int, layer: Union[vectorio.VectorShape, Group, TileGrid]) -> None:
//| """Insert a layer into the group."""
//| ...
//|
@@ -217,7 +217,7 @@ STATIC mp_obj_t displayio_group_obj_insert(mp_obj_t self_in, mp_obj_t index_obj,
MP_DEFINE_CONST_FUN_OBJ_3(displayio_group_insert_obj, displayio_group_obj_insert);
-//| def index(self, layer: Union[vectorio.Shape, Group, TileGrid]) -> int:
+//| def index(self, layer: Union[vectorio.VectorShape, Group, TileGrid]) -> int:
//| """Returns the index of the first copy of layer. Raises ValueError if not found."""
//| ...
//|
@@ -231,7 +231,7 @@ STATIC mp_obj_t displayio_group_obj_index(mp_obj_t self_in, mp_obj_t layer) {
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_index_obj, displayio_group_obj_index);
-//| def pop(self, i: int = -1) -> Union[vectorio.Shape, Group, TileGrid]:
+//| def pop(self, i: int = -1) -> Union[vectorio.VectorShape, Group, TileGrid]:
//| """Remove the ith item and return it."""
//| ...
//|
@@ -254,7 +254,7 @@ STATIC mp_obj_t displayio_group_obj_pop(size_t n_args, const mp_obj_t *pos_args,
MP_DEFINE_CONST_FUN_OBJ_KW(displayio_group_pop_obj, 1, displayio_group_obj_pop);
-//| def remove(self, layer: Union[vectorio.Shape, Group, TileGrid]) -> None:
+//| def remove(self, layer: Union[vectorio.VectorShape, Group, TileGrid]) -> None:
//| """Remove the first copy of layer. Raises ValueError if it is not present."""
//| ...
//|
@@ -284,7 +284,7 @@ STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//| def __getitem__(self, index: int) -> Union[vectorio.Shape, Group, TileGrid]:
+//| def __getitem__(self, index: int) -> Union[vectorio.VectorShape, Group, TileGrid]:
//| """Returns the value at the given index.
//|
//| This allows you to::
@@ -292,7 +292,7 @@ STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
//| print(group[0])"""
//| ...
//|
-//| def __setitem__(self, index: int, value: Union[vectorio.Shape, Group, TileGrid]) -> None:
+//| def __setitem__(self, index: int, value: Union[vectorio.VectorShape, Group, TileGrid]) -> None:
//| """Sets the value at the given index.
//|
//| This allows you to::
diff --git a/shared-bindings/fontio/Glyph.c b/shared-bindings/fontio/Glyph.c
index 6558e2e7a..486cebd71 100644
--- a/shared-bindings/fontio/Glyph.c
+++ b/shared-bindings/fontio/Glyph.c
@@ -39,7 +39,7 @@
//| dx: int,
//| dy: int,
//| shift_x: int,
-//| shift_y: int):
+//| shift_y: int) -> None:
//| """Named tuple used to capture a single glyph and its attributes.
//|
//| :param bitmap: the bitmap including the glyph
diff --git a/shared-bindings/framebufferio/FramebufferDisplay.c b/shared-bindings/framebufferio/FramebufferDisplay.c
index e29718fdf..8d1e2ac9c 100644
--- a/shared-bindings/framebufferio/FramebufferDisplay.c
+++ b/shared-bindings/framebufferio/FramebufferDisplay.c
@@ -47,11 +47,10 @@
//| objects in CircuitPython, Display objects live until `displayio.release_displays()`
//| is called. This is done so that CircuitPython can use the display itself."""
//|
-//| def __init__(self, framebuffer: rgbmatrix.RGBMatrix, *, rotation: int = 0, auto_refresh: bool = True) -> None:
+//| def __init__(self, framebuffer: _typing.FrameBuffer, *, rotation: int = 0, auto_refresh: bool = True) -> None:
//| """Create a Display object with the given framebuffer (a buffer, array, ulab.array, etc)
//|
-//| :param framebuffer: The framebuffer that the display is connected to
-//| :type framebuffer: any core object implementing the framebuffer protocol
+//| :param ~_typing.FrameBuffer framebuffer: The framebuffer that the display is connected to
//| :param bool auto_refresh: Automatically refresh the screen
//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)"""
//| ...
@@ -245,7 +244,7 @@ const mp_obj_property_t framebufferio_framebufferdisplay_auto_brightness_obj = {
};
//| width: int
-//| """Gets the width of the framebuffer"""
+//| """Gets the width of the framebuffer"""
//|
STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_width(mp_obj_t self_in) {
framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
@@ -261,7 +260,7 @@ const mp_obj_property_t framebufferio_framebufferdisplay_width_obj = {
};
//| height: int
-//| """Gets the height of the framebuffer"""
+//| """Gets the height of the framebuffer"""
//|
STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_height(mp_obj_t self_in) {
framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
@@ -299,8 +298,8 @@ const mp_obj_property_t framebufferio_framebufferdisplay_rotation_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| framebuffer: rgbmatrix.RGBMatrix
-//| """The framebuffer being used by the display"""
+//| framebuffer: _typing.FrameBuffer
+//| """The framebuffer being used by the display"""
//|
//|
STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_framebuffer(mp_obj_t self_in) {
@@ -317,11 +316,11 @@ const mp_obj_property_t framebufferio_framebufferframebuffer_obj = {
};
-//| def fill_row(self, y: int, buffer: WriteableBuffer) -> displayio:
+//| def fill_row(self, y: int, buffer: WriteableBuffer) -> WriteableBuffer:
//| """Extract the pixels from a single row
//|
//| :param int y: The top edge of the area
-//| :param bytearray buffer: The buffer in which to place the pixel data"""
+//| :param ~_typing.WriteableBuffer buffer: The buffer in which to place the pixel data"""
//| ...
//|
STATIC mp_obj_t framebufferio_framebufferdisplay_obj_fill_row(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
diff --git a/shared-bindings/gnss/PositionFix.h b/shared-bindings/gnss/PositionFix.h
index 34090872c..0fd595fc6 100644
--- a/shared-bindings/gnss/PositionFix.h
+++ b/shared-bindings/gnss/PositionFix.h
@@ -13,7 +13,7 @@ typedef enum {
POSITIONFIX_3D,
} gnss_positionfix_t;
-const mp_obj_type_t gnss_positionfix_type;
+extern const mp_obj_type_t gnss_positionfix_type;
gnss_positionfix_t gnss_positionfix_obj_to_type(mp_obj_t obj);
mp_obj_t gnss_positionfix_type_to_obj(gnss_positionfix_t mode);
diff --git a/shared-bindings/gnss/SatelliteSystem.h b/shared-bindings/gnss/SatelliteSystem.h
index 17f155002..02cd17db2 100644
--- a/shared-bindings/gnss/SatelliteSystem.h
+++ b/shared-bindings/gnss/SatelliteSystem.h
@@ -16,7 +16,7 @@ typedef enum {
SATELLITESYSTEM_QZSS_L1S = (1U << 4),
} gnss_satellitesystem_t;
-const mp_obj_type_t gnss_satellitesystem_type;
+extern const mp_obj_type_t gnss_satellitesystem_type;
gnss_satellitesystem_t gnss_satellitesystem_obj_to_type(mp_obj_t obj);
mp_obj_t gnss_satellitesystem_type_to_obj(gnss_satellitesystem_t mode);
diff --git a/shared-bindings/help.rst b/shared-bindings/help.rst
index f6d72a556..ccc3790a5 100644
--- a/shared-bindings/help.rst
+++ b/shared-bindings/help.rst
@@ -22,7 +22,7 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-:func:`help` - Built-in method to provide helpful information
+:func:`help` -- Built-in method to provide helpful information
==============================================================
.. function:: help(object=None)
diff --git a/shared-bindings/i2cperipheral/I2CPeripheral.c b/shared-bindings/i2cperipheral/I2CPeripheral.c
index cfebd472e..b5ac861b4 100644
--- a/shared-bindings/i2cperipheral/I2CPeripheral.c
+++ b/shared-bindings/i2cperipheral/I2CPeripheral.c
@@ -52,13 +52,14 @@ STATIC mp_obj_t mp_obj_new_i2cperipheral_i2c_peripheral_request(i2cperipheral_i2
//| class I2CPeripheral:
//| """Two wire serial protocol peripheral"""
//|
-//| def __init__(self, scl: microcontroller.Pin, sda: microcontroller.Pin, addresses: tuple, smbus: bool = False) -> None:
+//| def __init__(self, scl: microcontroller.Pin, sda: microcontroller.Pin, addresses: Sequence[int], smbus: bool = False) -> None:
//| """I2C is a two-wire protocol for communicating between devices.
//| This implements the peripheral (sensor, secondary) side.
//|
//| :param ~microcontroller.Pin scl: The clock pin
//| :param ~microcontroller.Pin sda: The data pin
-//| :param tuple addresses: The I2C addresses to respond to (how many is hw dependent).
+//| :param addresses: The I2C addresses to respond to (how many is hw dependent).
+//| :type addresses: list[int]
//| :param bool smbus: Use SMBUS timings if the hardware supports it"""
//| ...
//|
@@ -86,7 +87,7 @@ STATIC mp_obj_t i2cperipheral_i2c_peripheral_make_new(const mp_obj_type_t *type,
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
mp_int_t value;
if (!mp_obj_get_int_maybe(item, &value)) {
- mp_raise_TypeError(translate("can't convert address to int"));
+ mp_raise_TypeError_varg(translate("can't convert %q to %q"), MP_QSTR_address, MP_QSTR_int);
}
if (value < 0x00 || value > 0x7f) {
mp_raise_ValueError(translate("address out of bounds"));
@@ -352,7 +353,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(i2cperipheral_i2c_peripheral_request_read_obj, 1, i2c
//| def write(self, buffer: ReadableBuffer) -> int:
//| """Write the data contained in buffer.
//|
-//| :param buffer: Write out the data in this buffer
+//| :param ~_typing.ReadableBuffer buffer: Write out the data in this buffer
//| :return: Number of bytes written"""
//| ...
//|
diff --git a/shared-bindings/ipaddress/IPv4Address.c b/shared-bindings/ipaddress/IPv4Address.c
new file mode 100644
index 000000000..b2a10158a
--- /dev/null
+++ b/shared-bindings/ipaddress/IPv4Address.c
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * 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/ipaddress/IPv4Address.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#include "py/objproperty.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "shared-bindings/ipaddress/__init__.h"
+
+//| class IPv4Address:
+//| """Encapsulates an IPv4 address."""
+//|
+
+//| def __init__(self, address: Union[int, str, bytes]) -> None:
+//| """Create a new IPv4Address object encapsulating the address value.
+//|
+//| The value itself can either be bytes or a string formatted address."""
+//| ...
+//|
+STATIC mp_obj_t ipaddress_ipv4address_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_address };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_address, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ };
+
+ 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);
+
+ const mp_obj_t address = args[ARG_address].u_obj;
+
+ uint32_t value;
+ uint8_t* buf = NULL;
+ if (mp_obj_get_int_maybe(address, (mp_int_t*) &value)) {
+ // We're done.
+ buf = (uint8_t*) value;
+ } else if (MP_OBJ_IS_STR(address)) {
+ GET_STR_DATA_LEN(address, str_data, str_len);
+ if (!ipaddress_parse_ipv4address((const char*) str_data, str_len, &value)) {
+ mp_raise_ValueError(translate("Not a valid IP string"));
+ }
+ } else {
+ mp_buffer_info_t buf_info;
+ if (mp_get_buffer(address, &buf_info, MP_BUFFER_READ)) {
+ if (buf_info.len != 4) {
+ mp_raise_ValueError_varg(translate("Address must be %d bytes long"), 4);
+ }
+ buf = buf_info.buf;
+ }
+ }
+
+
+ ipaddress_ipv4address_obj_t *self = m_new_obj(ipaddress_ipv4address_obj_t);
+ self->base.type = &ipaddress_ipv4address_type;
+
+ common_hal_ipaddress_ipv4address_construct(self, buf, 4);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| packed: bytes
+//| """The bytes that make up the address (read-only)."""
+//|
+STATIC mp_obj_t ipaddress_ipv4address_get_packed(mp_obj_t self_in) {
+ ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_ipaddress_ipv4address_get_packed(self);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(ipaddress_ipv4address_get_packed_obj, ipaddress_ipv4address_get_packed);
+
+const mp_obj_property_t ipaddress_ipv4address_packed_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&ipaddress_ipv4address_get_packed_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| version: int
+//| """4 for IPv4, 6 for IPv6"""
+//|
+STATIC mp_obj_t ipaddress_ipv4address_get_version(mp_obj_t self_in) {
+ ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_buffer_info_t buf_info;
+ mp_obj_t address_bytes = common_hal_ipaddress_ipv4address_get_packed(self);
+ mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ);
+ mp_int_t version = 6;
+ if (buf_info.len == 4) {
+ version = 4;
+ }
+
+ return MP_OBJ_NEW_SMALL_INT(version);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(ipaddress_ipv4address_get_version_obj, ipaddress_ipv4address_get_version);
+
+const mp_obj_property_t ipaddress_ipv4address_version_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&ipaddress_ipv4address_get_version_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| def __eq__(self, other: IPv4Address) -> bool:
+//| """Two Address objects are equal if their addresses and address types are equal."""
+//| ...
+//|
+STATIC mp_obj_t ipaddress_ipv4address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ switch (op) {
+ // Two Addresses are equal if their address bytes and address_type are equal
+ case MP_BINARY_OP_EQUAL:
+ if (MP_OBJ_IS_TYPE(rhs_in, &ipaddress_ipv4address_type)) {
+ ipaddress_ipv4address_obj_t *lhs = MP_OBJ_TO_PTR(lhs_in);
+ ipaddress_ipv4address_obj_t *rhs = MP_OBJ_TO_PTR(rhs_in);
+ return mp_obj_new_bool(
+ mp_obj_equal(common_hal_ipaddress_ipv4address_get_packed(lhs),
+ common_hal_ipaddress_ipv4address_get_packed(rhs)));
+
+ } else {
+ return mp_const_false;
+ }
+
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
+//| def __hash__(self) -> int:
+//| """Returns a hash for the IPv4Address data."""
+//| ...
+//|
+STATIC mp_obj_t ipaddress_ipv4address_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ switch (op) {
+ // Two Addresses are equal if their address bytes and address_type are equal
+ case MP_UNARY_OP_HASH: {
+ mp_obj_t bytes = common_hal_ipaddress_ipv4address_get_packed(MP_OBJ_TO_PTR(self_in));
+ GET_STR_HASH(bytes, h);
+ if (h == 0) {
+ GET_STR_DATA_LEN(bytes, data, len);
+ h = qstr_compute_hash(data, len);
+ }
+ return MP_OBJ_NEW_SMALL_INT(h);
+ }
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC void ipaddress_ipv4address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_buffer_info_t buf_info;
+ mp_obj_t address_bytes = common_hal_ipaddress_ipv4address_get_packed(self);
+ mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ);
+
+ const uint8_t *buf = (uint8_t *) buf_info.buf;
+ mp_printf(print, "%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
+}
+
+STATIC const mp_rom_map_elem_t ipaddress_ipv4address_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_packed), MP_ROM_PTR(&ipaddress_ipv4address_packed_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(ipaddress_ipv4address_locals_dict, ipaddress_ipv4address_locals_dict_table);
+
+const mp_obj_type_t ipaddress_ipv4address_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Address,
+ .make_new = ipaddress_ipv4address_make_new,
+ .print = ipaddress_ipv4address_print,
+ .unary_op = ipaddress_ipv4address_unary_op,
+ .binary_op = ipaddress_ipv4address_binary_op,
+ .locals_dict = (mp_obj_dict_t*)&ipaddress_ipv4address_locals_dict
+};
diff --git a/shared-bindings/ipaddress/IPv4Address.h b/shared-bindings/ipaddress/IPv4Address.h
new file mode 100644
index 000000000..b45cf3bac
--- /dev/null
+++ b/shared-bindings/ipaddress/IPv4Address.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_IPADDRESS_IPV4ADDRESS_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS_IPV4ADDRESS_H
+
+#include "shared-module/ipaddress/IPv4Address.h"
+
+extern const mp_obj_type_t ipaddress_ipv4address_type;
+
+mp_obj_t common_hal_ipaddress_new_ipv4address(uint32_t value);
+void common_hal_ipaddress_ipv4address_construct(ipaddress_ipv4address_obj_t* self, uint8_t* buf, size_t len);
+mp_obj_t common_hal_ipaddress_ipv4address_get_packed(ipaddress_ipv4address_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS_IPV4ADDRESS_H
diff --git a/shared-bindings/ipaddress/__init__.c b/shared-bindings/ipaddress/__init__.c
new file mode 100644
index 000000000..7ec2984ef
--- /dev/null
+++ b/shared-bindings/ipaddress/__init__.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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/objexcept.h"
+#include "py/objstr.h"
+#include "py/parsenum.h"
+#include "py/runtime.h"
+#include "shared-bindings/ipaddress/__init__.h"
+#include "shared-bindings/ipaddress/IPv4Address.h"
+
+//| """
+//| The `ipaddress` module provides types for IP addresses. It is a subset of CPython's ipaddress
+//| module.
+//| """
+//|
+
+
+bool ipaddress_parse_ipv4address(const char* str_data, size_t str_len, uint32_t* ip_out) {
+ size_t period_count = 0;
+ size_t period_index[4] = {0, 0, 0, str_len};
+ for (size_t i = 0; i < str_len; i++) {
+ if (str_data[i] == '.') {
+ if (period_count < 3) {
+ period_index[period_count] = i;
+ }
+ period_count++;
+ }
+ }
+ if (period_count > 3) {
+ return false;
+ }
+
+ size_t last_period = 0;
+ if (ip_out != NULL) {
+ *ip_out = 0;
+ }
+ for (size_t i = 0; i < 4; i++) {
+ // Catch exceptions thrown by mp_parse_num_integer
+ nlr_buf_t nlr;
+ mp_obj_t octet;
+ if (nlr_push(&nlr) == 0) {
+ octet = mp_parse_num_integer((const char*) str_data + last_period, period_index[i] - last_period, 10, NULL);
+ nlr_pop();
+ } else {
+ return false;
+ }
+ last_period = period_index[i] + 1;
+ if (ip_out != NULL) {
+ mp_int_t int_octet = MP_OBJ_SMALL_INT_VALUE(octet);
+ *ip_out |= int_octet << (i * 8);
+ }
+ }
+ return true;
+}
+
+//| def ip_address(obj: Union[int]) -> IPv4Address:
+//| """Return a corresponding IP address object or raise ValueError if not possible."""
+//| ...
+//|
+
+STATIC mp_obj_t ipaddress_ip_address(mp_obj_t ip_in) {
+ uint32_t value;
+ if (mp_obj_get_int_maybe(ip_in, (mp_int_t*) &value)) {
+ // We're done.
+ } else if (MP_OBJ_IS_STR(ip_in)) {
+ GET_STR_DATA_LEN(ip_in, str_data, str_len);
+ if (!ipaddress_parse_ipv4address((const char*) str_data, str_len, &value)) {
+ mp_raise_ValueError(translate("Not a valid IP string"));
+ }
+ } else {
+ mp_raise_ValueError(translate("Only raw int supported for ip"));
+ }
+
+ return common_hal_ipaddress_new_ipv4address(value);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(ipaddress_ip_address_obj, ipaddress_ip_address);
+
+STATIC const mp_rom_map_elem_t ipaddress_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ipaddress) },
+ { MP_ROM_QSTR(MP_QSTR_ip_address), MP_ROM_PTR(&ipaddress_ip_address_obj) },
+ { MP_ROM_QSTR(MP_QSTR_IPv4Address), MP_ROM_PTR(&ipaddress_ipv4address_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(ipaddress_module_globals, ipaddress_module_globals_table);
+
+
+const mp_obj_module_t ipaddress_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&ipaddress_module_globals,
+};
diff --git a/shared-bindings/ipaddress/__init__.h b/shared-bindings/ipaddress/__init__.h
new file mode 100644
index 000000000..a1c31775f
--- /dev/null
+++ b/shared-bindings/ipaddress/__init__.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_IPADDRESS___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS___INIT___H
+
+#include "shared-module/ipaddress/__init__.h"
+
+bool ipaddress_parse_ipv4address(const char* ip_str, size_t len, uint32_t* ip_out);
+
+mp_obj_t common_hal_ipaddress_new_ipv4address(uint32_t value);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_IPADDRESS___INIT___H
diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c
index c00b1e314..2e58bdcc2 100644
--- a/shared-bindings/microcontroller/__init__.c
+++ b/shared-bindings/microcontroller/__init__.c
@@ -47,6 +47,9 @@
//| The `microcontroller` module defines the pins from the perspective of the
//| microcontroller. See `board` for board-specific pin mappings."""
//|
+//| from nvm import ByteArray
+//| from watchdog import WatchDogTimer
+//|
//| cpu: Processor
//| """CPU information and control, such as ``cpu.temperature`` and ``cpu.frequency``
@@ -133,14 +136,14 @@ STATIC mp_obj_t mcu_reset(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
-//| nvm: Optional[nvm.ByteArray]
+//| nvm: Optional[ByteArray]
//| """Available non-volatile memory.
//| This object is the sole instance of `nvm.ByteArray` when available or ``None`` otherwise.
//|
//| :type: nvm.ByteArray or None"""
//|
-//| watchdog: Optional[watchdog.WatchDogTimer]
+//| watchdog: Optional[WatchDogTimer]
//| """Available watchdog timer.
//| This object is the sole instance of `watchdog.WatchDogTimer` when available or ``None`` otherwise."""
//|
diff --git a/shared-bindings/multiterminal/__init__.c b/shared-bindings/multiterminal/__init__.c
index 1fbeca79c..689d3d761 100644
--- a/shared-bindings/multiterminal/__init__.c
+++ b/shared-bindings/multiterminal/__init__.c
@@ -78,7 +78,7 @@ STATIC mp_obj_t multiterminal_obj_clear_secondary_terminal() {
}
MP_DEFINE_CONST_FUN_OBJ_0(multiterminal_clear_secondary_terminal_obj, multiterminal_obj_clear_secondary_terminal);
-//| def schedule_secondary_terminal_read(socket: secondary_terminal) -> None:
+//| def schedule_secondary_terminal_read(socket: socket.socket) -> None:
//| """In cases where the underlying OS is doing task scheduling, this notifies
//| the OS when more data is available on the socket to read. This is useful
//| as a callback for lwip sockets."""
diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c
index 8eb426c2b..a353e34ae 100644
--- a/shared-bindings/neopixel_write/__init__.c
+++ b/shared-bindings/neopixel_write/__init__.c
@@ -53,8 +53,8 @@
//| def neopixel_write(digitalinout: digitalio.DigitalInOut, buf: ReadableBuffer) -> None:
//| """Write buf out on the given DigitalInOut.
//|
-//| :param digitalinout: the DigitalInOut to output with
-//| :param buf: The bytes to clock out. No assumption is made about color order"""
+//| :param ~digitalio.DigitalInOut digitalinout: the DigitalInOut to output with
+//| :param ~_typing.ReadableBuffer buf: The bytes to clock out. No assumption is made about color order"""
//| ...
STATIC mp_obj_t neopixel_write_neopixel_write_(mp_obj_t digitalinout_obj, mp_obj_t buf) {
if (!MP_OBJ_IS_TYPE(digitalinout_obj, &digitalio_digitalinout_type)) {
diff --git a/shared-bindings/network/__init__.c b/shared-bindings/network/__init__.c
index 35bbaa510..cfcadd98f 100644
--- a/shared-bindings/network/__init__.c
+++ b/shared-bindings/network/__init__.c
@@ -47,7 +47,7 @@
//| It is used by the 'socket' module to look up a suitable
//| NIC when a socket is created."""
//|
-//| def route() -> list:
+//| def route() -> List[object]:
//| """Returns a list of all configured NICs."""
//| ...
//|
diff --git a/shared-bindings/nvm/ByteArray.c b/shared-bindings/nvm/ByteArray.c
index 994ce7045..bed15c9ed 100644
--- a/shared-bindings/nvm/ByteArray.c
+++ b/shared-bindings/nvm/ByteArray.c
@@ -73,12 +73,14 @@ STATIC MP_DEFINE_CONST_DICT(nvm_bytearray_locals_dict, nvm_bytearray_locals_dict
//| @overload
//| def __getitem__(self, index: slice) -> bytearray: ...
+//| @overload
//| def __getitem__(self, index: int) -> int:
//| """Returns the value at the given index."""
//| ...
//|
//| @overload
//| def __setitem__(self, index: slice, value: ReadableBuffer) -> None: ...
+//| @overload
//| def __setitem__(self, index: int, value: int) -> None:
//| """Set the value at the given index."""
//| ...
diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c
index 2406dbc37..c499df972 100644
--- a/shared-bindings/os/__init__.c
+++ b/shared-bindings/os/__init__.c
@@ -43,12 +43,22 @@
//| code written in CircuitPython will work in CPython but not necessarily the
//| other way around."""
//|
+//| import typing
-//| def uname() -> tuple:
+//| def uname() -> _Uname:
//| """Returns a named tuple of operating specific and CircuitPython port
//| specific information."""
//| ...
//|
+//| class _Uname(typing.NamedTuple):
+//| """The type of values that :py:func:`.uname()` returns"""
+//|
+//| sysname: str
+//| nodename: str
+//| release: str
+//| version: str
+//| machine: str
+//|
STATIC mp_obj_t os_uname(void) {
return common_hal_os_uname();
}
@@ -134,7 +144,7 @@ mp_obj_t os_rmdir(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir);
-//| def stat(path: str) -> str:
+//| def stat(path: str) -> Tuple[int, int, int, int, int, int, int, int, int, int]:
//| """Get the status of a file or directory.
//|
//| .. note:: On builds without long integers, the number of seconds
diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c
index 15731ea40..0977e08ff 100644
--- a/shared-bindings/ps2io/Ps2.c
+++ b/shared-bindings/ps2io/Ps2.c
@@ -133,7 +133,7 @@ STATIC mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) {
int b = common_hal_ps2io_ps2_popleft(self);
if (b < 0) {
- mp_raise_IndexError(translate("Pop from an empty Ps2 buffer"));
+ mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_Ps2_space_buffer);
}
return MP_OBJ_NEW_SMALL_INT(b);
}
diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c
index 3d35f0544..2b787df4f 100644
--- a/shared-bindings/pulseio/PulseOut.c
+++ b/shared-bindings/pulseio/PulseOut.c
@@ -32,7 +32,7 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/pulseio/PulseOut.h"
-#include "shared-bindings/pulseio/PWMOut.h"
+#include "shared-bindings/pwmio/PWMOut.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
@@ -41,19 +41,20 @@
//| pulsed signal consists of timed on and off periods. Unlike PWM, there is no set duration
//| for on and off pairs."""
//|
-//| def __init__(self, carrier: PWMOut) -> None:
+//| def __init__(self, carrier: pwmio.PWMOut) -> None:
//| """Create a PulseOut object associated with the given PWMout object.
//|
-//| :param ~pulseio.PWMOut carrier: PWMOut that is set to output on the desired pin.
+//| :param ~pwmio.PWMOut carrier: PWMOut that is set to output on the desired pin.
//|
//| Send a short series of pulses::
//|
//| import array
//| import pulseio
+//| import pwmio
//| import board
//|
//| # 50% duty cycle at 38kHz.
-//| pwm = pulseio.PWMOut(board.D13, frequency=38000, duty_cycle=32768)
+//| pwm = pwmio.PWMOut(board.D13, frequency=38000, duty_cycle=32768)
//| pulse = pulseio.PulseOut(pwm)
//| # on off on off on
//| pulses = array.array('H', [65000, 1000, 65000, 65000, 1000])
@@ -64,20 +65,28 @@
//| pulse.send(pulses)"""
//| ...
//|
-STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- mp_arg_check_num(n_args, kw_args, 1, 1, false);
- mp_obj_t carrier_obj = args[0];
-
- if (!MP_OBJ_IS_TYPE(carrier_obj, &pulseio_pwmout_type)) {
- mp_raise_TypeError_varg(translate("Expected a %q"), pulseio_pwmout_type.name);
- }
-
- // create Pulse object from the given pin
+STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
self->base.type = &pulseio_pulseout_type;
- common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj));
-
+ mp_obj_t carrier_obj = pos_args[0];
+ if (MP_OBJ_IS_TYPE(carrier_obj, &pwmio_pwmout_type)) {
+ // Use a PWMOut Carrier
+ mp_arg_check_num(n_args, kw_args, 1, 1, false);
+ common_hal_pulseio_pulseout_construct(self, (pwmio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj), NULL, 0, 0);
+ } else {
+ // Use a Pin, frequency, and duty cycle
+ enum { ARG_pin, ARG_frequency};
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 38000} },
+ { MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1<<15} },
+ };
+ 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);
+ const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
+ common_hal_pulseio_pulseout_construct(self, NULL, pin, args[ARG_frequency].u_int, args[ARG_frequency].u_int);
+ }
return MP_OBJ_FROM_PTR(self);
}
diff --git a/shared-bindings/pulseio/PulseOut.h b/shared-bindings/pulseio/PulseOut.h
index 390910ff6..49dc555fe 100644
--- a/shared-bindings/pulseio/PulseOut.h
+++ b/shared-bindings/pulseio/PulseOut.h
@@ -29,12 +29,16 @@
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/pulseio/PulseOut.h"
-#include "common-hal/pulseio/PWMOut.h"
+#include "common-hal/pwmio/PWMOut.h"
extern const mp_obj_type_t pulseio_pulseout_type;
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
- const pulseio_pwmout_obj_t* carrier);
+ const pwmio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle);
+
extern void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self);
extern bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self);
extern void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self,
diff --git a/shared-bindings/pulseio/__init__.c b/shared-bindings/pulseio/__init__.c
index 87946e5f0..bfe9635f0 100644
--- a/shared-bindings/pulseio/__init__.c
+++ b/shared-bindings/pulseio/__init__.c
@@ -33,40 +33,29 @@
#include "shared-bindings/pulseio/__init__.h"
#include "shared-bindings/pulseio/PulseIn.h"
#include "shared-bindings/pulseio/PulseOut.h"
-#include "shared-bindings/pulseio/PWMOut.h"
+#include "shared-bindings/pwmio/PWMOut.h"
-//| """Support for pulse based protocols
+//| """Support for individual pulse based protocols
//|
//| The `pulseio` module contains classes to provide access to basic pulse IO.
+//| Individual pulses are commonly used in infrared remotes and in DHT
+//| temperature sensors.
+//|
+//|
+//| .. warning:: PWMOut is moving to `pwmio` and will be removed from `pulseio`
+//| in CircuitPython 7.
//|
-
//| All classes change hardware state and should be deinitialized when they
//| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
-//|
-//| For example::
-//|
-//| import pulseio
-//| import time
-//| from board import *
-//|
-//| pwm = pulseio.PWMOut(D13)
-//| pwm.duty_cycle = 2 ** 15
-//| time.sleep(0.1)
-//|
-//| This example will initialize the the device, set
-//| :py:data:`~pulseio.PWMOut.duty_cycle`, and then sleep 0.1 seconds.
-//| CircuitPython will automatically turn off the PWM when it resets all
-//| hardware after program completion. Use ``deinit()`` or a ``with`` statement
-//| to do it yourself."""
+//| :ref:`lifetime-and-contextmanagers` for more info."""
//|
STATIC const mp_rom_map_elem_t pulseio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pulseio) },
{ MP_ROM_QSTR(MP_QSTR_PulseIn), MP_ROM_PTR(&pulseio_pulsein_type) },
{ MP_ROM_QSTR(MP_QSTR_PulseOut), MP_ROM_PTR(&pulseio_pulseout_type) },
- { MP_ROM_QSTR(MP_QSTR_PWMOut), MP_ROM_PTR(&pulseio_pwmout_type) },
+ { MP_ROM_QSTR(MP_QSTR_PWMOut), MP_ROM_PTR(&pwmio_pwmout_type) },
};
STATIC MP_DEFINE_CONST_DICT(pulseio_module_globals, pulseio_module_globals_table);
diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pwmio/PWMOut.c
index e9b6c45d2..da0755592 100644
--- a/shared-bindings/pulseio/PWMOut.c
+++ b/shared-bindings/pwmio/PWMOut.c
@@ -31,7 +31,7 @@
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
-#include "shared-bindings/pulseio/PWMOut.h"
+#include "shared-bindings/pwmio/PWMOut.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
@@ -55,33 +55,33 @@
//|
//| Simple LED fade::
//|
-//| import pulseio
+//| import pwmio
//| import board
//|
-//| pwm = pulseio.PWMOut(board.D13) # output on D13
+//| pwm = pwmio.PWMOut(board.D13) # output on D13
//| pwm.duty_cycle = 2 ** 15 # Cycles the pin with 50% duty cycle (half of 2 ** 16) at the default 500hz
//|
//| PWM at specific frequency (servos and motors)::
//|
-//| import pulseio
+//| import pwmio
//| import board
//|
-//| pwm = pulseio.PWMOut(board.D13, frequency=50)
+//| pwm = pwmio.PWMOut(board.D13, frequency=50)
//| pwm.duty_cycle = 2 ** 15 # Cycles the pin with 50% duty cycle (half of 2 ** 16) at 50hz
//|
//| Variable frequency (usually tones)::
//|
-//| import pulseio
+//| import pwmio
//| import board
//| import time
//|
-//| pwm = pulseio.PWMOut(board.D13, duty_cycle=2 ** 15, frequency=440, variable_frequency=True)
+//| pwm = pwmio.PWMOut(board.D13, duty_cycle=2 ** 15, frequency=440, variable_frequency=True)
//| time.sleep(0.2)
//| pwm.frequency = 880
//| time.sleep(0.1)"""
//| ...
//|
-STATIC mp_obj_t pulseio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+STATIC mp_obj_t pwmio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
enum { ARG_pin, ARG_duty_cycle, ARG_frequency, ARG_variable_frequency };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ, },
@@ -99,9 +99,9 @@ STATIC mp_obj_t pulseio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args
bool variable_frequency = parsed_args[ARG_variable_frequency].u_bool;
// create PWM object from the given pin
- pulseio_pwmout_obj_t *self = m_new_obj(pulseio_pwmout_obj_t);
- self->base.type = &pulseio_pwmout_type;
- pwmout_result_t result = common_hal_pulseio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency);
+ pwmio_pwmout_obj_t *self = m_new_obj(pwmio_pwmout_obj_t);
+ self->base.type = &pwmio_pwmout_type;
+ pwmout_result_t result = common_hal_pwmio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency);
if (result == PWMOUT_INVALID_PIN) {
mp_raise_ValueError(translate("Invalid pin"));
} else if (result == PWMOUT_INVALID_FREQUENCY) {
@@ -119,15 +119,15 @@ STATIC mp_obj_t pulseio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args
//| """Deinitialises the PWMOut and releases any hardware resources for reuse."""
//| ...
//|
-STATIC mp_obj_t pulseio_pwmout_deinit(mp_obj_t self_in) {
- pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- common_hal_pulseio_pwmout_deinit(self);
+STATIC mp_obj_t pwmio_pwmout_deinit(mp_obj_t self_in) {
+ pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_pwmio_pwmout_deinit(self);
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pwmout_deinit_obj, pulseio_pwmout_deinit);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pwmio_pwmout_deinit_obj, pwmio_pwmout_deinit);
-STATIC void check_for_deinit(pulseio_pwmout_obj_t *self) {
- if (common_hal_pulseio_pwmout_deinited(self)) {
+STATIC void check_for_deinit(pwmio_pwmout_obj_t *self) {
+ if (common_hal_pwmio_pwmout_deinited(self)) {
raise_deinited_error();
}
}
@@ -143,12 +143,12 @@ STATIC void check_for_deinit(pulseio_pwmout_obj_t *self) {
//| :ref:`lifetime-and-contextmanagers` for more info."""
//| ...
//|
-STATIC mp_obj_t pulseio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t pwmio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
- common_hal_pulseio_pwmout_deinit(args[0]);
+ common_hal_pwmio_pwmout_deinit(args[0]);
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pwmout___exit___obj, 4, 4, pulseio_pwmout_obj___exit__);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pwmio_pwmout___exit___obj, 4, 4, pwmio_pwmout_obj___exit__);
//| duty_cycle: int
//| """16 bit value that dictates how much of one cycle is high (1) versus low
@@ -160,29 +160,29 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pwmout___exit___obj, 4, 4, pu
//| Reading this property will return the value from the internal representation,
//| so it may differ from the value set."""
//|
-STATIC mp_obj_t pulseio_pwmout_obj_get_duty_cycle(mp_obj_t self_in) {
- pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC mp_obj_t pwmio_pwmout_obj_get_duty_cycle(mp_obj_t self_in) {
+ pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
- return MP_OBJ_NEW_SMALL_INT(common_hal_pulseio_pwmout_get_duty_cycle(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_pwmio_pwmout_get_duty_cycle(self));
}
-MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pwmout_get_duty_cycle_obj, pulseio_pwmout_obj_get_duty_cycle);
+MP_DEFINE_CONST_FUN_OBJ_1(pwmio_pwmout_get_duty_cycle_obj, pwmio_pwmout_obj_get_duty_cycle);
-STATIC mp_obj_t pulseio_pwmout_obj_set_duty_cycle(mp_obj_t self_in, mp_obj_t duty_cycle) {
- pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC mp_obj_t pwmio_pwmout_obj_set_duty_cycle(mp_obj_t self_in, mp_obj_t duty_cycle) {
+ pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
mp_int_t duty = mp_obj_get_int(duty_cycle);
if (duty < 0 || duty > 0xffff) {
mp_raise_ValueError(translate("PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)"));
}
- common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
+ common_hal_pwmio_pwmout_set_duty_cycle(self, duty);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_2(pulseio_pwmout_set_duty_cycle_obj, pulseio_pwmout_obj_set_duty_cycle);
+MP_DEFINE_CONST_FUN_OBJ_2(pwmio_pwmout_set_duty_cycle_obj, pwmio_pwmout_obj_set_duty_cycle);
-const mp_obj_property_t pulseio_pwmout_duty_cycle_obj = {
+const mp_obj_property_t pwmio_pwmout_duty_cycle_obj = {
.base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&pulseio_pwmout_get_duty_cycle_obj,
- (mp_obj_t)&pulseio_pwmout_set_duty_cycle_obj,
+ .proxy = {(mp_obj_t)&pwmio_pwmout_get_duty_cycle_obj,
+ (mp_obj_t)&pwmio_pwmout_set_duty_cycle_obj,
(mp_obj_t)&mp_const_none_obj},
};
@@ -196,50 +196,50 @@ const mp_obj_property_t pulseio_pwmout_duty_cycle_obj = {
//| from the original duty cycle value. This should happen without any need
//| to manually re-set the duty cycle."""
//|
-STATIC mp_obj_t pulseio_pwmout_obj_get_frequency(mp_obj_t self_in) {
- pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC mp_obj_t pwmio_pwmout_obj_get_frequency(mp_obj_t self_in) {
+ pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
- return MP_OBJ_NEW_SMALL_INT(common_hal_pulseio_pwmout_get_frequency(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_pwmio_pwmout_get_frequency(self));
}
-MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pwmout_get_frequency_obj, pulseio_pwmout_obj_get_frequency);
+MP_DEFINE_CONST_FUN_OBJ_1(pwmio_pwmout_get_frequency_obj, pwmio_pwmout_obj_get_frequency);
-STATIC mp_obj_t pulseio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t frequency) {
- pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC mp_obj_t pwmio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t frequency) {
+ pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
- if (!common_hal_pulseio_pwmout_get_variable_frequency(self)) {
+ if (!common_hal_pwmio_pwmout_get_variable_frequency(self)) {
mp_raise_AttributeError(translate(
"PWM frequency not writable when variable_frequency is False on "
"construction."));
}
- common_hal_pulseio_pwmout_set_frequency(self, mp_obj_get_int(frequency));
+ common_hal_pwmio_pwmout_set_frequency(self, mp_obj_get_int(frequency));
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_2(pulseio_pwmout_set_frequency_obj, pulseio_pwmout_obj_set_frequency);
+MP_DEFINE_CONST_FUN_OBJ_2(pwmio_pwmout_set_frequency_obj, pwmio_pwmout_obj_set_frequency);
-const mp_obj_property_t pulseio_pwmout_frequency_obj = {
+const mp_obj_property_t pwmio_pwmout_frequency_obj = {
.base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&pulseio_pwmout_get_frequency_obj,
- (mp_obj_t)&pulseio_pwmout_set_frequency_obj,
+ .proxy = {(mp_obj_t)&pwmio_pwmout_get_frequency_obj,
+ (mp_obj_t)&pwmio_pwmout_set_frequency_obj,
(mp_obj_t)&mp_const_none_obj},
};
-STATIC const mp_rom_map_elem_t pulseio_pwmout_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pwmio_pwmout_locals_dict_table[] = {
// Methods
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pulseio_pwmout_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pwmio_pwmout_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
- { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pulseio_pwmout___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pwmio_pwmout___exit___obj) },
// Properties
- { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&pulseio_pwmout_duty_cycle_obj) },
- { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&pulseio_pwmout_frequency_obj) },
+ { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&pwmio_pwmout_duty_cycle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&pwmio_pwmout_frequency_obj) },
// TODO(tannewt): Add enabled to determine whether the signal is output
// without giving up the resources. Useful for IR output.
};
-STATIC MP_DEFINE_CONST_DICT(pulseio_pwmout_locals_dict, pulseio_pwmout_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(pwmio_pwmout_locals_dict, pwmio_pwmout_locals_dict_table);
-const mp_obj_type_t pulseio_pwmout_type = {
+const mp_obj_type_t pwmio_pwmout_type = {
{ &mp_type_type },
.name = MP_QSTR_PWMOut,
- .make_new = pulseio_pwmout_make_new,
- .locals_dict = (mp_obj_dict_t*)&pulseio_pwmout_locals_dict,
+ .make_new = pwmio_pwmout_make_new,
+ .locals_dict = (mp_obj_dict_t*)&pwmio_pwmout_locals_dict,
};
diff --git a/shared-bindings/pulseio/PWMOut.h b/shared-bindings/pwmio/PWMOut.h
index c72278e0e..1a99914ea 100644
--- a/shared-bindings/pulseio/PWMOut.h
+++ b/shared-bindings/pwmio/PWMOut.h
@@ -24,13 +24,13 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_PULSEIO_PWMOUT_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_PULSEIO_PWMOUT_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO_PWMOUT_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO_PWMOUT_H
#include "common-hal/microcontroller/Pin.h"
-#include "common-hal/pulseio/PWMOut.h"
+#include "common-hal/pwmio/PWMOut.h"
-extern const mp_obj_type_t pulseio_pwmout_type;
+extern const mp_obj_type_t pwmio_pwmout_type;
typedef enum {
PWMOUT_OK,
@@ -40,19 +40,19 @@ typedef enum {
PWMOUT_ALL_TIMERS_IN_USE
} pwmout_result_t;
-extern pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
+extern pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
const mcu_pin_obj_t* pin, uint16_t duty, uint32_t frequency,
bool variable_frequency);
-extern void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self);
-extern bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self);
-extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty);
-extern uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self);
-extern void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency);
-extern uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self);
-extern bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self);
+extern void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self);
+extern bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t* self);
+extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t* self, uint16_t duty);
+extern uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t* self);
+extern void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t frequency);
+extern uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t* self);
+extern bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t* self);
// This is used by the supervisor to claim PWMOut devices indefinitely.
-extern void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self);
-extern void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self);
+extern void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self);
+extern void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PULSEIO_PWMOUT_H
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO_PWMOUT_H
diff --git a/shared-bindings/pwmio/__init__.c b/shared-bindings/pwmio/__init__.c
new file mode 100644
index 000000000..a51383703
--- /dev/null
+++ b/shared-bindings/pwmio/__init__.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft 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 "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/pwmio/__init__.h"
+#include "shared-bindings/pwmio/PWMOut.h"
+
+//| """Support for PWM based protocols
+//|
+//| The `pwmio` module contains classes to provide access to basic pulse IO.
+//|
+
+//| All classes change hardware state and should be deinitialized when they
+//| are no longer needed if the program continues after use. To do so, either
+//| call :py:meth:`!deinit` or use a context manager. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+//| For example::
+//|
+//| import pwmio
+//| import time
+//| from board import *
+//|
+//| pwm = pwmio.PWMOut(D13)
+//| pwm.duty_cycle = 2 ** 15
+//| time.sleep(0.1)
+//|
+//| This example will initialize the the device, set
+//| :py:data:`~pwmio.PWMOut.duty_cycle`, and then sleep 0.1 seconds.
+//| CircuitPython will automatically turn off the PWM when it resets all
+//| hardware after program completion. Use ``deinit()`` or a ``with`` statement
+//| to do it yourself."""
+//|
+
+STATIC const mp_rom_map_elem_t pwmio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pwmio) },
+ { MP_ROM_QSTR(MP_QSTR_PWMOut), MP_ROM_PTR(&pwmio_pwmout_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(pwmio_module_globals, pwmio_module_globals_table);
+
+const mp_obj_module_t pwmio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&pwmio_module_globals,
+};
diff --git a/shared-bindings/pwmio/__init__.h b/shared-bindings/pwmio/__init__.h
new file mode 100644
index 000000000..93c70377d
--- /dev/null
+++ b/shared-bindings/pwmio/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * 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_PWMIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO___INIT___H
diff --git a/shared-bindings/rgbmatrix/RGBMatrix.c b/shared-bindings/rgbmatrix/RGBMatrix.c
index b2dd80682..e4683af92 100644
--- a/shared-bindings/rgbmatrix/RGBMatrix.c
+++ b/shared-bindings/rgbmatrix/RGBMatrix.c
@@ -128,7 +128,7 @@ STATIC void preflight_pins_or_throw(uint8_t clock_pin, uint8_t *rgb_pins, uint8_
}
}
-//| def __init__(self, *, width: int, bit_depth: int, rgb_pins: Sequence[digitalio.DigitalInOut], addr_pins: List[digitalio.DigitalInOut], clock_pin: digitalio.DigitalInOut, latch_pin: digitalio.DigitalInOut, output_enable_pin: digitalio.DigitalInOut, doublebuffer: bool = True, framebuffer: Optional[WriteableBuffer] = None, height: int = 0) -> None:
+//| def __init__(self, *, width: int, bit_depth: int, rgb_pins: Sequence[digitalio.DigitalInOut], addr_pins: Sequence[digitalio.DigitalInOut], clock_pin: digitalio.DigitalInOut, latch_pin: digitalio.DigitalInOut, output_enable_pin: digitalio.DigitalInOut, doublebuffer: bool = True, framebuffer: Optional[WriteableBuffer] = None, height: int = 0) -> None:
//| """Create a RGBMatrix object with the given attributes. The height of
//| the display is determined by the number of rgb and address pins:
//| len(rgb_pins) // 3 * 2 ** len(address_pins). With 6 RGB pins and 4
@@ -252,7 +252,7 @@ STATIC mp_obj_t rgbmatrix_rgbmatrix_deinit(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(rgbmatrix_rgbmatrix_deinit_obj, rgbmatrix_rgbmatrix_deinit);
static void check_for_deinit(rgbmatrix_rgbmatrix_obj_t *self) {
- if (!self->core.rgbPins) {
+ if (!self->protomatter.rgbPins) {
raise_deinited_error();
}
}
@@ -352,7 +352,8 @@ STATIC void rgbmatrix_rgbmatrix_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *
// These version exists so that the prototype matches the protocol,
// avoiding a type cast that can hide errors
-STATIC void rgbmatrix_rgbmatrix_swapbuffers(mp_obj_t self_in) {
+STATIC void rgbmatrix_rgbmatrix_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmap) {
+ (void)dirty_row_bitmap;
common_hal_rgbmatrix_rgbmatrix_refresh(self_in);
}
diff --git a/shared-bindings/rgbmatrix/RGBMatrix.h b/shared-bindings/rgbmatrix/RGBMatrix.h
index 027f817bb..1dc5a406c 100644
--- a/shared-bindings/rgbmatrix/RGBMatrix.h
+++ b/shared-bindings/rgbmatrix/RGBMatrix.h
@@ -24,29 +24,12 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_RGBMATRIX_RGBMATRIX_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_RGBMATRIX_RGBMATRIX_H
+#pragma once
#include "shared-module/rgbmatrix/RGBMatrix.h"
#include "lib/protomatter/core.h"
extern const mp_obj_type_t rgbmatrix_RGBMatrix_type;
-typedef struct {
- mp_obj_base_t base;
- mp_obj_t framebuffer;
- mp_buffer_info_t bufinfo;
- Protomatter_core core;
- void *timer;
- uint16_t bufsize, width;
- uint8_t rgb_pins[30];
- uint8_t addr_pins[10];
- uint8_t clock_pin, latch_pin, oe_pin;
- uint8_t rgb_count, addr_count;
- uint8_t bit_depth;
- bool core_is_initialized;
- bool paused;
- bool doublebuffer;
-} rgbmatrix_rgbmatrix_obj_t;
void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t* self, int width, int bit_depth, uint8_t rgb_count, uint8_t* rgb_pins, uint8_t addr_count, uint8_t* addr_pins, uint8_t clock_pin, uint8_t latch_pin, uint8_t oe_pin, bool doublebuffer, mp_obj_t framebuffer, void* timer);
void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t*);
@@ -57,5 +40,3 @@ bool common_hal_rgbmatrix_rgbmatrix_get_paused(rgbmatrix_rgbmatrix_obj_t* self);
void common_hal_rgbmatrix_rgbmatrix_refresh(rgbmatrix_rgbmatrix_obj_t* self);
int common_hal_rgbmatrix_rgbmatrix_get_width(rgbmatrix_rgbmatrix_obj_t* self);
int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self);
-
-#endif
diff --git a/shared-bindings/rotaryio/__init__.c b/shared-bindings/rotaryio/__init__.c
index 0fa457ca7..fd8578753 100644
--- a/shared-bindings/rotaryio/__init__.c
+++ b/shared-bindings/rotaryio/__init__.c
@@ -38,10 +38,9 @@
//| The `rotaryio` module contains classes to read different rotation encoding schemes. See
//| `Wikipedia's Rotary Encoder page <https://en.wikipedia.org/wiki/Rotary_encoder>`_ for more
//| background.
-
+//|
//| .. warning:: This module is not available in some SAMD21 (aka M0) builds. See the :ref:`module-support-matrix` for more info.
//|
-
//| All classes change hardware state and should be deinitialized when they
//| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See
diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c
index a0582d143..975f8b095 100644
--- a/shared-bindings/sdcardio/SDCard.c
+++ b/shared-bindings/sdcardio/SDCard.c
@@ -125,7 +125,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit);
//| """Read one or more blocks from the card
//|
//| :param int start_block: The block to start reading from
-//| :param bytearray buf: The buffer to write into. Length must be multiple of 512.
+//| :param ~_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512.
//|
//| :return: None"""
//|
@@ -149,7 +149,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, sdcardio_sdcard_readbl
//| """Write one or more blocks to the card
//|
//| :param int start_block: The block to start writing from
-//| :param bytearray buf: The buffer to read from. Length must be multiple of 512.
+//| :param ~_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512.
//|
//| :return: None"""
//|
diff --git a/shared-bindings/sdioio/SDCard.c b/shared-bindings/sdioio/SDCard.c
index 594fa71ff..aba414cd6 100644
--- a/shared-bindings/sdioio/SDCard.c
+++ b/shared-bindings/sdioio/SDCard.c
@@ -165,7 +165,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_count_obj, sdioio_sdcard_count);
//| """Read one or more blocks from the card
//|
//| :param int start_block: The block to start reading from
-//| :param bytearray buf: The buffer to write into. Length must be multiple of 512.
+//| :param ~_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512.
//|
//| :return: None"""
mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
@@ -182,12 +182,12 @@ mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks);
-//| def writeblocks(self, start_block: int, buf: WriteableBuffer) -> None:
+//| def writeblocks(self, start_block: int, buf: ReadableBuffer) -> None:
//|
//| """Write one or more blocks to the card
//|
//| :param int start_block: The block to start writing from
-//| :param bytearray buf: The buffer to read from. Length must be multiple of 512.
+//| :param ~_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512.
//|
//| :return: None"""
//|
diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c
new file mode 100644
index 000000000..e8f4e970a
--- /dev/null
+++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 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/objarray.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
+
+STATIC mp_obj_t sharpdisplay_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_spi_bus, ARG_chip_select, ARG_width, ARG_height, ARG_baudrate, NUM_ARGS };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_spi_bus, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_chip_select, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
+ { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
+ { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 2000000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
+
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mcu_pin_obj_t *chip_select = validate_obj_is_free_pin(args[ARG_chip_select].u_obj);
+ busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi_bus].u_obj);
+
+ sharpdisplay_framebuffer_obj_t* self = &allocate_display_bus_or_raise()->sharpdisplay;
+ self->base.type = &sharpdisplay_framebuffer_type;
+
+ common_hal_sharpdisplay_framebuffer_construct(self, spi, chip_select, args[ARG_baudrate].u_int, args[ARG_width].u_int, args[ARG_height].u_int);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+
+STATIC mp_int_t sharpdisplay_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
+ sharpdisplay_framebuffer_obj_t *self = (sharpdisplay_framebuffer_obj_t*)self_in;
+ // a readonly framebuffer would be unusual but not impossible
+ if ((flags & MP_BUFFER_WRITE) && !(self->bufinfo.typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) {
+ return 1;
+ }
+ *bufinfo = self->bufinfo;
+ return 0;
+}
+
+STATIC mp_obj_t sharpdisplay_framebuffer_deinit(mp_obj_t self_in) {
+ sharpdisplay_framebuffer_obj_t *self = (sharpdisplay_framebuffer_obj_t*)self_in;
+ common_hal_sharpdisplay_framebuffer_deinit(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(sharpdisplay_framebuffer_deinit_obj, sharpdisplay_framebuffer_deinit);
+
+STATIC const mp_rom_map_elem_t sharpdisplay_framebuffer_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sharpdisplay_framebuffer_deinit_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(sharpdisplay_framebuffer_locals_dict, sharpdisplay_framebuffer_locals_dict_table);
+
+const mp_obj_type_t sharpdisplay_framebuffer_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SharpMemoryFramebuffer,
+ .buffer_p = { .get_buffer = sharpdisplay_framebuffer_get_buffer, },
+ .make_new = sharpdisplay_framebuffer_make_new,
+ .protocol = &sharpdisplay_framebuffer_proto,
+ .locals_dict = (mp_obj_dict_t*)&sharpdisplay_framebuffer_locals_dict,
+};
diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h
new file mode 100644
index 000000000..30f1b867b
--- /dev/null
+++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 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.
+ */
+
+#pragma once
+
+// #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h"
+// #include "shared-module/framebufferio/FramebufferDisplay.h"
+
+#include "py/objtype.h"
+
+extern const mp_obj_type_t sharpdisplay_framebuffer_type;
diff --git a/shared-bindings/sharpdisplay/__init__.c b/shared-bindings/sharpdisplay/__init__.c
new file mode 100644
index 000000000..d1f728c61
--- /dev/null
+++ b/shared-bindings/sharpdisplay/__init__.c
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 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 <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h"
+
+//| """Support for Sharp Memory Display framebuffers"""
+//|
+
+STATIC const mp_rom_map_elem_t sharpdisplay_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sharpdisplay) },
+ { MP_ROM_QSTR(MP_QSTR_SharpMemoryFramebuffer), MP_ROM_PTR(&sharpdisplay_framebuffer_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(sharpdisplay_module_globals, sharpdisplay_module_globals_table);
+
+const mp_obj_module_t sharpdisplay_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&sharpdisplay_module_globals,
+};
diff --git a/shared-bindings/sharpdisplay/__init__.h b/shared-bindings/sharpdisplay/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-bindings/sharpdisplay/__init__.h
diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c
index 53ac57d11..38840da5e 100644
--- a/shared-bindings/socket/__init__.c
+++ b/shared-bindings/socket/__init__.c
@@ -52,11 +52,17 @@ STATIC const mp_obj_type_t socket_type;
//| def __init__(self, family: int, type: int, proto: int) -> None:
//| """Create a new socket
//|
-//| :param ~int family: AF_INET or AF_INET6
-//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
-//| :param ~int proto: IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW (ignored)"""
+//| :param int family: AF_INET or AF_INET6
+//| :param int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
+//| :param int proto: IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW (ignored)"""
//| ...
//|
+//| AF_INET: int
+//| AF_INET6: int
+//| SOCK_STREAM: int
+//| SOCK_DGRAM: int
+//| SOCK_RAW: int
+//|
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 0, 4, false);
@@ -96,10 +102,11 @@ STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
}
}
-//| def bind(self, address: tuple) -> None:
+//| def bind(self, address: Tuple[str, int]) -> None:
//| """Bind a socket to an address
//|
-//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| :param address: tuple of (remote_address, remote_port)
+//| :type address: tuple(str, int)"""
//| ...
//|
@@ -126,7 +133,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
//| def listen(self, backlog: int) -> None:
//| """Set socket to listen for incoming connections
//|
-//| :param ~int backlog: length of backlog queue for waiting connetions"""
+//| :param int backlog: length of backlog queue for waiting connetions"""
//| ...
//|
@@ -148,7 +155,7 @@ STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
-//| def accept(self) -> tuple:
+//| def accept(self) -> Tuple[socket, str]:
//| """Accept a connection on a listening socket of type SOCK_STREAM,
//| creating a new socket of type SOCK_STREAM.
//| Returns a tuple of (new_socket, remote_address)"""
@@ -185,10 +192,11 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
-//| def connect(self, address: tuple) -> None:
+//| def connect(self, address: Tuple[str, int]) -> None:
//| """Connect a socket to a remote address
//|
-//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| :param address: tuple of (remote_address, remote_port)
+//| :type address: tuple(str, int)"""
//| ...
//|
@@ -216,7 +224,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
//| """Send some bytes to the connected remote address.
//| Suits sockets of type SOCK_STREAM
//|
-//| :param ~bytes bytes: some bytes to send"""
+//| :param ~_typing.ReadableBuffer bytes: some bytes to send"""
//| ...
//|
@@ -259,7 +267,7 @@ STATIC mp_int_t _socket_recv_into(mod_network_socket_obj_t *sock, byte *buf, mp_
//| Suits sockets of type SOCK_STREAM
//| Returns an int of number of bytes read.
//|
-//| :param bytearray buffer: buffer to receive into
+//| :param ~_typing.WriteableBuffer buffer: buffer to receive into
//| :param int bufsize: optionally, a maximum number of bytes to read."""
//| ...
//|
@@ -290,7 +298,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_into_obj, 2, 3, socket_re
//| Suits sockets of type SOCK_STREAM
//| Returns a bytes() of length <= bufsize
//|
-//| :param ~int bufsize: maximum number of bytes to receive"""
+//| :param int bufsize: maximum number of bytes to receive"""
//| ...
//|
@@ -312,12 +320,13 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
-//| def sendto(self, bytes: ReadableBuffer, address: tuple) -> int:
+//| def sendto(self, bytes: ReadableBuffer, address: Tuple[str, int]) -> int:
//| """Send some bytes to a specific address.
//| Suits sockets of type SOCK_DGRAM
//|
-//| :param ~bytes bytes: some bytes to send
-//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| :param ~_typing.ReadableBuffer bytes: some bytes to send
+//| :param address: tuple of (remote_address, remote_port)
+//| :type address: tuple(str, int)"""
//| ...
//|
@@ -346,7 +355,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
-//| def recvfrom(self, bufsize: int) -> Tuple[bytes, tuple]:
+//| def recvfrom(self, bufsize: int) -> Tuple[bytes, Tuple[str, int]]:
//| """Reads some bytes from the connected remote address.
//| Suits sockets of type SOCK_STREAM
//|
@@ -354,7 +363,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
//| * a bytes() of length <= bufsize
//| * a remote_address, which is a tuple of ip address and port number
//|
-//| :param ~int bufsize: maximum number of bytes to receive"""
+//| :param int bufsize: maximum number of bytes to receive"""
//| ...
//|
@@ -422,7 +431,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_s
//| def settimeout(self, value: int) -> None:
//| """Set the timeout value for this socket.
//|
-//| :param ~int value: timeout in seconds. 0 means non-blocking. None means block indefinitely."""
+//| :param int value: timeout in seconds. 0 means non-blocking. None means block indefinitely."""
//| ...
//|
@@ -453,7 +462,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
//| def setblocking(self, flag: bool) -> Optional[int]:
//| """Set the blocking behaviour of this socket.
//|
-//| :param ~bool flag: False means non-blocking, True means block indefinitely."""
+//| :param bool flag: False means non-blocking, True means block indefinitely."""
//| ...
//|
@@ -512,7 +521,7 @@ STATIC const mp_obj_type_t socket_type = {
.locals_dict = (mp_obj_dict_t*)&socket_locals_dict,
};
-//| def getaddrinfo(host: str, port: int) -> tuple:
+//| def getaddrinfo(host: str, port: int) -> Tuple[int, int, int, str, str]:
//| """Gets the address information for a hostname and port
//|
//| Returns the appropriate family, socket type, socket protocol and
diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c
new file mode 100644
index 000000000..e1b1e6967
--- /dev/null
+++ b/shared-bindings/socketpool/Socket.c
@@ -0,0 +1,468 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
+ * 2018 Nick Moore 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 "shared-bindings/socketpool/Socket.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/objtuple.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mperrno.h"
+
+#include "esp_log.h"
+static const char* TAG = "socket binding";
+
+//| class Socket:
+//| """TCP, UDP and RAW socket. Cannot be created directly. Instead, call
+//| `SocketPool.socket()`.
+//|
+//| Provides a subset of CPython's `socket.socket` API. It only implements the versions of
+//| recv that do not allocate bytes objects."""
+//|
+
+//| def __enter__(self) -> Socket:
+//| """No-op used by Context Managers."""
+//| ...
+//|
+// Provided by context manager helper.
+
+//| def __exit__(self) -> None:
+//| """Automatically closes the Socket when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
+//|
+STATIC mp_obj_t socketpool_socket___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_socketpool_socket_close(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket___exit___obj, 4, 4, socketpool_socket___exit__);
+
+// //| def bind(self, address: tuple) -> None:
+// //| """Bind a socket to an address
+// //|
+// //| :param ~tuple address: tuple of (remote_address, remote_port)"""
+// //| ...
+// //|
+
+// STATIC mp_obj_t socketpool_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
+// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+// // // get address
+// // uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+// // mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
+
+// // // check if we need to select a NIC
+// // socket_select_nic(self, ip);
+
+// // // call the NIC to bind the socket
+// // int _errno;
+// // if (self->nic_type->bind(self, ip, port, &_errno) != 0) {
+// // mp_raise_OSError(_errno);
+// // }
+
+// return mp_const_none;
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_bind_obj, socketpool_socket_bind);
+
+// //| def listen(self, backlog: int) -> None:
+// //| """Set socket to listen for incoming connections
+// //|
+// //| :param ~int backlog: length of backlog queue for waiting connetions"""
+// //| ...
+// //|
+
+// STATIC mp_obj_t socketpool_socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
+// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+// // if (self->nic == MP_OBJ_NULL) {
+// // // not connected
+// // // TODO I think we can listen even if not bound...
+// // mp_raise_OSError(MP_ENOTCONN);
+// // }
+
+// // int _errno;
+// // if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) {
+// // mp_raise_OSError(_errno);
+// // }
+
+// return mp_const_none;
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_listen_obj, socketpool_socket_listen);
+
+// //| def accept(self) -> tuple:
+// //| """Accept a connection on a listening socket of type SOCK_STREAM,
+// //| creating a new socket of type SOCK_STREAM.
+// //| Returns a tuple of (new_socket, remote_address)"""
+// //|
+
+// STATIC mp_obj_t socketpool_socket_accept(mp_obj_t self_in) {
+// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+// // // create new socket object
+// // // starts with empty NIC so that finaliser doesn't run close() method if accept() fails
+// // mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+// // socket2->base.type = &socket_type;
+// // socket2->nic = MP_OBJ_NULL;
+// // socket2->nic_type = NULL;
+
+// // // accept incoming connection
+// // uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+// // mp_uint_t port;
+// // int _errno;
+// // if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) {
+// // mp_raise_OSError(_errno);
+// // }
+
+// // // new socket has valid state, so set the NIC to the same as parent
+// // socket2->nic = self->nic;
+// // socket2->nic_type = self->nic_type;
+
+// // // make the return value
+// // mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+// // client->items[0] = MP_OBJ_FROM_PTR(socket2);
+// // client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
+
+// return mp_const_none;
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_accept_obj, socketpool_socket_accept);
+
+//| def close(self) -> None:
+//| """Closes this Socket and makes its resources available to its SocketPool."""
+//|
+STATIC mp_obj_t socketpool_socket_close(mp_obj_t self_in) {
+ socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_socketpool_socket_close(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_close_obj, socketpool_socket_close);
+
+//| def connect(self, address: tuple) -> None:
+//| """Connect a socket to a remote address
+//|
+//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| ...
+//|
+
+STATIC mp_obj_t socketpool_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
+ socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_obj_t *addr_items;
+ mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
+
+ size_t hostlen;
+ const char* host = mp_obj_str_get_data(addr_items[0], &hostlen);
+ mp_int_t port = mp_obj_get_int(addr_items[1]);
+
+ bool ok = common_hal_socketpool_socket_connect(self, host, hostlen, port);
+ if (!ok) {
+ ESP_EARLY_LOGW(TAG, "socket connect failed");
+ mp_raise_OSError(0);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_connect_obj, socketpool_socket_connect);
+
+//| def send(self, bytes: ReadableBuffer) -> int:
+//| """Send some bytes to the connected remote address.
+//| Suits sockets of type SOCK_STREAM
+//|
+//| :param ~bytes bytes: some bytes to send"""
+//| ...
+//|
+
+STATIC mp_obj_t socketpool_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
+ socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (common_hal_socketpool_socket_get_closed(self)) {
+ // Bad file number.
+ mp_raise_OSError(MP_EBADF);
+ }
+ if (!common_hal_socketpool_socket_get_connected(self)) {
+ mp_raise_BrokenPipeError();
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ mp_int_t ret = common_hal_socketpool_socket_send(self, bufinfo.buf, bufinfo.len);
+ if (ret == -1) {
+ mp_raise_BrokenPipeError();
+ }
+ return mp_obj_new_int_from_uint(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_send_obj, socketpool_socket_send);
+
+
+// helper function for socket_recv and socket_recv_into to handle common operations of both
+// STATIC mp_int_t _socket_recv_into(mod_network_socket_obj_t *sock, byte *buf, mp_int_t len) {
+// mp_int_t ret = 0;
+// // int _errno;
+// // mp_int_t ret = sock->nic_type->recv(sock, buf, len, &_errno);
+// // if (ret == -1) {
+// // mp_raise_OSError(_errno);
+// // }
+// return ret;
+// }
+
+
+//| def recv_into(self, buffer: WriteableBuffer, bufsize: int) -> int:
+//| """Reads some bytes from the connected remote address, writing
+//| into the provided buffer. If bufsize <= len(buffer) is given,
+//| a maximum of bufsize bytes will be read into the buffer. If no
+//| valid value is given for bufsize, the default is the length of
+//| the given buffer.
+//|
+//| Suits sockets of type SOCK_STREAM
+//| Returns an int of number of bytes read.
+//|
+//| :param bytearray buffer: buffer to receive into
+//| :param int bufsize: optionally, a maximum number of bytes to read."""
+//| ...
+//|
+
+STATIC mp_obj_t socketpool_socket_recv_into(size_t n_args, const mp_obj_t *args) {
+ socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (common_hal_socketpool_socket_get_closed(self)) {
+ // Bad file number.
+ mp_raise_OSError(MP_EBADF);
+ }
+ if (!common_hal_socketpool_socket_get_connected(self)) {
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
+ mp_int_t len = bufinfo.len;
+ if (n_args == 3) {
+ mp_int_t given_len = mp_obj_get_int(args[2]);
+ if (given_len > 0 && given_len < len) {
+ len = given_len;
+ }
+ }
+
+ if (len == 0) {
+ return MP_OBJ_NEW_SMALL_INT(0);
+ }
+
+ mp_int_t ret = common_hal_socketpool_socket_recv_into(self, (byte*)bufinfo.buf, len);
+ return mp_obj_new_int_from_uint(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket_recv_into_obj, 2, 3, socketpool_socket_recv_into);
+
+// //| def sendto(self, bytes: ReadableBuffer, address: tuple) -> int:
+// //| """Send some bytes to a specific address.
+// //| Suits sockets of type SOCK_DGRAM
+// //|
+// //| :param ~bytes bytes: some bytes to send
+// //| :param ~tuple address: tuple of (remote_address, remote_port)"""
+// //| ...
+// //|
+
+// STATIC mp_obj_t socketpool_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
+// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+// // // get the data
+// // mp_buffer_info_t bufinfo;
+// // mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
+
+// // // get address
+// // uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+// // mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
+
+// // // check if we need to select a NIC
+// // socket_select_nic(self, ip);
+
+// // // call the NIC to sendto
+// // int _errno;
+// // mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
+// // if (ret == -1) {
+// // mp_raise_OSError(_errno);
+// // }
+// mp_int_t ret = 0;
+
+// return mp_obj_new_int(ret);
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_3(socketpool_socket_sendto_obj, socketpool_socket_sendto);
+
+// //| def recvfrom(self, bufsize: int) -> Tuple[bytes, tuple]:
+// //| """Reads some bytes from the connected remote address.
+// //| Suits sockets of type SOCK_STREAM
+// //|
+// //| Returns a tuple containing
+// //| * a bytes() of length <= bufsize
+// //| * a remote_address, which is a tuple of ip address and port number
+// //|
+// //| :param ~int bufsize: maximum number of bytes to receive"""
+// //| ...
+// //|
+
+// STATIC mp_obj_t socketpool_socket_recvfrom_into(mp_obj_t self_in, mp_obj_t len_in) {
+// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+// // if (self->nic == MP_OBJ_NULL) {
+// // // not connected
+// // mp_raise_OSError(MP_ENOTCONN);
+// // }
+// // vstr_t vstr;
+// // vstr_init_len(&vstr, mp_obj_get_int(len_in));
+// // byte ip[4];
+// // mp_uint_t port;
+// // int _errno;
+// // mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
+// // if (ret == -1) {
+// // mp_raise_OSError(_errno);
+// // }
+// mp_obj_t tuple[2];
+// // if (ret == 0) {
+// // tuple[0] = mp_const_empty_bytes;
+// // } else {
+// // vstr.len = ret;
+// // tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+// // }
+// // tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
+// return mp_obj_new_tuple(2, tuple);
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_recvfrom_into_obj, socketpool_socket_recvfrom_into);
+
+// //| def setsockopt(self, level: int, optname: int, value: int) -> None:
+// //| """Sets socket options"""
+// //| ...
+// //|
+
+// STATIC mp_obj_t socketpool_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
+// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+// // mp_int_t level = mp_obj_get_int(args[1]);
+// // mp_int_t opt = mp_obj_get_int(args[2]);
+
+// // const void *optval;
+// // mp_uint_t optlen;
+// // mp_int_t val;
+// // if (mp_obj_is_integer(args[3])) {
+// // val = mp_obj_get_int_truncated(args[3]);
+// // optval = &val;
+// // optlen = sizeof(val);
+// // } else {
+// // mp_buffer_info_t bufinfo;
+// // mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
+// // optval = bufinfo.buf;
+// // optlen = bufinfo.len;
+// // }
+
+// // int _errno;
+// // if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
+// // mp_raise_OSError(_errno);
+// // }
+
+// return mp_const_none;
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket_setsockopt_obj, 4, 4, socketpool_socket_setsockopt);
+
+//| def settimeout(self, value: int) -> None:
+//| """Set the timeout value for this socket.
+//|
+//| :param ~int value: timeout in seconds. 0 means non-blocking. None means block indefinitely."""
+//| ...
+//|
+
+STATIC mp_obj_t socketpool_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
+ socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t timeout_ms;
+ if (timeout_in == mp_const_none) {
+ timeout_ms = -1;
+ } else {
+ #if MICROPY_PY_BUILTINS_FLOAT
+ timeout_ms = 1000 * mp_obj_get_float(timeout_in);
+ #else
+ timeout_ms = 1000 * mp_obj_get_int(timeout_in);
+ #endif
+ }
+ common_hal_socketpool_socket_settimeout(self, timeout_ms);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_settimeout_obj, socketpool_socket_settimeout);
+
+// //| def setblocking(self, flag: bool) -> Optional[int]:
+// //| """Set the blocking behaviour of this socket.
+// //|
+// //| :param ~bool flag: False means non-blocking, True means block indefinitely."""
+// //| ...
+// //|
+
+// // method socket.setblocking(flag)
+// STATIC mp_obj_t socketpool_socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
+// // if (mp_obj_is_true(blocking)) {
+// // return socket_settimeout(self_in, mp_const_none);
+// // } else {
+// // return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0));
+// // }
+// return mp_const_none;
+// }
+// STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_setblocking_obj, socketpool_socket_setblocking);
+
+//| def __hash__(self) -> int:
+//| """Returns a hash for the Socket."""
+//| ...
+//|
+STATIC mp_obj_t socketpool_socket_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ switch (op) {
+ case MP_UNARY_OP_HASH: {
+ return MP_OBJ_NEW_SMALL_INT(common_hal_socketpool_socket_get_hash(MP_OBJ_TO_PTR(self_in)));
+ }
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC const mp_rom_map_elem_t socketpool_socket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&socketpool_socket___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&socketpool_socket_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socketpool_socket_close_obj) },
+
+ // { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socketpool_socket_bind_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socketpool_socket_listen_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socketpool_socket_accept_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socketpool_socket_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socketpool_socket_send_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socketpool_socket_sendto_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_recvfrom_into), MP_ROM_PTR(&socketpool_socket_recvfrom_into_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv_into), MP_ROM_PTR(&socketpool_socket_recv_into_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socketpool_socket_setsockopt_obj) },
+ { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socketpool_socket_settimeout_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socketpool_socket_setblocking_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(socketpool_socket_locals_dict, socketpool_socket_locals_dict_table);
+
+const mp_obj_type_t socketpool_socket_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Socket,
+ .locals_dict = (mp_obj_dict_t*)&socketpool_socket_locals_dict,
+ .unary_op = socketpool_socket_unary_op,
+};
diff --git a/shared-bindings/socketpool/Socket.h b/shared-bindings/socketpool/Socket.h
new file mode 100644
index 000000000..f0be95c92
--- /dev/null
+++ b/shared-bindings/socketpool/Socket.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_SOCKETPOOL_SOCKET_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL_SOCKET_H
+
+#include "common-hal/socketpool/Socket.h"
+
+extern const mp_obj_type_t socketpool_socket_type;
+
+void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_uint_t timeout_ms);
+bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const char* host, size_t hostlen, mp_int_t port);
+mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len);
+mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len);
+void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self);
+bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t* self);
+bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self);
+mp_uint_t common_hal_socketpool_socket_get_hash(socketpool_socket_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL_SOCKET_H
diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c
new file mode 100644
index 000000000..0eeebd691
--- /dev/null
+++ b/shared-bindings/socketpool/SocketPool.c
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
+ * 2018 Nick Moore 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 <stdio.h>
+#include <string.h>
+
+#include "py/objtuple.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mperrno.h"
+
+#include "shared-bindings/ipaddress/__init__.h"
+#include "shared-bindings/socketpool/Socket.h"
+#include "shared-bindings/socketpool/SocketPool.h"
+
+#include "esp_log.h"
+static const char* TAG = "socketpool binding";
+
+//| class SocketPool:
+//| """A pool of socket resources available for the given radio. Only one
+//| SocketPool can be created for each radio.
+//|
+//| SocketPool should be used in place of CPython's socket which provides
+//| a pool of sockets provided by the underlying OS."""
+//|
+
+STATIC mp_obj_t socketpool_socketpool_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ mp_arg_check_num(n_args, kw_args, 1, 1, false);
+
+ socketpool_socketpool_obj_t *s = m_new_obj_with_finaliser(socketpool_socketpool_obj_t);
+ s->base.type = &socketpool_socketpool_type;
+ mp_obj_t radio = args[0];
+
+ common_hal_socketpool_socketpool_construct(s, radio);
+
+ return MP_OBJ_FROM_PTR(s);
+}
+
+
+//| def socket(self, family: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP) -> None:
+//| """Create a new socket
+//|
+//| :param ~int family: AF_INET or AF_INET6
+//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
+//| :param ~int proto: IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW (ignored)"""
+//| ...
+//|
+STATIC mp_obj_t socketpool_socketpool_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_check_num(n_args, kw_args, 0, 5, false);
+
+ socketpool_socketpool_obj_t *self = pos_args[0];
+ socketpool_socketpool_addressfamily_t family = SOCKETPOOL_AF_INET;
+ socketpool_socketpool_sock_t type = SOCKETPOOL_SOCK_STREAM;
+ if (n_args >= 2) {
+ family = mp_obj_get_int(pos_args[1]);
+ if (n_args >= 3) {
+ type = mp_obj_get_int(pos_args[2]);
+ }
+ }
+ return common_hal_socketpool_socket(self, family, type);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_socket_obj, 1, socketpool_socketpool_socket);
+
+//| def getaddrinfo(host: str, port: int, family: int = 0, type: int = 0, proto: int = 0, flags: int = 0) -> tuple:
+//| """Gets the address information for a hostname and port
+//|
+//| Returns the appropriate family, socket type, socket protocol and
+//| address information to call socket.socket() and socket.connect() with,
+//| as a tuple."""
+//| ...
+//|
+
+STATIC mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_host, ARG_port, ARG_family, ARG_type, ARG_proto, ARG_flags };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_host, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_port, MP_ARG_INT | MP_ARG_REQUIRED },
+ { MP_QSTR_family, MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_type, MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_port, MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_flags, MP_ARG_INT, {.u_int = 0} },
+ };
+ socketpool_socketpool_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const char *host = mp_obj_str_get_str(args[ARG_host].u_obj);
+ mp_int_t port = args[ARG_port].u_int;
+ mp_obj_t ip_str = mp_const_none;
+
+ if (strlen(host) > 0 && ipaddress_parse_ipv4address(host, strlen(host), NULL)) {
+ ip_str = args[ARG_host].u_obj;
+ }
+
+ if (ip_str == mp_const_none) {
+ ip_str = common_hal_socketpool_socketpool_gethostbyname(self, host);
+ }
+
+ if (ip_str == mp_const_none) {
+ ESP_EARLY_LOGW(TAG, "no ip str");
+ mp_raise_OSError(0);
+ }
+
+ mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_AF_INET);
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCKETPOOL_SOCK_STREAM);
+ tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
+ tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
+ mp_obj_tuple_t *sockaddr = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+ sockaddr->items[0] = ip_str;
+ sockaddr->items[1] = MP_OBJ_NEW_SMALL_INT(port);
+ tuple->items[4] = MP_OBJ_FROM_PTR(sockaddr);
+ return mp_obj_new_list(1, (mp_obj_t*)&tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_getaddrinfo_obj, 3, socketpool_socketpool_getaddrinfo);
+
+STATIC const mp_rom_map_elem_t socketpool_socketpool_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socketpool_socketpool_socket_obj) },
+ { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&socketpool_socketpool_getaddrinfo_obj) },
+
+ // class constants
+ { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(SOCKETPOOL_AF_INET) },
+ { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(SOCKETPOOL_AF_INET6) },
+
+ { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCKETPOOL_SOCK_STREAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCKETPOOL_SOCK_DGRAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCKETPOOL_SOCK_RAW) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(socketpool_socketpool_locals_dict, socketpool_socketpool_locals_dict_table);
+
+const mp_obj_type_t socketpool_socketpool_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SocketPool,
+ .make_new = socketpool_socketpool_make_new,
+ .locals_dict = (mp_obj_dict_t*)&socketpool_socketpool_locals_dict,
+};
diff --git a/shared-bindings/socketpool/SocketPool.h b/shared-bindings/socketpool/SocketPool.h
new file mode 100644
index 000000000..b007aad8f
--- /dev/null
+++ b/shared-bindings/socketpool/SocketPool.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_SOCKETPOOL_SOCKETPOOL_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL_SOCKETPOOL_H
+
+#include "common-hal/socketpool/SocketPool.h"
+
+#include "shared-bindings/socketpool/Socket.h"
+
+extern const mp_obj_type_t socketpool_socketpool_type;
+
+typedef enum {
+ SOCKETPOOL_SOCK_STREAM,
+ SOCKETPOOL_SOCK_DGRAM,
+ SOCKETPOOL_SOCK_RAW
+} socketpool_socketpool_sock_t;
+
+typedef enum {
+ SOCKETPOOL_AF_INET,
+ SOCKETPOOL_AF_INET6
+} socketpool_socketpool_addressfamily_t;
+
+void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t* self, mp_obj_t radio);
+
+socketpool_socket_obj_t* common_hal_socketpool_socket(socketpool_socketpool_obj_t* self,
+ socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type);
+
+mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_obj_t* self,
+ const char* host);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL_SOCKETPOOL_H
diff --git a/shared-bindings/socketpool/__init__.c b/shared-bindings/socketpool/__init__.c
new file mode 100644
index 000000000..d3f8ba302
--- /dev/null
+++ b/shared-bindings/socketpool/__init__.c
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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/objexcept.h"
+#include "py/objstr.h"
+#include "py/parsenum.h"
+#include "py/runtime.h"
+#include "shared-bindings/socketpool/__init__.h"
+#include "shared-bindings/socketpool/Socket.h"
+#include "shared-bindings/socketpool/SocketPool.h"
+
+//| """
+//| The `socketpool` module provides sockets through a pool. The pools themselves
+//| act like CPython's `socket` module.
+//| """
+//|
+
+STATIC const mp_rom_map_elem_t socketpool_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_socketpool) },
+
+ { MP_ROM_QSTR(MP_QSTR_SocketPool), MP_ROM_PTR(&socketpool_socketpool_type) },
+ { MP_ROM_QSTR(MP_QSTR_Socket), MP_ROM_PTR(&socketpool_socket_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(socketpool_globals, socketpool_globals_table);
+
+const mp_obj_module_t socketpool_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&socketpool_globals,
+};
diff --git a/shared-bindings/socketpool/__init__.h b/shared-bindings/socketpool/__init__.h
new file mode 100644
index 000000000..a017e96c6
--- /dev/null
+++ b/shared-bindings/socketpool/__init__.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_SOCKETPOOL___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL___INIT___H
diff --git a/shared-bindings/ssl/SSLContext.c b/shared-bindings/ssl/SSLContext.c
new file mode 100644
index 000000000..d2c236d3b
--- /dev/null
+++ b/shared-bindings/ssl/SSLContext.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft 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 <stdio.h>
+#include <string.h>
+
+#include "py/objtuple.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mperrno.h"
+
+#include "shared-bindings/ssl/SSLContext.h"
+
+//| class SSLContext:
+//| """Settings related to SSL that can be applied to a socket by wrapping it.
+//| This is useful to provide SSL certificates to specific connections
+//| rather than all of them."""
+//|
+
+STATIC mp_obj_t ssl_sslcontext_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ mp_arg_check_num(n_args, kw_args, 0, 1, false);
+
+ ssl_sslcontext_obj_t *s = m_new_obj(ssl_sslcontext_obj_t);
+ s->base.type = &ssl_sslcontext_type;
+
+ common_hal_ssl_sslcontext_construct(s);
+
+ return MP_OBJ_FROM_PTR(s);
+}
+
+//| def wrap_socket(sock: socketpool.Socket, *, server_side: bool = False, server_hostname: str = None) -> socketpool.Socket:
+//| """Wraps the socket into a socket-compatible class that handles SSL negotiation.
+//| The socket must be of type SOCK_STREAM."""
+//| ...
+//|
+
+STATIC mp_obj_t ssl_sslcontext_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sock, ARG_server_side, ARG_server_hostname };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sock, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+ ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const char *server_hostname = mp_obj_str_get_str(args[ARG_server_hostname].u_obj);
+ bool server_side = args[ARG_server_side].u_bool;
+ if (server_side && server_hostname != NULL) {
+ mp_raise_ValueError(translate("Server side context cannot have hostname"));
+ }
+
+ socketpool_socket_obj_t* sock = args[ARG_sock].u_obj;
+
+ return common_hal_ssl_sslcontext_wrap_socket(self, sock, server_side, server_hostname);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_wrap_socket_obj, 2, ssl_sslcontext_wrap_socket);
+
+STATIC const mp_rom_map_elem_t ssl_sslcontext_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_sslcontext_wrap_socket_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(ssl_sslcontext_locals_dict, ssl_sslcontext_locals_dict_table);
+
+const mp_obj_type_t ssl_sslcontext_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SSLContext,
+ .make_new = ssl_sslcontext_make_new,
+ .locals_dict = (mp_obj_dict_t*)&ssl_sslcontext_locals_dict,
+};
diff --git a/shared-bindings/ssl/SSLContext.h b/shared-bindings/ssl/SSLContext.h
new file mode 100644
index 000000000..f7f985af7
--- /dev/null
+++ b/shared-bindings/ssl/SSLContext.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_SSL_SSLCONTEXT_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_SSL_SSLCONTEXT_H
+
+#include "common-hal/ssl/SSLContext.h"
+
+#include "shared-bindings/socketpool/Socket.h"
+
+extern const mp_obj_type_t ssl_sslcontext_type;
+
+void common_hal_ssl_sslcontext_construct(ssl_sslcontext_obj_t* self);
+
+socketpool_socket_obj_t* common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t* self,
+ socketpool_socket_obj_t* sock, bool server_side, const char* server_hostname);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SSL_SSLCONTEXT_H
diff --git a/shared-bindings/ssl/__init__.c b/shared-bindings/ssl/__init__.c
new file mode 100644
index 000000000..57f4e6f4a
--- /dev/null
+++ b/shared-bindings/ssl/__init__.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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/objexcept.h"
+#include "py/objstr.h"
+#include "py/parsenum.h"
+#include "py/runtime.h"
+#include "shared-bindings/ssl/__init__.h"
+#include "shared-bindings/ssl/SSLContext.h"
+
+//| """
+//| The `ssl` module provides SSL contexts to wrap sockets in.
+//| """
+//|
+
+//| def create_default_context() -> ssl.SSLContext:
+//| """Return the default SSLContext."""
+//| ...
+//|
+
+STATIC mp_obj_t ssl_create_default_context(void) {
+ ssl_sslcontext_obj_t *s = m_new_obj(ssl_sslcontext_obj_t);
+ s->base.type = &ssl_sslcontext_type;
+
+ common_hal_ssl_create_default_context(s);
+ return s;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(ssl_create_default_context_obj, ssl_create_default_context);
+
+STATIC const mp_rom_map_elem_t ssl_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ssl) },
+
+ { MP_ROM_QSTR(MP_QSTR_create_default_context), MP_ROM_PTR(&ssl_create_default_context_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_sslcontext_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(ssl_globals, ssl_globals_table);
+
+const mp_obj_module_t ssl_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&ssl_globals,
+};
diff --git a/shared-bindings/ssl/__init__.h b/shared-bindings/ssl/__init__.h
new file mode 100644
index 000000000..5ddada64e
--- /dev/null
+++ b/shared-bindings/ssl/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_SSL___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_SSL___INIT___H
+
+#include "common-hal/ssl/SSLContext.h"
+
+void common_hal_ssl_create_default_context(ssl_sslcontext_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SSL___INIT___H
diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c
index 79c5274aa..cafaf5986 100644
--- a/shared-bindings/storage/__init__.c
+++ b/shared-bindings/storage/__init__.c
@@ -187,7 +187,7 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
//| """Like builtin ``open()``"""
//| ...
//|
-//| def ilistdir(self, path: str) -> Iterator[Tuple[AnyStr, int, int, int]]:
+//| def ilistdir(self, path: str) -> Iterator[Union[Tuple[AnyStr, int, int, int], Tuple[AnyStr, int, int]]]:
//| """Return an iterator whose values describe files and folders within
//| ``path``"""
//| ...
@@ -200,11 +200,11 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
//| """Like `os.rmdir`"""
//| ...
//|
-//| def stat(self, path: str) -> str:
+//| def stat(self, path: str) -> Tuple[int, int, int, int, int, int, int, int, int, int]:
//| """Like `os.stat`"""
//| ...
//|
-//| def statvfs(self, path: str) -> Tuple[str, str, str, str, str, str, str, str, str, str]:
+//| def statvfs(self, path: int) -> Tuple[int, int, int, int, int, int, int, int, int, int]:
//| """Like `os.statvfs`"""
//| ...
//|
diff --git a/shared-bindings/struct/__init__.c b/shared-bindings/struct/__init__.c
index d74b96212..b886a662e 100644
--- a/shared-bindings/struct/__init__.c
+++ b/shared-bindings/struct/__init__.c
@@ -62,7 +62,7 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize);
-//| def pack(fmt: str, *values: ReadableBuffer) -> bytes:
+//| def pack(fmt: str, *values: Any) -> bytes:
//| """Pack the values according to the format string fmt.
//| The return value is a bytes object encoding the values."""
//| ...
@@ -80,7 +80,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack);
-//| def pack_into(fmt: str, buffer: WriteableBuffer, offset: int, *values: ReadableBuffer) -> None:
+//| def pack_into(fmt: str, buffer: WriteableBuffer, offset: int, *values: Any) -> None:
//| """Pack the values according to the format string fmt into a buffer
//| starting at offset. offset may be negative to count from the end of buffer."""
//| ...
@@ -106,7 +106,7 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX, struct_pack_into);
-//| def unpack(fmt: str, data: ReadableBuffer) -> tuple:
+//| def unpack(fmt: str, data: ReadableBuffer) -> Tuple[Any, ...]:
//| """Unpack from the data according to the format string fmt. The return value
//| is a tuple of the unpacked values. The buffer size must match the size
//| required by the format."""
@@ -124,7 +124,7 @@ STATIC mp_obj_t struct_unpack(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_obj, 2, 3, struct_unpack);
-//| def unpack_from(fmt: str, data: ReadableBuffer, offset: int = 0) -> tuple:
+//| def unpack_from(fmt: str, data: ReadableBuffer, offset: int = 0) -> Tuple[Any, ...]:
//| """Unpack from the data starting at offset according to the format string fmt.
//| offset may be negative to count from the end of buffer. The return value is
//| a tuple of the unpacked values. The buffer size must be at least as big
diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c
index b59394bbc..bc6fdbff5 100644
--- a/shared-bindings/supervisor/__init__.c
+++ b/shared-bindings/supervisor/__init__.c
@@ -45,7 +45,7 @@
//| This object is the sole instance of `supervisor.Runtime`."""
//|
-//| def enable_autoreload(self) -> None:
+//| def enable_autoreload() -> None:
//| """Enable autoreload based on USB file write activity."""
//| ...
//|
@@ -55,7 +55,7 @@ STATIC mp_obj_t supervisor_enable_autoreload(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_enable_autoreload_obj, supervisor_enable_autoreload);
-//| def disable_autoreload(self) -> None:
+//| def disable_autoreload() -> None:
//| """Disable autoreload based on USB file write activity until
//| `enable_autoreload` is called."""
//| ...
@@ -66,7 +66,7 @@ STATIC mp_obj_t supervisor_disable_autoreload(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_disable_autoreload_obj, supervisor_disable_autoreload);
-//| def set_rgb_status_brightness(self, brightness: int) -> None:
+//| def set_rgb_status_brightness(brightness: int) -> None:
//| """Set brightness of status neopixel from 0-255
//| `set_rgb_status_brightness` is called."""
//| ...
@@ -82,7 +82,7 @@ STATIC mp_obj_t supervisor_set_rgb_status_brightness(mp_obj_t lvl){
}
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness);
-//| def reload(self) -> None:
+//| def reload() -> None:
//| """Reload the main Python code and run it (equivalent to hitting Ctrl-D at the REPL)."""
//| ...
//|
@@ -93,7 +93,7 @@ STATIC mp_obj_t supervisor_reload(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
-//| def set_next_stack_limit(self, size: int) -> None:
+//| def set_next_stack_limit(size: int) -> None:
//| """Set the size of the stack for the next vm run. If its too large, the default will be used."""
//| ...
//|
diff --git a/shared-bindings/support_matrix.rst b/shared-bindings/support_matrix.rst
index 124f3a810..1b75e0256 100644
--- a/shared-bindings/support_matrix.rst
+++ b/shared-bindings/support_matrix.rst
@@ -6,11 +6,16 @@ Support Matrix
The following table lists the available built-in modules for each CircuitPython
capable board.
-.. csv-table::
+.. list-table::
:header-rows: 1
:widths: 7, 50
- "Board", "Modules Available"
- {% for key, value in support_matrix|dictsort -%}
- "{{ key }}", "{{ '`' ~ value|join("`, `") ~ '`' }}"
- {% endfor -%}
+ * - Board
+ - Modules Available
+
+ {% for key, value in support_matrix|dictsort %}
+ {{ '.. _' ~ key|replace(" ", "-") ~ ':' }}
+ * - {{ key }}
+ - {{ '`' ~ value|join("`, `") ~ '`' }}
+
+ {% endfor %}
diff --git a/shared-bindings/terminalio/__init__.c b/shared-bindings/terminalio/__init__.c
index 589211139..9cd1da5b6 100644
--- a/shared-bindings/terminalio/__init__.c
+++ b/shared-bindings/terminalio/__init__.c
@@ -40,6 +40,9 @@
//| The `terminalio` module contains classes to display a character stream on a display. The built
//| in font is available as ``terminalio.FONT``."""
//|
+//| FONT: fontio.BuiltinFont
+//| """The built in font"""
+//|
STATIC const mp_rom_map_elem_t terminalio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_terminalio) },
{ MP_ROM_QSTR(MP_QSTR_Terminal), MP_OBJ_FROM_PTR(&terminalio_terminal_type) },
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index 262da17fd..44f82c62e 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -93,7 +93,7 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp
}
//| class struct_time:
-//| def __init__(self, time_tuple: tuple) -> None:
+//| def __init__(self, time_tuple: Tuple[int, int, int, int, int, int, int, int, int]) -> None:
//| """Structure used to capture a date and time. Note that it takes a tuple!
//|
//| :param tuple time_tuple: Tuple of time info: ``(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)``
@@ -215,7 +215,7 @@ STATIC mp_obj_t time_time(void) {
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
//| def monotonic_ns() -> int:
-//| """Return the time of the specified clock clk_id in nanoseconds.
+//| """Return the time of the monotonic clock, cannot go backward, in nanoseconds.
//|
//| :return: the current time
//| :rtype: int"""
@@ -280,7 +280,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_obj_tuple_get(t, &len, &elem);
if (len != 9) {
- mp_raise_TypeError(translate("function takes exactly 9 arguments"));
+ mp_raise_TypeError_varg(translate("function takes %d positional arguments but %d were given"), 9);
}
if (mp_obj_get_int(elem[0]) < 2000) {
diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c
index 83c0df4ae..c7c05a974 100644
--- a/shared-bindings/usb_hid/Device.c
+++ b/shared-bindings/usb_hid/Device.c
@@ -58,6 +58,25 @@ STATIC mp_obj_t usb_hid_device_send_report(mp_obj_t self_in, mp_obj_t buffer) {
}
MP_DEFINE_CONST_FUN_OBJ_2(usb_hid_device_send_report_obj, usb_hid_device_send_report);
+//| last_received_report: bytes
+//| """The HID OUT report as a `bytes`. (read-only). `None` if nothing received."""
+//|
+STATIC mp_obj_t usb_hid_device_obj_get_last_received_report(mp_obj_t self_in) {
+ usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->out_report_buffer == 0) {
+ return mp_const_none;
+ }
+ return mp_obj_new_bytes(self->out_report_buffer, self->out_report_length);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(usb_hid_device_get_last_received_report_obj, usb_hid_device_obj_get_last_received_report);
+
+const mp_obj_property_t usb_hid_device_last_received_report_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&usb_hid_device_get_last_received_report_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
//| usage_page: int
//| """The usage page of the device as an `int`. Can be thought of a category. (read-only)"""
//|
@@ -95,9 +114,10 @@ const mp_obj_property_t usb_hid_device_usage_obj = {
};
STATIC const mp_rom_map_elem_t usb_hid_device_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_send_report), MP_ROM_PTR(&usb_hid_device_send_report_obj) },
- { MP_ROM_QSTR(MP_QSTR_usage_page), MP_ROM_PTR(&usb_hid_device_usage_page_obj)},
- { MP_ROM_QSTR(MP_QSTR_usage), MP_ROM_PTR(&usb_hid_device_usage_obj)},
+ { MP_ROM_QSTR(MP_QSTR_send_report), MP_ROM_PTR(&usb_hid_device_send_report_obj) },
+ { MP_ROM_QSTR(MP_QSTR_last_received_report), MP_ROM_PTR(&usb_hid_device_last_received_report_obj) },
+ { MP_ROM_QSTR(MP_QSTR_usage_page), MP_ROM_PTR(&usb_hid_device_usage_page_obj)},
+ { MP_ROM_QSTR(MP_QSTR_usage), MP_ROM_PTR(&usb_hid_device_usage_obj)},
};
STATIC MP_DEFINE_CONST_DICT(usb_hid_device_locals_dict, usb_hid_device_locals_dict_table);
diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c
index 5570b601c..d88a0db48 100644
--- a/shared-bindings/usb_midi/__init__.c
+++ b/shared-bindings/usb_midi/__init__.c
@@ -35,8 +35,14 @@
#include "py/runtime.h"
-//| """Classes to transmit and receive MIDI messages over USB"""
+//| """MIDI over USB
//|
+//| The `usb_midi` module contains classes to transmit and receive MIDI messages over USB."""
+//|
+//| ports: Tuple[Union[PortIn, PortOut], ...]
+//| """Tuple of all MIDI ports. Each item is ether `PortIn` or `PortOut`."""
+//|
+
mp_map_elem_t usb_midi_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_midi) },
{ MP_ROM_QSTR(MP_QSTR_ports), mp_const_empty_tuple },
@@ -45,17 +51,7 @@ mp_map_elem_t usb_midi_module_globals_table[] = {
};
// This isn't const so we can set ports dynamically.
-mp_obj_dict_t usb_midi_module_globals = {
- .base = {&mp_type_dict},
- .map = {
- .all_keys_are_qstrs = 1,
- .is_fixed = 1,
- .is_ordered = 1,
- .used = MP_ARRAY_SIZE(usb_midi_module_globals_table),
- .alloc = MP_ARRAY_SIZE(usb_midi_module_globals_table),
- .table = usb_midi_module_globals_table,
- },
-};
+MP_DEFINE_MUTABLE_DICT(usb_midi_module_globals, usb_midi_module_globals_table);
const mp_obj_module_t usb_midi_module = {
.base = { &mp_type_module },
diff --git a/shared-bindings/vectorio/VectorShape.c b/shared-bindings/vectorio/VectorShape.c
index 957e9dc08..bc8c8d29c 100644
--- a/shared-bindings/vectorio/VectorShape.c
+++ b/shared-bindings/vectorio/VectorShape.c
@@ -20,7 +20,7 @@
//| class VectorShape:
-//| def __init__(self, shape: Polygon, pixel_shader: displayio.Palette, x: int=0, y: int=0) -> None:
+//| def __init__(self, shape: Union[Polygon, Rectangle, Circle], pixel_shader: Union[displayio.ColorConverter, displayio.Palette], x: int=0, y: int=0) -> None:
//| """Binds a vector shape to a location and pixel color
//|
//| :param shape: The shape to draw.
@@ -145,7 +145,7 @@ const mp_obj_property_t vectorio_vector_shape_y_obj = {
};
-//| pixel_shader: displayio.Palette
+//| pixel_shader: Union[displayio.ColorConverter, displayio.Palette]
//| """The pixel shader of the shape."""
//|
STATIC mp_obj_t vectorio_vector_shape_obj_get_pixel_shader(mp_obj_t self_in) {
diff --git a/shared-bindings/watchdog/WatchDogMode.h b/shared-bindings/watchdog/WatchDogMode.h
index 68022671f..fb09445a9 100644
--- a/shared-bindings/watchdog/WatchDogMode.h
+++ b/shared-bindings/watchdog/WatchDogMode.h
@@ -35,7 +35,7 @@ typedef enum {
WATCHDOGMODE_RESET,
} watchdog_watchdogmode_t;
-const mp_obj_type_t watchdog_watchdogmode_type;
+extern const mp_obj_type_t watchdog_watchdogmode_type;
watchdog_watchdogmode_t watchdog_watchdogmode_obj_to_type(mp_obj_t obj);
mp_obj_t watchdog_watchdogmode_type_to_obj(watchdog_watchdogmode_t mode);
diff --git a/shared-bindings/wifi/Network.c b/shared-bindings/wifi/Network.c
new file mode 100644
index 000000000..b6d5e0901
--- /dev/null
+++ b/shared-bindings/wifi/Network.c
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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 <string.h>
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/wifi/Network.h"
+
+//| class Network:
+//| """A wifi network provided by a nearby access point.
+//|
+//| """
+//|
+
+//| def __init__(self) -> None:
+//| """You cannot create an instance of `wifi.Network`. They are returned by `wifi.Radio.start_scanning_networks`."""
+//| ...
+//|
+
+//| ssid: str
+//| """String id of the network"""
+//|
+STATIC mp_obj_t wifi_network_get_ssid(mp_obj_t self) {
+ return common_hal_wifi_network_get_ssid(self);
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_ssid_obj, wifi_network_get_ssid);
+
+const mp_obj_property_t wifi_network_ssid_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&wifi_network_get_ssid_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+
+//| rssi: int
+//| """Signal strength of the network"""
+//|
+STATIC mp_obj_t wifi_network_get_rssi(mp_obj_t self) {
+ return common_hal_wifi_network_get_rssi(self);
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_rssi_obj, wifi_network_get_rssi);
+
+const mp_obj_property_t wifi_network_rssi_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&wifi_network_get_rssi_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+
+//| channel: int
+//| """Channel number the network is operating on"""
+//|
+STATIC mp_obj_t wifi_network_get_channel(mp_obj_t self) {
+ return common_hal_wifi_network_get_channel(self);
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_channel_obj, wifi_network_get_channel);
+
+const mp_obj_property_t wifi_network_channel_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&wifi_network_get_channel_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+
+STATIC const mp_rom_map_elem_t wifi_network_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wifi_network_ssid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&wifi_network_rssi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wifi_network_channel_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(wifi_network_locals_dict, wifi_network_locals_dict_table);
+
+const mp_obj_type_t wifi_network_type = {
+ .base = { &mp_type_type },
+ .name = MP_QSTR_Network,
+ .locals_dict = (mp_obj_t)&wifi_network_locals_dict,
+};
diff --git a/shared-bindings/wifi/Network.h b/shared-bindings/wifi/Network.h
new file mode 100644
index 000000000..6a7f7be4a
--- /dev/null
+++ b/shared-bindings/wifi/Network.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_WIFI_NETWORK_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_NETWORK_H
+
+#include <stdint.h>
+
+#include "common-hal/wifi/Network.h"
+
+#include "py/objstr.h"
+
+const mp_obj_type_t wifi_network_type;
+
+extern mp_obj_t common_hal_wifi_network_get_ssid(wifi_network_obj_t *self);
+extern mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self);
+extern mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_NETWORK_H
diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c
new file mode 100644
index 000000000..329dcb1b5
--- /dev/null
+++ b/shared-bindings/wifi/Radio.c
@@ -0,0 +1,224 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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 <string.h>
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/wifi/__init__.h"
+
+//| class Radio:
+//| """Native wifi radio.
+//|
+//| This class manages the station and access point functionality of the native
+//| Wifi radio.
+//|
+//| """
+//|
+
+//| def __init__(self) -> None:
+//| """You cannot create an instance of `wifi.Radio`.
+//| Use `wifi.radio` to access the sole instance available."""
+//| ...
+//|
+
+//| enabled: bool
+//| """True when the wifi radio is enabled."""
+//|
+STATIC mp_obj_t wifi_radio_get_enabled(mp_obj_t self) {
+ return mp_obj_new_bool(common_hal_wifi_radio_get_enabled(self));
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_enabled_obj, wifi_radio_get_enabled);
+
+const mp_obj_property_t wifi_radio_enabled_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&wifi_radio_get_enabled_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| mac_address: bytes
+//| """MAC address of the wifi radio. (read-only)"""
+//|
+STATIC mp_obj_t wifi_radio_get_mac_address(mp_obj_t self) {
+ return MP_OBJ_FROM_PTR(common_hal_wifi_radio_get_mac_address(self));
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_mac_address_obj, wifi_radio_get_mac_address);
+
+const mp_obj_property_t wifi_radio_mac_address_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&wifi_radio_get_mac_address_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+
+//| def start_scanning_networks(self, *, start_channel=1, stop_channel=11) -> Iterable[Network]:
+//| """Scans for available wifi networks over the given channel range. Make sure the channels are allowed in your country."""
+//| ...
+//|
+STATIC mp_obj_t wifi_radio_start_scanning_networks(mp_obj_t self_in) {
+ wifi_radio_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_wifi_radio_start_scanning_networks(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_start_scanning_networks_obj, wifi_radio_start_scanning_networks);
+
+//| def stop_scanning_networks(self) -> None:
+//| """Stop scanning for Wifi networks and free any resources used to do it."""
+//| ...
+//|
+STATIC mp_obj_t wifi_radio_stop_scanning_networks(mp_obj_t self_in) {
+ wifi_radio_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_wifi_radio_stop_scanning_networks(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_scanning_networks_obj, wifi_radio_stop_scanning_networks);
+
+//| def connect(self, ssid: ReadableBuffer, password: ReadableBuffer = b"", *, channel: Optional[int] = 0, timeout: Optional[float] = None) -> bool:
+//| """Connects to the given ssid and waits for an ip address. Reconnections are handled
+//| automatically once one connection succeeds."""
+//| ...
+//|
+STATIC mp_obj_t wifi_radio_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_ssid, ARG_password, ARG_channel, ARG_timeout };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_password, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_float_t timeout = 0;
+ if (args[ARG_timeout].u_obj != mp_const_none) {
+ timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
+ }
+
+
+ mp_buffer_info_t ssid;
+ mp_get_buffer_raise(args[ARG_ssid].u_obj, &ssid, MP_BUFFER_READ);
+
+ mp_buffer_info_t password;
+ password.len = 0;
+ if (args[ARG_password].u_obj != MP_OBJ_NULL) {
+ mp_get_buffer_raise(args[ARG_password].u_obj, &password, MP_BUFFER_READ);
+ if (password.len > 0 && (password.len < 8 || password.len > 63)) {
+ mp_raise_ValueError(translate("WiFi password must be between 8 and 63 characters"));
+ }
+ }
+
+ wifi_radio_error_t error = common_hal_wifi_radio_connect(self, ssid.buf, ssid.len, password.buf, password.len, args[ARG_channel].u_int, timeout);
+ if (error == WIFI_RADIO_ERROR_AUTH) {
+ mp_raise_ConnectionError(translate("Authentication failure"));
+ } else if (error == WIFI_RADIO_ERROR_NO_AP_FOUND) {
+ mp_raise_ConnectionError(translate("No network with that ssid"));
+ } else if (error != WIFI_RADIO_ERROR_NONE) {
+ mp_raise_ConnectionError(translate("Unknown failure"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_connect_obj, 1, wifi_radio_connect);
+
+//| ipv4_address: Optional[ipaddress.IPv4Address]
+//| """IP v4 Address of the radio when connected to an access point. None otherwise."""
+//|
+STATIC mp_obj_t wifi_radio_get_ipv4_address(mp_obj_t self) {
+ return common_hal_wifi_radio_get_ipv4_address(self);
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv4_address_obj, wifi_radio_get_ipv4_address);
+
+const mp_obj_property_t wifi_radio_ipv4_address_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&wifi_radio_get_ipv4_address_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| def ping(self, ip, *, timeout: float = 0.5) -> float:
+//| """Ping an IP to test connectivity. Returns echo time in seconds.
+//| Returns None when it times out."""
+//| ...
+//|
+STATIC mp_obj_t wifi_radio_ping(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_ip, ARG_timeout };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_ip, MP_ARG_REQUIRED | MP_ARG_OBJ, },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_float_t timeout = 0.5;
+ if (args[ARG_timeout].u_obj != mp_const_none) {
+ timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
+ }
+
+ mp_int_t time_ms = common_hal_wifi_radio_ping(self, args[ARG_ip].u_obj, timeout);
+ if (time_ms == -1) {
+ return mp_const_none;
+ }
+
+ return mp_obj_new_float(time_ms / 1000.0);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_ping_obj, 1, wifi_radio_ping);
+
+STATIC const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&wifi_radio_enabled_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mac_address), MP_ROM_PTR(&wifi_radio_mac_address_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_start_scanning_networks), MP_ROM_PTR(&wifi_radio_start_scanning_networks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_scanning_networks), MP_ROM_PTR(&wifi_radio_stop_scanning_networks_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wifi_radio_connect_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_connect_to_enterprise), MP_ROM_PTR(&wifi_radio_connect_to_enterprise_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_ipv4_address_obj) },
+
+ // { MP_ROM_QSTR(MP_QSTR_access_point_active), MP_ROM_PTR(&wifi_radio_access_point_active_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_start_access_point), MP_ROM_PTR(&wifi_radio_start_access_point_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_ping), MP_ROM_PTR(&wifi_radio_ping_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(wifi_radio_locals_dict, wifi_radio_locals_dict_table);
+
+const mp_obj_type_t wifi_radio_type = {
+ .base = { &mp_type_type },
+ .name = MP_QSTR_Radio,
+ .locals_dict = (mp_obj_t)&wifi_radio_locals_dict,
+};
diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h
new file mode 100644
index 000000000..812814f9e
--- /dev/null
+++ b/shared-bindings/wifi/Radio.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_WIFI_RADIO_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_RADIO_H
+
+#include <stdint.h>
+
+#include "common-hal/wifi/Radio.h"
+
+#include "py/objstr.h"
+
+const mp_obj_type_t wifi_radio_type;
+
+
+typedef enum {
+ WIFI_RADIO_ERROR_NONE,
+ WIFI_RADIO_ERROR_UNKNOWN,
+ WIFI_RADIO_ERROR_AUTH,
+ WIFI_RADIO_ERROR_NO_AP_FOUND
+} wifi_radio_error_t;
+
+extern bool common_hal_wifi_radio_get_enabled(wifi_radio_obj_t *self);
+extern void common_hal_wifi_radio_set_enabled(wifi_radio_obj_t *self, bool enabled);
+
+extern mp_obj_t common_hal_wifi_radio_get_mac_address(wifi_radio_obj_t *self);
+
+extern mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self);
+extern void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self);
+
+extern wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t* ssid, size_t ssid_len, uint8_t* password, size_t password_len, uint8_t channel, mp_float_t timeout);
+
+extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
+
+extern mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_RADIO_H
diff --git a/shared-bindings/wifi/ScannedNetworks.c b/shared-bindings/wifi/ScannedNetworks.c
new file mode 100644
index 000000000..c927d7282
--- /dev/null
+++ b/shared-bindings/wifi/ScannedNetworks.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * 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 <string.h>
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/wifi/ScannedNetworks.h"
+
+#include "esp_log.h"
+static const char *TAG = "cp iternext";
+
+//| class ScannedNetworks:
+//| """Iterates over all `wifi.Network` objects found while scanning. This object is always created
+//| by a `wifi.Radio`: it has no user-visible constructor."""
+//|
+STATIC mp_obj_t scannednetworks_iternext(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &wifi_scannednetworks_type));
+ wifi_scannednetworks_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_t network = common_hal_wifi_scannednetworks_next(self);
+ if (network != mp_const_none) {
+ return network;
+ }
+
+ ESP_EARLY_LOGI(TAG, "stop iteration");
+ return MP_OBJ_STOP_ITERATION;
+}
+
+//| def __init__(self) -> None:
+//| """Cannot be instantiated directly. Use `wifi.Radio.start_scanning_networks`."""
+//| ...
+//|
+//| def __iter__(self) -> Iterator[Network]:
+//| """Returns itself since it is the iterator."""
+//| ...
+//|
+//| def __next__(self) -> Network:
+//| """Returns the next `wifi.Network`.
+//| Raises `StopIteration` if scanning is finished and no other results are available."""
+//| ...
+//|
+
+const mp_obj_type_t wifi_scannednetworks_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ScannedNetworks,
+ .getiter = mp_identity_getiter,
+ .iternext = scannednetworks_iternext,
+};
diff --git a/shared-bindings/wifi/ScannedNetworks.h b/shared-bindings/wifi/ScannedNetworks.h
new file mode 100644
index 000000000..8e0aa435d
--- /dev/null
+++ b/shared-bindings/wifi/ScannedNetworks.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * 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_WIFI_SCANNEDNETWORKS_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_SCANNEDNETWORKS_H
+
+#include "py/obj.h"
+#include "common-hal/wifi/ScannedNetworks.h"
+
+extern const mp_obj_type_t wifi_scannednetworks_type;
+
+mp_obj_t common_hal_wifi_scannednetworks_next(wifi_scannednetworks_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_SCANNEDNETWORKS_H
diff --git a/shared-bindings/wifi/__init__.c b/shared-bindings/wifi/__init__.c
new file mode 100644
index 000000000..352ceb331
--- /dev/null
+++ b/shared-bindings/wifi/__init__.c
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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/objexcept.h"
+#include "py/runtime.h"
+#include "shared-bindings/wifi/__init__.h"
+#include "shared-bindings/wifi/Network.h"
+#include "shared-bindings/wifi/Radio.h"
+
+//| """
+//| The `wifi` module provides necessary low-level functionality for managing wifi
+//| wifi connections. Use `socketpool` for communicating over the network."""
+//|
+//| radio: Radio
+//| """Wifi radio used to manage both station and AP modes.
+//| This object is the sole instance of `wifi.Radio`."""
+//|
+
+
+// Called when wifi is imported.
+STATIC mp_obj_t wifi___init__(void) {
+ common_hal_wifi_init();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(wifi___init___obj, wifi___init__);
+
+
+STATIC const mp_rom_map_elem_t wifi_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wifi) },
+ { MP_ROM_QSTR(MP_QSTR_Network), MP_ROM_PTR(&wifi_network_type) },
+ { MP_ROM_QSTR(MP_QSTR_Radio), MP_ROM_PTR(&wifi_radio_type) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&common_hal_wifi_radio_obj) },
+
+ // Initialization
+ { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&wifi___init___obj) },
+
+};
+
+STATIC MP_DEFINE_CONST_DICT(wifi_module_globals, wifi_module_globals_table);
+
+
+const mp_obj_module_t wifi_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&wifi_module_globals,
+};
diff --git a/shared-bindings/wifi/__init__.h b/shared-bindings/wifi/__init__.h
new file mode 100644
index 000000000..c06ee16be
--- /dev/null
+++ b/shared-bindings/wifi/__init__.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft 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_WIFI___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WIFI___INIT___H
+
+#include "py/objlist.h"
+
+#include "shared-bindings/wifi/Radio.h"
+
+extern wifi_radio_obj_t common_hal_wifi_radio_obj;
+
+void common_hal_wifi_init(void);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI___INIT___H
diff --git a/shared-bindings/wiznet/wiznet5k.c b/shared-bindings/wiznet/wiznet5k.c
index 4e5744d82..5e9a3a9fb 100644
--- a/shared-bindings/wiznet/wiznet5k.c
+++ b/shared-bindings/wiznet/wiznet5k.c
@@ -134,7 +134,7 @@ const mp_obj_property_t wiznet5k_dhcp_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| def ifconfig(self, params: Optional[Tuple] = None) -> Optional[Tuple]:
+//| def ifconfig(self, params: Optional[Tuple[str, str, str, str]] = None) -> Optional[Tuple[str, str, str, str]]:
//| """Called without parameters, returns a tuple of
//| (ip_address, subnet_mask, gateway_address, dns_server)
//|