summaryrefslogtreecommitdiff
path: root/shared-bindings
diff options
context:
space:
mode:
Diffstat (limited to 'shared-bindings')
-rw-r--r--shared-bindings/_bleio/Adapter.c176
-rw-r--r--shared-bindings/_bleio/Adapter.h5
-rw-r--r--shared-bindings/_bleio/Address.c70
-rw-r--r--shared-bindings/_bleio/Attribute.c56
-rw-r--r--shared-bindings/_bleio/Characteristic.c143
-rw-r--r--shared-bindings/_bleio/CharacteristicBuffer.c80
-rw-r--r--shared-bindings/_bleio/CharacteristicBuffer.h2
-rw-r--r--shared-bindings/_bleio/Connection.c131
-rw-r--r--shared-bindings/_bleio/Connection.h11
-rw-r--r--shared-bindings/_bleio/Descriptor.c70
-rw-r--r--shared-bindings/_bleio/PacketBuffer.c152
-rw-r--r--shared-bindings/_bleio/PacketBuffer.h7
-rw-r--r--shared-bindings/_bleio/ScanEntry.c55
-rw-r--r--shared-bindings/_bleio/ScanResults.c30
-rw-r--r--shared-bindings/_bleio/Service.c50
-rw-r--r--shared-bindings/_bleio/UUID.c68
-rw-r--r--shared-bindings/_bleio/__init__.c62
-rw-r--r--shared-bindings/_eve/__init__.c435
-rw-r--r--shared-bindings/_pew/PewPew.c41
-rw-r--r--shared-bindings/_pew/__init__.c14
-rw-r--r--shared-bindings/_pixelbuf/PixelBuf.c127
-rw-r--r--shared-bindings/_pixelbuf/PixelBuf.h2
-rw-r--r--shared-bindings/_pixelbuf/__init__.c40
-rw-r--r--shared-bindings/_stage/Layer.c44
-rw-r--r--shared-bindings/_stage/Text.c36
-rw-r--r--shared-bindings/_stage/__init__.c24
-rw-r--r--shared-bindings/aesio/__init__.c65
-rw-r--r--shared-bindings/aesio/__init__.h53
-rw-r--r--shared-bindings/aesio/aes.c268
-rw-r--r--shared-bindings/analogio/AnalogIn.c69
-rw-r--r--shared-bindings/analogio/AnalogOut.c61
-rw-r--r--shared-bindings/analogio/__init__.c17
-rw-r--r--shared-bindings/audiobusio/I2SOut.c162
-rw-r--r--shared-bindings/audiobusio/PDMIn.c150
-rw-r--r--shared-bindings/audiobusio/__init__.c17
-rw-r--r--shared-bindings/audiocore/RawSample.c99
-rw-r--r--shared-bindings/audiocore/WaveFile.c93
-rw-r--r--shared-bindings/audiocore/__init__.c17
-rw-r--r--shared-bindings/audioio/AudioOut.c186
-rw-r--r--shared-bindings/audioio/__init__.c16
-rw-r--r--shared-bindings/audiomixer/Mixer.c125
-rw-r--r--shared-bindings/audiomixer/MixerVoice.c42
-rw-r--r--shared-bindings/audiomixer/__init__.c16
-rw-r--r--shared-bindings/audiomp3/MP3Decoder.c96
-rw-r--r--shared-bindings/audiomp3/__init__.c15
-rw-r--r--shared-bindings/audiopwmio/PWMAudioOut.c193
-rw-r--r--shared-bindings/audiopwmio/__init__.c16
-rw-r--r--shared-bindings/bitbangio/I2C.c162
-rw-r--r--shared-bindings/bitbangio/OneWire.c84
-rw-r--r--shared-bindings/bitbangio/SPI.c142
-rw-r--r--shared-bindings/bitbangio/__init__.c18
-rw-r--r--shared-bindings/board/__init__.c39
-rw-r--r--shared-bindings/busio/I2C.c196
-rw-r--r--shared-bindings/busio/OneWire.c87
-rw-r--r--shared-bindings/busio/SPI.c229
-rw-r--r--shared-bindings/busio/SPI.h4
-rw-r--r--shared-bindings/busio/UART.c196
-rw-r--r--shared-bindings/busio/UART.h16
-rw-r--r--shared-bindings/busio/__init__.c19
-rw-r--r--shared-bindings/countio/Counter.c145
-rw-r--r--shared-bindings/countio/Counter.h18
-rw-r--r--shared-bindings/countio/__init__.c36
-rw-r--r--shared-bindings/countio/__init__.h9
-rw-r--r--shared-bindings/digitalio/DigitalInOut.c126
-rw-r--r--shared-bindings/digitalio/DigitalInOut.h7
-rw-r--r--shared-bindings/digitalio/Direction.c24
-rw-r--r--shared-bindings/digitalio/DriveMode.c26
-rw-r--r--shared-bindings/digitalio/Pull.c28
-rw-r--r--shared-bindings/digitalio/__init__.c19
-rw-r--r--shared-bindings/displayio/Bitmap.c77
-rw-r--r--shared-bindings/displayio/Bitmap.h1
-rw-r--r--shared-bindings/displayio/ColorConverter.c31
-rw-r--r--shared-bindings/displayio/Display.c244
-rw-r--r--shared-bindings/displayio/Display.h4
-rw-r--r--shared-bindings/displayio/EPaperDisplay.c148
-rw-r--r--shared-bindings/displayio/FourWire.c91
-rw-r--r--shared-bindings/displayio/FourWire.h3
-rw-r--r--shared-bindings/displayio/Group.c114
-rw-r--r--shared-bindings/displayio/I2CDisplay.c67
-rw-r--r--shared-bindings/displayio/OnDiskBitmap.c78
-rw-r--r--shared-bindings/displayio/Palette.c57
-rw-r--r--shared-bindings/displayio/ParallelBus.c91
-rw-r--r--shared-bindings/displayio/Shape.c30
-rw-r--r--shared-bindings/displayio/TileGrid.c106
-rw-r--r--shared-bindings/displayio/__init__.c41
-rw-r--r--shared-bindings/fontio/BuiltinFont.c37
-rw-r--r--shared-bindings/fontio/Glyph.c36
-rw-r--r--shared-bindings/fontio/__init__.c17
-rw-r--r--shared-bindings/framebufferio/FramebufferDisplay.c403
-rw-r--r--shared-bindings/framebufferio/FramebufferDisplay.h69
-rw-r--r--shared-bindings/framebufferio/__init__.c50
-rw-r--r--shared-bindings/framebufferio/__init__.h0
-rw-r--r--shared-bindings/frequencyio/FrequencyIn.c109
-rw-r--r--shared-bindings/frequencyio/__init__.c19
-rw-r--r--shared-bindings/gamepad/GamePad.c116
-rw-r--r--shared-bindings/gamepad/__init__.c12
-rw-r--r--shared-bindings/gamepadshift/GamePadShift.c47
-rw-r--r--shared-bindings/gamepadshift/__init__.c12
-rw-r--r--shared-bindings/gnss/GNSS.c227
-rw-r--r--shared-bindings/gnss/GNSS.h49
-rw-r--r--shared-bindings/gnss/PositionFix.c108
-rw-r--r--shared-bindings/gnss/PositionFix.h50
-rw-r--r--shared-bindings/gnss/SatelliteSystem.c145
-rw-r--r--shared-bindings/gnss/SatelliteSystem.h55
-rw-r--r--shared-bindings/gnss/__init__.c53
-rw-r--r--shared-bindings/help.rst31
-rw-r--r--shared-bindings/i2cperipheral/I2CPeripheral.c435
-rw-r--r--shared-bindings/i2cperipheral/I2CPeripheral.h (renamed from shared-bindings/i2cslave/I2CSlave.h)26
-rw-r--r--shared-bindings/i2cperipheral/__init__.c (renamed from shared-bindings/i2cslave/__init__.c)57
-rw-r--r--shared-bindings/i2cslave/I2CSlave.c449
-rw-r--r--shared-bindings/index.rst10
-rw-r--r--shared-bindings/math/__init__.c337
-rw-r--r--shared-bindings/microcontroller/Pin.c59
-rw-r--r--shared-bindings/microcontroller/Pin.h13
-rw-r--r--shared-bindings/microcontroller/Processor.c48
-rw-r--r--shared-bindings/microcontroller/RunMode.c36
-rw-r--r--shared-bindings/microcontroller/__init__.c97
-rw-r--r--shared-bindings/microcontroller/__init__.h5
-rw-r--r--shared-bindings/multiterminal/__init__.c37
-rw-r--r--shared-bindings/neopixel_write/__init__.c20
-rw-r--r--shared-bindings/neopixel_write/__init__.h6
-rw-r--r--shared-bindings/network/__init__.c15
-rw-r--r--shared-bindings/nvm/ByteArray.c30
-rw-r--r--shared-bindings/nvm/__init__.c16
-rw-r--r--shared-bindings/os/__init__.c125
-rw-r--r--shared-bindings/ps2io/Ps2.c143
-rw-r--r--shared-bindings/ps2io/__init__.c16
-rw-r--r--shared-bindings/pulseio/PWMOut.c118
-rw-r--r--shared-bindings/pulseio/PulseIn.c163
-rw-r--r--shared-bindings/pulseio/PulseOut.c82
-rw-r--r--shared-bindings/pulseio/__init__.c18
-rw-r--r--shared-bindings/random/__init__.c60
-rw-r--r--shared-bindings/rgbmatrix/RGBMatrix.c423
-rw-r--r--shared-bindings/rgbmatrix/RGBMatrix.h61
-rw-r--r--shared-bindings/rgbmatrix/__init__.c47
-rw-r--r--shared-bindings/rotaryio/IncrementalEncoder.c80
-rw-r--r--shared-bindings/rotaryio/__init__.c20
-rw-r--r--shared-bindings/rtc/RTC.c44
-rw-r--r--shared-bindings/rtc/__init__.c42
-rw-r--r--shared-bindings/sdcardio/SDCard.c183
-rw-r--r--shared-bindings/sdcardio/SDCard.h30
-rw-r--r--shared-bindings/sdcardio/__init__.c47
-rw-r--r--shared-bindings/sdcardio/__init__.h0
-rw-r--r--shared-bindings/sdioio/SDCard.c296
-rw-r--r--shared-bindings/sdioio/SDCard.h66
-rw-r--r--shared-bindings/sdioio/__init__.c47
-rw-r--r--shared-bindings/sdioio/__init__.h0
-rw-r--r--shared-bindings/socket/__init__.c160
-rw-r--r--shared-bindings/storage/__init__.c168
-rw-r--r--shared-bindings/struct/__init__.c53
-rwxr-xr-xshared-bindings/supervisor/Runtime.c40
-rw-r--r--shared-bindings/supervisor/__init__.c59
-rwxr-xr-xshared-bindings/supervisor/__init__.h2
-rw-r--r--shared-bindings/terminalio/Terminal.c25
-rw-r--r--shared-bindings/terminalio/__init__.c16
-rw-r--r--shared-bindings/time/__init__.c122
-rw-r--r--shared-bindings/touchio/TouchIn.c72
-rw-r--r--shared-bindings/touchio/__init__.c16
-rw-r--r--shared-bindings/uheap/__init__.c14
-rw-r--r--shared-bindings/ulab/__init__.pyi169
-rw-r--r--shared-bindings/ulab/approx/__init__.pyi51
-rw-r--r--shared-bindings/ulab/compare/__init__.pyi38
-rw-r--r--shared-bindings/ulab/extras/__init__.pyi10
-rw-r--r--shared-bindings/ulab/fft/__init__.pyi22
-rw-r--r--shared-bindings/ulab/filter/__init__.pyi36
-rw-r--r--shared-bindings/ulab/linalg/__init__.pyi57
-rw-r--r--shared-bindings/ulab/numerical/__init__.pyi57
-rw-r--r--shared-bindings/ulab/poly/__init__.pyi10
-rw-r--r--shared-bindings/ulab/vector/__init__.pyi118
-rw-r--r--shared-bindings/usb_hid/Device.c38
-rw-r--r--shared-bindings/usb_hid/__init__.c21
-rw-r--r--shared-bindings/usb_midi/PortIn.c45
-rw-r--r--shared-bindings/usb_midi/PortOut.c26
-rw-r--r--shared-bindings/usb_midi/__init__.c17
-rw-r--r--shared-bindings/ustack/__init__.c33
-rw-r--r--shared-bindings/vectorio/Circle.c74
-rw-r--r--shared-bindings/vectorio/Circle.h22
-rw-r--r--shared-bindings/vectorio/Polygon.c94
-rw-r--r--shared-bindings/vectorio/Polygon.h24
-rw-r--r--shared-bindings/vectorio/Rectangle.c52
-rw-r--r--shared-bindings/vectorio/Rectangle.h15
-rw-r--r--shared-bindings/vectorio/VectorShape.c190
-rw-r--r--shared-bindings/vectorio/VectorShape.h27
-rw-r--r--shared-bindings/vectorio/__init__.c27
-rw-r--r--shared-bindings/watchdog/WatchDogMode.c99
-rw-r--r--shared-bindings/watchdog/WatchDogMode.h49
-rw-r--r--shared-bindings/watchdog/WatchDogTimer.c186
-rw-r--r--shared-bindings/watchdog/WatchDogTimer.h48
-rw-r--r--shared-bindings/watchdog/__init__.c81
-rw-r--r--shared-bindings/watchdog/__init__.h (renamed from shared-bindings/help.c)16
-rw-r--r--shared-bindings/wiznet/__init__.c17
-rw-r--r--shared-bindings/wiznet/wiznet5k.c60
192 files changed, 9197 insertions, 5351 deletions
diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c
index 921667f0f..13acb9d3c 100644
--- a/shared-bindings/_bleio/Adapter.c
+++ b/shared-bindings/_bleio/Adapter.c
@@ -47,35 +47,32 @@
#define INTERVAL_MAX_STRING "40.959375"
#define WINDOW_DEFAULT (0.1f)
-//| .. currentmodule:: _bleio
+//| class Adapter:
+//| """BLE adapter
//|
-//| :class:`Adapter` --- BLE adapter
-//| ----------------------------------------------------
+//| The Adapter 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).
//|
-//| The Adapter 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
+//| 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.
//|
-//| 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
-//| 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.
-//|
-//| The built-in BLE 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.
+//| The built-in BLE 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."""
//|
-//| .. class:: Adapter()
-//|
-//| You cannot create an instance of `_bleio.Adapter`.
-//| Use `_bleio.adapter` to access the sole instance available.
+//| def __init__(self, ):
+//| """You cannot create an instance of `_bleio.Adapter`.
+//| Use `_bleio.adapter` to access the sole instance available."""
+//| ...
//|
-//| .. attribute:: enabled
-//|
-//| State of the BLE adapter.
+//| enabled: Any = ...
+//| """State of the BLE adapter."""
//|
STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) {
return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled(self));
@@ -98,9 +95,8 @@ const mp_obj_property_t bleio_adapter_enabled_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: address
-//|
-//| MAC address of the BLE adapter. (read-only)
+//| address: Any = ...
+//| """MAC address of the BLE adapter. (read-only)"""
//|
STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address(self));
@@ -115,11 +111,10 @@ const mp_obj_property_t bleio_adapter_address_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: name
-//|
-//| name of the BLE adapter used once connected.
-//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
-//| to make it easy to distinguish multiple CircuitPython boards.
+//| name: Any = ...
+//| """name of the BLE adapter used once connected.
+//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
+//| to make it easy to distinguish multiple CircuitPython boards."""
//|
STATIC mp_obj_t bleio_adapter_get_name(mp_obj_t self) {
return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_name(self));
@@ -140,27 +135,34 @@ const mp_obj_property_t bleio_adapter_name_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1)
+//| def start_advertising(self, data: buf, *, scan_response: buf = None, connectable: bool = True, anonymous: bool = False, timeout: int = 0, interval: float = 0.1) -> Any:
+//| """Starts advertising until `stop_advertising` is called or if connectable, another device
+//| connects to us.
//|
-//| Starts advertising until `stop_advertising` is called or if connectable, another device
-//| connects to us.
+//| .. warning: If data is longer than 31 bytes, then this will automatically advertise as an
+//| extended advertisement that older BLE 4.x clients won't be able to scan for.
//|
-//| .. warning: If data is longer than 31 bytes, then this will automatically advertise as an
-//| extended advertisement that older BLE 4.x clients won't be able to scan for.
+//| .. 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 bool connectable: If `True` then other devices are allowed to connect to this peripheral.
-//| :param float interval: advertising interval, in seconds
+//| :param buf data: advertising data packet bytes
+//| :param buf 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.
+//| :param float interval: advertising interval, in seconds"""
+//| ...
//|
STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval };
+ enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_anonymous, ARG_timeout, ARG_interval };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ { MP_QSTR_anonymous, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
@@ -187,20 +189,23 @@ STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t
}
bool connectable = args[ARG_connectable].u_bool;
+ bool anonymous = args[ARG_anonymous].u_bool;
+ uint32_t timeout = args[ARG_timeout].u_int;
if (data_bufinfo.len > 31 && connectable && scan_response_bufinfo.len > 0) {
mp_raise_bleio_BluetoothError(translate("Cannot have scan responses for extended, connectable advertisements."));
}
- common_hal_bleio_adapter_start_advertising(self, connectable, interval,
+ common_hal_bleio_adapter_start_advertising(self, connectable, anonymous, timeout, interval,
&data_bufinfo, &scan_response_bufinfo);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_advertising_obj, 2, bleio_adapter_start_advertising);
-//| .. method:: stop_advertising()
+//| def stop_advertising(self, ) -> Any:
+//| """Stop sending advertising packets."""
+//| ...
//|
-//| Stop sending advertising packets.
STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) {
bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -210,25 +215,25 @@ STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapter_stop_advertising);
-//| .. method:: start_scan(prefixes=b"", \*, buffer_size=512, extended=False, timeout=None, interval=0.1, window=0.1, minimum_rssi=-80, active=True)
-//|
-//| Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are
-//| filtered and returned separately.
+//| def start_scan(self, prefixes: sequence = b"", *, buffer_size: int = 512, extended: bool = False, timeout: float = None, interval: float = 0.1, window: float = 0.1, minimum_rssi: int = -80, active: bool = True) -> Any:
+//| """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
-//| 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.
-//| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set.
-//| :param float timeout: the scan timeout in seconds. If None, will scan until `stop_scan` is called.
-//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows
-//| Must be in the range 0.0025 - 40.959375 seconds.
-//| :param float window: the duration (in seconds) to scan a single BLE channel.
-//| window must be <= interval.
-//| :param int minimum_rssi: the minimum rssi of entries to return.
-//| :param bool active: retrieve scan responses for scannable advertisements.
-//| :returns: an iterable of `_bleio.ScanEntry` objects
-//| :rtype: iterable
+//| :param sequence 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.
+//| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set.
+//| :param float timeout: the scan timeout in seconds. If None, will scan until `stop_scan` is called.
+//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows
+//| Must be in the range 0.0025 - 40.959375 seconds.
+//| :param float window: the duration (in seconds) to scan a single BLE channel.
+//| window must be <= interval.
+//| :param int minimum_rssi: the minimum rssi of entries to return.
+//| :param bool active: retrieve scan responses for scannable advertisements.
+//| :returns: an iterable of `_bleio.ScanEntry` objects
+//| :rtype: iterable"""
+//| ...
//|
STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_prefixes, ARG_buffer_size, ARG_extended, ARG_timeout, ARG_interval, ARG_window, ARG_minimum_rssi, ARG_active };
@@ -283,9 +288,10 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan);
-//| .. method:: stop_scan()
+//| def stop_scan(self, ) -> Any:
+//| """Stop the current scan."""
+//| ...
//|
-//| Stop the current scan.
STATIC mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) {
bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -295,10 +301,25 @@ STATIC mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_scan_obj, bleio_adapter_stop_scan);
-//| .. attribute:: connected
+//| advertising: Any = ...
+//| """True when the adapter is currently advertising. (read-only)"""
//|
-//| True when the adapter is connected to another device regardless of who initiated the
-//| connection. (read-only)
+STATIC mp_obj_t bleio_adapter_get_advertising(mp_obj_t self) {
+ return mp_obj_new_bool(common_hal_bleio_adapter_get_advertising(self));
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_advertising_obj, bleio_adapter_get_advertising);
+
+const mp_obj_property_t bleio_adapter_advertising_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_adapter_get_advertising_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| connected: Any = ...
+//| """True when the adapter is connected to another device regardless of who initiated the
+//| connection. (read-only)"""
//|
STATIC mp_obj_t bleio_adapter_get_connected(mp_obj_t self) {
return mp_obj_new_bool(common_hal_bleio_adapter_get_connected(self));
@@ -313,10 +334,9 @@ const mp_obj_property_t bleio_adapter_connected_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: connections
-//|
-//| Tuple of active connections including those initiated through
-//| :py:meth:`_bleio.Adapter.connect`. (read-only)
+//| connections: Any = ...
+//| """Tuple of active connections including those initiated through
+//| :py:meth:`_bleio.Adapter.connect`. (read-only)"""
//|
STATIC mp_obj_t bleio_adapter_get_connections(mp_obj_t self) {
return common_hal_bleio_adapter_get_connections(self);
@@ -330,12 +350,12 @@ const mp_obj_property_t bleio_adapter_connections_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. method:: connect(address, *, timeout)
-//|
-//| Attempts a connection to the device with the given address.
+//| def connect(self, address: Address, *, timeout: float/int) -> Any:
+//| """Attempts a connection to the device with the given address.
//|
-//| :param Address address: The address of the peripheral to connect to
-//| :param float/int timeout: Try to connect for timeout seconds.
+//| :param Address address: The address of the peripheral to connect to
+//| :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) {
bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -360,9 +380,10 @@ STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 2, bleio_adapter_connect);
-//| .. method:: erase_bonding()
+//| def erase_bonding(self, ) -> Any:
+//| """Erase all bonding information stored in flash memory."""
+//| ...
//|
-//| Erase all bonding information stored in flash memory.
STATIC mp_obj_t bleio_adapter_erase_bonding(mp_obj_t self_in) {
bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -379,6 +400,7 @@ STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_adapter_start_advertising_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_adapter_stop_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_advertising), MP_ROM_PTR(&bleio_adapter_advertising_obj) },
{ MP_ROM_QSTR(MP_QSTR_start_scan), MP_ROM_PTR(&bleio_adapter_start_scan_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop_scan), MP_ROM_PTR(&bleio_adapter_stop_scan_obj) },
diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h
index 9b20a461a..39147b6eb 100644
--- a/shared-bindings/_bleio/Adapter.h
+++ b/shared-bindings/_bleio/Adapter.h
@@ -37,6 +37,7 @@
const mp_obj_type_t bleio_adapter_type;
+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);
@@ -45,9 +46,9 @@ extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_o
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);
-extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len);
+extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len);
-extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
+extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
extern void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self);
extern mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active);
diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c
index c31eb604b..9beaff2ab 100644
--- a/shared-bindings/_bleio/Address.c
+++ b/shared-bindings/_bleio/Address.c
@@ -34,22 +34,18 @@
#include "shared-bindings/_bleio/Address.h"
#include "shared-module/_bleio/Address.h"
-//| .. currentmodule:: _bleio
-//|
-//| :class:`Address` -- BLE address
-//| =========================================================
-//|
-//| Encapsulates the address of a BLE device.
+//| class Address:
+//| """Encapsulates the address of a BLE device."""
//|
-//| .. class:: Address(address, address_type)
-//|
-//| Create a new Address object encapsulating the address value.
-//| The value itself can be one of:
+//| def __init__(self, address: buf, address_type: Any):
+//| """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 int address_type: one of the integer values: `PUBLIC`, `RANDOM_STATIC`,
-//| `RANDOM_PRIVATE_RESOLVABLE`, or `RANDOM_PRIVATE_NON_RESOLVABLE`.
+//| :param buf 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`."""
+//| ...
//|
STATIC mp_obj_t bleio_address_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, ARG_address_type };
@@ -81,9 +77,8 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-//| .. attribute:: address_bytes
-//|
-//| The bytes that make up the device address (read-only).
+//| address_bytes: Any = ...
+//| r"""The bytes that make up the device address (read-only).
//|
//| Note that the ``bytes`` object returned is in little-endian order:
//| The least significant byte is ``address_bytes[0]``. So the address will
@@ -97,7 +92,7 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
//| >>> _bleio.adapter.address
//| <Address c8:1d:f5:ed:a8:35>
//| >>> _bleio.adapter.address.address_bytes
-//| b'5\xa8\xed\xf5\x1d\xc8'
+//| b'5\\xa8\\xed\\xf5\\x1d\\xc8'"""
//|
STATIC mp_obj_t bleio_address_get_address_bytes(mp_obj_t self_in) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -113,12 +108,11 @@ const mp_obj_property_t bleio_address_address_bytes_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: type
-//|
-//| The address type (read-only).
+//| type: Any = ...
+//| """The address type (read-only).
//|
//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, `RANDOM_PRIVATE_RESOLVABLE`,
-//| or `RANDOM_PRIVATE_NON_RESOLVABLE`.
+//| or `RANDOM_PRIVATE_NON_RESOLVABLE`."""
//|
STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -134,9 +128,9 @@ const mp_obj_property_t bleio_address_type_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: __eq__(other)
-//|
-//| Two Address objects are equal if their addresses and address types are equal.
+//| def __eq__(self, other: Any) -> Any:
+//| """Two Address objects are equal if their addresses and address types are equal."""
+//| ...
//|
STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
switch (op) {
@@ -160,9 +154,9 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o
}
}
-//| .. method:: __hash__()
-//|
-//| Returns a hash for the Address data.
+//| def __hash__(self, ) -> Any:
+//| """Returns a hash for the Address data."""
+//| ...
//|
STATIC mp_obj_t bleio_address_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
switch (op) {
@@ -193,22 +187,18 @@ STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
}
-//| .. data:: PUBLIC
-//|
-//| A publicly known address, with a company ID (high 24 bits)and company-assigned part (low 24 bits).
-//|
-//| .. data:: RANDOM_STATIC
-//|
-//| A randomly generated address that does not change often. It may never change or may change after
-//| a power cycle.
-//|
-//| .. data:: RANDOM_PRIVATE_RESOLVABLE
+//| PUBLIC: Any = ...
+//| """A publicly known address, with a company ID (high 24 bits)and company-assigned part (low 24 bits)."""
//|
-//| An address that is usable when the peer knows the other device's secret Identity Resolving Key (IRK).
+//| RANDOM_STATIC: Any = ...
+//| """A randomly generated address that does not change often. It may never change or may change after
+//| a power cycle."""
//|
-//| .. data:: RANDOM_PRIVATE_NON_RESOLVABLE
+//| RANDOM_PRIVATE_RESOLVABLE: Any = ...
+//| """An address that is usable when the peer knows the other device's secret Identity Resolving Key (IRK)."""
//|
-//| A randomly generated address that changes on every connection.
+//| RANDOM_PRIVATE_NON_RESOLVABLE: Any = ...
+//| """A randomly generated address that changes on every connection."""
//|
STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) },
diff --git a/shared-bindings/_bleio/Attribute.c b/shared-bindings/_bleio/Attribute.c
index 2d8b15b9f..6c47c87ba 100644
--- a/shared-bindings/_bleio/Attribute.c
+++ b/shared-bindings/_bleio/Attribute.c
@@ -29,52 +29,40 @@
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/UUID.h"
-//
-
-//| .. currentmodule:: _bleio
-//|
-//| :class:`Attribute` -- BLE Attribute
-//| =========================================================
-//|
-//| Definitions associated with all BLE attributes: characteristics, descriptors, etc.
-//| :py:class:`~_bleio.Attribute` is, notionally, a superclass of
-//| :py:class:`~Characteristic` and :py:class:`~Descriptor`,
-//| but is not defined as a Python superclass of those classes.
+//| class Attribute:
+//| """Definitions associated with all BLE attributes: characteristics, descriptors, etc.
//|
-//| .. class:: Attribute()
+//| :py:class:`~_bleio.Attribute` is, notionally, a superclass of
+//| :py:class:`~Characteristic` and :py:class:`~Descriptor`,
+//| but is not defined as a Python superclass of those classes."""
//|
-//| You cannot create an instance of :py:class:`~_bleio.Attribute`.
+//| def __init__(self, ):
+//| """You cannot create an instance of :py:class:`~_bleio.Attribute`."""
+//| ...
//|
STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = {
-//| .. data:: NO_ACCESS
-//|
-//| security mode: access not allowed
-//|
-//| .. data:: OPEN
-//|
-//| security_mode: no security (link is not encrypted)
-//|
-//| .. data:: ENCRYPT_NO_MITM
-//|
-//| security_mode: unauthenticated encryption, without man-in-the-middle protection
-//|
-//| .. data:: ENCRYPT_WITH_MITM
-//|
-//| security_mode: authenticated encryption, with man-in-the-middle protection
+//| NO_ACCESS: Any = ...
+//| """security mode: access not allowed"""
//|
-//| .. data:: LESC_ENCRYPT_WITH_MITM
+//| OPEN: Any = ...
+//| """security_mode: no security (link is not encrypted)"""
//|
-//| security_mode: LESC encryption, with man-in-the-middle protection
+//| ENCRYPT_NO_MITM: Any = ...
+//| """security_mode: unauthenticated encryption, without man-in-the-middle protection"""
//|
-//| .. data:: SIGNED_NO_MITM
+//| ENCRYPT_WITH_MITM: Any = ...
+//| """security_mode: authenticated encryption, with man-in-the-middle protection"""
//|
-//| security_mode: unauthenticated data signing, without man-in-the-middle protection
+//| LESC_ENCRYPT_WITH_MITM: Any = ...
+//| """security_mode: LESC encryption, with man-in-the-middle protection"""
//|
-//| .. data:: SIGNED_WITH_MITM
+//| SIGNED_NO_MITM: Any = ...
+//| """security_mode: unauthenticated data signing, without man-in-the-middle protection"""
//|
-//| security_mode: authenticated data signing, without man-in-the-middle protection
+//| SIGNED_WITH_MITM: Any = ...
+//| """security_mode: authenticated data signing, without man-in-the-middle protection"""
//|
{ MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SECURITY_MODE_NO_ACCESS) },
{ MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SECURITY_MODE_OPEN) },
diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c
index e55191f7c..785b677d6 100644
--- a/shared-bindings/_bleio/Characteristic.c
+++ b/shared-bindings/_bleio/Characteristic.c
@@ -33,45 +33,41 @@
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
-//| .. currentmodule:: _bleio
-//|
-//| :class:`Characteristic` -- BLE service characteristic
-//| =========================================================
-//|
-//| Stores information about a BLE service characteristic and allows reading
-//| and writing of the characteristic's value.
-//|
-//| .. class:: Characteristic
-//|
-//| There is no regular constructor for a Characteristic. A new local Characteristic can be created
-//| and attached to a Service by calling `add_to_service()`.
-//| Remote Characteristic objects are created by `Connection.discover_remote_services()`
-//| as part of remote Services.
-//|
-
-//| .. method:: add_to_service(service, uuid, *, properties=0, read_perm=Attribute.OPEN, write_perm=Attribute.OPEN, max_length=20, fixed_length=False, initial_value=None)
-//|
-//| Create a new Characteristic object, and add it to this Service.
-//|
-//| :param Service service: The service that will provide this characteristic
-//| :param UUID uuid: The uuid of the characteristic
-//| :param int properties: The properties of the characteristic,
-//| specified as a bitmask of these values bitwise-or'd together:
-//| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.
-//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which
-//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
-//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
-//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
-//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which
-//| security mode is required. Values allowed are the same as ``read_perm``.
-//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
-//| 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
-//| filled with zeros.
-//|
-//| :return: the new Characteristic.
+//| class Characteristic:
+//| """Stores information about a BLE service characteristic and allows reading
+//| and writing of the characteristic's value."""
+//|
+//| def __init__(self, ):
+//| """There is no regular constructor for a Characteristic. A new local Characteristic can be created
+//| and attached to a Service by calling `add_to_service()`.
+//| Remote Characteristic objects are created by `Connection.discover_remote_services()`
+//| as part of remote Services."""
+//| ...
+//|
+
+//| def add_to_service(self, service: Service, uuid: UUID, *, properties: int = 0, read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, max_length: int = 20, fixed_length: bool = False, initial_value: buf = None) -> Any:
+//| """Create a new Characteristic object, and add it to this Service.
+//|
+//| :param Service service: The service that will provide this characteristic
+//| :param UUID uuid: The uuid of the characteristic
+//| :param int properties: The properties of the characteristic,
+//| specified as a bitmask of these values bitwise-or'd together:
+//| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.
+//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which
+//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
+//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
+//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
+//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which
+//| security mode is required. Values allowed are the same as ``read_perm``.
+//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
+//| 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
+//| filled with zeros.
+//|
+//| :return: the new Characteristic."""
+//| ...
//|
STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// class is arg[0], which we can ignore.
@@ -145,11 +141,10 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj,
-//| .. attribute:: properties
-//|
-//| An int bitmask representing which properties are set, specified as bitwise or'ing of
+//| properties: Any = ...
+//| """An int bitmask representing which properties are set, specified as bitwise or'ing of
//| of these possible values.
-//| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.
+//| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`."""
//|
STATIC mp_obj_t bleio_characteristic_get_properties(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -165,11 +160,10 @@ const mp_obj_property_t bleio_characteristic_properties_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: uuid
-//|
-//| The UUID of this characteristic. (read-only)
+//| uuid: Any = ...
+//| """The UUID of this characteristic. (read-only)
//|
-//| Will be ``None`` if the 128-bit UUID for this characteristic is not known.
+//| Will be ``None`` if the 128-bit UUID for this characteristic is not known."""
//|
STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -186,9 +180,8 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: value
-//|
-//| The value of this characteristic.
+//| value: Any = ...
+//| """The value of this characteristic."""
//|
STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -218,9 +211,8 @@ const mp_obj_property_t bleio_characteristic_value_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: descriptors
-//|
-//| A tuple of :py:class:`Descriptor` that describe this characteristic. (read-only)
+//| descriptors: Any = ...
+//| """A tuple of :py:class:`Descriptor` that describe 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);
@@ -249,9 +241,8 @@ const mp_obj_property_t bleio_characteristic_descriptors_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: service (read-only)
-//|
-//| The Service this Characteristic is a part of.
+//| service: Any = ...
+//| """The Service this Characteristic is a part of."""
//|
STATIC mp_obj_t bleio_characteristic_get_service(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -267,12 +258,12 @@ const mp_obj_property_t bleio_characteristic_service_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. method:: set_cccd(*, notify=False, indicate=False)
+//| def set_cccd(self, *, notify: bool = False, indicate: float = False) -> Any:
+//| """Set the remote characteristic's CCCD to enable or disable notification and indication.
//|
-//| Set the remote characteristic's CCCD to enable or disable notification and indication.
-//|
-//| :param bool notify: True if Characteristic should receive notifications of remote writes
-//| :param float indicate: True if Characteristic should receive indications of remote writes
+//| :param bool notify: True if Characteristic should receive notifications of remote writes
+//| :param float indicate: True if Characteristic should receive indications of remote writes"""
+//| ...
//|
STATIC mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -300,29 +291,23 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
// Bitmask constants to represent properties
-//| .. data:: BROADCAST
-//|
-//| property: allowed in advertising packets
-//|
-//| .. data:: INDICATE
-//|
-//| property: server will indicate to the client when the value is set and wait for a response
-//|
-//| .. data:: NOTIFY
-//|
-//| property: server will notify the client when the value is set
-//|
-//| .. data:: READ
+//| BROADCAST: Any = ...
+//| """property: allowed in advertising packets"""
//|
-//| property: clients may read this characteristic
+//| INDICATE: Any = ...
+//| """property: server will indicate to the client when the value is set and wait for a response"""
//|
-//| .. data:: WRITE
+//| NOTIFY: Any = ...
+//| """property: server will notify the client when the value is set"""
//|
-//| property: clients may write this characteristic; a response will be sent back
+//| READ: Any = ...
+//| """property: clients may read this characteristic"""
//|
-//| .. data:: WRITE_NO_RESPONSE
+//| WRITE: Any = ...
+//| """property: clients may write this characteristic; a response will be sent back"""
//|
-//| property: clients may write this characteristic; no response will be sent back
+//| WRITE_NO_RESPONSE: Any = ...
+//| """property: clients may write this characteristic; no response will be sent back"""
//|
{ MP_ROM_QSTR(MP_QSTR_BROADCAST), MP_ROM_INT(CHAR_PROP_BROADCAST) },
{ MP_ROM_QSTR(MP_QSTR_INDICATE), MP_ROM_INT(CHAR_PROP_INDICATE) },
diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c
index fc95d0d50..6cbd587c6 100644
--- a/shared-bindings/_bleio/CharacteristicBuffer.c
+++ b/shared-bindings/_bleio/CharacteristicBuffer.c
@@ -41,24 +41,21 @@ STATIC void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self
}
}
-//| .. currentmodule:: _bleio
+//| class CharacteristicBuffer:
+//| """Accumulates a Characteristic's incoming values in a FIFO buffer."""
//|
-//| :class:`CharacteristicBuffer` -- BLE Service incoming values buffer.
-//| =====================================================================
+//| def __init__(self, characteristic: Characteristic, *, timeout: int = 1, buffer_size: int = 64):
//|
-//| Accumulates a Characteristic's incoming values in a FIFO buffer.
+//| """Monitor the given Characteristic. Each time a new value is written to the Characteristic
+//| add the newly-written bytes to a FIFO buffer.
//|
-//| .. class:: CharacteristicBuffer(characteristic, *, timeout=1, buffer_size=64)
-//|
-//| Monitor the given Characteristic. Each time a new value is written to the Characteristic
-//| add the newly-written bytes to a FIFO buffer.
-//|
-//| :param Characteristic characteristic: The Characteristic to monitor.
-//| It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic
-//| in a remote Service that a Central has connected to.
-//| :param int timeout: the timeout in seconds to wait for the first character and between subsequent characters.
-//| :param int buffer_size: Size of ring buffer that stores incoming data coming from client.
-//| Must be >= 1.
+//| :param Characteristic characteristic: The Characteristic to monitor.
+//| It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic
+//| in a remote Service that a Central has connected to.
+//| :param int timeout: the timeout in seconds to wait for the first character and between subsequent characters.
+//| :param int buffer_size: Size of ring buffer that stores incoming data coming from client.
+//| Must be >= 1."""
+//| ...
//|
STATIC mp_obj_t bleio_characteristic_buffer_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_characteristic, ARG_timeout, ARG_buffer_size, };
@@ -103,29 +100,29 @@ STATIC void check_for_deinit(bleio_characteristic_buffer_obj_t *self) {
// These are standard stream methods. Code is in py/stream.c.
//
-//| .. method:: read(nbytes=None)
-//|
-//| Read characters. If ``nbytes`` is specified then read at most that many
-//| bytes. Otherwise, read everything that arrives until the connection
-//| times out. Providing the number of bytes expected is highly recommended
-//| because it will be faster.
-//|
-//| :return: Data read
-//| :rtype: bytes or None
+//| def read(self, nbytes: Any = None) -> Any:
+//| """Read characters. If ``nbytes`` is specified then read at most that many
+//| bytes. Otherwise, read everything that arrives until the connection
+//| times out. Providing the number of bytes expected is highly recommended
+//| because it will be faster.
//|
-//| .. method:: readinto(buf)
+//| :return: Data read
+//| :rtype: bytes or None"""
+//| ...
//|
-//| Read bytes into the ``buf``. Read at most ``len(buf)`` bytes.
+//| def readinto(self, buf: Any) -> Any:
+//| """Read bytes into the ``buf``. Read at most ``len(buf)`` bytes.
//|
-//| :return: number of bytes read and stored into ``buf``
-//| :rtype: int or None (on a non-blocking error)
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: int or None (on a non-blocking error)"""
+//| ...
//|
-//| .. method:: readline()
+//| def readline(self, ) -> Any:
+//| """Read a line, ending in a newline character.
//|
-//| Read a line, ending in a newline character.
-//|
-//| :return: the line read
-//| :rtype: int or None
+//| :return: the line read
+//| :rtype: int or None"""
+//| ...
//|
// These three methods are used by the shared stream methods.
@@ -170,9 +167,8 @@ STATIC mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t r
return ret;
}
-//| .. attribute:: in_waiting
-//|
-//| The number of bytes in the input buffer, available to be read
+//| in_waiting: Any = ...
+//| """The number of bytes in the input buffer, available to be read"""
//|
STATIC mp_obj_t bleio_characteristic_buffer_obj_get_in_waiting(mp_obj_t self_in) {
bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -188,9 +184,9 @@ const mp_obj_property_t bleio_characteristic_buffer_in_waiting_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: reset_input_buffer()
-//|
-//| Discard any unread characters in the input buffer.
+//| def reset_input_buffer(self, ) -> Any:
+//| """Discard any unread characters in the input buffer."""
+//| ...
//|
STATIC mp_obj_t bleio_characteristic_buffer_obj_reset_input_buffer(mp_obj_t self_in) {
bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -200,9 +196,9 @@ STATIC mp_obj_t bleio_characteristic_buffer_obj_reset_input_buffer(mp_obj_t self
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_buffer_reset_input_buffer_obj, bleio_characteristic_buffer_obj_reset_input_buffer);
-//| .. method:: deinit()
-//|
-//| Disable permanently.
+//| def deinit(self, ) -> Any:
+//| """Disable permanently."""
+//| ...
//|
STATIC mp_obj_t bleio_characteristic_buffer_deinit(mp_obj_t self_in) {
bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/_bleio/CharacteristicBuffer.h b/shared-bindings/_bleio/CharacteristicBuffer.h
index 83e6fef02..e82e96ca9 100644
--- a/shared-bindings/_bleio/CharacteristicBuffer.h
+++ b/shared-bindings/_bleio/CharacteristicBuffer.h
@@ -32,7 +32,7 @@
extern const mp_obj_type_t bleio_characteristic_buffer_type;
extern void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size);
-int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode);
+uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode);
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self);
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self);
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self);
diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c
index c157af365..0a96d8a11 100644
--- a/shared-bindings/_bleio/Connection.c
+++ b/shared-bindings/_bleio/Connection.c
@@ -42,28 +42,24 @@
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Service.h"
-//| .. currentmodule:: _bleio
+//| class Connection:
+//| """A BLE connection to another device. Used to discover and interact with services on the other
+//| device.
//|
-//| :class:`Connection` -- A BLE connection
-//| =========================================================
+//| Usage::
//|
-//| A BLE connection to another device. Used to discover and interact with services on the other
-//| device.
+//| import _bleio
//|
-//| Usage::
+//| my_entry = None
+//| for entry in _bleio.adapter.scan(2.5):
+//| if entry.name is not None and entry.name == 'InterestingPeripheral':
+//| my_entry = entry
+//| break
//|
-//| import _bleio
+//| if not my_entry:
+//| raise Exception("'InterestingPeripheral' not found")
//|
-//| my_entry = None
-//| for entry in _bleio.adapter.scan(2.5):
-//| if entry.name is not None and entry.name == 'InterestingPeripheral':
-//| my_entry = entry
-//| break
-//|
-//| if not my_entry:
-//| raise Exception("'InterestingPeripheral' not found")
-//|
-//| connection = _bleio.adapter.connect(my_entry.address, timeout=10)
+//| connection = _bleio.adapter.connect(my_entry.address, timeout=10)"""
//|
void bleio_connection_ensure_connected(bleio_connection_obj_t *self) {
@@ -72,15 +68,15 @@ void bleio_connection_ensure_connected(bleio_connection_obj_t *self) {
}
}
-//| .. class:: Connection()
-//|
-//| Connections cannot be made directly. Instead, to initiate a connection use `Adapter.connect`.
-//| Connections may also be made when another device initiates a connection. To use a Connection
-//| created by a peer, read the `Adapter.connections` property.
+//| def __init__(self, ):
+//| """Connections cannot be made directly. Instead, to initiate a connection use `Adapter.connect`.
+//| Connections may also be made when another device initiates a connection. To use a Connection
+//| created by a peer, read the `Adapter.connections` property.
+//| ...
//|
-//| .. method:: disconnect()
-//|
-//| Disconnects from the remote peripheral. Does nothing if already disconnected.
+//| def disconnect(self, ) -> Any:
+//| ""Disconnects from the remote peripheral. Does nothing if already disconnected."""
+//| ...
//|
STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -91,9 +87,9 @@ STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connection_disconnect);
-//| .. method:: pair(*, bond=True)
-//|
-//| Pair to the peer to improve security.
+//| def pair(self, *, bond: Any = True) -> Any:
+//| """Pair to the peer to improve security."""
+//| ...
//|
STATIC mp_obj_t bleio_connection_pair(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -113,29 +109,29 @@ STATIC mp_obj_t bleio_connection_pair(mp_uint_t n_args, const mp_obj_t *pos_args
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_pair_obj, 1, bleio_connection_pair);
-//| .. method:: discover_remote_services(service_uuids_whitelist=None)
-//|
-//| 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.
+//| def discover_remote_services(self, service_uuids_whitelist: iterable = None) -> Any:
+//| """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.
//|
-//| :param iterable service_uuids_whitelist:
+//| :param iterable service_uuids_whitelist:
//|
-//| an iterable of :py:class:~`UUID` objects for the services provided by the peripheral
-//| that you want to use.
+//| 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
-//| and will not be returned.
+//| The peripheral may provide more services, but services not listed are ignored
+//| and will not be returned.
//|
-//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be
-//| slow.
+//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be
+//| 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
-//| 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.)
+//| 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
+//| 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.)
//|
-//| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral.
+//| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral."""
+//| ...
//|
STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -156,9 +152,8 @@ STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, cons
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_discover_remote_services_obj, 1, bleio_connection_discover_remote_services);
-//| .. attribute:: connected
-//|
-//| True if connected to the remote peer.
+//| connected: Any = ...
+//| """True if connected to the remote peer."""
//|
STATIC mp_obj_t bleio_connection_get_connected(mp_obj_t self_in) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -175,9 +170,8 @@ const mp_obj_property_t bleio_connection_connected_obj = {
};
-//| .. attribute:: paired
-//|
-//| True if paired to the remote peer.
+//| paired: Any = ...
+//| """True if paired to the remote peer."""
//|
STATIC mp_obj_t bleio_connection_get_paired(mp_obj_t self_in) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -194,17 +188,15 @@ const mp_obj_property_t bleio_connection_paired_obj = {
};
-//| .. attribute:: connection_interval
-//|
-//| Time between transmissions in milliseconds. Will be multiple of 1.25ms. Lower numbers
+//| connection_interval: Any = ...
+//| """Time between transmissions in milliseconds. Will be multiple of 1.25ms. Lower numbers
//| increase speed and decrease latency but increase power consumption.
//|
//| When setting connection_interval, the peer may reject the new interval and
//| `connection_interval` will then remain the same.
//|
//| Apple has additional guidelines that dictate should be a multiple of 15ms except if HID is
-//| available. When HID is available Apple devices may accept 11.25ms intervals.
-//|
+//| available. When HID is available Apple devices may accept 11.25ms intervals."""
//|
STATIC mp_obj_t bleio_connection_get_connection_interval(mp_obj_t self_in) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -214,6 +206,24 @@ STATIC mp_obj_t bleio_connection_get_connection_interval(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connection_interval_obj, bleio_connection_get_connection_interval);
+//| attribute: Any = ...
+//| """The maximum number of data bytes that can be sent in a single transmission,
+//| not including overhead bytes.
+//|
+//| This is the maximum number of bytes that can be sent in a notification,
+//| which must be sent in a single packet.
+//| But for a regular characteristic read or write, may be sent in multiple packets,
+//| so this limit does not apply."""
+//|
+STATIC mp_obj_t bleio_connection_get_max_packet_length(mp_obj_t self_in) {
+ bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ bleio_connection_ensure_connected(self);
+ return mp_obj_new_int(common_hal_bleio_connection_get_max_packet_length(self->connection));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_max_packet_length_obj, bleio_connection_get_max_packet_length);
+
+
STATIC mp_obj_t bleio_connection_set_connection_interval(mp_obj_t self_in, mp_obj_t interval_in) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -233,6 +243,13 @@ const mp_obj_property_t bleio_connection_connection_interval_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+const mp_obj_property_t bleio_connection_max_packet_length_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_connection_get_max_packet_length_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_connection_pair_obj) },
@@ -243,7 +260,7 @@ STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_paired), MP_ROM_PTR(&bleio_connection_paired_obj) },
{ MP_ROM_QSTR(MP_QSTR_connection_interval), MP_ROM_PTR(&bleio_connection_connection_interval_obj) },
-
+ { MP_ROM_QSTR(MP_QSTR_max_packet_length), MP_ROM_PTR(&bleio_connection_max_packet_length_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table);
diff --git a/shared-bindings/_bleio/Connection.h b/shared-bindings/_bleio/Connection.h
index c6f260160..a5313a937 100644
--- a/shared-bindings/_bleio/Connection.h
+++ b/shared-bindings/_bleio/Connection.h
@@ -34,11 +34,12 @@
extern const mp_obj_type_t bleio_connection_type;
-extern void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond);
-extern void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self);
-extern bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self);
-extern bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self);
-extern mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist);
+void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond);
+void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self);
+bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self);
+mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self);
+bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self);
+mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist);
mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self);
void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval);
diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c
index f7b6b5bbf..9d7020849 100644
--- a/shared-bindings/_bleio/Descriptor.c
+++ b/shared-bindings/_bleio/Descriptor.c
@@ -33,41 +33,38 @@
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/UUID.h"
-//| .. currentmodule:: _bleio
+//| class Descriptor:
+//| """Stores information about a BLE descriptor.
//|
-//| :class:`Descriptor` -- BLE descriptor
-//| =========================================================
+//| Descriptors are attached to BLE characteristics and provide contextual
+//| information about the characteristic."""
//|
-//| Stores information about a BLE descriptor.
-//| Descriptors are attached to BLE characteristics and provide contextual
-//| information about the characteristic.
+//| def __init__(self, ):
+//| """There is no regular constructor for a Descriptor. A new local Descriptor can be created
+//| and attached to a Characteristic by calling `add_to_characteristic()`.
+//| Remote Descriptor objects are created by `Connection.discover_remote_services()`
+//| as part of remote Characteristics in the remote Services that are discovered.
//|
-//| .. class:: Descriptor
+//| .. classmethod:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'')
//|
-//| There is no regular constructor for a Descriptor. A new local Descriptor can be created
-//| and attached to a Characteristic by calling `add_to_characteristic()`.
-//| Remote Descriptor objects are created by `Connection.discover_remote_services()`
-//| as part of remote Characteristics in the remote Services that are discovered.
+//| Create a new Descriptor object, and add it to this Service.
//|
-//| .. classmethod:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'')
+//| :param Characteristic characteristic: The characteristic that will hold this descriptor
+//| :param UUID uuid: The uuid of the descriptor
+//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which
+//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
+//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
+//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
+//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which
+//| security mode is required. Values allowed are the same as ``read_perm``.
+//| :param int max_length: Maximum length in bytes of the descriptor value. The maximum allowed is
+//| 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.
//|
-//| Create a new Descriptor object, and add it to this Service.
-//|
-//| :param Characteristic characteristic: The characteristic that will hold this descriptor
-//| :param UUID uuid: The uuid of the descriptor
-//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which
-//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
-//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
-//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
-//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which
-//| security mode is required. Values allowed are the same as ``read_perm``.
-//| :param int max_length: Maximum length in bytes of the descriptor value. The maximum allowed is
-//| 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.
-//|
-//| :return: the new Descriptor.
+//| :return: the new Descriptor."""
+//| ...
//|
STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// class is arg[0], which we can ignore.
@@ -135,9 +132,8 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_descriptor_add_to_characteristic_fun_obj, 3, bleio_descriptor_add_to_characteristic);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_descriptor_add_to_characteristic_obj, MP_ROM_PTR(&bleio_descriptor_add_to_characteristic_fun_obj));
-//| .. attribute:: uuid
-//|
-//| The descriptor uuid. (read-only)
+//| uuid: Any = ...
+//| """The descriptor uuid. (read-only)"""
//|
STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) {
bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -154,9 +150,8 @@ const mp_obj_property_t bleio_descriptor_uuid_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: characteristic (read-only)
-//|
-//| The Characteristic this Descriptor is a part of.
+//| characteristic: Any = ...
+//| """The Characteristic this Descriptor is a part of."""
//|
STATIC mp_obj_t bleio_descriptor_get_characteristic(mp_obj_t self_in) {
bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -172,9 +167,8 @@ const mp_obj_property_t bleio_descriptor_characteristic_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: value
-//|
-//| The value of this descriptor.
+//| value: Any = ...
+//| """The value of this descriptor."""
//|
STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) {
bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/_bleio/PacketBuffer.c b/shared-bindings/_bleio/PacketBuffer.c
index 3ed295f01..907bfabd2 100644
--- a/shared-bindings/_bleio/PacketBuffer.c
+++ b/shared-bindings/_bleio/PacketBuffer.c
@@ -35,29 +35,28 @@
#include "shared-bindings/_bleio/UUID.h"
#include "shared-bindings/util.h"
-//| .. currentmodule:: _bleio
+//| class PacketBuffer:
+//| """Accumulates a Characteristic's incoming packets in a FIFO buffer and facilitates packet aware
+//| outgoing writes. A packet's size is either the characteristic length or the maximum transmission
+//| unit (MTU) minus overhead, whichever is smaller. The MTU can change so check `incoming_packet_length`
+//| and `outgoing_packet_length` before creating a buffer to store data.
//|
-//| :class:`PacketBuffer` -- Packet-oriented characteristic usage.
-//| =====================================================================
+//| When we're the server, we ignore all connections besides the first to subscribe to
+//| notifications."""
//|
-//| Accumulates a Characteristic's incoming packets in a FIFO buffer and facilitates packet aware
-//| outgoing writes. A packet's size is either the characteristic length or the maximum transmission
-//| unit (MTU), whichever is smaller. The MTU can change so check `packet_size` before creating a
-//| buffer to store data.
+//| def __init__(self, characteristic: Characteristic, *, buffer_size: int):
+//| """Monitor the given Characteristic. Each time a new value is written to the Characteristic
+//| add the newly-written bytes to a FIFO buffer.
//|
-//| When we're the server, we ignore all connections besides the first to subscribe to
-//| notifications.
+//| Monitor the given Characteristic. Each time a new value is written to the Characteristic
+//| add the newly-written packet of bytes to a FIFO buffer.
//|
-//| .. class:: PacketBuffer(characteristic, *, buffer_size)
-//|
-//| Monitor the given Characteristic. Each time a new value is written to the Characteristic
-//| add the newly-written bytes to a FIFO buffer.
-//|
-//| :param Characteristic characteristic: The Characteristic to monitor.
-//| It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic
-//| in a remote Service that a Central has connected to.
-//| :param int buffer_size: Size of ring buffer (in packets of the Characteristic's maximum
-//| length) that stores incoming packets coming from the peer.
+//| :param Characteristic characteristic: The Characteristic to monitor.
+//| It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic
+//| in a remote Service that a Central has connected to.
+//| :param int buffer_size: Size of ring buffer (in packets of the Characteristic's maximum
+//| length) that stores incoming packets coming from the peer."""
+//| ...
//|
STATIC mp_obj_t bleio_packet_buffer_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_characteristic, ARG_buffer_size };
@@ -71,7 +70,7 @@ STATIC mp_obj_t bleio_packet_buffer_make_new(const mp_obj_type_t *type, size_t n
const mp_obj_t characteristic = args[ARG_characteristic].u_obj;
- const int buffer_size = args[ARG_buffer_size].u_int;
+ const mp_int_t buffer_size = args[ARG_buffer_size].u_int;
if (buffer_size < 1) {
mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_buffer_size);
}
@@ -94,13 +93,13 @@ STATIC void check_for_deinit(bleio_packet_buffer_obj_t *self) {
}
}
-//| .. method:: readinto(buf)
-//|
-//| Reads a single BLE packet into the ``buf``. Raises an exception if the next packet is longer
-//| than the given buffer. Use `packet_size` to read the maximum length of a single packet.
+//| def readinto(self, buf: Any) -> Any:
+//| """Reads a single BLE packet into the ``buf``. Raises an exception if the next packet is longer
+//| than the given buffer. Use `packet_size` to read the maximum length of a single packet.
//|
-//| :return: number of bytes read and stored into ``buf``
-//| :rtype: int
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: int"""
+//| ...
//|
STATIC mp_obj_t bleio_packet_buffer_readinto(mp_obj_t self_in, mp_obj_t buffer_obj) {
bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -109,16 +108,24 @@ STATIC mp_obj_t bleio_packet_buffer_readinto(mp_obj_t self_in, mp_obj_t buffer_o
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buffer_obj, &bufinfo, MP_BUFFER_WRITE);
- return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_packet_buffer_readinto(self, bufinfo.buf, bufinfo.len));
+ mp_int_t size = common_hal_bleio_packet_buffer_readinto(self, bufinfo.buf, bufinfo.len);
+ if (size < 0) {
+ mp_raise_ValueError_varg(translate("Buffer too short by %d bytes"), size * -1);
+ }
+
+ return MP_OBJ_NEW_SMALL_INT(size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_packet_buffer_readinto_obj, bleio_packet_buffer_readinto);
-//| .. method:: write(data, *, header=None)
+//| def write(self, data: Any, *, header: Any = None) -> Any:
+//| """Writes all bytes from data into the same outgoing packet. The bytes from header are included
+//| before data when the pending packet is currently empty.
//|
-//| Writes all bytes from data into the same outgoing packet. The bytes from header are included
-//| before data when the pending packet is currently empty.
+//| This does not block until the data is sent. It only blocks until the data is pending.
//|
-//| This does not block until the data is sent. It only blocks until the data is pending.
+//| :return: number of bytes written. May include header bytes when packet is empty.
+//| :rtype: int"""
+//| ...
//|
// TODO: Add a kwarg `merge=False` to dictate whether subsequent writes are merged into a pending
// one.
@@ -144,16 +151,27 @@ STATIC mp_obj_t bleio_packet_buffer_write(mp_uint_t n_args, const mp_obj_t *pos_
mp_get_buffer_raise(args[ARG_header].u_obj, &header_bufinfo, MP_BUFFER_READ);
}
- common_hal_bleio_packet_buffer_write(self, data_bufinfo.buf, data_bufinfo.len,
- header_bufinfo.buf, header_bufinfo.len);
- return mp_const_none;
+ mp_int_t num_bytes_written = common_hal_bleio_packet_buffer_write(
+ self, data_bufinfo.buf, data_bufinfo.len, header_bufinfo.buf, header_bufinfo.len);
+ if (num_bytes_written < 0) {
+ // TODO: Raise an error if not connected. Right now the not-connected error
+ // is unreliable, because common_hal_bleio_packet_buffer_write()
+ // checks for conn_handle being set, but setting that
+ // can be delayed because conn_handle is discovered by spying on
+ // gatts write events, which may not have been sent yet.
+ //
+ // IDEAL:
+ // mp_raise_bleio_ConnectionError(translate("Not connected"));
+ // TEMPORARY:
+ num_bytes_written = 0;
+ }
+ return MP_OBJ_NEW_SMALL_INT(num_bytes_written);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_packet_buffer_write_obj, 1, bleio_packet_buffer_write);
-//| .. method:: deinit()
-//|
-//| Disable permanently.
-//|
+//| def deinit(self) -> Any:
+//| """Disable permanently."""
+//| ...
STATIC mp_obj_t bleio_packet_buffer_deinit(mp_obj_t self_in) {
bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_bleio_packet_buffer_deinit(self);
@@ -161,33 +179,65 @@ STATIC mp_obj_t bleio_packet_buffer_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_packet_buffer_deinit_obj, bleio_packet_buffer_deinit);
-//| .. attribute:: packet_size
+//| packet_size: int = ...
+//| """`packet_size` is the same as `incoming_packet_length`.
+//| The name `packet_size` is deprecated and
+//| will be removed in CircuitPython 6.0.0."""
//|
-//| Maximum size of each packet in bytes. This is the minimum of the Characteristic length and
-//| the negotiated Maximum Transfer Unit (MTU).
+//| incoming_packet_length: Any = ...
+//| """Maximum length in bytes of a packet we are reading."""
+//|
+STATIC mp_obj_t bleio_packet_buffer_get_incoming_packet_length(mp_obj_t self_in) {
+ bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_int_t size = common_hal_bleio_packet_buffer_get_incoming_packet_length(self);
+ if (size < 0) {
+ mp_raise_ValueError(translate("No connection: length cannot be determined"));
+ }
+ return MP_OBJ_NEW_SMALL_INT(size);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_packet_buffer_get_incoming_packet_length_obj, bleio_packet_buffer_get_incoming_packet_length);
+
+const mp_obj_property_t bleio_packet_buffer_incoming_packet_length_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_packet_buffer_get_incoming_packet_length_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| outgoing_packet_length: int = ...
+//| """Maximum length in bytes of a packet we are writing."""
//|
-STATIC mp_obj_t bleio_packet_buffer_get_packet_size(mp_obj_t self_in) {
+STATIC mp_obj_t bleio_packet_buffer_get_outgoing_packet_length(mp_obj_t self_in) {
bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_packet_buffer_get_packet_size(self));
+ mp_int_t size = common_hal_bleio_packet_buffer_get_outgoing_packet_length(self);
+ if (size < 0) {
+ mp_raise_ValueError(translate("No connection: length cannot be determined"));
+ }
+ return MP_OBJ_NEW_SMALL_INT(size);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_packet_buffer_get_packet_size_obj, bleio_packet_buffer_get_packet_size);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_packet_buffer_get_outgoing_packet_length_obj, bleio_packet_buffer_get_outgoing_packet_length);
-const mp_obj_property_t bleio_packet_buffer_packet_size_obj = {
+const mp_obj_property_t bleio_packet_buffer_outgoing_packet_length_obj = {
.base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_packet_buffer_get_packet_size_obj,
+ .proxy = { (mp_obj_t)&bleio_packet_buffer_get_outgoing_packet_length_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj },
};
STATIC const mp_rom_map_elem_t bleio_packet_buffer_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bleio_packet_buffer_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bleio_packet_buffer_deinit_obj) },
// Standard stream methods.
- { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bleio_packet_buffer_readinto_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_packet_buffer_write_obj) },
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_packet_size), MP_ROM_PTR(&bleio_packet_buffer_packet_size_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bleio_packet_buffer_readinto_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_packet_buffer_write_obj) },
+
+ // .packet_size is now an alias for .incoming_packet_length
+ // TODO: Remove in 6.0.0.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_packet_size), MP_ROM_PTR(&bleio_packet_buffer_incoming_packet_length_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_incoming_packet_length), MP_ROM_PTR(&bleio_packet_buffer_incoming_packet_length_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_outgoing_packet_length), MP_ROM_PTR(&bleio_packet_buffer_outgoing_packet_length_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_packet_buffer_locals_dict, bleio_packet_buffer_locals_dict_table);
diff --git a/shared-bindings/_bleio/PacketBuffer.h b/shared-bindings/_bleio/PacketBuffer.h
index 990a2f8bb..769e0a0c7 100644
--- a/shared-bindings/_bleio/PacketBuffer.h
+++ b/shared-bindings/_bleio/PacketBuffer.h
@@ -34,9 +34,10 @@ extern const mp_obj_type_t bleio_packet_buffer_type;
extern void common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
size_t buffer_size);
-void common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len, uint8_t* header, size_t header_len);
-int common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len);
-uint16_t common_hal_bleio_packet_buffer_get_packet_size(bleio_packet_buffer_obj_t *self);
+mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len, uint8_t* header, size_t header_len);
+mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len);
+mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self);
+mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_buffer_obj_t *self);
bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self);
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self);
diff --git a/shared-bindings/_bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c
index d03cd6fb5..905bea81d 100644
--- a/shared-bindings/_bleio/ScanEntry.c
+++ b/shared-bindings/_bleio/ScanEntry.c
@@ -35,25 +35,21 @@
#include "shared-bindings/_bleio/UUID.h"
#include "shared-module/_bleio/ScanEntry.h"
-//| .. currentmodule:: _bleio
-//|
-//| :class:`ScanEntry` -- BLE scan data
-//| =========================================================
-//|
-//| Encapsulates information about a device that was received during scanning. It can be
-//| advertisement or scan response data. This object may only be created by a `_bleio.ScanResults`:
-//| it has no user-visible constructor.
+//| class ScanEntry:
+//| """Encapsulates information about a device that was received during scanning. It can be
+//| advertisement or scan response data. This object may only be created by a `_bleio.ScanResults`:
+//| it has no user-visible constructor."""
//|
-//| .. class:: ScanEntry()
-//|
-//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`.
+//| def __init__(self, ):
+//| """Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`."""
+//| ...
//|
-//| .. method:: matches(prefixes, *, all=True)
-//|
-//| Returns True if the ScanEntry matches all prefixes when ``all`` is True. This is stricter
-//| than the scan filtering which accepts any advertisements that match any of the prefixes
-//| where all is False.
+//| def matches(self, prefixes: Any, *, all: Any = True) -> Any:
+//| """Returns True if the ScanEntry matches all prefixes when ``all`` is True. This is stricter
+//| than the scan filtering which accepts any advertisements that match any of the prefixes
+//| where all is False."""
+//| ...
//|
STATIC mp_obj_t bleio_scanentry_matches(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -67,16 +63,15 @@ STATIC mp_obj_t bleio_scanentry_matches(mp_uint_t n_args, const mp_obj_t *pos_ar
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_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_prefixes].u_obj, &bufinfo, MP_BUFFER_READ);
return mp_obj_new_bool(common_hal_bleio_scanentry_matches(self, bufinfo.buf, bufinfo.len, args[ARG_all].u_bool));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanentry_matches_obj, 2, bleio_scanentry_matches);
-//| .. attribute:: address
-//|
-//| The address of the device (read-only), of type `_bleio.Address`.
+//| address: Any = ...
+//| """The address of the device (read-only), of type `_bleio.Address`."""
//|
STATIC mp_obj_t bleio_scanentry_get_address(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -91,9 +86,8 @@ const mp_obj_property_t bleio_scanentry_address_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: advertisement_bytes
-//|
-//| All the advertisement data present in the packet, returned as a ``bytes`` object. (read-only)
+//| advertisement_bytes: Any = ...
+//| """All the advertisement data present in the packet, returned as a ``bytes`` object. (read-only)"""
//|
STATIC mp_obj_t scanentry_get_advertisement_bytes(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -108,9 +102,8 @@ const mp_obj_property_t bleio_scanentry_advertisement_bytes_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: rssi
-//|
-//| The signal strength of the device at the time of the scan, in integer dBm. (read-only)
+//| rssi: Any = ...
+//| """The signal strength of the device at the time of the scan, in integer dBm. (read-only)"""
//|
STATIC mp_obj_t scanentry_get_rssi(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -125,9 +118,8 @@ const mp_obj_property_t bleio_scanentry_rssi_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: connectable
-//|
-//| True if the device can be connected to. (read-only)
+//| connectable: Any = ...
+//| """True if the device can be connected to. (read-only)"""
//|
STATIC mp_obj_t scanentry_get_connectable(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -142,9 +134,8 @@ const mp_obj_property_t bleio_scanentry_connectable_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: scan_response
-//|
-//| True if the entry was a scan response. (read-only)
+//| scan_response: Any = ...
+//| """True if the entry was a scan response. (read-only)"""
//|
STATIC mp_obj_t scanentry_get_scan_response(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/_bleio/ScanResults.c b/shared-bindings/_bleio/ScanResults.c
index dcece3d5d..6077dcbda 100644
--- a/shared-bindings/_bleio/ScanResults.c
+++ b/shared-bindings/_bleio/ScanResults.c
@@ -32,13 +32,9 @@
#include "py/runtime.h"
#include "shared-bindings/_bleio/ScanResults.h"
-//| .. currentmodule:: _bleio
-//|
-//| :class:`ScanResults` -- An Iterator over BLE scanning results
-//| ===============================================================
-//|
-//| Iterates over advertising data received while scanning. This object is always created
-//| by a `_bleio.Adapter`: it has no user-visible constructor.
+//| class ScanResults:
+//| """Iterates over advertising data received while scanning. This object is always created
+//| by a `_bleio.Adapter`: it has no user-visible constructor."""
//|
STATIC mp_obj_t scanresults_iternext(mp_obj_t self_in) {
mp_check_self(MP_OBJ_IS_TYPE(self_in, &bleio_scanresults_type));
@@ -50,18 +46,18 @@ STATIC mp_obj_t scanresults_iternext(mp_obj_t self_in) {
return MP_OBJ_STOP_ITERATION;
}
-//| .. class:: ScanResults()
-//|
-//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`.
-//|
-//| .. method:: __iter__()
-//|
-//| Returns itself since it is the iterator.
+//| def __init__(self, ):
+//| """Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`."""
+//| ...
//|
-//| .. method:: __next__()
+//| def __iter__(self, ) -> Any:
+//| """Returns itself since it is the iterator."""
+//| ...
//|
-//| Returns the next `_bleio.ScanEntry`. Blocks if none have been received and scanning is still
-//| active. Raises `StopIteration` if scanning is finished and no other results are available.
+//| def __next__(self, ) -> Any:
+//| """Returns the next `_bleio.ScanEntry`. Blocks if none have been received and scanning is still
+//| active. Raises `StopIteration` if scanning is finished and no other results are available."""
+//| ...
//|
const mp_obj_type_t bleio_scanresults_type = {
diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c
index bc242bc36..5ca7504f2 100644
--- a/shared-bindings/_bleio/Service.c
+++ b/shared-bindings/_bleio/Service.c
@@ -32,25 +32,21 @@
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
-//| .. currentmodule:: _bleio
+//| class Service:
+//| """Stores information about a BLE service and its characteristics."""
//|
-//| :class:`Service` -- BLE GATT Service
-//| =========================================================
+//| def __init__(self, uuid: UUID, *, secondary: bool = False):
+//| """Create a new Service identified by the specified UUID. It can be accessed by all
+//| connections. This is known as a Service server. Client Service objects are created via
+//| `Connection.discover_remote_services`.
//|
-//| Stores information about a BLE service and its characteristics.
+//| To mark the Service as secondary, pass `True` as :py:data:`secondary`.
//|
-//| .. class:: Service(uuid, *, secondary=False)
+//| :param UUID uuid: The uuid of the service
+//| :param bool secondary: If the service is a secondary one
//|
-//| Create a new Service identified by the specified UUID. It can be accessed by all
-//| connections. This is known as a Service server. Client Service objects are created via
-//| `Connection.discover_remote_services`.
-//|
-//| To mark the Service as secondary, pass `True` as :py:data:`secondary`.
-//|
-//| :param UUID uuid: The uuid of the service
-//| :param bool secondary: If the service is a secondary one
-//
-//| :return: the new Service
+//| :return: the new Service"""
+//| ...
//|
STATIC mp_obj_t bleio_service_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_uuid, ARG_secondary };
@@ -77,10 +73,9 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(service);
}
-//| .. attribute:: characteristics
-//|
-//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by
-//| this service. (read-only)
+//| characteristics: Any = ...
+//| """A tuple of :py:class:`Characteristic` designating the characteristics that are offered by
+//| this service. (read-only)"""
//|
STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) {
bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -97,9 +92,8 @@ const mp_obj_property_t bleio_service_characteristics_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: remote
-//|
-//| True if this is a service provided by a remote device. (read-only)
+//| remote: Any = ...
+//| """True if this is a service provided by a remote device. (read-only)"""
//|
STATIC mp_obj_t bleio_service_get_remote(mp_obj_t self_in) {
bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -115,9 +109,8 @@ const mp_obj_property_t bleio_service_remote_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: secondary
-//|
-//| True if this is a secondary service. (read-only)
+//| secondary: Any = ...
+//| """True if this is a secondary service. (read-only)"""
//|
STATIC mp_obj_t bleio_service_get_secondary(mp_obj_t self_in) {
bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -133,11 +126,10 @@ const mp_obj_property_t bleio_service_secondary_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. attribute:: uuid
-//|
-//| The UUID of this service. (read-only)
+//| uuid: Any = ...
+//| """The UUID of this service. (read-only)
//|
-//| Will be ``None`` if the 128-bit UUID for this service is not known.
+//| Will be ``None`` if the 128-bit UUID for this service is not known."""
//|
STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) {
bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c
index dd3415902..78161b956 100644
--- a/shared-bindings/_bleio/UUID.c
+++ b/shared-bindings/_bleio/UUID.c
@@ -33,28 +33,23 @@
#include "py/runtime.h"
#include "shared-bindings/_bleio/UUID.h"
-//| .. currentmodule:: _bleio
+//| class UUID:
+//| """A 16-bit or 128-bit UUID. Can be used for services, characteristics, descriptors and more."""
//|
-//| :class:`UUID` -- BLE UUID
-//| =========================================================
+//| def __init__(self, value: Any):
+//| """Create a new UUID or UUID object encapsulating the uuid value.
+//| The value can be one of:
//|
-//| A 16-bit or 128-bit UUID. Can be used for services, characteristics, descriptors and more.
+//| - an `int` value in range 0 to 0xFFFF (Bluetooth SIG 16-bit UUID)
+//| - a buffer object (bytearray, bytes) of 16 bytes in little-endian order (128-bit UUID)
+//| - a string of hex digits of the form 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
//|
-
-//| .. class:: UUID(value)
-//|
-//| Create a new UUID or UUID object encapsulating the uuid value.
-//| The value can be one of:
-//|
-//| - an `int` value in range 0 to 0xFFFF (Bluetooth SIG 16-bit UUID)
-//| - a buffer object (bytearray, bytes) of 16 bytes in little-endian order (128-bit UUID)
-//| - a string of hex digits of the form 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+//| Creating a 128-bit UUID registers the UUID with the onboard BLE software, and provides a
+//| temporary 16-bit UUID that can be used in place of the full 128-bit UUID.
//|
-//| Creating a 128-bit UUID registers the UUID with the onboard BLE software, and provides a
-//| 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
+//| :param value: The uuid value to encapsulate
+//| :type value: int or typing.ByteString"""
+//| ...
//|
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) {
mp_arg_check_num(n_args, kw_args, 1, 1, false);
@@ -125,11 +120,10 @@ STATIC mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, co
return MP_OBJ_FROM_PTR(self);
}
-//| .. attribute:: uuid16
-//|
-//| The 16-bit part of the UUID. (read-only)
+//| uuid16: Any = ...
+//| """The 16-bit part of the UUID. (read-only)
//|
-//| :type: int
+//| :type: int"""
//|
STATIC mp_obj_t bleio_uuid_get_uuid16(mp_obj_t self_in) {
bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -145,12 +139,11 @@ const mp_obj_property_t bleio_uuid_uuid16_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: uuid128
-//|
-//| The 128-bit value of the UUID
+//| uuid128: Any = ...
+//| """The 128-bit value of the UUID
//| Raises AttributeError if this is a 16-bit UUID. (read-only)
//|
-//| :type: bytes
+//| :type: bytes"""
//|
STATIC mp_obj_t bleio_uuid_get_uuid128(mp_obj_t self_in) {
bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -172,12 +165,11 @@ const mp_obj_property_t bleio_uuid_uuid128_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: size
-//|
-//| 128 if this UUID represents a 128-bit vendor-specific UUID. 16 if this UUID represents a
+//| size: Any = ...
+//| """128 if this UUID represents a 128-bit vendor-specific UUID. 16 if this UUID represents a
//| 16-bit Bluetooth SIG assigned UUID. (read-only) 32-bit UUIDs are not currently supported.
//|
-//| :type: int
+//| :type: int"""
//|
STATIC mp_obj_t bleio_uuid_get_size(mp_obj_t self_in) {
bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -194,9 +186,9 @@ const mp_obj_property_t bleio_uuid_size_obj = {
};
-//| .. method:: pack_into(buffer, offset=0)
-//|
-//| Packs the UUID into the given buffer at the given offset.
+//| def pack_into(self, buffer: Any, offset: Any = 0) -> Any:
+//| """Packs the UUID into the given buffer at the given offset."""
+//| ...
//|
STATIC mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -210,7 +202,7 @@ STATIC mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args,
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_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
@@ -256,11 +248,9 @@ STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//|
-
-//| .. method:: __eq__(other)
-//|
-//| Two UUID objects are equal if their values match and they are both 128-bit or both 16-bit.
+//| def __eq__(self, other: Any) -> Any:
+//| """Two UUID objects are equal if their values match and they are both 128-bit or both 16-bit."""
+//| ...
//|
STATIC mp_obj_t bleio_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
switch (op) {
diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c
index dd401398c..90b185f79 100644
--- a/shared-bindings/_bleio/__init__.c
+++ b/shared-bindings/_bleio/__init__.c
@@ -41,13 +41,7 @@
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
-//| :mod:`_bleio` --- Bluetooth Low Energy (BLE) communication
-//| ================================================================
-//|
-//| .. module:: _bleio
-//| :synopsis: Bluetooth Low Energy functionality
-//| :platform: nRF
-//|
+//| """
//| 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
@@ -58,34 +52,17 @@
//| provides higher-level convenience functionality, including predefined beacons, clients,
//| servers.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Address
-//| Adapter
-//| Attribute
-//| Characteristic
-//| CharacteristicBuffer
-//| Connection
-//| Descriptor
-//| PacketBuffer
-//| ScanEntry
-//| ScanResults
-//| Service
-//| UUID
-//|
//| .. attribute:: adapter
//|
//| BLE Adapter used to manage device discovery and connections.
-//| This object is the sole instance of `_bleio.Adapter`.
+//| This object is the sole instance of `_bleio.Adapter`."""
//|
-//| .. class:: BluetoothError(Exception)
-//|
-//| Catch all exception for Bluetooth related errors.
-//|
+
+//| class BluetoothError:
+//| def __init__(self, Exception: Any):
+//| """Catch all exception for Bluetooth related errors."""
+//| ...
MP_DEFINE_BLEIO_EXCEPTION(BluetoothError, Exception)
NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t* fmt, ...) {
@@ -95,10 +72,10 @@ NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t* fmt, ...)
va_end(argptr);
nlr_raise(exception);
}
-
-//| .. class:: ConnectionError(BluetoothError)
-//|
-//| Raised when a connection is unavailable.
+//| class ConnectionError:
+//| def __init__(self, BluetoothError: Any):
+//| """Raised when a connection is unavailable."""
+//| ...
//|
MP_DEFINE_BLEIO_EXCEPTION(ConnectionError, bleio_BluetoothError)
NORETURN void mp_raise_bleio_ConnectionError(const compressed_string_t* fmt, ...) {
@@ -109,19 +86,20 @@ NORETURN void mp_raise_bleio_ConnectionError(const compressed_string_t* fmt, ...
nlr_raise(exception);
}
-//| .. class:: RoleError(BluetoothError)
-//|
-//| Raised when a resource is used as the mismatched role. For example, if a local CCCD is
-//| attempted to be set but they can only be set when remote.
+//| class RoleError:
+//| def __init__(self, BluetoothError: Any):
+//| """Raised when a resource is used as the mismatched role. For example, if a local CCCD is
+//| attempted to be set but they can only be set when remote."""
+//| ...
//|
MP_DEFINE_BLEIO_EXCEPTION(RoleError, bleio_BluetoothError)
NORETURN void mp_raise_bleio_RoleError(const compressed_string_t* msg) {
mp_raise_msg(&mp_type_bleio_RoleError, msg);
}
-
-//| .. class:: SecurityError(BluetoothError)
-//|
-//| Raised when a security related error occurs.
+//| class SecurityError:
+//| def __init__(self, BluetoothError: Any):
+//| """Raised when a security related error occurs."""
+//| ...
//|
MP_DEFINE_BLEIO_EXCEPTION(SecurityError, bleio_BluetoothError)
NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* fmt, ...) {
diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c
index 9bc790f5d..4fa48f2c7 100644
--- a/shared-bindings/_eve/__init__.c
+++ b/shared-bindings/_eve/__init__.c
@@ -34,16 +34,11 @@
#include "shared-module/_eve/__init__.h"
#include "shared-bindings/_eve/__init__.h"
-//| :mod:`_eve` --- low-level BridgeTek EVE bindings
-//| ================================================
-//|
-//| .. module:: _eve
-//| :synopsis: low-level BridgeTek EVE bindings
-//| :platform: SAMD21/SAMD51
+//| """Low-level BridgeTek EVE bindings
//|
//| The `_eve` module provides a class _EVE which
-//| contains methods for constructing EVE command
-//| buffers and appending basic graphics commands.
+//| contains methods for constructing EVE command
+//| buffers and appending basic graphics commands."""
//|
typedef struct _mp_obj__EVE_t {
@@ -63,11 +58,11 @@ STATIC mp_obj_t _register(mp_obj_t self, mp_obj_t o) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(register_obj, _register);
-//| .. method:: flush()
-//|
-//| Send any queued drawing commands directly to the hardware.
+//| def flush(self, ) -> Any:
+//| """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));
@@ -75,11 +70,11 @@ STATIC mp_obj_t _flush(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(flush_obj, _flush);
-//| .. method:: cc(b)
-//|
-//| Append bytes to the command FIFO.
+//| def cc(self, b: bytes) -> Any:
+//| """Append bytes to the command FIFO.
//|
-//| :param bytes b: The bytes to add
+//| :param bytes b: The bytes to add"""
+//| ...
//|
STATIC mp_obj_t _cc(mp_obj_t self, mp_obj_t b) {
mp_buffer_info_t buffer_info;
@@ -91,14 +86,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc_obj, _cc);
//{
-//| .. method:: AlphaFunc(func, ref)
-//|
-//| Set the alpha test function
+//| def AlphaFunc(self, func: int, ref: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -109,14 +104,14 @@ 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);
-//| .. method:: Begin(prim)
-//|
-//| Begin drawing a graphics primitive
+//| def Begin(self, prim: int) -> Any:
+//| """Begin drawing a 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) {
uint32_t prim = mp_obj_get_int_truncated(a0);
@@ -125,11 +120,11 @@ STATIC mp_obj_t _begin(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(begin_obj, _begin);
-//| .. method:: BitmapExtFormat(format)
+//| def BitmapExtFormat(self, format: int) -> Any:
+//| """Set the bitmap format
//|
-//| 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) {
@@ -139,13 +134,13 @@ STATIC mp_obj_t _bitmapextformat(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmapextformat_obj, _bitmapextformat);
-//| .. method:: BitmapHandle(handle)
-//|
-//| Set the bitmap handle
+//| def BitmapHandle(self, handle: int) -> Any:
+//| """Set the bitmap handle
//|
//| :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) {
@@ -155,12 +150,12 @@ STATIC mp_obj_t _bitmaphandle(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaphandle_obj, _bitmaphandle);
-//| .. method:: BitmapLayoutH(linestride, height)
-//|
-//| Set the source bitmap memory format and layout for the current handle. high bits for large bitmaps
+//| def BitmapLayoutH(self, linestride: int, height: int) -> Any:
+//| """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 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) {
@@ -171,13 +166,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);
-//| .. method:: BitmapLayout(format, linestride, height)
-//|
-//| Set the source bitmap memory format and layout for the current handle
+//| def BitmapLayout(self, format: int, linestride: int, height: int) -> Any:
+//| """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 height: bitmap height, in lines. Range 0-511"""
+//| ...
//|
STATIC mp_obj_t _bitmaplayout(size_t n_args, const mp_obj_t *args) {
@@ -189,12 +184,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);
-//| .. method:: BitmapSizeH(width, height)
-//|
-//| Set the screen drawing of bitmaps for the current handle. high bits for large bitmaps
+//| def BitmapSizeH(self, width: int, height: int) -> Any:
+//| """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 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) {
@@ -205,15 +200,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);
-//| .. method:: BitmapSize(filter, wrapx, wrapy, width, height)
-//|
-//| Set the screen drawing of bitmaps for the current handle
+//| def BitmapSize(self, filter: int, wrapx: int, wrapy: int, width: int, height: int) -> Any:
+//| """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 height: drawn bitmap height, in pixels. Range 0-511"""
+//| ...
//|
STATIC mp_obj_t _bitmapsize(size_t n_args, const mp_obj_t *args) {
@@ -227,11 +222,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);
-//| .. method:: BitmapSource(addr)
+//| def BitmapSource(self, addr: int) -> Any:
+//| """Set the source address for bitmap graphics
//|
-//| 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) {
@@ -241,14 +236,14 @@ STATIC mp_obj_t _bitmapsource(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmapsource_obj, _bitmapsource);
-//| .. method:: BitmapSwizzle(r, g, b, a)
-//|
-//| 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) -> Any:
+//| """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 a: alpha component source channel. Range 0-7"""
+//| ...
//|
STATIC mp_obj_t _bitmapswizzle(size_t n_args, const mp_obj_t *args) {
@@ -261,16 +256,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);
-//| .. method:: BitmapTransformA(p, v)
-//|
-//| Set the :math:`a` component of the bitmap transform matrix
+//| def BitmapTransformA(self, p: Any, v: int) -> Any:
+//| """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
//|
//| 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) {
@@ -281,16 +276,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);
-//| .. method:: BitmapTransformB(p, v)
-//|
-//| Set the :math:`b` component of the bitmap transform matrix
+//| def BitmapTransformB(self, p: Any, v: int) -> Any:
+//| """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
//|
//| 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) {
@@ -301,13 +296,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);
-//| .. method:: BitmapTransformC(v)
-//|
-//| Set the :math:`c` component of the bitmap transform matrix
+//| def BitmapTransformC(self, v: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -317,16 +312,16 @@ STATIC mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformc_obj, _bitmaptransformc);
-//| .. method:: BitmapTransformD(p, v)
-//|
-//| Set the :math:`d` component of the bitmap transform matrix
+//| def BitmapTransformD(self, p: Any, v: int) -> Any:
+//| """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
//|
//| 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) {
@@ -337,16 +332,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);
-//| .. method:: BitmapTransformE(p, v)
-//|
-//| Set the :math:`e` component of the bitmap transform matrix
+//| def BitmapTransformE(self, p: Any, v: int) -> Any:
+//| """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
//|
//| 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) {
@@ -357,13 +352,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);
-//| .. method:: BitmapTransformF(v)
-//|
-//| Set the :math:`f` component of the bitmap transform matrix
+//| def BitmapTransformF(self, v: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -373,14 +368,14 @@ STATIC mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformf_obj, _bitmaptransformf);
-//| .. method:: BlendFunc(src, dst)
-//|
-//| Set pixel arithmetic
+//| def BlendFunc(self, src: int, dst: int) -> Any:
+//| """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)
//|
-//| 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) {
@@ -391,11 +386,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);
-//| .. method:: Call(dest)
-//|
-//| Execute a sequence of commands at another location in the display list
+//| def Call(self, dest: int) -> Any:
+//| """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) {
@@ -405,13 +400,13 @@ STATIC mp_obj_t _call(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(call_obj, _call);
-//| .. method:: Cell(cell)
-//|
-//| Set the bitmap cell number for the vertex2f command
+//| def Cell(self, cell: int) -> Any:
+//| """Set the bitmap cell number for the vertex2f command
//|
//| :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) {
@@ -421,13 +416,13 @@ STATIC mp_obj_t _cell(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cell_obj, _cell);
-//| .. method:: ClearColorA(alpha)
-//|
-//| Set clear value for the alpha channel
+//| def ClearColorA(self, alpha: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -437,15 +432,15 @@ STATIC mp_obj_t _clearcolora(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(clearcolora_obj, _clearcolora);
-//| .. method:: ClearColorRGB(red, green, blue)
-//|
-//| Set clear values for red, green and blue channels
+//| def ClearColorRGB(self, red: int, green: int, blue: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -457,13 +452,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);
-//| .. method:: Clear(c, s, t)
-//|
-//| Clear buffers to preset values
+//| def Clear(self, c: int, s: int, t: int) -> Any:
+//| """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 t: clear tag buffer. Range 0-1"""
+//| ...
//|
STATIC mp_obj_t _clear(size_t n_args, const mp_obj_t *args) {
@@ -475,13 +470,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);
-//| .. method:: ClearStencil(s)
-//|
-//| Set clear value for the stencil buffer
+//| def ClearStencil(self, s: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -491,13 +486,12 @@ STATIC mp_obj_t _clearstencil(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(clearstencil_obj, _clearstencil);
-//| .. method:: ClearTag(s)
-//|
-//| Set clear value for the tag buffer
+//| def ClearTag(self, s: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -507,13 +501,13 @@ STATIC mp_obj_t _cleartag(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cleartag_obj, _cleartag);
-//| .. method:: ColorA(alpha)
-//|
-//| Set the current color alpha
+//| def ColorA(self, alpha: int) -> Any:
+//| """Set the current color alpha
//|
//| :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) {
@@ -523,16 +517,16 @@ STATIC mp_obj_t _colora(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(colora_obj, _colora);
-//| .. method:: ColorMask(r, g, b, a)
-//|
-//| Enable and disable writing of frame buffer color components
+//| def ColorMask(self, r: int, g: int, b: int, a: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -545,15 +539,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);
-//| .. method:: ColorRGB(red, green, blue)
-//|
-//| Set the drawing color
+//| def ColorRGB(self, red: int, green: int, blue: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -565,9 +559,8 @@ 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);
-//| .. method:: Display()
-//|
-//| End the display list
+//| def Display(self, ) -> Any: ...
+//| """End the display list"""
//|
STATIC mp_obj_t _display(mp_obj_t self) {
@@ -577,12 +570,12 @@ STATIC mp_obj_t _display(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_obj, _display);
-//| .. method:: End()
+//| def End(self, ) -> Any:
+//| """End drawing a graphics primitive
//|
-//| 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) {
@@ -591,11 +584,11 @@ STATIC mp_obj_t _end(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(end_obj, _end);
-//| .. method:: Jump(dest)
+//| def Jump(self, dest: int) -> Any:
+//| """Execute commands at another location in the display list
//|
-//| 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) {
@@ -605,13 +598,13 @@ STATIC mp_obj_t _jump(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(jump_obj, _jump);
-//| .. method:: LineWidth(width)
-//|
-//| Set the width of rasterized lines
+//| def LineWidth(self, width: int) -> Any:
+//| """Set the width of rasterized lines
//|
//| :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) {
@@ -621,11 +614,11 @@ STATIC mp_obj_t _linewidth(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(linewidth_obj, _linewidth);
-//| .. method:: Macro(m)
-//|
-//| Execute a single command from a macro register
+//| def Macro(self, m: int) -> Any:
+//| """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) {
@@ -635,9 +628,9 @@ STATIC mp_obj_t _macro(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(macro_obj, _macro);
-//| .. method:: Nop()
-//|
-//| No operation
+//| def Nop(self, ) -> Any:
+//| """No operation"""
+//| ...
//|
STATIC mp_obj_t _nop(mp_obj_t self) {
@@ -647,13 +640,13 @@ STATIC mp_obj_t _nop(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(nop_obj, _nop);
-//| .. method:: PaletteSource(addr)
-//|
-//| Set the base address of the palette
+//| def PaletteSource(self, addr: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -663,13 +656,13 @@ STATIC mp_obj_t _palettesource(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(palettesource_obj, _palettesource);
-//| .. method:: PointSize(size)
-//|
-//| Set the radius of rasterized points
+//| def PointSize(self, size: int) -> Any:
+//| """Set the radius of rasterized points
//|
//| :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) {
@@ -679,9 +672,9 @@ STATIC mp_obj_t _pointsize(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pointsize_obj, _pointsize);
-//| .. method:: RestoreContext()
-//|
-//| Restore the current graphics context from the context stack
+//| def RestoreContext(self, ) -> Any:
+//| """Restore the current graphics context from the context stack"""
+//| ...
//|
STATIC mp_obj_t _restorecontext(mp_obj_t self) {
@@ -691,9 +684,9 @@ STATIC mp_obj_t _restorecontext(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(restorecontext_obj, _restorecontext);
-//| .. method:: Return()
-//|
-//| Return from a previous call command
+//| def Return(self, ) -> Any:
+//| """Return from a previous call command"""
+//| ...
//|
STATIC mp_obj_t _return(mp_obj_t self) {
@@ -703,9 +696,9 @@ STATIC mp_obj_t _return(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(return_obj, _return);
-//| .. method:: SaveContext()
-//|
-//| Push the current graphics context on the context stack
+//| def SaveContext(self, ) -> Any:
+//| """Push the current graphics context on the context stack"""
+//| ...
//|
STATIC mp_obj_t _savecontext(mp_obj_t self) {
@@ -715,14 +708,14 @@ STATIC mp_obj_t _savecontext(mp_obj_t self) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(savecontext_obj, _savecontext);
-//| .. method:: ScissorSize(width, height)
-//|
-//| Set the size of the scissor clip rectangle
+//| def ScissorSize(self, width: int, height: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -733,14 +726,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);
-//| .. method:: ScissorXY(x, y)
-//|
-//| Set the top left corner of the scissor clip rectangle
+//| def ScissorXY(self, x: int, y: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -751,15 +744,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);
-//| .. method:: StencilFunc(func, ref, mask)
-//|
-//| Set function and reference value for stencil testing
+//| def StencilFunc(self, func: int, ref: int, mask: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -771,13 +764,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);
-//| .. method:: StencilMask(mask)
-//|
-//| Control the writing of individual bits in the stencil planes
+//| def StencilMask(self, mask: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -787,14 +780,14 @@ STATIC mp_obj_t _stencilmask(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(stencilmask_obj, _stencilmask);
-//| .. method:: StencilOp(sfail, spass)
-//|
-//| Set stencil test actions
+//| def StencilOp(self, sfail: int, spass: int) -> Any:
+//| """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)
//|
-//| 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) {
@@ -805,13 +798,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);
-//| .. method:: TagMask(mask)
-//|
-//| Control the writing of the tag buffer
+//| def TagMask(self, mask: int) -> Any:
+//| """Control the writing of the tag buffer
//|
//| :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) {
@@ -821,13 +814,13 @@ STATIC mp_obj_t _tagmask(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(tagmask_obj, _tagmask);
-//| .. method:: Tag(s)
-//|
-//| Set the current tag value
+//| def Tag(self, s: int) -> Any:
+//| """Set the current tag value
//|
//| :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) {
@@ -837,13 +830,13 @@ STATIC mp_obj_t _tag(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(tag_obj, _tag);
-//| .. method:: VertexTranslateX(x)
-//|
-//| Set the vertex transformation's x translation component
+//| def VertexTranslateX(self, x: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -853,13 +846,13 @@ STATIC mp_obj_t _vertextranslatex(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatex_obj, _vertextranslatex);
-//| .. method:: VertexTranslateY(y)
-//|
-//| Set the vertex transformation's y translation component
+//| def VertexTranslateY(self, y: int) -> Any:
+//| """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
//|
-//| 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`."""
+//| ...
//|
@@ -870,13 +863,13 @@ STATIC mp_obj_t _vertextranslatey(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatey_obj, _vertextranslatey);
-//| .. method:: VertexFormat(frac)
-//|
-//| Set the precision of vertex2f coordinates
+//| def VertexFormat(self, frac: int) -> Any:
+//| """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
//|
-//| 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) {
@@ -886,15 +879,15 @@ STATIC mp_obj_t _vertexformat(mp_obj_t self, mp_obj_t a0) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertexformat_obj, _vertexformat);
-//| .. method:: Vertex2ii(x, y, handle, cell)
-//|
-//| :param int x: x-coordinate in pixels. Range 0-511
+//| def Vertex2ii(self, x: int, y: int, handle: int, cell: int) -> Any:
+//| """: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) {
uint32_t x = mp_obj_get_int_truncated(args[1]);
@@ -961,12 +954,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii);
// Hand-written functions {
-//| .. method:: Vertex2f(b)
-//|
-//| Draw a point.
+//| def Vertex2f(self, b: Any) -> Any:
+//| """Draw a point.
//|
//| :param float x: pixel x-coordinate
-//| :param float y: pixel y-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);
@@ -980,14 +973,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));
-//| .. method:: cmd0(n)
-//|
-//| Append the command word n to the FIFO
+//| def cmd0(self, n: int) -> Any:
+//| """Append the command word n to the FIFO
//|
//| :param int n: The command code
//|
//| This method is used by the ``eve`` module to efficiently add
-//| commands to the FIFO.
+//| commands to the FIFO."""
+//| ...
//|
STATIC mp_obj_t _cmd0(mp_obj_t self, mp_obj_t n) {
@@ -997,9 +990,8 @@ STATIC mp_obj_t _cmd0(mp_obj_t self, mp_obj_t n) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cmd0_obj, _cmd0);
-//| .. method:: cmd(n, fmt, args)
-//|
-//| Append a command packet to the FIFO.
+//| def cmd(self, n: int, fmt: str, args: tuple) -> Any:
+//| """Append a command packet to the FIFO.
//|
//| :param int n: The command code
//| :param str fmt: The command format `struct` layout
@@ -1008,7 +1000,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(cmd0_obj, _cmd0);
//| Supported format codes: h, H, i, I.
//|
//| This method is used by the ``eve`` module to efficiently add
-//| commands to the FIFO.
+//| 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 3ff208761..352ef38f2 100644
--- a/shared-bindings/_pew/PewPew.c
+++ b/shared-bindings/_pew/PewPew.c
@@ -31,36 +31,31 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/util.h"
#include "PewPew.h"
-#include "shared-module/_pew/PewPew.h"
+#include "common-hal/_pew/PewPew.h"
#include "supervisor/shared/translate.h"
-
-//| .. currentmodule:: _pew
-//|
-//| :class:`PewPew` -- LED matrix and button driver
-//| ===============================================
+//| class PewPew:
+//| """This is an internal module to be used by the ``pew.py`` library from
+//| https://github.com/pewpew-game/pew-pewpew-standalone-10.x to handle the
+//| LED matrix display and buttons on the ``pewpew10`` board.
//|
-//| This is an internal module to be used by the ``pew.py`` library from
-//| https://github.com/pewpew-game/pew-pewpew-standalone-10.x to handle the
-//| LED matrix display and buttons on the ``pewpew10`` board.
+//| Usage::
//|
-//| Usage::
-//|
-//| This singleton class is instantiated by the ``pew`` library, and
-//| used internally by it. All user-visible interactions are done through
-//| that library.
+//| This singleton class is instantiated by the ``pew`` library, and
+//| used internally by it. All user-visible interactions are done through
+//| that library."""
//|
-//| .. class:: PewPew(buffer, rows, cols, buttons)
-//|
-//| Initializes matrix scanning routines.
+//| def __init__(self, buffer: Any, rows: Any, cols: Any, buttons: Any):
+//| """Initializes matrix scanning routines.
//|
-//| The ``buffer`` is a 64 byte long ``bytearray`` that stores what should
-//| be displayed on the matrix. ``rows`` and ``cols`` are both lists of
-//| eight ``DigitalInputOutput`` objects that are connected to the matrix
-//| rows and columns. ``buttons`` is a ``DigitalInputOutput`` object that
-//| is connected to the common side of all buttons (the other sides of the
-//| buttons are connected to rows of the matrix).
+//| The ``buffer`` is a 64 byte long ``bytearray`` that stores what should
+//| be displayed on the matrix. ``rows`` and ``cols`` are both lists of
+//| eight ``DigitalInputOutput`` objects that are connected to the matrix
+//| rows and columns. ``buttons`` is a ``DigitalInputOutput`` object that
+//| is connected to the common side of all buttons (the other sides of the
+//| buttons are connected to rows of the matrix)."""
+//| ...
//|
STATIC mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *pos_args, mp_map_t *kw_args) {
diff --git a/shared-bindings/_pew/__init__.c b/shared-bindings/_pew/__init__.c
index 6c5520ac5..498beaf1c 100644
--- a/shared-bindings/_pew/__init__.c
+++ b/shared-bindings/_pew/__init__.c
@@ -27,7 +27,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "PewPew.h"
-#include "shared-module/_pew/PewPew.h"
+#include "common-hal/_pew/PewPew.h"
STATIC mp_obj_t get_pressed(void) {
pew_obj_t *pew = MP_STATE_VM(pew_singleton);
@@ -41,17 +41,7 @@ STATIC mp_obj_t get_pressed(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_pressed_obj, get_pressed);
-//| :mod:`_pew` --- LED matrix driver
-//| ==================================
-//|
-//| .. module:: _pew
-//| :synopsis: LED matrix driver
-//| :platform: SAMD21
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| PewPew
+//| """LED matrix driver"""
//|
STATIC const mp_rom_map_elem_t pew_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pew) },
diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c
index 61b4c9ae0..c953951ea 100644
--- a/shared-bindings/_pixelbuf/PixelBuf.c
+++ b/shared-bindings/_pixelbuf/PixelBuf.c
@@ -44,31 +44,27 @@ extern const int32_t colorwheel(float pos);
static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t* parsed);
-//| .. currentmodule:: pixelbuf
+//| class PixelBuf:
+//| """A fast RGB[W] pixel buffer for LED and similar devices."""
//|
-//| :class:`PixelBuf` -- A fast RGB[W] pixel buffer for LED and similar devices
-//| ===========================================================================
+//| def __init__(self, size: int, *, byteorder: str = "BGR", brightness: float = 0, auto_write: bool = False, header: bytes = b"", trailer: bytes = b""):
+//| """Create a PixelBuf object of the specified size, byteorder, and bits per pixel.
//|
-//| :class:`~_pixelbuf.PixelBuf` implements an RGB[W] bytearray abstraction.
+//| When brightness is less than 1.0, a second buffer will be used to store the color values
+//| before they are adjusted for brightness.
//|
-//| .. class:: PixelBuf(size, *, byteorder="BGR", brightness=0, auto_write=False, header=b"", trailer=b"")
+//| When ``P`` (PWM duration) is present as the 4th character of the byteorder
+//| string, the 4th value in the tuple/list for a pixel is the individual pixel
+//| brightness (0.0-1.0) and will enable a Dotstar compatible 1st byte for each
+//| pixel.
//|
-//| Create a PixelBuf object of the specified size, byteorder, and bits per pixel.
-//|
-//| When brightness is less than 1.0, a second buffer will be used to store the color values
-//| before they are adjusted for brightness.
-//|
-//| When ``P`` (pwm duration) is present as the 4th character of the byteorder
-//| string, the 4th value in the tuple/list for a pixel is the individual pixel
-//| brightness (0.0-1.0) and will enable a Dotstar compatible 1st byte in the
-//| output buffer (``buf``).
-//|
-//| :param ~int size: Number of pixelsx
-//| :param ~str byteorder: Byte order string (such as "BGR" 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 bytes header: Sequence of bytes to always send before pixel values.
+//| :param bytes 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) {
mp_arg_check_num(n_args, kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
@@ -156,9 +152,8 @@ static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t
}
}
-//| .. attribute:: bpp
-//|
-//| The number of bytes per pixel in the buffer (read-only)
+//| bpp: Any = ...
+//| """The number of bytes per pixel in the buffer (read-only)"""
//|
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_bpp(mp_obj_t self_in) {
return MP_OBJ_NEW_SMALL_INT(common_hal__pixelbuf_pixelbuf_get_bpp(self_in));
@@ -173,12 +168,11 @@ const mp_obj_property_t pixelbuf_pixelbuf_bpp_obj = {
};
-//| .. attribute:: brightness
-//|
-//| Float value between 0 and 1. Output brightness.
+//| brightness: Any = ...
+//| """Float value between 0 and 1. Output brightness.
//|
//| When brightness is less than 1.0, a second buffer will be used to store the color values
-//| before they are adjusted for brightness.
+//| before they are adjusted for brightness."""
//|
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_brightness(mp_obj_t self_in) {
return mp_obj_new_float(common_hal__pixelbuf_pixelbuf_get_brightness(self_in));
@@ -205,9 +199,8 @@ const mp_obj_property_t pixelbuf_pixelbuf_brightness_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: auto_write
-//|
-//| Whether to automatically write the pixels after each update.
+//| auto_write: Any = ...
+//| """Whether to automatically write the pixels after each update."""
//|
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_auto_write(mp_obj_t self_in) {
return mp_obj_new_bool(common_hal__pixelbuf_pixelbuf_get_auto_write(self_in));
@@ -228,9 +221,8 @@ const mp_obj_property_t pixelbuf_pixelbuf_auto_write_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: byteorder
-//|
-//| byteorder string for the buffer (read-only)
+//| byteorder: Any = ...
+//| """byteorder string for the buffer (read-only)"""
//|
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_byteorder(mp_obj_t self_in) {
return common_hal__pixelbuf_pixelbuf_get_byteorder_string(self_in);
@@ -253,10 +245,10 @@ STATIC mp_obj_t pixelbuf_pixelbuf_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//| .. method:: show()
-//|
-//| Transmits the color data to the pixels so that they are shown. This is done automatically
-//| when `auto_write` is True.
+//| def show(self, ) -> Any:
+//| """Transmits the color data to the pixels so that they are shown. This is done automatically
+//| when `auto_write` is True."""
+//| ...
//|
STATIC mp_obj_t pixelbuf_pixelbuf_show(mp_obj_t self_in) {
@@ -265,9 +257,9 @@ 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);
-//| .. function:: fill(color)
-//|
-//| Fills the given pixelbuf with the given color.
+//| def fill(color: Any) -> Any:
+//| """Fills the given pixelbuf with the given color."""
+//| ...
//|
STATIC mp_obj_t pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t value) {
@@ -277,17 +269,19 @@ 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);
-
-//| .. method:: __getitem__(index)
-//|
-//| Returns the pixel value at the given index as a tuple of (Red, Green, Blue[, White]) values
-//| between 0 and 255.
-//|
-//| .. method:: __setitem__(index, value)
+//| def __getitem__(self, index: Any) -> Any:
+//| """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."""
+//| ...
//|
-//| Sets the pixel value at the given index. Value can either be a tuple of (Red, Green, Blue
-//| [, White]) values between 0 and 255 or an integer where the red, green and blue values are
-//| packed into the lower three bytes (0xRRGGBB).
+//| def __setitem__(self, index: Any, value: Any) -> Any:
+//| """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).
+//| For RGBW byteorders, if given only RGB values either as an int or as a tuple, the white value
+//| is used instead when the red, green, and blue values are the same."""
+//| ...
//|
STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
if (value == MP_OBJ_NULL) {
@@ -304,18 +298,21 @@ 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);
- if (slice.step < 0) {
- mp_raise_IndexError(translate("Negative step not supported"));
+ size_t slice_len;
+ if (slice.step > 0) {
+ slice_len = slice.stop - slice.start;
+ } else {
+ slice_len = 1 + slice.start - slice.stop;
+ }
+ if (slice.step > 1 || slice.step < -1) {
+ size_t step = slice.step > 0 ? slice.step : slice.step * -1;
+ slice_len = (slice_len / step) + (slice_len % step ? 1 : 0);
}
if (value == MP_OBJ_SENTINEL) { // Get
- size_t len = slice.stop - slice.start;
- if (slice.step > 1) {
- len = (len / slice.step) + (len % slice.step ? 1 : 0);
- }
- mp_obj_tuple_t* t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL));
- for (uint i = 0; i < len; i++) {
- t->items[i] = common_hal__pixelbuf_pixelbuf_get_pixel(self_in, i * slice.step);
+ mp_obj_tuple_t* t = MP_OBJ_TO_PTR(mp_obj_new_tuple(slice_len, NULL));
+ for (uint i = 0; i < slice_len; i++) {
+ t->items[i] = common_hal__pixelbuf_pixelbuf_get_pixel(self_in, i * slice.step + slice.start);
}
return MP_OBJ_FROM_PTR(t);
} else { // Set
@@ -325,10 +322,6 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
mp_raise_ValueError(translate("tuple/list required on RHS"));
}
- size_t dst_len = (slice.stop - slice.start);
- if (slice.step > 1) {
- dst_len = (dst_len / slice.step) + (dst_len % slice.step ? 1 : 0);
- }
mp_obj_t *src_objs;
size_t num_items;
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
@@ -340,12 +333,12 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
num_items = l->len;
src_objs = l->items;
}
- if (num_items != dst_len) {
+ if (num_items != slice_len) {
mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."),
- dst_len, num_items);
+ slice_len, num_items);
}
- common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.stop, slice.step, src_objs);
+ common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.step, slice_len, src_objs);
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 68d6d4eef..14ee2e900 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, size_t stop, size_t step, 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);
#endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c
index 424ed23e4..bfd479fde 100644
--- a/shared-bindings/_pixelbuf/__init__.c
+++ b/shared-bindings/_pixelbuf/__init__.c
@@ -33,56 +33,48 @@
#include "shared-bindings/_pixelbuf/PixelBuf.h"
-//| :mod:`_pixelbuf` --- Fast RGB(W) pixel buffer and helpers
-//| ===========================================================
-
-//| .. module:: _pixelbuf
-//| :synopsis: 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.
//|
-//| Byteorders are configured with strings, such as "RGB" or "RGBD".
-//| TODO: Pull in docs from pypixelbuf.
-
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| PixelBuf
-
+//| Byteorders are configured with strings, such as "RGB" or "RGBD"."""
+// TODO: Pull in docs from pypixelbuf.
-//| .. function:: wheel(n)
+//| def colorwheel(n: int) -> Any:
+//| """C implementation of the common wheel() function found in many examples.
+//| Returns the colorwheel RGB value as an integer value for n (usable in :py:class:`PixelBuf`, neopixel, and dotstar)."""
+//| ...
//|
-//| C implementation of the common wheel() function found in many examples.
-//| Returns the colorwheel RGB value as an integer value for n (usable in :py:class:`PixelBuf`, neopixel, and dotstar).
+//| def wheel(n: Any) -> Any:
+//| """Use of wheel() is deprecated. Please use colorwheel()."""
//|
-STATIC mp_obj_t pixelbuf_wheel(mp_obj_t n) {
+STATIC mp_obj_t pixelbuf_colorwheel(mp_obj_t n) {
return MP_OBJ_NEW_SMALL_INT(colorwheel(MP_OBJ_IS_SMALL_INT(n) ? MP_OBJ_SMALL_INT_VALUE(n) : mp_obj_float_get(n)));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_wheel_obj, pixelbuf_wheel);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_colorwheel_obj, pixelbuf_colorwheel);
const int32_t colorwheel(float pos) {
if (pos > 255) {
pos = pos - ((uint32_t)(pos / 256) * 256);
}
if (pos < 85)
- return (uint8_t)(pos * 3) << 16 | (uint8_t)(255 - (pos * 3)) << 8;
+ return (uint8_t)(255 - (pos * 3)) << 16 | (uint8_t)(pos * 3) << 8;
else if (pos < 170) {
pos -= 85;
- return (uint8_t)(255 - (pos * 3)) << 16 | (uint8_t)(pos * 3);
+ return (uint8_t)(255 - (pos * 3)) << 8 | (uint8_t)(pos * 3);
} else {
pos -= 170;
- return (uint8_t)(pos * 3) << 8 | (uint8_t)(255 - pos * 3);
+ return (uint8_t)(pos * 3) << 16 | (uint8_t)(255 - (pos * 3));
}
}
STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pixelbuf) },
{ MP_ROM_QSTR(MP_QSTR_PixelBuf), MP_ROM_PTR(&pixelbuf_pixelbuf_type) },
- { MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_PTR(&pixelbuf_wheel_obj) },
+ { MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_PTR(&pixelbuf_colorwheel_obj) },
+ { MP_ROM_QSTR(MP_QSTR_colorwheel), MP_ROM_PTR(&pixelbuf_colorwheel_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pixelbuf_module_globals, pixelbuf_module_globals_table);
diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c
index 12028b131..0f8260e53 100644
--- a/shared-bindings/_stage/Layer.c
+++ b/shared-bindings/_stage/Layer.c
@@ -30,25 +30,23 @@
#include "Layer.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: _stage
+//| class Layer:
+//| """Keep information about a single layer of graphics"""
//|
-//| :class:`Layer` -- Keep information about a single layer of graphics
-//| ===================================================================
+//| def __init__(self, width: int, height: int, graphic: bytearray, palette: bytearray, grid: bytearray):
+//| """Keep internal information about a layer of graphics (either a
+//| ``Grid`` or a ``Sprite``) in a format suitable for fast rendering
+//| with the ``render()`` function.
//|
-//| .. class:: Layer(width, height, graphic, palette, [grid])
+//| :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.
//|
-//| Keep internal information about a layer of graphics (either a
-//| ``Grid`` or a ``Sprite``) in a format suitable for fast rendering
-//| with the ``render()`` function.
-//|
-//| :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.
-//|
-//| This class is intended for internal use in the ``stage`` library and
-//| it shouldn't be used on its own.
+//| This class is intended for internal use in the ``stage`` library and
+//| it shouldn't be used on its own."""
+//| ...
//|
STATIC mp_obj_t layer_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *args, mp_map_t *kw_args) {
@@ -90,9 +88,9 @@ STATIC mp_obj_t layer_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: move(x, y)
-//|
-//| Set the offset of the layer to the specified values.
+//| def move(self, x: Any, y: Any) -> Any:
+//| """Set the offset of the layer to the specified values."""
+//| ...
//|
STATIC mp_obj_t layer_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
layer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -102,10 +100,10 @@ STATIC mp_obj_t layer_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_move_obj, layer_move);
-//| .. method:: frame(frame, rotation)
-//|
-//| Set the animation frame of the sprite, and optionally rotation its
-//| graphic.
+//| def frame(self, frame: Any, rotation: Any) -> Any:
+//| """Set the animation frame of the sprite, and optionally rotation its
+//| graphic."""
+//| ...
//|
STATIC mp_obj_t layer_frame(mp_obj_t self_in, mp_obj_t frame_in,
mp_obj_t rotation_in) {
diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c
index 49c1d00ca..b0ff1525c 100644
--- a/shared-bindings/_stage/Text.c
+++ b/shared-bindings/_stage/Text.c
@@ -30,25 +30,23 @@
#include "Text.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: _stage
+//| class Text:
+//| """Keep information about a single grid of text"""
//|
-//| :class:`Text` -- Keep information about a single text of text
-//| ==============================================================
+//| def __init__(self, width: int, height: int, font: bytearray, palette: bytearray, chars: bytearray):
+//| """Keep internal information about a grid of text
+//| in a format suitable for fast rendering
+//| with the ``render()`` function.
//|
-//| .. class:: Text(width, height, font, palette, chars)
+//| :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.
//|
-//| Keep internal information about a text of text
-//| in a format suitable for fast rendering
-//| with the ``render()`` function.
-//|
-//| :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.
-//|
-//| This class is intended for internal use in the ``stage`` library and
-//| it shouldn't be used on its own.
+//| This class is intended for internal use in the ``stage`` library and
+//| it shouldn't be used on its own."""
+//| ...
//|
STATIC mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *args, mp_map_t *kw_args) {
@@ -84,9 +82,9 @@ STATIC mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: move(x, y)
-//|
-//| Set the offset of the text to the specified values.
+//| def move(self, x: Any, y: Any) -> Any:
+//| """Set the offset of the text to the specified values."""
+//| ...
//|
STATIC mp_obj_t text_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
text_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c
index 4bac280bf..6a5638185 100644
--- a/shared-bindings/_stage/__init__.c
+++ b/shared-bindings/_stage/__init__.c
@@ -34,26 +34,13 @@
#include "Layer.h"
#include "Text.h"
-//| :mod:`_stage` --- C-level helpers for animation of sprites on a stage
-//| =====================================================================
-//|
-//| .. module:: _stage
-//| :synopsis: C-level helpers for animation of sprites on a stage
-//| :platform: SAMD21
+//| """C-level helpers for animation of sprites on a stage
//|
//| The `_stage` module contains native code to speed-up the ```stage`` Library
-//| <https://github.com/python-ugame/circuitpython-stage>`_.
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Layer
-//| Text
+//| <https://github.com/python-ugame/circuitpython-stage>`_."""
//|
-//| .. function:: render(x0, y0, x1, y1, layers, buffer, display[, scale[, background]])
-//|
-//| Render and send to the display a fragment of the screen.
+//| def render(x0: int, y0: int, x1: int, y1: int, layers: list, buffer: bytearray, display: displayio.Display, scale: int, background: int) -> Any:
+//| """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.
@@ -70,7 +57,8 @@
//| valid.
//|
//| This function is intended for internal use in the ``stage`` library
-//| and all the necessary checks are performed there.
+//| and all the necessary checks are performed there."""
+//|
STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) {
uint16_t x0 = mp_obj_get_int(args[0]);
uint16_t y0 = mp_obj_get_int(args[1]);
diff --git a/shared-bindings/aesio/__init__.c b/shared-bindings/aesio/__init__.c
new file mode 100644
index 000000000..80913b70a
--- /dev/null
+++ b/shared-bindings/aesio/__init__.c
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 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 "__init__.h"
+
+//| """AES encryption routines
+//|
+//| The `AES` module contains classes used to implement encryption
+//| and decryption. It aims to be low overhead in terms of memory."""
+
+
+STATIC const mp_obj_tuple_t mp_aes_key_size_obj = {
+ {&mp_type_tuple},
+ 3,
+ {
+ MP_OBJ_NEW_SMALL_INT(16),
+ MP_OBJ_NEW_SMALL_INT(24),
+ MP_OBJ_NEW_SMALL_INT(32),
+ }
+};
+
+STATIC const mp_rom_map_elem_t aesio_module_globals_table[] = {
+ {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_aesio)},
+ {MP_ROM_QSTR(MP_QSTR_AES), MP_ROM_PTR(&aesio_aes_type) },
+ {MP_ROM_QSTR(MP_QSTR_MODE_ECB), MP_ROM_INT(AES_MODE_ECB)},
+ {MP_ROM_QSTR(MP_QSTR_MODE_CBC), MP_ROM_INT(AES_MODE_CBC)},
+ {MP_ROM_QSTR(MP_QSTR_MODE_CTR), MP_ROM_INT(AES_MODE_CTR)},
+ {MP_ROM_QSTR(MP_QSTR_block_size), MP_ROM_INT(AES_BLOCKLEN)},
+ {MP_ROM_QSTR(MP_QSTR_key_size), (mp_obj_t)&mp_aes_key_size_obj},
+};
+
+STATIC MP_DEFINE_CONST_DICT(aesio_module_globals, aesio_module_globals_table);
+
+const mp_obj_module_t aesio_module = {
+ .base = {&mp_type_module},
+ .globals = (mp_obj_dict_t *)&aesio_module_globals,
+};
diff --git a/shared-bindings/aesio/__init__.h b/shared-bindings/aesio/__init__.h
new file mode 100644
index 000000000..634fed2e5
--- /dev/null
+++ b/shared-bindings/aesio/__init__.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 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_AESIO_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AESIO_H
+
+#include "shared-module/aesio/__init__.h"
+
+extern const mp_obj_type_t aesio_aes_type;
+
+void common_hal_aesio_aes_construct(aesio_aes_obj_t* self,
+ const uint8_t* key,
+ uint32_t key_length,
+ const uint8_t* iv,
+ int mode,
+ int counter);
+void common_hal_aesio_aes_rekey(aesio_aes_obj_t* self,
+ const uint8_t* key,
+ uint32_t key_length,
+ const uint8_t* iv);
+void common_hal_aesio_aes_set_mode(aesio_aes_obj_t* self,
+ int mode);
+void common_hal_aesio_aes_encrypt(aesio_aes_obj_t* self,
+ uint8_t* buffer,
+ size_t len);
+void common_hal_aesio_aes_decrypt(aesio_aes_obj_t* self,
+ uint8_t* buffer,
+ size_t len);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AESIO_H
diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c
new file mode 100644
index 000000000..f6a0a89b8
--- /dev/null
+++ b/shared-bindings/aesio/aes.c
@@ -0,0 +1,268 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "py/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/aesio/__init__.h"
+
+// Defined at the end of this file
+
+//| class AES:
+//| """Encrypt and decrypt AES streams"""
+//|
+//| def __init__(self, key, mode=0, iv=None, segment_size=8) -> Any:
+//| """Create a new AES state with the given key.
+//|
+//| :param bytearray 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
+//|
+//| Additional arguments are supported for legacy reasons.
+//|
+//| Encrypting a string::
+//|
+//| import aesio
+//| from binascii import hexlify
+//|
+//| key = b'Sixteen byte key'
+//| inp = b'Circuit Python!!' # Note: 16-bytes long
+//| outp = bytearray(len(inp))
+//| cipher = aesio.AES(key, aesio.mode.MODE_ECB)
+//| cipher.encrypt_into(inp, outp)
+//| hexlify(outp)"""
+//| ...
+//|
+
+STATIC mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args,
+ const mp_obj_t *pos_args,
+ mp_map_t *kw_args) {
+ (void)type;
+ enum { ARG_key, ARG_mode, ARG_IV, ARG_counter, ARG_segment_size };
+ static const mp_arg_t allowed_args[] = {
+ {MP_QSTR_key, MP_ARG_OBJ | MP_ARG_REQUIRED},
+ {MP_QSTR_mode, MP_ARG_INT, {.u_int = AES_MODE_ECB}},
+ {MP_QSTR_IV, MP_ARG_OBJ},
+ {MP_QSTR_counter, MP_ARG_OBJ},
+ {MP_QSTR_segment_size, MP_ARG_INT, {.u_int = 8}},
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
+ allowed_args, args);
+
+ aesio_aes_obj_t *self = m_new_obj(aesio_aes_obj_t);
+ self->base.type = &aesio_aes_type;
+
+ mp_buffer_info_t bufinfo;
+
+ const uint8_t *key = NULL;
+ uint32_t key_length = 0;
+ if (mp_get_buffer(args[ARG_key].u_obj, &bufinfo, MP_BUFFER_READ)) {
+ if ((bufinfo.len != 16) && (bufinfo.len != 24) && (bufinfo.len != 32)) {
+ mp_raise_TypeError(translate("Key must be 16, 24, or 32 bytes long"));
+ }
+ key = bufinfo.buf;
+ key_length = bufinfo.len;
+ } else {
+ mp_raise_TypeError(translate("No key was specified"));
+ }
+
+ int mode = args[ARG_mode].u_int;
+ switch (args[ARG_mode].u_int) {
+ case AES_MODE_CBC:
+ case AES_MODE_ECB:
+ case AES_MODE_CTR:
+ break;
+ default:
+ mp_raise_TypeError(translate("Requested AES mode is unsupported"));
+ }
+
+ // IV is required for CBC mode and is ignored for other modes.
+ const uint8_t *iv = NULL;
+ if (args[ARG_IV].u_obj != NULL &&
+ mp_get_buffer(args[ARG_IV].u_obj, &bufinfo, MP_BUFFER_READ)) {
+ if (bufinfo.len != AES_BLOCKLEN) {
+ mp_raise_TypeError_varg(translate("IV must be %d bytes long"),
+ AES_BLOCKLEN);
+ }
+ iv = bufinfo.buf;
+ }
+
+ common_hal_aesio_aes_construct(self, key, key_length, iv, mode,
+ args[ARG_counter].u_int);
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t aesio_aes_rekey(size_t n_args, const mp_obj_t *pos_args) {
+ aesio_aes_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(pos_args[1], &bufinfo, MP_BUFFER_READ);
+ const uint8_t *key = bufinfo.buf;
+ size_t key_length = bufinfo.len;
+ if (key == NULL) {
+ mp_raise_ValueError(translate("No key was specified"));
+ }
+ if ((key_length != 16) && (key_length != 24) && (key_length != 32)) {
+ mp_raise_TypeError(translate("Key must be 16, 24, or 32 bytes long"));
+ }
+
+ const uint8_t *iv = NULL;
+ if (n_args > 2) {
+ mp_get_buffer_raise(pos_args[2], &bufinfo, MP_BUFFER_READ);
+ size_t iv_length = bufinfo.len;
+ iv = (const uint8_t *)bufinfo.buf;
+ if (iv_length != AES_BLOCKLEN) {
+ mp_raise_TypeError_varg(translate("IV must be %d bytes long"),
+ AES_BLOCKLEN);
+ }
+ }
+
+ common_hal_aesio_aes_rekey(self, key, key_length, iv);
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR(aesio_aes_rekey_obj, 2, aesio_aes_rekey);
+
+STATIC void validate_length(aesio_aes_obj_t *self, size_t src_length,
+ size_t dest_length) {
+ if (src_length != dest_length) {
+ mp_raise_ValueError(
+ translate("Source and destination buffers must be the same length"));
+ }
+
+ switch (self->mode) {
+ case AES_MODE_ECB:
+ if (src_length != 16) {
+ mp_raise_msg(&mp_type_ValueError,
+ translate("ECB only operates on 16 bytes at a time"));
+ }
+ break;
+ case AES_MODE_CBC:
+ if ((src_length & 15) != 0) {
+ mp_raise_msg(&mp_type_ValueError,
+ translate("CBC blocks must be multiples of 16 bytes"));
+ }
+ break;
+ case AES_MODE_CTR:
+ break;
+ }
+}
+
+//| def encrypt_into(src, dest) -> None:
+//| """Encrypt the buffer from ``src`` into ``dest``.
+//|
+//| For ECB mode, the buffers must be 16 bytes long. For CBC mode, the
+//| buffers must be a multiple of 16 bytes, and must be equal length. For
+//| CTX mode, there are no restrictions."""
+//| ...
+//|
+STATIC mp_obj_t aesio_aes_encrypt_into(mp_obj_t aesio_obj, mp_obj_t src,
+ mp_obj_t dest) {
+ if (!MP_OBJ_IS_TYPE(aesio_obj, &aesio_aes_type)) {
+ mp_raise_TypeError_varg(translate("Expected a %q"), aesio_aes_type.name);
+ }
+ // Convert parameters into expected types.
+ aesio_aes_obj_t *aes = MP_OBJ_TO_PTR(aesio_obj);
+
+ mp_buffer_info_t srcbufinfo, destbufinfo;
+ mp_get_buffer_raise(src, &srcbufinfo, MP_BUFFER_READ);
+ mp_get_buffer_raise(dest, &destbufinfo, MP_BUFFER_WRITE);
+ validate_length(aes, srcbufinfo.len, destbufinfo.len);
+
+ memcpy(destbufinfo.buf, srcbufinfo.buf, srcbufinfo.len);
+
+ common_hal_aesio_aes_encrypt(aes, (uint8_t *)destbufinfo.buf,
+ destbufinfo.len);
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(aesio_aes_encrypt_into_obj,
+ aesio_aes_encrypt_into);
+
+//| def decrypt_into(src, dest) -> None:
+//|
+//| """Decrypt the buffer from ``src`` into ``dest``.
+//| For ECB mode, the buffers must be 16 bytes long. For CBC mode, the
+//| buffers must be a multiple of 16 bytes, and must be equal length. For
+//| CTX mode, there are no restrictions."""
+//| ...
+//|
+STATIC mp_obj_t aesio_aes_decrypt_into(mp_obj_t aesio_obj, mp_obj_t src,
+ mp_obj_t dest) {
+ if (!MP_OBJ_IS_TYPE(aesio_obj, &aesio_aes_type)) {
+ mp_raise_TypeError_varg(translate("Expected a %q"), aesio_aes_type.name);
+ }
+ // Convert parameters into expected types.
+ aesio_aes_obj_t *aes = MP_OBJ_TO_PTR(aesio_obj);
+
+ mp_buffer_info_t srcbufinfo, destbufinfo;
+ mp_get_buffer_raise(src, &srcbufinfo, MP_BUFFER_READ);
+ mp_get_buffer_raise(dest, &destbufinfo, MP_BUFFER_WRITE);
+ validate_length(aes, srcbufinfo.len, destbufinfo.len);
+
+ memcpy(destbufinfo.buf, srcbufinfo.buf, srcbufinfo.len);
+
+ common_hal_aesio_aes_decrypt(aes, (uint8_t *)destbufinfo.buf,
+ destbufinfo.len);
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(aesio_aes_decrypt_into_obj,
+ aesio_aes_decrypt_into);
+
+STATIC mp_obj_t aesio_aes_get_mode(mp_obj_t aesio_obj) {
+ if (!MP_OBJ_IS_TYPE(aesio_obj, &aesio_aes_type)) {
+ mp_raise_TypeError_varg(translate("Expected a %q"), aesio_aes_type.name);
+ }
+ aesio_aes_obj_t *self = MP_OBJ_TO_PTR(aesio_obj);
+ return MP_OBJ_NEW_SMALL_INT(self->mode);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(aesio_aes_get_mode_obj, aesio_aes_get_mode);
+
+STATIC mp_obj_t aesio_aes_set_mode(mp_obj_t aesio_obj, mp_obj_t mode_obj) {
+ if (!MP_OBJ_IS_TYPE(aesio_obj, &aesio_aes_type)) {
+ mp_raise_TypeError_varg(translate("Expected a %q"), aesio_aes_type.name);
+ }
+ aesio_aes_obj_t *self = MP_OBJ_TO_PTR(aesio_obj);
+
+ int mode = mp_obj_get_int(mode_obj);
+ switch (mode) {
+ case AES_MODE_CBC:
+ case AES_MODE_ECB:
+ case AES_MODE_CTR:
+ break;
+ default:
+ mp_raise_TypeError(translate("Requested AES mode is unsupported"));
+ }
+
+ common_hal_aesio_aes_set_mode(self, mode);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(aesio_aes_set_mode_obj, aesio_aes_set_mode);
+
+const mp_obj_property_t aesio_aes_mode_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&aesio_aes_get_mode_obj,
+ (mp_obj_t)&aesio_aes_set_mode_obj, (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t aesio_locals_dict_table[] = {
+ // Methods
+ {MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_AES)},
+ {MP_ROM_QSTR(MP_QSTR_encrypt_into), (mp_obj_t)&aesio_aes_encrypt_into_obj},
+ {MP_ROM_QSTR(MP_QSTR_decrypt_into), (mp_obj_t)&aesio_aes_decrypt_into_obj},
+ {MP_ROM_QSTR(MP_QSTR_rekey), (mp_obj_t)&aesio_aes_rekey_obj},
+ {MP_ROM_QSTR(MP_QSTR_mode), (mp_obj_t)&aesio_aes_mode_obj},
+};
+STATIC MP_DEFINE_CONST_DICT(aesio_locals_dict, aesio_locals_dict_table);
+
+const mp_obj_type_t aesio_aes_type = {
+ {&mp_type_type},
+ .name = MP_QSTR_AES,
+ .make_new = aesio_aes_make_new,
+ .locals_dict = (mp_obj_dict_t *)&aesio_locals_dict,
+};
diff --git a/shared-bindings/analogio/AnalogIn.c b/shared-bindings/analogio/AnalogIn.c
index 9a9b525d8..400784b39 100644
--- a/shared-bindings/analogio/AnalogIn.c
+++ b/shared-bindings/analogio/AnalogIn.c
@@ -36,26 +36,24 @@
#include "shared-bindings/analogio/AnalogIn.h"
#include "shared-bindings/util.h"
-//| .. currentmodule:: analogio
+//| class AnalogIn:
+//| """Read analog voltage levels
//|
-//| :class:`AnalogIn` -- read analog voltage
-//| ============================================
+//| Usage::
//|
-//| Usage::
+//| import analogio
+//| from board import *
//|
-//| import analogio
-//| from board import *
-//|
-//| adc = analogio.AnalogIn(A1)
-//| val = adc.value
+//| adc = analogio.AnalogIn(A1)
+//| val = adc.value"""
//|
-//| .. class:: AnalogIn(pin)
-//|
-//| Use the AnalogIn on the given pin. The reference voltage varies by
-//| platform so use ``reference_voltage`` to read the configured setting.
+//| def __init__(self, pin: microcontroller.Pin):
+//| """Use the AnalogIn on the given pin. The reference voltage varies by
+//| platform so use ``reference_voltage`` to read the configured setting.
//|
-//| :param ~microcontroller.Pin pin: the pin to read from
+//| :param ~microcontroller.Pin pin: the pin to read from"""
+//| ...
//|
STATIC mp_obj_t analogio_analogin_make_new(const mp_obj_type_t *type,
mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
@@ -63,21 +61,18 @@ STATIC mp_obj_t analogio_analogin_make_new(const mp_obj_type_t *type,
mp_arg_check_num(n_args, kw_args, 1, 1, false);
// 1st argument is the pin
- mp_obj_t pin_obj = args[0];
- assert_pin(pin_obj, false);
+ const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
analogio_analogin_obj_t *self = m_new_obj(analogio_analogin_obj_t);
self->base.type = &analogio_analogin_type;
- const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj);
- assert_pin_free(pin);
common_hal_analogio_analogin_construct(self, pin);
- return (mp_obj_t) self;
+ return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Turn off the AnalogIn and release the pin for other use.
+//| def deinit(self, ) -> Any:
+//| """Turn off the AnalogIn and release the pin for other use."""
+//| ...
//|
STATIC mp_obj_t analogio_analogin_deinit(mp_obj_t self_in) {
analogio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -91,16 +86,16 @@ STATIC void check_for_deinit(analogio_analogin_obj_t *self) {
raise_deinited_error();
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t analogio_analogin___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -109,12 +104,11 @@ STATIC mp_obj_t analogio_analogin___exit__(size_t n_args, const mp_obj_t *args)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogin___exit___obj, 4, 4, analogio_analogin___exit__);
-//| .. attribute:: value
-//|
-//| The value on the analog pin between 0 and 65535 inclusive (16-bit). (read-only)
+//| value: Any = ...
+//| """The value on the analog pin between 0 and 65535 inclusive (16-bit). (read-only)
//|
//| Even if the underlying analog to digital converter (ADC) is lower
-//| resolution, the value is 16-bit.
+//| resolution, the value is 16-bit."""
//|
STATIC mp_obj_t analogio_analogin_obj_get_value(mp_obj_t self_in) {
analogio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -130,10 +124,9 @@ const mp_obj_property_t analogio_analogin_value_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: reference_voltage
-//|
-//| The maximum voltage measurable (also known as the reference voltage) as a
-//| `float` in Volts.
+//| reference_voltage: Any = ...
+//| """The maximum voltage measurable (also known as the reference voltage) as a
+//| `float` in Volts."""
//|
STATIC mp_obj_t analogio_analogin_obj_get_reference_voltage(mp_obj_t self_in) {
analogio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -141,7 +134,7 @@ STATIC mp_obj_t analogio_analogin_obj_get_reference_voltage(mp_obj_t self_in) {
float reference_voltage = common_hal_analogio_analogin_get_reference_voltage(self);
if (reference_voltage <= 0.0f) {
- return mp_const_none;
+ return mp_const_none;
} else {
return mp_obj_new_float(reference_voltage);
}
diff --git a/shared-bindings/analogio/AnalogOut.c b/shared-bindings/analogio/AnalogOut.c
index 0816da465..a8edcc0ae 100644
--- a/shared-bindings/analogio/AnalogOut.c
+++ b/shared-bindings/analogio/AnalogOut.c
@@ -36,46 +36,39 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: analogio
+//| class AnalogOut:
+//| """Output analog values (a specific voltage).
//|
-//| :class:`AnalogOut` -- output analog voltage
-//| ============================================
+//| Example usage::
//|
-//| The AnalogOut is used to output analog values (a specific voltage).
+//| import analogio
+//| from microcontroller import pin
//|
-//| Example usage::
+//| dac = analogio.AnalogOut(pin.PA02) # output on pin PA02
+//| dac.value = 32768 # makes PA02 1.65V"""
//|
-//| import analogio
-//| from microcontroller import pin
+//| def __init__(self, pin: microcontroller.Pin):
+//| """Use the AnalogOut on the given pin.
//|
-//| dac = analogio.AnalogOut(pin.PA02) # output on pin PA02
-//| dac.value = 32768 # makes PA02 1.65V
-//|
-
-//| .. class:: AnalogOut(pin)
-//|
-//| Use the AnalogOut on the given pin.
-//|
-//| :param ~microcontroller.Pin pin: the pin to output to
+//| :param ~microcontroller.Pin pin: the pin to output to"""
+//| ...
//|
STATIC mp_obj_t analogio_analogout_make_new(const mp_obj_type_t *type, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// check arguments
mp_arg_check_num(n_args, kw_args, 1, 1, false);
- assert_pin(args[0], false);
- const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]);
+ const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
analogio_analogout_obj_t *self = m_new_obj(analogio_analogout_obj_t);
self->base.type = &analogio_analogout_type;
- assert_pin_free(pin);
common_hal_analogio_analogout_construct(self, pin);
- return self;
+ return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Turn off the AnalogOut and release the pin for other use.
+//| def deinit(self, ) -> Any:
+//| """Turn off the AnalogOut and release the pin for other use."""
+//| ...
//|
STATIC mp_obj_t analogio_analogout_deinit(mp_obj_t self_in) {
analogio_analogout_obj_t *self = self_in;
@@ -86,16 +79,16 @@ STATIC mp_obj_t analogio_analogout_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(analogio_analogout_deinit_obj, analogio_analogout_deinit);
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t analogio_analogout___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -104,12 +97,12 @@ STATIC mp_obj_t analogio_analogout___exit__(size_t n_args, const mp_obj_t *args)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogout___exit___obj, 4, 4, analogio_analogout___exit__);
-//| .. attribute:: value
-//|
-//| The value on the analog pin between 0 and 65535 inclusive (16-bit). (write-only)
+//| value: Any = ...
+//| """The value on the analog pin between 0 and 65535 inclusive (16-bit). (write-only)
//|
//| Even if the underlying digital to analog converter (DAC) is lower
-//| resolution, the value is 16-bit.
+//| resolution, the value is 16-bit."""
+//|
STATIC mp_obj_t analogio_analogout_obj_set_value(mp_obj_t self_in, mp_obj_t value) {
analogio_analogout_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (common_hal_analogio_analogout_deinited(self)) {
diff --git a/shared-bindings/analogio/__init__.c b/shared-bindings/analogio/__init__.c
index b468bcde0..1f059f340 100644
--- a/shared-bindings/analogio/__init__.c
+++ b/shared-bindings/analogio/__init__.c
@@ -34,25 +34,12 @@
#include "shared-bindings/analogio/AnalogIn.h"
#include "shared-bindings/analogio/AnalogOut.h"
-//| :mod:`analogio` --- Analog hardware support
-//| =================================================
-//|
-//| .. module:: analogio
-//| :synopsis: Analog hardware support
-//| :platform: SAMD21, ESP8266
+//| """Analog hardware support
//|
//| The `analogio` module contains classes to provide access to analog IO
//| typically implemented with digital-to-analog (DAC) and analog-to-digital
//| (ADC) converters.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| AnalogIn
-//| AnalogOut
-//|
//| 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
@@ -70,7 +57,7 @@
//| This example will initialize the the device, read
//| :py:data:`~analogio.AnalogIn.value` and then
//| :py:meth:`~analogio.AnalogIn.deinit` the hardware. The last step is optional
-//| because CircuitPython will do it automatically after the program finishes.
+//| because CircuitPython will do it automatically after the program finishes."""
//|
STATIC const mp_rom_map_elem_t analogio_module_globals_table[] = {
diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c
index 8f7382fde..fd71a6e85 100644
--- a/shared-bindings/audiobusio/I2SOut.c
+++ b/shared-bindings/audiobusio/I2SOut.c
@@ -35,64 +35,60 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiobusio
+//| class I2SOut:
+//| """Output an I2S audio signal"""
//|
-//| :class:`I2SOut` -- Output an I2S audio signal
-//| ========================================================
+//| def __init__(self, bit_clock: microcontroller.Pin, word_select: microcontroller.Pin, data: microcontroller.Pin, *, left_justified: bool):
+//| """Create a I2SOut object associated with the given pins.
//|
-//| I2S is used to output an audio signal on an I2S bus.
+//| :param ~microcontroller.Pin bit_clock: The bit clock (or serial clock) pin
+//| :param ~microcontroller.Pin word_select: The word select (or left/right clock) pin
+//| :param ~microcontroller.Pin data: The data pin
+//| :param bool left_justified: True when data bits are aligned with the word select clock. False
+//| when they are shifted by one to match classic I2S protocol.
//|
-//| .. class:: I2SOut(bit_clock, word_select, data, *, left_justified)
+//| Simple 8ksps 440 Hz sine wave on `Metro M0 Express <https://www.adafruit.com/product/3505>`_
+//| using `UDA1334 Breakout <https://www.adafruit.com/product/3678>`_::
//|
-//| Create a I2SOut object associated with the given pins.
+//| import audiobusio
+//| import audiocore
+//| import board
+//| import array
+//| import time
+//| import math
//|
-//| :param ~microcontroller.Pin bit_clock: The bit clock (or serial clock) pin
-//| :param ~microcontroller.Pin word_select: The word select (or left/right clock) pin
-//| :param ~microcontroller.Pin data: The data pin
-//| :param bool left_justified: True when data bits are aligned with the word select clock. False
-//| when they are shifted by one to match classic I2S protocol.
+//| # Generate one period of sine wave.
+//| length = 8000 // 440
+//| sine_wave = array.array("H", [0] * length)
+//| for i in range(length):
+//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
//|
-//| Simple 8ksps 440 Hz sine wave on `Metro M0 Express <https://www.adafruit.com/product/3505>`_
-//| using `UDA1334 Breakout <https://www.adafruit.com/product/3678>`_::
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
+//| i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9)
+//| i2s.play(sine_wave, loop=True)
+//| time.sleep(1)
+//| i2s.stop()
//|
-//| import audiobusio
-//| import audiocore
-//| import board
-//| import array
-//| import time
-//| import math
+//| Playing a wave file from flash::
//|
-//| # Generate one period of sine wave.
-//| length = 8000 // 440
-//| sine_wave = array.array("H", [0] * length)
-//| for i in range(length):
-//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
+//| import board
+//| import audioio
+//| import audiocore
+//| import audiobusio
+//| import digitalio
//|
-//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
-//| i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9)
-//| i2s.play(sine_wave, loop=True)
-//| time.sleep(1)
-//| i2s.stop()
//|
-//| Playing a wave file from flash::
+//| f = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audiocore.WaveFile(f)
//|
-//| import board
-//| import audioio
-//| import audiocore
-//| import audiobusio
-//| import digitalio
+//| a = audiobusio.I2SOut(board.D1, board.D0, board.D9)
//|
-//|
-//| f = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audiocore.WaveFile(f)
-//|
-//| a = audiobusio.I2SOut(board.D1, board.D0, board.D9)
-//|
-//| print("playing")
-//| a.play(wav)
-//| while a.playing:
-//| pass
-//| print("stopped")
+//| print("playing")
+//| a.play(wav)
+//| while a.playing:
+//| pass
+//| print("stopped")"""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_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_bit_clock, ARG_word_select, ARG_data, ARG_left_justified };
@@ -105,17 +101,9 @@ STATIC mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_obj_t bit_clock_obj = args[ARG_bit_clock].u_obj;
- assert_pin(bit_clock_obj, false);
- const mcu_pin_obj_t *bit_clock = MP_OBJ_TO_PTR(bit_clock_obj);
-
- mp_obj_t word_select_obj = args[ARG_word_select].u_obj;
- assert_pin(word_select_obj, false);
- const mcu_pin_obj_t *word_select = MP_OBJ_TO_PTR(word_select_obj);
-
- mp_obj_t data_obj = args[ARG_data].u_obj;
- assert_pin(data_obj, false);
- const mcu_pin_obj_t *data = MP_OBJ_TO_PTR(data_obj);
+ const mcu_pin_obj_t *bit_clock = validate_obj_is_free_pin(args[ARG_bit_clock].u_obj);
+ const mcu_pin_obj_t *word_select = validate_obj_is_free_pin(args[ARG_word_select].u_obj);
+ const mcu_pin_obj_t *data = validate_obj_is_free_pin(args[ARG_data].u_obj);
audiobusio_i2sout_obj_t *self = m_new_obj_with_finaliser(audiobusio_i2sout_obj_t);
self->base.type = &audiobusio_i2sout_type;
@@ -124,9 +112,9 @@ STATIC mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the I2SOut and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the I2SOut and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_deinit(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -140,16 +128,16 @@ STATIC void check_for_deinit(audiobusio_i2sout_obj_t *self) {
raise_deinited_error();
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -159,14 +147,14 @@ 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__);
-//| .. method:: play(sample, *, loop=False)
-//|
-//| Plays the sample once when loop=False and continuously when loop=True.
-//| Does not block. Use `playing` to block.
+//| def play(self, sample: Any, *, loop: Any = False) -> Any:
+//| """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`, or `audiomixer.Mixer`.
//|
-//| The sample itself should consist of 8 bit or 16 bit samples.
+//| The sample itself should consist of 8 bit or 16 bit samples."""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sample, ARG_loop };
@@ -186,9 +174,9 @@ STATIC mp_obj_t audiobusio_i2sout_obj_play(size_t n_args, const mp_obj_t *pos_ar
}
MP_DEFINE_CONST_FUN_OBJ_KW(audiobusio_i2sout_play_obj, 1, audiobusio_i2sout_obj_play);
-//| .. method:: stop()
-//|
-//| Stops playback.
+//| def stop(self, ) -> Any:
+//| """Stops playback."""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_obj_stop(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -198,9 +186,8 @@ STATIC mp_obj_t audiobusio_i2sout_obj_stop(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_stop_obj, audiobusio_i2sout_obj_stop);
-//| .. attribute:: playing
-//|
-//| True when the audio sample is being output. (read-only)
+//| playing: Any = ...
+//| """True when the audio sample is being output. (read-only)"""
//|
STATIC mp_obj_t audiobusio_i2sout_obj_get_playing(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -216,9 +203,9 @@ const mp_obj_property_t audiobusio_i2sout_playing_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: pause()
-//|
-//| Stops playback temporarily while remembering the position. Use `resume` to resume playback.
+//| def pause(self, ) -> Any:
+//| """Stops playback temporarily while remembering the position. Use `resume` to resume playback."""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_obj_pause(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -232,9 +219,9 @@ STATIC mp_obj_t audiobusio_i2sout_obj_pause(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_pause_obj, audiobusio_i2sout_obj_pause);
-//| .. method:: resume()
-//|
-//| Resumes sample playback after :py:func:`pause`.
+//| def resume(self, ) -> Any:
+//| """Resumes sample playback after :py:func:`pause`."""
+//| ...
//|
STATIC mp_obj_t audiobusio_i2sout_obj_resume(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -248,9 +235,8 @@ STATIC mp_obj_t audiobusio_i2sout_obj_resume(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_resume_obj, audiobusio_i2sout_obj_resume);
-//| .. attribute:: paused
-//|
-//| True when playback is paused. (read-only)
+//| paused: Any = ...
+//| """True when playback is paused. (read-only)"""
//|
STATIC mp_obj_t audiobusio_i2sout_obj_get_paused(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c
index 0c92c2478..5b950297b 100644
--- a/shared-bindings/audiobusio/PDMIn.c
+++ b/shared-bindings/audiobusio/PDMIn.c
@@ -36,56 +36,52 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiobusio
-//|
-//| :class:`PDMIn` -- Record an input PDM audio stream
-//| ========================================================
-//|
-//| PDMIn can be used to record an input audio signal on a given set of pins.
-//|
-//| .. class:: PDMIn(clock_pin, data_pin, *, sample_rate=16000, bit_depth=8, mono=True, oversample=64, startup_delay=0.11)
-//|
-//| Create a PDMIn object associated with the given pins. This allows you to
-//| record audio signals from the given pins. Individual ports may put further
-//| restrictions on the recording parameters. The overall sample rate is
-//| determined by `sample_rate` x ``oversample``, and the total must be 1MHz or
-//| higher, so `sample_rate` must be a minimum of 16000.
-//|
-//| :param ~microcontroller.Pin clock_pin: The pin to output the clock to
-//| :param ~microcontroller.Pin data_pin: The pin to read the data from
-//| :param int sample_rate: Target sample_rate of the resulting samples. Check `sample_rate` for actual value.
-//| Minimum sample_rate is about 16000 Hz.
-//| :param int bit_depth: Final number of bits per sample. Must be divisible by 8
-//| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise
-//| :param int oversample: Number of single bit samples to decimate into a final sample. Must be divisible by 8
-//| :param float startup_delay: seconds to wait after starting microphone clock
-//| to allow microphone to turn on. Most require only 0.01s; some require 0.1s. Longer is safer.
-//| Must be in range 0.0-1.0 seconds.
-//|
-
-//| Record 8-bit unsigned samples to buffer::
-//|
-//| import audiobusio
-//| import board
-//|
-//| # Prep a buffer to record into
-//| b = bytearray(200)
-//| with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000) as mic:
-//| mic.record(b, len(b))
-//|
-//| Record 16-bit unsigned samples to buffer::
-//|
-//| import audiobusio
-//| import board
-//|
-//| # Prep a buffer to record into. The array interface doesn't allow for
-//| # constructing with a set size so we append to it until we have the size
-//| # we want.
-//| b = array.array("H")
-//| for i in range(200):
-//| b.append(0)
-//| with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16) as mic:
-//| mic.record(b, len(b))
+//| class PDMIn:
+//| """Record an input PDM audio stream"""
+//|
+//| def __init__(self, clock_pin: microcontroller.Pin, data_pin: microcontroller.Pin, *, sample_rate: int = 16000, bit_depth: int = 8, mono: bool = True, oversample: int = 64, startup_delay: float = 0.11):
+//| """Create a PDMIn object associated with the given pins. This allows you to
+//| record audio signals from the given pins. Individual ports may put further
+//| restrictions on the recording parameters. The overall sample rate is
+//| determined by `sample_rate` x ``oversample``, and the total must be 1MHz or
+//| higher, so `sample_rate` must be a minimum of 16000.
+//|
+//| :param ~microcontroller.Pin clock_pin: The pin to output the clock to
+//| :param ~microcontroller.Pin data_pin: The pin to read the data from
+//| :param int sample_rate: Target sample_rate of the resulting samples. Check `sample_rate` for actual value.
+//| Minimum sample_rate is about 16000 Hz.
+//| :param int bit_depth: Final number of bits per sample. Must be divisible by 8
+//| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise
+//| :param int oversample: Number of single bit samples to decimate into a final sample. Must be divisible by 8
+//| :param float startup_delay: seconds to wait after starting microphone clock
+//| to allow microphone to turn on. Most require only 0.01s; some require 0.1s. Longer is safer.
+//| Must be in range 0.0-1.0 seconds."""
+//|
+
+//| """Record 8-bit unsigned samples to buffer::
+//|
+//| import audiobusio
+//| import board
+//|
+//| # Prep a buffer to record into
+//| b = bytearray(200)
+//| with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000) as mic:
+//| mic.record(b, len(b))
+//|
+//| Record 16-bit unsigned samples to buffer::
+//|
+//| import audiobusio
+//| import board
+//|
+//| # Prep a buffer to record into. The array interface doesn't allow for
+//| # constructing with a set size so we append to it until we have the size
+//| # we want.
+//| b = array.array("H")
+//| for i in range(200):
+//| b.append(0)
+//| with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16) as mic:
+//| mic.record(b, len(b))"""
+//| ...
//|
STATIC mp_obj_t audiobusio_pdmin_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_clock_pin, ARG_data_pin, ARG_sample_rate, ARG_bit_depth, ARG_mono, ARG_oversample, ARG_startup_delay };
@@ -104,15 +100,8 @@ STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_obj_t clock_pin_obj = args[ARG_clock_pin].u_obj;
- assert_pin(clock_pin_obj, false);
- const mcu_pin_obj_t *clock_pin = MP_OBJ_TO_PTR(clock_pin_obj);
- assert_pin_free(clock_pin);
-
- mp_obj_t data_pin_obj = args[ARG_data_pin].u_obj;
- assert_pin(data_pin_obj, false);
- const mcu_pin_obj_t *data_pin = MP_OBJ_TO_PTR(data_pin_obj);
- assert_pin_free(data_pin);
+ const mcu_pin_obj_t *clock_pin = validate_obj_is_free_pin(args[ARG_clock_pin].u_obj);
+ const mcu_pin_obj_t *data_pin = validate_obj_is_free_pin(args[ARG_data_pin].u_obj);
// create PDMIn object from the given pin
audiobusio_pdmin_obj_t *self = m_new_obj(audiobusio_pdmin_obj_t);
@@ -145,9 +134,9 @@ STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the PDMIn and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the PDMIn and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audiobusio_pdmin_deinit(mp_obj_t self_in) {
audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -161,15 +150,15 @@ STATIC void check_for_deinit(audiobusio_pdmin_obj_t *self) {
raise_deinited_error();
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context."""
+//| ...
//|
STATIC mp_obj_t audiobusio_pdmin_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -179,17 +168,17 @@ STATIC mp_obj_t audiobusio_pdmin_obj___exit__(size_t n_args, const mp_obj_t *arg
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4, audiobusio_pdmin_obj___exit__);
-//| .. method:: record(destination, destination_length)
+//| def record(self, destination: Any, destination_length: Any) -> Any:
+//| """Records destination_length bytes of samples to destination. This is
+//| blocking.
//|
-//| Records destination_length bytes of samples to destination. This is
-//| blocking.
+//| An IOError may be raised when the destination is too slow to record the
+//| audio at the given rate. For internal flash, writing all 1s to the file
+//| before recording is recommended to speed up writes.
//|
-//| An IOError may be raised when the destination is too slow to record the
-//| audio at the given rate. For internal flash, writing all 1s to the file
-//| before recording is recommended to speed up writes.
-//|
-//| :return: The number of samples recorded. If this is less than ``destination_length``,
-//| some samples were missed due to processing time.
+//| :return: The number of samples recorded. If this is less than ``destination_length``,
+//| some samples were missed due to processing time."""
+//| ...
//|
STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) {
audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_obj);
@@ -221,10 +210,9 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat
}
MP_DEFINE_CONST_FUN_OBJ_3(audiobusio_pdmin_record_obj, audiobusio_pdmin_obj_record);
-//| .. attribute:: sample_rate
-//|
-//| The actual sample_rate of the recording. This may not match the constructed
-//| sample rate due to internal clock limitations.
+//| sample_rate: Any = ...
+//| """The actual sample_rate of the recording. This may not match the constructed
+//| sample rate due to internal clock limitations."""
//|
STATIC mp_obj_t audiobusio_pdmin_obj_get_sample_rate(mp_obj_t self_in) {
audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audiobusio/__init__.c b/shared-bindings/audiobusio/__init__.c
index f7e3a0766..89ccbb88b 100644
--- a/shared-bindings/audiobusio/__init__.c
+++ b/shared-bindings/audiobusio/__init__.c
@@ -34,29 +34,16 @@
#include "shared-bindings/audiobusio/I2SOut.h"
#include "shared-bindings/audiobusio/PDMIn.h"
-//| :mod:`audiobusio` --- Support for audio input and output over digital bus
-//| =========================================================================
-//|
-//| .. module:: audiobusio
-//| :synopsis: Support for audio input and output over digital bus
-//| :platform: SAMD21
+//| """Support for audio input and output over digital buses
//|
//| The `audiobusio` module contains classes to provide access to audio IO
//| over digital buses. These protocols are used to communicate audio to other
//| chips in the same circuit. It doesn't include audio interconnect protocols
//| such as S/PDIF.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| I2SOut
-//| PDMIn
-//|
//| All libraries change hardware state and should be deinitialized when they
//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a
-//| context manager.
+//| context manager."""
//|
STATIC const mp_rom_map_elem_t audiobusio_module_globals_table[] = {
diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c
index 87d410ea1..2eadf1fab 100644
--- a/shared-bindings/audiocore/RawSample.c
+++ b/shared-bindings/audiocore/RawSample.c
@@ -35,44 +35,40 @@
#include "shared-bindings/audiocore/RawSample.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiocore
-//|
-//| :class:`RawSample` -- A raw audio sample buffer
-//| ========================================================
-//|
-//| An in-memory sound sample
-//|
-//| .. class:: RawSample(buffer, *, channel_count=1, sample_rate=8000)
-//|
-//| Create a RawSample based on the given buffer of signed values. If channel_count is more than
-//| 1 then each channel's samples should alternate. In other words, for a two channel buffer, the
-//| first sample will be for channel 1, the second sample will be for channel two, the third for
-//| channel 1 and so on.
-//|
-//| :param array buffer: An `array.array` with samples
-//| :param int channel_count: The number of channels in the buffer
-//| :param int sample_rate: The desired playback sample rate
-//|
-//| Simple 8ksps 440 Hz sin wave::
-//|
-//| import audiocore
-//| import audioio
-//| import board
-//| import array
-//| import time
-//| import math
-//|
-//| # Generate one period of sine wav.
-//| length = 8000 // 440
-//| sine_wave = array.array("h", [0] * length)
-//| for i in range(length):
-//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15))
-//|
-//| dac = audioio.AudioOut(board.SPEAKER)
-//| sine_wave = audiocore.RawSample(sine_wave)
-//| dac.play(sine_wave, loop=True)
-//| time.sleep(1)
-//| dac.stop()
+//| class RawSample:
+//| """A raw audio sample buffer in memory"""
+//|
+//| def __init__(self, buffer: array.array, *, channel_count: int = 1, sample_rate: int = 8000):
+//| """Create a RawSample based on the given buffer of signed values. If channel_count is more than
+//| 1 then each channel's samples should alternate. In other words, for a two channel buffer, the
+//| first sample will be for channel 1, the second sample will be for channel two, the third for
+//| channel 1 and so on.
+//|
+//| :param array.array buffer: An `array.array` with samples
+//| :param int channel_count: The number of channels in the buffer
+//| :param int sample_rate: The desired playback sample rate
+//|
+//| Simple 8ksps 440 Hz sin wave::
+//|
+//| import audiocore
+//| import audioio
+//| import board
+//| import array
+//| import time
+//| import math
+//|
+//| # Generate one period of sine wav.
+//| length = 8000 // 440
+//| sine_wave = array.array("h", [0] * length)
+//| for i in range(length):
+//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
+//|
+//| dac = audioio.AudioOut(board.SPEAKER)
+//| sine_wave = audiocore.RawSample(sine_wave)
+//| dac.play(sine_wave, loop=True)
+//| time.sleep(1)
+//| dac.stop()"""
+//| ...
//|
STATIC mp_obj_t audioio_rawsample_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_buffer, ARG_channel_count, ARG_sample_rate };
@@ -105,9 +101,9 @@ STATIC mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the AudioOut and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the AudioOut and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audioio_rawsample_deinit(mp_obj_t self_in) {
audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -122,16 +118,16 @@ STATIC void check_for_deinit(audioio_rawsample_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t audioio_rawsample_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -140,12 +136,11 @@ STATIC mp_obj_t audioio_rawsample_obj___exit__(size_t n_args, const mp_obj_t *ar
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_rawsample___exit___obj, 4, 4, audioio_rawsample_obj___exit__);
-//| .. attribute:: sample_rate
-//|
-//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
+//| sample_rate: Any = ...
+//| """32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
//| When the sample is looped, this can change the pitch output without changing the underlying
//| sample. This will not change the sample rate of any active playback. Call ``play`` again to
-//| change it.
+//| change it."""
//|
STATIC mp_obj_t audioio_rawsample_obj_get_sample_rate(mp_obj_t self_in) {
audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c
index 178d2a139..a067f6cda 100644
--- a/shared-bindings/audiocore/WaveFile.c
+++ b/shared-bindings/audiocore/WaveFile.c
@@ -33,43 +33,41 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiocore
+//| class WaveFile:
+//| """Load a wave file for audio playback
//|
-//| :class:`WaveFile` -- Load a wave file for audio playback
-//| ========================================================
+//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
+//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
+//| an internal buffer."""
//|
-//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
-//| 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: bytearray):
+//| """Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
-//| .. class:: WaveFile(file[, buffer])
+//| :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.
//|
-//| 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.
+//| Playing a wave file from flash::
//|
+//| import board
+//| import audiocore
+//| import audioio
+//| import digitalio
//|
-//| Playing a wave file from flash::
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
//|
-//| import board
-//| import audiocore
-//| import audioio
-//| import digitalio
+//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audiocore.WaveFile(data)
+//| a = audioio.AudioOut(board.A0)
//|
-//| # Required for CircuitPlayground Express
-//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
-//| speaker_enable.switch_to_output(value=True)
-//|
-//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audiocore.WaveFile(data)
-//| a = audioio.AudioOut(board.A0)
-//|
-//| print("playing")
-//| a.play(wav)
-//| while a.playing:
-//| pass
-//| print("stopped")
+//| print("playing")
+//| a.play(wav)
+//| while a.playing:
+//| pass
+//| print("stopped")"""
+//| ...
//|
STATIC mp_obj_t audioio_wavefile_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, 2, false);
@@ -93,10 +91,9 @@ STATIC mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the WaveFile and releases all memory resources for reuse.
-//|
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the WaveFile and releases all memory resources for reuse."""
+//| ...
STATIC mp_obj_t audioio_wavefile_deinit(mp_obj_t self_in) {
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audioio_wavefile_deinit(self);
@@ -110,16 +107,16 @@ STATIC void check_for_deinit(audioio_wavefile_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t audioio_wavefile_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -128,11 +125,10 @@ STATIC mp_obj_t audioio_wavefile_obj___exit__(size_t n_args, const mp_obj_t *arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_wavefile___exit___obj, 4, 4, audioio_wavefile_obj___exit__);
-//| .. attribute:: sample_rate
-//|
-//| 32 bit value that dictates how quickly samples are loaded into the DAC
+//| sample_rate: Any = ...
+//| """32 bit value that dictates how quickly samples are loaded into the DAC
//| in Hertz (cycles per second). When the sample is looped, this can change
-//| the pitch output without changing the underlying sample.
+//| the pitch output without changing the underlying sample."""
//|
STATIC mp_obj_t audioio_wavefile_obj_get_sample_rate(mp_obj_t self_in) {
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -156,9 +152,8 @@ const mp_obj_property_t audioio_wavefile_sample_rate_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: bits_per_sample
-//|
-//| Bits per sample. (read only)
+//| bits_per_sample: Any = ...
+//| """Bits per sample. (read only)"""
//|
STATIC mp_obj_t audioio_wavefile_obj_get_bits_per_sample(mp_obj_t self_in) {
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -173,10 +168,8 @@ const mp_obj_property_t audioio_wavefile_bits_per_sample_obj = {
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
-
-//| .. attribute:: channel_count
-//|
-//| Number of audio channels. (read only)
+//| channel_count: Any = ...
+//| """Number of audio channels. (read only)"""
//|
STATIC mp_obj_t audioio_wavefile_obj_get_channel_count(mp_obj_t self_in) {
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audiocore/__init__.c b/shared-bindings/audiocore/__init__.c
index cf05112cb..b400b9454 100644
--- a/shared-bindings/audiocore/__init__.c
+++ b/shared-bindings/audiocore/__init__.c
@@ -35,22 +35,7 @@
#include "shared-bindings/audiocore/WaveFile.h"
//#include "shared-bindings/audiomixer/Mixer.h"
-//| :mod:`audiocore` --- Support for audio samples and mixer
-//| ========================================================
-//|
-//| .. module:: audiocore
-//| :synopsis: Support for audio samples and mixer
-//| :platform: SAMD21
-//|
-//| The `audiocore` module contains core classes for audio IO
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| RawSample
-//| WaveFile
+//| """Support for audio samples"""
//|
STATIC const mp_rom_map_elem_t audiocore_module_globals_table[] = {
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index eb4ef1fc6..9ba72bd41 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -36,63 +36,59 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
-//|
-//| :class:`AudioOut` -- Output an analog audio signal
-//| ========================================================
-//|
-//| AudioOut can be used to output an analog audio signal on a given pin.
-//|
-//| .. class:: AudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000)
-//|
-//| Create a AudioOut object associated with the given pin(s). This allows you to
-//| play audio signals out on the given pin(s).
-//|
-//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
-//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
-//| :param int quiescent_value: The output value when no signal is present. Samples should start
-//| and end with this value to prevent audible popping.
-//|
-//| Simple 8ksps 440 Hz sin wave::
-//|
-//| import audiocore
-//| import audioio
-//| import board
-//| import array
-//| import time
-//| import math
-//|
-//| # Generate one period of sine wav.
-//| length = 8000 // 440
-//| sine_wave = array.array("H", [0] * length)
-//| for i in range(length):
-//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
-//|
-//| dac = audioio.AudioOut(board.SPEAKER)
-//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
-//| dac.play(sine_wave, loop=True)
-//| time.sleep(1)
-//| dac.stop()
-//|
-//| Playing a wave file from flash::
-//|
-//| import board
-//| import audioio
-//| import digitalio
-//|
-//| # Required for CircuitPlayground Express
-//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
-//| speaker_enable.switch_to_output(value=True)
-//|
-//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audiocore.WaveFile(data)
-//| a = audioio.AudioOut(board.A0)
-//|
-//| print("playing")
-//| a.play(wav)
-//| while a.playing:
-//| pass
-//| print("stopped")
+//| class AudioOut:
+//| """Output an analog audio signal"""
+//|
+//| def __init__(self, left_channel: microcontroller.Pin, *, right_channel: microcontroller.Pin = None, quiescent_value: int = 0x8000):
+//| """Create a AudioOut object associated with the given pin(s). This allows you to
+//| play audio signals out on the given pin(s).
+//|
+//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
+//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
+//| :param int quiescent_value: The output value when no signal is present. Samples should start
+//| and end with this value to prevent audible popping.
+//|
+//| Simple 8ksps 440 Hz sin wave::
+//|
+//| import audiocore
+//| import audioio
+//| import board
+//| import array
+//| import time
+//| import math
+//|
+//| # Generate one period of sine wav.
+//| length = 8000 // 440
+//| sine_wave = array.array("H", [0] * length)
+//| for i in range(length):
+//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
+//|
+//| dac = audioio.AudioOut(board.SPEAKER)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
+//| dac.play(sine_wave, loop=True)
+//| time.sleep(1)
+//| dac.stop()
+//|
+//| Playing a wave file from flash::
+//|
+//| import board
+//| import audioio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audiocore.WaveFile(data)
+//| a = audioio.AudioOut(board.A0)
+//|
+//| print("playing")
+//| a.play(wav)
+//| while a.playing:
+//| pass
+//| print("stopped")"""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_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_left_channel, ARG_right_channel, ARG_quiescent_value };
@@ -104,16 +100,8 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_obj_t left_channel_obj = args[ARG_left_channel].u_obj;
- assert_pin(left_channel_obj, false);
- const mcu_pin_obj_t *left_channel_pin = MP_OBJ_TO_PTR(left_channel_obj);
-
- mp_obj_t right_channel_obj = args[ARG_right_channel].u_obj;
- const mcu_pin_obj_t *right_channel_pin = NULL;
- if (right_channel_obj != mp_const_none) {
- assert_pin(right_channel_obj, false);
- right_channel_pin = MP_OBJ_TO_PTR(right_channel_obj);
- }
+ const mcu_pin_obj_t *left_channel_pin = validate_obj_is_free_pin(args[ARG_left_channel].u_obj);
+ const mcu_pin_obj_t *right_channel_pin = validate_obj_is_free_pin_or_none(args[ARG_right_channel].u_obj);
// create AudioOut object from the given pin
audioio_audioout_obj_t *self = m_new_obj(audioio_audioout_obj_t);
@@ -123,9 +111,9 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the AudioOut and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the AudioOut and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_deinit(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -139,16 +127,16 @@ STATIC void check_for_deinit(audioio_audioout_obj_t *self) {
raise_deinited_error();
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -158,16 +146,16 @@ 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__);
-//| .. method:: play(sample, *, loop=False)
+//| def play(self, sample: Any, *, loop: Any = False) -> Any:
+//| """Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
//|
-//| 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`, or `audiomixer.Mixer`.
-//|
-//| 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
-//| DAC that ignores the lowest 6 bits when playing 16 bit samples.
+//| 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
+//| DAC that ignores the lowest 6 bits when playing 16 bit samples."""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sample, ARG_loop };
@@ -187,9 +175,9 @@ STATIC mp_obj_t audioio_audioout_obj_play(size_t n_args, const mp_obj_t *pos_arg
}
MP_DEFINE_CONST_FUN_OBJ_KW(audioio_audioout_play_obj, 1, audioio_audioout_obj_play);
-//| .. method:: stop()
-//|
-//| Stops playback and resets to the start of the sample.
+//| def stop(self, ) -> Any:
+//| """Stops playback and resets to the start of the sample."""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_obj_stop(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -199,9 +187,8 @@ STATIC mp_obj_t audioio_audioout_obj_stop(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_stop_obj, audioio_audioout_obj_stop);
-//| .. attribute:: playing
-//|
-//| True when an audio sample is being output even if `paused`. (read-only)
+//| playing: Any = ...
+//| """True when an audio sample is being output even if `paused`. (read-only)"""
//|
STATIC mp_obj_t audioio_audioout_obj_get_playing(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -217,9 +204,9 @@ const mp_obj_property_t audioio_audioout_playing_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: pause()
-//|
-//| Stops playback temporarily while remembering the position. Use `resume` to resume playback.
+//| def pause(self, ) -> Any:
+//| """Stops playback temporarily while remembering the position. Use `resume` to resume playback."""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_obj_pause(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -233,9 +220,9 @@ STATIC mp_obj_t audioio_audioout_obj_pause(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_pause_obj, audioio_audioout_obj_pause);
-//| .. method:: resume()
-//|
-//| Resumes sample playback after :py:func:`pause`.
+//| def resume(self, ) -> Any:
+//| """Resumes sample playback after :py:func:`pause`."""
+//| ...
//|
STATIC mp_obj_t audioio_audioout_obj_resume(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -249,9 +236,8 @@ STATIC mp_obj_t audioio_audioout_obj_resume(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_resume_obj, audioio_audioout_obj_resume);
-//| .. attribute:: paused
-//|
-//| True when playback is paused. (read-only)
+//| paused: Any = ...
+//| """True when playback is paused. (read-only)"""
//|
STATIC mp_obj_t audioio_audioout_obj_get_paused(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c
index 02a5fe1ee..7ec927834 100644
--- a/shared-bindings/audioio/__init__.c
+++ b/shared-bindings/audioio/__init__.c
@@ -42,22 +42,10 @@
#include "shared-bindings/audiomixer/Mixer.h"
#endif
-//| :mod:`audioio` --- Support for audio input and output
-//| ======================================================
-//|
-//| .. module:: audioio
-//| :synopsis: Support for audio input and output
-//| :platform: SAMD21
+//| """Support for audio output
//|
//| The `audioio` module contains classes to provide access to audio IO.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| AudioOut
-//|
//| 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
@@ -68,7 +56,7 @@
//|
//| For compatibility with CircuitPython 4.x, some builds allow the items in
//| `audiocore` to be imported from `audioio`. This will be removed for all
-//| boards in a future build of CircuitPython.
+//| boards in a future build of CircuitPython."""
//|
STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = {
diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c
index 03ffb9373..31e62cdae 100644
--- a/shared-bindings/audiomixer/Mixer.c
+++ b/shared-bindings/audiomixer/Mixer.c
@@ -38,49 +38,45 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiomixer
+//| class Mixer:
+//| """Mixes one or more audio samples together into one sample."""
//|
-//| :class:`Mixer` -- Mixes one or more audio samples together
-//| ===========================================================
+//| def __init__(self, voice_count: int = 2, buffer_size: int = 1024, channel_count: int = 2, bits_per_sample: int = 16, samples_signed: bool = True, sample_rate: int = 8000):
+//| """Create a Mixer object that can mix multiple channels with the same sample rate.
+//| Samples are accessed and controlled with the mixer's `audiomixer.MixerVoice` objects.
//|
-//| Mixer mixes multiple samples into one sample.
+//| :param int voice_count: The maximum number of voices to mix
+//| :param int buffer_size: The total size in bytes of the buffers to mix into
+//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo.
+//| :param int bits_per_sample: The bits per sample of the samples being played
+//| :param bool samples_signed: Samples are signed (True) or unsigned (False)
+//| :param int sample_rate: The sample rate to be used for all samples
//|
-//| .. class:: Mixer(voice_count=2, buffer_size=1024, channel_count=2, bits_per_sample=16, samples_signed=True, sample_rate=8000)
+//| Playing a wave file from flash::
//|
-//| Create a Mixer object that can mix multiple channels with the same sample rate.
-//| Samples are accessed and controlled with the mixer's `audiomixer.MixerVoice` objects.
+//| import board
+//| import audioio
+//| import audiocore
+//| import audiomixer
+//| import digitalio
//|
-//| :param int voice_count: The maximum number of voices to mix
-//| :param int buffer_size: The total size in bytes of the buffers to mix into
-//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo.
-//| :param int bits_per_sample: The bits per sample of the samples being played
-//| :param bool samples_signed: Samples are signed (True) or unsigned (False)
-//| :param int sample_rate: The sample rate to be used for all samples
+//| a = audioio.AudioOut(board.A0)
+//| music = audiocore.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb"))
+//| drum = audiocore.WaveFile(open("drum.wav", "rb"))
+//| mixer = audiomixer.Mixer(voice_count=2, sample_rate=16000, channel_count=1,
+//| bits_per_sample=16, samples_signed=True)
//|
-//| Playing a wave file from flash::
-//|
-//| import board
-//| import audioio
-//| import audiocore
-//| import audiomixer
-//| import digitalio
-//|
-//| a = audioio.AudioOut(board.A0)
-//| music = audiocore.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb"))
-//| drum = audiocore.WaveFile(open("drum.wav", "rb"))
-//| mixer = audiomixer.Mixer(voice_count=2, sample_rate=16000, channel_count=1,
-//| bits_per_sample=16, samples_signed=True)
-//|
-//| print("playing")
-//| # Have AudioOut play our Mixer source
-//| a.play(mixer)
-//| # Play the first sample voice
-//| mixer.voice[0].play(music)
-//| while mixer.playing:
-//| # Play the second sample voice
-//| mixer.voice[1].play(drum)
-//| time.sleep(1)
-//| print("stopped")
+//| print("playing")
+//| # Have AudioOut play our Mixer source
+//| a.play(mixer)
+//| # Play the first sample voice
+//| mixer.voice[0].play(music)
+//| while mixer.playing:
+//| # Play the second sample voice
+//| mixer.voice[1].play(drum)
+//| time.sleep(1)
+//| print("stopped")"""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixer_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_voice_count, ARG_buffer_size, ARG_channel_count, ARG_bits_per_sample, ARG_samples_signed, ARG_sample_rate };
@@ -125,9 +121,9 @@ STATIC mp_obj_t audiomixer_mixer_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the Mixer and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the Mixer and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixer_deinit(mp_obj_t self_in) {
audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -142,16 +138,16 @@ STATIC void check_for_deinit(audiomixer_mixer_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -160,9 +156,8 @@ STATIC mp_obj_t audiomixer_mixer_obj___exit__(size_t n_args, const mp_obj_t *arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomixer_mixer___exit___obj, 4, 4, audiomixer_mixer_obj___exit__);
-//| .. attribute:: playing
-//|
-//| True when any voice is being output. (read-only)
+//| playing: Any = ...
+//| """True when any voice is being output. (read-only)"""
//|
STATIC mp_obj_t audiomixer_mixer_obj_get_playing(mp_obj_t self_in) {
audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -178,9 +173,8 @@ const mp_obj_property_t audiomixer_mixer_playing_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: sample_rate
-//|
-//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
+//| sample_rate: Any = ...
+//| """32 bit value that dictates how quickly samples are played in Hertz (cycles per second)."""
//|
STATIC mp_obj_t audiomixer_mixer_obj_get_sample_rate(mp_obj_t self_in) {
audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -196,14 +190,13 @@ const mp_obj_property_t audiomixer_mixer_sample_rate_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: voice
-//|
-//| A tuple of the mixer's `audiomixer.MixerVoice` object(s).
+//| voice: Any = ...
+//| """A tuple of the mixer's `audiomixer.MixerVoice` object(s).
//|
//| .. code-block:: python
//|
//| >>> mixer.voice
-//| (<MixerVoice>,)
+//| (<MixerVoice>,)"""
STATIC mp_obj_t audiomixer_mixer_obj_get_voice(mp_obj_t self_in) {
audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
@@ -218,14 +211,14 @@ const mp_obj_property_t audiomixer_mixer_voice_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: play(sample, *, voice=0, loop=False)
+//| def play(self, sample: Any, *, voice: Any = 0, loop: Any = False) -> Any:
+//| """Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
//|
-//| 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`, or `audiomixer.Mixer`.
-//|
-//| The sample must match the Mixer's encoding settings given in the constructor.
+//| The sample must match the Mixer's encoding settings given in the constructor."""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sample, ARG_voice, ARG_loop };
@@ -251,9 +244,9 @@ STATIC mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_arg
}
MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixer_play_obj, 1, audiomixer_mixer_obj_play);
-//| .. method:: stop_voice(voice=0)
-//|
-//| Stops playback of the sample on the given voice.
+//| def stop_voice(self, voice: Any = 0) -> Any:
+//| """Stops playback of the sample on the given voice."""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_voice };
diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c
index 188f76f57..ec5768d2f 100644
--- a/shared-bindings/audiomixer/MixerVoice.c
+++ b/shared-bindings/audiomixer/MixerVoice.c
@@ -37,16 +37,14 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiomixer
+//| class MixerVoice:
+//| """Voice objects used with Mixer
//|
-//| :class:`MixerVoice` -- Voice objects used with Mixer
-//| =====================================================
+//| Used to access and control samples with `audiomixer.Mixer`."""
//|
-//| Used to access and control samples with `audiomixer.Mixer`.
-//|
-//| .. class:: MixerVoice()
-//|
-//| MixerVoice instance object(s) created by `audiomixer.Mixer`.
+//| def __init__(self, ):
+//| """MixerVoice instance object(s) created by `audiomixer.Mixer`."""
+//| ...
//|
// TODO: support mono or stereo voices
STATIC mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -58,14 +56,14 @@ STATIC mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: play(sample, *, loop=False)
-//|
-//| Plays the sample once when ``loop=False``, and continuously when ``loop=True``.
-//| Does not block. Use `playing` to block.
+//| def play(self, sample: Any, *, loop: Any = False) -> Any:
+//| """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`, `audiomixer.Mixer` or `audiocore.RawSample`.
//|
-//| The sample must match the `audiomixer.Mixer`'s encoding settings given in the constructor.
+//| The sample must match the `audiomixer.Mixer`'s encoding settings given in the constructor."""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixervoice_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sample, ARG_loop };
@@ -83,9 +81,9 @@ STATIC mp_obj_t audiomixer_mixervoice_obj_play(size_t n_args, const mp_obj_t *po
}
MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_play_obj, 1, audiomixer_mixervoice_obj_play);
-//| .. method:: stop()
-//|
-//| Stops playback of the sample on this voice.
+//| def stop(self, ) -> Any:
+//| """Stops playback of the sample on this voice."""
+//| ...
//|
STATIC mp_obj_t audiomixer_mixervoice_obj_stop(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_voice };
@@ -102,9 +100,8 @@ STATIC mp_obj_t audiomixer_mixervoice_obj_stop(size_t n_args, const mp_obj_t *po
}
MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_stop_obj, 1, audiomixer_mixervoice_obj_stop);
-//| .. attribute:: level()
-//|
-//| The volume level of a voice, as a floating point number between 0 and 1.
+//| level: Any = ...
+//| """The volume level of a voice, as a floating point number between 0 and 1."""
//|
STATIC mp_obj_t audiomixer_mixervoice_obj_get_level(mp_obj_t self_in) {
return mp_obj_new_float(common_hal_audiomixer_mixervoice_get_level(self_in));
@@ -139,9 +136,8 @@ const mp_obj_property_t audiomixer_mixervoice_level_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: playing
-//|
-//| True when this voice is being output. (read-only)
+//| playing: Any = ...
+//| """True when this voice is being output. (read-only)"""
//|
STATIC mp_obj_t audiomixer_mixervoice_obj_get_playing(mp_obj_t self_in) {
diff --git a/shared-bindings/audiomixer/__init__.c b/shared-bindings/audiomixer/__init__.c
index 79bab440e..1146bb798 100644
--- a/shared-bindings/audiomixer/__init__.c
+++ b/shared-bindings/audiomixer/__init__.c
@@ -32,21 +32,7 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/audiomixer/Mixer.h"
-//| :mod:`audiomixer` --- Support for audio mixer
-//| ========================================================
-//|
-//| .. module:: audiomixer
-//| :synopsis: Support for audio mixer
-//|
-//| The `audiomixer` module contains core classes for mixing audio sources
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Mixer
-//| MixerVoice
+//| """Support for audio mixing"""
//|
STATIC const mp_rom_map_elem_t audiomixer_module_globals_table[] = {
diff --git a/shared-bindings/audiomp3/MP3Decoder.c b/shared-bindings/audiomp3/MP3Decoder.c
index 224042212..e6d48e32c 100644
--- a/shared-bindings/audiomp3/MP3Decoder.c
+++ b/shared-bindings/audiomp3/MP3Decoder.c
@@ -34,41 +34,38 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiomp3
+//| class MP3:
+//| """Load a mp3 file for audio playback"""
//|
-//| :class:`MP3Decoder` -- Load a mp3 file for audio playback
-//| =========================================================
+//| def __init__(self, file: typing.BinaryIO, buffer: bytearray):
//|
-//| An object that decodes MP3 files for playback on an audio device.
+//| """Load a .mp3 file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
-//| .. class:: MP3(file[, buffer])
+//| :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.
//|
-//| 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.
+//| Playing a mp3 file from flash::
//|
+//| import board
+//| import audiomp3
+//| import audioio
+//| import digitalio
//|
-//| Playing a mp3 file from flash::
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
//|
-//| import board
-//| import audiomp3
-//| import audioio
-//| import digitalio
+//| data = open("cplay-16bit-16khz-64kbps.mp3", "rb")
+//| mp3 = audiomp3.MP3Decoder(data)
+//| a = audioio.AudioOut(board.A0)
//|
-//| # Required for CircuitPlayground Express
-//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
-//| speaker_enable.switch_to_output(value=True)
-//|
-//| data = open("cplay-16bit-16khz-64kbps.mp3", "rb")
-//| mp3 = audiomp3.MP3Decoder(data)
-//| a = audioio.AudioOut(board.A0)
-//|
-//| print("playing")
-//| a.play(mp3)
-//| while a.playing:
-//| pass
-//| print("stopped")
+//| print("playing")
+//| a.play(mp3)
+//| while a.playing:
+//| pass
+//| print("stopped")"""
+//| ...
//|
STATIC mp_obj_t audiomp3_mp3file_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, 2, false);
@@ -92,9 +89,9 @@ STATIC mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the MP3 and releases all memory resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the MP3 and releases all memory resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audiomp3_mp3file_deinit(mp_obj_t self_in) {
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -109,16 +106,16 @@ STATIC void check_for_deinit(audiomp3_mp3file_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t audiomp3_mp3file_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -127,9 +124,8 @@ 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__);
-//| .. attribute:: file
-//|
-//| File to play back.
+//| file: Any = ...
+//| """File to play back."""
//|
STATIC mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) {
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -158,11 +154,10 @@ const mp_obj_property_t audiomp3_mp3file_file_obj = {
-//| .. attribute:: sample_rate
-//|
-//| 32 bit value that dictates how quickly samples are loaded into the DAC
+//| sample_rate: Any = ...
+//| """32 bit value that dictates how quickly samples are loaded into the DAC
//| in Hertz (cycles per second). When the sample is looped, this can change
-//| the pitch output without changing the underlying sample.
+//| the pitch output without changing the underlying sample."""
//|
STATIC mp_obj_t audiomp3_mp3file_obj_get_sample_rate(mp_obj_t self_in) {
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -186,9 +181,8 @@ const mp_obj_property_t audiomp3_mp3file_sample_rate_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: bits_per_sample
-//|
-//| Bits per sample. (read only)
+//| bits_per_sample: Any = ...
+//| """Bits per sample. (read only)"""
//|
STATIC mp_obj_t audiomp3_mp3file_obj_get_bits_per_sample(mp_obj_t self_in) {
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -204,9 +198,8 @@ const mp_obj_property_t audiomp3_mp3file_bits_per_sample_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: channel_count
-//|
-//| Number of audio channels. (read only)
+//| channel_count: Any = ...
+//| """Number of audio channels. (read only)"""
//|
STATIC mp_obj_t audiomp3_mp3file_obj_get_channel_count(mp_obj_t self_in) {
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -222,9 +215,8 @@ const mp_obj_property_t audiomp3_mp3file_channel_count_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: rms_level
-//|
-//| The RMS audio level of a recently played moment of audio. (read only)
+//| rms_level: Any = ...
+//| """The RMS audio level of a recently played moment of audio. (read only)"""
//|
STATIC mp_obj_t audiomp3_mp3file_obj_get_rms_level(mp_obj_t self_in) {
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audiomp3/__init__.c b/shared-bindings/audiomp3/__init__.c
index fb2187669..62e5f56cb 100644
--- a/shared-bindings/audiomp3/__init__.c
+++ b/shared-bindings/audiomp3/__init__.c
@@ -31,20 +31,7 @@
#include "shared-bindings/audiomp3/MP3Decoder.h"
-//| :mod:`audiomp3` --- Support for MP3-compressed audio files
-//| ==========================================================
-//|
-//| .. module:: audiomp3
-//| :synopsis: Support for mp3 files
-//|
-//| The `audiomp3` module contains an mp3 decoder
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| MP3Decoder
+//| """Support for MP3-compressed audio files"""
//|
STATIC const mp_rom_map_elem_t audiomp3_module_globals_table[] = {
diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c
index 60bf08500..812b7330d 100644
--- a/shared-bindings/audiopwmio/PWMAudioOut.c
+++ b/shared-bindings/audiopwmio/PWMAudioOut.c
@@ -36,66 +36,62 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audiopwmio
-//|
-//| :class:`PWMAudioOut` -- Output an analog audio signal
-//| ========================================================
-//|
-//| AudioOut can be used to output an analog audio signal on a given pin.
-//|
-//| .. class:: PWMAudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000)
-//|
-//| Create a PWMAudioOut object associated with the given pin(s). This allows you to
-//| play audio signals out on the given pin(s). In contrast to mod:`audioio`,
-//| the pin(s) specified are digital pins, and are driven with a device-dependent PWM
-//| signal.
-//|
-//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
-//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
-//| :param int quiescent_value: The output value when no signal is present. Samples should start
-//| and end with this value to prevent audible popping.
-//|
-//| Simple 8ksps 440 Hz sin wave::
-//|
-//| import audiocore
-//| import audiopwmio
-//| import board
-//| import array
-//| import time
-//| import math
-//|
-//| # Generate one period of sine wav.
-//| length = 8000 // 440
-//| sine_wave = array.array("H", [0] * length)
-//| for i in range(length):
-//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
-//|
-//| dac = audiopwmio.PWMAudioOut(board.SPEAKER)
-//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
-//| dac.play(sine_wave, loop=True)
-//| time.sleep(1)
-//| dac.stop()
-//|
-//| Playing a wave file from flash::
-//|
-//| import board
-//| import audiocore
-//| import audiopwmio
-//| import digitalio
-//|
-//| # Required for CircuitPlayground Express
-//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
-//| speaker_enable.switch_to_output(value=True)
-//|
-//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audiocore.WaveFile(data)
-//| a = audiopwmio.PWMAudioOut(board.SPEAKER)
-//|
-//| print("playing")
-//| a.play(wav)
-//| while a.playing:
-//| pass
-//| print("stopped")
+//| class PWMAudioOut:
+//| """Output an analog audio signal by varying the PWM duty cycle."""
+//|
+//| def __init__(self, left_channel: microcontroller.Pin, *, right_channel: microcontroller.Pin = None, quiescent_value: int = 0x8000):
+//| """Create a PWMAudioOut object associated with the given pin(s). This allows you to
+//| play audio signals out on the given pin(s). In contrast to mod:`audioio`,
+//| the pin(s) specified are digital pins, and are driven with a device-dependent PWM
+//| signal.
+//|
+//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
+//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
+//| :param int quiescent_value: The output value when no signal is present. Samples should start
+//| and end with this value to prevent audible popping.
+//|
+//| Simple 8ksps 440 Hz sin wave::
+//|
+//| import audiocore
+//| import audiopwmio
+//| import board
+//| import array
+//| import time
+//| import math
+//|
+//| # Generate one period of sine wav.
+//| length = 8000 // 440
+//| sine_wave = array.array("H", [0] * length)
+//| for i in range(length):
+//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
+//|
+//| dac = audiopwmio.PWMAudioOut(board.SPEAKER)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
+//| dac.play(sine_wave, loop=True)
+//| time.sleep(1)
+//| dac.stop()
+//|
+//| Playing a wave file from flash::
+//|
+//| import board
+//| import audiocore
+//| import audiopwmio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audiocore.WaveFile(data)
+//| a = audiopwmio.PWMAudioOut(board.SPEAKER)
+//|
+//| print("playing")
+//| a.play(wav)
+//| while a.playing:
+//| pass
+//| print("stopped")"""
+//| ...
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_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_left_channel, ARG_right_channel, ARG_quiescent_value };
@@ -107,16 +103,8 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_obj_t left_channel_obj = args[ARG_left_channel].u_obj;
- assert_pin(left_channel_obj, false);
- const mcu_pin_obj_t *left_channel_pin = MP_OBJ_TO_PTR(left_channel_obj);
-
- mp_obj_t right_channel_obj = args[ARG_right_channel].u_obj;
- const mcu_pin_obj_t *right_channel_pin = NULL;
- if (right_channel_obj != mp_const_none) {
- assert_pin(right_channel_obj, false);
- right_channel_pin = MP_OBJ_TO_PTR(right_channel_obj);
- }
+ const mcu_pin_obj_t *left_channel_pin = validate_obj_is_free_pin(args[ARG_left_channel].u_obj);
+ const mcu_pin_obj_t *right_channel_pin = validate_obj_is_free_pin_or_none(args[ARG_right_channel].u_obj);
// create AudioOut object from the given pin
audiopwmio_pwmaudioout_obj_t *self = m_new_obj(audiopwmio_pwmaudioout_obj_t);
@@ -126,9 +114,9 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the PWMAudioOut and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the PWMAudioOut and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_deinit(mp_obj_t self_in) {
audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -142,17 +130,16 @@ STATIC void check_for_deinit(audiopwmio_pwmaudioout_obj_t *self) {
raise_deinited_error();
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
-//|
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
STATIC mp_obj_t audiopwmio_pwmaudioout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
common_hal_audiopwmio_pwmaudioout_deinit(args[0]);
@@ -161,16 +148,16 @@ 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__);
-//| .. method:: play(sample, *, loop=False)
+//| def play(self, sample: Any, *, loop: Any = False) -> Any:
+//| """Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
//|
-//| 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`, or `audiomixer.Mixer`.
-//|
-//| 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
-//| DAC that ignores the lowest 6 bits when playing 16 bit samples.
+//| 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
+//| DAC that ignores the lowest 6 bits when playing 16 bit samples."""
+//| ...
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sample, ARG_loop };
@@ -190,9 +177,9 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_obj_play(size_t n_args, const mp_obj_t *p
}
MP_DEFINE_CONST_FUN_OBJ_KW(audiopwmio_pwmaudioout_play_obj, 1, audiopwmio_pwmaudioout_obj_play);
-//| .. method:: stop()
-//|
-//| Stops playback and resets to the start of the sample.
+//| def stop(self, ) -> Any:
+//| """Stops playback and resets to the start of the sample."""
+//| ...
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_obj_stop(mp_obj_t self_in) {
audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -202,9 +189,8 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_obj_stop(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_stop_obj, audiopwmio_pwmaudioout_obj_stop);
-//| .. attribute:: playing
-//|
-//| True when an audio sample is being output even if `paused`. (read-only)
+//| playing: Any = ...
+//| """True when an audio sample is being output even if `paused`. (read-only)"""
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_playing(mp_obj_t self_in) {
audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -220,9 +206,9 @@ const mp_obj_property_t audiopwmio_pwmaudioout_playing_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: pause()
-//|
-//| Stops playback temporarily while remembering the position. Use `resume` to resume playback.
+//| def pause(self, ) -> Any:
+//| """Stops playback temporarily while remembering the position. Use `resume` to resume playback."""
+//| ...
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_obj_pause(mp_obj_t self_in) {
audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -236,9 +222,9 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_obj_pause(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_pause_obj, audiopwmio_pwmaudioout_obj_pause);
-//| .. method:: resume()
-//|
-//| Resumes sample playback after :py:func:`pause`.
+//| def resume(self, ) -> Any:
+//| """Resumes sample playback after :py:func:`pause`."""
+//| ...
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_obj_resume(mp_obj_t self_in) {
audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -252,9 +238,8 @@ STATIC mp_obj_t audiopwmio_pwmaudioout_obj_resume(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_resume_obj, audiopwmio_pwmaudioout_obj_resume);
-//| .. attribute:: paused
-//|
-//| True when playback is paused. (read-only)
+//| paused: Any = ...
+//| """True when playback is paused. (read-only)"""
//|
STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_paused(mp_obj_t self_in) {
audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/audiopwmio/__init__.c b/shared-bindings/audiopwmio/__init__.c
index 8a2b202b3..5caea1420 100644
--- a/shared-bindings/audiopwmio/__init__.c
+++ b/shared-bindings/audiopwmio/__init__.c
@@ -33,29 +33,17 @@
#include "shared-bindings/audiopwmio/__init__.h"
#include "shared-bindings/audiopwmio/PWMAudioOut.h"
-//| :mod:`audiopwmio` --- Support for audio input and output
-//| ========================================================
-//|
-//| .. module:: audiopwmio
-//| :synopsis: Support for audio output via digital PWM
-//| :platform: NRF52
+//| """Audio output via digital PWM
//|
//| The `audiopwmio` module contains classes to provide access to audio IO.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| PWMAudioOut
-//|
//| 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.
//|
//| Since CircuitPython 5, `Mixer`, `RawSample` and `WaveFile` are moved
-//| to :mod:`audiocore`.
+//| to :mod:`audiocore`."""
//|
STATIC const mp_rom_map_elem_t audiopwmio_module_globals_table[] = {
diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c
index 01a128393..43fe11e62 100644
--- a/shared-bindings/bitbangio/I2C.c
+++ b/shared-bindings/bitbangio/I2C.c
@@ -37,21 +37,27 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: bitbangio
+//| class I2C:
+//| """Two wire serial protocol"""
//|
-//| :class:`I2C` --- Two wire serial protocol
-//| ------------------------------------------
+//| def __init__(self, scl: microcontroller.Pin, sda: microcontroller.Pin, *, frequency: int = 400000, timeout: int):
+//| """I2C is a two-wire protocol for communicating between devices. At the
+//| physical level it consists of 2 wires: SCL and SDA, the clock and data
+//| lines respectively.
//|
-//| .. class:: I2C(scl, sda, *, frequency=400000, timeout)
+//| .. seealso:: Using this class directly requires careful lock management.
+//| Instead, use :class:`~adafruit_bus_device.i2c_device.I2CDevice` to
+//| manage locks.
//|
-//| I2C is a two-wire protocol for communicating between devices. At the
-//| physical level it consists of 2 wires: SCL and SDA, the clock and data
-//| lines respectively.
+//| .. seealso:: Using this class to directly read registers requires manual
+//| bit unpacking. Instead, use an existing driver or make one with
+//| :ref:`Register <register-module-reference>` data descriptors.
//|
-//| :param ~microcontroller.Pin scl: The clock pin
-//| :param ~microcontroller.Pin sda: The data pin
-//| :param int frequency: The clock frequency of the bus
-//| :param int timeout: The maximum clock stretching timeout in microseconds
+//| :param ~microcontroller.Pin scl: The clock pin
+//| :param ~microcontroller.Pin sda: The data pin
+//| :param int frequency: The clock frequency of the bus
+//| :param int timeout: The maximum clock stretching timeout in microseconds"""
+//| ...
//|
STATIC mp_obj_t bitbangio_i2c_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_scl, ARG_sda, ARG_frequency, ARG_timeout };
@@ -63,10 +69,9 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args,
};
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);
- assert_pin(args[ARG_scl].u_obj, false);
- assert_pin(args[ARG_sda].u_obj, false);
- const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj);
- const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
+
+ const mcu_pin_obj_t* scl = validate_obj_is_free_pin(args[ARG_scl].u_obj);
+ const mcu_pin_obj_t* sda = validate_obj_is_free_pin(args[ARG_sda].u_obj);
bitbangio_i2c_obj_t *self = m_new_obj(bitbangio_i2c_obj_t);
self->base.type = &bitbangio_i2c_type;
@@ -74,9 +79,9 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args,
return (mp_obj_t)self;
}
-//| .. method:: deinit()
-//|
-//| Releases control of the underlying hardware so other classes can use it.
+//| def deinit(self, ) -> Any:
+//| """Releases control of the underlying hardware so other classes can use it."""
+//| ...
//|
STATIC mp_obj_t bitbangio_i2c_obj_deinit(mp_obj_t self_in) {
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -91,16 +96,16 @@ STATIC void check_for_deinit(bitbangio_i2c_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used in Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used in Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware on context exit. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware on context exit. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t bitbangio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -115,11 +120,11 @@ static void check_lock(bitbangio_i2c_obj_t *self) {
}
}
-//| .. method:: scan()
-//|
-//| 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.
+//| def scan(self, ) -> Any:
+//| """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."""
+//| ...
//|
STATIC mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) {
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -137,9 +142,9 @@ STATIC mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_scan_obj, bitbangio_i2c_scan);
-//| .. method:: try_lock()
-//|
-//| Attempts to grab the I2C lock. Returns True on success.
+//| def try_lock(self, ) -> Any:
+//| """Attempts to grab the I2C lock. Returns True on success."""
+//| ...
//|
STATIC mp_obj_t bitbangio_i2c_obj_try_lock(mp_obj_t self_in) {
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -148,9 +153,9 @@ STATIC mp_obj_t bitbangio_i2c_obj_try_lock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_try_lock_obj, bitbangio_i2c_obj_try_lock);
-//| .. method:: unlock()
-//|
-//| Releases the I2C lock.
+//| def unlock(self, ) -> Any:
+//| """Releases the I2C lock."""
+//| ...
//|
STATIC mp_obj_t bitbangio_i2c_obj_unlock(mp_obj_t self_in) {
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -160,20 +165,20 @@ STATIC mp_obj_t bitbangio_i2c_obj_unlock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
-//| .. method:: readfrom_into(address, buffer, *, start=0, end=None)
-//|
-//| Read into ``buffer`` from the slave specified by ``address``.
-//| The number of bytes read will be the length of ``buffer``.
-//| At least one byte must be read.
+//| def readfrom_into(self, address: int, buffer: bytearray, *, start: int = 0, end: int = None) -> Any:
+//| """Read into ``buffer`` from the device selected by ``address``.
+//| The number of bytes read will be the length of ``buffer``.
+//| At least one byte must be read.
//|
-//| If ``start`` or ``end`` is provided, then the buffer will be sliced
-//| as if ``buffer[start:end]``. This will not cause an allocation like
-//| ``buf[start:end]`` will so it saves memory.
+//| If ``start`` or ``end`` is provided, then the buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like
+//| ``buf[start:end]`` will so it saves memory.
//|
-//| :param int address: 7-bit device address
-//| :param bytearray buffer: buffer to write into
-//| :param int start: Index to start writing at
-//| :param int end: Index to write up to but not include
+//| :param int address: 7-bit device address
+//| :param bytearray buffer: buffer to write into
+//| :param int start: Index to start writing at
+//| :param int end: Index to write up to but not include"""
+//| ...
//|
// Shared arg parsing for readfrom_into and writeto_then_readfrom.
STATIC void readfrom(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
@@ -212,25 +217,25 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_readfrom_into);
-//| .. method:: writeto(address, buffer, *, start=0, end=None, stop=True)
+//| def writeto(self, address: int, buffer: bytearray, *, start: int = 0, end: int = None, stop: bool = True) -> Any:
+//| """Write the bytes from ``buffer`` to the device selected by ``address`` and then transmits a
+//| stop bit. Use `writeto_then_readfrom` when needing a write, no stop and repeated start
+//| before a read.
//|
-//| Write the bytes from ``buffer`` to the slave specified by ``address`` and then transmits a
-//| stop bit. Use `writeto_then_readfrom` when needing a write, no stop and repeated start
-//| before a read.
+//| If ``start`` or ``end`` is provided, then the buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like
+//| ``buffer[start:end]`` will so it saves memory.
//|
-//| If ``start`` or ``end`` is provided, then the buffer will be sliced
-//| as if ``buffer[start:end]``. This will not cause an allocation like
-//| ``buffer[start:end]`` will so it saves memory.
+//| Writing a buffer or slice of length zero is permitted, as it can be used
+//| to poll for the existence of a device.
//|
-//| Writing a buffer or slice of length zero is permitted, as it can be used
-//| 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 int start: Index to start writing from
-//| :param int end: Index to read up to but not include
-//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
-//| Deprecated. Will be removed in 6.x and act as stop=True.
+//| :param int address: 7-bit device address
+//| :param bytearray 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
+//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
+//| Deprecated. Will be removed in 6.x and act as stop=True."""
+//| ...
//|
// Shared arg parsing for writeto and writeto_then_readfrom.
STATIC void writeto(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) {
@@ -272,23 +277,22 @@ 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);
-//| .. method:: writeto_then_readfrom(address, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None)
-//|
-//| Write the bytes from ``out_buffer`` to the slave specified 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.
+//| def writeto_then_readfrom(self, address: int, out_buffer: bytearray, in_buffer: bytearray, *, out_start: int = 0, out_end: int = None, in_start: int = 0, in_end: int = None) -> Any:
+//| """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.
//|
-//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
-//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
-//| will so it saves memory.
+//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
+//| 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 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
-//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``
+//| :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 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
+//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``"""
//|
STATIC mp_obj_t bitbangio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
diff --git a/shared-bindings/bitbangio/OneWire.c b/shared-bindings/bitbangio/OneWire.c
index 73bedcd8d..a236f4c2a 100644
--- a/shared-bindings/bitbangio/OneWire.c
+++ b/shared-bindings/bitbangio/OneWire.c
@@ -34,33 +34,32 @@
#include "shared-bindings/bitbangio/OneWire.h"
#include "shared-bindings/util.h"
-//| .. currentmodule:: bitbangio
+//| class OneWire:
+//| """Lowest-level of the Maxim OneWire protocol
//|
-//| :class:`OneWire` -- Lowest-level of the Maxim OneWire protocol
-//| ===============================================================
+//| :class:`~bitbangio.OneWire` implements the timing-sensitive foundation of
+//| the Maxim (formerly Dallas Semi) OneWire protocol.
//|
-//| :class:`~bitbangio.OneWire` implements the timing-sensitive foundation of
-//| the Maxim (formerly Dallas Semi) OneWire protocol.
+//| Protocol definition is here: https://www.maximintegrated.com/en/app-notes/index.mvp/id/126"""
//|
-//| Protocol definition is here: https://www.maximintegrated.com/en/app-notes/index.mvp/id/126
+//| def __init__(self, pin: microcontroller.Pin):
//|
-//| .. class:: OneWire(pin)
+//| """Create a OneWire object associated with the given pin. The object
+//| implements the lowest level timing-sensitive bits of the protocol.
//|
-//| Create a OneWire object associated with the given pin. The object
-//| implements the lowest level timing-sensitive bits of the protocol.
+//| :param ~microcontroller.Pin pin: Pin to read pulses from.
//|
-//| :param ~microcontroller.Pin pin: Pin to read pulses from.
+//| Read a short series of pulses::
//|
-//| Read a short series of pulses::
+//| import bitbangio
+//| import board
//|
-//| import bitbangio
-//| import board
-//|
-//| onewire = bitbangio.OneWire(board.D7)
-//| onewire.reset()
-//| onewire.write_bit(True)
-//| onewire.write_bit(False)
-//| print(onewire.read_bit())
+//| onewire = bitbangio.OneWire(board.D7)
+//| onewire.reset()
+//| onewire.write_bit(True)
+//| onewire.write_bit(False)
+//| print(onewire.read_bit())"""
+//| ...
//|
STATIC mp_obj_t bitbangio_onewire_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_pin };
@@ -69,9 +68,8 @@ STATIC mp_obj_t bitbangio_onewire_make_new(const mp_obj_type_t *type, size_t n_a
};
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);
- assert_pin(args[ARG_pin].u_obj, false);
- const mcu_pin_obj_t* pin = MP_OBJ_TO_PTR(args[ARG_pin].u_obj);
- assert_pin_free(pin);
+
+ const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
bitbangio_onewire_obj_t *self = m_new_obj(bitbangio_onewire_obj_t);
self->base.type = &bitbangio_onewire_type;
@@ -80,9 +78,9 @@ STATIC mp_obj_t bitbangio_onewire_make_new(const mp_obj_type_t *type, size_t n_a
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialize the OneWire bus and release any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialize the OneWire bus and release any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t bitbangio_onewire_deinit(mp_obj_t self_in) {
bitbangio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -97,16 +95,16 @@ STATIC void check_for_deinit(bitbangio_onewire_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t bitbangio_onewire_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -115,9 +113,9 @@ STATIC mp_obj_t bitbangio_onewire_obj___exit__(size_t n_args, const mp_obj_t *ar
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_onewire___exit___obj, 4, 4, bitbangio_onewire_obj___exit__);
-//| .. method:: reset()
-//|
-//| Reset the OneWire bus
+//| def reset(self, ) -> Any:
+//| """Reset the OneWire bus"""
+//| ...
//|
STATIC mp_obj_t bitbangio_onewire_obj_reset(mp_obj_t self_in) {
bitbangio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -127,12 +125,12 @@ STATIC mp_obj_t bitbangio_onewire_obj_reset(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_onewire_reset_obj, bitbangio_onewire_obj_reset);
-//| .. method:: read_bit()
+//| def read_bit(self, ) -> Any:
+//| """Read in a bit
//|
-//| Read in a bit
-//|
-//| :returns: bit state read
-//| :rtype: bool
+//| :returns: bit state read
+//| :rtype: bool"""
+//| ...
//|
STATIC mp_obj_t bitbangio_onewire_obj_read_bit(mp_obj_t self_in) {
bitbangio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -142,9 +140,9 @@ STATIC mp_obj_t bitbangio_onewire_obj_read_bit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_onewire_read_bit_obj, bitbangio_onewire_obj_read_bit);
-//| .. method:: write_bit(value)
-//|
-//| Write out a bit based on value.
+//| def write_bit(self, value: Any) -> Any:
+//| """Write out a bit based on value."""
+//| ...
//|
STATIC mp_obj_t bitbangio_onewire_obj_write_bit(mp_obj_t self_in, mp_obj_t bool_obj) {
bitbangio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c
index 9a51bde66..6d31037c7 100644
--- a/shared-bindings/bitbangio/SPI.c
+++ b/shared-bindings/bitbangio/SPI.c
@@ -39,26 +39,34 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: bitbangio
+//| class SPI:
+//| """A 3-4 wire serial protocol
//|
-//| :class:`SPI` -- a 3-4 wire serial protocol
-//| -----------------------------------------------
+//| SPI is a serial protocol that has exclusive pins for data in and out of the
+//| main device. It is typically faster than :py:class:`~bitbangio.I2C` because a
+//| separate pin is used to select a device rather than a transmitted
+//| address. This class only manages three of the four SPI lines: `!clock`,
+//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate
+//| select line, often abbreviated `!CS` or `!SS`. (This is common because
+//| multiple secondaries can share the `!clock`, `!MOSI` and `!MISO` lines
+//| and therefore the hardware.)"""
//|
-//| SPI is a serial protocol that has exclusive pins for data in and out of the
-//| master. It is typically faster than :py:class:`~bitbangio.I2C` because a
-//| separate pin is used to control the active slave rather than a transmitted
-//| address. This class only manages three of the four SPI lines: `!clock`,
-//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate slave
-//| select line. (This is common because multiple slaves can share the `!clock`,
-//| `!MOSI` and `!MISO` lines and therefore the hardware.)
+//| def __init__(self, clock: microcontroller.Pin, MOSI: microcontroller.Pin = None, MISO: microcontroller.Pin = None):
+//| """Construct an SPI object on the given pins.
//|
-//| .. class:: SPI(clock, MOSI=None, MISO=None)
+//| .. seealso:: Using this class directly requires careful lock management.
+//| Instead, use :class:`~adafruit_bus_device.spi_device.SPIDevice` to
+//| manage locks.
//|
-//| Construct an SPI object on the given pins.
+//| .. seealso:: Using this class to directly read registers requires manual
+//| bit unpacking. Instead, use an existing driver or make one with
+//| :ref:`Register <register-module-reference>` data descriptors.
//|
-//| :param ~microcontroller.Pin clock: the pin to use for the clock.
-//| :param ~microcontroller.Pin MOSI: the Master Out Slave In pin.
-//| :param ~microcontroller.Pin MISO: the Master In Slave Out pin.
+//|
+//| :param ~microcontroller.Pin clock: the pin to use for the clock.
+//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin.
+//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin."""
+//| ...
//|
// TODO(tannewt): Support LSB SPI.
@@ -71,12 +79,10 @@ STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args,
};
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);
- assert_pin(args[ARG_clock].u_obj, false);
- assert_pin(args[ARG_MOSI].u_obj, true);
- assert_pin(args[ARG_MISO].u_obj, true);
- const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj);
- const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj);
- const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj);
+
+ const mcu_pin_obj_t* clock = validate_obj_is_free_pin(args[ARG_clock].u_obj);
+ const mcu_pin_obj_t* mosi = validate_obj_is_free_pin_or_none(args[ARG_MOSI].u_obj);
+ const mcu_pin_obj_t* miso = validate_obj_is_free_pin_or_none(args[ARG_MISO].u_obj);
bitbangio_spi_obj_t *self = m_new_obj(bitbangio_spi_obj_t);
self->base.type = &bitbangio_spi_type;
@@ -84,9 +90,9 @@ STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args,
return (mp_obj_t)self;
}
-//| .. method:: deinit()
-//|
-//| Turn off the SPI bus.
+//| def deinit(self, ) -> Any:
+//| """Turn off the SPI bus."""
+//| ...
//|
STATIC mp_obj_t bitbangio_spi_obj_deinit(mp_obj_t self_in) {
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -101,16 +107,16 @@ STATIC void check_for_deinit(bitbangio_spi_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t bitbangio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -126,15 +132,15 @@ static void check_lock(bitbangio_spi_obj_t *self) {
}
}
-//| .. method:: configure(*, baudrate=100000, polarity=0, phase=0, bits=8)
-//|
-//| Configures the SPI bus. Only valid when locked.
+//| def configure(self, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, bits: int = 8) -> Any:
+//| """Configures the SPI bus. Only valid when locked.
//|
-//| :param int baudrate: the clock rate in Hertz
-//| :param int polarity: the base state of the clock line (0 or 1)
-//| :param int phase: the edge of the clock that data is captured. First (0)
-//| or second (1). Rising or falling depends on clock polarity.
-//| :param int bits: the number of bits per word
+//| :param int baudrate: the clock rate in Hertz
+//| :param int polarity: the base state of the clock line (0 or 1)
+//| :param int phase: the edge of the clock that data is captured. First (0)
+//| or second (1). Rising or falling depends on clock polarity.
+//| :param int bits: the number of bits per word"""
+//| ...
//|
STATIC mp_obj_t bitbangio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits };
@@ -168,12 +174,12 @@ STATIC mp_obj_t bitbangio_spi_configure(size_t n_args, const mp_obj_t *pos_args,
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_configure_obj, 1, bitbangio_spi_configure);
-//| .. method:: try_lock()
+//| def try_lock(self, ) -> Any:
+//| """Attempts to grab the SPI lock. Returns True on success.
//|
-//| Attempts to grab the SPI lock. Returns True on success.
-//|
-//| :return: True when lock has been grabbed
-//| :rtype: bool
+//| :return: True when lock has been grabbed
+//| :rtype: bool"""
+//| ...
//|
STATIC mp_obj_t bitbangio_spi_obj_try_lock(mp_obj_t self_in) {
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -182,9 +188,9 @@ STATIC mp_obj_t bitbangio_spi_obj_try_lock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_try_lock_obj, bitbangio_spi_obj_try_lock);
-//| .. method:: unlock()
-//|
-//| Releases the SPI lock.
+//| def unlock(self, ) -> Any:
+//| """Releases the SPI lock."""
+//| ...
//|
STATIC mp_obj_t bitbangio_spi_obj_unlock(mp_obj_t self_in) {
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -194,10 +200,10 @@ STATIC mp_obj_t bitbangio_spi_obj_unlock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock);
-//| .. method:: write(buf)
-//|
-//| Write the data contained in ``buf``. Requires the SPI being locked.
-//| If the buffer is empty, nothing happens.
+//| def write(self, buf: Any) -> Any:
+//| """Write the data contained in ``buf``. Requires the SPI being locked.
+//| If the buffer is empty, nothing happens."""
+//| ...
//|
// TODO(tannewt): Add support for start and end kwargs.
STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
@@ -218,11 +224,11 @@ STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_spi_write_obj, bitbangio_spi_write);
-//| .. method:: readinto(buf)
-//|
-//| Read into the buffer specified by ``buf`` while writing zeroes.
-//| Requires the SPI being locked.
-//| If the number of bytes to read is 0, nothing happens.
+//| def readinto(self, buf: Any) -> Any:
+//| """Read into the buffer specified by ``buf`` while writing zeroes.
+//| Requires the SPI being locked.
+//| If the number of bytes to read is 0, nothing happens."""
+//| ...
//|
// TODO(tannewt): Add support for start and end kwargs.
STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) {
@@ -242,19 +248,19 @@ STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_spi_readinto_obj, 2, 2, bitbangio_spi_readinto);
-//| .. method:: write_readinto(buffer_out, buffer_in, *, out_start=0, out_end=None, in_start=0, in_end=None)
-//|
-//| Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
-//| 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.
+//| def write_readinto(self, buffer_out: bytearray, buffer_in: bytearray, *, out_start: Any = 0, out_end: int = None, in_start: Any = 0, in_end: int = None) -> Any:
+//| """Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
+//| 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 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]``
-//| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``
+//| :param bytearray buffer_out: Write out the data in this buffer
+//| :param bytearray 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]``
+//| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``"""
+//| ...
//|
STATIC mp_obj_t bitbangio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
diff --git a/shared-bindings/bitbangio/__init__.c b/shared-bindings/bitbangio/__init__.c
index 3123fb199..e04bdf701 100644
--- a/shared-bindings/bitbangio/__init__.c
+++ b/shared-bindings/bitbangio/__init__.c
@@ -40,12 +40,7 @@
#include "py/runtime.h"
-//| :mod:`bitbangio` --- Digital protocols implemented by the CPU
-//| =============================================================
-//|
-//| .. module:: bitbangio
-//| :synopsis: Digital protocols implemented by the CPU
-//| :platform: SAMD21, ESP8266
+//| """Digital protocols implemented by the CPU
//|
//| The `bitbangio` module contains classes to provide digital bus protocol
//| support regardless of whether the underlying hardware exists to use the
@@ -55,15 +50,6 @@
//| hardware to implement the protocols. Native implementations will be faster
//| than bitbanged versions and have more capabilities.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| I2C
-//| OneWire
-//| SPI
-//|
//| 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
@@ -81,7 +67,7 @@
//| This example will initialize the the device, run
//| :py:meth:`~bitbangio.I2C.scan` and then :py:meth:`~bitbangio.I2C.deinit` the
//| hardware. The last step is optional because CircuitPython automatically
-//| resets hardware after a program finishes.
+//| resets hardware after a program finishes."""
//|
STATIC const mp_rom_map_elem_t bitbangio_module_globals_table[] = {
diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c
index 3dda59fb8..010a9fb92 100644
--- a/shared-bindings/board/__init__.c
+++ b/shared-bindings/board/__init__.c
@@ -29,21 +29,17 @@
#include "shared-bindings/board/__init__.h"
-//| :mod:`board` --- Board specific pin names
-//| ========================================================
-//|
-//| .. module:: board
-//| :synopsis: Board specific pin names
+//| """Board specific pin names
//|
//| Common container for board base pin names. These will vary from board to
//| board so don't expect portability when using this module.
//|
//| .. warning:: The board module varies by board. The APIs documented here may or may not be
-//| available on a specific board.
+//| available on a specific board."""
-//| .. function:: I2C()
-//|
-//| Returns the `busio.I2C` object for the board designated SDA and SCL pins. It is a singleton.
+//| def I2C() -> Any:
+//| """Returns the `busio.I2C` object for the board designated SDA and SCL pins. It is a singleton."""
+//| ...
//|
#if BOARD_I2C
@@ -65,10 +61,10 @@ mp_obj_t board_i2c(void) {
MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c);
-//| .. function:: SPI()
-//|
-//| Returns the `busio.SPI` object for the board designated SCK, MOSI and MISO pins. It is a
-//| singleton.
+//| def SPI() -> Any:
+//| """Returns the `busio.SPI` object for the board designated SCK, MOSI and MISO pins. It is a
+//| singleton."""
+//| ...
//|
#if BOARD_SPI
mp_obj_t board_spi(void) {
@@ -89,15 +85,14 @@ mp_obj_t board_spi(void) {
#endif
MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi);
-//| .. function:: UART()
-//|
-//| Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton.
-//|
-//| The object created uses the default parameter values for `busio.UART`. If you need to set
-//| parameters that are not changeable after creation, such as ``receiver_buffer_size``,
-//| do not use `board.UART()`; instead create a `busio.UART` object explicitly with the
-//| desired parameters.
+//| def UART() -> Any:
+//| """Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton.
//|
+//| The object created uses the default parameter values for `busio.UART`. If you need to set
+//| parameters that are not changeable after creation, such as ``receiver_buffer_size``,
+//| do not use `board.UART()`; instead create a `busio.UART` object explicitly with the
+//| desired parameters."""
+//| ...
//|
#if BOARD_UART
mp_obj_t board_uart(void) {
@@ -113,7 +108,7 @@ mp_obj_t board_uart(void) {
}
#else
mp_obj_t board_uart(void) {
- mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_SPI);
+ mp_raise_NotImplementedError_varg(translate("No default %q bus"), MP_QSTR_UART);
return NULL;
}
#endif
diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c
index 50a95beb2..b61dd93f3 100644
--- a/shared-bindings/busio/I2C.c
+++ b/shared-bindings/busio/I2C.c
@@ -36,33 +36,32 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: busio
+//| class I2C:
+//| """Two wire serial protocol"""
//|
-//| :class:`I2C` --- Two wire serial protocol
-//| ------------------------------------------
+//| def __init__(self, scl: microcontroller.Pin, sda: microcontroller.Pin, *, frequency: int = 400000, timeout: int = 255):
//|
-//| .. class:: I2C(scl, sda, *, frequency=400000, timeout=255)
+//| """I2C is a two-wire protocol for communicating between devices. At the
+//| physical level it consists of 2 wires: SCL and SDA, the clock and data
+//| lines respectively.
//|
-//| I2C is a two-wire protocol for communicating between devices. At the
-//| physical level it consists of 2 wires: SCL and SDA, the clock and data
-//| lines respectively.
+//| .. seealso:: Using this class directly requires careful lock management.
+//| Instead, use :class:`~adafruit_bus_device.i2c_device.I2CDevice` to
+//| manage locks.
//|
-//| .. seealso:: Using this class directly requires careful lock management.
-//| Instead, use :class:`~adafruit_bus_device.i2c_device.I2CDevice` to
-//| manage locks.
+//| .. seealso:: Using this class to directly read registers requires manual
+//| bit unpacking. Instead, use an existing driver or make one with
+//| :ref:`Register <register-module-reference>` data descriptors.
//|
-//| .. seealso:: Using this class to directly read registers requires manual
-//| bit unpacking. Instead, use an existing driver or make one with
-//| :ref:`Register <register-module-reference>` data descriptors.
+//| :param ~microcontroller.Pin scl: The clock pin
+//| :param ~microcontroller.Pin sda: The data pin
+//| :param int frequency: The clock frequency in Hertz
+//| :param int timeout: The maximum clock stretching timeut - (used only for bitbangio.I2C; ignored for busio.I2C)
//|
-//| :param ~microcontroller.Pin scl: The clock pin
-//| :param ~microcontroller.Pin sda: The data pin
-//| :param int frequency: The clock frequency in Hertz
-//| :param int timeout: The maximum clock stretching timeut - (used only for bitbangio.I2C; ignored for busio.I2C)
-//|
-//| .. note:: On the nRF52840, only one I2C object may be created,
-//| except on the Circuit Playground Bluefruit, which allows two,
-//| one for the onboard accelerometer, and one for offboard use.
+//| .. note:: On the nRF52840, only one I2C object may be created,
+//| except on the Circuit Playground Bluefruit, which allows two,
+//| one for the onboard accelerometer, and one for offboard use."""
+//| ...
//|
STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t);
@@ -76,19 +75,17 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, con
};
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);
- assert_pin(args[ARG_scl].u_obj, false);
- assert_pin(args[ARG_sda].u_obj, false);
- const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj);
- assert_pin_free(scl);
- const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
- assert_pin_free(sda);
+
+ const mcu_pin_obj_t* scl = validate_obj_is_free_pin(args[ARG_scl].u_obj);
+ const mcu_pin_obj_t* sda = validate_obj_is_free_pin(args[ARG_sda].u_obj);
+
common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int);
return (mp_obj_t)self;
}
-//| .. method:: deinit()
-//|
-//| Releases control of the underlying hardware so other classes can use it.
+//| def deinit(self, ) -> Any:
+//| """Releases control of the underlying hardware so other classes can use it."""
+//| ...
//|
STATIC mp_obj_t busio_i2c_obj_deinit(mp_obj_t self_in) {
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -103,16 +100,16 @@ STATIC void check_for_deinit(busio_i2c_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used in Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used in Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware on context exit. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware on context exit. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t busio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -128,13 +125,14 @@ static void check_lock(busio_i2c_obj_t *self) {
}
}
-//| .. method:: scan()
+//| def scan(self, ) -> Any:
//|
-//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a
-//| list of those that respond.
+//| """Scan all I2C addresses between 0x08 and 0x77 inclusive and return a
+//| list of those that respond.
//|
-//| :return: List of device ids on the I2C bus
-//| :rtype: list
+//| :return: List of device ids on the I2C bus
+//| :rtype: list"""
+//| ...
//|
STATIC mp_obj_t busio_i2c_scan(mp_obj_t self_in) {
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -152,12 +150,12 @@ STATIC mp_obj_t busio_i2c_scan(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_scan_obj, busio_i2c_scan);
-//| .. method:: try_lock()
+//| def try_lock(self, ) -> Any:
+//| """Attempts to grab the I2C lock. Returns True on success.
//|
-//| Attempts to grab the I2C lock. Returns True on success.
-//|
-//| :return: True when lock has been grabbed
-//| :rtype: bool
+//| :return: True when lock has been grabbed
+//| :rtype: bool"""
+//| ...
//|
STATIC mp_obj_t busio_i2c_obj_try_lock(mp_obj_t self_in) {
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -166,9 +164,9 @@ STATIC mp_obj_t busio_i2c_obj_try_lock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_try_lock_obj, busio_i2c_obj_try_lock);
-//| .. method:: unlock()
-//|
-//| Releases the I2C lock.
+//| def unlock(self, ) -> Any:
+//| """Releases the I2C lock."""
+//| ...
//|
STATIC mp_obj_t busio_i2c_obj_unlock(mp_obj_t self_in) {
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -178,20 +176,20 @@ STATIC mp_obj_t busio_i2c_obj_unlock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
-//| .. method:: readfrom_into(address, buffer, *, start=0, end=None)
+//| def readfrom_into(self, address: int, buffer: bytearray, *, start: int = 0, end: int = None) -> Any:
+//| """Read into ``buffer`` from the device selected by ``address``.
+//| The number of bytes read will be the length of ``buffer``.
+//| At least one byte must be read.
//|
-//| Read into ``buffer`` from the slave specified by ``address``.
-//| The number of bytes read will be the length of ``buffer``.
-//| At least one byte must be read.
+//| If ``start`` or ``end`` is provided, then the buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like
+//| ``buf[start:end]`` will so it saves memory.
//|
-//| If ``start`` or ``end`` is provided, then the buffer will be sliced
-//| as if ``buffer[start:end]``. This will not cause an allocation like
-//| ``buf[start:end]`` will so it saves memory.
-//|
-//| :param int address: 7-bit device address
-//| :param bytearray 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)``
+//| :param int address: 7-bit device address
+//| :param bytearray 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)``"""
+//| ...
//|
// Shared arg parsing for readfrom_into and writeto_then_readfrom.
STATIC void readfrom(busio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
@@ -230,26 +228,26 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args,
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_into);
-//| .. method:: writeto(address, buffer, *, start=0, end=None, stop=True)
-//|
-//| Write the bytes from ``buffer`` to the slave specified by ``address``.
-//| Transmits a stop bit when stop is True. Setting stop=False is deprecated and stop will be
-//| removed in CircuitPython 6.x. Use `writeto_then_readfrom` when needing a write, no stop and
-//| repeated start before a read.
-//|
-//| If ``start`` or ``end`` is provided, then the buffer will be sliced
-//| as if ``buffer[start:end]``. This will not cause an allocation like
-//| ``buffer[start:end]`` will so it saves memory.
-//|
-//| Writing a buffer or slice of length zero is permitted, as it can be used
-//| 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 int start: Index to start writing from
-//| :param int end: Index to read up to but not include. Defaults to ``len(buffer)``
-//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
-//| Deprecated. Will be removed in 6.x and act as stop=True.
+//| def writeto(self, address: int, buffer: bytearray, *, start: int = 0, end: int = None, stop: bool = True) -> Any:
+//| """Write the bytes from ``buffer`` to the device selected by ``address``.
+//| Transmits a stop bit when stop is True. Setting stop=False is deprecated and stop will be
+//| removed in CircuitPython 6.x. Use `writeto_then_readfrom` when needing a write, no stop and
+//| repeated start before a read.
+//|
+//| If ``start`` or ``end`` is provided, then the buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like
+//| ``buffer[start:end]`` will so it saves memory.
+//|
+//| Writing a buffer or slice of length zero is permitted, as it can be used
+//| 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 int start: Index to start writing from
+//| :param int end: Index to read up to but not include. Defaults to ``len(buffer)``
+//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
+//| Deprecated. Will be removed in 6.x and act as stop=True."""
+//| ...
//|
// Shared arg parsing for writeto and writeto_then_readfrom.
STATIC void writeto(busio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) {
@@ -289,23 +287,23 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto);
-//| .. method:: writeto_then_readfrom(address, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None)
-//|
-//| Write the bytes from ``out_buffer`` to the slave specified 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.
-//|
-//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
-//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
-//| 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 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
-//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``
+//| def writeto_then_readfrom(self, address: int, out_buffer: bytearray, in_buffer: bytearray, *, out_start: int = 0, out_end: int = None, in_start: int = 0, in_end: int = None) -> Any:
+//| """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.
+//|
+//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
+//| 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 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
+//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``"""
+//| ...
//|
STATIC mp_obj_t busio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
diff --git a/shared-bindings/busio/OneWire.c b/shared-bindings/busio/OneWire.c
index aca2a3ef2..723cc031a 100644
--- a/shared-bindings/busio/OneWire.c
+++ b/shared-bindings/busio/OneWire.c
@@ -34,33 +34,32 @@
#include "shared-bindings/busio/OneWire.h"
#include "shared-bindings/util.h"
-//| .. currentmodule:: busio
+//| class OneWire:
+//| """Lowest-level of the Maxim OneWire protocol"""
//|
-//| :class:`OneWire` -- Lowest-level of the Maxim OneWire protocol
-//| =================================================================
+//| def __init__(self, pin: microcontroller.Pin):
+//| """(formerly Dallas Semi) OneWire protocol.
//|
-//| :class:`~busio.OneWire` implements the timing-sensitive foundation of the Maxim
-//| (formerly Dallas Semi) OneWire protocol.
+//| Protocol definition is here: https://www.maximintegrated.com/en/app-notes/index.mvp/id/126
//|
-//| Protocol definition is here: https://www.maximintegrated.com/en/app-notes/index.mvp/id/126
+//| .. class:: OneWire(pin)
//|
-//| .. class:: OneWire(pin)
+//| Create a OneWire object associated with the given pin. The object
+//| implements the lowest level timing-sensitive bits of the protocol.
//|
-//| Create a OneWire object associated with the given pin. The object
-//| implements the lowest level timing-sensitive bits of the protocol.
+//| :param ~microcontroller.Pin pin: Pin connected to the OneWire bus
//|
-//| :param ~microcontroller.Pin pin: Pin connected to the OneWire bus
+//| Read a short series of pulses::
//|
-//| Read a short series of pulses::
+//| import busio
+//| import board
//|
-//| import busio
-//| import board
-//|
-//| onewire = busio.OneWire(board.D7)
-//| onewire.reset()
-//| onewire.write_bit(True)
-//| onewire.write_bit(False)
-//| print(onewire.read_bit())
+//| onewire = busio.OneWire(board.D7)
+//| onewire.reset()
+//| onewire.write_bit(True)
+//| onewire.write_bit(False)
+//| print(onewire.read_bit())"""
+//| ...
//|
STATIC mp_obj_t busio_onewire_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_pin };
@@ -69,9 +68,7 @@ STATIC mp_obj_t busio_onewire_make_new(const mp_obj_type_t *type, size_t n_args,
};
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);
- assert_pin(args[ARG_pin].u_obj, false);
- const mcu_pin_obj_t* pin = MP_OBJ_TO_PTR(args[ARG_pin].u_obj);
- assert_pin_free(pin);
+ const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
busio_onewire_obj_t *self = m_new_obj(busio_onewire_obj_t);
self->base.type = &busio_onewire_type;
@@ -80,9 +77,9 @@ STATIC mp_obj_t busio_onewire_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialize the OneWire bus and release any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialize the OneWire bus and release any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t busio_onewire_deinit(mp_obj_t self_in) {
busio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -97,16 +94,16 @@ STATIC void check_for_deinit(busio_onewire_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t busio_onewire_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -115,12 +112,12 @@ STATIC mp_obj_t busio_onewire_obj___exit__(size_t n_args, const mp_obj_t *args)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_onewire___exit___obj, 4, 4, busio_onewire_obj___exit__);
-//| .. method:: reset()
+//| def reset(self, ) -> Any:
+//| """Reset the OneWire bus and read presence
//|
-//| Reset the OneWire bus and read presence
-//|
-//| :returns: False when at least one device is present
-//| :rtype: bool
+//| :returns: False when at least one device is present
+//| :rtype: bool"""
+//| ...
//|
STATIC mp_obj_t busio_onewire_obj_reset(mp_obj_t self_in) {
busio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -130,12 +127,12 @@ STATIC mp_obj_t busio_onewire_obj_reset(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_onewire_reset_obj, busio_onewire_obj_reset);
-//| .. method:: read_bit()
-//|
-//| Read in a bit
+//| def read_bit(self, ) -> Any:
+//| """Read in a bit
//|
-//| :returns: bit state read
-//| :rtype: bool
+//| :returns: bit state read
+//| :rtype: bool"""
+//| ...
//|
STATIC mp_obj_t busio_onewire_obj_read_bit(mp_obj_t self_in) {
busio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -145,9 +142,9 @@ STATIC mp_obj_t busio_onewire_obj_read_bit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_onewire_read_bit_obj, busio_onewire_obj_read_bit);
-//| .. method:: write_bit(value)
-//|
-//| Write out a bit based on value.
+//| def write_bit(self, value: Any) -> Any:
+//| """Write out a bit based on value."""
+//| ...
//|
STATIC mp_obj_t busio_onewire_obj_write_bit(mp_obj_t self_in, mp_obj_t bool_obj) {
busio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index 828ffb8d0..793ab4f67 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -40,43 +40,45 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: busio
-//|
-//| :class:`SPI` -- a 3-4 wire serial protocol
-//| -----------------------------------------------
+
+//| class SPI:
+//| """A 3-4 wire serial protocol
//|
-//| SPI is a serial protocol that has exclusive pins for data in and out of the
-//| master. It is typically faster than :py:class:`~busio.I2C` because a
-//| separate pin is used to control the active slave rather than a transitted
-//| address. This class only manages three of the four SPI lines: `!clock`,
-//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate slave
-//| select line. (This is common because multiple slaves can share the `!clock`,
-//| `!MOSI` and `!MISO` lines and therefore the hardware.)
+//| SPI is a serial protocol that has exclusive pins for data in and out of the
+//| main device. It is typically faster than :py:class:`~bitbangio.I2C` because a
+//| separate pin is used to select a device rather than a transmitted
+//| address. This class only manages three of the four SPI lines: `!clock`,
+//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate
+//| select line, often abbreviated `!CS` or `!SS`. (This is common because
+//| multiple secondaries can share the `!clock`, `!MOSI` and `!MISO` lines
+//| and therefore the hardware.)"""
//|
-//| .. class:: SPI(clock, MOSI=None, MISO=None)
+//| def __init__(self, clock: microcontroller.Pin, MOSI: microcontroller.Pin = None, MISO: microcontroller.Pin = None):
//|
-//| Construct an SPI object on the given pins.
+//| """Construct an SPI object on the given pins.
//|
-//| ..note:: The SPI peripherals allocated in order of desirability, if possible,
-//| such as highest speed and not shared use first. For instance, on the nRF52840,
-//| there is a single 32MHz SPI peripheral, and multiple 8MHz peripherals,
-//| some of which may also be used for I2C. The 32MHz SPI peripheral is returned
-//| first, then the exclusive 8MHz SPI peripheral, and finally the shared 8MHz
-//| peripherals.
+//| ..note:: The SPI peripherals allocated in order of desirability, if possible,
+//| such as highest speed and not shared use first. For instance, on the nRF52840,
+//| there is a single 32MHz SPI peripheral, and multiple 8MHz peripherals,
+//| some of which may also be used for I2C. The 32MHz SPI peripheral is returned
+//| first, then the exclusive 8MHz SPI peripheral, and finally the shared 8MHz
+//| peripherals.
//|
-//| .. seealso:: Using this class directly requires careful lock management.
-//| Instead, use :class:`~adafruit_bus_device.spi_device.SPIDevice` to
-//| manage locks.
+//| .. seealso:: Using this class directly requires careful lock management.
+//| Instead, use :class:`~adafruit_bus_device.spi_device.SPIDevice` to
+//| manage locks.
//|
-//| .. seealso:: Using this class to directly read registers requires manual
-//| bit unpacking. Instead, use an existing driver or make one with
-//| :ref:`Register <register-module-reference>` data descriptors.
+//| .. seealso:: Using this class to directly read registers requires manual
+//| bit unpacking. Instead, use an existing driver or make one with
+//| :ref:`Register <register-module-reference>` data descriptors.
//|
-//| :param ~microcontroller.Pin clock: the pin to use for the clock.
-//| :param ~microcontroller.Pin MOSI: the Master Out Slave In pin.
-//| :param ~microcontroller.Pin MISO: the Master In Slave Out pin.
+//| :param ~microcontroller.Pin clock: the pin to use for the clock.
+//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin.
+//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin."""
+//| ...
//|
+
// TODO(tannewt): Support LSB SPI.
STATIC mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
busio_spi_obj_t *self = m_new_obj(busio_spi_obj_t);
@@ -89,22 +91,18 @@ STATIC mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, con
};
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);
- assert_pin(args[ARG_clock].u_obj, false);
- assert_pin(args[ARG_MOSI].u_obj, true);
- assert_pin(args[ARG_MISO].u_obj, true);
- const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj);
- assert_pin_free(clock);
- const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj);
- assert_pin_free(mosi);
- const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj);
- assert_pin_free(miso);
+
+ const mcu_pin_obj_t* clock = validate_obj_is_free_pin(args[ARG_clock].u_obj);
+ const mcu_pin_obj_t* mosi = validate_obj_is_free_pin_or_none(args[ARG_MOSI].u_obj);
+ const mcu_pin_obj_t* miso = validate_obj_is_free_pin_or_none(args[ARG_MISO].u_obj);
+
common_hal_busio_spi_construct(self, clock, mosi, miso);
- return (mp_obj_t)self;
+ return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Turn off the SPI bus.
+//| def deinit(self, ) -> Any:
+//| """Turn off the SPI bus."""
+//| ...
//|
STATIC mp_obj_t busio_spi_obj_deinit(mp_obj_t self_in) {
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -113,16 +111,16 @@ STATIC mp_obj_t busio_spi_obj_deinit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_deinit_obj, busio_spi_obj_deinit);
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers.
+//| Provided by context manager helper."""
+//| ...
//|
-// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t busio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -144,29 +142,30 @@ STATIC void check_for_deinit(busio_spi_obj_t *self) {
}
}
-//| .. method:: configure(*, baudrate=100000, polarity=0, phase=0, bits=8)
-//|
-//| Configures the SPI bus. The SPI object must be locked.
+//| def configure(self, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, bits: int = 8) -> Any:
+//| """Configures the SPI bus. The SPI object must be locked.
//|
-//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower
-//| due to the granularity of available clock settings.
-//| Check the `frequency` attribute for the actual clock rate.
-//| :param int polarity: the base state of the clock line (0 or 1)
-//| :param int phase: the edge of the clock that data is captured. First (0)
-//| or second (1). Rising or falling depends on clock polarity.
-//| :param int bits: the number of bits per word
+//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower
+//| due to the granularity of available clock settings.
+//| Check the `frequency` attribute for the actual clock rate.
+//| :param int polarity: the base state of the clock line (0 or 1)
+//| :param int phase: the edge of the clock that data is captured. First (0)
+//| or second (1). Rising or falling depends on clock polarity.
+//| :param int bits: the number of bits per word
//|
-//| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that
-//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is
-//| within spec for the SAMD21.
+//| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that
+//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is
+//| within spec for the SAMD21.
//|
-//| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz,
-//| and 8MHz.
-//| If you pick a a baudrate other than one of these, the nearest lower
-//| baudrate will be chosen, with a minimum of 125kHz.
-//| Two SPI objects may be created, except on the Circuit Playground Bluefruit,
-//| which allows only one (to allow for an additional I2C object).
+//| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz,
+//| and 8MHz.
+//| If you pick a a baudrate other than one of these, the nearest lower
+//| baudrate will be chosen, with a minimum of 125kHz.
+//| Two SPI objects may be created, except on the Circuit Playground Bluefruit,
+//| which allows only one (to allow for an additional I2C object)."""
+//| ...
//|
+
STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits };
static const mp_arg_t allowed_args[] = {
@@ -202,23 +201,25 @@ STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_configure_obj, 1, busio_spi_configure);
-//| .. method:: try_lock()
+//| def try_lock(self, ) -> Any:
+//| """Attempts to grab the SPI lock. Returns True on success.
//|
-//| Attempts to grab the SPI lock. Returns True on success.
-//|
-//| :return: True when lock has been grabbed
-//| :rtype: bool
+//| :return: True when lock has been grabbed
+//| :rtype: bool"""
+//| ...
//|
+
STATIC mp_obj_t busio_spi_obj_try_lock(mp_obj_t self_in) {
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(common_hal_busio_spi_try_lock(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_try_lock_obj, busio_spi_obj_try_lock);
-//| .. method:: unlock()
-//|
-//| Releases the SPI lock.
+//| def unlock(self, ) -> Any:
+//| """Releases the SPI lock."""
+//| ...
//|
+
STATIC mp_obj_t busio_spi_obj_unlock(mp_obj_t self_in) {
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
@@ -227,15 +228,16 @@ STATIC mp_obj_t busio_spi_obj_unlock(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock);
-//| .. method:: write(buffer, *, start=0, end=None)
-//|
-//| Write the data contained in ``buffer``. The SPI object must be locked.
-//| If the buffer is empty, nothing happens.
+//| def write(self, buffer: bytearray, *, start: Any = 0, end: int = None) -> Any:
+//| """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 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)``
+//| :param bytearray 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)``"""
+//| ...
//|
+
STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end };
static const mp_arg_t allowed_args[] = {
@@ -268,17 +270,18 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write);
-//| .. method:: readinto(buffer, *, start=0, end=None, write_value=0)
+//| def readinto(self, buffer: bytearray, *, start: Any = 0, end: int = None, write_value: int = 0) -> Any:
+//| """Read into ``buffer`` while writing ``write_value`` for each byte read.
+//| The SPI object must be locked.
+//| If the number of bytes to read is 0, nothing happens.
//|
-//| Read into ``buffer`` while writing ``write_value`` for each byte read.
-//| 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 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.)
+//| :param bytearray 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.)"""
+//| ...
//|
+
STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value };
static const mp_arg_t allowed_args[] = {
@@ -311,21 +314,22 @@ 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);
-//| .. method:: write_readinto(buffer_out, buffer_in, *, out_start=0, out_end=None, in_start=0, in_end=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.
+//| def write_readinto(self, buffer_out: bytearray, buffer_in: bytearray, *, out_start: Any = 0, out_end: int = None, in_start: Any = 0, in_end: int = None) -> Any:
+//| """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 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]``
-//| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``
+//| :param bytearray buffer_out: Write out the data in this buffer
+//| :param bytearray 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]``
+//| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``"""
+//| ...
//|
+
STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
static const mp_arg_t allowed_args[] = {
@@ -373,11 +377,11 @@ STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto);
-//| .. attribute:: frequency
-//|
-//| The actual SPI bus frequency. This may not match the frequency requested
-//| due to internal limitations.
+//| frequency: Any = ...
+//| """The actual SPI bus frequency. This may not match the frequency requested
+//| due to internal limitations."""
//|
+
STATIC mp_obj_t busio_spi_obj_get_frequency(mp_obj_t self_in) {
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
@@ -414,3 +418,10 @@ const mp_obj_type_t busio_spi_type = {
.make_new = busio_spi_make_new,
.locals_dict = (mp_obj_dict_t*)&busio_spi_locals_dict,
};
+
+busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj) {
+ if (!MP_OBJ_IS_TYPE(obj, &busio_spi_type)) {
+ mp_raise_TypeError_varg(translate("Expected a %q"), busio_spi_type.name);
+ }
+ return MP_OBJ_TO_PTR(obj);
+}
diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h
index b7b0715d1..3a8b6dbc1 100644
--- a/shared-bindings/busio/SPI.h
+++ b/shared-bindings/busio/SPI.h
@@ -56,7 +56,7 @@ extern bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *dat
extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value);
// Reads and write len bytes simultaneously.
-extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len);
+extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len);
// Return actual SPI bus frequency.
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self);
@@ -70,4 +70,6 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self);
// This is used by the supervisor to claim SPI devices indefinitely.
extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self);
+extern busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj_in);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H
diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c
index e4a6b93d9..25cf5f480 100644
--- a/shared-bindings/busio/UART.c
+++ b/shared-bindings/busio/UART.c
@@ -39,33 +39,31 @@
#include "py/stream.h"
#include "supervisor/shared/translate.h"
-
-//| .. currentmodule:: busio
-//|
-//| :class:`UART` -- a bidirectional serial protocol
-//| =================================================
-//|
-//|
-//| .. class:: UART(tx, rx, *, baudrate=9600, bits=8, parity=None, stop=1, timeout=1, receiver_buffer_size=64)
-//|
-//| A common bidirectional serial protocol that uses an an agreed upon speed
-//| rather than a shared clock line.
-//|
-//| :param ~microcontroller.Pin tx: the pin to transmit with, or ``None`` if this ``UART`` is receive-only.
-//| :param ~microcontroller.Pin rx: the pin to receive on, or ``None`` if this ``UART`` is transmit-only.
-//| :param ~microcontroller.Pin rts: the pin for rts, or ``None`` if rts not in use.
-//| :param ~microcontroller.Pin cts: the pin for cts, or ``None`` if cts not in use.
-//| :param ~microcontroller.Pin rs485_dir: the pin for rs485 direction setting, or ``None`` if rs485 not in use.
-//| :param bool rs485_invert: set to invert the sense of the rs485_dir pin.
-//| :param int baudrate: the transmit and receive speed.
-//| :param int bits: the number of bits per byte, 7, 8 or 9.
-//| :param Parity parity: the parity used for error checking.
-//| :param int stop: the number of stop bits, 1 or 2.
-//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds.
-//| :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.)
-//|
-//| *New in CircuitPython 4.0:* ``timeout`` has incompatibly changed units from milliseconds to seconds.
-//| The new upper limit on ``timeout`` is meant to catch mistaken use of milliseconds.
+#define STREAM_DEBUG(...) (void)0
+// #define STREAM_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
+
+//| class UART:
+//| """A bidirectional serial protocol"""
+//| def __init__(self, tx: microcontroller.Pin, rx: microcontroller.Pin, *, baudrate: int = 9600, bits: int = 8, parity: Parity = None, stop: int = 1, timeout: float = 1, receiver_buffer_size: int = 64):
+//| """A common bidirectional serial protocol that uses an an agreed upon speed
+//| rather than a shared clock line.
+//|
+//| :param ~microcontroller.Pin tx: the pin to transmit with, or ``None`` if this ``UART`` is receive-only.
+//| :param ~microcontroller.Pin rx: the pin to receive on, or ``None`` if this ``UART`` is transmit-only.
+//| :param ~microcontroller.Pin rts: the pin for rts, or ``None`` if rts not in use.
+//| :param ~microcontroller.Pin cts: the pin for cts, or ``None`` if cts not in use.
+//| :param ~microcontroller.Pin rs485_dir: the output pin for rs485 direction setting, or ``None`` if rs485 not in use.
+//| :param bool rs485_invert: rs485_dir pin active high when set. Active low otherwise.
+//| :param int baudrate: the transmit and receive speed.
+//| :param int bits: the number of bits per byte, 7, 8 or 9.
+//| :param Parity parity: the parity used for error checking.
+//| :param int stop: the number of stop bits, 1 or 2.
+//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds.
+//| :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.)
+//|
+//| *New in CircuitPython 4.0:* ``timeout`` has incompatibly changed units from milliseconds to seconds.
+//| The new upper limit on ``timeout`` is meant to catch mistaken use of milliseconds."""
+//| ...
//|
typedef struct {
mp_obj_base_t base;
@@ -89,8 +87,8 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co
enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size,
ARG_rts, ARG_cts, ARG_rs485_dir,ARG_rs485_invert};
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_tx, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_rx, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 9600} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
@@ -105,24 +103,23 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co
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);
- assert_pin(args[ARG_rx].u_obj, true);
- const mcu_pin_obj_t* rx = MP_OBJ_TO_PTR(args[ARG_rx].u_obj);
- assert_pin_free(rx);
+ const mcu_pin_obj_t* rx = validate_obj_is_free_pin_or_none(args[ARG_rx].u_obj);
+ const mcu_pin_obj_t* tx = validate_obj_is_free_pin_or_none(args[ARG_tx].u_obj);
- assert_pin(args[ARG_tx].u_obj, true);
- const mcu_pin_obj_t* tx = MP_OBJ_TO_PTR(args[ARG_tx].u_obj);
- assert_pin_free(tx);
+ if ( (tx == NULL) && (rx == NULL) ) {
+ mp_raise_ValueError(translate("tx and rx cannot both be None"));
+ }
uint8_t bits = args[ARG_bits].u_int;
if (bits < 7 || bits > 9) {
mp_raise_ValueError(translate("bits must be 7, 8 or 9"));
}
- uart_parity_t parity = PARITY_NONE;
+ busio_uart_parity_t parity = BUSIO_UART_PARITY_NONE;
if (args[ARG_parity].u_obj == &busio_uart_parity_even_obj) {
- parity = PARITY_EVEN;
+ parity = BUSIO_UART_PARITY_EVEN;
} else if (args[ARG_parity].u_obj == &busio_uart_parity_odd_obj) {
- parity = PARITY_ODD;
+ parity = BUSIO_UART_PARITY_ODD;
}
uint8_t stop = args[ARG_stop].u_int;
@@ -133,22 +130,21 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co
mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
validate_timeout(timeout);
- const mcu_pin_obj_t* rts = MP_OBJ_TO_PTR(args[ARG_rts].u_obj);
-
- const mcu_pin_obj_t* cts = MP_OBJ_TO_PTR(args[ARG_cts].u_obj);
+ const mcu_pin_obj_t* rts = validate_obj_is_free_pin_or_none(args[ARG_rts].u_obj);
+ const mcu_pin_obj_t* cts = validate_obj_is_free_pin_or_none(args[ARG_cts].u_obj);
+ const mcu_pin_obj_t* rs485_dir = validate_obj_is_free_pin_or_none(args[ARG_rs485_dir].u_obj);
- const mcu_pin_obj_t* rs485_dir = args[ARG_rs485_dir].u_obj;
- bool rs485_invert = args[ARG_rs485_invert].u_bool;
+ const bool rs485_invert = args[ARG_rs485_invert].u_bool;
common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert,
args[ARG_baudrate].u_int, bits, parity, stop, timeout,
- args[ARG_receiver_buffer_size].u_int);
+ args[ARG_receiver_buffer_size].u_int, NULL, false);
return (mp_obj_t)self;
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the UART and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the UART and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t busio_uart_obj_deinit(mp_obj_t self_in) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -163,16 +159,16 @@ STATIC void check_for_deinit(busio_uart_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t busio_uart_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -183,46 +179,49 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_
// These are standard stream methods. Code is in py/stream.c.
//
-//| .. method:: read(nbytes=None)
-//|
-//| Read characters. If ``nbytes`` is specified then read at most that many
-//| bytes. Otherwise, read everything that arrives until the connection
-//| times out. Providing the number of bytes expected is highly recommended
-//| because it will be faster.
+//| def read(self, nbytes: Any = None) -> Any:
+//| """Read characters. If ``nbytes`` is specified then read at most that many
+//| bytes. Otherwise, read everything that arrives until the connection
+//| times out. Providing the number of bytes expected is highly recommended
+//| because it will be faster.
//|
-//| :return: Data read
-//| :rtype: bytes or None
+//| :return: Data read
+//| :rtype: bytes or None"""
+//| ...
//|
-//| .. method:: readinto(buf)
-//|
-//| Read bytes into the ``buf``. Read at most ``len(buf)`` bytes.
-//|
-//| :return: number of bytes read and stored into ``buf``
-//| :rtype: int or None (on a non-blocking error)
-//|
-//| *New in CircuitPython 4.0:* No length parameter is permitted.
+
+//| def readinto(self, buf: Any) -> Any:
+//| """Read bytes into the ``buf``. Read at most ``len(buf)`` bytes.
//|
-//| .. method:: readline()
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: int or None (on a non-blocking error)
//|
-//| Read a line, ending in a newline character, or
-//| return None if a timeout occurs sooner, or
-//| return everything readable if no newline is found and timeout=0
+//| *New in CircuitPython 4.0:* No length parameter is permitted."""
+//| ...
//|
-//| :return: the line read
-//| :rtype: str or None
+//| def readline(self, ) -> Any:
+//| """Read a line, ending in a newline character, or
+//| return None if a timeout occurs sooner, or
+//| return everything readable if no newline is found and timeout=0
//|
-//| .. method:: write(buf)
+//| :return: the line read
+//| :rtype: bytes or None"""
+//| ...
//|
-//| Write the buffer of bytes to the bus.
+
+//| def write(self, buf: Any) -> Any:
+//| """Write the buffer of bytes to the bus.
//|
-//| *New in CircuitPython 4.0:* ``buf`` must be bytes, not a string.
+//| *New in CircuitPython 4.0:* ``buf`` must be bytes, not a string.
//|
-//| :return: the number of bytes written
-//| :rtype: int or None
+//| :return: the number of bytes written
+//| :rtype: int or None"""
+//| ...
//|
// These three methods are used by the shared stream methods.
STATIC mp_uint_t busio_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+ STREAM_DEBUG("busio_uart_read stream %d\n", size);
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
byte *buf = buf_in;
@@ -263,9 +262,8 @@ STATIC mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t
return ret;
}
-//| .. attribute:: baudrate
-//|
-//| The current baudrate.
+//| baudrate: Any = ...
+//| """The current baudrate."""
//|
STATIC mp_obj_t busio_uart_obj_get_baudrate(mp_obj_t self_in) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -290,9 +288,8 @@ const mp_obj_property_t busio_uart_baudrate_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: in_waiting
-//|
-//| The number of bytes in the input buffer, available to be read
+//| in_waiting: Any = ...
+//| """The number of bytes in the input buffer, available to be read"""
//|
STATIC mp_obj_t busio_uart_obj_get_in_waiting(mp_obj_t self_in) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -308,9 +305,8 @@ const mp_obj_property_t busio_uart_in_waiting_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: timeout
-//|
-//| The current timeout, in seconds (float).
+//| timeout: Any = ...
+//| """The current timeout, in seconds (float)."""
//|
STATIC mp_obj_t busio_uart_obj_get_timeout(mp_obj_t self_in) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -337,9 +333,8 @@ const mp_obj_property_t busio_uart_timeout_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: reset_input_buffer()
-//|
-//| Discard any unread characters in the input buffer.
+//| def reset_input_buffer(self, ) -> Any: ...
+//| """Discard any unread characters in the input buffer."""
//|
STATIC mp_obj_t busio_uart_obj_reset_input_buffer(mp_obj_t self_in) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -349,17 +344,14 @@ STATIC mp_obj_t busio_uart_obj_reset_input_buffer(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_reset_input_buffer_obj, busio_uart_obj_reset_input_buffer);
-//| .. class:: busio.UART.Parity()
-//|
-//| Enum-like class to define the parity used to verify correct data transfer.
-//|
-//| .. data:: ODD
-//|
-//| Total number of ones should be odd.
+//| class Parity:
+//| """Enum-like class to define the parity used to verify correct data transfer."""
//|
-//| .. data:: EVEN
+//| ODD: Any = ...
+//| """Total number of ones should be odd."""
//|
-//| Total number of ones should be even.
+//| EVEN: Any = ...
+//| """Total number of ones should be even."""
//|
const mp_obj_type_t busio_uart_parity_type;
diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h
index fe71e8668..ce8da1445 100644
--- a/shared-bindings/busio/UART.h
+++ b/shared-bindings/busio/UART.h
@@ -29,22 +29,24 @@
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/busio/UART.h"
+#include "py/ringbuf.h"
extern const mp_obj_type_t busio_uart_type;
typedef enum {
- PARITY_NONE,
- PARITY_EVEN,
- PARITY_ODD
-} uart_parity_t;
+ BUSIO_UART_PARITY_NONE,
+ BUSIO_UART_PARITY_EVEN,
+ BUSIO_UART_PARITY_ODD
+} busio_uart_parity_t;
// Construct an underlying UART object.
extern void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
- uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
- mp_float_t timeout, uint16_t receiver_buffer_size);
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
+ mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
+ bool sigint_enabled);
extern void common_hal_busio_uart_deinit(busio_uart_obj_t *self);
extern bool common_hal_busio_uart_deinited(busio_uart_obj_t *self);
@@ -66,4 +68,6 @@ extern uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *
extern void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self);
extern bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self);
+extern void common_hal_busio_uart_never_reset(busio_uart_obj_t *self);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_UART_H
diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c
index ff2933dc6..04632c2f4 100644
--- a/shared-bindings/busio/__init__.c
+++ b/shared-bindings/busio/__init__.c
@@ -38,12 +38,7 @@
#include "py/runtime.h"
-//| :mod:`busio` --- Hardware accelerated behavior
-//| =================================================
-//|
-//| .. module:: busio
-//| :synopsis: Hardware accelerated behavior
-//| :platform: SAMD21
+//| """Hardware accelerated external bus access
//|
//| The `busio` module contains classes to support a variety of serial
//| protocols.
@@ -54,16 +49,6 @@
//| then a RuntimeError will be raised. Use the `bitbangio` module to explicitly
//| bitbang a serial protocol on any general purpose pins.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| I2C
-//| OneWire
-//| SPI
-//| UART
-//|
//| 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
@@ -81,7 +66,7 @@
//| This example will initialize the the device, run
//| :py:meth:`~busio.I2C.scan` and then :py:meth:`~busio.I2C.deinit` the
//| hardware. The last step is optional because CircuitPython automatically
-//| resets hardware after a program finishes.
+//| resets hardware after a program finishes."""
//|
STATIC const mp_rom_map_elem_t busio_module_globals_table[] = {
diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c
new file mode 100644
index 000000000..8db795015
--- /dev/null
+++ b/shared-bindings/countio/Counter.c
@@ -0,0 +1,145 @@
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/runtime0.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/countio/Counter.h"
+#include "shared-bindings/util.h"
+
+//| class Counter:
+//| """Counter will keep track of the number of falling edge transistions (pulses) on a
+//| given pin"""
+//|
+//| def __init__(self, pin_a):
+//| """Create a Counter object associated with the given pin. It tracks the number of
+//| falling pulses relative when the object is constructed.
+//|
+//| :param ~microcontroller.Pin pin_a: Pin to read pulses from.
+//|
+//|
+//| For example::
+//|
+//| import countio
+//| import time
+//| from board import *
+//|
+//| pin_counter = countio.Counter(board.D1)
+//| #reset the count after 100 counts
+//| while True:
+//| if pin_counter.count == 100:
+//| pin_counter.reset()
+//| print(pin_counter.count)"""
+//|
+STATIC mp_obj_t countio_counter_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_pin_a };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin_a, 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);
+
+ const mcu_pin_obj_t* pin_a = validate_obj_is_free_pin(args[ARG_pin_a].u_obj);
+
+
+ countio_counter_obj_t *self = m_new_obj(countio_counter_obj_t);
+ self->base.type = &countio_counter_type;
+
+ common_hal_countio_counter_construct(self, pin_a);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| def deinit(self):
+//| """Deinitializes the Counter and releases any hardware resources for reuse."""
+//|
+STATIC mp_obj_t countio_counter_deinit(mp_obj_t self_in) {
+ countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_countio_counter_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(countio_counter_deinit_obj, countio_counter_deinit);
+
+STATIC void check_for_deinit(countio_counter_obj_t *self) {
+ if (common_hal_countio_counter_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| def __enter__(self):
+//| """No-op used by Context Managers."""
+//|
+// Provided by context manager helper.
+
+//| def __exit__(self):
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//|
+STATIC mp_obj_t countio_counter_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_countio_counter_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(countio_counter___exit___obj, 4, 4, countio_counter_obj___exit__);
+
+
+//| count: int = ...
+//| """The current count in terms of pulses."""
+//|
+STATIC mp_obj_t countio_counter_obj_get_count(mp_obj_t self_in) {
+ countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ return mp_obj_new_int(common_hal_countio_counter_get_count(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(countio_counter_get_count_obj, countio_counter_obj_get_count);
+
+STATIC mp_obj_t countio_counter_obj_set_count(mp_obj_t self_in, mp_obj_t new_count) {
+ countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ common_hal_countio_counter_set_count(self, mp_obj_get_int(new_count));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(countio_counter_set_count_obj, countio_counter_obj_set_count);
+
+const mp_obj_property_t countio_counter_count_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&countio_counter_get_count_obj,
+ (mp_obj_t)&countio_counter_set_count_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| def reset(self):
+//| """Resets the count back to 0."""
+//|
+STATIC mp_obj_t countio_counter_reset(mp_obj_t self_in){
+ countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ //set the position to zero for reset
+ common_hal_countio_counter_reset(self);
+ return mp_const_none;
+}
+
+
+MP_DEFINE_CONST_FUN_OBJ_1(countio_counter_reset_obj, countio_counter_reset);
+
+STATIC const mp_rom_map_elem_t countio_counter_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&countio_counter_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&countio_counter___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&countio_counter_count_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&countio_counter_reset_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(countio_counter_locals_dict, countio_counter_locals_dict_table);
+
+const mp_obj_type_t countio_counter_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Counter,
+ .make_new = countio_counter_make_new,
+ .locals_dict = (mp_obj_dict_t*)&countio_counter_locals_dict,
+};
diff --git a/shared-bindings/countio/Counter.h b/shared-bindings/countio/Counter.h
new file mode 100644
index 000000000..15adbbe2a
--- /dev/null
+++ b/shared-bindings/countio/Counter.h
@@ -0,0 +1,18 @@
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_COUNTER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_COUNTER_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/countio/Counter.h"
+
+extern const mp_obj_type_t countio_counter_type;
+
+extern void common_hal_countio_counter_construct(countio_counter_obj_t* self,
+ const mcu_pin_obj_t* pin_a);
+extern void common_hal_countio_counter_deinit(countio_counter_obj_t* self);
+extern bool common_hal_countio_counter_deinited(countio_counter_obj_t* self);
+extern mp_int_t common_hal_countio_counter_get_count(countio_counter_obj_t* self);
+extern void common_hal_countio_counter_set_count(countio_counter_obj_t* self,
+ mp_int_t new_count);
+extern void common_hal_countio_counter_reset(countio_counter_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_COUNTER_H
diff --git a/shared-bindings/countio/__init__.c b/shared-bindings/countio/__init__.c
new file mode 100644
index 000000000..7046a5e72
--- /dev/null
+++ b/shared-bindings/countio/__init__.c
@@ -0,0 +1,36 @@
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/countio/__init__.h"
+#include "shared-bindings/countio/Counter.h"
+
+//| """Support for edge counting
+//|
+//| The `countio` module contains logic to read and count edge transistions
+//|
+
+//| .. 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
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//|
+
+STATIC const mp_rom_map_elem_t countio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_countio) },
+ { MP_ROM_QSTR(MP_QSTR_Counter), MP_ROM_PTR(&countio_counter_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(countio_module_globals, countio_module_globals_table);
+
+const mp_obj_module_t countio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&countio_module_globals,
+};
diff --git a/shared-bindings/countio/__init__.h b/shared-bindings/countio/__init__.h
new file mode 100644
index 000000000..35ae9f035
--- /dev/null
+++ b/shared-bindings/countio/__init__.h
@@ -0,0 +1,9 @@
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO___INIT___H
diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c
index 16472c12c..eaf2c1810 100644
--- a/shared-bindings/digitalio/DigitalInOut.c
+++ b/shared-bindings/digitalio/DigitalInOut.c
@@ -43,23 +43,20 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: digitalio
+//| class DigitalInOut:
+//| """Digital input and output
//|
-//| :class:`DigitalInOut` -- digital input and output
-//| =========================================================
+//| A DigitalInOut is used to digitally control I/O pins. For analog control of
+//| a pin, see the :py:class:`analogio.AnalogIn` and
+//| :py:class:`analogio.AnalogOut` classes."""
//|
-//| A DigitalInOut is used to digitally control I/O pins. For analog control of
-//| a pin, see the :py:class:`analogio.AnalogIn` and
-//| :py:class:`analogio.AnalogOut` classes.
+//| def __init__(self, pin: microcontroller.Pin):
+//| """Create a new DigitalInOut object associated with the pin. Defaults to input
+//| with no pull. Use :py:meth:`switch_to_input` and
+//| :py:meth:`switch_to_output` to change the direction.
//|
-
-//| .. class:: DigitalInOut(pin)
-//|
-//| Create a new DigitalInOut object associated with the pin. Defaults to input
-//| with no pull. Use :py:meth:`switch_to_input` and
-//| :py:meth:`switch_to_output` to change the direction.
-//|
-//| :param ~microcontroller.Pin pin: The pin to control
+//| :param ~microcontroller.Pin pin: The pin to control"""
+//| ...
//|
STATIC mp_obj_t digitalio_digitalinout_make_new(const mp_obj_type_t *type,
mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
@@ -68,17 +65,15 @@ STATIC mp_obj_t digitalio_digitalinout_make_new(const mp_obj_type_t *type,
digitalio_digitalinout_obj_t *self = m_new_obj(digitalio_digitalinout_obj_t);
self->base.type = &digitalio_digitalinout_type;
- assert_pin(args[0], false);
- mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]);
- assert_pin_free(pin);
+ mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
common_hal_digitalio_digitalinout_construct(self, pin);
- return (mp_obj_t)self;
+ return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Turn off the DigitalInOut and release the pin for other use.
+//| def deinit(self) -> None:
+//| """Turn off the DigitalInOut and release the pin for other use."""
+//| ...
//|
STATIC mp_obj_t digitalio_digitalinout_obj_deinit(mp_obj_t self_in) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -87,16 +82,16 @@ STATIC mp_obj_t digitalio_digitalinout_obj_deinit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_deinit_obj, digitalio_digitalinout_obj_deinit);
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> DigitalInOut:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> None:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t digitalio_digitalinout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -111,14 +106,14 @@ STATIC void check_for_deinit(digitalio_digitalinout_obj_t *self) {
}
}
+//| def switch_to_output(self, value: bool = False, drive_mode: digitalio.DriveMode = digitalio.DriveMode.PUSH_PULL) -> None:
+//| """Set the drive mode and value and then switch to writing out digital
+//| values.
//|
-//| .. method:: switch_to_output(value=False, drive_mode=digitalio.DriveMode.PUSH_PULL)
-//|
-//| Set the drive mode and value and then switch to writing out digital
-//| values.
-//|
-//| :param bool value: default value to set upon switching
-//| :param ~digitalio.DriveMode drive_mode: drive mode for the output
+//| :param bool value: default value to set upon switching
+//| :param ~digitalio.DriveMode drive_mode: drive mode for the output
+//| """
+//| ...
//|
STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_value, ARG_drive_mode };
@@ -136,27 +131,30 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_
drive_mode = DRIVE_MODE_OPEN_DRAIN;
}
// do the transfer
- common_hal_digitalio_digitalinout_switch_to_output(self, args[ARG_value].u_bool, drive_mode);
+ digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(self, args[ARG_value].u_bool, drive_mode);
+ if (result == DIGITALINOUT_INPUT_ONLY) {
+ mp_raise_NotImplementedError(translate("Pin is input only"));
+ }
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(digitalio_digitalinout_switch_to_output_obj, 1, digitalio_digitalinout_switch_to_output);
-//| .. method:: switch_to_input(pull=None)
-//|
-//| Set the pull and then switch to read in digital values.
+//| def switch_to_input(self, pull: Pull = None) -> None:
+//| """Set the pull and then switch to read in digital values.
//|
-//| :param Pull pull: pull configuration for the input
+//| :param Pull pull: pull configuration for the input
//|
-//| Example usage::
+//| Example usage::
//|
-//| import digitalio
-//| import board
+//| import digitalio
+//| import board
//|
-//| switch = digitalio.DigitalInOut(board.SLIDE_SWITCH)
-//| switch.switch_to_input(pull=digitalio.Pull.UP)
-//| # Or, after switch_to_input
-//| switch.pull = digitalio.Pull.UP
-//| print(switch.value)
+//| switch = digitalio.DigitalInOut(board.SLIDE_SWITCH)
+//| switch.switch_to_input(pull=digitalio.Pull.UP)
+//| # Or, after switch_to_input
+//| switch.pull = digitalio.Pull.UP
+//| print(switch.value)"""
+//| ...
//|
STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_pull };
@@ -168,6 +166,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o
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);
+
digitalio_pull_t pull = PULL_NONE;
if (args[ARG_pull].u_rom_obj == &digitalio_pull_up_obj) {
pull = PULL_UP;
@@ -180,14 +179,13 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o
}
MP_DEFINE_CONST_FUN_OBJ_KW(digitalio_digitalinout_switch_to_input_obj, 1, digitalio_digitalinout_switch_to_input);
-//| .. attribute:: direction
-//|
-//| The direction of the pin.
+//| direction: Direction = ...
+//| """The direction of the pin.
//|
//| Setting this will use the defaults from the corresponding
//| :py:meth:`switch_to_input` or :py:meth:`switch_to_output` method. If
//| you want to set pull, value or drive mode prior to switching, then use
-//| those methods instead.
+//| those methods instead."""
//|
typedef struct {
mp_obj_base_t base;
@@ -212,7 +210,10 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_direction(mp_obj_t self_in, mp_ob
if (value == &digitalio_direction_input_obj) {
common_hal_digitalio_digitalinout_switch_to_input(self, PULL_NONE);
} else if (value == &digitalio_direction_output_obj) {
- common_hal_digitalio_digitalinout_switch_to_output(self, false, DRIVE_MODE_PUSH_PULL);
+ digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(self, false, DRIVE_MODE_PUSH_PULL);
+ if (result == DIGITALINOUT_INPUT_ONLY) {
+ mp_raise_NotImplementedError(translate("Pin is input only"));
+ }
} else {
mp_raise_ValueError(translate("Invalid direction."));
}
@@ -227,9 +228,8 @@ const mp_obj_property_t digitalio_digitalio_direction_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: value
-//|
-//| The digital logic level of the pin.
+//| value: Bool = ...
+//| """The digital logic level of the pin."""
//|
STATIC mp_obj_t digitalio_digitalinout_obj_get_value(mp_obj_t self_in) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -258,12 +258,11 @@ const mp_obj_property_t digitalio_digitalinout_value_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: drive_mode
-//|
-//| The pin drive mode. One of:
+//| drive_mode: DriveMode = ...
+//| """The pin drive mode. One of:
//|
//| - `digitalio.DriveMode.PUSH_PULL`
-//| - `digitalio.DriveMode.OPEN_DRAIN`
+//| - `digitalio.DriveMode.OPEN_DRAIN`"""
//|
STATIC mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -303,15 +302,14 @@ const mp_obj_property_t digitalio_digitalio_drive_mode_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: pull
-//|
-//| The pin pull direction. One of:
+//| pull: Optional[Pull] = ...
+//| """The pin pull direction. One of:
//|
//| - `digitalio.Pull.UP`
//| - `digitalio.Pull.DOWN`
//| - `None`
//|
-//| :raises AttributeError: if `direction` is :py:data:`~digitalio.Direction.OUTPUT`.
+//| :raises AttributeError: if `direction` is :py:data:`~digitalio.Direction.OUTPUT`."""
//|
STATIC mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/digitalio/DigitalInOut.h b/shared-bindings/digitalio/DigitalInOut.h
index eee0d5801..dd6f088ab 100644
--- a/shared-bindings/digitalio/DigitalInOut.h
+++ b/shared-bindings/digitalio/DigitalInOut.h
@@ -37,18 +37,19 @@ extern const mp_obj_type_t digitalio_digitalinout_type;
typedef enum {
DIGITALINOUT_OK,
- DIGITALINOUT_PIN_BUSY
+ DIGITALINOUT_PIN_BUSY,
+ DIGITALINOUT_INPUT_ONLY
} digitalinout_result_t;
digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin);
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self);
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self);
void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
-void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode);
+digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode);
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
void common_hal_digitalio_digitalinout_set_value(digitalio_digitalinout_obj_t* self, bool value);
bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t* self);
-void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, digitalio_drive_mode_t drive_mode);
+digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, digitalio_drive_mode_t drive_mode);
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
diff --git a/shared-bindings/digitalio/Direction.c b/shared-bindings/digitalio/Direction.c
index c8188fc89..dbd0e93e4 100644
--- a/shared-bindings/digitalio/Direction.c
+++ b/shared-bindings/digitalio/Direction.c
@@ -38,23 +38,19 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
-//| .. currentmodule:: digitalio
+//| class Direction:
+//| """Defines the direction of a digital pin"""
//|
-//| :class:`Direction` -- defines the direction of a digital pin
-//| =============================================================
+//| def __init__(self, ):
+//| """Enum-like class to define which direction the digital values are
+//| going."""
+//| ...
//|
-//| .. class:: Direction
+//| INPUT: Any = ...
+//| """Read digital data in"""
//|
-//| Enum-like class to define which direction the digital values are
-//| going.
-//|
-//| .. data:: INPUT
-//|
-//| Read digital data in
-//|
-//| .. data:: OUTPUT
-//|
-//| Write digital data out
+//| OUTPUT: Any = ...
+//| """Write digital data out"""
//|
const mp_obj_type_t digitalio_direction_type;
diff --git a/shared-bindings/digitalio/DriveMode.c b/shared-bindings/digitalio/DriveMode.c
index 51e1e2ee5..31b682d38 100644
--- a/shared-bindings/digitalio/DriveMode.c
+++ b/shared-bindings/digitalio/DriveMode.c
@@ -26,24 +26,20 @@
#include "shared-bindings/digitalio/DriveMode.h"
-//| .. currentmodule:: digitalio
+//| class DriveMode:
+//| """Defines the drive mode of a digital pin"""
//|
-//| :class:`DriveMode` -- defines the drive mode of a digital pin
-//| =============================================================
+//| def __init__(self, ):
+//| """Enum-like class to define the drive mode used when outputting
+//| digital values."""
+//| ...
//|
-//| .. class:: DriveMode
+//| PUSH_PULL: Any = ...
+//| """Output both high and low digital values"""
//|
-//| Enum-like class to define the drive mode used when outputting
-//| digital values.
-//|
-//| .. data:: PUSH_PULL
-//|
-//| Output both high and low digital values
-//|
-//| .. data:: OPEN_DRAIN
-//|
-//| Output low digital values but go into high z for digital high. This is
-//| useful for i2c and other protocols that share a digital line.
+//| OPEN_DRAIN: Any = ...
+//| """Output low digital values but go into high z for digital high. This is
+//| useful for i2c and other protocols that share a digital line."""
//|
const mp_obj_type_t digitalio_drive_mode_type;
diff --git a/shared-bindings/digitalio/Pull.c b/shared-bindings/digitalio/Pull.c
index 813268db7..9aeec1f33 100644
--- a/shared-bindings/digitalio/Pull.c
+++ b/shared-bindings/digitalio/Pull.c
@@ -26,25 +26,21 @@
#include "shared-bindings/digitalio/Pull.h"
-//| .. currentmodule:: digitalio
+//| class Pull:
+//| """Defines the pull of a digital input pin"""
//|
-//| :class:`Pull` -- defines the pull of a digital input pin
-//| =============================================================
+//| def __init__(self, ):
+//| """Enum-like class to define the pull value, if any, used while reading
+//| digital values in."""
+//| ...
//|
-//| .. class:: Pull
+//| UP: Any = ...
+//| """When the input line isn't being driven the pull up can pull the state
+//| of the line high so it reads as true."""
//|
-//| Enum-like class to define the pull value, if any, used while reading
-//| digital values in.
-//|
-//| .. data:: UP
-//|
-//| When the input line isn't being driven the pull up can pull the state
-//| of the line high so it reads as true.
-//|
-//| .. data:: DOWN
-//|
-//| When the input line isn't being driven the pull down can pull the
-//| state of the line low so it reads as false.
+//| DOWN: Any = ...
+//| """When the input line isn't being driven the pull down can pull the
+//| state of the line low so it reads as false."""
//|
const mp_obj_type_t digitalio_pull_type;
diff --git a/shared-bindings/digitalio/__init__.c b/shared-bindings/digitalio/__init__.c
index 1632262d2..f8f45b158 100644
--- a/shared-bindings/digitalio/__init__.c
+++ b/shared-bindings/digitalio/__init__.c
@@ -38,25 +38,10 @@
#include "py/runtime.h"
-//| :mod:`digitalio` --- Basic digital pin support
-//| =================================================
-//|
-//| .. module:: digitalio
-//| :synopsis: Basic digital pin support
-//| :platform: SAMD21, ESP8266
+//| """Basic digital pin support
//|
//| The `digitalio` module contains classes to provide access to basic digital IO.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| DigitalInOut
-//| Direction
-//| DriveMode
-//| Pull
-//|
//| 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
@@ -86,7 +71,7 @@
//| led.value = True
//| time.sleep(0.1)
//| led.value = False
-//| time.sleep(0.1)
+//| time.sleep(0.1)"""
//|
STATIC const mp_rom_map_elem_t digitalio_module_globals_table[] = {
diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c
index 91c17f2d1..a52840f2e 100644
--- a/shared-bindings/displayio/Bitmap.c
+++ b/shared-bindings/displayio/Bitmap.c
@@ -36,22 +36,18 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class Bitmap:
+//| """Stores values of a certain size in a 2D array"""
//|
-//| :class:`Bitmap` -- Stores values in a 2D array
-//| ==========================================================================
+//| def __init__(self, width: int, height: int, value_count: int):
+//| """Create a Bitmap object with the given fixed size. Each pixel stores a value that is used to
+//| index into a corresponding palette. This enables differently colored sprites to share the
+//| underlying Bitmap. value_count is used to minimize the memory used to store the Bitmap.
//|
-//| Stores values of a certain size in a 2D array
-//|
-//| .. class:: Bitmap(width, height, value_count)
-//|
-//| Create a Bitmap object with the given fixed size. Each pixel stores a value that is used to
-//| index into a corresponding palette. This enables differently colored sprites to share the
-//| underlying Bitmap. value_count is used to minimize the memory used to store the Bitmap.
-//|
-//| :param int width: The number of values wide
-//| :param int height: The number of values high
-//| :param int value_count: The number of possible pixel values.
+//| :param int width: The number of values wide
+//| :param int height: The number of values high
+//| :param int value_count: The number of possible pixel values."""
+//| ...
//|
STATIC mp_obj_t displayio_bitmap_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 3, 3, false);
@@ -77,9 +73,8 @@ STATIC mp_obj_t displayio_bitmap_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. attribute:: width
-//|
-//| Width of the bitmap. (read only)
+//| width: Any = ...
+//| """Width of the bitmap. (read only)"""
//|
STATIC mp_obj_t displayio_bitmap_obj_get_width(mp_obj_t self_in) {
displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in);
@@ -96,9 +91,8 @@ const mp_obj_property_t displayio_bitmap_width_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: height
-//|
-//| Height of the bitmap. (read only)
+//| height: Any = ...
+//| """Height of the bitmap. (read only)"""
//|
STATIC mp_obj_t displayio_bitmap_obj_get_height(mp_obj_t self_in) {
displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in);
@@ -115,23 +109,23 @@ const mp_obj_property_t displayio_bitmap_height_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: __getitem__(index)
+//| def __getitem__(self, index: Any) -> Any:
+//| """Returns the value at the given index. The index can either be an x,y tuple or an int equal
+//| to ``y * width + x``.
//|
-//| Returns the value at the given index. The index can either be an x,y tuple or an int equal
-//| to ``y * width + x``.
+//| This allows you to::
//|
-//| This allows you to::
+//| print(bitmap[0,1])"""
+//| ...
//|
-//| print(bitmap[0,1])
+//| def __setitem__(self, index: Any, value: Any) -> Any:
+//| """Sets the value at the given index. The index can either be an x,y tuple or an int equal
+//| to ``y * width + x``.
//|
-//| .. method:: __setitem__(index, value)
+//| This allows you to::
//|
-//| Sets the value at the given index. The index can either be an x,y tuple or an int equal
-//| to ``y * width + x``.
-//|
-//| This allows you to::
-//|
-//| bitmap[0,1] = 3
+//| bitmap[0,1] = 3"""
+//| ...
//|
STATIC mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) {
if (value_obj == mp_const_none) {
@@ -178,9 +172,28 @@ 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: Any) -> Any:
+//| """Fills the bitmap with the supplied palette index value."""
+//| ...
+//|
+STATIC mp_obj_t displayio_bitmap_obj_fill(mp_obj_t self_in, mp_obj_t value_obj) {
+ displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_int_t value = mp_obj_get_int(value_obj);
+ if (value >= 1 << common_hal_displayio_bitmap_get_bits_per_value(self)) {
+ mp_raise_ValueError(translate("pixel value requires too many bits"));
+ }
+ common_hal_displayio_bitmap_fill(self, value);
+
+ return mp_const_none;
+}
+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_fill), MP_ROM_PTR(&displayio_bitmap_fill_obj) },
+
};
STATIC MP_DEFINE_CONST_DICT(displayio_bitmap_locals_dict, displayio_bitmap_locals_dict_table);
diff --git a/shared-bindings/displayio/Bitmap.h b/shared-bindings/displayio/Bitmap.h
index 90694951f..46c337329 100644
--- a/shared-bindings/displayio/Bitmap.h
+++ b/shared-bindings/displayio/Bitmap.h
@@ -41,5 +41,6 @@ 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);
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);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_BITMAP_H
diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c
index db2d1b6e2..33d0bdd3c 100644
--- a/shared-bindings/displayio/ColorConverter.c
+++ b/shared-bindings/displayio/ColorConverter.c
@@ -36,18 +36,15 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class ColorConverter:
+//| """Converts one color format to another."""
//|
-//| :class:`ColorConverter` -- Converts one color format to another
-//| =========================================================================================
+//| def __init__(self, *, dither: bool = False):
+//| """Create a ColorConverter object to convert color formats. Only supports RGB888 to RGB565
+//| currently.
+//| :param bool dither: Adds random noise to dither the output image"""
+//| ...
//|
-//| Converts one color format to another.
-//|
-//| .. class:: ColorConverter(*, dither=False)
-//|
-//| Create a ColorConverter object to convert color formats. Only supports RGB888 to RGB565
-//| currently.
-//| :param bool dither: Adds random noise to dither the output image
// TODO(tannewt): Add support for other color formats.
//|
@@ -68,9 +65,9 @@ STATIC mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, siz
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: convert(color)
-//|
-//| Converts the given RGB888 color to RGB565
+//| def convert(self, color: Any) -> Any:
+//| """Converts the given RGB888 color to RGB565"""
+//| ...
//|
STATIC mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t color_obj) {
displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in);
@@ -87,10 +84,9 @@ STATIC mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_colorconverter_convert_obj, displayio_colorconverter_obj_convert);
-//| .. attribute:: dither
-//|
-//| When true the color converter dithers the output by adding random noise when
-//| truncating to display bitdepth
+//| dither: Any = ...
+//| """When true the color converter dithers the output by adding random noise when
+//| truncating to display bitdepth"""
//|
STATIC mp_obj_t displayio_colorconverter_obj_get_dither(mp_obj_t self_in) {
displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in);
@@ -126,4 +122,3 @@ const mp_obj_type_t displayio_colorconverter_type = {
.make_new = displayio_colorconverter_make_new,
.locals_dict = (mp_obj_dict_t*)&displayio_colorconverter_locals_dict,
};
-
diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c
index 5759e8ad2..6e454f34b 100644
--- a/shared-bindings/displayio/Display.c
+++ b/shared-bindings/displayio/Display.c
@@ -39,74 +39,74 @@
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
-//|
-//| :class:`Display` -- Manage updating a display over a display bus
-//| ==========================================================================
-//|
-//| This initializes a display and connects it into CircuitPython. Unlike other
-//| objects in CircuitPython, Display objects live until `displayio.release_displays()`
-//| is called. This is done so that CircuitPython can use the display itself.
-//|
-//| Most people should not use this class directly. Use a specific display driver instead that will
-//| contain the initialization sequence at minimum.
-//|
-//| .. class:: Display(display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, grayscale=False, pixels_in_byte_share_row=True, bytes_per_cell=1, reverse_pixels_in_byte=False, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness_command=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False, auto_refresh=True, native_frames_per_second=60)
-//|
-//| Create a Display object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
-//|
-//| The ``init_sequence`` is bitpacked to minimize the ram impact. Every command begins with a
-//| command byte followed by a byte to determine the parameter count and if a delay is need after.
-//| When the top bit of the second byte is 1, the next byte will be the delay time in milliseconds.
-//| The remaining 7 bits are the parameter count excluding any delay byte. The third through final
-//| bytes are the remaining command parameters. The next byte will begin a new command definition.
-//| Here is a portion of ILI9341 init code:
-//|
-//| .. code-block:: python
-//|
-//| init_sequence = (b"\xe1\x0f\x00\x0E\x14\x03\x11\x07\x31\xC1\x48\x08\x0F\x0C\x31\x36\x0F" # Set Gamma
-//| b"\x11\x80\x78"# Exit Sleep then delay 0x78 (120ms)
-//| b"\x29\x80\x78"# Display on then delay 0x78 (120ms)
-//| )
-//| display = displayio.Display(display_bus, init_sequence, width=320, height=240)
-//|
-//| The first command is 0xe1 with 15 (0xf) parameters following. The second and third are 0x11 and
-//| 0x29 respectively with delays (0x80) of 120ms (0x78) and no parameters. Multiple byte literals
-//| (b"") are merged together on load. The parens are needed to allow byte literals on subsequent
-//| lines.
-//|
-//| The initialization sequence should always leave the display memory access inline with the scan
-//| of the display to minimize tearing artifacts.
-//|
-//| :param display_bus: The bus that the display is connected to
-//| :type display_bus: displayio.FourWire or displayio.ParallelBus
-//| :param buffer 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
-//| :param int rowstart: The index if the first visible row
-//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)
-//| :param int color_depth: The number of bits of color per pixel transmitted. (Some displays
-//| support 18 bit but 16 is easier to transmit. The last bit is extrapolated.)
-//| :param bool grayscale: True if the display only shows a single color.
-//| :param bool pixels_in_byte_share_row: True when pixels are less than a byte and a byte includes pixels from the same row of the display. When False, pixels share a column.
-//| :param int bytes_per_cell: Number of bytes per addressable memory location when color_depth < 8. When greater than one, bytes share a row or column according to pixels_in_byte_share_row.
-//| :param bool reverse_pixels_in_byte: Reverses the pixel order within each byte when color_depth < 8. Does not apply across multiple bytes even if there is more than one byte per cell (bytes_per_cell.)
-//| :param int set_column_command: Command used to set the start and end columns to update
-//| :param int set_row_command: Command used so set the start and end rows to update
-//| :param int write_ram_command: Command used to write pixels values into the update region. Ignored if data_as_commands is set.
-//| :param int set_vertical_scroll: Command used to set the first row to show
-//| :param microcontroller.Pin backlight_pin: Pin connected to the display's backlight
-//| :param int brightness_command: Command to set display brightness. Usually available in OLED controllers.
-//| :param bool brightness: Initial display brightness. This value is ignored if auto_brightness is True.
-//| :param bool auto_brightness: If True, brightness is controlled via an ambient light sensor or other mechanism.
-//| :param bool single_byte_bounds: Display column and row commands use single bytes
-//| :param bool data_as_commands: Treat all init and boundary data as SPI commands. Certain displays require this.
-//| :param bool auto_refresh: Automatically refresh the screen
-//| :param int native_frames_per_second: Number of display refreshes per second that occur with the given init_sequence.
+//| class Display:
+//| """Manage updating a display over a display bus
+//|
+//| This initializes a display and connects it into CircuitPython. Unlike other
+//| objects in CircuitPython, Display objects live until `displayio.release_displays()`
+//| is called. This is done so that CircuitPython can use the display itself.
+//|
+//| Most people should not use this class directly. Use a specific display driver instead that will
+//| contain the initialization sequence at minimum."""
+//|
+//| def __init__(self, display_bus: Any, init_sequence: buffer, *, width: int, height: int, colstart: int = 0, rowstart: int = 0, rotation: int = 0, color_depth: int = 16, grayscale: bool = False, pixels_in_byte_share_row: bool = True, bytes_per_cell: int = 1, reverse_pixels_in_byte: bool = False, set_column_command: int = 0x2a, set_row_command: int = 0x2b, write_ram_command: int = 0x2c, set_vertical_scroll: int = 0, backlight_pin: microcontroller.Pin = None, brightness_command: int = None, brightness: bool = 1.0, auto_brightness: bool = False, single_byte_bounds: bool = False, data_as_commands: bool = False, auto_refresh: bool = True, native_frames_per_second: int = 60):
+//| r"""Create a Display object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
+//|
+//| The ``init_sequence`` is bitpacked to minimize the ram impact. Every command begins with a
+//| command byte followed by a byte to determine the parameter count and if a delay is need after.
+//| When the top bit of the second byte is 1, the next byte will be the delay time in milliseconds.
+//| The remaining 7 bits are the parameter count excluding any delay byte. The third through final
+//| bytes are the remaining command parameters. The next byte will begin a new command definition.
+//| Here is a portion of ILI9341 init code:
+//|
+//| .. code-block:: python
+//|
+//| init_sequence = (b"\xe1\x0f\x00\x0E\x14\x03\x11\x07\x31\xC1\x48\x08\x0F\x0C\x31\x36\x0F" # Set Gamma
+//| b"\x11\x80\x78"# Exit Sleep then delay 0x78 (120ms)
+//| b"\x29\x80\x78"# Display on then delay 0x78 (120ms)
+//| )
+//| display = displayio.Display(display_bus, init_sequence, width=320, height=240)
+//|
+//| The first command is 0xe1 with 15 (0xf) parameters following. The second and third are 0x11 and
+//| 0x29 respectively with delays (0x80) of 120ms (0x78) and no parameters. Multiple byte literals
+//| (b"") are merged together on load. The parens are needed to allow byte literals on subsequent
+//| lines.
+//|
+//| The initialization sequence should always leave the display memory access inline with the scan
+//| of the display to minimize tearing artifacts.
+//|
+//| :param display_bus: The bus that the display is connected to
+//| :type display_bus: displayio.FourWire or displayio.ParallelBus
+//| :param buffer 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
+//| :param int rowstart: The index if the first visible row
+//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)
+//| :param int color_depth: The number of bits of color per pixel transmitted. (Some displays
+//| support 18 bit but 16 is easier to transmit. The last bit is extrapolated.)
+//| :param bool grayscale: True if the display only shows a single color.
+//| :param bool pixels_in_byte_share_row: True when pixels are less than a byte and a byte includes pixels from the same row of the display. When False, pixels share a column.
+//| :param int bytes_per_cell: Number of bytes per addressable memory location when color_depth < 8. When greater than one, bytes share a row or column according to pixels_in_byte_share_row.
+//| :param bool reverse_pixels_in_byte: Reverses the pixel order within each byte when color_depth < 8. Does not apply across multiple bytes even if there is more than one byte per cell (bytes_per_cell.)
+//| :param bool reverse_bytes_in_word: Reverses the order of bytes within a word when color_depth == 16
+//| :param int set_column_command: Command used to set the start and end columns to update
+//| :param int set_row_command: Command used so set the start and end rows to update
+//| :param int write_ram_command: Command used to write pixels values into the update region. Ignored if data_as_commands is set.
+//| :param int set_vertical_scroll: Command used to set the first row to show
+//| :param microcontroller.Pin backlight_pin: Pin connected to the display's backlight
+//| :param int brightness_command: Command to set display brightness. Usually available in OLED controllers.
+//| :param bool brightness: Initial display brightness. This value is ignored if auto_brightness is True.
+//| :param bool auto_brightness: If True, brightness is controlled via an ambient light sensor or other mechanism.
+//| :param bool single_byte_bounds: Display column and row commands use single bytes
+//| :param bool data_as_commands: Treat all init and boundary data as SPI commands. Certain displays require this.
+//| :param bool auto_refresh: Automatically refresh the screen
+//| :param int native_frames_per_second: Number of display refreshes per second that occur with the given init_sequence.
+//| :param bool backlight_on_high: If True, pulling the backlight pin high turns the backlight on."""
+//| ...
//|
STATIC mp_obj_t displayio_display_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_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_bytes_per_cell, ARG_reverse_pixels_in_byte, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_auto_brightness, ARG_single_byte_bounds, ARG_data_as_commands, ARG_auto_refresh, ARG_native_frames_per_second };
+ enum { ARG_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_bytes_per_cell, ARG_reverse_pixels_in_byte, ARG_reverse_bytes_in_word, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_auto_brightness, ARG_single_byte_bounds, ARG_data_as_commands, ARG_auto_refresh, ARG_native_frames_per_second, ARG_backlight_on_high };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_init_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ },
@@ -120,6 +120,7 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
{ MP_QSTR_pixels_in_byte_share_row, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
{ MP_QSTR_bytes_per_cell, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1} },
{ MP_QSTR_reverse_pixels_in_byte, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ { MP_QSTR_reverse_bytes_in_word, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
{ MP_QSTR_set_column_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2a} },
{ MP_QSTR_set_row_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2b} },
{ MP_QSTR_write_ram_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2c} },
@@ -132,6 +133,7 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
{ MP_QSTR_data_as_commands, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_auto_refresh, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
{ MP_QSTR_native_frames_per_second, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 60} },
+ { MP_QSTR_backlight_on_high, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
};
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);
@@ -141,13 +143,7 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_init_sequence].u_obj, &bufinfo, MP_BUFFER_READ);
- mp_obj_t backlight_pin_obj = args[ARG_backlight_pin].u_obj;
- assert_pin(backlight_pin_obj, true);
- const mcu_pin_obj_t* backlight_pin = NULL;
- if (backlight_pin_obj != NULL && backlight_pin_obj != mp_const_none) {
- backlight_pin = MP_OBJ_TO_PTR(backlight_pin_obj);
- assert_pin_free(backlight_pin);
- }
+ const mcu_pin_obj_t* backlight_pin = validate_obj_is_free_pin_or_none(args[ARG_backlight_pin].u_obj);
mp_float_t brightness = mp_obj_get_float(args[ARG_brightness].u_obj);
@@ -156,23 +152,17 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
mp_raise_ValueError(translate("Display rotation must be in 90 degree increments"));
}
- displayio_display_obj_t *self = NULL;
- for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].display.base.type == NULL ||
- displays[i].display.base.type == &mp_type_NoneType) {
- self = &displays[i].display;
- break;
- }
- }
- if (self == NULL) {
- mp_raise_RuntimeError(translate("Too many displays"));
- }
+ primary_display_t *disp = allocate_display_or_raise();
+ displayio_display_obj_t *self = &disp->display;;
self->base.type = &displayio_display_type;
common_hal_displayio_display_construct(
self,
display_bus, args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation,
args[ARG_color_depth].u_int, args[ARG_grayscale].u_bool,
- args[ARG_pixels_in_byte_share_row].u_bool, args[ARG_bytes_per_cell].u_bool, args[ARG_reverse_pixels_in_byte].u_bool,
+ args[ARG_pixels_in_byte_share_row].u_bool,
+ args[ARG_bytes_per_cell].u_bool,
+ args[ARG_reverse_pixels_in_byte].u_bool,
+ args[ARG_reverse_bytes_in_word].u_bool,
args[ARG_set_column_command].u_int, args[ARG_set_row_command].u_int,
args[ARG_write_ram_command].u_int,
args[ARG_set_vertical_scroll].u_int,
@@ -184,7 +174,8 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
args[ARG_single_byte_bounds].u_bool,
args[ARG_data_as_commands].u_bool,
args[ARG_auto_refresh].u_bool,
- args[ARG_native_frames_per_second].u_int
+ args[ARG_native_frames_per_second].u_int,
+ args[ARG_backlight_on_high].u_bool
);
return self;
@@ -197,12 +188,13 @@ static displayio_display_obj_t* native_display(mp_obj_t display_obj) {
return MP_OBJ_TO_PTR(native_display);
}
-//| .. method:: show(group)
+//| def show(self, group: Group) -> Any:
+//| """Switches to displaying the given group of layers. When group is None, the default
+//| CircuitPython terminal will be shown.
//|
-//| Switches to displaying the given group of layers. When group is None, the default
-//| CircuitPython terminal will be shown.
+//| :param Group group: The group to show."""
+//| ...
//|
-//| :param Group group: The group to show.
STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in) {
displayio_display_obj_t *self = native_display(self_in);
displayio_group_t* group = NULL;
@@ -218,21 +210,21 @@ 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);
-//| .. method:: refresh(*, target_frames_per_second=60, minimum_frames_per_second=1)
+//| def refresh(self, *, target_frames_per_second: int = 60, minimum_frames_per_second: int = 1) -> Any:
+//| """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.
//|
-//| 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.
//|
-//| 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.
+//| When auto refresh is on, updates the display immediately. (The display will also update
+//| without calls to this.)
//|
-//| 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.
-//| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second.
+//| :param int target_frames_per_second: How many times a second `refresh` should be called and the screen updated.
+//| :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 };
@@ -253,9 +245,8 @@ STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos
}
MP_DEFINE_CONST_FUN_OBJ_KW(displayio_display_refresh_obj, 1, displayio_display_obj_refresh);
-//| .. attribute:: auto_refresh
-//|
-//| True when the display is refreshed automatically.
+//| auto_refresh: Any = ...
+//| """True when the display is refreshed automatically."""
//|
STATIC mp_obj_t displayio_display_obj_get_auto_refresh(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
@@ -279,11 +270,10 @@ const mp_obj_property_t displayio_display_auto_refresh_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: brightness
-//|
-//| The brightness of the display as a float. 0.0 is off and 1.0 is full brightness. When
+//| brightness: Any = ...
+//| """The brightness of the display as a float. 0.0 is off and 1.0 is full brightness. When
//| `auto_brightness` is True, the value of `brightness` will change automatically.
-//| If `brightness` is set, `auto_brightness` will be disabled and will be set to False.
+//| If `brightness` is set, `auto_brightness` will be disabled and will be set to False."""
//|
STATIC mp_obj_t displayio_display_obj_get_brightness(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
@@ -317,12 +307,11 @@ const mp_obj_property_t displayio_display_brightness_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: auto_brightness
-//|
-//| True when the display brightness is adjusted automatically, based on an ambient
+//| auto_brightness: Any = ...
+//| """True when the display brightness is adjusted automatically, based on an ambient
//| light sensor or other method. Note that some displays may have this set to True by default,
//| but not actually implement automatic brightness adjustment. `auto_brightness` is set to False
-//| if `brightness` is set manually.
+//| if `brightness` is set manually."""
//|
STATIC mp_obj_t displayio_display_obj_get_auto_brightness(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
@@ -349,9 +338,8 @@ const mp_obj_property_t displayio_display_auto_brightness_obj = {
-//| .. attribute:: width
-//|
-//| Gets the width of the board
+//| width: Any = ...
+//| Gets the width of the board
//|
//|
STATIC mp_obj_t displayio_display_obj_get_width(mp_obj_t self_in) {
@@ -367,9 +355,8 @@ const mp_obj_property_t displayio_display_width_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: height
-//|
-//| Gets the height of the board
+//| height: Any = ...
+//| """Gets the height of the board"""
//|
//|
STATIC mp_obj_t displayio_display_obj_get_height(mp_obj_t self_in) {
@@ -385,9 +372,8 @@ const mp_obj_property_t displayio_display_height_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: rotation
-//|
-//| The rotation of the display as an int in degrees.
+//| rotation: Any = ...
+//| """The rotation of the display as an int in degrees."""
//|
STATIC mp_obj_t displayio_display_obj_get_rotation(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
@@ -409,9 +395,8 @@ const mp_obj_property_t displayio_display_rotation_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: bus
-//|
-//| The bus being used by the display
+//| bus: Any = ...
+//| """The bus being used by the display"""
//|
//|
STATIC mp_obj_t displayio_display_obj_get_bus(mp_obj_t self_in) {
@@ -428,12 +413,13 @@ const mp_obj_property_t displayio_display_bus_obj = {
};
-//| .. method:: fill_row(y, buffer)
+//| def fill_row(self, y: int, buffer: bytearray) -> Any:
+//| """Extract the pixels from a single row
//|
-//| 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 int y: The top edge of the area
-//| :param bytearray 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) {
enum { ARG_y, ARG_buffer };
static const mp_arg_t allowed_args[] = {
diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h
index b82a68ebe..e69c5b6b5 100644
--- a/shared-bindings/displayio/Display.h
+++ b/shared-bindings/displayio/Display.h
@@ -41,11 +41,11 @@ extern const mp_obj_type_t displayio_display_type;
void common_hal_displayio_display_construct(displayio_display_obj_t* self,
mp_obj_t bus, uint16_t width, uint16_t height,
int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t color_depth, bool grayscale,
- bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte,
+ bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte, bool reverse_bytes_in_word,
uint8_t set_column_command, uint8_t set_row_command, uint8_t write_ram_command, uint8_t set_vertical_scroll,
uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin, uint16_t brightness_command,
mp_float_t brightness, bool auto_brightness,
- bool single_byte_bounds, bool data_as_commands, bool auto_refresh, uint16_t native_frames_per_second);
+ bool single_byte_bounds, bool data_as_commands, bool auto_refresh, uint16_t native_frames_per_second, bool backlight_on_high);
bool common_hal_displayio_display_show(displayio_display_obj_t* self,
displayio_group_t* root_group);
diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c
index 81e06f82f..8b77e4df3 100644
--- a/shared-bindings/displayio/EPaperDisplay.c
+++ b/shared-bindings/displayio/EPaperDisplay.c
@@ -39,55 +39,53 @@
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class EPaperDisplay:
+//| """Manage updating an epaper display over a display bus
//|
-//| :class:`EPaperDisplay` -- Manage updating an epaper display over a display bus
-//| ==============================================================================
+//| This initializes an epaper display and connects it into CircuitPython. Unlike other
+//| objects in CircuitPython, EPaperDisplay objects live until `displayio.release_displays()`
+//| is called. This is done so that CircuitPython can use the display itself.
//|
-//| This initializes an epaper display and connects it into CircuitPython. Unlike other
-//| objects in CircuitPython, EPaperDisplay objects live until `displayio.release_displays()`
-//| is called. This is done so that CircuitPython can use the display itself.
+//| Most people should not use this class directly. Use a specific display driver instead that will
+//| contain the startup and shutdown sequences at minimum."""
//|
-//| Most people should not use this class directly. Use a specific display driver instead that will
-//| contain the startup and shutdown sequences at minimum.
+//| def __init__(self, display_bus: Any, start_sequence: buffer, stop_sequence: buffer, *, width: int, height: int, ram_width: int, ram_height: int, colstart: int = 0, rowstart: int = 0, rotation: int = 0, set_column_window_command: int = None, set_row_window_command: int = None, single_byte_bounds: Any = False, write_black_ram_command: int, black_bits_inverted: bool = False, write_color_ram_command: int = None, color_bits_inverted: bool = False, highlight_color: int = 0x000000, refresh_display_command: int, refresh_time: float = 40, busy_pin: microcontroller.Pin = None, busy_state: bool = True, seconds_per_frame: float = 180, always_toggle_chip_select: bool = False):
+//| """Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
//|
-//| .. class:: EPaperDisplay(display_bus, start_sequence, stop_sequence, *, width, height, ram_width, ram_height, colstart=0, rowstart=0, rotation=0, set_column_window_command=None, set_row_window_command=None, single_byte_bounds=False, write_black_ram_command, black_bits_inverted=False, write_color_ram_command=None, color_bits_inverted=False, highlight_color=0x000000, refresh_display_command, refresh_time=40, busy_pin=None, busy_state=True, seconds_per_frame=180, always_toggle_chip_select=False)
+//| The ``start_sequence`` and ``stop_sequence`` are bitpacked to minimize the ram impact. Every
+//| command begins with a command byte followed by a byte to determine the parameter count and if
+//| a delay is need after. When the top bit of the second byte is 1, the next byte will be the
+//| delay time in milliseconds. The remaining 7 bits are the parameter count excluding any delay
+//| byte. The third through final bytes are the remaining command parameters. The next byte will
+//| begin a new command definition.
//|
-//| Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
-//|
-//| The ``start_sequence`` and ``stop_sequence`` are bitpacked to minimize the ram impact. Every
-//| command begins with a command byte followed by a byte to determine the parameter count and if
-//| a delay is need after. When the top bit of the second byte is 1, the next byte will be the
-//| delay time in milliseconds. The remaining 7 bits are the parameter count excluding any delay
-//| byte. The third through final bytes are the remaining command parameters. The next byte will
-//| 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.
-//| :param int width: Width in pixels
-//| :param int height: Height in pixels
-//| :param int ram_width: RAM width in pixels
-//| :param int ram_height: RAM height in pixels
-//| :param int colstart: The index if the first visible column
-//| :param int rowstart: The index if the first visible row
-//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)
-//| :param int set_column_window_command: Command used to set the start and end columns to update
-//| :param int set_row_window_command: Command used so set the start and end rows to update
-//| :param int set_current_column_command: Command used to set the current column location
-//| :param int set_current_row_command: Command used to set the current row location
-//| :param int write_black_ram_command: Command used to write pixels values into the update region
-//| :param bool black_bits_inverted: True if 0 bits are used to show black pixels. Otherwise, 1 means to show black.
-//| :param int write_color_ram_command: Command used to write pixels values into the update region
-//| :param bool color_bits_inverted: True if 0 bits are used to show the color. Otherwise, 1 means to show color.
-//| :param int highlight_color: RGB888 of source color to highlight with third ePaper color.
-//| :param int refresh_display_command: Command used to start a display refresh
-//| :param float refresh_time: Time it takes to refresh the display before the stop_sequence should be sent. Ignored when busy_pin is provided.
-//| :param microcontroller.Pin busy_pin: Pin used to signify the display is busy
-//| :param bool busy_state: State of the busy pin when the display is busy
-//| :param float seconds_per_frame: Minimum number of seconds between screen refreshes
-//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte
+//| :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.
+//| :param int width: Width in pixels
+//| :param int height: Height in pixels
+//| :param int ram_width: RAM width in pixels
+//| :param int ram_height: RAM height in pixels
+//| :param int colstart: The index if the first visible column
+//| :param int rowstart: The index if the first visible row
+//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)
+//| :param int set_column_window_command: Command used to set the start and end columns to update
+//| :param int set_row_window_command: Command used so set the start and end rows to update
+//| :param int set_current_column_command: Command used to set the current column location
+//| :param int set_current_row_command: Command used to set the current row location
+//| :param int write_black_ram_command: Command used to write pixels values into the update region
+//| :param bool black_bits_inverted: True if 0 bits are used to show black pixels. Otherwise, 1 means to show black.
+//| :param int write_color_ram_command: Command used to write pixels values into the update region
+//| :param bool color_bits_inverted: True if 0 bits are used to show the color. Otherwise, 1 means to show color.
+//| :param int highlight_color: RGB888 of source color to highlight with third ePaper color.
+//| :param int refresh_display_command: Command used to start a display refresh
+//| :param float refresh_time: Time it takes to refresh the display before the stop_sequence should be sent. Ignored when busy_pin is provided.
+//| :param microcontroller.Pin busy_pin: Pin used to signify the display is busy
+//| :param bool busy_state: State of the busy pin when the display is busy
+//| :param float seconds_per_frame: Minimum number of seconds between screen refreshes
+//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte"""
+//| ...
//|
STATIC mp_obj_t displayio_epaperdisplay_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_display_bus, ARG_start_sequence, ARG_stop_sequence, ARG_width, ARG_height, ARG_ram_width, ARG_ram_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_set_column_window_command, ARG_set_row_window_command, ARG_set_current_column_command, ARG_set_current_row_command, ARG_write_black_ram_command, ARG_black_bits_inverted, ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color, ARG_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state, ARG_seconds_per_frame, ARG_always_toggle_chip_select };
@@ -129,30 +127,15 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size
mp_get_buffer_raise(args[ARG_stop_sequence].u_obj, &stop_bufinfo, MP_BUFFER_READ);
- mp_obj_t busy_pin_obj = args[ARG_busy_pin].u_obj;
- assert_pin(busy_pin_obj, true);
- const mcu_pin_obj_t* busy_pin = NULL;
- if (busy_pin_obj != NULL && busy_pin_obj != mp_const_none) {
- busy_pin = MP_OBJ_TO_PTR(busy_pin_obj);
- assert_pin_free(busy_pin);
- }
+ const mcu_pin_obj_t* busy_pin = validate_obj_is_free_pin_or_none(args[ARG_busy_pin].u_obj);
mp_int_t rotation = args[ARG_rotation].u_int;
if (rotation % 90 != 0) {
mp_raise_ValueError(translate("Display rotation must be in 90 degree increments"));
}
- displayio_epaperdisplay_obj_t *self = NULL;
- for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].display.base.type == NULL ||
- displays[i].display.base.type == &mp_type_NoneType) {
- self = &displays[i].epaper_display;
- break;
- }
- }
- if (self == NULL) {
- mp_raise_RuntimeError(translate("Too many displays"));
- }
+ primary_display_t *disp = allocate_display_or_raise();
+ displayio_epaperdisplay_obj_t *self = &disp->epaper_display;;
mp_float_t refresh_time = mp_obj_get_float(args[ARG_refresh_time].u_obj);
mp_float_t seconds_per_frame = mp_obj_get_float(args[ARG_seconds_per_frame].u_obj);
@@ -185,12 +168,13 @@ static displayio_epaperdisplay_obj_t* native_display(mp_obj_t display_obj) {
return MP_OBJ_TO_PTR(native_display);
}
-//| .. method:: show(group)
+//| def show(self, group: Group) -> Any:
+//| """Switches to displaying the given group of layers. When group is None, the default
+//| CircuitPython terminal will be shown.
//|
-//| Switches to displaying the given group of layers. When group is None, the default
-//| CircuitPython terminal will be shown.
+//| :param Group group: The group to show."""
+//| ...
//|
-//| :param Group group: The group to show.
STATIC mp_obj_t displayio_epaperdisplay_obj_show(mp_obj_t self_in, mp_obj_t group_in) {
displayio_epaperdisplay_obj_t *self = native_display(self_in);
displayio_group_t* group = NULL;
@@ -206,10 +190,10 @@ STATIC mp_obj_t displayio_epaperdisplay_obj_show(mp_obj_t self_in, mp_obj_t grou
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_epaperdisplay_show_obj, displayio_epaperdisplay_obj_show);
-//| .. method:: refresh()
-//|
-//| Refreshes the display immediately or raises an exception if too soon. Use
-//| ``time.sleep(display.time_to_refresh)`` to sleep until a refresh can occur.
+//| def refresh(self, ) -> Any:
+//| """Refreshes the display immediately or raises an exception if too soon. Use
+//| ``time.sleep(display.time_to_refresh)`` to sleep until a refresh can occur."""
+//| ...
//|
STATIC mp_obj_t displayio_epaperdisplay_obj_refresh(mp_obj_t self_in) {
displayio_epaperdisplay_obj_t *self = native_display(self_in);
@@ -221,10 +205,8 @@ STATIC mp_obj_t displayio_epaperdisplay_obj_refresh(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_refresh_obj, displayio_epaperdisplay_obj_refresh);
-//| .. attribute:: time_to_refresh
-//|
-//| Time, in fractional seconds, until the ePaper display can be refreshed.
-//|
+//| time_to_refresh: Any = ...
+//| """Time, in fractional seconds, until the ePaper display can be refreshed."""
//|
STATIC mp_obj_t displayio_epaperdisplay_obj_get_time_to_refresh(mp_obj_t self_in) {
displayio_epaperdisplay_obj_t *self = native_display(self_in);
@@ -239,10 +221,8 @@ const mp_obj_property_t displayio_epaperdisplay_time_to_refresh_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: width
-//|
-//| Gets the width of the display in pixels
-//|
+//| width: Any = ...
+//| """Gets the width of the display in pixels"""
//|
STATIC mp_obj_t displayio_epaperdisplay_obj_get_width(mp_obj_t self_in) {
displayio_epaperdisplay_obj_t *self = native_display(self_in);
@@ -257,10 +237,8 @@ const mp_obj_property_t displayio_epaperdisplay_width_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: height
-//|
-//| Gets the height of the display in pixels
-//|
+//| height: Any = ...
+//| """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);
@@ -275,10 +253,8 @@ const mp_obj_property_t displayio_epaperdisplay_height_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: bus
-//|
-//| The bus being used by the display
-//|
+//| bus: Any = ...
+//| """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/FourWire.c b/shared-bindings/displayio/FourWire.c
index 51203d460..5ee4ec5a9 100644
--- a/shared-bindings/displayio/FourWire.c
+++ b/shared-bindings/displayio/FourWire.c
@@ -38,75 +38,68 @@
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class FourWire:
+//| """Manage updating a display over SPI four wire protocol in the background while Python code runs.
+//| It doesn't handle display initialization."""
//|
-//| :class:`FourWire` -- Manage updating a display over SPI four wire protocol
-//| ==========================================================================
+//| def __init__(self, spi_bus: busio.SPI, *, command: microcontroller.Pin, chip_select: microcontroller.Pin, reset: microcontroller.Pin = None, baudrate: int = 24000000, polarity: int = 0, phase: int = 0):
+//| """Create a FourWire object associated with the given pins.
//|
-//| Manage updating a display over SPI four wire protocol in the background while Python code runs.
-//| It doesn't handle display initialization.
+//| The SPI bus and pins are then in use by the display until `displayio.release_displays()` is
+//| called even after a reload. (It does this so CircuitPython can use the display after your code
+//| is done.) So, the first time you initialize a display bus in code.py you should call
+//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
//|
-//| .. class:: FourWire(spi_bus, *, command, chip_select, reset=None, baudrate=24000000)
-//|
-//| Create a FourWire object associated with the given pins.
-//|
-//| The SPI bus and pins are then in use by the display until `displayio.release_displays()` is
-//| called even after a reload. (It does this so CircuitPython can use the display after your code
-//| is done.) So, the first time you initialize a display bus in code.py you should call
-//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
-//|
-//| :param busio.SPI spi_bus: The SPI bus that make up the clock and data lines
-//| :param microcontroller.Pin command: Data or command pin
-//| :param microcontroller.Pin chip_select: Chip select pin
-//| :param microcontroller.Pin reset: Reset pin. When None only software reset can be used
-//| :param int baudrate: Maximum baudrate in Hz for the display on the bus
+//| :param busio.SPI spi_bus: The SPI bus that make up the clock and data lines
+//| :param microcontroller.Pin command: Data or command pin
+//| :param microcontroller.Pin chip_select: Chip select pin
+//| :param microcontroller.Pin reset: Reset pin. When None only software reset can be used
+//| :param int baudrate: Maximum baudrate in Hz for the display on the bus
+//| :param int polarity: the base state of the clock line (0 or 1)
+//| :param int phase: the edge of the clock that data is captured. First (0)
+//| or second (1). Rising or falling depends on clock polarity."""
+//| ...
//|
STATIC mp_obj_t displayio_fourwire_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_command, ARG_chip_select, ARG_reset, ARG_baudrate };
+ enum { ARG_spi_bus, ARG_command, ARG_chip_select, ARG_reset, ARG_baudrate, ARG_polarity, ARG_phase };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_spi_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_command, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_chip_select, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_reset, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
{ MP_QSTR_baudrate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 24000000} },
+ { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_obj_t command = args[ARG_command].u_obj;
- mp_obj_t chip_select = args[ARG_chip_select].u_obj;
- assert_pin_free(command);
- assert_pin_free(chip_select);
- mp_obj_t reset = args[ARG_reset].u_obj;
- if (reset != mp_const_none) {
- assert_pin_free(reset);
- } else {
- reset = NULL;
- }
+ mcu_pin_obj_t *command = validate_obj_is_free_pin(args[ARG_command].u_obj);
+ mcu_pin_obj_t *chip_select = validate_obj_is_free_pin(args[ARG_chip_select].u_obj);
+ mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj);
- displayio_fourwire_obj_t* self = NULL;
mp_obj_t spi = args[ARG_spi_bus].u_obj;
- for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].fourwire_bus.base.type == NULL ||
- displays[i].fourwire_bus.base.type == &mp_type_NoneType) {
- self = &displays[i].fourwire_bus;
- self->base.type = &displayio_fourwire_type;
- break;
- }
+ displayio_fourwire_obj_t* self = &allocate_display_bus_or_raise()->fourwire_bus;
+ self->base.type = &displayio_fourwire_type;
+
+ uint8_t polarity = args[ARG_polarity].u_int;
+ if (polarity != 0 && polarity != 1) {
+ mp_raise_ValueError(translate("Invalid polarity"));
}
- if (self == NULL) {
- mp_raise_RuntimeError(translate("Too many display busses"));
+ uint8_t phase = args[ARG_phase].u_int;
+ if (phase != 0 && phase != 1) {
+ mp_raise_ValueError(translate("Invalid phase"));
}
common_hal_displayio_fourwire_construct(self,
- MP_OBJ_TO_PTR(spi), command, chip_select, reset, args[ARG_baudrate].u_int);
+ MP_OBJ_TO_PTR(spi), command, chip_select, reset, args[ARG_baudrate].u_int, polarity, phase);
return self;
}
-//| .. method:: reset()
-//|
-//| Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
-//| is available.
+//| def reset(self, ) -> Any:
+//| """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
+//| is available."""
+//| ...
//|
STATIC mp_obj_t displayio_fourwire_obj_reset(mp_obj_t self_in) {
displayio_fourwire_obj_t *self = self_in;
@@ -118,10 +111,10 @@ STATIC mp_obj_t displayio_fourwire_obj_reset(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_fourwire_reset_obj, displayio_fourwire_obj_reset);
-//| .. method:: send(command, data, *, toggle_every_byte=False)
-//|
-//| Sends the given command value followed by the full set of data. Display state, such as
-//| vertical scroll, set via ``send`` may or may not be reset once the code is done.
+//| def send(self, command: Any, data: Any, *, toggle_every_byte: Any = False) -> Any:
+//| """Sends the given command value followed by the full set of data. Display state, such as
+//| vertical scroll, set via ``send`` may or may not be reset once the code is done."""
+//| ...
//|
STATIC mp_obj_t displayio_fourwire_obj_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_command, ARG_data, ARG_toggle_every_byte };
diff --git a/shared-bindings/displayio/FourWire.h b/shared-bindings/displayio/FourWire.h
index d0935f063..ac186d2c3 100644
--- a/shared-bindings/displayio/FourWire.h
+++ b/shared-bindings/displayio/FourWire.h
@@ -38,7 +38,8 @@ extern const mp_obj_type_t displayio_fourwire_type;
void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self,
busio_spi_obj_t* spi, const mcu_pin_obj_t* command,
- const mcu_pin_obj_t* chip_select, const mcu_pin_obj_t* reset, uint32_t baudrate);
+ const mcu_pin_obj_t* chip_select, const mcu_pin_obj_t* reset, uint32_t baudrate,
+ uint8_t polarity, uint8_t phase);
void common_hal_displayio_fourwire_deinit(displayio_fourwire_obj_t* self);
diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c
index dd7600eb9..b6f96883b 100644
--- a/shared-bindings/displayio/Group.c
+++ b/shared-bindings/displayio/Group.c
@@ -35,22 +35,18 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class Group:
+//| """Manage a group of sprites and groups and how they are inter-related."""
//|
-//| :class:`Group` -- Group together sprites and subgroups
-//| ==========================================================================
+//| def __init__(self, *, max_size: int = 4, scale: int = 1, x: int = 0, y: int = 0):
+//| """Create a Group of a given size and scale. Scale is in one dimension. For example, scale=2
+//| leads to a layer's pixel being 2x2 pixels when in the group.
//|
-//| Manage a group of sprites and groups and how they are inter-related.
-//|
-//| .. class:: Group(*, max_size=4, scale=1, x=0, y=0)
-//|
-//| Create a Group of a given size and scale. Scale is in one dimension. For example, scale=2
-//| leads to a layer's pixel being 2x2 pixels when in the group.
-//|
-//| :param int max_size: The maximum group size.
-//| :param int scale: Scale of layer pixels in one dimension.
-//| :param int x: Initial x position within the parent.
-//| :param int y: Initial y position within the parent.
+//| :param int max_size: The maximum group size.
+//| :param int scale: Scale of layer pixels in one dimension.
+//| :param int x: Initial x position within the parent.
+//| :param int y: Initial y position within the parent."""
+//| ...
//|
STATIC mp_obj_t displayio_group_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_max_size, ARG_scale, ARG_x, ARG_y };
@@ -90,10 +86,9 @@ displayio_group_t* native_group(mp_obj_t group_obj) {
return MP_OBJ_TO_PTR(native_group);
}
-//| .. attribute:: hidden
-//|
-//| True when the Group and all of it's layers are not visible. When False, the Group's layers
-//| are visible if they haven't been hidden.
+//| hidden: Any = ...
+//| """True when the Group and all of it's layers are not visible. When False, the Group's layers
+//| are visible if they haven't been hidden."""
//|
STATIC mp_obj_t displayio_group_obj_get_hidden(mp_obj_t self_in) {
displayio_group_t *self = native_group(self_in);
@@ -116,10 +111,9 @@ const mp_obj_property_t displayio_group_hidden_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: scale
-//|
-//| Scales each pixel within the Group in both directions. For example, when scale=2 each pixel
-//| will be represented by 2x2 pixels.
+//| scale: Any = ...
+//| """Scales each pixel within the Group in both directions. For example, when scale=2 each pixel
+//| will be represented by 2x2 pixels."""
//|
STATIC mp_obj_t displayio_group_obj_get_scale(mp_obj_t self_in) {
displayio_group_t *self = native_group(self_in);
@@ -146,9 +140,8 @@ const mp_obj_property_t displayio_group_scale_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: x
-//|
-//| X position of the Group in the parent.
+//| x: Any = ...
+//| """X position of the Group in the parent."""
//|
STATIC mp_obj_t displayio_group_obj_get_x(mp_obj_t self_in) {
displayio_group_t *self = native_group(self_in);
@@ -172,9 +165,8 @@ const mp_obj_property_t displayio_group_x_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: y
-//|
-//| Y position of the Group in the parent.
+//| y: Any = ...
+//| """Y position of the Group in the parent."""
//|
STATIC mp_obj_t displayio_group_obj_get_y(mp_obj_t self_in) {
displayio_group_t *self = native_group(self_in);
@@ -198,9 +190,9 @@ const mp_obj_property_t displayio_group_y_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: append(layer)
-//|
-//| Append a layer to the group. It will be drawn above other layers.
+//| def append(self, layer: Any) -> Any:
+//| """Append a layer to the group. It will be drawn above other layers."""
+//| ...
//|
STATIC mp_obj_t displayio_group_obj_append(mp_obj_t self_in, mp_obj_t layer) {
displayio_group_t *self = native_group(self_in);
@@ -209,9 +201,9 @@ 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);
-//| .. method:: insert(index, layer)
-//|
-//| Insert a layer into the group.
+//| def insert(self, index: Any, layer: Any) -> Any:
+//| """Insert a layer into the group."""
+//| ...
//|
STATIC mp_obj_t displayio_group_obj_insert(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t layer) {
displayio_group_t *self = native_group(self_in);
@@ -222,9 +214,9 @@ 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);
-//| .. method:: index(layer)
-//|
-//| Returns the index of the first copy of layer. Raises ValueError if not found.
+//| def index(self, layer: Any) -> Any:
+//| """Returns the index of the first copy of layer. Raises ValueError if not found."""
+//| ...
//|
STATIC mp_obj_t displayio_group_obj_index(mp_obj_t self_in, mp_obj_t layer) {
displayio_group_t *self = native_group(self_in);
@@ -236,9 +228,9 @@ 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);
-//| .. method:: pop(i=-1)
-//|
-//| Remove the ith item and return it.
+//| def pop(self, i: Any = -1) -> Any:
+//| """Remove the ith item and return it."""
+//| ...
//|
STATIC mp_obj_t displayio_group_obj_pop(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_i };
@@ -259,9 +251,9 @@ 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);
-//| .. method:: remove(layer)
-//|
-//| Remove the first copy of layer. Raises ValueError if it is not present.
+//| def remove(self, layer: Any) -> Any:
+//| """Remove the first copy of layer. Raises ValueError if it is not present."""
+//| ...
//|
STATIC mp_obj_t displayio_group_obj_remove(mp_obj_t self_in, mp_obj_t layer) {
mp_obj_t index = displayio_group_obj_index(self_in, layer);
@@ -272,9 +264,9 @@ STATIC mp_obj_t displayio_group_obj_remove(mp_obj_t self_in, mp_obj_t layer) {
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_remove_obj, displayio_group_obj_remove);
-//| .. method:: __len__()
-//|
-//| Returns the number of layers in a Group
+//| def __len__(self, ) -> Any:
+//| """Returns the number of layers in a Group"""
+//| ...
//|
STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
displayio_group_t *self = native_group(self_in);
@@ -286,29 +278,29 @@ STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//| .. method:: __getitem__(index)
-//|
-//| Returns the value at the given index.
-//|
-//| This allows you to::
-//|
-//| print(group[0])
+//| def __getitem__(self, index: Any) -> Any:
+//| """Returns the value at the given index.
//|
-//| .. method:: __setitem__(index, value)
+//| This allows you to::
//|
-//| Sets the value at the given index.
+//| print(group[0])"""
+//| ...
//|
-//| This allows you to::
+//| def __setitem__(self, index: Any, value: Any) -> Any:
+//| """Sets the value at the given index.
//|
-//| group[0] = sprite
+//| This allows you to::
//|
-//| .. method:: __delitem__(index)
+//| group[0] = sprite"""
+//| ...
//|
-//| Deletes the value at the given index.
+//| def __delitem__(self, index: Any) -> Any:
+//| """Deletes the value at the given index.
//|
-//| This allows you to::
+//| This allows you to::
//|
-//| del group[0]
+//| del group[0]"""
+//| ...
//|
STATIC mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) {
displayio_group_t *self = native_group(self_in);
diff --git a/shared-bindings/displayio/I2CDisplay.c b/shared-bindings/displayio/I2CDisplay.c
index 9b863f656..0cfac6672 100644
--- a/shared-bindings/displayio/I2CDisplay.c
+++ b/shared-bindings/displayio/I2CDisplay.c
@@ -38,26 +38,22 @@
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class I2CDisplay:
+//| """Manage updating a display over I2C in the background while Python code runs.
+//| It doesn't handle display initialization."""
//|
-//| :class:`I2CDisplay` -- Manage updating a display over I2C
-//| ==========================================================================
+//| def __init__(self, i2c_bus: busio.I2C, *, device_address: int, reset: microcontroller.Pin = None):
+//| """Create a I2CDisplay object associated with the given I2C bus and reset pin.
//|
-//| Manage updating a display over I2C in the background while Python code runs.
-//| It doesn't handle display initialization.
+//| The I2C bus and pins are then in use by the display until `displayio.release_displays()` is
+//| called even after a reload. (It does this so CircuitPython can use the display after your code
+//| is done.) So, the first time you initialize a display bus in code.py you should call
+//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
//|
-//| .. class:: I2CDisplay(i2c_bus, *, device_address, reset=None)
-//|
-//| Create a I2CDisplay object associated with the given I2C bus and reset pin.
-//|
-//| The I2C bus and pins are then in use by the display until `displayio.release_displays()` is
-//| called even after a reload. (It does this so CircuitPython can use the display after your code
-//| is done.) So, the first time you initialize a display bus in code.py you should call
-//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
-//|
-//| :param busio.I2C i2c_bus: The I2C bus that make up the clock and data lines
-//| :param int device_address: The I2C address of the device
-//| :param microcontroller.Pin reset: Reset pin. When None only software reset can be used
+//| :param busio.I2C i2c_bus: The I2C bus that make up the clock and data lines
+//| :param int device_address: The I2C address of the device
+//| :param microcontroller.Pin reset: Reset pin. When None only software reset can be used"""
+//| ...
//|
STATIC mp_obj_t displayio_i2cdisplay_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_i2c_bus, ARG_device_address, ARG_reset };
@@ -69,36 +65,21 @@ STATIC mp_obj_t displayio_i2cdisplay_make_new(const mp_obj_type_t *type, size_t
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_obj_t reset = args[ARG_reset].u_obj;
- if (reset != mp_const_none) {
- assert_pin_free(reset);
- } else {
- reset = NULL;
- }
+ mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj);
- displayio_i2cdisplay_obj_t* self = NULL;
mp_obj_t i2c = args[ARG_i2c_bus].u_obj;
- for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].i2cdisplay_bus.base.type == NULL ||
- displays[i].i2cdisplay_bus.base.type == &mp_type_NoneType) {
- self = &displays[i].i2cdisplay_bus;
- self->base.type = &displayio_i2cdisplay_type;
- break;
- }
- }
- if (self == NULL) {
- mp_raise_RuntimeError(translate("Too many display busses"));
- }
+ displayio_i2cdisplay_obj_t* self = &allocate_display_bus_or_raise()->i2cdisplay_bus;
+ self->base.type = &displayio_i2cdisplay_type;
common_hal_displayio_i2cdisplay_construct(self,
MP_OBJ_TO_PTR(i2c), args[ARG_device_address].u_int, reset);
return self;
}
-//| .. method:: reset()
-//|
-//| Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
-//| is available.
+//| def reset(self, ) -> Any:
+//| """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
+//| is available."""
+//| ...
//|
STATIC mp_obj_t displayio_i2cdisplay_obj_reset(mp_obj_t self_in) {
displayio_i2cdisplay_obj_t *self = self_in;
@@ -110,10 +91,10 @@ STATIC mp_obj_t displayio_i2cdisplay_obj_reset(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_i2cdisplay_reset_obj, displayio_i2cdisplay_obj_reset);
-//| .. method:: send(command, data)
-//|
-//| Sends the given command value followed by the full set of data. Display state, such as
-//| vertical scroll, set via ``send`` may or may not be reset once the code is done.
+//| def send(self, command: Any, data: Any) -> Any:
+//| """Sends the given command value followed by the full set of data. Display state, such as
+//| vertical scroll, set via ``send`` may or may not be reset once the code is done."""
+//| ...
//|
STATIC mp_obj_t displayio_i2cdisplay_obj_send(mp_obj_t self, mp_obj_t command_obj, mp_obj_t data_obj) {
mp_int_t command_int = MP_OBJ_SMALL_INT_VALUE(command_obj);
diff --git a/shared-bindings/displayio/OnDiskBitmap.c b/shared-bindings/displayio/OnDiskBitmap.c
index 57179947e..170873653 100644
--- a/shared-bindings/displayio/OnDiskBitmap.c
+++ b/shared-bindings/displayio/OnDiskBitmap.c
@@ -33,51 +33,47 @@
#include "supervisor/shared/translate.h"
#include "shared-bindings/displayio/OnDiskBitmap.h"
-//| .. currentmodule:: displayio
+//| class OnDiskBitmap:
+//| """Loads values straight from disk. This minimizes memory use but can lead to
+//| much slower pixel load times. These load times may result in frame tearing where only part of
+//| the image is visible.
//|
-//| :class:`OnDiskBitmap` -- Loads pixels straight from disk
-//| ==========================================================================
+//| It's easiest to use on a board with a built in display such as the `Hallowing M0 Express
+//| <https://www.adafruit.com/product/3900>`_.
//|
-//| Loads values straight from disk. This minimizes memory use but can lead to
-//| much slower pixel load times. These load times may result in frame tearing where only part of
-//| the image is visible.
+//| .. code-block:: Python
//|
-//| It's easiest to use on a board with a built in display such as the `Hallowing M0 Express
-//| <https://www.adafruit.com/product/3900>`_.
+//| import board
+//| import displayio
+//| import time
+//| import pulseio
//|
-//| .. code-block:: Python
+//| board.DISPLAY.auto_brightness = False
+//| board.DISPLAY.brightness = 0
+//| splash = displayio.Group()
+//| board.DISPLAY.show(splash)
//|
-//| import board
-//| import displayio
-//| import time
-//| import pulseio
+//| with open("/sample.bmp", "rb") as f:
+//| odb = displayio.OnDiskBitmap(f)
+//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter())
+//| splash.append(face)
+//| # Wait for the image to load.
+//| board.DISPLAY.refresh(target_frames_per_second=60)
//|
-//| board.DISPLAY.auto_brightness = False
-//| board.DISPLAY.brightness = 0
-//| splash = displayio.Group()
-//| board.DISPLAY.show(splash)
+//| # Fade up the backlight
+//| for i in range(100):
+//| board.DISPLAY.brightness = 0.01 * i
+//| time.sleep(0.05)
//|
-//| with open("/sample.bmp", "rb") as f:
-//| odb = displayio.OnDiskBitmap(f)
-//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter())
-//| splash.append(face)
-//| # Wait for the image to load.
-//| board.DISPLAY.refresh(target_frames_per_second=60)
+//| # Wait forever
+//| while True:
+//| pass"""
//|
-//| # Fade up the backlight
-//| for i in range(100):
-//| board.DISPLAY.brightness = 0.01 * i
-//| time.sleep(0.05)
+//| def __init__(self, file: file):
+//| """Create an OnDiskBitmap object with the given file.
//|
-//| # Wait forever
-//| while True:
-//| pass
-//|
-//| .. class:: OnDiskBitmap(file)
-//|
-//| Create an OnDiskBitmap object with the given file.
-//|
-//| :param file file: The open bitmap file
+//| :param file file: The open bitmap file"""
+//| ...
//|
STATIC mp_obj_t displayio_ondiskbitmap_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 1, 1, false);
@@ -93,9 +89,8 @@ STATIC mp_obj_t displayio_ondiskbitmap_make_new(const mp_obj_type_t *type, size_
return MP_OBJ_FROM_PTR(self);
}
-//| .. attribute:: width
-//|
-//| Width of the bitmap. (read only)
+//| width: Any = ...
+//| """Width of the bitmap. (read only)"""
//|
STATIC mp_obj_t displayio_ondiskbitmap_obj_get_width(mp_obj_t self_in) {
displayio_ondiskbitmap_t *self = MP_OBJ_TO_PTR(self_in);
@@ -113,9 +108,8 @@ const mp_obj_property_t displayio_ondiskbitmap_width_obj = {
};
-//| .. attribute:: height
-//|
-//| Height of the bitmap. (read only)
+//| height: Any = ...
+//| """Height of the bitmap. (read only)"""
//|
STATIC mp_obj_t displayio_ondiskbitmap_obj_get_height(mp_obj_t self_in) {
displayio_ondiskbitmap_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/displayio/Palette.c b/shared-bindings/displayio/Palette.c
index 67a7db85b..37cfbd82e 100644
--- a/shared-bindings/displayio/Palette.c
+++ b/shared-bindings/displayio/Palette.c
@@ -36,19 +36,22 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
-//|
-//| :class:`Palette` -- Stores a mapping from bitmap pixel palette_indexes to display colors
-//| =========================================================================================
-//|
-//| Map a pixel palette_index to a full color. Colors are transformed to the display's format internally to
-//| save memory.
+
+
+
+
+
+
+//| class Palette:
+//| """Map a pixel palette_index to a full color. Colors are transformed to the display's format internally to
+//| save memory."""
//|
-//| .. class:: Palette(color_count)
+//| def __init__(self, color_count: int):
+//| """Create a Palette object to store a set number of colors.
//|
-//| Create a Palette object to store a set number of colors.
+//| :param int color_count: The number of colors in the Palette"""
+//| ...
//|
-//| :param int color_count: The number of colors in the Palette
// TODO(tannewt): Add support for other color formats.
// TODO(tannewt): Add support for 8-bit alpha blending.
//|
@@ -67,9 +70,9 @@ STATIC mp_obj_t displayio_palette_make_new(const mp_obj_type_t *type, size_t n_a
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: __len__()
-//|
-//| Returns the number of colors in a Palette
+//| def __len__(self, ) -> Any:
+//| """Returns the number of colors in a Palette"""
+//| ...
//|
STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
displayio_palette_t *self = MP_OBJ_TO_PTR(self_in);
@@ -81,21 +84,21 @@ STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//| .. method:: __setitem__(index, value)
-//|
-//| Sets the pixel color at the given index. The index should be an integer in the range 0 to color_count-1.
+//| def __setitem__(self, index: Any, value: Any) -> Any:
+//| r"""Sets the pixel color at the given index. The index should be an integer in the range 0 to color_count-1.
//|
-//| The value argument represents a color, and can be from 0x000000 to 0xFFFFFF (to represent an RGB value).
-//| Value can be an int, bytes (3 bytes (RGB) or 4 bytes (RGB + pad byte)), bytearray,
-//| or a tuple or list of 3 integers.
+//| The value argument represents a color, and can be from 0x000000 to 0xFFFFFF (to represent an RGB value).
+//| Value can be an int, bytes (3 bytes (RGB) or 4 bytes (RGB + pad byte)), bytearray,
+//| or a tuple or list of 3 integers.
//|
-//| This allows you to::
+//| This allows you to::
//|
-//| palette[0] = 0xFFFFFF # set using an integer
-//| palette[1] = b'\xff\xff\x00' # set using 3 bytes
-//| palette[2] = b'\xff\xff\x00\x00' # set using 4 bytes
-//| palette[3] = bytearray(b'\x00\x00\xFF') # set using a bytearay of 3 or 4 bytes
-//| palette[4] = (10, 20, 30) # set using a tuple of 3 integers
+//| palette[0] = 0xFFFFFF # set using an integer
+//| palette[1] = b'\xff\xff\x00' # set using 3 bytes
+//| palette[2] = b'\xff\xff\x00\x00' # set using 4 bytes
+//| palette[3] = bytearray(b'\x00\x00\xFF') # set using a bytearay of 3 or 4 bytes
+//| palette[4] = (10, 20, 30) # set using a tuple of 3 integers"""
+//| ...
//|
STATIC mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
if (value == MP_OBJ_NULL) {
@@ -144,7 +147,7 @@ STATIC mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val
return mp_const_none;
}
-//| .. method:: make_transparent(palette_index)
+//| def make_transparent(self, palette_index: Any) -> Any: ...
//|
STATIC mp_obj_t displayio_palette_obj_make_transparent(mp_obj_t self_in, mp_obj_t palette_index_obj) {
displayio_palette_t *self = MP_OBJ_TO_PTR(self_in);
@@ -158,7 +161,7 @@ STATIC mp_obj_t displayio_palette_obj_make_transparent(mp_obj_t self_in, mp_obj_
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_palette_make_transparent_obj, displayio_palette_obj_make_transparent);
-//| .. method:: make_opaque(palette_index)
+//| def make_opaque(self, palette_index: Any) -> Any: ...
//|
STATIC mp_obj_t displayio_palette_obj_make_opaque(mp_obj_t self_in, mp_obj_t palette_index_obj) {
displayio_palette_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/displayio/ParallelBus.c b/shared-bindings/displayio/ParallelBus.c
index f7195b9cc..eb75ecc03 100644
--- a/shared-bindings/displayio/ParallelBus.c
+++ b/shared-bindings/displayio/ParallelBus.c
@@ -37,31 +37,27 @@
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class ParallelBus:
+//| """Manage updating a display over 8-bit parallel bus in the background while Python code runs. This
+//| protocol may be refered to as 8080-I Series Parallel Interface in datasheets. It doesn't handle
+//| display initialization."""
//|
-//| :class:`ParallelBus` -- Manage updating a display over 8-bit parallel bus
-//| ==============================================================================
+//| def __init__(self, *, data0: microcontroller.Pin, command: microcontroller.Pin, chip_select: microcontroller.Pin, write: microcontroller.Pin, read: microcontroller.Pin, reset: microcontroller.Pin):
+//| """Create a ParallelBus object associated with the given pins. The bus is inferred from data0
+//| by implying the next 7 additional pins on a given GPIO port.
//|
-//| Manage updating a display over 8-bit parallel bus in the background while Python code runs. This
-//| protocol may be refered to as 8080-I Series Parallel Interface in datasheets. It doesn't handle
-//| display initialization.
+//| The parallel bus and pins are then in use by the display until `displayio.release_displays()`
+//| is called even after a reload. (It does this so CircuitPython can use the display after your
+//| code is done.) So, the first time you initialize a display bus in code.py you should call
+//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
//|
-//| .. class:: ParallelBus(*, data0, command, chip_select, write, read, reset)
-//|
-//| Create a ParallelBus object associated with the given pins. The bus is inferred from data0
-//| by implying the next 7 additional pins on a given GPIO port.
-//|
-//| The parallel bus and pins are then in use by the display until `displayio.release_displays()`
-//| is called even after a reload. (It does this so CircuitPython can use the display after your
-//| code is done.) So, the first time you initialize a display bus in code.py you should call
-//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
-//|
-//| :param microcontroller.Pin data0: The first data pin. The rest are implied
-//| :param microcontroller.Pin command: Data or command pin
-//| :param microcontroller.Pin chip_select: Chip select pin
-//| :param microcontroller.Pin write: Write pin
-//| :param microcontroller.Pin read: Read pin
-//| :param microcontroller.Pin reset: Reset pin
+//| :param microcontroller.Pin data0: The first data pin. The rest are implied
+//| :param microcontroller.Pin command: Data or command pin
+//| :param microcontroller.Pin chip_select: Chip select pin
+//| :param microcontroller.Pin write: Write pin
+//| :param microcontroller.Pin read: Read pin
+//| :param microcontroller.Pin reset: Reset pin"""
+//| ...
//|
STATIC mp_obj_t displayio_parallelbus_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_data0, ARG_command, ARG_chip_select, ARG_write, ARG_read, ARG_reset };
@@ -71,46 +67,31 @@ STATIC mp_obj_t displayio_parallelbus_make_new(const mp_obj_type_t *type, size_t
{ MP_QSTR_chip_select, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_write, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_read, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
- { MP_QSTR_reset, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ { MP_QSTR_reset, MP_ARG_OBJ | MP_ARG_KW_ONLY | 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);
- mp_obj_t data0 = args[ARG_data0].u_obj;
- mp_obj_t command = args[ARG_command].u_obj;
- mp_obj_t chip_select = args[ARG_chip_select].u_obj;
- mp_obj_t write = args[ARG_write].u_obj;
- mp_obj_t read = args[ARG_read].u_obj;
- mp_obj_t reset = args[ARG_reset].u_obj;
- assert_pin_free(data0);
- assert_pin_free(command);
- assert_pin_free(chip_select);
- assert_pin_free(write);
- assert_pin_free(read);
- assert_pin_free(reset);
+ mcu_pin_obj_t *data0 = validate_obj_is_free_pin(args[ARG_data0].u_obj);
+ mcu_pin_obj_t *command = validate_obj_is_free_pin(args[ARG_command].u_obj);
+ mcu_pin_obj_t *chip_select = validate_obj_is_free_pin(args[ARG_chip_select].u_obj);
+ mcu_pin_obj_t *write = validate_obj_is_free_pin(args[ARG_write].u_obj);
+ mcu_pin_obj_t *read = validate_obj_is_free_pin(args[ARG_read].u_obj);
+ mcu_pin_obj_t *reset = validate_obj_is_free_pin(args[ARG_reset].u_obj);
- displayio_parallelbus_obj_t* self = NULL;
- for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].parallel_bus.base.type== NULL ||
- displays[i].parallel_bus.base.type == &mp_type_NoneType) {
- self = &displays[i].parallel_bus;
- self->base.type = &displayio_parallelbus_type;
- break;
- }
- }
- if (self == NULL) {
- mp_raise_RuntimeError(translate("Too many display busses"));
- }
+ displayio_parallelbus_obj_t* self = &allocate_display_bus_or_raise()->parallel_bus;
+ self->base.type = &displayio_parallelbus_type;
common_hal_displayio_parallelbus_construct(self, data0, command, chip_select, write, read, reset);
return self;
}
-//| .. method:: reset()
-//|
-//| Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
-//| is available.
+//| def reset(self, ) -> Any:
+//| """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
+//| is available."""
+//| ...
//|
+
STATIC mp_obj_t displayio_parallelbus_obj_reset(mp_obj_t self_in) {
displayio_parallelbus_obj_t *self = self_in;
@@ -121,10 +102,10 @@ STATIC mp_obj_t displayio_parallelbus_obj_reset(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_parallelbus_reset_obj, displayio_parallelbus_obj_reset);
-//| .. method:: send(command, data)
-//|
-//| Sends the given command value followed by the full set of data. Display state, such as
-//| vertical scroll, set via ``send`` may or may not be reset once the code is done.
+//| def send(self, command: Any, data: Any) -> Any:
+//| """Sends the given command value followed by the full set of data. Display state, such as
+//| vertical scroll, set via ``send`` may or may not be reset once the code is done."""
+//| ...
//|
STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_obj, mp_obj_t data_obj) {
mp_int_t command_int = MP_OBJ_SMALL_INT_VALUE(command_obj);
diff --git a/shared-bindings/displayio/Shape.c b/shared-bindings/displayio/Shape.c
index 7c7b10501..fce89c771 100644
--- a/shared-bindings/displayio/Shape.c
+++ b/shared-bindings/displayio/Shape.c
@@ -34,22 +34,18 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class Shape:
+//| """Represents a shape made by defining boundaries that may be mirrored."""
//|
-//| :class:`Shape` -- Represents a shape by defining its bounds on each row
-//| ==========================================================================
+//| def __init__(self, width: int, height: int, *, mirror_x: bool = False, mirror_y: bool = False):
+//| """Create a Shape object with the given fixed size. Each pixel is one bit and is stored by the
+//| column boundaries of the shape on each row. Each row's boundary defaults to the full row.
//|
-//| Represents any shape made by defining boundaries that may be mirrored.
-//|
-//| .. class:: Shape(width, height, *, mirror_x=False, mirror_y=False)
-//|
-//| Create a Shape object with the given fixed size. Each pixel is one bit and is stored by the
-//| column boundaries of the shape on each row. Each row's boundary defaults to the full row.
-//|
-//| :param int width: The number of pixels wide
-//| :param int height: The number of pixels high
-//| :param bool mirror_x: When true the left boundary is mirrored to the right.
-//| :param bool mirror_y: When true the top boundary is mirrored to the bottom.
+//| :param int width: The number of pixels wide
+//| :param int height: The number of pixels high
+//| :param bool mirror_x: When true the left boundary is mirrored to the right.
+//| :param bool mirror_y: When true the top boundary is mirrored to the bottom."""
+//| ...
//|
STATIC mp_obj_t displayio_shape_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_width, ARG_height, ARG_mirror_x, ARG_mirror_y };
@@ -83,9 +79,9 @@ STATIC mp_obj_t displayio_shape_make_new(const mp_obj_type_t *type, size_t n_arg
}
-//| .. method:: set_boundary(y, start_x, end_x)
-//|
-//| Loads pre-packed data into the given row.
+//| def set_boundary(self, y: Any, start_x: Any, end_x: Any) -> Any:
+//| """Loads pre-packed data into the given row."""
+//| ...
//|
STATIC mp_obj_t displayio_shape_obj_set_boundary(size_t n_args, const mp_obj_t *args) {
(void) n_args;
diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c
index 288eb4b23..01fba46a5 100644
--- a/shared-bindings/displayio/TileGrid.c
+++ b/shared-bindings/displayio/TileGrid.c
@@ -40,33 +40,30 @@
#include "shared-bindings/displayio/Shape.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: displayio
+//| class TileGrid:
+//| """A grid of tiles sourced out of one bitmap
//|
-//| :class:`TileGrid` -- A grid of tiles sourced out of one bitmap
-//| ==========================================================================
+//| Position a grid of tiles sourced from a bitmap and pixel_shader combination. Multiple grids
+//| can share bitmaps and pixel shaders.
//|
-//| Position a grid of tiles sourced from a bitmap and pixel_shader combination. Multiple grids
-//| can share bitmaps and pixel shaders.
+//| A single tile grid is also known as a Sprite."""
//|
-//| A single tile grid is also known as a Sprite.
+//| def __init__(self, bitmap: displayio.Bitmap, *, pixel_shader: displayio.Palette, width: int = 1, height: int = 1, tile_width: int = None, tile_height: int = None, default_tile: int = 0, x: int = 0, y: int = 0):
+//| """Create a TileGrid object. The bitmap is source for 2d pixels. The pixel_shader is used to
+//| convert the value and its location to a display native pixel color. This may be a simple color
+//| palette lookup, a gradient, a pattern or a color transformer.
//|
-//| .. class:: TileGrid(bitmap, *, pixel_shader, width=1, height=1, tile_width=None, tile_height=None, default_tile=0, x=0, y=0)
+//| tile_width and tile_height match the height of the bitmap by default.
//|
-//| Create a TileGrid object. The bitmap is source for 2d pixels. The pixel_shader is used to
-//| convert the value and its location to a display native pixel color. This may be a simple color
-//| palette lookup, a gradient, a pattern or a color transformer.
-//|
-//| tile_width and tile_height match the height of the bitmap by default.
-//|
-//| :param displayio.Bitmap bitmap: The bitmap storing one or more tiles.
-//| :param displayio.Palette pixel_shader: The pixel shader that produces colors from values
-//| :param int width: Width of the grid in tiles.
-//| :param int height: Height of the grid in tiles.
-//| :param int tile_width: Width of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions.
-//| :param int tile_height: Height of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions.
-//| :param int default_tile: Default tile index to show.
-//| :param int x: Initial x position of the left edge within the parent.
-//| :param int y: Initial y position of the top edge within the parent.
+//| :param displayio.Bitmap bitmap: The bitmap storing one or more tiles.
+//| :param displayio.Palette pixel_shader: The pixel shader that produces colors from values
+//| :param int width: Width of the grid in tiles.
+//| :param int height: Height of the grid in tiles.
+//| :param int tile_width: Width of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions.
+//| :param int tile_height: Height of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions.
+//| :param int default_tile: Default tile index to show.
+//| :param int x: Initial x position of the left edge within the parent.
+//| :param int y: Initial y position of the top edge within the parent."""
//|
STATIC mp_obj_t displayio_tilegrid_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_bitmap, ARG_pixel_shader, ARG_width, ARG_height, ARG_tile_width, ARG_tile_height, ARG_default_tile, ARG_x, ARG_y };
@@ -144,9 +141,8 @@ static displayio_tilegrid_t* native_tilegrid(mp_obj_t tilegrid_obj) {
mp_obj_assert_native_inited(native_tilegrid);
return MP_OBJ_TO_PTR(native_tilegrid);
}
-//| .. attribute:: hidden
-//|
-//| True when the TileGrid is hidden. This may be False even when a part of a hidden Group.
+//| hidden: Any = ...
+//| """True when the TileGrid is hidden. This may be False even when a part of a hidden Group."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_hidden(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -169,9 +165,8 @@ const mp_obj_property_t displayio_tilegrid_hidden_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: x
-//|
-//| X position of the left edge in the parent.
+//| x: Any = ...
+//| """X position of the left edge in the parent."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_x(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -195,9 +190,8 @@ const mp_obj_property_t displayio_tilegrid_x_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: y
-//|
-//| Y position of the top edge in the parent.
+//| y: Any = ...
+//| """Y position of the top edge in the parent."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_y(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -221,9 +215,8 @@ const mp_obj_property_t displayio_tilegrid_y_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: flip_x
-//|
-//| If true, the left edge rendered will be the right edge of the right-most tile.
+//| flip_x: Any = ...
+//| """If true, the left edge rendered will be the right edge of the right-most tile."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_flip_x(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -246,9 +239,8 @@ const mp_obj_property_t displayio_tilegrid_flip_x_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: flip_y
-//|
-//| If true, the top edge rendered will be the bottom edge of the bottom-most tile.
+//| flip_y: Any = ...
+//| """If true, the top edge rendered will be the bottom edge of the bottom-most tile."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_flip_y(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -272,10 +264,9 @@ const mp_obj_property_t displayio_tilegrid_flip_y_obj = {
};
-//| .. attribute:: transpose_xy
-//|
-//| If true, the TileGrid's axis will be swapped. When combined with mirroring, any 90 degree
-//| rotation can be achieved along with the corresponding mirrored version.
+//| transpose_xy: Any = ...
+//| """If true, the TileGrid's axis will be swapped. When combined with mirroring, any 90 degree
+//| rotation can be achieved along with the corresponding mirrored version."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_transpose_xy(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -298,9 +289,8 @@ const mp_obj_property_t displayio_tilegrid_transpose_xy_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: pixel_shader
-//|
-//| The pixel shader of the tilegrid.
+//| pixel_shader: Any = ...
+//| """The pixel shader of the tilegrid."""
//|
STATIC mp_obj_t displayio_tilegrid_obj_get_pixel_shader(mp_obj_t self_in) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
@@ -327,27 +317,27 @@ const mp_obj_property_t displayio_tilegrid_pixel_shader_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: __getitem__(index)
-//|
-//| Returns the tile index at the given index. The index can either be an x,y tuple or an int equal
-//| to ``y * width + x``.
-//|
-//| This allows you to::
+//| def __getitem__(self, index: Any) -> Any:
+//| """Returns the tile index at the given index. The index can either be an x,y tuple or an int equal
+//| to ``y * width + x``.
//|
-//| print(grid[0])
+//| This allows you to::
//|
-//| .. method:: __setitem__(index, tile_index)
+//| print(grid[0])"""
+//| ...
//|
-//| Sets the tile index at the given index. The index can either be an x,y tuple or an int equal
-//| to ``y * width + x``.
+//| def __setitem__(self, index: Any, tile_index: Any) -> Any:
+//| """Sets the tile index at the given index. The index can either be an x,y tuple or an int equal
+//| to ``y * width + x``.
//|
-//| This allows you to::
+//| This allows you to::
//|
-//| grid[0] = 10
+//| grid[0] = 10
//|
-//| or::
+//| or::
//|
-//| grid[0,0] = 10
+//| grid[0,0] = 10"""
+//| ...
//|
STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) {
displayio_tilegrid_t *self = native_tilegrid(self_in);
diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c
index f78325593..b791336b5 100644
--- a/shared-bindings/displayio/__init__.c
+++ b/shared-bindings/displayio/__init__.c
@@ -43,44 +43,21 @@
#include "shared-bindings/displayio/Shape.h"
#include "shared-bindings/displayio/TileGrid.h"
-//| :mod:`displayio` --- Native display driving
-//| =========================================================================
-//|
-//| .. module:: displayio
-//| :synopsis: Native helpers for driving displays
-//| :platform: SAMD21, SAMD51, nRF52
+//| """Native helpers for driving displays
//|
//| The `displayio` module contains classes to manage display output
-//| including synchronizing with refresh rates and partial updating.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Bitmap
-//| ColorConverter
-//| Display
-//| EPaperDisplay
-//| FourWire
-//| Group
-//| I2CDisplay
-//| OnDiskBitmap
-//| Palette
-//| ParallelBus
-//| Shape
-//| TileGrid
+//| including synchronizing with refresh rates and partial updating."""
//|
-//| .. function:: release_displays()
-//|
-//| Releases any actively used displays so their busses and pins can be used again. This will also
-//| release the builtin display on boards that have one. You will need to reinitialize it yourself
-//| afterwards. This may take seconds to complete if an active EPaperDisplay is refreshing.
+//| def release_displays() -> Any:
+//| """Releases any actively used displays so their busses and pins can be used again. This will also
+//| release the builtin display on boards that have one. You will need to reinitialize it yourself
+//| afterwards. This may take seconds to complete if an active EPaperDisplay is refreshing.
//|
-//| Use this once in your code.py if you initialize a display. Place it right before the
-//| initialization so the display is active as long as possible.
+//| Use this once in your code.py if you initialize a display. Place it right before the
+//| initialization so the display is active as long as possible."""
+//| ...
//|
STATIC mp_obj_t displayio_release_displays(void) {
common_hal_displayio_release_displays();
diff --git a/shared-bindings/fontio/BuiltinFont.c b/shared-bindings/fontio/BuiltinFont.c
index 74bc4d29e..bf9a65873 100644
--- a/shared-bindings/fontio/BuiltinFont.c
+++ b/shared-bindings/fontio/BuiltinFont.c
@@ -36,25 +36,20 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: fontio
+//| class BuiltinFont:
+//| """A font built into CircuitPython"""
//|
-//| :class:`BuiltinFont` -- A font built into CircuitPython
-//| =========================================================================================
-//|
-//| A font built into CircuitPython.
-//|
-//| .. class:: BuiltinFont()
-//|
-//| Creation not supported. Available fonts are defined when CircuitPython is built. See the
-//| `Adafruit_CircuitPython_Bitmap_Font <https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font>`_
-//| library for dynamically loaded fonts.
+//| def __init__(self, ):
+//| """Creation not supported. Available fonts are defined when CircuitPython is built. See the
+//| `Adafruit_CircuitPython_Bitmap_Font <https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font>`_
+//| library for dynamically loaded fonts."""
+//| ...
//|
-//| .. attribute:: bitmap
-//|
-//| Bitmap containing all font glyphs starting with ASCII and followed by unicode. Use
+//| bitmap: Any = ...
+//| """Bitmap containing all font glyphs starting with ASCII and followed by unicode. Use
//| `get_glyph` in most cases. This is useful for use with `displayio.TileGrid` and
-//| `terminalio.Terminal`.
+//| `terminalio.Terminal`."""
//|
STATIC mp_obj_t fontio_builtinfont_obj_get_bitmap(mp_obj_t self_in) {
fontio_builtinfont_t *self = MP_OBJ_TO_PTR(self_in);
@@ -69,9 +64,9 @@ const mp_obj_property_t fontio_builtinfont_bitmap_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: get_bounding_box()
-//|
-//| Returns the maximum bounds of all glyphs in the font in a tuple of two values: width, height.
+//| def get_bounding_box(self, ) -> Any:
+//| """Returns the maximum bounds of all glyphs in the font in a tuple of two values: width, height."""
+//| ...
//|
STATIC mp_obj_t fontio_builtinfont_obj_get_bounding_box(mp_obj_t self_in) {
fontio_builtinfont_t *self = MP_OBJ_TO_PTR(self_in);
@@ -81,9 +76,9 @@ STATIC mp_obj_t fontio_builtinfont_obj_get_bounding_box(mp_obj_t self_in) {
MP_DEFINE_CONST_FUN_OBJ_1(fontio_builtinfont_get_bounding_box_obj, fontio_builtinfont_obj_get_bounding_box);
-//| .. method:: get_glyph(codepoint)
-//|
-//| Returns a `fontio.Glyph` for the given codepoint or None if no glyph is available.
+//| def get_glyph(self, codepoint: Any) -> Any:
+//| """Returns a `fontio.Glyph` for the given codepoint or None if no glyph is available."""
+//| ...
//|
STATIC mp_obj_t fontio_builtinfont_obj_get_glyph(mp_obj_t self_in, mp_obj_t codepoint_obj) {
fontio_builtinfont_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/fontio/Glyph.c b/shared-bindings/fontio/Glyph.c
index a23284152..6558e2e7a 100644
--- a/shared-bindings/fontio/Glyph.c
+++ b/shared-bindings/fontio/Glyph.c
@@ -28,23 +28,29 @@
#include <stdint.h>
-//| .. currentmodule:: fontio
+//| class Glyph:
+//| """Storage of glyph info"""
//|
-//| :class:`Glyph` -- Storage of glyph info
-//| ==========================================================================
+//| def __init__(self,
+//| bitmap: displayio.Bitmap,
+//| tile_index: int,
+//| width: int,
+//| height: int,
+//| dx: int,
+//| dy: int,
+//| shift_x: int,
+//| shift_y: int):
+//| """Named tuple used to capture a single glyph and its attributes.
//|
-//| .. class:: Glyph(bitmap, tile_index, width, height, dx, dy, shift_x, shift_y)
-//|
-//| Named tuple used to capture a single glyph and its attributes.
-//|
-//| :param displayio.Bitmap bitmap: the bitmap including the glyph
-//| :param int tile_index: the tile index within the bitmap
-//| :param int width: the width of the glyph's bitmap
-//| :param int height: the height of the glyph's bitmap
-//| :param int dx: x adjustment to the bitmap's position
-//| :param int dy: y adjustment to the bitmap's position
-//| :param int shift_x: the x difference to the next glyph
-//| :param int shift_y: the y difference to the next glyph
+//| :param bitmap: the bitmap including the glyph
+//| :param tile_index: the tile index within the bitmap
+//| :param width: the width of the glyph's bitmap
+//| :param height: the height of the glyph's bitmap
+//| :param dx: x adjustment to the bitmap's position
+//| :param dy: y adjustment to the bitmap's position
+//| :param shift_x: the x difference to the next glyph
+//| :param shift_y: the y difference to the next glyph"""
+//| ...
//|
const mp_obj_namedtuple_type_t fontio_glyph_type = {
.base = {
diff --git a/shared-bindings/fontio/__init__.c b/shared-bindings/fontio/__init__.c
index cd0f5ab0f..f376f3503 100644
--- a/shared-bindings/fontio/__init__.c
+++ b/shared-bindings/fontio/__init__.c
@@ -33,22 +33,7 @@
#include "shared-bindings/fontio/BuiltinFont.h"
#include "shared-bindings/fontio/Glyph.h"
-//| :mod:`fontio` --- Core font related data structures
-//| =========================================================================
-//|
-//| .. module:: fontio
-//| :synopsis: Core font related data structures
-//| :platform: SAMD21, SAMD51, nRF52
-//|
-//| The `fontio` module contains classes to store font related information.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| BuiltinFont
-//| Glyph
+//| """Core font related data structures"""
//|
STATIC const mp_rom_map_elem_t fontio_module_globals_table[] = {
diff --git a/shared-bindings/framebufferio/FramebufferDisplay.c b/shared-bindings/framebufferio/FramebufferDisplay.c
new file mode 100644
index 000000000..51ef09059
--- /dev/null
+++ b/shared-bindings/framebufferio/FramebufferDisplay.c
@@ -0,0 +1,403 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ * 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 "shared-bindings/framebufferio/FramebufferDisplay.h"
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/objtype.h"
+#include "py/runtime.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/util.h"
+#include "shared-module/displayio/__init__.h"
+#include "supervisor/shared/translate.h"
+
+//| class FramebufferDisplay:
+//| """Manage updating a display with framebuffer in RAM
+//|
+//| This initializes a display and connects it into CircuitPython. Unlike other
+//| 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: Any, *, rotation: int = 0, auto_refresh: bool = True):
+//| """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 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)"""
+//| ...
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_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_framebuffer, ARG_rotation, ARG_auto_refresh, NUM_ARGS };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_framebuffer, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_rotation, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_auto_refresh, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ };
+ MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t framebuffer = args[ARG_framebuffer].u_obj;
+
+ mp_int_t rotation = args[ARG_rotation].u_int;
+ if (rotation % 90 != 0) {
+ mp_raise_ValueError(translate("Display rotation must be in 90 degree increments"));
+ }
+
+ primary_display_t *disp = allocate_display_or_raise();
+ framebufferio_framebufferdisplay_obj_t *self = &disp->framebuffer_display;
+ self->base.type = &framebufferio_framebufferdisplay_type;
+ common_hal_framebufferio_framebufferdisplay_construct(
+ self,
+ framebuffer,
+ rotation,
+ args[ARG_auto_refresh].u_bool
+ );
+
+ return self;
+}
+
+// Helper to ensure we have the native super class instead of a subclass.
+static framebufferio_framebufferdisplay_obj_t* native_display(mp_obj_t display_obj) {
+ mp_obj_t native_display = mp_instance_cast_to_native_base(display_obj, &framebufferio_framebufferdisplay_type);
+ mp_obj_assert_native_inited(native_display);
+ return MP_OBJ_TO_PTR(native_display);
+}
+
+//| def show(self, group: Group) -> Any:
+//| """Switches to displaying the given group of layers. When group is None, the default
+//| CircuitPython terminal will be shown.
+//|
+//| :param Group group: The group to show."""
+//| ...
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_show(mp_obj_t self_in, mp_obj_t group_in) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ displayio_group_t* group = NULL;
+ if (group_in != mp_const_none) {
+ group = MP_OBJ_TO_PTR(native_group(group_in));
+ }
+
+ bool ok = common_hal_framebufferio_framebufferdisplay_show(self, group);
+ if (!ok) {
+ mp_raise_ValueError(translate("Group already used"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_show_obj, framebufferio_framebufferdisplay_obj_show);
+
+//| def refresh(self, *, target_frames_per_second: int = 60, minimum_frames_per_second: int = 1) -> Any:
+//| """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.
+//|
+//| 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.
+//| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second."""
+//| ...
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_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_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);
+
+ framebufferio_framebufferdisplay_obj_t *self = native_display(pos_args[0]);
+ uint32_t maximum_ms_per_real_frame = 0xffffffff;
+ mp_int_t minimum_frames_per_second = args[ARG_minimum_frames_per_second].u_int;
+ if (minimum_frames_per_second > 0) {
+ maximum_ms_per_real_frame = 1000 / minimum_frames_per_second;
+ }
+ return mp_obj_new_bool(common_hal_framebufferio_framebufferdisplay_refresh(self, 1000 / args[ARG_target_frames_per_second].u_int, maximum_ms_per_real_frame));
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(framebufferio_framebufferdisplay_refresh_obj, 1, framebufferio_framebufferdisplay_obj_refresh);
+
+//| auto_refresh: Any = ...
+//| """True when the display is refreshed automatically."""
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_auto_refresh(mp_obj_t self_in) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ return mp_obj_new_bool(common_hal_framebufferio_framebufferdisplay_get_auto_refresh(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_auto_refresh_obj, framebufferio_framebufferdisplay_obj_get_auto_refresh);
+
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_set_auto_refresh(mp_obj_t self_in, mp_obj_t auto_refresh) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+
+ common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, mp_obj_is_true(auto_refresh));
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_set_auto_refresh_obj, framebufferio_framebufferdisplay_obj_set_auto_refresh);
+
+const mp_obj_property_t framebufferio_framebufferdisplay_auto_refresh_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_auto_refresh_obj,
+ (mp_obj_t)&framebufferio_framebufferdisplay_set_auto_refresh_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| brightness: Any = ...
+//| """The brightness of the display as a float. 0.0 is off and 1.0 is full brightness. When
+//| `auto_brightness` is True, the value of `brightness` will change automatically.
+//| If `brightness` is set, `auto_brightness` will be disabled and will be set to False."""
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_brightness(mp_obj_t self_in) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ mp_float_t brightness = common_hal_framebufferio_framebufferdisplay_get_brightness(self);
+ if (brightness < 0) {
+ mp_raise_RuntimeError(translate("Brightness not adjustable"));
+ }
+ return mp_obj_new_float(brightness);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_brightness_obj, framebufferio_framebufferdisplay_obj_get_brightness);
+
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ common_hal_framebufferio_framebufferdisplay_set_auto_brightness(self, false);
+ mp_float_t brightness = mp_obj_get_float(brightness_obj);
+ if (brightness < 0.0f || brightness > 1.0f) {
+ mp_raise_ValueError(translate("Brightness must be 0-1.0"));
+ }
+ bool ok = common_hal_framebufferio_framebufferdisplay_set_brightness(self, brightness);
+ if (!ok) {
+ mp_raise_RuntimeError(translate("Brightness not adjustable"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_set_brightness_obj, framebufferio_framebufferdisplay_obj_set_brightness);
+
+const mp_obj_property_t framebufferio_framebufferdisplay_brightness_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_brightness_obj,
+ (mp_obj_t)&framebufferio_framebufferdisplay_set_brightness_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| auto_brightness: Any = ...
+//| """True when the display brightness is adjusted automatically, based on an ambient
+//| light sensor or other method. Note that some displays may have this set to True by default,
+//| but not actually implement automatic brightness adjustment. `auto_brightness` is set to False
+//| if `brightness` is set manually."""
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_auto_brightness(mp_obj_t self_in) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ return mp_obj_new_bool(common_hal_framebufferio_framebufferdisplay_get_auto_brightness(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_auto_brightness_obj, framebufferio_framebufferdisplay_obj_get_auto_brightness);
+
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_set_auto_brightness(mp_obj_t self_in, mp_obj_t auto_brightness) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+
+ bool ok = common_hal_framebufferio_framebufferdisplay_set_auto_brightness(self, mp_obj_is_true(auto_brightness));
+ if (!ok) {
+ mp_raise_RuntimeError(translate("Brightness not adjustable"));
+ }
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_set_auto_brightness_obj, framebufferio_framebufferdisplay_obj_set_auto_brightness);
+
+const mp_obj_property_t framebufferio_framebufferdisplay_auto_brightness_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_auto_brightness_obj,
+ (mp_obj_t)&framebufferio_framebufferdisplay_set_auto_brightness_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| width: Any = ...
+//| """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);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_framebufferio_framebufferdisplay_get_width(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_width_obj, framebufferio_framebufferdisplay_obj_get_width);
+
+const mp_obj_property_t framebufferio_framebufferdisplay_width_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_width_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| height: Any = ...
+//| """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);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_framebufferio_framebufferdisplay_get_height(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_height_obj, framebufferio_framebufferdisplay_obj_get_height);
+
+const mp_obj_property_t framebufferio_framebufferdisplay_height_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_height_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| rotation: Any = ...
+//| """The rotation of the display as an int in degrees."""
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_rotation(mp_obj_t self_in) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_framebufferio_framebufferdisplay_get_rotation(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_rotation_obj, framebufferio_framebufferdisplay_obj_get_rotation);
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_set_rotation(mp_obj_t self_in, mp_obj_t value) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ common_hal_framebufferio_framebufferdisplay_set_rotation(self, mp_obj_get_int(value));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_set_rotation_obj, framebufferio_framebufferdisplay_obj_set_rotation);
+
+
+const mp_obj_property_t framebufferio_framebufferdisplay_rotation_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_rotation_obj,
+ (mp_obj_t)&framebufferio_framebufferdisplay_set_rotation_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| framebuffer: Any = ...
+//| """The framebuffer being used by the display"""
+//|
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_get_framebuffer(mp_obj_t self_in) {
+ framebufferio_framebufferdisplay_obj_t *self = native_display(self_in);
+ return common_hal_framebufferio_framebufferdisplay_get_framebuffer(self);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(framebufferio_framebufferdisplay_get_framebuffer_obj, framebufferio_framebufferdisplay_obj_get_framebuffer);
+
+const mp_obj_property_t framebufferio_framebufferframebuffer_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&framebufferio_framebufferdisplay_get_framebuffer_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+//| def fill_row(self, y: int, buffer: bytearray) -> Any:
+//| """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"""
+//| ...
+//|
+STATIC mp_obj_t framebufferio_framebufferdisplay_obj_fill_row(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_y, ARG_buffer };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_y, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = -1} },
+ { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {} },
+ };
+ 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);
+ framebufferio_framebufferdisplay_obj_t *self = native_display(pos_args[0]);
+ mp_int_t y = args[ARG_y].u_int;
+ mp_obj_t *result = args[ARG_buffer].u_obj;
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(result, &bufinfo, MP_BUFFER_WRITE);
+
+ if (bufinfo.typecode != BYTEARRAY_TYPECODE) {
+ mp_raise_ValueError(translate("Buffer is not a bytearray."));
+ }
+ if (self->core.colorspace.depth != 16) {
+ mp_raise_ValueError(translate("Display must have a 16 bit colorspace."));
+ }
+
+ displayio_area_t area = {
+ .x1 = 0,
+ .y1 = y,
+ .x2 = self->core.width,
+ .y2 = y + 1
+ };
+ uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth;
+ uint16_t buffer_size = self->core.width / pixels_per_word;
+ uint16_t pixels_per_buffer = displayio_area_size(&area);
+ if (pixels_per_buffer % pixels_per_word) {
+ buffer_size += 1;
+ }
+
+ uint32_t *result_buffer = bufinfo.buf;
+ size_t result_buffer_size = bufinfo.len;
+
+ if (result_buffer_size >= (buffer_size * 4)) {
+ volatile uint32_t mask_length = (pixels_per_buffer / 32) + 1;
+ uint32_t mask[mask_length];
+
+ for (uint16_t k = 0; k < mask_length; k++) {
+ mask[k] = 0x00000000;
+ }
+
+ displayio_display_core_fill_area(&self->core, &area, mask, result_buffer);
+ return result;
+ } else {
+ mp_raise_ValueError(translate("Buffer is too small"));
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(framebufferio_framebufferdisplay_fill_row_obj, 1, framebufferio_framebufferdisplay_obj_fill_row);
+
+STATIC const mp_rom_map_elem_t framebufferio_framebufferdisplay_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&framebufferio_framebufferdisplay_show_obj) },
+ { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&framebufferio_framebufferdisplay_refresh_obj) },
+ { MP_ROM_QSTR(MP_QSTR_fill_row), MP_ROM_PTR(&framebufferio_framebufferdisplay_fill_row_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_auto_refresh), MP_ROM_PTR(&framebufferio_framebufferdisplay_auto_refresh_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&framebufferio_framebufferdisplay_brightness_obj) },
+ { MP_ROM_QSTR(MP_QSTR_auto_brightness), MP_ROM_PTR(&framebufferio_framebufferdisplay_auto_brightness_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&framebufferio_framebufferdisplay_width_obj) },
+ { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&framebufferio_framebufferdisplay_height_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&framebufferio_framebufferdisplay_rotation_obj) },
+ { MP_ROM_QSTR(MP_QSTR_framebuffer), MP_ROM_PTR(&framebufferio_framebufferframebuffer_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(framebufferio_framebufferdisplay_locals_dict, framebufferio_framebufferdisplay_locals_dict_table);
+
+const mp_obj_type_t framebufferio_framebufferdisplay_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_FramebufferDisplay,
+ .make_new = framebufferio_framebufferdisplay_make_new,
+ .locals_dict = (mp_obj_dict_t*)&framebufferio_framebufferdisplay_locals_dict,
+};
diff --git a/shared-bindings/framebufferio/FramebufferDisplay.h b/shared-bindings/framebufferio/FramebufferDisplay.h
new file mode 100644
index 000000000..c41e041ce
--- /dev/null
+++ b/shared-bindings/framebufferio/FramebufferDisplay.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries
+ * 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.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_FRAMEBUFFERDISPLAY_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_FRAMEBUFFERDISPLAY_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "shared-module/framebufferio/FramebufferDisplay.h"
+#include "shared-module/displayio/Group.h"
+
+extern const mp_obj_type_t framebufferio_framebufferdisplay_type;
+
+#define DELAY 0x80
+
+#define NO_BRIGHTNESS_COMMAND 0x100
+
+void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebufferdisplay_obj_t* self,
+ mp_obj_t framebuffer,
+ uint16_t rotation,
+ bool auto_refresh);
+
+bool common_hal_framebufferio_framebufferdisplay_show(framebufferio_framebufferdisplay_obj_t* self,
+ displayio_group_t* root_group);
+
+bool common_hal_framebufferio_framebufferdisplay_refresh(framebufferio_framebufferdisplay_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame);
+
+bool common_hal_framebufferio_framebufferdisplay_get_auto_refresh(framebufferio_framebufferdisplay_obj_t* self);
+void common_hal_framebufferio_framebufferdisplay_set_auto_refresh(framebufferio_framebufferdisplay_obj_t* self, bool auto_refresh);
+
+uint16_t common_hal_framebufferio_framebufferdisplay_get_width(framebufferio_framebufferdisplay_obj_t* self);
+uint16_t common_hal_framebufferio_framebufferdisplay_get_height(framebufferio_framebufferdisplay_obj_t* self);
+uint16_t common_hal_framebufferio_framebufferdisplay_get_rotation(framebufferio_framebufferdisplay_obj_t* self);
+void common_hal_framebufferio_framebufferdisplay_set_rotation(framebufferio_framebufferdisplay_obj_t* self, int rotation);
+
+bool common_hal_framebufferio_framebufferdisplay_get_auto_brightness(framebufferio_framebufferdisplay_obj_t* self);
+bool common_hal_framebufferio_framebufferdisplay_set_auto_brightness(framebufferio_framebufferdisplay_obj_t* self, bool auto_brightness);
+
+mp_float_t common_hal_framebufferio_framebufferdisplay_get_brightness(framebufferio_framebufferdisplay_obj_t* self);
+bool common_hal_framebufferio_framebufferdisplay_set_brightness(framebufferio_framebufferdisplay_obj_t* self, mp_float_t brightness);
+
+mp_obj_t common_hal_framebufferio_framebufferdisplay_framebuffer(framebufferio_framebufferdisplay_obj_t* self);
+
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_FRAMEBUFFERDISPLAY_H
diff --git a/shared-bindings/framebufferio/__init__.c b/shared-bindings/framebufferio/__init__.c
new file mode 100644
index 000000000..3e58162bf
--- /dev/null
+++ b/shared-bindings/framebufferio/__init__.c
@@ -0,0 +1,50 @@
+/*
+ * 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/obj.h"
+#include "shared-bindings/framebufferio/__init__.h"
+#include "shared-bindings/framebufferio/FramebufferDisplay.h"
+
+//| """Native framebuffer display driving
+//|
+//| The `framebufferio` module contains classes to manage display output
+//| including synchronizing with refresh rates and partial updating.
+//| It is used in conjunction with classes from `displayio` to actually
+//| place items on the display; and classes like `RGBMatrix` to actually
+//| drive the display."""
+//|
+
+#if CIRCUITPY_FRAMEBUFFERIO
+static const mp_rom_map_elem_t framebufferio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebufferio) },
+ { MP_ROM_QSTR(MP_QSTR_FramebufferDisplay), MP_ROM_PTR(&framebufferio_framebufferdisplay_type) },
+};
+STATIC MP_DEFINE_CONST_DICT(framebufferio_module_globals, framebufferio_module_globals_table);
+const mp_obj_module_t framebufferio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&framebufferio_module_globals,
+};
+#endif
diff --git a/shared-bindings/framebufferio/__init__.h b/shared-bindings/framebufferio/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-bindings/framebufferio/__init__.h
diff --git a/shared-bindings/frequencyio/FrequencyIn.c b/shared-bindings/frequencyio/FrequencyIn.c
index e2b924c07..2d628088b 100644
--- a/shared-bindings/frequencyio/FrequencyIn.c
+++ b/shared-bindings/frequencyio/FrequencyIn.c
@@ -35,43 +35,41 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: frequencyio
+//| class FrequencyIn:
+//| """Read a frequency signal
//|
-//| :class:`FrequencyIn` -- Read a frequency signal
-//| ========================================================
+//| FrequencyIn is used to measure the frequency, in hertz, of a digital signal
+//| on an incoming pin. Accuracy has shown to be within 10%, if not better. It
+//| is recommended to utilize an average of multiple samples to smooth out readings.
//|
-//| FrequencyIn is used to measure the frequency, in hertz, of a digital signal
-//| on an incoming pin. Accuracy has shown to be within 10%, if not better. It
-//| is recommended to utilize an average of multiple samples to smooth out readings.
+//| Frequencies below 1KHz are not currently detectable.
//|
-//| Frequencies below 1KHz are not currently detectable.
+//| FrequencyIn will not determine pulse width (use ``PulseIn``)."""
//|
-//| FrequencyIn will not determine pulse width (use ``PulseIn``).
+//| def __init__(self, pin: microcontroller.Pin, capture_period: int = 10):
+//| """Create a FrequencyIn object associated with the given pin.
//|
-//| .. class:: FrequencyIn(pin, capture_period=10)
+//| :param ~microcontroller.Pin pin: Pin to read frequency from.
+//| :param int capture_period: Keyword argument to set the measurement period, in
+//| milliseconds. Default is 10ms; range is 1ms - 500ms.
//|
-//| Create a FrequencyIn object associated with the given pin.
+//| Read the incoming frequency from a pin::
//|
-//| :param ~microcontroller.Pin pin: Pin to read frequency from.
-//| :param int capture_period: Keyword argument to set the measurement period, in
-//| milliseconds. Default is 10ms; range is 1ms - 500ms.
+//| import frequencyio
+//| import board
//|
-//| Read the incoming frequency from a pin::
+//| frequency = frequencyio.FrequencyIn(board.D11)
//|
-//| import frequencyio
-//| import board
+//| # Loop while printing the detected frequency
+//| while True:
+//| print(frequency.value)
//|
-//| frequency = frequencyio.FrequencyIn(board.D11)
-//|
-//| # Loop while printing the detected frequency
-//| while True:
-//| print(frequency.value)
-//|
-//| # Optional clear() will reset the value
-//| # to zero. Without this, if the incoming
-//| # signal stops, the last reading will remain
-//| # as the value.
-//| frequency.clear()
+//| # Optional clear() will reset the value
+//| # to zero. Without this, if the incoming
+//| # signal stops, the last reading will remain
+//| # as the value.
+//| frequency.clear()"""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -87,9 +85,7 @@ STATIC mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size
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);
- assert_pin(args[ARG_pin].u_obj, false);
- mcu_pin_obj_t* pin = MP_OBJ_TO_PTR(args[ARG_pin].u_obj);
- assert_pin_free(pin);
+ mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
const uint16_t capture_period = args[ARG_capture_period].u_int;
@@ -98,9 +94,9 @@ STATIC mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the FrequencyIn and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the FrequencyIn and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_deinit(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -115,16 +111,16 @@ STATIC void check_for_deinit(frequencyio_frequencyin_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -133,9 +129,9 @@ STATIC mp_obj_t frequencyio_frequencyin_obj___exit__(size_t n_args, const mp_obj
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(frequencyio_frequencyin___exit___obj, 4, 4, frequencyio_frequencyin_obj___exit__);
-//| .. method:: pause()
-//|
-//| Pause frequency capture.
+//| def pause(self, ) -> Any:
+//| """Pause frequency capture."""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_pause(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -146,9 +142,9 @@ STATIC mp_obj_t frequencyio_frequencyin_obj_pause(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_pause_obj, frequencyio_frequencyin_obj_pause);
-//| .. method:: resume()
-//|
-//| Resumes frequency capture.
+//| def resume(self, ) -> Any:
+//| """Resumes frequency capture."""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_resume(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -159,9 +155,9 @@ STATIC mp_obj_t frequencyio_frequencyin_obj_resume(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_resume_obj, frequencyio_frequencyin_obj_resume);
-//| .. method:: clear()
-//|
-//| Clears the last detected frequency capture value.
+//| def clear(self, ) -> Any:
+//| """Clears the last detected frequency capture value."""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_clear(mp_obj_t self_in) {
@@ -173,14 +169,13 @@ STATIC mp_obj_t frequencyio_frequencyin_obj_clear(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_clear_obj, frequencyio_frequencyin_obj_clear);
-//| .. attribute:: capture_period
-//|
-//| The capture measurement period. Lower incoming frequencies will be measured
+//| capture_period: Any = ...
+//| """The capture measurement period. Lower incoming frequencies will be measured
//| more accurately with longer capture periods. Higher frequencies are more
//| accurate with shorter capture periods.
//|
-//| .. note:: When setting a new ``capture_period``, all previous capture information is
-//| cleared with a call to ``clear()``.
+//| .. note:: When setting a new ``capture_period``, all previous capture information is
+//| cleared with a call to ``clear()``."""
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_get_capture_period(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -206,9 +201,9 @@ const mp_obj_property_t frequencyio_frequencyin_capture_period_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: __get__(index)
-//|
-//| Returns the value of the last frequency captured.
+//| def __get__(self, index: Any) -> Any:
+//| """Returns the value of the last frequency captured."""
+//| ...
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_get_value(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/frequencyio/__init__.c b/shared-bindings/frequencyio/__init__.c
index 48a026824..031004d4b 100644
--- a/shared-bindings/frequencyio/__init__.c
+++ b/shared-bindings/frequencyio/__init__.c
@@ -33,23 +33,8 @@
#include "shared-bindings/frequencyio/__init__.h"
#include "shared-bindings/frequencyio/FrequencyIn.h"
-//| :mod:`frequencyio` --- Support for frequency based protocols
-//| =============================================================
+//| """Support for frequency based protocols
//|
-//| .. module:: frequencyio
-//| :synopsis: Support for frequency based protocols
-//| :platform: SAMD51
-//|
-//| The `frequencyio` module contains classes to provide access to basic frequency IO.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| FrequencyIn
-//|
-
//| .. warning:: This module is not available in SAMD21 builds. See the
//| :ref:`module-support-matrix` for more info.
//|
@@ -73,7 +58,7 @@
//| :py:data:`~frequencyio.FrequencyIn.capture_period`, and then sleep 0.1 seconds.
//| CircuitPython will automatically turn off FrequencyIn capture when it resets all
//| hardware after program completion. Use ``deinit()`` or a ``with`` statement
-//| to do it yourself.
+//| to do it yourself."""
//|
STATIC const mp_rom_map_elem_t frequencyio_module_globals_table[] = {
diff --git a/shared-bindings/gamepad/GamePad.c b/shared-bindings/gamepad/GamePad.c
index d3c29019a..9a23344b3 100644
--- a/shared-bindings/gamepad/GamePad.c
+++ b/shared-bindings/gamepad/GamePad.c
@@ -33,66 +33,64 @@
#include "shared-bindings/gamepad/__init__.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "supervisor/shared/translate.h"
+#include "supervisor/shared/tick.h"
-
-//| .. currentmodule:: gamepad
-//|
-//| :class:`GamePad` -- Scan buttons for presses
-//| ============================================
+//| class GamePad:
+//| """Scan buttons for presses
//|
-//| Usage::
+//| Usage::
//|
-//| import board
-//| import digitalio
-//| import gamepad
-//| import time
+//| import board
+//| import digitalio
+//| import gamepad
+//| import time
//|
-//| B_UP = 1 << 0
-//| B_DOWN = 1 << 1
+//| B_UP = 1 << 0
+//| B_DOWN = 1 << 1
//|
//|
-//| pad = gamepad.GamePad(
-//| digitalio.DigitalInOut(board.D10),
-//| digitalio.DigitalInOut(board.D11),
-//| )
+//| pad = gamepad.GamePad(
+//| digitalio.DigitalInOut(board.D10),
+//| digitalio.DigitalInOut(board.D11),
+//| )
//|
-//| y = 0
-//| while True:
-//| buttons = pad.get_pressed()
-//| if buttons & B_UP:
-//| y -= 1
-//| print(y)
-//| elif buttons & B_DOWN:
-//| y += 1
-//| print(y)
-//| time.sleep(0.1)
-//| while buttons:
-//| # Wait for all buttons to be released.
+//| y = 0
+//| while True:
//| buttons = pad.get_pressed()
+//| if buttons & B_UP:
+//| y -= 1
+//| print(y)
+//| elif buttons & B_DOWN:
+//| y += 1
+//| print(y)
//| time.sleep(0.1)
+//| while buttons:
+//| # Wait for all buttons to be released.
+//| buttons = pad.get_pressed()
+//| time.sleep(0.1)"""
//|
-//| .. class:: GamePad([b1[, b2[, b3[, b4[, b5[, b6[, b7[, b8]]]]]]]])
-//|
-//| Initializes button scanning routines.
-//|
-//| The ``b1``-``b8`` parameters are ``DigitalInOut`` objects, which
-//| immediately get switched to input with a pull-up, (unless they already
-//| were set to pull-down, in which case they remain so), and then scanned
-//| regularly for button presses. The order is the same as the order of
-//| bits returned by the ``get_pressed`` function. You can re-initialize
-//| it with different keys, then the new object will replace the previous
-//| one.
-//|
-//| The basic feature required here is the ability to poll the keys at
-//| regular intervals (so that de-bouncing is consistent) and fast enough
-//| (so that we don't miss short button presses) while at the same time
-//| letting the user code run normally, call blocking functions and wait
-//| on delays.
-//|
-//| They button presses are accumulated, until the ``get_pressed`` method
-//| is called, at which point the button state is cleared, and the new
-//| button presses start to be recorded.
+//| def __init__(self, b1: Any, b2: Any, b3: Any, b4: Any, b5: Any, b6: Any, b7: Any, b8: Any):
+//| """Initializes button scanning routines.
+//|
+//| The ``b1``-``b8`` parameters are ``DigitalInOut`` objects, which
+//| immediately get switched to input with a pull-up, (unless they already
+//| were set to pull-down, in which case they remain so), and then scanned
+//| regularly for button presses. The order is the same as the order of
+//| bits returned by the ``get_pressed`` function. You can re-initialize
+//| it with different keys, then the new object will replace the previous
+//| one.
+//|
+//| The basic feature required here is the ability to poll the keys at
+//| regular intervals (so that de-bouncing is consistent) and fast enough
+//| (so that we don't miss short button presses) while at the same time
+//| letting the user code run normally, call blocking functions and wait
+//| on delays.
+//|
+//| They button presses are accumulated, until the ``get_pressed`` method
+//| is called, at which point the button state is cleared, and the new
+//| button presses start to be recorded."""
+//| ...
//|
STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *args, mp_map_t *kw_args) {
@@ -105,24 +103,26 @@ STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args,
gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton);
if (!gamepad_singleton ||
!MP_OBJ_IS_TYPE(MP_OBJ_FROM_PTR(gamepad_singleton), &gamepad_type)) {
- gamepad_singleton = m_new_obj(gamepad_obj_t);
+ gamepad_singleton = m_new_ll_obj(gamepad_obj_t);
gamepad_singleton->base.type = &gamepad_type;
- gamepad_singleton = gc_make_long_lived(gamepad_singleton);
+ if (!MP_STATE_VM(gamepad_singleton)) {
+ supervisor_enable_tick();
+ }
MP_STATE_VM(gamepad_singleton) = gamepad_singleton;
}
common_hal_gamepad_gamepad_init(gamepad_singleton, args, n_args);
return MP_OBJ_FROM_PTR(gamepad_singleton);
}
-//| .. method:: get_pressed()
-//|
-//| Get the status of buttons pressed since the last call and clear it.
+//| def get_pressed(self, ) -> Any:
+//| """Get the status of buttons pressed since the last call and clear it.
//|
//| Returns an 8-bit number, with bits that correspond to buttons,
//| which have been pressed (or held down) since the last call to this
//| function set to 1, and the remaining bits set to 0. Then it clears
//| the button state, so that new button presses (or buttons that are
-//| held down) can be recorded for the next call.
+//| held down) can be recorded for the next call."""
+//| ...
//|
STATIC mp_obj_t gamepad_get_pressed(mp_obj_t self_in) {
gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton);
@@ -133,9 +133,9 @@ STATIC mp_obj_t gamepad_get_pressed(mp_obj_t self_in) {
MP_DEFINE_CONST_FUN_OBJ_1(gamepad_get_pressed_obj, gamepad_get_pressed);
-//| .. method:: deinit()
-//|
-//| Disable button scanning.
+//| def deinit(self, ) -> Any:
+//| """Disable button scanning."""
+//| ...
//|
STATIC mp_obj_t gamepad_deinit(mp_obj_t self_in) {
common_hal_gamepad_gamepad_deinit(self_in);
diff --git a/shared-bindings/gamepad/__init__.c b/shared-bindings/gamepad/__init__.c
index cea0b4ee9..557777f50 100644
--- a/shared-bindings/gamepad/__init__.c
+++ b/shared-bindings/gamepad/__init__.c
@@ -29,17 +29,7 @@
#include "shared-bindings/gamepad/GamePad.h"
#include "shared-bindings/util.h"
-//| :mod:`gamepad` --- Button handling
-//| ==================================
-//|
-//| .. module:: gamepad
-//| :synopsis: Button handling
-//| :platform: SAMD21
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| GamePad
+//| """Button handling in the background"""
//|
STATIC const mp_rom_map_elem_t gamepad_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gamepad) },
diff --git a/shared-bindings/gamepadshift/GamePadShift.c b/shared-bindings/gamepadshift/GamePadShift.c
index 91203ad20..854f092ad 100644
--- a/shared-bindings/gamepadshift/GamePadShift.c
+++ b/shared-bindings/gamepadshift/GamePadShift.c
@@ -31,25 +31,24 @@
#include "shared-bindings/gamepadshift/GamePadShift.h"
#include "shared-bindings/gamepadshift/__init__.h"
#include "supervisor/shared/translate.h"
+#include "supervisor/shared/tick.h"
-//| .. currentmodule:: gamepadshift
+//| class GamePadShift:
+//| """Scan buttons for presses through a shift register"""
//|
-//| :class:`GamePadShift` -- Scan buttons for presses through a shift register
-//| ===========================================================================
+//| def __init__(self, clock: Any, data: Any, latch: Any):
+//| """Initializes button scanning routines.
//|
-//| .. class:: GamePadShift(clock, data, latch)
+//| The ``clock``, ``data`` and ``latch`` parameters are ``DigitalInOut``
+//| objects connected to the shift register controlling the buttons.
//|
-//| Initializes button scanning routines.
+//| They button presses are accumulated, until the ``get_pressed`` method
+//| is called, at which point the button state is cleared, and the new
+//| button presses start to be recorded.
//|
-//| The ``clock``, ``data`` and ``latch`` parameters are ``DigitalInOut``
-//| objects connected to the shift register controlling the buttons.
-//|
-//| They button presses are accumulated, until the ``get_pressed`` method
-//| is called, at which point the button state is cleared, and the new
-//| button presses start to be recorded.
-//|
-//| Only one gamepad (`gamepad.GamePad` or `gamepadshift.GamePadShift`)
-//| may be used at a time.
+//| Only one gamepad (`gamepad.GamePad` or `gamepadshift.GamePadShift`)
+//| may be used at a time."""
+//| ...
//|
STATIC mp_obj_t gamepadshift_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -72,24 +71,26 @@ STATIC mp_obj_t gamepadshift_make_new(const mp_obj_type_t *type, size_t n_args,
if (!gamepad_singleton ||
!MP_OBJ_IS_TYPE(MP_OBJ_FROM_PTR(gamepad_singleton),
&gamepadshift_type)) {
- gamepad_singleton = m_new_obj(gamepadshift_obj_t);
+ gamepad_singleton = m_new_ll_obj(gamepadshift_obj_t);
gamepad_singleton->base.type = &gamepadshift_type;
- gamepad_singleton = gc_make_long_lived(gamepad_singleton);
+ if (!MP_STATE_VM(gamepad_singleton)) {
+ supervisor_enable_tick();
+ }
MP_STATE_VM(gamepad_singleton) = gamepad_singleton;
}
common_hal_gamepadshift_gamepadshift_init(gamepad_singleton, clock_pin, data_pin, latch_pin);
return MP_OBJ_FROM_PTR(gamepad_singleton);
}
-//| .. method:: get_pressed()
-//|
-//| Get the status of buttons pressed since the last call and clear it.
+//| def get_pressed(self, ) -> Any:
+//| """Get the status of buttons pressed since the last call and clear it.
//|
//| Returns an 8-bit number, with bits that correspond to buttons,
//| which have been pressed (or held down) since the last call to this
//| function set to 1, and the remaining bits set to 0. Then it clears
//| the button state, so that new button presses (or buttons that are
-//| held down) can be recorded for the next call.
+//| held down) can be recorded for the next call."""
+//| ...
//|
STATIC mp_obj_t gamepadshift_get_pressed(mp_obj_t self_in) {
gamepadshift_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton);
@@ -99,9 +100,9 @@ STATIC mp_obj_t gamepadshift_get_pressed(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(gamepadshift_get_pressed_obj, gamepadshift_get_pressed);
-//| .. method:: deinit()
-//|
-//| Disable button scanning.
+//| def deinit(self, ) -> Any:
+//| """Disable button scanning."""
+//| ...
//|
STATIC mp_obj_t gamepadshift_deinit(mp_obj_t self_in) {
common_hal_gamepadshift_gamepadshift_deinit(self_in);
diff --git a/shared-bindings/gamepadshift/__init__.c b/shared-bindings/gamepadshift/__init__.c
index 2d3667726..f17135893 100644
--- a/shared-bindings/gamepadshift/__init__.c
+++ b/shared-bindings/gamepadshift/__init__.c
@@ -30,17 +30,7 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/util.h"
-//| :mod:`gamepadshift` --- Tracks button presses read through a shift register
-//| ===========================================================================
-//|
-//| .. module:: gamepadshift
-//| :synopsis: Tracks button presses read through a shift register
-//| :platform: SAMD21, SAMD51
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| GamePadShift
+//| """Tracks button presses read through a shift register"""
//|
STATIC const mp_rom_map_elem_t gamepadshift_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gamepadshift) },
diff --git a/shared-bindings/gnss/GNSS.c b/shared-bindings/gnss/GNSS.c
new file mode 100644
index 000000000..929e02ab8
--- /dev/null
+++ b/shared-bindings/gnss/GNSS.c
@@ -0,0 +1,227 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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/gnss/GNSS.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-bindings/util.h"
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+
+//| class GNSS:
+//| """Get updated positioning information from Global Navigation Satellite System (GNSS)
+//|
+//| Usage::
+//|
+//| import gnss
+//| import time
+//|
+//| nav = gnss.GNSS([gnss.SatelliteSystem.GPS, gnss.SatelliteSystem.GLONASS])
+//| last_print = time.monotonic()
+//| while True:
+//| nav.update()
+//| current = time.monotonic()
+//| if current - last_print >= 1.0:
+//| last_print = current
+//| if nav.fix is gnss.PositionFix.INVALID:
+//| print("Waiting for fix...")
+//| continue
+//| print("Latitude: {0:.6f} degrees".format(nav.latitude))
+//| print("Longitude: {0:.6f} degrees".format(nav.longitude))"""
+//|
+
+//| def __init__(self, ):
+//| """Turn on the GNSS.
+//|
+//| :param gnss.SatelliteSystem system: satellite system to use"""
+//| ...
+//|
+STATIC mp_obj_t gnss_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ gnss_obj_t *self = m_new_obj(gnss_obj_t);
+ self->base.type = &gnss_type;
+ enum { ARG_system };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_system, 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);
+
+ unsigned long selection = 0;
+ if (MP_OBJ_IS_TYPE(args[ARG_system].u_obj, &gnss_satellitesystem_type)) {
+ selection |= gnss_satellitesystem_obj_to_type(args[ARG_system].u_obj);
+ } else if (MP_OBJ_IS_TYPE(args[ARG_system].u_obj, &mp_type_list)) {
+ size_t systems_size = 0;
+ mp_obj_t *systems;
+ mp_obj_list_get(args[ARG_system].u_obj, &systems_size, &systems);
+ for (size_t i = 0; i < systems_size; ++i) {
+ if (!MP_OBJ_IS_TYPE(systems[i], &gnss_satellitesystem_type)) {
+ mp_raise_TypeError(translate("System entry must be gnss.SatelliteSystem"));
+ }
+ selection |= gnss_satellitesystem_obj_to_type(systems[i]);
+ }
+ } else {
+ mp_raise_TypeError(translate("System entry must be gnss.SatelliteSystem"));
+ }
+
+ common_hal_gnss_construct(self, selection);
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| def deinit(self, ) -> Any:
+//| """Turn off the GNSS."""
+//| ...
+//|
+STATIC mp_obj_t gnss_obj_deinit(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_gnss_deinit(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_deinit_obj, gnss_obj_deinit);
+
+STATIC void check_for_deinit(gnss_obj_t *self) {
+ if (common_hal_gnss_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| def update(self, ) -> Any:
+//| """Update GNSS positioning information."""
+//| ...
+//|
+STATIC mp_obj_t gnss_obj_update(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ common_hal_gnss_update(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_update_obj, gnss_obj_update);
+
+//| latitude: Any = ...
+//| """Latitude of current position in degrees (float)."""
+//|
+STATIC mp_obj_t gnss_obj_get_latitude(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_float(common_hal_gnss_get_latitude(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_get_latitude_obj, gnss_obj_get_latitude);
+
+const mp_obj_property_t gnss_latitude_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&gnss_get_latitude_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| longitude: Any = ...
+//| """Longitude of current position in degrees (float)."""
+//|
+STATIC mp_obj_t gnss_obj_get_longitude(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_float(common_hal_gnss_get_longitude(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_get_longitude_obj, gnss_obj_get_longitude);
+
+const mp_obj_property_t gnss_longitude_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&gnss_get_longitude_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| altitude: Any = ...
+//| """Altitude of current position in meters (float)."""
+//|
+STATIC mp_obj_t gnss_obj_get_altitude(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_float(common_hal_gnss_get_altitude(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_get_altitude_obj, gnss_obj_get_altitude);
+
+const mp_obj_property_t gnss_altitude_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&gnss_get_altitude_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| timestamp: Any = ...
+//| """Time when the position data was updated."""
+//|
+STATIC mp_obj_t gnss_obj_get_timestamp(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ timeutils_struct_time_t tm;
+ common_hal_gnss_get_timestamp(self, &tm);
+ return struct_time_from_tm(&tm);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_get_timestamp_obj, gnss_obj_get_timestamp);
+
+const mp_obj_property_t gnss_timestamp_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&gnss_get_timestamp_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| fix: Any = ...
+//| """Fix mode."""
+//|
+STATIC mp_obj_t gnss_obj_get_fix(mp_obj_t self_in) {
+ gnss_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return gnss_positionfix_type_to_obj(common_hal_gnss_get_fix(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(gnss_get_fix_obj, gnss_obj_get_fix);
+
+const mp_obj_property_t gnss_fix_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&gnss_get_fix_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t gnss_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gnss_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&gnss_update_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_latitude), MP_ROM_PTR(&gnss_latitude_obj) },
+ { MP_ROM_QSTR(MP_QSTR_longitude), MP_ROM_PTR(&gnss_longitude_obj) },
+ { MP_ROM_QSTR(MP_QSTR_altitude), MP_ROM_PTR(&gnss_altitude_obj) },
+ { MP_ROM_QSTR(MP_QSTR_timestamp), MP_ROM_PTR(&gnss_timestamp_obj) },
+ { MP_ROM_QSTR(MP_QSTR_fix), MP_ROM_PTR(&gnss_fix_obj) }
+};
+STATIC MP_DEFINE_CONST_DICT(gnss_locals_dict, gnss_locals_dict_table);
+
+const mp_obj_type_t gnss_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_GNSS,
+ .make_new = gnss_make_new,
+ .locals_dict = (mp_obj_dict_t*)&gnss_locals_dict,
+};
diff --git a/shared-bindings/gnss/GNSS.h b/shared-bindings/gnss/GNSS.h
new file mode 100644
index 000000000..61ae35b12
--- /dev/null
+++ b/shared-bindings/gnss/GNSS.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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_GNSS_GNSS_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_GNSS_GNSS_H
+
+#include "common-hal/gnss/GNSS.h"
+#include "shared-bindings/gnss/SatelliteSystem.h"
+#include "shared-bindings/gnss/PositionFix.h"
+
+#include "lib/timeutils/timeutils.h"
+
+extern const mp_obj_type_t gnss_type;
+
+void common_hal_gnss_construct(gnss_obj_t *self, unsigned long selection);
+void common_hal_gnss_deinit(gnss_obj_t *self);
+bool common_hal_gnss_deinited(gnss_obj_t *self);
+void common_hal_gnss_update(gnss_obj_t *self);
+
+mp_float_t common_hal_gnss_get_latitude(gnss_obj_t *self);
+mp_float_t common_hal_gnss_get_longitude(gnss_obj_t *self);
+mp_float_t common_hal_gnss_get_altitude(gnss_obj_t *self);
+void common_hal_gnss_get_timestamp(gnss_obj_t *self, timeutils_struct_time_t *tm);
+gnss_positionfix_t common_hal_gnss_get_fix(gnss_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_GNSS_GNSS_H
diff --git a/shared-bindings/gnss/PositionFix.c b/shared-bindings/gnss/PositionFix.c
new file mode 100644
index 000000000..106a28c34
--- /dev/null
+++ b/shared-bindings/gnss/PositionFix.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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/gnss/PositionFix.h"
+
+//| class PositionFix:
+//| """Position fix mode"""
+//|
+//| def __init__(self, ):
+//| """Enum-like class to define the position fix mode."""
+//|
+//| INVALID: Any = ...
+//| """No measurement.
+//|
+//| :type gnss.PositionFix:"""
+//|
+//| FIX_2D: Any = ...
+//| """2D fix.
+//|
+//| :type gnss.PositionFix:"""
+//|
+//| FIX_3D: Any = ...
+//| """3D fix.
+//|
+//| :type gnss.PositionFix:"""
+//|
+const mp_obj_type_t gnss_positionfix_type;
+
+const gnss_positionfix_obj_t gnss_positionfix_invalid_obj = {
+ { &gnss_positionfix_type },
+};
+
+const gnss_positionfix_obj_t gnss_positionfix_fix2d_obj = {
+ { &gnss_positionfix_type },
+};
+
+const gnss_positionfix_obj_t gnss_positionfix_fix3d_obj = {
+ { &gnss_positionfix_type },
+};
+
+gnss_positionfix_t gnss_positionfix_obj_to_type(mp_obj_t obj) {
+ gnss_positionfix_t posfix = POSITIONFIX_INVALID;
+ if (obj == MP_ROM_PTR(&gnss_positionfix_fix2d_obj)) {
+ posfix = POSITIONFIX_2D;
+ } else if (obj == MP_ROM_PTR(&gnss_positionfix_fix3d_obj)) {
+ posfix = POSITIONFIX_3D;
+ }
+ return posfix;
+}
+
+mp_obj_t gnss_positionfix_type_to_obj(gnss_positionfix_t posfix) {
+ switch (posfix) {
+ case POSITIONFIX_2D:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_positionfix_fix2d_obj);
+ case POSITIONFIX_3D:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_positionfix_fix3d_obj);
+ case POSITIONFIX_INVALID:
+ default:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_positionfix_invalid_obj);
+ }
+}
+
+STATIC const mp_rom_map_elem_t gnss_positionfix_locals_dict_table[] = {
+ {MP_ROM_QSTR(MP_QSTR_INVALID), MP_ROM_PTR(&gnss_positionfix_invalid_obj)},
+ {MP_ROM_QSTR(MP_QSTR_FIX_2D), MP_ROM_PTR(&gnss_positionfix_fix2d_obj)},
+ {MP_ROM_QSTR(MP_QSTR_FIX_3D), MP_ROM_PTR(&gnss_positionfix_fix3d_obj)},
+};
+STATIC MP_DEFINE_CONST_DICT(gnss_positionfix_locals_dict, gnss_positionfix_locals_dict_table);
+
+STATIC void gnss_positionfix_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ qstr posfix = MP_QSTR_INVALID;
+ if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_positionfix_fix2d_obj)) {
+ posfix = MP_QSTR_FIX_2D;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_positionfix_fix3d_obj)) {
+ posfix = MP_QSTR_FIX_3D;
+ }
+ mp_printf(print, "%q.%q.%q", MP_QSTR_gnss, MP_QSTR_PositionFix, posfix);
+}
+
+const mp_obj_type_t gnss_positionfix_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PositionFix,
+ .print = gnss_positionfix_print,
+ .locals_dict = (mp_obj_t)&gnss_positionfix_locals_dict,
+};
diff --git a/shared-bindings/gnss/PositionFix.h b/shared-bindings/gnss/PositionFix.h
new file mode 100644
index 000000000..64497cb59
--- /dev/null
+++ b/shared-bindings/gnss/PositionFix.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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_GNSS_POSITIONFIX_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_GNSS_POSITIONFIX_H
+
+#include "py/obj.h"
+
+typedef enum {
+ POSITIONFIX_INVALID,
+ POSITIONFIX_2D,
+ POSITIONFIX_3D,
+} gnss_positionfix_t;
+
+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);
+
+typedef struct {
+ mp_obj_base_t base;
+} gnss_positionfix_obj_t;
+extern const gnss_positionfix_obj_t gnss_positionfix_invalid_obj;
+extern const gnss_positionfix_obj_t gnss_positionfix_fix2d_obj;
+extern const gnss_positionfix_obj_t gnss_positionfix_fix3d_obj;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_GNSS_POSITIONFIX_H
diff --git a/shared-bindings/gnss/SatelliteSystem.c b/shared-bindings/gnss/SatelliteSystem.c
new file mode 100644
index 000000000..badc02b96
--- /dev/null
+++ b/shared-bindings/gnss/SatelliteSystem.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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/gnss/SatelliteSystem.h"
+
+//| class SatelliteSystem:
+//| """Satellite system type"""
+//|
+//| def __init__(self, ):
+//| """Enum-like class to define the satellite system type."""
+//|
+//| GPS: Any = ...
+//| """Global Positioning System.
+//|
+//| :type gnss.SatelliteSystem:"""
+//|
+//| GLONASS: Any = ...
+//| """GLObal NAvigation Satellite System.
+//|
+//| :type gnss.SatelliteSystem:"""
+//|
+//| SBAS: Any = ...
+//| """Satellite Based Augmentation System.
+//|
+//| :type gnss.SatelliteSystem:"""
+//|
+//| QZSS_L1CA: Any = ...
+//| """Quasi-Zenith Satellite System L1C/A.
+//|
+//| :type gnss.SatelliteSystem:"""
+//|
+//| QZSS_L1S: Any = ...
+//| """Quasi-Zenith Satellite System L1S.
+//|
+//| :type gnss.SatelliteSystem:"""
+//|
+const mp_obj_type_t gnss_satellitesystem_type;
+
+const gnss_satellitesystem_obj_t gnss_satellitesystem_gps_obj = {
+ { &gnss_satellitesystem_type },
+};
+
+const gnss_satellitesystem_obj_t gnss_satellitesystem_glonass_obj = {
+ { &gnss_satellitesystem_type },
+};
+
+const gnss_satellitesystem_obj_t gnss_satellitesystem_sbas_obj = {
+ { &gnss_satellitesystem_type },
+};
+
+const gnss_satellitesystem_obj_t gnss_satellitesystem_qzss_l1ca_obj = {
+ { &gnss_satellitesystem_type },
+};
+
+const gnss_satellitesystem_obj_t gnss_satellitesystem_qzss_l1s_obj = {
+ { &gnss_satellitesystem_type },
+};
+
+gnss_satellitesystem_t gnss_satellitesystem_obj_to_type(mp_obj_t obj) {
+ if (obj == MP_ROM_PTR(&gnss_satellitesystem_gps_obj)) {
+ return SATELLITESYSTEM_GPS;
+ } else if (obj == MP_ROM_PTR(&gnss_satellitesystem_glonass_obj)) {
+ return SATELLITESYSTEM_GLONASS;
+ } else if (obj == MP_ROM_PTR(&gnss_satellitesystem_sbas_obj)) {
+ return SATELLITESYSTEM_SBAS;
+ } else if (obj == MP_ROM_PTR(&gnss_satellitesystem_qzss_l1ca_obj)) {
+ return SATELLITESYSTEM_QZSS_L1CA;
+ } else if (obj == MP_ROM_PTR(&gnss_satellitesystem_qzss_l1s_obj)) {
+ return SATELLITESYSTEM_QZSS_L1S;
+ }
+ return SATELLITESYSTEM_NONE;
+}
+
+mp_obj_t gnss_satellitesystem_type_to_obj(gnss_satellitesystem_t system) {
+ switch (system) {
+ case SATELLITESYSTEM_GPS:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_satellitesystem_gps_obj);
+ case SATELLITESYSTEM_GLONASS:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_satellitesystem_glonass_obj);
+ case SATELLITESYSTEM_SBAS:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_satellitesystem_sbas_obj);
+ case SATELLITESYSTEM_QZSS_L1CA:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_satellitesystem_qzss_l1ca_obj);
+ case SATELLITESYSTEM_QZSS_L1S:
+ return (mp_obj_t)MP_ROM_PTR(&gnss_satellitesystem_qzss_l1s_obj);
+ case SATELLITESYSTEM_NONE:
+ default:
+ return (mp_obj_t)MP_ROM_PTR(&mp_const_none_obj);
+ }
+}
+
+STATIC const mp_rom_map_elem_t gnss_satellitesystem_locals_dict_table[] = {
+ {MP_ROM_QSTR(MP_QSTR_GPS), MP_ROM_PTR(&gnss_satellitesystem_gps_obj)},
+ {MP_ROM_QSTR(MP_QSTR_GLONASS), MP_ROM_PTR(&gnss_satellitesystem_glonass_obj)},
+ {MP_ROM_QSTR(MP_QSTR_SBAS), MP_ROM_PTR(&gnss_satellitesystem_sbas_obj)},
+ {MP_ROM_QSTR(MP_QSTR_QZSS_L1CA), MP_ROM_PTR(&gnss_satellitesystem_qzss_l1ca_obj)},
+ {MP_ROM_QSTR(MP_QSTR_QZSS_L1S), MP_ROM_PTR(&gnss_satellitesystem_qzss_l1s_obj)},
+};
+STATIC MP_DEFINE_CONST_DICT(gnss_satellitesystem_locals_dict, gnss_satellitesystem_locals_dict_table);
+
+STATIC void gnss_satellitesystem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ qstr system = MP_QSTR_None;
+ if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_satellitesystem_gps_obj)) {
+ system = MP_QSTR_GPS;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_satellitesystem_glonass_obj)) {
+ system = MP_QSTR_GLONASS;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_satellitesystem_sbas_obj)) {
+ system = MP_QSTR_SBAS;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_satellitesystem_qzss_l1ca_obj)) {
+ system = MP_QSTR_QZSS_L1CA;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_satellitesystem_qzss_l1s_obj)) {
+ system = MP_QSTR_QZSS_L1S;
+ }
+ mp_printf(print, "%q.%q.%q", MP_QSTR_gnss, MP_QSTR_SatelliteSystem, system);
+}
+
+const mp_obj_type_t gnss_satellitesystem_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SatelliteSystem,
+ .print = gnss_satellitesystem_print,
+ .locals_dict = (mp_obj_t)&gnss_satellitesystem_locals_dict,
+};
diff --git a/shared-bindings/gnss/SatelliteSystem.h b/shared-bindings/gnss/SatelliteSystem.h
new file mode 100644
index 000000000..484e861ab
--- /dev/null
+++ b/shared-bindings/gnss/SatelliteSystem.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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_GNSS_SATELLITESYSTEM_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_GNSS_SATELLITESYSTEM_H
+
+#include "py/obj.h"
+
+typedef enum {
+ SATELLITESYSTEM_NONE = 0,
+ SATELLITESYSTEM_GPS = (1U << 0),
+ SATELLITESYSTEM_GLONASS = (1U << 1),
+ SATELLITESYSTEM_SBAS = (1U << 2),
+ SATELLITESYSTEM_QZSS_L1CA = (1U << 3),
+ SATELLITESYSTEM_QZSS_L1S = (1U << 4),
+} gnss_satellitesystem_t;
+
+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);
+
+typedef struct {
+ mp_obj_base_t base;
+} gnss_satellitesystem_obj_t;
+extern const gnss_satellitesystem_obj_t gnss_satellitesystem_gps_obj;
+extern const gnss_satellitesystem_obj_t gnss_satellitesystem_glonass_obj;
+extern const gnss_satellitesystem_obj_t gnss_satellitesystem_sbas_obj;
+extern const gnss_satellitesystem_obj_t gnss_satellitesystem_qzss_l1ca_obj;
+extern const gnss_satellitesystem_obj_t gnss_satellitesystem_qzss_l1s_obj;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_GNSS_SATELLITESYSTEM_H
diff --git a/shared-bindings/gnss/__init__.c b/shared-bindings/gnss/__init__.c
new file mode 100644
index 000000000..b3cf722f1
--- /dev/null
+++ b/shared-bindings/gnss/__init__.c
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "shared-bindings/gnss/GNSS.h"
+#include "shared-bindings/gnss/SatelliteSystem.h"
+#include "shared-bindings/gnss/PositionFix.h"
+#include "shared-bindings/util.h"
+
+//| """Global Navigation Satellite System
+//|
+//| The `gnss` module contains classes to control the GNSS and acquire positioning information."""
+//|
+STATIC const mp_rom_map_elem_t gnss_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gnss) },
+ { MP_ROM_QSTR(MP_QSTR_GNSS), MP_ROM_PTR(&gnss_type) },
+
+ // Enum-like Classes.
+ { MP_ROM_QSTR(MP_QSTR_SatelliteSystem), MP_ROM_PTR(&gnss_satellitesystem_type) },
+ { MP_ROM_QSTR(MP_QSTR_PositionFix), MP_ROM_PTR(&gnss_positionfix_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(gnss_module_globals, gnss_module_globals_table);
+
+const mp_obj_module_t gnss_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&gnss_module_globals,
+};
diff --git a/shared-bindings/help.rst b/shared-bindings/help.rst
new file mode 100644
index 000000000..f6d72a556
--- /dev/null
+++ b/shared-bindings/help.rst
@@ -0,0 +1,31 @@
+.. 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.
+
+:func:`help` - Built-in method to provide helpful information
+==============================================================
+
+.. function:: help(object=None)
+
+ Prints a help method about the given object. When ``object`` is none,
+ prints general port information.
diff --git a/shared-bindings/i2cperipheral/I2CPeripheral.c b/shared-bindings/i2cperipheral/I2CPeripheral.c
new file mode 100644
index 000000000..4a3900174
--- /dev/null
+++ b/shared-bindings/i2cperipheral/I2CPeripheral.c
@@ -0,0 +1,435 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Noralf Trønnes
+ *
+ * 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/microcontroller/Pin.h"
+#include "shared-bindings/i2cperipheral/I2CPeripheral.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-bindings/util.h"
+
+#include "lib/utils/buffer_helper.h"
+#include "lib/utils/context_manager_helpers.h"
+#include "lib/utils/interrupt_char.h"
+
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "py/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+
+STATIC mp_obj_t mp_obj_new_i2cperipheral_i2c_peripheral_request(i2cperipheral_i2c_peripheral_obj_t *peripheral, uint8_t address, bool is_read, bool is_restart) {
+ i2cperipheral_i2c_peripheral_request_obj_t *self = m_new_obj(i2cperipheral_i2c_peripheral_request_obj_t);
+ self->base.type = &i2cperipheral_i2c_peripheral_request_type;
+ self->peripheral = peripheral;
+ self->address = address;
+ self->is_read = is_read;
+ self->is_restart = is_restart;
+ return (mp_obj_t)self;
+}
+
+//| class I2CPeripheral:
+//| """Two wire serial protocol peripheral"""
+//|
+//| def __init__(self, scl: microcontroller.Pin, sda: microcontroller.Pin, addresses: tuple, smbus: bool = False):
+//| """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 bool smbus: Use SMBUS timings if the hardware supports it"""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ i2cperipheral_i2c_peripheral_obj_t *self = m_new_obj(i2cperipheral_i2c_peripheral_obj_t);
+ self->base.type = &i2cperipheral_i2c_peripheral_type;
+ enum { ARG_scl, ARG_sda, ARG_addresses, ARG_smbus };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_addresses, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_smbus, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ };
+ 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* scl = validate_obj_is_free_pin(args[ARG_scl].u_obj);
+ const mcu_pin_obj_t* sda = validate_obj_is_free_pin(args[ARG_sda].u_obj);
+
+ mp_obj_iter_buf_t iter_buf;
+ mp_obj_t iterable = mp_getiter(args[ARG_addresses].u_obj, &iter_buf);
+ mp_obj_t item;
+ uint8_t *addresses = NULL;
+ unsigned int i = 0;
+ 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"));
+ }
+ if (value < 0x00 || value > 0x7f) {
+ mp_raise_ValueError(translate("address out of bounds"));
+ }
+ addresses = m_renew(uint8_t, addresses, i, i + 1);
+ addresses[i++] = value;
+ }
+ if (i == 0) {
+ mp_raise_ValueError(translate("addresses is empty"));
+ }
+
+ common_hal_i2cperipheral_i2c_peripheral_construct(self, scl, sda, addresses, i, args[ARG_smbus].u_bool);
+ return (mp_obj_t)self;
+}
+
+//| def deinit(self, ) -> Any:
+//| """Releases control of the underlying hardware so other classes can use it."""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_obj_deinit(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cperipheral_i2c_peripheral_type));
+ i2cperipheral_i2c_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_i2cperipheral_i2c_peripheral_deinit(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(i2cperipheral_i2c_peripheral_deinit_obj, i2cperipheral_i2c_peripheral_obj_deinit);
+
+//| def __enter__(self, ) -> Any:
+//| """No-op used in Context Managers."""
+//| ...
+//|
+// Provided by context manager helper.
+
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware on context exit. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ mp_check_self(MP_OBJ_IS_TYPE(args[0], &i2cperipheral_i2c_peripheral_type));
+ i2cperipheral_i2c_peripheral_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ common_hal_i2cperipheral_i2c_peripheral_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cperipheral_i2c_peripheral___exit___obj, 4, 4, i2cperipheral_i2c_peripheral_obj___exit__);
+
+//| def request(self, timeout: float = -1) -> Any:
+//| """Wait for an I2C request.
+//|
+//| :param float timeout: Timeout in seconds. Zero means wait forever, a negative value means check once
+//| :return: I2C Slave Request or None if timeout=-1 and there's no request
+//| :rtype: ~i2cperipheral.I2CPeripheralRequest"""
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &i2cperipheral_i2c_peripheral_type));
+ i2cperipheral_i2c_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ if(common_hal_i2cperipheral_i2c_peripheral_deinited(self)) {
+ raise_deinited_error();
+ }
+ enum { ARG_timeout };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_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);
+
+ #if MICROPY_PY_BUILTINS_FLOAT
+ float f = mp_obj_get_float(args[ARG_timeout].u_obj) * 1000;
+ int timeout_ms = (int)f;
+ #else
+ int timeout_ms = mp_obj_get_int(args[ARG_timeout].u_obj) * 1000;
+ #endif
+
+ bool forever = false;
+ uint64_t timeout_end = 0;
+ if (timeout_ms == 0) {
+ forever = true;
+ } else if (timeout_ms > 0) {
+ timeout_end = common_hal_time_monotonic() + timeout_ms;
+ }
+
+ int last_error = 0;
+
+ do {
+ uint8_t address;
+ bool is_read;
+ bool is_restart;
+
+ RUN_BACKGROUND_TASKS;
+ if (mp_hal_is_interrupted()) {
+ return mp_const_none;
+ }
+
+ int status = common_hal_i2cperipheral_i2c_peripheral_is_addressed(self, &address, &is_read, &is_restart);
+ if (status < 0) {
+ // On error try one more time before bailing out
+ if (last_error) {
+ mp_raise_OSError(last_error);
+ }
+ last_error = -status;
+ mp_hal_delay_ms(10);
+ continue;
+ }
+
+ last_error = 0;
+
+ if (status == 0) {
+ mp_hal_delay_us(10);
+ continue;
+ }
+
+ return mp_obj_new_i2cperipheral_i2c_peripheral_request(self, address, is_read, is_restart);
+ } while (forever || common_hal_time_monotonic() < timeout_end);
+
+ if (timeout_ms > 0) {
+ mp_raise_OSError(MP_ETIMEDOUT);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(i2cperipheral_i2c_peripheral_request_obj, 1, i2cperipheral_i2c_peripheral_request);
+
+STATIC const mp_rom_map_elem_t i2cperipheral_i2c_peripheral_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2cperipheral_i2c_peripheral___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_request), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_obj) },
+
+};
+
+STATIC MP_DEFINE_CONST_DICT(i2cperipheral_i2c_peripheral_locals_dict, i2cperipheral_i2c_peripheral_locals_dict_table);
+
+const mp_obj_type_t i2cperipheral_i2c_peripheral_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_I2CPeripheral,
+ .make_new = i2cperipheral_i2c_peripheral_make_new,
+ .locals_dict = (mp_obj_dict_t*)&i2cperipheral_i2c_peripheral_locals_dict,
+};
+
+//| class I2CPeripheralRequest:
+//|
+//| def __init__(self, peripheral: i2cperipheral.I2CPeripheral, address: int, is_read: bool, is_restart: bool):
+//| """Information about an I2C transfer request
+//| This cannot be instantiated directly, but is returned by :py:meth:`I2CPeripheral.request`.
+//|
+//| :param peripheral: The I2CPeripheral object receiving this request
+//| :param address: I2C address
+//| :param is_read: True if the main peripheral is requesting data
+//| :param is_restart: Repeated Start Condition"""
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_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, 4, 4, false);
+ return mp_obj_new_i2cperipheral_i2c_peripheral_request(args[0], mp_obj_get_int(args[1]), mp_obj_is_true(args[2]), mp_obj_is_true(args[3]));
+}
+
+//| def __enter__(self, ) -> Any:
+//| """No-op used in Context Managers."""
+//| ...
+//|
+// Provided by context manager helper.
+
+//| def __exit__(self, ) -> Any:
+//| """Close the request."""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ mp_check_self(MP_OBJ_IS_TYPE(args[0], &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ common_hal_i2cperipheral_i2c_peripheral_close(self->peripheral);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cperipheral_i2c_peripheral_request___exit___obj, 4, 4, i2cperipheral_i2c_peripheral_request_obj___exit__);
+
+//| address: int = ...
+//| """The I2C address of the request."""
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_get_address(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_int(self->address);
+}
+MP_DEFINE_CONST_PROP_GET(i2cperipheral_i2c_peripheral_request_address_obj, i2cperipheral_i2c_peripheral_request_get_address);
+
+//| is_read: bool = ...
+//| """The I2C main controller is reading from this peripheral."""
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_get_is_read(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(self->is_read);
+}
+MP_DEFINE_CONST_PROP_GET(i2cperipheral_i2c_peripheral_request_is_read_obj, i2cperipheral_i2c_peripheral_request_get_is_read);
+
+//| is_restart: bool = ...
+//| """Is Repeated Start Condition."""
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_get_is_restart(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(self->is_restart);
+}
+MP_DEFINE_CONST_PROP_GET(i2cperipheral_i2c_peripheral_request_is_restart_obj, i2cperipheral_i2c_peripheral_request_get_is_restart);
+
+//| def read(self, n: int = -1, ack: bool = True) -> bytearray:
+//| """Read data.
+//| If ack=False, the caller is responsible for calling :py:meth:`I2CPeripheralRequest.ack`.
+//|
+//| :param n: Number of bytes to read (negative means all)
+//| :param ack: Whether or not to send an ACK after the n'th byte
+//| :return: Bytes read"""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ enum { ARG_n, ARG_ack };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_n, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_ack, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ };
+ 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);
+
+ if (self->is_read) {
+ mp_raise_OSError(MP_EACCES);
+ }
+
+ int n = args[ARG_n].u_int;
+ if (n == 0) {
+ return mp_obj_new_bytearray(0, NULL);
+ }
+ bool ack = args[ARG_ack].u_bool;
+
+ int i = 0;
+ uint8_t *buffer = NULL;
+ uint64_t timeout_end = common_hal_time_monotonic() + 10 * 1000;
+ while (common_hal_time_monotonic() < timeout_end) {
+ RUN_BACKGROUND_TASKS;
+ if (mp_hal_is_interrupted()) {
+ break;
+ }
+
+ uint8_t data;
+ int num = common_hal_i2cperipheral_i2c_peripheral_read_byte(self->peripheral, &data);
+ if (num == 0) {
+ break;
+ }
+
+ buffer = m_renew(uint8_t, buffer, i, i + 1);
+ buffer[i++] = data;
+ if (i == n) {
+ if (ack) {
+ common_hal_i2cperipheral_i2c_peripheral_ack(self->peripheral, true);
+ }
+ break;
+ }
+ common_hal_i2cperipheral_i2c_peripheral_ack(self->peripheral, true);
+ }
+
+ return mp_obj_new_bytearray(i, buffer);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(i2cperipheral_i2c_peripheral_request_read_obj, 1, i2cperipheral_i2c_peripheral_request_read);
+
+//| def write(self, buffer: bytearray) -> int:
+//| """Write the data contained in buffer.
+//|
+//| :param buffer: Write out the data in this buffer
+//| :return: Number of bytes written"""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_write(mp_obj_t self_in, mp_obj_t buf_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (!self->is_read) {
+ mp_raise_OSError(MP_EACCES);
+ }
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+
+ for (size_t i = 0; i < bufinfo.len; i++) {
+ RUN_BACKGROUND_TASKS;
+ if (mp_hal_is_interrupted()) {
+ break;
+ }
+
+ int num = common_hal_i2cperipheral_i2c_peripheral_write_byte(self->peripheral, ((uint8_t *)(bufinfo.buf))[i]);
+ if (num == 0) {
+ return mp_obj_new_int(i);
+ }
+ }
+
+ return mp_obj_new_int(bufinfo.len);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(i2cperipheral_i2c_peripheral_request_write_obj, i2cperipheral_i2c_peripheral_request_write);
+
+//| def ack(self, ack: bool = True) -> Any:
+//| """Acknowledge or Not Acknowledge last byte received.
+//| Use together with :py:meth:`I2CPeripheralRequest.read` ack=False.
+//|
+//| :param ack: Whether to send an ACK or NACK"""
+//| ...
+//|
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_ack(uint n_args, const mp_obj_t *args) {
+ mp_check_self(MP_OBJ_IS_TYPE(args[0], &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ bool ack = (n_args == 1) ? true : mp_obj_is_true(args[1]);
+
+ if (self->is_read) {
+ mp_raise_OSError(MP_EACCES);
+ }
+
+ common_hal_i2cperipheral_i2c_peripheral_ack(self->peripheral, ack);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cperipheral_i2c_peripheral_request_ack_obj, 1, 2, i2cperipheral_i2c_peripheral_request_ack);
+
+STATIC mp_obj_t i2cperipheral_i2c_peripheral_request_close(mp_obj_t self_in) {
+ mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cperipheral_i2c_peripheral_request_type));
+ i2cperipheral_i2c_peripheral_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_i2cperipheral_i2c_peripheral_close(self->peripheral);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(i2cperipheral_i2c_peripheral_request_close_obj, i2cperipheral_i2c_peripheral_request_close);
+
+STATIC const mp_rom_map_elem_t i2cperipheral_i2c_peripheral_request_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_address_obj) },
+ { MP_ROM_QSTR(MP_QSTR_is_read), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_is_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_is_restart), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_is_restart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ack), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_ack_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_request_close_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(i2cperipheral_i2c_peripheral_request_locals_dict, i2cperipheral_i2c_peripheral_request_locals_dict_table);
+
+const mp_obj_type_t i2cperipheral_i2c_peripheral_request_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_I2CPeripheralRequest,
+ .make_new = i2cperipheral_i2c_peripheral_request_make_new,
+ .locals_dict = (mp_obj_dict_t*)&i2cperipheral_i2c_peripheral_request_locals_dict,
+};
diff --git a/shared-bindings/i2cslave/I2CSlave.h b/shared-bindings/i2cperipheral/I2CPeripheral.h
index abb761416..3035cfbfe 100644
--- a/shared-bindings/i2cslave/I2CSlave.h
+++ b/shared-bindings/i2cperipheral/I2CPeripheral.h
@@ -30,31 +30,31 @@
#include "py/obj.h"
#include "common-hal/microcontroller/Pin.h"
-#include "common-hal/i2cslave/I2CSlave.h"
+#include "common-hal/i2cperipheral/I2CPeripheral.h"
typedef struct {
mp_obj_base_t base;
- i2cslave_i2c_slave_obj_t *slave;
+ i2cperipheral_i2c_peripheral_obj_t *peripheral;
uint16_t address;
bool is_read;
bool is_restart;
-} i2cslave_i2c_slave_request_obj_t;
+} i2cperipheral_i2c_peripheral_request_obj_t;
-extern const mp_obj_type_t i2cslave_i2c_slave_request_type;
+extern const mp_obj_type_t i2cperipheral_i2c_peripheral_request_type;
-extern const mp_obj_type_t i2cslave_i2c_slave_type;
+extern const mp_obj_type_t i2cperipheral_i2c_peripheral_type;
-extern void common_hal_i2cslave_i2c_slave_construct(i2cslave_i2c_slave_obj_t *self,
+extern void common_hal_i2cperipheral_i2c_peripheral_construct(i2cperipheral_i2c_peripheral_obj_t *self,
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda,
uint8_t *addresses, unsigned int num_addresses, bool smbus);
-extern void common_hal_i2cslave_i2c_slave_deinit(i2cslave_i2c_slave_obj_t *self);
-extern bool common_hal_i2cslave_i2c_slave_deinited(i2cslave_i2c_slave_obj_t *self);
+extern void common_hal_i2cperipheral_i2c_peripheral_deinit(i2cperipheral_i2c_peripheral_obj_t *self);
+extern bool common_hal_i2cperipheral_i2c_peripheral_deinited(i2cperipheral_i2c_peripheral_obj_t *self);
-extern int common_hal_i2cslave_i2c_slave_is_addressed(i2cslave_i2c_slave_obj_t *self,
+extern int common_hal_i2cperipheral_i2c_peripheral_is_addressed(i2cperipheral_i2c_peripheral_obj_t *self,
uint8_t *address, bool *is_read, bool *is_restart);
-extern int common_hal_i2cslave_i2c_slave_read_byte(i2cslave_i2c_slave_obj_t *self, uint8_t *data);
-extern int common_hal_i2cslave_i2c_slave_write_byte(i2cslave_i2c_slave_obj_t *self, uint8_t data);
-extern void common_hal_i2cslave_i2c_slave_ack(i2cslave_i2c_slave_obj_t *self, bool ack);
-extern void common_hal_i2cslave_i2c_slave_close(i2cslave_i2c_slave_obj_t *self);
+extern int common_hal_i2cperipheral_i2c_peripheral_read_byte(i2cperipheral_i2c_peripheral_obj_t *self, uint8_t *data);
+extern int common_hal_i2cperipheral_i2c_peripheral_write_byte(i2cperipheral_i2c_peripheral_obj_t *self, uint8_t data);
+extern void common_hal_i2cperipheral_i2c_peripheral_ack(i2cperipheral_i2c_peripheral_obj_t *self, bool ack);
+extern void common_hal_i2cperipheral_i2c_peripheral_close(i2cperipheral_i2c_peripheral_obj_t *self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_I2C_SLAVE_H
diff --git a/shared-bindings/i2cslave/__init__.c b/shared-bindings/i2cperipheral/__init__.c
index 1c692e54e..e2cb8509d 100644
--- a/shared-bindings/i2cslave/__init__.c
+++ b/shared-bindings/i2cperipheral/__init__.c
@@ -30,44 +30,32 @@
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
-//#include "shared-bindings/i2cslave/__init__.h"
-#include "shared-bindings/i2cslave/I2CSlave.h"
+//#include "shared-bindings/i2cperipheral/__init__.h"
+#include "shared-bindings/i2cperipheral/I2CPeripheral.h"
#include "py/runtime.h"
-//| :mod:`i2cslave` --- Two wire serial protocol slave
-//| ==================================================
+//| """Two wire serial protocol peripheral
//|
-//| .. module:: i2cslave
-//| :synopsis: Two wire serial protocol slave
-//| :platform: SAMD21, SAMD51
+//| The `i2cperipheral` module contains classes to support an I2C peripheral.
//|
-//| The `i2cslave` module contains classes to support a I2C slave.
-//|
-//| Classes
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| I2CSlave
-//|
-//| Example emulating 2 devices::
+//| Example emulating a peripheral with 2 addresses (read and write)::
//|
//| import board
-//| from i2cslave import I2CSlave
+//| from i2cperipheral import I2CPeripheral
//|
//| regs = [0] * 16
//| index = 0
//|
-//| with I2CSlave(board.SCL, board.SDA, (0x40, 0x41)) as slave:
+//| with I2CPeripheral(board.SCL, board.SDA, (0x40, 0x41)) as device:
//| while True:
-//| r = slave.request()
+//| r = device.request()
//| if not r:
//| # Maybe do some housekeeping
//| continue
-//| with r: # Closes the transfer if necessary by sending a NACK or feeding the master dummy bytes
+//| with r: # Closes the transfer if necessary by sending a NACK or feeding dummy bytes
//| if r.address == 0x40:
-//| if not r.is_read: # Master write which is Slave read
+//| if not r.is_read: # Main write which is Selected read
//| b = r.read(1)
//| if not b or b[0] > 15:
//| break
@@ -75,11 +63,11 @@
//| b = r.read(1)
//| if b:
//| regs[index] = b[0]
-//| elif r.is_restart: # Combined transfer: This is the Master read message
+//| elif r.is_restart: # Combined transfer: This is the Main read message
//| n = r.write(bytes([regs[index]]))
//| #else:
//| # A read transfer is not supported in this example
-//| # If the Master tries, it will get 0xff byte(s) by the ctx manager (r.close())
+//| # If the microcontroller tries, it will get 0xff byte(s) by the ctx manager (r.close())
//| elif r.address == 0x41:
//| if not r.is_read:
//| b = r.read(1)
@@ -87,7 +75,7 @@
//| # do something
//| pass
//|
-//| This example sets up an I2C slave that can be accessed from Linux like this::
+//| This example sets up an I2C device that can be accessed from Linux like this::
//|
//| $ i2cget -y 1 0x40 0x01
//| 0x00
@@ -96,22 +84,23 @@
//| 0xaa
//|
//| .. warning::
-//| I2CSlave makes use of clock stretching in order to slow down the master.
-//| Make sure the I2C master supports this.
+//| I2CPeripheral makes use of clock stretching in order to slow down
+//| the host.
+//| Make sure the I2C host supports this.
//|
//| Raspberry Pi in particular does not support this with its I2C hw block.
//| This can be worked around by using the ``i2c-gpio`` bit banging driver.
-//| Since the RPi firmware uses the hw i2c, it's not possible to emulate a HAT eeprom.
+//| Since the RPi firmware uses the hw i2c, it's not possible to emulate a HAT eeprom."""
//|
-STATIC const mp_rom_map_elem_t i2cslave_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_i2cslave) },
- { MP_ROM_QSTR(MP_QSTR_I2CSlave), MP_ROM_PTR(&i2cslave_i2c_slave_type) },
+STATIC const mp_rom_map_elem_t i2cperipheral_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_i2cperipheral) },
+ { MP_ROM_QSTR(MP_QSTR_I2CPeripheral), MP_ROM_PTR(&i2cperipheral_i2c_peripheral_type) },
};
-STATIC MP_DEFINE_CONST_DICT(i2cslave_module_globals, i2cslave_module_globals_table);
+STATIC MP_DEFINE_CONST_DICT(i2cperipheral_module_globals, i2cperipheral_module_globals_table);
-const mp_obj_module_t i2cslave_module = {
+const mp_obj_module_t i2cperipheral_module = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&i2cslave_module_globals,
+ .globals = (mp_obj_dict_t*)&i2cperipheral_module_globals,
};
diff --git a/shared-bindings/i2cslave/I2CSlave.c b/shared-bindings/i2cslave/I2CSlave.c
deleted file mode 100644
index c98ea52e0..000000000
--- a/shared-bindings/i2cslave/I2CSlave.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Noralf Trønnes
- *
- * 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/microcontroller/Pin.h"
-#include "shared-bindings/i2cslave/I2CSlave.h"
-#include "shared-bindings/time/__init__.h"
-#include "shared-bindings/util.h"
-
-#include "lib/utils/buffer_helper.h"
-#include "lib/utils/context_manager_helpers.h"
-#include "lib/utils/interrupt_char.h"
-
-#include "py/mperrno.h"
-#include "py/mphal.h"
-#include "py/obj.h"
-#include "py/objproperty.h"
-#include "py/runtime.h"
-
-STATIC mp_obj_t mp_obj_new_i2cslave_i2c_slave_request(i2cslave_i2c_slave_obj_t *slave, uint8_t address, bool is_read, bool is_restart) {
- i2cslave_i2c_slave_request_obj_t *self = m_new_obj(i2cslave_i2c_slave_request_obj_t);
- self->base.type = &i2cslave_i2c_slave_request_type;
- self->slave = slave;
- self->address = address;
- self->is_read = is_read;
- self->is_restart = is_restart;
- return (mp_obj_t)self;
-}
-
-//| .. currentmodule:: i2cslave
-//|
-//| :class:`I2CSlave` --- Two wire serial protocol slave
-//| ----------------------------------------------------
-//|
-//| .. class:: I2CSlave(scl, sda, addresses, smbus=False)
-//|
-//| I2C is a two-wire protocol for communicating between devices.
-//| This implements the slave 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 bool smbus: Use SMBUS timings if the hardware supports it
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- i2cslave_i2c_slave_obj_t *self = m_new_obj(i2cslave_i2c_slave_obj_t);
- self->base.type = &i2cslave_i2c_slave_type;
- enum { ARG_scl, ARG_sda, ARG_addresses, ARG_smbus };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_addresses, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_smbus, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- };
- 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);
-
- assert_pin(args[ARG_scl].u_obj, false);
- assert_pin(args[ARG_sda].u_obj, false);
- const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj);
- assert_pin_free(scl);
- const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
- assert_pin_free(sda);
-
- mp_obj_iter_buf_t iter_buf;
- mp_obj_t iterable = mp_getiter(args[ARG_addresses].u_obj, &iter_buf);
- mp_obj_t item;
- uint8_t *addresses = NULL;
- unsigned int i = 0;
- 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"));
- }
- if (value < 0x00 || value > 0x7f) {
- mp_raise_ValueError(translate("address out of bounds"));
- }
- addresses = m_renew(uint8_t, addresses, i, i + 1);
- addresses[i++] = value;
- }
- if (i == 0) {
- mp_raise_ValueError(translate("addresses is empty"));
- }
-
- common_hal_i2cslave_i2c_slave_construct(self, scl, sda, addresses, i, args[ARG_smbus].u_bool);
- return (mp_obj_t)self;
-}
-
-//| .. method:: deinit()
-//|
-//| Releases control of the underlying hardware so other classes can use it.
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_obj_deinit(mp_obj_t self_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cslave_i2c_slave_type));
- i2cslave_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(self_in);
- common_hal_i2cslave_i2c_slave_deinit(self);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_1(i2cslave_i2c_slave_deinit_obj, i2cslave_i2c_slave_obj_deinit);
-
-//| .. method:: __enter__()
-//|
-//| No-op used in Context Managers.
-//|
-// Provided by context manager helper.
-
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware on context exit. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_obj___exit__(size_t n_args, const mp_obj_t *args) {
- mp_check_self(MP_OBJ_IS_TYPE(args[0], &i2cslave_i2c_slave_type));
- i2cslave_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- common_hal_i2cslave_i2c_slave_deinit(self);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cslave_i2c_slave___exit___obj, 4, 4, i2cslave_i2c_slave_obj___exit__);
-
-//| .. method:: request(timeout=-1)
-//|
-//| Wait for an I2C request from a master.
-//|
-//| :param float timeout: Timeout in seconds. Zero means wait forever, a negative value means check once
-//| :return: I2C Slave Request or None if timeout=-1 and there's no request
-//| :rtype: ~i2cslave.I2CSlaveRequest
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &i2cslave_i2c_slave_type));
- i2cslave_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- if(common_hal_i2cslave_i2c_slave_deinited(self)) {
- raise_deinited_error();
- }
- enum { ARG_timeout };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_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);
-
- #if MICROPY_PY_BUILTINS_FLOAT
- float f = mp_obj_get_float(args[ARG_timeout].u_obj) * 1000;
- int timeout_ms = (int)f;
- #else
- int timeout_ms = mp_obj_get_int(args[ARG_timeout].u_obj) * 1000;
- #endif
-
- bool forever = false;
- uint64_t timeout_end = 0;
- if (timeout_ms == 0) {
- forever = true;
- } else if (timeout_ms > 0) {
- timeout_end = common_hal_time_monotonic() + timeout_ms;
- }
-
- int last_error = 0;
-
- do {
- uint8_t address;
- bool is_read;
- bool is_restart;
-
- RUN_BACKGROUND_TASKS;
- if (mp_hal_is_interrupted()) {
- return mp_const_none;
- }
-
- int status = common_hal_i2cslave_i2c_slave_is_addressed(self, &address, &is_read, &is_restart);
- if (status < 0) {
- // On error try one more time before bailing out
- if (last_error) {
- mp_raise_OSError(last_error);
- }
- last_error = -status;
- mp_hal_delay_ms(10);
- continue;
- }
-
- last_error = 0;
-
- if (status == 0) {
- mp_hal_delay_us(10);
- continue;
- }
-
- return mp_obj_new_i2cslave_i2c_slave_request(self, address, is_read, is_restart);
- } while (forever || common_hal_time_monotonic() < timeout_end);
-
- if (timeout_ms > 0) {
- mp_raise_OSError(MP_ETIMEDOUT);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(i2cslave_i2c_slave_request_obj, 1, i2cslave_i2c_slave_request);
-
-STATIC const mp_rom_map_elem_t i2cslave_i2c_slave_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&i2cslave_i2c_slave_deinit_obj) },
- { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
- { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2cslave_i2c_slave___exit___obj) },
- { MP_ROM_QSTR(MP_QSTR_request), MP_ROM_PTR(&i2cslave_i2c_slave_request_obj) },
-
-};
-
-STATIC MP_DEFINE_CONST_DICT(i2cslave_i2c_slave_locals_dict, i2cslave_i2c_slave_locals_dict_table);
-
-const mp_obj_type_t i2cslave_i2c_slave_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2CSlave,
- .make_new = i2cslave_i2c_slave_make_new,
- .locals_dict = (mp_obj_dict_t*)&i2cslave_i2c_slave_locals_dict,
-};
-
-
-//| :class:`I2CSlaveRequest` --- I2C Slave Request
-//| ----------------------------------------------
-//|
-//| .. class:: I2CSlaveRequest(slave, address, is_read, is_restart)
-//|
-//| I2C transfer request from a master.
-//| This cannot be instantiated directly, but is returned by :py:meth:`I2CSlave.request`.
-//|
-//| :param ~i2cslave.I2CSlave slave: The I2C Slave receiving this request
-//| :param int address: I2C address
-//| :param bool is_read: I2C Master read request
-//| :param bool is_restart: Repeated Start Condition
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_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, 4, 4, false);
- return mp_obj_new_i2cslave_i2c_slave_request(args[0], mp_obj_get_int(args[1]), mp_obj_is_true(args[2]), mp_obj_is_true(args[3]));
-}
-
-//| .. method:: __enter__()
-//|
-//| No-op used in Context Managers.
-//|
-// Provided by context manager helper.
-
-//| .. method:: __exit__()
-//|
-//| Close the request.
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_obj___exit__(size_t n_args, const mp_obj_t *args) {
- mp_check_self(MP_OBJ_IS_TYPE(args[0], &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- common_hal_i2cslave_i2c_slave_close(self->slave);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cslave_i2c_slave_request___exit___obj, 4, 4, i2cslave_i2c_slave_request_obj___exit__);
-
-//| .. attribute:: address
-//|
-//| The I2C address of the request.
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_get_address(mp_obj_t self_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return mp_obj_new_int(self->address);
-}
-MP_DEFINE_CONST_PROP_GET(i2cslave_i2c_slave_request_address_obj, i2cslave_i2c_slave_request_get_address);
-
-//| .. attribute:: is_read
-//|
-//| The I2C master is reading from the device.
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_get_is_read(mp_obj_t self_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return mp_obj_new_bool(self->is_read);
-}
-MP_DEFINE_CONST_PROP_GET(i2cslave_i2c_slave_request_is_read_obj, i2cslave_i2c_slave_request_get_is_read);
-
-//| .. attribute:: is_restart
-//|
-//| Is Repeated Start Condition.
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_get_is_restart(mp_obj_t self_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return mp_obj_new_bool(self->is_restart);
-}
-MP_DEFINE_CONST_PROP_GET(i2cslave_i2c_slave_request_is_restart_obj, i2cslave_i2c_slave_request_get_is_restart);
-
-//| .. method:: read(n=-1, ack=True)
-//|
-//| Read data.
-//| If ack=False, the caller is responsible for calling :py:meth:`I2CSlaveRequest.ack`.
-//|
-//| :param int n: Number of bytes to read (negative means all)
-//| :param bool ack: Whether or not to send an ACK after the n'th byte
-//| :return: Bytes read
-//| :rtype: bytearray
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- enum { ARG_n, ARG_ack };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_n, MP_ARG_INT, {.u_int = -1} },
- { MP_QSTR_ack, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
- };
- 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);
-
- if (self->is_read) {
- mp_raise_OSError(MP_EACCES);
- }
-
- int n = args[ARG_n].u_int;
- if (n == 0) {
- return mp_obj_new_bytearray(0, NULL);
- }
- bool ack = args[ARG_ack].u_bool;
-
- int i = 0;
- uint8_t *buffer = NULL;
- uint64_t timeout_end = common_hal_time_monotonic() + 10 * 1000;
- while (common_hal_time_monotonic() < timeout_end) {
- RUN_BACKGROUND_TASKS;
- if (mp_hal_is_interrupted()) {
- break;
- }
-
- uint8_t data;
- int num = common_hal_i2cslave_i2c_slave_read_byte(self->slave, &data);
- if (num == 0) {
- break;
- }
-
- buffer = m_renew(uint8_t, buffer, i, i + 1);
- buffer[i++] = data;
- if (i == n) {
- if (ack) {
- common_hal_i2cslave_i2c_slave_ack(self->slave, true);
- }
- break;
- }
- common_hal_i2cslave_i2c_slave_ack(self->slave, true);
- }
-
- return mp_obj_new_bytearray(i, buffer);
-}
-MP_DEFINE_CONST_FUN_OBJ_KW(i2cslave_i2c_slave_request_read_obj, 1, i2cslave_i2c_slave_request_read);
-
-//| .. method:: write(buffer)
-//|
-//| Write the data contained in buffer.
-//|
-//| :param bytearray buffer: Write out the data in this buffer
-//| :return: Number of bytes written
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_write(mp_obj_t self_in, mp_obj_t buf_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- if (!self->is_read) {
- mp_raise_OSError(MP_EACCES);
- }
-
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
-
- for (size_t i = 0; i < bufinfo.len; i++) {
- RUN_BACKGROUND_TASKS;
- if (mp_hal_is_interrupted()) {
- break;
- }
-
- int num = common_hal_i2cslave_i2c_slave_write_byte(self->slave, ((uint8_t *)(bufinfo.buf))[i]);
- if (num == 0) {
- return mp_obj_new_int(i);
- }
- }
-
- return mp_obj_new_int(bufinfo.len);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(i2cslave_i2c_slave_request_write_obj, i2cslave_i2c_slave_request_write);
-
-//| .. method:: ack(ack=True)
-//|
-//| Acknowledge or Not Acknowledge last byte received.
-//| Use together with :py:meth:`I2CSlaveRequest.read` ack=False.
-//|
-//| :param bool ack: Whether to send an ACK or NACK
-//|
-STATIC mp_obj_t i2cslave_i2c_slave_request_ack(uint n_args, const mp_obj_t *args) {
- mp_check_self(MP_OBJ_IS_TYPE(args[0], &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- bool ack = (n_args == 1) ? true : mp_obj_is_true(args[1]);
-
- if (self->is_read) {
- mp_raise_OSError(MP_EACCES);
- }
-
- common_hal_i2cslave_i2c_slave_ack(self->slave, ack);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cslave_i2c_slave_request_ack_obj, 1, 2, i2cslave_i2c_slave_request_ack);
-
-STATIC mp_obj_t i2cslave_i2c_slave_request_close(mp_obj_t self_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &i2cslave_i2c_slave_request_type));
- i2cslave_i2c_slave_request_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- common_hal_i2cslave_i2c_slave_close(self->slave);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(i2cslave_i2c_slave_request_close_obj, i2cslave_i2c_slave_request_close);
-
-STATIC const mp_rom_map_elem_t i2cslave_i2c_slave_request_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
- { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2cslave_i2c_slave_request___exit___obj) },
- { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&i2cslave_i2c_slave_request_address_obj) },
- { MP_ROM_QSTR(MP_QSTR_is_read), MP_ROM_PTR(&i2cslave_i2c_slave_request_is_read_obj) },
- { MP_ROM_QSTR(MP_QSTR_is_restart), MP_ROM_PTR(&i2cslave_i2c_slave_request_is_restart_obj) },
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&i2cslave_i2c_slave_request_read_obj) },
- { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&i2cslave_i2c_slave_request_write_obj) },
- { MP_ROM_QSTR(MP_QSTR_ack), MP_ROM_PTR(&i2cslave_i2c_slave_request_ack_obj) },
- { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&i2cslave_i2c_slave_request_close_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(i2cslave_i2c_slave_request_locals_dict, i2cslave_i2c_slave_request_locals_dict_table);
-
-const mp_obj_type_t i2cslave_i2c_slave_request_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2CSlaveRequest,
- .make_new = i2cslave_i2c_slave_request_make_new,
- .locals_dict = (mp_obj_dict_t*)&i2cslave_i2c_slave_request_locals_dict,
-};
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index cbffdb614..bf04ae18b 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -7,13 +7,17 @@ present or if flash space is limited. For example, a microcontroller without
analog features will not have `analogio`. See the `support_matrix` page for
a list of modules supported on each board.
+.. toctree::
+ :hidden:
+
+ support_matrix
+
Modules
---------
.. toctree::
:glob:
- :maxdepth: 3
+ :maxdepth: 2
- support_matrix
- */__init__
+ ../shared-bindings/*/index
help
diff --git a/shared-bindings/math/__init__.c b/shared-bindings/math/__init__.c
index 0bf8047c9..8226a08ec 100644
--- a/shared-bindings/math/__init__.c
+++ b/shared-bindings/math/__init__.c
@@ -38,15 +38,10 @@
#define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846)
-//| :mod:`math` --- mathematical functions
-//| ========================================================
-//|
-//| .. module:: math
-//| :synopsis: mathematical functions
-//| :platform: SAMD21/SAMD51
+//| """mathematical functions
//|
//| The `math` module provides some basic mathematical functions for
-//| working with floating-point numbers.
+//| working with floating-point numbers."""
//|
STATIC NORETURN void math_error(void) {
@@ -83,182 +78,170 @@ STATIC NORETURN void math_error(void) {
// 1.442695040888963407354163704 is 1/_M_LN2
#define log2(x) (log(x) * 1.442695040888963407354163704)
#endif
- //| Constants
- //| ---------
- //|
- //| .. data:: e
- //|
- //| base of the natural logarithm
- //|
- //| .. data:: pi
- //|
- //| the ratio of a circle's circumference to its diameter
- //|
-
- //| Functions
- //| ---------
- //|
- //| .. function:: acos(x)
- //|
- //| Return the inverse cosine of ``x``.
- //|
- //| .. function:: asin(x)
- //|
- //| Return the inverse sine of ``x``.
- //|
- //| .. function:: atan(x)
- //|
- //| Return the inverse tangent of ``x``.
- //|
- //| .. function:: atan2(y,x)
- //|
- //| Return the principal value of the inverse tangent of ``y/x``.
- //|
- //| .. function:: ceil(x)
- //|
- //| Return an integer, being ``x`` rounded towards positive infinity.
- //|
- //| .. function:: copysign(x,y)
- //|
- //| Return ``x`` with the sign of ``y``.
- //|
- //| .. function:: cos(x)
- //|
- //| Return the cosine of ``x``.
- //|
- //| .. function:: degrees(x)
- //|
- //| Return radians ``x`` converted to degrees.
- //|
- //| .. function:: exp(x)
- //|
- //| Return the exponential of ``x``.
- //|
- //| .. function:: fabs(x)
- //|
- //| Return the absolute value of ``x``.
- //|
- //| .. function:: floor(x)
- //|
- //| Return an integer, being ``x`` rounded towards negative infinity.
- //|
- //| .. function:: fmod(x,y)
- //|
- //| Return the remainder of ``x/y``.
- //|
- //| .. function:: frexp(x)
- //|
- //| Decomposes a floating-point number into its mantissa and exponent.
- //| The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e``
- //| exactly. If ``x == 0`` then the function returns ``(0.0, 0)``, otherwise
- //| the relation ``0.5 <= abs(m) < 1`` holds.
- //|
- //| .. function:: isfinite(x)
- //|
- //| Return ``True`` if ``x`` is finite.
- //|
- //| .. function:: isinf(x)
- //|
- //| Return ``True`` if ``x`` is infinite.
- //|
- //| .. function:: isnan(x)
- //|
- //| Return ``True`` if ``x`` is not-a-number
- //|
- //| .. function:: ldexp(x, exp)
- //|
- //| Return ``x * (2**exp)``.
- //|
- //| .. function:: modf(x)
- //|
- //| Return a tuple of two floats, being the fractional and integral parts of
- //| ``x``. Both return values have the same sign as ``x``.
- //|
- //| .. function:: pow(x, y)
- //|
- //| Returns ``x`` to the power of ``y``.
- //|
- //| .. function:: radians(x)
- //|
- //| Return degrees ``x`` converted to radians.
- //|
- //| .. function:: sin(x)
- //|
- //| Return the sine of ``x``.
- //|
- //| .. function:: sqrt(x)
- //|
- //| Returns the square root of ``x``.
- //|
- //| .. function:: tan(x)
- //|
- //| Return the tangent of ``x``.
- //|
- //| .. function:: trunc(x)
- //|
- //| Return an integer, being ``x`` rounded towards 0.
- //|
+
+//| e: Any = ...
+//| """base of the natural logarithm"""
+//|
+//| pi: Any = ...
+//| """the ratio of a circle's circumference to its diameter"""
+//|
+
+//| def acos(x: Any) -> Any:
+//| """Return the inverse cosine of ``x``."""
+//| ...
+//|
+//| def asin(x: Any) -> Any:
+//| """Return the inverse sine of ``x``."""
+//| ...
+//|
+//| def atan(x: Any) -> Any:
+//| """Return the inverse tangent of ``x``."""
+//| ...
+//|
+//| def atan2(y: Any, x: Any) -> Any:
+//| """Return the principal value of the inverse tangent of ``y/x``."""
+//| ...
+//|
+//| def ceil(x: Any) -> Any:
+//| """Return an integer, being ``x`` rounded towards positive infinity."""
+//| ...
+//|
+//| def copysign(x: Any, y: Any) -> Any:
+//| """Return ``x`` with the sign of ``y``."""
+//| ...
+//|
+//| def cos(x: Any) -> Any:
+//| """Return the cosine of ``x``."""
+//| ...
+//|
+//| def degrees(x: Any) -> Any:
+//| """Return radians ``x`` converted to degrees."""
+//| ...
+//|
+//| def exp(x: Any) -> Any:
+//| """Return the exponential of ``x``."""
+//| ...
+//|
+//| def fabs(x: Any) -> Any:
+//| """Return the absolute value of ``x``."""
+//| ...
+//|
+//| def floor(x: Any) -> Any:
+//| """Return an integer, being ``x`` rounded towards negative infinity."""
+//| ...
+//|
+//| def fmod(x: Any, y: Any) -> Any:
+//| """Return the remainder of ``x/y``."""
+//| ...
+//|
+//| def frexp(x: Any) -> Any:
+//| """Decomposes a floating-point number into its mantissa and exponent.
+//| The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e``
+//| exactly. If ``x == 0`` then the function returns ``(0.0, 0)``, otherwise
+//| the relation ``0.5 <= abs(m) < 1`` holds."""
+//| ...
+//|
+//| def isfinite(x: Any) -> Any:
+//| """Return ``True`` if ``x`` is finite."""
+//| ...
+//|
+//| def isinf(x: Any) -> Any:
+//| """Return ``True`` if ``x`` is infinite."""
+//| ...
+//|
+//| def isnan(x: Any) -> Any:
+//| """Return ``True`` if ``x`` is not-a-number"""
+//| ...
+//|
+//| def ldexp(x: Any, exp: Any) -> Any:
+//| """Return ``x * (2**exp)``."""
+//| ...
+//|
+//| def modf(x: Any) -> Any:
+//| """Return a tuple of two floats, being the fractional and integral parts of
+//| ``x``. Both return values have the same sign as ``x``."""
+//| ...
+//|
+//| def pow(x: Any, y: Any) -> Any:
+//| """Returns ``x`` to the power of ``y``."""
+//|
+//| def radians(x: Any) -> Any:
+//| """Return degrees ``x`` converted to radians."""
+//|
+//| def sin(x: Any) -> Any:
+//| """Return the sine of ``x``."""
+//| ...
+//|
+//| def sqrt(x: Any) -> Any:
+//| """Returns the square root of ``x``."""
+//| ...
+//|
+//| def tan(x: Any) -> Any:
+//| """Return the tangent of ``x``."""
+//| ...
+//|
+//| def trunc(x: Any) -> Any:
+//| """Return an integer, being ``x`` rounded towards 0."""
+//| ...
+//|
MATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0))
MATH_FUN_2(pow, pow)
MATH_FUN_1(exp, exp)
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-// Special functions
-// -----------------
-//
-// .. function:: expm1(x)
-//
-// Return ``exp(x) - 1``.
-//
+//| def expm1(x):
+//| """Return ``exp(x) - 1``."""
+//| ...
+//|
MATH_FUN_1(expm1, expm1)
-// .. function:: log2(x)
-//
-// Return the base-2 logarithm of ``x``.
-//
+//| def log2(x):
+//| """Return the base-2 logarithm of ``x``."""
+//| ...
+//|
MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0))
-// .. function:: log10(x)
-//
-// Return the base-10 logarithm of ``x``.
-//
+//| def log10(x):
+//| """Return the base-10 logarithm of ``x``."""
+//| ...
+//|
MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0))
-// .. function:: cosh(x)
-//
-// Return the hyperbolic cosine of ``x``.
-//
+//| def cosh(x):
+//| """Return the hyperbolic cosine of ``x``."""
+//| ...
+//|
MATH_FUN_1(cosh, cosh)
-// .. function:: sinh(x)
-//
-// Return the hyperbolic sine of ``x``.
-//
+//| def sinh(x):
+//| """Return the hyperbolic sine of ``x``."""
+//| ...
+//|
MATH_FUN_1(sinh, sinh)
-// .. function:: tanh(x)
-//
-// Return the hyperbolic tangent of ``x``.
-//
+//| def tanh(x):
+//| """Return the hyperbolic tangent of ``x``."""
+//| ...
+//|
MATH_FUN_1(tanh, tanh)
-// .. function:: acosh(x)
-//
-// Return the inverse hyperbolic cosine of ``x``.
-//
+//| def acosh(x):
+//| """Return the inverse hyperbolic cosine of ``x``."""
+//| ...
+//|
MATH_FUN_1(acosh, acosh)
-// .. function:: asinh(x)
-//
-// Return the inverse hyperbolic sine of ``x``.
-//
+//| def asinh(x):
+//| """Return the inverse hyperbolic sine of ``x``."""
+//| ...
+//|
MATH_FUN_1(asinh, asinh)
-// .. function:: atanh(x)
-//
-// Return the inverse hyperbolic tangent of ``x``.
-//
+//| def atanh(x):
+//| """Return the inverse hyperbolic tangent of ``x``."""
+//| ...
+//|
MATH_FUN_1(atanh, atanh)
#endif
@@ -297,28 +280,28 @@ MATH_FUN_1_TO_INT(trunc, trunc)
MATH_FUN_2(ldexp, ldexp)
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-// .. function:: erf(x)
-//
-// Return the error function of ``x``.
-//
+//| def erf(x):
+//| """Return the error function of ``x``."""
+//| ...
+//|
MATH_FUN_1(erf, erf)
-// .. function:: erfc(x)
-//
-// Return the complementary error function of ``x``.
-//
+//| def erfc(x):
+//| """Return the complementary error function of ``x``."""
+//| ...
+//|
MATH_FUN_1(erfc, erfc)
-// .. function:: gamma(x)
-//
-// Return the gamma function of ``x``.
-//
+//| def gamma(x):
+//| """Return the gamma function of ``x``."""
+//| ...
+//|
MATH_FUN_1(gamma, tgamma)
-// .. function:: lgamma(x)
-//
-// Return the natural logarithm of the gamma function of ``x``.
-//
+//| def lgamma(x):
+//| """Return the natural logarithm of the gamma function of ``x``."""
+//| ...
+//|
MATH_FUN_1(lgamma, lgamma)
#endif
//TODO: factorial, fsum
diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c
index 3635f0afb..d5b971ae5 100644
--- a/shared-bindings/microcontroller/Pin.c
+++ b/shared-bindings/microcontroller/Pin.c
@@ -33,18 +33,14 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: microcontroller
+//| class Pin:
+//| """Identifies an IO pin on the microcontroller."""
//|
-//| :class:`Pin` --- Pin reference
-//| ------------------------------------------
-//|
-//| Identifies an IO pin on the microcontroller.
-//|
-//| .. class:: Pin()
-//|
-//| Identifies an IO pin on the microcontroller. They are fixed by the
-//| hardware so they cannot be constructed on demand. Instead, use
-//| `board` or `microcontroller.pin` to reference the desired pin.
+//| def __init__(self, ):
+//| """Identifies an IO pin on the microcontroller. They are fixed by the
+//| hardware so they cannot be constructed on demand. Instead, use
+//| `board` or `microcontroller.pin` to reference the desired pin."""
+//| ...
//|
static void get_pin_name(const mcu_pin_obj_t *self, qstr* package, qstr* module, qstr* name) {
@@ -84,10 +80,47 @@ const mp_obj_type_t mcu_pin_type = {
.print = mcu_pin_print
};
-void assert_pin(mp_obj_t obj, bool none_ok) {
- if ((obj != mp_const_none || !none_ok) && !MP_OBJ_IS_TYPE(obj, &mcu_pin_type)) {
+mcu_pin_obj_t *validate_obj_is_pin(mp_obj_t obj) {
+ if (!MP_OBJ_IS_TYPE(obj, &mcu_pin_type)) {
mp_raise_TypeError_varg(translate("Expected a %q"), mcu_pin_type.name);
}
+ return MP_OBJ_TO_PTR(obj);
+}
+
+// Validate that the obj is a pin or None. Return an mcu_pin_obj_t* or NULL, correspondingly.
+mcu_pin_obj_t *validate_obj_is_pin_or_none(mp_obj_t obj) {
+ if (obj == mp_const_none) {
+ return NULL;
+ }
+ return validate_obj_is_pin(obj);
+}
+
+mcu_pin_obj_t *validate_obj_is_free_pin(mp_obj_t obj) {
+ mcu_pin_obj_t *pin = validate_obj_is_pin(obj);
+ assert_pin_free(pin);
+ return pin;
+}
+
+// Validate every element in the list to be a free pin.
+void validate_list_is_free_pins(qstr what, mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out) {
+ mp_int_t len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq));
+ if (len > max_pins) {
+ mp_raise_ValueError_varg(translate("At most %d %q may be specified (not %d)"), max_pins, what, len);
+ }
+ *count_out = len;
+ for (mp_int_t i=0; i<len; i++) {
+ pins_out[i] = validate_obj_is_free_pin(mp_obj_subscr(seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
+ }
+}
+
+// Validate that the obj is a free pin or None. Return an mcu_pin_obj_t* or NULL, correspondingly.
+mcu_pin_obj_t *validate_obj_is_free_pin_or_none(mp_obj_t obj) {
+ if (obj == mp_const_none) {
+ return NULL;
+ }
+ mcu_pin_obj_t *pin = validate_obj_is_pin(obj);
+ assert_pin_free(pin);
+ return pin;
}
void assert_pin_free(const mcu_pin_obj_t* pin) {
diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h
index 2d15dd5c5..f6659db7d 100644
--- a/shared-bindings/microcontroller/Pin.h
+++ b/shared-bindings/microcontroller/Pin.h
@@ -33,11 +33,22 @@
// Type object used in Python. Should be shared between ports.
extern const mp_obj_type_t mcu_pin_type;
-void assert_pin(mp_obj_t obj, bool none_ok);
+mcu_pin_obj_t *validate_obj_is_pin(mp_obj_t obj);
+mcu_pin_obj_t *validate_obj_is_pin_or_none(mp_obj_t obj);
+mcu_pin_obj_t *validate_obj_is_free_pin(mp_obj_t obj);
+mcu_pin_obj_t *validate_obj_is_free_pin_or_none(mp_obj_t obj);
+void validate_list_is_free_pins(qstr what, mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out);
+
void assert_pin_free(const mcu_pin_obj_t* pin);
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin);
void common_hal_never_reset_pin(const mcu_pin_obj_t* pin);
void common_hal_reset_pin(const mcu_pin_obj_t* pin);
+uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t* pin);
+void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin);
+void common_hal_mcu_pin_claim_number(uint8_t pin_no);
+void common_hal_mcu_pin_reset_number(uint8_t pin_no);
+
+#define COMMON_HAL_MCU_NO_PIN ((uint8_t)0xff)
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H
diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c
index 023f063e0..c4b249124 100644
--- a/shared-bindings/microcontroller/Processor.c
+++ b/shared-bindings/microcontroller/Processor.c
@@ -34,29 +34,24 @@
#include "py/runtime.h"
-//| .. currentmodule:: microcontroller
+//| class Processor:
+//| """Microcontroller CPU information and control
//|
-//| :class:`Processor` --- Microcontroller CPU information and control
-//| ------------------------------------------------------------------
+//| Usage::
//|
-//| Get information about the microcontroller CPU and control it.
-//|
-//| Usage::
-//|
-//| import microcontroller
-//| print(microcontroller.cpu.frequency)
-//| print(microcontroller.cpu.temperature)
+//| import microcontroller
+//| print(microcontroller.cpu.frequency)
+//| print(microcontroller.cpu.temperature)"""
//|
-//| .. class:: Processor()
-//|
-//| You cannot create an instance of `microcontroller.Processor`.
-//| Use `microcontroller.cpu` to access the sole instance available.
+//| def __init__(self, ):
+//| """You cannot create an instance of `microcontroller.Processor`.
+//| Use `microcontroller.cpu` to access the sole instance available."""
+//| ...
//|
-//| .. attribute:: frequency
-//|
-//| The CPU operating frequency as an `int`, in Hertz. (read-only)
+//| frequency: int = ...
+//| """The CPU operating frequency in Hertz. (read-only)"""
//|
STATIC mp_obj_t mcu_processor_get_frequency(mp_obj_t self) {
return mp_obj_new_int_from_uint(common_hal_mcu_processor_get_frequency());
@@ -72,11 +67,10 @@ const mp_obj_property_t mcu_processor_frequency_obj = {
},
};
-//| .. attribute:: temperature
+//| temperature: Any = ...
+//| """The on-chip temperature, in Celsius, as a float. (read-only)
//|
-//| The on-chip temperature, in Celsius, as a float. (read-only)
-//|
-//| Is `None` if the temperature is not available.
+//| Is `None` if the temperature is not available."""
//|
STATIC mp_obj_t mcu_processor_get_temperature(mp_obj_t self) {
float temperature = common_hal_mcu_processor_get_temperature();
@@ -93,9 +87,8 @@ const mp_obj_property_t mcu_processor_temperature_obj = {
},
};
-//| .. attribute:: uid
-//|
-//| The unique id (aka serial number) of the chip as a `bytearray`. (read-only)
+//| uid: Any = ...
+//| """The unique id (aka serial number) of the chip as a `bytearray`. (read-only)"""
//|
STATIC mp_obj_t mcu_processor_get_uid(mp_obj_t self) {
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
@@ -113,11 +106,10 @@ const mp_obj_property_t mcu_processor_uid_obj = {
},
};
-//| .. attribute:: voltage
-//|
-//| The input voltage to the microcontroller, as a float. (read-only)
+//| voltage: Any = ...
+//| """The input voltage to the microcontroller, as a float. (read-only)
//|
-//| Is `None` if the voltage is not available.
+//| Is `None` if the voltage is not available."""
//|
STATIC mp_obj_t mcu_processor_get_voltage(mp_obj_t self) {
float voltage = common_hal_mcu_processor_get_voltage();
diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c
index 913242ad2..6db315d8d 100644
--- a/shared-bindings/microcontroller/RunMode.c
+++ b/shared-bindings/microcontroller/RunMode.c
@@ -26,34 +26,28 @@
#include "shared-bindings/microcontroller/RunMode.h"
-//| .. currentmodule:: microcontroller
+//| class RunMode:
+//| """run state of the microcontroller"""
//|
-//| :class:`RunMode` -- run state of the microcontroller
-//| =============================================================
+//| def __init__(self, ):
+//| """Enum-like class to define the run mode of the microcontroller and
+//| CircuitPython."""
//|
-//| .. class:: RunMode()
+//| NORMAL: Any = ...
+//| """Run CircuitPython as normal.
//|
-//| Enum-like class to define the run mode of the microcontroller and
-//| CircuitPython.
+//| :type microcontroller.RunMode:"""
//|
-//| .. attribute:: NORMAL
+//| SAFE_MODE: Any = ...
+//| """Run CircuitPython in safe mode. User code will not be run and the
+//| file system will be writeable over USB.
//|
-//| Run CircuitPython as normal.
+//| :type microcontroller.RunMode:"""
//|
-//| :type microcontroller.RunMode:
+//| BOOTLOADER: Any = ...
+//| """Run the bootloader.
//|
-//| .. attribute:: SAFE_MODE
-//|
-//| Run CircuitPython in safe mode. User code will not be run and the
-//| file system will be writeable over USB.
-//|
-//| :type microcontroller.RunMode:
-//|
-//| .. attribute:: BOOTLOADER
-//|
-//| Run the bootloader.
-//|
-//| :type microcontroller.RunMode:
+//| :type microcontroller.RunMode:"""
//|
const mp_obj_type_t mcu_runmode_type;
diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c
index 090c4564d..88fe9c224 100644
--- a/shared-bindings/microcontroller/__init__.c
+++ b/shared-bindings/microcontroller/__init__.c
@@ -42,41 +42,26 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| :mod:`microcontroller` --- Pin references and cpu functionality
-//| ================================================================
-//|
-//| .. module:: microcontroller
-//| :synopsis: Pin references and core functionality
-//| :platform: SAMD21, ESP8266
+//| """Pin references and cpu functionality
//|
//| The `microcontroller` module defines the pins from the perspective of the
-//| microcontroller. See `board` for board-specific pin mappings.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Pin
-//| Processor
-//| RunMode
+//| microcontroller. See `board` for board-specific pin mappings."""
//|
-//| .. data:: cpu
-//|
-//| CPU information and control, such as ``cpu.temperature`` and ``cpu.frequency``
-//| (clock frequency).
-//| This object is the sole instance of `microcontroller.Processor`.
+//| cpu: Processor = ...
+//| """CPU information and control, such as ``cpu.temperature`` and ``cpu.frequency``
+//| (clock frequency).
+//| This object is the sole instance of `microcontroller.Processor`."""
//|
-//| .. function:: delay_us(delay)
-//|
-//| Dedicated delay method used for very short delays. **Do not** do long delays
-//| because this stops all other functions from completing. Think of this as an empty
-//| ``while`` loop that runs for the specified ``(delay)`` time. If you have other
-//| code or peripherals (e.g audio recording) that require specific timing or
-//| processing while you are waiting, explore a different avenue such as using
-//| `time.sleep()`.
+//| def delay_us(delay: Any) -> Any:
+//| """Dedicated delay method used for very short delays. **Do not** do long delays
+//| because this stops all other functions from completing. Think of this as an empty
+//| ``while`` loop that runs for the specified ``(delay)`` time. If you have other
+//| code or peripherals (e.g audio recording) that require specific timing or
+//| processing while you are waiting, explore a different avenue such as using
+//| `time.sleep()`."""
+//| ...
//|
STATIC mp_obj_t mcu_delay_us(mp_obj_t delay_obj) {
uint32_t delay = mp_obj_get_int(delay_obj);
@@ -87,9 +72,9 @@ STATIC mp_obj_t mcu_delay_us(mp_obj_t delay_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_delay_us_obj, mcu_delay_us);
-//| .. function:: disable_interrupts()
-//|
-//| Disable all interrupts. Be very careful, this can stall everything.
+//| def disable_interrupts() -> Any:
+//| """Disable all interrupts. Be very careful, this can stall everything."""
+//| ...
//|
STATIC mp_obj_t mcu_disable_interrupts(void) {
common_hal_mcu_disable_interrupts();
@@ -97,9 +82,9 @@ STATIC mp_obj_t mcu_disable_interrupts(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_disable_interrupts_obj, mcu_disable_interrupts);
-//| .. function:: enable_interrupts()
-//|
-//| Enable the interrupts that were enabled at the last disable.
+//| def enable_interrupts() -> Any:
+//| """Enable the interrupts that were enabled at the last disable."""
+//| ...
//|
STATIC mp_obj_t mcu_enable_interrupts(void) {
common_hal_mcu_enable_interrupts();
@@ -107,12 +92,12 @@ STATIC mp_obj_t mcu_enable_interrupts(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupts);
-//| .. function:: on_next_reset(run_mode)
-//|
-//| Configure the run mode used the next time the microcontroller is reset but
-//| not powered down.
+//| def on_next_reset(run_mode: microcontroller.RunMode) -> Any:
+//| """Configure the run mode used the next time the microcontroller is reset but
+//| not powered down.
//|
-//| :param ~microcontroller.RunMode run_mode: The next run mode
+//| :param ~microcontroller.RunMode run_mode: The next run mode"""
+//| ...
//|
STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) {
mcu_runmode_t run_mode;
@@ -132,14 +117,14 @@ STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset);
-//| .. function:: reset()
-//|
-//| Reset the microcontroller. After reset, the microcontroller will enter the
-//| run mode last set by `on_next_reset`.
+//| def reset() -> Any:
+//| """Reset the microcontroller. After reset, the microcontroller will enter the
+//| run mode last set by `on_next_reset`.
//|
-//| .. warning:: This may result in file system corruption when connected to a
-//| host computer. Be very careful when calling this! Make sure the device
-//| "Safely removed" on Windows or "ejected" on Mac OSX and Linux.
+//| .. warning:: This may result in file system corruption when connected to a
+//| host computer. Be very careful when calling this! Make sure the device
+//| "Safely removed" on Windows or "ejected" on Mac OSX and Linux."""
+//| ...
//|
STATIC mp_obj_t mcu_reset(void) {
common_hal_mcu_reset();
@@ -148,22 +133,21 @@ STATIC mp_obj_t mcu_reset(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
-//| .. data:: nvm
+//| nvm: Any = ...
+//| """Available non-volatile memory.
+//| This object is the sole instance of `nvm.ByteArray` when available or ``None`` otherwise.
//|
-//| Available non-volatile memory.
-//| This object is the sole instance of `nvm.ByteArray` when available or ``None`` otherwise.
-//|
-//| :type: nvm.ByteArray or None
+//| :type: nvm.ByteArray or None"""
//|
-//| :mod:`microcontroller.pin` --- Microcontroller pin names
+//| """:mod:`microcontroller.pin` --- Microcontroller pin names
//| --------------------------------------------------------
//|
//| .. module:: microcontroller.pin
//| :synopsis: Microcontroller pin names
//| :platform: SAMD21
//|
-//| References to pins as named by the microcontroller
+//| References to pins as named by the microcontroller"""
//|
const mp_obj_module_t mcu_pin_module = {
.base = { &mp_type_module },
@@ -183,6 +167,11 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
#else
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) },
#endif
+ #if CIRCUITPY_WATCHDOG
+ { MP_ROM_QSTR(MP_QSTR_watchdog), MP_ROM_PTR(&common_hal_mcu_watchdogtimer_obj) },
+ #else
+ { MP_ROM_QSTR(MP_QSTR_watchdog), MP_ROM_PTR(&mp_const_none_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) },
diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h
index e1487c555..8abdff763 100644
--- a/shared-bindings/microcontroller/__init__.h
+++ b/shared-bindings/microcontroller/__init__.h
@@ -49,10 +49,13 @@ extern const mcu_processor_obj_t common_hal_mcu_processor_obj;
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
-
#include "common-hal/nvm/ByteArray.h"
extern const nvm_bytearray_obj_t common_hal_mcu_nvm_obj;
+#endif
+#if CIRCUITPY_WATCHDOG
+#include "common-hal/watchdog/WatchDogTimer.h"
+extern watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj;
#endif
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H
diff --git a/shared-bindings/multiterminal/__init__.c b/shared-bindings/multiterminal/__init__.c
index 8de3c50d7..baf2fb674 100644
--- a/shared-bindings/multiterminal/__init__.c
+++ b/shared-bindings/multiterminal/__init__.c
@@ -30,34 +30,29 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-//| :mod:`multiterminal` --- Manage additional terminal sources
-//| ===========================================================
-//|
-//| .. module:: multiterminal
-//| :synopsis: Manage additional terminal sources
-//| :platform: ESP8266
+//| """Manage additional terminal sources
//|
//| The `multiterminal` module allows you to configure an additional serial
//| terminal source. Incoming characters are accepted from both the internal
-//| serial connection and the optional secondary connection.
+//| serial connection and the optional secondary connection."""
//|
-//| .. function:: get_secondary_terminal()
-//|
-//| Returns the current secondary terminal.
+//| def get_secondary_terminal() -> Any:
+//| """Returns the current secondary terminal."""
+//| ...
//|
STATIC mp_obj_t multiterminal_obj_get_secondary_terminal() {
return common_hal_multiterminal_get_secondary_terminal();
}
MP_DEFINE_CONST_FUN_OBJ_0(multiterminal_get_secondary_terminal_obj, multiterminal_obj_get_secondary_terminal);
-//| .. function:: set_secondary_terminal(stream)
-//|
-//| Read additional input from the given stream and write out back to it.
+//| def set_secondary_terminal(stream: stream) -> Any:
+//| """Read additional input from the given stream and write out back to it.
//| This doesn't replace the core stream (usually UART or native USB) but is
//| mixed in instead.
//|
-//| :param stream stream: secondary stream
+//| :param stream stream: secondary stream"""
+//| ...
//|
STATIC mp_obj_t multiterminal_obj_set_secondary_terminal(mp_obj_t secondary_terminal) {
mp_obj_t write_m[3];
@@ -73,9 +68,9 @@ STATIC mp_obj_t multiterminal_obj_set_secondary_terminal(mp_obj_t secondary_term
}
MP_DEFINE_CONST_FUN_OBJ_1(multiterminal_set_secondary_terminal_obj, multiterminal_obj_set_secondary_terminal);
-//| .. function:: clear_secondary_terminal()
-//|
-//| Clears the secondary terminal.
+//| def clear_secondary_terminal() -> Any:
+//| """Clears the secondary terminal."""
+//| ...
//|
STATIC mp_obj_t multiterminal_obj_clear_secondary_terminal() {
common_hal_multiterminal_clear_secondary_terminal();
@@ -83,11 +78,11 @@ 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);
-//| .. function:: schedule_secondary_terminal_read(socket)
-//|
-//| In cases where the underlying OS is doing task scheduling, this notifies
+//| def schedule_secondary_terminal_read(socket: Any) -> Any:
+//| """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.
+//| as a callback for lwip sockets."""
+//| ...
//|
// TODO(tannewt): This is a funny API. Replace it with a direct call into the OS
// by the lwip object.
diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c
index 1ee66337b..5e5bc31eb 100644
--- a/shared-bindings/neopixel_write/__init__.c
+++ b/shared-bindings/neopixel_write/__init__.c
@@ -31,12 +31,7 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "supervisor/shared/translate.h"
-//| :mod:`neopixel_write` --- Low-level neopixel implementation
-//| ===========================================================
-//|
-//| .. module:: neopixel_write
-//| :synopsis: Low-level neopixel implementation
-//| :platform: SAMD21
+//| """Low-level neopixel implementation
//|
//| The `neopixel_write` module contains a helper method to write out bytes in
//| the 800khz neopixel protocol.
@@ -53,15 +48,14 @@
//| pin = digitalio.DigitalInOut(board.NEOPIXEL)
//| pin.direction = digitalio.Direction.OUTPUT
//| pixel_off = bytearray([0, 0, 0])
-//| neopixel_write.neopixel_write(pin, pixel_off)
-//|
-//| .. function:: neopixel_write(digitalinout, buf)
-//|
-//| Write buf out on the given DigitalInOut.
+//| neopixel_write.neopixel_write(pin, pixel_off)"""
//|
-//| :param ~digitalio.DigitalInOut digitalinout: the DigitalInOut to output with
-//| :param bytearray buf: The bytes to clock out. No assumption is made about color order
+//| def neopixel_write(digitalinout: digitalio.DigitalInOut, buf: bytearray) -> 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"""
+//| ...
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)) {
mp_raise_TypeError_varg(translate("Expected a %q"), digitalio_digitalinout_type.name);
diff --git a/shared-bindings/neopixel_write/__init__.h b/shared-bindings/neopixel_write/__init__.h
index 39b565ee2..9799e3413 100644
--- a/shared-bindings/neopixel_write/__init__.h
+++ b/shared-bindings/neopixel_write/__init__.h
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef SAMD_NEOPIXEL_WRITE_H
-#define SAMD_NEOPIXEL_WRITE_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H
#include <stdint.h>
#include <stdbool.h>
@@ -34,4 +34,4 @@
extern void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* gpio, uint8_t *pixels, uint32_t numBytes);
-#endif
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_NEOPIXEL_WRITE_H
diff --git a/shared-bindings/network/__init__.c b/shared-bindings/network/__init__.c
index 01763a73c..6af86688e 100644
--- a/shared-bindings/network/__init__.c
+++ b/shared-bindings/network/__init__.c
@@ -38,20 +38,15 @@
#if CIRCUITPY_NETWORK
-//| :mod:`network` --- Network Interface Management
-//| ===============================================
-//|
-//| .. module:: network
-//| :synopsis: Network Interface Management
-//| :platform: SAMD
+//| """Network Interface Management
//|
//| This module provides a registry of configured NICs.
//| It is used by the 'socket' module to look up a suitable
-//| NIC when a socket is created.
-//|
-//| .. function:: route()
+//| NIC when a socket is created."""
//|
-//| Returns a list of all configured NICs.
+//| def route() -> Any:
+//| """Returns a list of all configured NICs."""
+//| ...
//|
STATIC mp_obj_t network_route(void) {
diff --git a/shared-bindings/nvm/ByteArray.c b/shared-bindings/nvm/ByteArray.c
index 31bedeacc..06d7d4c95 100644
--- a/shared-bindings/nvm/ByteArray.c
+++ b/shared-bindings/nvm/ByteArray.c
@@ -31,29 +31,27 @@
#include "shared-bindings/nvm/ByteArray.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: nvm
+//| class ByteArray:
+//| r"""Presents a stretch of non-volatile memory as a bytearray.
//|
-//| :class:`ByteArray` -- Presents a stretch of non-volatile memory as a bytearray.
-//| ================================================================================
+//| Non-volatile memory is available as a byte array that persists over reloads
+//| and power cycles. Each assignment causes an erase and write cycle so its recommended to assign
+//| all values to change at once.
//|
-//| Non-volatile memory is available as a byte array that persists over reloads
-//| and power cycles. Each assignment causes an erase and write cycle so its recommended to assign
-//| all values to change at once.
+//| Usage::
//|
-//| Usage::
-//|
-//| import microcontroller
-//| microcontroller.nvm[0:3] = b"\xcc\x10\x00"
+//| import microcontroller
+//| microcontroller.nvm[0:3] = b\"\xcc\x10\x00\""""
//|
-//| .. class:: ByteArray()
-//|
-//| Not currently dynamically supported. Access the sole instance through `microcontroller.nvm`.
+//| def __init__(self, ):
+//| """Not currently dynamically supported. Access the sole instance through `microcontroller.nvm`."""
+//| ...
//|
-//| .. method:: __len__()
-//|
-//| Return the length. This is used by (`len`)
+//| def __len__(self, ) -> Any:
+//| """Return the length. This is used by (`len`)"""
+//| ...
//|
STATIC mp_obj_t nvm_bytearray_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
nvm_bytearray_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/nvm/__init__.c b/shared-bindings/nvm/__init__.c
index 811855c09..e9784bd18 100644
--- a/shared-bindings/nvm/__init__.c
+++ b/shared-bindings/nvm/__init__.c
@@ -31,23 +31,15 @@
#include "shared-bindings/nvm/__init__.h"
#include "shared-bindings/nvm/ByteArray.h"
-//| :mod:`nvm` --- Non-volatile memory
-//| ===========================================================
-//|
-//| .. module:: nvm
-//| :synopsis: Non-volatile memory
-//| :platform: SAMD21
+//| """Non-volatile memory
//|
//| The `nvm` module allows you to store whatever raw bytes you wish in a
//| reserved section non-volatile memory.
//|
-
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
+//| Note that this module can't be imported and used directly. The sole
+//| instance of :class:`ByteArray` is available at
+//| :attr:`microcontroller.nvm`."""
//|
-//| ByteArray
STATIC const mp_rom_map_elem_t nvm_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_nvm) },
{ MP_ROM_QSTR(MP_QSTR_ByteArray), MP_ROM_PTR(&nvm_bytearray_type) },
diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c
index f3b745aef..4e991d089 100644
--- a/shared-bindings/os/__init__.c
+++ b/shared-bindings/os/__init__.c
@@ -37,31 +37,26 @@
#include "py/runtime.h"
#include "shared-bindings/os/__init__.h"
-//| :mod:`os` --- functions that an OS normally provides
-//| ========================================================
-//|
-//| .. module:: os
-//| :synopsis: functions that an OS normally provides
-//| :platform: SAMD21
+//| """functions that an OS normally provides
//|
//| The `os` module is a strict subset of the CPython `cpython:os` module. So,
//| code written in CircuitPython will work in CPython but not necessarily the
-//| other way around.
+//| other way around."""
//|
-//| .. function:: uname()
-//|
-//| Returns a named tuple of operating specific and CircuitPython port
-//| specific information.
+//| def uname() -> Any:
+//| """Returns a named tuple of operating specific and CircuitPython port
+//| specific information."""
+//| ...
//|
STATIC mp_obj_t os_uname(void) {
return common_hal_os_uname();
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
-//| .. function:: chdir(path)
-//|
-//| Change current directory.
+//| def chdir(path: Any) -> Any:
+//| """Change current directory."""
+//| ...
//|
mp_obj_t os_chdir(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
@@ -70,18 +65,18 @@ mp_obj_t os_chdir(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir);
-//| .. function:: getcwd()
-//|
-//| Get the current directory.
+//| def getcwd() -> Any:
+//| """Get the current directory."""
+//| ...
//|
mp_obj_t os_getcwd(void) {
return common_hal_os_getcwd();
}
MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
-//| .. function:: listdir([dir])
-//|
-//| With no argument, list the current directory. Otherwise list the given directory.
+//| def listdir(dir: Any) -> Any:
+//| """With no argument, list the current directory. Otherwise list the given directory."""
+//| ...
//|
mp_obj_t os_listdir(size_t n_args, const mp_obj_t *args) {
const char* path;
@@ -94,9 +89,9 @@ mp_obj_t os_listdir(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
-//| .. function:: mkdir(path)
-//|
-//| Create a new directory.
+//| def mkdir(path: Any) -> Any:
+//| """Create a new directory."""
+//| ...
//|
mp_obj_t os_mkdir(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
@@ -105,9 +100,9 @@ mp_obj_t os_mkdir(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
-//| .. function:: remove(path)
-//|
-//| Remove a file.
+//| def remove(path: Any) -> Any:
+//| """Remove a file."""
+//| ...
//|
mp_obj_t os_remove(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
@@ -116,9 +111,9 @@ mp_obj_t os_remove(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
-//| .. function:: rmdir(path)
-//|
-//| Remove a directory.
+//| def rmdir(path: Any) -> Any:
+//| """Remove a directory."""
+//| ...
//|
mp_obj_t os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) {
const char *old_path = mp_obj_str_get_str(old_path_in);
@@ -128,9 +123,9 @@ mp_obj_t os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
-//| .. function:: rename(old_path, new_path)
-//|
-//| Rename a file.
+//| def rename(old_path: Any, new_path: Any) -> Any:
+//| """Rename a file."""
+//| ...
//|
mp_obj_t os_rmdir(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
@@ -139,14 +134,14 @@ mp_obj_t os_rmdir(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir);
-//| .. function:: stat(path)
-//|
-//| Get the status of a file or directory.
+//| def stat(path: Any) -> Any:
+//| """Get the status of a file or directory.
//|
-//| .. note:: On builds without long integers, the number of seconds
-//| for contemporary dates will not fit in a small integer.
-//| So the time fields return 946684800,
-//| which is the number of seconds corresponding to 1999-12-31.
+//| .. note:: On builds without long integers, the number of seconds
+//| for contemporary dates will not fit in a small integer.
+//| So the time fields return 946684800,
+//| which is the number of seconds corresponding to 1999-12-31."""
+//| ...
//|
mp_obj_t os_stat(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
@@ -154,26 +149,26 @@ mp_obj_t os_stat(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
-//| .. function:: statvfs(path)
+//| def statvfs(path: Any) -> Any:
+//| """Get the status of a fileystem.
//|
-//| Get the status of a fileystem.
+//| Returns a tuple with the filesystem information in the following order:
//|
-//| Returns a tuple with the filesystem information in the following order:
+//| * ``f_bsize`` -- file system block size
+//| * ``f_frsize`` -- fragment size
+//| * ``f_blocks`` -- size of fs in f_frsize units
+//| * ``f_bfree`` -- number of free blocks
+//| * ``f_bavail`` -- number of free blocks for unpriviliged users
+//| * ``f_files`` -- number of inodes
+//| * ``f_ffree`` -- number of free inodes
+//| * ``f_favail`` -- number of free inodes for unpriviliged users
+//| * ``f_flag`` -- mount flags
+//| * ``f_namemax`` -- maximum filename length
//|
-//| * ``f_bsize`` -- file system block size
-//| * ``f_frsize`` -- fragment size
-//| * ``f_blocks`` -- size of fs in f_frsize units
-//| * ``f_bfree`` -- number of free blocks
-//| * ``f_bavail`` -- number of free blocks for unpriviliged users
-//| * ``f_files`` -- number of inodes
-//| * ``f_ffree`` -- number of free inodes
-//| * ``f_favail`` -- number of free inodes for unpriviliged users
-//| * ``f_flag`` -- mount flags
-//| * ``f_namemax`` -- maximum filename length
-//|
-//| Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
-//| and the ``f_flags`` parameter may return ``0`` as they can be unavailable
-//| in a port-specific implementation.
+//| Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
+//| and the ``f_flags`` parameter may return ``0`` as they can be unavailable
+//| in a port-specific implementation."""
+//| ...
//|
mp_obj_t os_statvfs(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
@@ -181,9 +176,9 @@ mp_obj_t os_statvfs(mp_obj_t path_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(os_statvfs_obj, os_statvfs);
-//| .. function:: sync()
-//|
-//| Sync all filesystems.
+//| def sync() -> Any:
+//| """Sync all filesystems."""
+//| ...
//|
STATIC mp_obj_t os_sync(void) {
for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
@@ -194,10 +189,10 @@ STATIC mp_obj_t os_sync(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
-//| .. function:: urandom(size)
-//|
-//| Returns a string of *size* random bytes based on a hardware True Random
-//| Number Generator. When not available, it will raise a NotImplementedError.
+//| def urandom(size: Any) -> Any:
+//| """Returns a string of *size* random bytes based on a hardware True Random
+//| Number Generator. When not available, it will raise a NotImplementedError."""
+//| ...
//|
STATIC mp_obj_t os_urandom(mp_obj_t size_in) {
mp_int_t size = mp_obj_get_int(size_in);
@@ -229,9 +224,9 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
-//| .. data:: sep
+//| """.. data:: sep
//|
-//| Separator used to delineate path components such as folder and file names.
+//| Separator used to delineate path components such as folder and file names."""
//|
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
};
diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c
index fb5c24b85..a87b14ddd 100644
--- a/shared-bindings/ps2io/Ps2.c
+++ b/shared-bindings/ps2io/Ps2.c
@@ -36,38 +36,36 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: ps2io
+//| class Ps2:
+//| """Communicate with a PS/2 keyboard or mouse
//|
-//| :class:`Ps2` -- Communicate with a PS/2 keyboard or mouse
-//| =========================================================
+//| Ps2 implements the PS/2 keyboard/mouse serial protocol, used in
+//| legacy devices. It is similar to UART but there are only two
+//| lines (Data and Clock). PS/2 devices are 5V, so bidirectional
+//| level converters must be used to connect the I/O lines to pins
+//| of 3.3V boards."""
//|
-//| Ps2 implements the PS/2 keyboard/mouse serial protocol, used in
-//| legacy devices. It is similar to UART but there are only two
-//| lines (Data and Clock). PS/2 devices are 5V, so bidirectional
-//| level converters must be used to connect the I/O lines to pins
-//| of 3.3V boards.
+//| def __init__(self, data_pin: microcontroller.Pin, clock_pin: microcontroller.Pin):
+//| """Create a Ps2 object associated with the given pins.
//|
-//| .. class:: Ps2(data_pin, clock_pin)
+//| :param ~microcontroller.Pin data_pin: Pin tied to data wire.
+//| :param ~microcontroller.Pin clock_pin: Pin tied to clock wire.
+//| This pin must support interrupts.
//|
-//| Create a Ps2 object associated with the given pins.
+//| Read one byte from PS/2 keyboard and turn on Scroll Lock LED::
//|
-//| :param ~microcontroller.Pin data_pin: Pin tied to data wire.
-//| :param ~microcontroller.Pin clock_pin: Pin tied to clock wire.
-//| This pin must support interrupts.
+//| import ps2io
+//| import board
//|
-//| Read one byte from PS/2 keyboard and turn on Scroll Lock LED::
+//| kbd = ps2io.Ps2(board.D10, board.D11)
//|
-//| import ps2io
-//| import board
+//| while len(kbd) == 0:
+//| pass
//|
-//| kbd = ps2io.Ps2(board.D10, board.D11)
-//|
-//| while len(kbd) == 0:
-//| pass
-//|
-//| print(kbd.popleft())
-//| print(kbd.sendcmd(0xed))
-//| print(kbd.sendcmd(0x01))
+//| print(kbd.popleft())
+//| print(kbd.sendcmd(0xed))
+//| print(kbd.sendcmd(0x01))"""
+//| ...
//|
STATIC mp_obj_t ps2io_ps2_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_datapin, ARG_clkpin };
@@ -77,12 +75,9 @@ STATIC mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, con
};
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);
- assert_pin(args[ARG_clkpin].u_obj, false);
- assert_pin(args[ARG_datapin].u_obj, false);
- const mcu_pin_obj_t* clkpin = MP_OBJ_TO_PTR(args[ARG_clkpin].u_obj);
- assert_pin_free(clkpin);
- const mcu_pin_obj_t* datapin = MP_OBJ_TO_PTR(args[ARG_datapin].u_obj);
- assert_pin_free(datapin);
+
+ const mcu_pin_obj_t* clkpin = validate_obj_is_free_pin(args[ARG_clkpin].u_obj);
+ const mcu_pin_obj_t* datapin = validate_obj_is_free_pin(args[ARG_datapin].u_obj);
ps2io_ps2_obj_t *self = m_new_obj(ps2io_ps2_obj_t);
self->base.type = &ps2io_ps2_type;
@@ -92,9 +87,9 @@ STATIC mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, con
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the Ps2 and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the Ps2 and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t ps2io_ps2_deinit(mp_obj_t self_in) {
ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -109,16 +104,16 @@ STATIC void check_for_deinit(ps2io_ps2_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t ps2io_ps2_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -127,10 +122,10 @@ STATIC mp_obj_t ps2io_ps2_obj___exit__(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ps2io_ps2___exit___obj, 4, 4, ps2io_ps2_obj___exit__);
-//| .. method:: popleft()
-//|
-//| Removes and returns the oldest received byte. When buffer
-//| is empty, raises an IndexError exception.
+//| def popleft(self, ) -> Any:
+//| """Removes and returns the oldest received byte. When buffer
+//| is empty, raises an IndexError exception."""
+//| ...
//|
STATIC mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) {
ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -144,18 +139,18 @@ STATIC mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_popleft_obj, ps2io_ps2_obj_popleft);
-//| .. method:: sendcmd(byte)
-//|
-//| Sends a command byte to PS/2. Returns the response byte, typically
-//| the general ack value (0xFA). Some commands return additional data
-//| which is available through :py:func:`popleft()`.
+//| def sendcmd(self, byte: int) -> Any:
+//| """Sends a command byte to PS/2. Returns the response byte, typically
+//| the general ack value (0xFA). Some commands return additional data
+//| which is available through :py:func:`popleft()`.
//|
-//| Raises a RuntimeError in case of failure. The root cause can be found
-//| by calling :py:func:`clear_errors()`. It is advisable to call
-//| :py:func:`clear_errors()` before :py:func:`sendcmd()` to flush any
-//| previous errors.
+//| Raises a RuntimeError in case of failure. The root cause can be found
+//| by calling :py:func:`clear_errors()`. It is advisable to call
+//| :py:func:`clear_errors()` before :py:func:`sendcmd()` to flush any
+//| previous errors.
//|
-//| :param int byte: byte value of the command
+//| :param int byte: byte value of the command"""
+//| ...
//|
STATIC mp_obj_t ps2io_ps2_obj_sendcmd(mp_obj_t self_in, mp_obj_t ob) {
ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -169,35 +164,35 @@ STATIC mp_obj_t ps2io_ps2_obj_sendcmd(mp_obj_t self_in, mp_obj_t ob) {
}
MP_DEFINE_CONST_FUN_OBJ_2(ps2io_ps2_sendcmd_obj, ps2io_ps2_obj_sendcmd);
-//| .. method:: clear_errors()
+//| def clear_errors(self, ) -> Any:
+//| """Returns and clears a bitmap with latest recorded communication errors.
//|
-//| Returns and clears a bitmap with latest recorded communication errors.
+//| Reception errors (arise asynchronously, as data is received):
//|
-//| Reception errors (arise asynchronously, as data is received):
+//| 0x01: start bit not 0
//|
-//| 0x01: start bit not 0
+//| 0x02: timeout
//|
-//| 0x02: timeout
+//| 0x04: parity bit error
//|
-//| 0x04: parity bit error
+//| 0x08: stop bit not 1
//|
-//| 0x08: stop bit not 1
+//| 0x10: buffer overflow, newest data discarded
//|
-//| 0x10: buffer overflow, newest data discarded
+//| Transmission errors (can only arise in the course of sendcmd()):
//|
-//| Transmission errors (can only arise in the course of sendcmd()):
+//| 0x100: clock pin didn't go to LO in time
//|
-//| 0x100: clock pin didn't go to LO in time
+//| 0x200: clock pin didn't go to HI in time
//|
-//| 0x200: clock pin didn't go to HI in time
+//| 0x400: data pin didn't ACK
//|
-//| 0x400: data pin didn't ACK
+//| 0x800: clock pin didn't ACK
//|
-//| 0x800: clock pin didn't ACK
+//| 0x1000: device didn't respond to RTS
//|
-//| 0x1000: device didn't respond to RTS
-//|
-//| 0x2000: device didn't send a response byte in time
+//| 0x2000: device didn't send a response byte in time"""
+//| ...
//|
STATIC mp_obj_t ps2io_ps2_obj_clear_errors(mp_obj_t self_in) {
ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -207,10 +202,10 @@ STATIC mp_obj_t ps2io_ps2_obj_clear_errors(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_clear_errors_obj, ps2io_ps2_obj_clear_errors);
-//| .. method:: __len__()
-//|
-//| Returns the number of received bytes in buffer, available
-//| to :py:func:`popleft()`.
+//| def __len__(self, ) -> Any:
+//| """Returns the number of received bytes in buffer, available
+//| to :py:func:`popleft()`."""
+//| ...
//|
STATIC mp_obj_t ps2_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/ps2io/__init__.c b/shared-bindings/ps2io/__init__.c
index ec7c43e51..38a70b1a2 100644
--- a/shared-bindings/ps2io/__init__.c
+++ b/shared-bindings/ps2io/__init__.c
@@ -33,22 +33,10 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/ps2io/Ps2.h"
-//| :mod:`ps2io` --- Support for PS/2 protocol
-//| =====================================================
-//|
-//| .. module:: ps2io
-//| :synopsis: Support for PS/2 based devices
-//| :platform: SAMD21
+//| """Support for PS/2 protocol
//|
//| The `ps2io` module contains classes to provide PS/2 communication.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Ps2
-//|
//| .. warning:: This module is not available in some SAMD21 builds. See the
//| :ref:`module-support-matrix` for more info.
@@ -57,7 +45,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.
+//| :ref:`lifetime-and-contextmanagers` for more info."""
//|
STATIC const mp_rom_map_elem_t ps2io_module_globals_table[] = {
diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c
index 53b88c61a..7970c02f3 100644
--- a/shared-bindings/pulseio/PWMOut.c
+++ b/shared-bindings/pulseio/PWMOut.c
@@ -35,55 +35,51 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: pulseio
+//| class PWMOut:
+//| """Output a Pulse Width Modulated signal on a given pin."""
//|
-//| :class:`PWMOut` -- Output a Pulse Width Modulated signal
-//| ========================================================
+//| def __init__(self, pin: microcontroller.Pin, *, duty_cycle: int = 0, frequency: int = 500, variable_frequency: bool = False):
+//| """Create a PWM object associated with the given pin. This allows you to
+//| write PWM signals out on the given pin. Frequency is fixed after init
+//| unless ``variable_frequency`` is True.
//|
-//| PWMOut can be used to output a PWM signal on a given pin.
+//| .. note:: When ``variable_frequency`` is True, further PWM outputs may be
+//| limited because it may take more internal resources to be flexible. So,
+//| when outputting both fixed and flexible frequency signals construct the
+//| fixed outputs first.
//|
-//| .. class:: PWMOut(pin, *, duty_cycle=0, frequency=500, variable_frequency=False)
+//| :param ~microcontroller.Pin pin: The pin to output to
+//| :param int duty_cycle: The fraction of each pulse which is high. 16-bit
+//| :param int frequency: The target frequency in Hertz (32-bit)
+//| :param bool variable_frequency: True if the frequency will change over time
//|
-//| Create a PWM object associated with the given pin. This allows you to
-//| write PWM signals out on the given pin. Frequency is fixed after init
-//| unless ``variable_frequency`` is True.
+//| Simple LED fade::
//|
-//| .. note:: When ``variable_frequency`` is True, further PWM outputs may be
-//| limited because it may take more internal resources to be flexible. So,
-//| when outputting both fixed and flexible frequency signals construct the
-//| fixed outputs first.
+//| import pulseio
+//| import board
//|
-//| :param ~microcontroller.Pin pin: The pin to output to
-//| :param int duty_cycle: The fraction of each pulse which is high. 16-bit
-//| :param int frequency: The target frequency in Hertz (32-bit)
-//| :param bool variable_frequency: True if the frequency will change over time
+//| pwm = pulseio.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
//|
-//| Simple LED fade::
+//| PWM at specific frequency (servos and motors)::
//|
-//| import pulseio
-//| import board
+//| import pulseio
+//| import board
//|
-//| pwm = pulseio.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 = pulseio.PWMOut(board.D13, frequency=50)
+//| pwm.duty_cycle = 2 ** 15 # Cycles the pin with 50% duty cycle (half of 2 ** 16) at 50hz
//|
-//| PWM at specific frequency (servos and motors)::
+//| Variable frequency (usually tones)::
//|
-//| import pulseio
-//| import board
+//| import pulseio
+//| import board
+//| import time
//|
-//| pwm = pulseio.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 board
-//| import time
-//|
-//| pwm = pulseio.PWMOut(board.D13, duty_cycle=2 ** 15, frequency=440, variable_frequency=True)
-//| time.sleep(0.2)
-//| pwm.frequency = 880
-//| time.sleep(0.1)
+//| pwm = pulseio.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) {
enum { ARG_pin, ARG_duty_cycle, ARG_frequency, ARG_variable_frequency };
@@ -96,10 +92,7 @@ STATIC mp_obj_t pulseio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args
mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args);
- mp_obj_t pin_obj = parsed_args[ARG_pin].u_obj;
- assert_pin(pin_obj, false);
- const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj);
- assert_pin_free(pin);
+ const mcu_pin_obj_t *pin = validate_obj_is_free_pin(parsed_args[ARG_pin].u_obj);
uint16_t duty_cycle = parsed_args[ARG_duty_cycle].u_int;
uint32_t frequency = parsed_args[ARG_frequency].u_int;
@@ -122,9 +115,9 @@ STATIC mp_obj_t pulseio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the PWMOut and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """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);
@@ -139,16 +132,16 @@ STATIC void check_for_deinit(pulseio_pwmout_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t pulseio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -157,16 +150,16 @@ STATIC mp_obj_t pulseio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pwmout___exit___obj, 4, 4, pulseio_pwmout_obj___exit__);
-//| .. attribute:: duty_cycle
+//| duty_cycle: Any = ...
+//| """16 bit value that dictates how much of one cycle is high (1) versus low
+//| (0). 0xffff will always be high, 0 will always be low and 0x7fff will
+//| be half high and then half low.
//|
-//| 16 bit value that dictates how much of one cycle is high (1) versus low
-//| (0). 0xffff will always be high, 0 will always be low and 0x7fff will
-//| be half high and then half low.
+//| Depending on how PWM is implemented on a specific board, the internal
+//| representation for duty cycle might have less than 16 bits of resolution.
+//| Reading this property will return the value from the internal representation,
+//| so it may differ from the value set."""
//|
-//| Depending on how PWM is implemented on a specific board, the internal
-//| representation for duty cycle might have less than 16 bits of resolution.
-//| 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);
check_for_deinit(self);
@@ -193,16 +186,15 @@ const mp_obj_property_t pulseio_pwmout_duty_cycle_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: frequency
-//|
-//| 32 bit value that dictates the PWM frequency in Hertz (cycles per
+//| frequency: Any = ...
+//| """32 bit value that dictates the PWM frequency in Hertz (cycles per
//| second). Only writeable when constructed with ``variable_frequency=True``.
//|
//| Depending on how PWM is implemented on a specific board, the internal value
//| for the PWM's duty cycle may need to be recalculated when the frequency
//| changes. In these cases, the duty cycle is automatically recalculated
//| from the original duty cycle value. This should happen without any need
-//| to manually re-set the duty cycle.
+//| 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);
diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c
index 8b69109f0..5c52b2582 100644
--- a/shared-bindings/pulseio/PulseIn.c
+++ b/shared-bindings/pulseio/PulseIn.c
@@ -35,51 +35,46 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: pulseio
+//| class PulseIn:
+//| """Measure a series of active and idle pulses. This is commonly used in infrared receivers
+//| and low cost temperature sensors (DHT). The pulsed signal consists of timed active and
+//| idle periods. Unlike PWM, there is no set duration for active and idle pairs."""
//|
-//| :class:`PulseIn` -- Read a series of pulse durations
-//| ========================================================
+//| def __init__(self, pin: microcontroller.Pin, maxlen: int = 2, *, idle_state: bool = False):
+//| """Create a PulseIn object associated with the given pin. The object acts as
+//| a read-only sequence of pulse lengths with a given max length. When it is
+//| active, new pulse lengths are added to the end of the list. When there is
+//| no more room (len() == `maxlen`) the oldest pulse length is removed to
+//| make room.
//|
-//| PulseIn is used to measure a series of active and idle pulses. This is
-//| commonly used in infrared receivers and low cost temperature sensors (DHT).
-//| The pulsed signal consists of timed active and idle periods. Unlike PWM,
-//| there is no set duration for active and idle pairs.
+//| :param ~microcontroller.Pin pin: Pin to read pulses from.
+//| :param int maxlen: Maximum number of pulse durations to store at once
+//| :param bool idle_state: Idle state of the pin. At start and after `resume`
+//| the first recorded pulse will the opposite state from idle.
//|
-//| .. class:: PulseIn(pin, maxlen=2, *, idle_state=False)
+//| Read a short series of pulses::
//|
-//| Create a PulseIn object associated with the given pin. The object acts as
-//| a read-only sequence of pulse lengths with a given max length. When it is
-//| active, new pulse lengths are added to the end of the list. When there is
-//| no more room (len() == `maxlen`) the oldest pulse length is removed to
-//| make room.
+//| import pulseio
+//| import board
//|
-//| :param ~microcontroller.Pin pin: Pin to read pulses from.
-//| :param int maxlen: Maximum number of pulse durations to store at once
-//| :param bool idle_state: Idle state of the pin. At start and after `resume`
-//| the first recorded pulse will the opposite state from idle.
+//| pulses = pulseio.PulseIn(board.D7)
//|
-//| Read a short series of pulses::
+//| # Wait for an active pulse
+//| while len(pulses) == 0:
+//| pass
+//| # Pause while we do something with the pulses
+//| pulses.pause()
//|
-//| import pulseio
-//| import board
+//| # Print the pulses. pulses[0] is an active pulse unless the length
+//| # reached max length and idle pulses are recorded.
+//| print(pulses)
//|
-//| pulses = pulseio.PulseIn(board.D7)
+//| # Clear the rest
+//| pulses.clear()
//|
-//| # Wait for an active pulse
-//| while len(pulses) == 0:
-//| pass
-//| # Pause while we do something with the pulses
-//| pulses.pause()
-//|
-//| # Print the pulses. pulses[0] is an active pulse unless the length
-//| # reached max length and idle pulses are recorded.
-//| print(pulses)
-//|
-//| # Clear the rest
-//| pulses.clear()
-//|
-//| # Resume with an 80 microsecond active pulse
-//| pulses.resume(80)
+//| # Resume with an 80 microsecond active pulse
+//| pulses.resume(80)"""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_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_pin, ARG_maxlen, ARG_idle_state };
@@ -90,9 +85,7 @@ STATIC mp_obj_t pulseio_pulsein_make_new(const mp_obj_type_t *type, size_t n_arg
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- assert_pin(args[ARG_pin].u_obj, false);
- const mcu_pin_obj_t* pin = MP_OBJ_TO_PTR(args[ARG_pin].u_obj);
- assert_pin_free(pin);
+ const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
pulseio_pulsein_obj_t *self = m_new_obj(pulseio_pulsein_obj_t);
self->base.type = &pulseio_pulsein_type;
@@ -103,9 +96,9 @@ STATIC mp_obj_t pulseio_pulsein_make_new(const mp_obj_type_t *type, size_t n_arg
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the PulseIn and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the PulseIn and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_deinit(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -120,16 +113,16 @@ STATIC void check_for_deinit(pulseio_pulsein_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -138,9 +131,9 @@ STATIC mp_obj_t pulseio_pulsein_obj___exit__(size_t n_args, const mp_obj_t *args
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulsein___exit___obj, 4, 4, pulseio_pulsein_obj___exit__);
-//| .. method:: pause()
-//|
-//| Pause pulse capture
+//| def pause(self, ) -> Any:
+//| """Pause pulse capture"""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_obj_pause(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -151,16 +144,16 @@ STATIC mp_obj_t pulseio_pulsein_obj_pause(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_pause_obj, pulseio_pulsein_obj_pause);
-//| .. method:: resume(trigger_duration=0)
+//| def resume(self, trigger_duration: int = 0) -> Any:
+//| """Resumes pulse capture after an optional trigger pulse.
//|
-//| Resumes pulse capture after an optional trigger pulse.
+//| .. warning:: Using trigger pulse with a device that drives both high and
+//| low signals risks a short. Make sure your device is open drain (only
+//| drives low) when using a trigger pulse. You most likely added a
+//| "pull-up" resistor to your circuit to do this.
//|
-//| .. warning:: Using trigger pulse with a device that drives both high and
-//| low signals risks a short. Make sure your device is open drain (only
-//| drives low) when using a trigger pulse. You most likely added a
-//| "pull-up" resistor to your circuit to do this.
-//|
-//| :param int trigger_duration: trigger pulse duration in microseconds
+//| :param int trigger_duration: trigger pulse duration in microseconds"""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_obj_resume(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_trigger_duration };
@@ -178,9 +171,9 @@ STATIC mp_obj_t pulseio_pulsein_obj_resume(size_t n_args, const mp_obj_t *pos_ar
}
MP_DEFINE_CONST_FUN_OBJ_KW(pulseio_pulsein_resume_obj, 1, pulseio_pulsein_obj_resume);
-//| .. method:: clear()
-//|
-//| Clears all captured pulses
+//| def clear(self, ) -> Any:
+//| """Clears all captured pulses"""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_obj_clear(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -191,9 +184,9 @@ STATIC mp_obj_t pulseio_pulsein_obj_clear(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_clear_obj, pulseio_pulsein_obj_clear);
-//| .. method:: popleft()
-//|
-//| Removes and returns the oldest read pulse.
+//| def popleft(self, ) -> Any:
+//| """Removes and returns the oldest read pulse."""
+//| ...
//|
STATIC mp_obj_t pulseio_pulsein_obj_popleft(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -203,10 +196,9 @@ STATIC mp_obj_t pulseio_pulsein_obj_popleft(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_popleft_obj, pulseio_pulsein_obj_popleft);
-//| .. attribute:: maxlen
-//|
-//| The maximum length of the PulseIn. When len() is equal to maxlen,
-//| it is unclear which pulses are active and which are idle.
+//| maxlen: Any = ...
+//| """The maximum length of the PulseIn. When len() is equal to maxlen,
+//| it is unclear which pulses are active and which are idle."""
//|
STATIC mp_obj_t pulseio_pulsein_obj_get_maxlen(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -223,10 +215,9 @@ const mp_obj_property_t pulseio_pulsein_maxlen_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: paused
-//|
-//| True when pulse capture is paused as a result of :py:func:`pause` or an error during capture
-//| such as a signal that is too fast.
+//| paused: Any = ...
+//| """True when pulse capture is paused as a result of :py:func:`pause` or an error during capture
+//| such as a signal that is too fast."""
//|
STATIC mp_obj_t pulseio_pulsein_obj_get_paused(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -243,14 +234,14 @@ const mp_obj_property_t pulseio_pulsein_paused_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: __len__()
-//|
-//| Returns the current pulse length
+//| def __len__(self, ) -> Any:
+//| """Returns the current pulse length
//|
-//| This allows you to::
+//| This allows you to::
//|
-//| pulses = pulseio.PulseIn(pin)
-//| print(len(pulses))
+//| pulses = pulseio.PulseIn(pin)
+//| print(len(pulses))"""
+//| ...
//|
STATIC mp_obj_t pulsein_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -263,14 +254,14 @@ STATIC mp_obj_t pulsein_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-//| .. method:: __getitem__(index)
-//|
-//| Returns the value at the given index or values in slice.
+//| def __getitem__(self, index: Any) -> Any:
+//| """Returns the value at the given index or values in slice.
//|
-//| This allows you to::
+//| This allows you to::
//|
-//| pulses = pulseio.PulseIn(pin)
-//| print(pulses[0])
+//| pulses = pulseio.PulseIn(pin)
+//| print(pulses[0])"""
+//| ...
//|
STATIC mp_obj_t pulsein_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) {
if (value == mp_const_none) {
diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c
index 172459e5d..16b0a6f0c 100644
--- a/shared-bindings/pulseio/PulseOut.c
+++ b/shared-bindings/pulseio/PulseOut.c
@@ -36,37 +36,33 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: pulseio
+//| class PulseOut:
+//| """Pulse PWM "carrier" output on and off. This is commonly used in infrared remotes. The
+//| pulsed signal consists of timed on and off periods. Unlike PWM, there is no set duration
+//| for on and off pairs."""
//|
-//| :class:`PulseOut` -- Output a pulse train
-//| ========================================================
+//| def __init__(self, carrier: pulseio.PWMOut):
+//| """Create a PulseOut object associated with the given PWMout object.
//|
-//| PulseOut is used to pulse PWM "carrier" output on and off. This is commonly
-//| used in infrared remotes. The pulsed signal consists of timed on and off
-//| periods. Unlike PWM, there is no set duration for on and off pairs.
+//| :param ~pulseio.PWMOut carrier: PWMOut that is set to output on the desired pin.
//|
-//| .. class:: PulseOut(carrier)
+//| Send a short series of pulses::
//|
-//| Create a PulseOut object associated with the given PWMout object.
+//| import array
+//| import pulseio
+//| import board
//|
-//| :param ~pulseio.PWMOut carrier: PWMOut that is set to output on the desired pin.
+//| # 50% duty cycle at 38kHz.
+//| pwm = pulseio.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])
+//| pulse.send(pulses)
//|
-//| Send a short series of pulses::
-//|
-//| import array
-//| import pulseio
-//| import board
-//|
-//| # 50% duty cycle at 38kHz.
-//| pwm = pulseio.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])
-//| pulse.send(pulses)
-//|
-//| # Modify the array of pulses.
-//| pulses[0] = 200
-//| pulse.send(pulses)
+//| # Modify the array of pulses.
+//| pulses[0] = 200
+//| 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);
@@ -85,9 +81,9 @@ STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_ar
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the PulseOut and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the PulseOut and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t pulseio_pulseout_deinit(mp_obj_t self_in) {
pulseio_pulseout_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -96,16 +92,16 @@ STATIC mp_obj_t pulseio_pulseout_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulseout_deinit_obj, pulseio_pulseout_deinit);
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t pulseio_pulseout_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -114,16 +110,16 @@ STATIC mp_obj_t pulseio_pulseout_obj___exit__(size_t n_args, const mp_obj_t *arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulseout___exit___obj, 4, 4, pulseio_pulseout_obj___exit__);
-//| .. method:: send(pulses)
-//|
-//| Pulse alternating on and off durations in microseconds starting with on.
-//| ``pulses`` must be an `array.array` with data type 'H' for unsigned
-//| halfword (two bytes).
+//| def send(self, pulses: array.array) -> Any:
+//| """Pulse alternating on and off durations in microseconds starting with on.
+//| ``pulses`` must be an `array.array` with data type 'H' for unsigned
+//| halfword (two bytes).
//|
-//| This method waits until the whole array of pulses has been sent and
-//| ensures the signal is off afterwards.
+//| This method waits until the whole array of pulses has been sent and
+//| ensures the signal is off afterwards.
//|
-//| :param array.array pulses: pulse durations in microseconds
+//| :param array.array pulses: pulse durations in microseconds"""
+//| ...
//|
STATIC mp_obj_t pulseio_pulseout_obj_send(mp_obj_t self_in, mp_obj_t pulses) {
pulseio_pulseout_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/pulseio/__init__.c b/shared-bindings/pulseio/__init__.c
index a3cec3dca..87946e5f0 100644
--- a/shared-bindings/pulseio/__init__.c
+++ b/shared-bindings/pulseio/__init__.c
@@ -35,24 +35,10 @@
#include "shared-bindings/pulseio/PulseOut.h"
#include "shared-bindings/pulseio/PWMOut.h"
-//| :mod:`pulseio` --- Support for pulse based protocols
-//| =====================================================
-//|
-//| .. module:: pulseio
-//| :synopsis: Support for pulse based protocols
-//| :platform: SAMD21, ESP8266
+//| """Support for pulse based protocols
//|
//| The `pulseio` module contains classes to provide access to basic pulse IO.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| PulseIn
-//| PulseOut
-//| PWMOut
-//|
//| 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
@@ -73,7 +59,7 @@
//| :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.
+//| to do it yourself."""
//|
STATIC const mp_rom_map_elem_t pulseio_module_globals_table[] = {
diff --git a/shared-bindings/random/__init__.c b/shared-bindings/random/__init__.c
index de4c90910..c0124df41 100644
--- a/shared-bindings/random/__init__.c
+++ b/shared-bindings/random/__init__.c
@@ -33,12 +33,7 @@
#include "shared-bindings/random/__init__.h"
#include "supervisor/shared/translate.h"
-//| :mod:`random` --- pseudo-random numbers and choices
-//| ========================================================
-//|
-//| .. module:: random
-//| :synopsis: pseudo-random numbers and choices
-//| :platform: SAMD21, ESP8266
+//| """pseudo-random numbers and choices
//|
//| The `random` module is a strict subset of the CPython `cpython:random`
//| module. So, code written in CircuitPython will work in CPython but not
@@ -49,13 +44,13 @@
//| Once seeded, it will be deterministic, which is why its bad for cryptography.
//|
//| .. warning:: Numbers from this module are not cryptographically strong! Use
-//| bytes from `os.urandom` directly for true randomness.
+//| bytes from `os.urandom` directly for true randomness."""
//|
-//| .. function:: seed(seed)
-//|
-//| Sets the starting seed of the random number generation. Further calls to
-//| `random` will return deterministic results afterwards.
+//| def seed(seed: Any) -> Any:
+//| """Sets the starting seed of the random number generation. Further calls to
+//| `random` will return deterministic results afterwards."""
+//| ...
//|
STATIC mp_obj_t random_seed(mp_obj_t seed_in) {
mp_uint_t seed = mp_obj_get_int_truncated(seed_in);
@@ -64,9 +59,9 @@ STATIC mp_obj_t random_seed(mp_obj_t seed_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(random_seed_obj, random_seed);
-//| .. function:: getrandbits(k)
-//|
-//| Returns an integer with *k* random bits.
+//| def getrandbits(k: Any) -> Any:
+//| """Returns an integer with *k* random bits."""
+//| ...
//|
STATIC mp_obj_t random_getrandbits(mp_obj_t num_in) {
int n = mp_obj_get_int(num_in);
@@ -77,10 +72,9 @@ STATIC mp_obj_t random_getrandbits(mp_obj_t num_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(random_getrandbits_obj, random_getrandbits);
-//| .. function:: randrange(stop)
-//| randrange(start, stop, step=1)
-//|
-//| Returns a randomly selected integer from ``range(start, stop, step)``.
+//| def randrange(stop: Any) -> Any:
+//| """Returns a randomly selected integer from ``range(start, stop, step)``."""
+//| ...
//|
STATIC mp_obj_t random_randrange(size_t n_args, const mp_obj_t *args) {
mp_int_t start = 0;
@@ -120,10 +114,10 @@ STATIC mp_obj_t random_randrange(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(random_randrange_obj, 1, 3, random_randrange);
-//| .. function:: randint(a, b)
-//|
-//| Returns a randomly selected integer between a and b inclusive. Equivalent
-//| to ``randrange(a, b + 1, 1)``
+//| def randint(a: Any, b: Any) -> Any:
+//| """Returns a randomly selected integer between a and b inclusive. Equivalent
+//| to ``randrange(a, b + 1, 1)``"""
+//| ...
//|
STATIC mp_obj_t random_randint(mp_obj_t a_in, mp_obj_t b_in) {
mp_int_t a = mp_obj_get_int(a_in);
@@ -135,10 +129,10 @@ STATIC mp_obj_t random_randint(mp_obj_t a_in, mp_obj_t b_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(random_randint_obj, random_randint);
-//| .. function:: choice(seq)
-//|
-//| Returns a randomly selected element from the given sequence. Raises
-//| IndexError when the sequence is empty.
+//| def choice(seq: Any) -> Any:
+//| """Returns a randomly selected element from the given sequence. Raises
+//| IndexError when the sequence is empty."""
+//| ...
//|
STATIC mp_obj_t random_choice(mp_obj_t seq) {
mp_int_t len = mp_obj_get_int(mp_obj_len(seq));
@@ -149,19 +143,19 @@ STATIC mp_obj_t random_choice(mp_obj_t seq) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(random_choice_obj, random_choice);
-//| .. function:: random()
-//|
-//| Returns a random float between 0 and 1.0.
+//| def random() -> Any:
+//| """Returns a random float between 0 and 1.0."""
+//| ...
//|
STATIC mp_obj_t random_random(void) {
return mp_obj_new_float(shared_modules_random_random());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(random_random_obj, random_random);
-//| .. function:: uniform(a, b)
-//|
-//| Returns a random float between a and b. It may or may not be inclusive
-//| depending on float rounding.
+//| def uniform(a: Any, b: Any) -> Any:
+//| """Returns a random float between a and b. It may or may not be inclusive
+//| depending on float rounding."""
+//| ...
//|
STATIC mp_obj_t random_uniform(mp_obj_t a_in, mp_obj_t b_in) {
mp_float_t a = mp_obj_get_float(a_in);
diff --git a/shared-bindings/rgbmatrix/RGBMatrix.c b/shared-bindings/rgbmatrix/RGBMatrix.c
new file mode 100644
index 000000000..c833faa6e
--- /dev/null
+++ b/shared-bindings/rgbmatrix/RGBMatrix.c
@@ -0,0 +1,423 @@
+/*
+ * This file is part of the Micro Python 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/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/objarray.h"
+
+#include "common-hal/rgbmatrix/RGBMatrix.h"
+#include "shared-bindings/rgbmatrix/RGBMatrix.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/util.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/framebufferio/__init__.h"
+#include "shared-module/framebufferio/FramebufferDisplay.h"
+
+//| class RGBMatrix:
+//| """Displays an in-memory framebuffer to a HUB75-style RGB LED matrix."""
+//|
+
+extern Protomatter_core *_PM_protoPtr;
+
+STATIC uint8_t validate_pin(mp_obj_t obj) {
+ mcu_pin_obj_t *result = validate_obj_is_free_pin(obj);
+ return common_hal_mcu_pin_number(result);
+}
+
+STATIC void validate_pins(qstr what, uint8_t* pin_nos, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out) {
+ mcu_pin_obj_t *pins[max_pins];
+ validate_list_is_free_pins(what, pins, max_pins, seq, count_out);
+ for (mp_int_t i=0; i<*count_out; i++) {
+ pin_nos[i] = common_hal_mcu_pin_number(pins[i]);
+ }
+}
+
+STATIC void claim_and_never_reset_pin(mp_obj_t pin) {
+ common_hal_mcu_pin_claim(pin);
+ common_hal_never_reset_pin(pin);
+}
+
+STATIC void claim_and_never_reset_pins(mp_obj_t seq) {
+ mp_int_t len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq));
+ for (mp_int_t i=0; i<len; i++) {
+ claim_and_never_reset_pin(mp_obj_subscr(seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
+ }
+}
+
+STATIC void preflight_pins_or_throw(uint8_t clock_pin, uint8_t *rgb_pins, uint8_t rgb_pin_count, bool allow_inefficient) {
+ uint32_t port = clock_pin / 32;
+ uint32_t bit_mask = 1 << (clock_pin % 32);
+
+ for (uint8_t i = 0; i < rgb_pin_count; i++) {
+ uint32_t pin_port = rgb_pins[i] / 32;
+
+ if (pin_port != port) {
+ mp_raise_ValueError_varg(
+ translate("rgb_pins[%d] is not on the same port as clock"), i);
+ }
+
+ uint32_t pin_mask = 1 << (rgb_pins[i] % 32);
+ if (pin_mask & bit_mask) {
+ mp_raise_ValueError_varg(
+ translate("rgb_pins[%d] duplicates another pin assignment"), i);
+ }
+
+ bit_mask |= pin_mask;
+ }
+
+ if (allow_inefficient) {
+ return;
+ }
+
+ uint8_t byte_mask = 0;
+ if (bit_mask & 0x000000FF) byte_mask |= 0b0001;
+ if (bit_mask & 0x0000FF00) byte_mask |= 0b0010;
+ if (bit_mask & 0x00FF0000) byte_mask |= 0b0100;
+ if (bit_mask & 0xFF000000) byte_mask |= 0b1000;
+
+ uint8_t bytes_per_element = 0xff;
+ uint8_t ideal_bytes_per_element = (rgb_pin_count + 7) / 8;
+
+ switch(byte_mask) {
+ case 0b0001:
+ case 0b0010:
+ case 0b0100:
+ case 0b1000:
+ bytes_per_element = 1;
+ break;
+
+ case 0b0011:
+ case 0b1100:
+ bytes_per_element = 2;
+ break;
+
+ default:
+ bytes_per_element = 4;
+ break;
+ }
+
+ if (bytes_per_element != ideal_bytes_per_element) {
+ mp_raise_ValueError_varg(
+ translate("Pinout uses %d bytes per element, which consumes more than the ideal %d bytes. If this cannot be avoided, pass allow_inefficient=True to the constructor"),
+ bytes_per_element, ideal_bytes_per_element);
+ }
+}
+
+//| def __init__(self, *, width: Any, bit_depth: Any, rgb_pins: Any, addr_pins: Any, clock_pin: Any, latch_pin: Any, output_enable_pin: Any, doublebuffer: Any = True, framebuffer: Any = None, height: Any = 0):
+//| """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
+//| address lines, the display will be 32 pixels tall. If the optional height
+//| parameter is specified and is not 0, it is checked against the calculated
+//| height.
+//|
+//| Up to 30 RGB pins and 8 address pins are supported.
+//|
+//| The RGB pins must be within a single "port" and performance and memory
+//| usage are best when they are all within "close by" bits of the port.
+//| The clock pin must also be on the same port as the RGB pins. See the
+//| documentation of the underlying protomatter C library for more
+//| information. Generally, Adafruit's interface boards are designed so
+//| that these requirements are met when matched with the intended
+//| microcontroller board. For instance, the Feather M4 Express works
+//| together with the RGB Matrix Feather.
+//|
+//| The framebuffer is in "RGB565" format.
+//|
+//| "RGB565" means that it is organized as a series of 16-bit numbers
+//| where the highest 5 bits are interpreted as red, the next 6 as
+//| green, and the final 5 as blue. The object can be any buffer, but
+//| `array.array` and `ulab.array` objects are most often useful.
+//| To update the content, modify the framebuffer and call refresh.
+//|
+//| If a framebuffer is not passed in, one is allocated and initialized
+//| to all black. In any case, the framebuffer can be retrieved
+//| by passing the RGBMatrix object to memoryview().
+//|
+//| If doublebuffer is False, some memory is saved, but the display may
+//| flicker during updates.
+//|
+//| A RGBMatrix is often used in conjunction with a
+//| `framebufferio.FramebufferDisplay`."""
+//|
+
+STATIC mp_obj_t rgbmatrix_rgbmatrix_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_width, ARG_bit_depth, ARG_rgb_list, ARG_addr_list,
+ ARG_clock_pin, ARG_latch_pin, ARG_output_enable_pin, ARG_doublebuffer, ARG_framebuffer, ARG_height };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_bit_depth, MP_ARG_INT | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_rgb_pins, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_addr_pins, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_clock_pin, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_latch_pin, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_output_enable_pin, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
+ { MP_QSTR_doublebuffer, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = true } },
+ { MP_QSTR_framebuffer, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = mp_const_none } },
+ { MP_QSTR_height, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 0 } },
+ };
+ 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);
+
+ rgbmatrix_rgbmatrix_obj_t *self = &allocate_display_bus_or_raise()->rgbmatrix;
+ self->base.type = &rgbmatrix_RGBMatrix_type;
+
+ uint8_t rgb_count, addr_count;
+ uint8_t rgb_pins[MP_ARRAY_SIZE(self->rgb_pins)];
+ uint8_t addr_pins[MP_ARRAY_SIZE(self->addr_pins)];
+ uint8_t clock_pin = validate_pin(args[ARG_clock_pin].u_obj);
+ uint8_t latch_pin = validate_pin(args[ARG_latch_pin].u_obj);
+ uint8_t output_enable_pin = validate_pin(args[ARG_output_enable_pin].u_obj);
+
+ validate_pins(MP_QSTR_rgb_pins, rgb_pins, MP_ARRAY_SIZE(self->rgb_pins), args[ARG_rgb_list].u_obj, &rgb_count);
+ validate_pins(MP_QSTR_addr_pins, addr_pins, MP_ARRAY_SIZE(self->addr_pins), args[ARG_addr_list].u_obj, &addr_count);
+
+ if (rgb_count % 6) {
+ mp_raise_ValueError_varg(translate("Must use a multiple of 6 rgb pins, not %d"), rgb_count);
+ }
+
+ // TODO(@jepler) Use fewer than all rows of pixels if height < computed_height
+ if (args[ARG_height].u_int != 0) {
+ int computed_height = (rgb_count / 3) << (addr_count);
+ if (computed_height != args[ARG_height].u_int) {
+ mp_raise_ValueError_varg(
+ translate("%d address pins and %d rgb pins indicate a height of %d, not %d"), addr_count, rgb_count, computed_height, args[ARG_height].u_int);
+ }
+ }
+
+ preflight_pins_or_throw(clock_pin, rgb_pins, rgb_count, true);
+
+ mp_obj_t framebuffer = args[ARG_framebuffer].u_obj;
+ if (framebuffer == mp_const_none) {
+ int width = args[ARG_width].u_int;
+ int bufsize = 2 * width * rgb_count / 3 * (1 << addr_count);
+ framebuffer = mp_obj_new_bytearray_of_zeros(bufsize);
+ }
+
+ common_hal_rgbmatrix_rgbmatrix_construct(self,
+ args[ARG_width].u_int,
+ args[ARG_bit_depth].u_int,
+ rgb_count, rgb_pins,
+ addr_count, addr_pins,
+ clock_pin, latch_pin, output_enable_pin,
+ args[ARG_doublebuffer].u_bool,
+ framebuffer, NULL);
+
+ claim_and_never_reset_pins(args[ARG_rgb_list].u_obj);
+ claim_and_never_reset_pins(args[ARG_addr_list].u_obj);
+ claim_and_never_reset_pin(args[ARG_clock_pin].u_obj);
+ claim_and_never_reset_pin(args[ARG_output_enable_pin].u_obj);
+ claim_and_never_reset_pin(args[ARG_latch_pin].u_obj);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| def deinit(self, ) -> Any:
+//| """Free the resources (pins, timers, etc.) associated with this
+//| rgbmatrix instance. After deinitialization, no further operations
+//| may be performed."""
+//| ...
+//|
+STATIC mp_obj_t rgbmatrix_rgbmatrix_deinit(mp_obj_t self_in) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ common_hal_rgbmatrix_rgbmatrix_deinit(self);
+ return mp_const_none;
+}
+
+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) {
+ raise_deinited_error();
+ }
+}
+
+//| brightness: Any = ...
+//| """In the current implementation, 0.0 turns the display off entirely
+//| and any other value up to 1.0 turns the display on fully."""
+//|
+STATIC mp_obj_t rgbmatrix_rgbmatrix_get_brightness(mp_obj_t self_in) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ check_for_deinit(self);
+ return mp_obj_new_float(common_hal_rgbmatrix_rgbmatrix_get_paused(self)? 0.0f : 1.0f);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(rgbmatrix_rgbmatrix_get_brightness_obj, rgbmatrix_rgbmatrix_get_brightness);
+
+STATIC mp_obj_t rgbmatrix_rgbmatrix_set_brightness(mp_obj_t self_in, mp_obj_t value_in) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ check_for_deinit(self);
+ mp_float_t brightness = mp_obj_get_float(value_in);
+ if (brightness < 0.0f || brightness > 1.0f) {
+ mp_raise_ValueError(translate("Brightness must be 0-1.0"));
+ }
+ common_hal_rgbmatrix_rgbmatrix_set_paused(self, brightness <= 0);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(rgbmatrix_rgbmatrix_set_brightness_obj, rgbmatrix_rgbmatrix_set_brightness);
+
+const mp_obj_property_t rgbmatrix_rgbmatrix_brightness_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&rgbmatrix_rgbmatrix_get_brightness_obj,
+ (mp_obj_t)&rgbmatrix_rgbmatrix_set_brightness_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| def refresh(self) -> Any: ...
+//| """Transmits the color data in the buffer to the pixels so that
+//| they are shown."""
+//|
+STATIC mp_obj_t rgbmatrix_rgbmatrix_refresh(mp_obj_t self_in) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ check_for_deinit(self);
+ common_hal_rgbmatrix_rgbmatrix_refresh(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(rgbmatrix_rgbmatrix_refresh_obj, rgbmatrix_rgbmatrix_refresh);
+
+//| width: int = ...
+//| """The width of the display, in pixels"""
+//|
+STATIC mp_obj_t rgbmatrix_rgbmatrix_get_width(mp_obj_t self_in) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_rgbmatrix_rgbmatrix_get_width(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(rgbmatrix_rgbmatrix_get_width_obj, rgbmatrix_rgbmatrix_get_width);
+const mp_obj_property_t rgbmatrix_rgbmatrix_width_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&rgbmatrix_rgbmatrix_get_width_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| height: int = ...
+//| """The height of the display, in pixels"""
+//|
+STATIC mp_obj_t rgbmatrix_rgbmatrix_get_height(mp_obj_t self_in) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_rgbmatrix_rgbmatrix_get_height(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(rgbmatrix_rgbmatrix_get_height_obj, rgbmatrix_rgbmatrix_get_height);
+
+const mp_obj_property_t rgbmatrix_rgbmatrix_height_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&rgbmatrix_rgbmatrix_get_height_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t rgbmatrix_rgbmatrix_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rgbmatrix_rgbmatrix_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&rgbmatrix_rgbmatrix_brightness_obj) },
+ { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&rgbmatrix_rgbmatrix_refresh_obj) },
+ { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&rgbmatrix_rgbmatrix_width_obj) },
+ { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&rgbmatrix_rgbmatrix_height_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(rgbmatrix_rgbmatrix_locals_dict, rgbmatrix_rgbmatrix_locals_dict_table);
+
+STATIC void rgbmatrix_rgbmatrix_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t*)self_in;
+ check_for_deinit(self);
+
+ *bufinfo = self->bufinfo;
+}
+
+// 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) {
+ common_hal_rgbmatrix_rgbmatrix_refresh(self_in);
+}
+
+STATIC void rgbmatrix_rgbmatrix_deinit_proto(mp_obj_t self_in) {
+ common_hal_rgbmatrix_rgbmatrix_deinit(self_in);
+}
+
+STATIC float rgbmatrix_rgbmatrix_get_brightness_proto(mp_obj_t self_in) {
+ return common_hal_rgbmatrix_rgbmatrix_get_paused(self_in) ? 0.0f : 1.0f;
+}
+
+STATIC bool rgbmatrix_rgbmatrix_set_brightness_proto(mp_obj_t self_in, mp_float_t value) {
+ common_hal_rgbmatrix_rgbmatrix_set_paused(self_in, value <= 0);
+ return true;
+}
+
+STATIC int rgbmatrix_rgbmatrix_get_width_proto(mp_obj_t self_in) {
+ return common_hal_rgbmatrix_rgbmatrix_get_width(self_in);
+}
+
+STATIC int rgbmatrix_rgbmatrix_get_height_proto(mp_obj_t self_in) {
+ return common_hal_rgbmatrix_rgbmatrix_get_height(self_in);
+}
+
+STATIC int rgbmatrix_rgbmatrix_get_color_depth_proto(mp_obj_t self_in) {
+ return 16;
+}
+
+STATIC int rgbmatrix_rgbmatrix_get_bytes_per_cell_proto(mp_obj_t self_in) {
+ return 1;
+}
+
+STATIC int rgbmatrix_rgbmatrix_get_native_frames_per_second_proto(mp_obj_t self_in) {
+ return 250;
+}
+
+
+STATIC const framebuffer_p_t rgbmatrix_rgbmatrix_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer)
+ .get_bufinfo = rgbmatrix_rgbmatrix_get_bufinfo,
+ .set_brightness = rgbmatrix_rgbmatrix_set_brightness_proto,
+ .get_brightness = rgbmatrix_rgbmatrix_get_brightness_proto,
+ .get_width = rgbmatrix_rgbmatrix_get_width_proto,
+ .get_height = rgbmatrix_rgbmatrix_get_height_proto,
+ .get_color_depth = rgbmatrix_rgbmatrix_get_color_depth_proto,
+ .get_bytes_per_cell = rgbmatrix_rgbmatrix_get_bytes_per_cell_proto,
+ .get_native_frames_per_second = rgbmatrix_rgbmatrix_get_native_frames_per_second_proto,
+ .swapbuffers = rgbmatrix_rgbmatrix_swapbuffers,
+ .deinit = rgbmatrix_rgbmatrix_deinit_proto,
+};
+
+STATIC mp_int_t rgbmatrix_rgbmatrix_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
+ rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_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;
+}
+
+const mp_obj_type_t rgbmatrix_RGBMatrix_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_RGBMatrix,
+ .buffer_p = { .get_buffer = rgbmatrix_rgbmatrix_get_buffer, },
+ .make_new = rgbmatrix_rgbmatrix_make_new,
+ .protocol = &rgbmatrix_rgbmatrix_proto,
+ .locals_dict = (mp_obj_dict_t*)&rgbmatrix_rgbmatrix_locals_dict,
+};
diff --git a/shared-bindings/rgbmatrix/RGBMatrix.h b/shared-bindings/rgbmatrix/RGBMatrix.h
new file mode 100644
index 000000000..027f817bb
--- /dev/null
+++ b/shared-bindings/rgbmatrix/RGBMatrix.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the Micro Python 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.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_RGBMATRIX_RGBMATRIX_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_RGBMATRIX_RGBMATRIX_H
+
+#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*);
+void rgbmatrix_rgbmatrix_collect_ptrs(rgbmatrix_rgbmatrix_obj_t*);
+void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, mp_obj_t framebuffer);
+void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t* self, bool paused);
+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/rgbmatrix/__init__.c b/shared-bindings/rgbmatrix/__init__.c
new file mode 100644
index 000000000..7f0576652
--- /dev/null
+++ b/shared-bindings/rgbmatrix/__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/rgbmatrix/RGBMatrix.h"
+
+//| """Low-level routines for bitbanged LED matrices"""
+//|
+
+STATIC const mp_rom_map_elem_t rgbmatrix_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rgbmatrix) },
+ { MP_ROM_QSTR(MP_QSTR_RGBMatrix), MP_ROM_PTR(&rgbmatrix_RGBMatrix_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(rgbmatrix_module_globals, rgbmatrix_module_globals_table);
+
+const mp_obj_module_t rgbmatrix_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&rgbmatrix_module_globals,
+};
diff --git a/shared-bindings/rotaryio/IncrementalEncoder.c b/shared-bindings/rotaryio/IncrementalEncoder.c
index f2f157847..8b2723866 100644
--- a/shared-bindings/rotaryio/IncrementalEncoder.c
+++ b/shared-bindings/rotaryio/IncrementalEncoder.c
@@ -34,35 +34,31 @@
#include "shared-bindings/rotaryio/IncrementalEncoder.h"
#include "shared-bindings/util.h"
-//| .. currentmodule:: rotaryio
+//| class IncrementalEncoder:
+//| """IncrementalEncoder determines the relative rotational position based on two series of pulses."""
//|
-//| :class:`IncrementalEncoder` -- Track the relative position of an incremental encoder
-//| ====================================================================================
+//| def __init__(self, pin_a: microcontroller.Pin, pin_b: microcontroller.Pin):
+//| """Create an IncrementalEncoder object associated with the given pins. It tracks the positional
+//| state of an incremental rotary encoder (also known as a quadrature encoder.) Position is
+//| relative to the position when the object is contructed.
//|
-//| IncrementalEncoder determines the relative rotational position based on two series of pulses.
+//| :param ~microcontroller.Pin pin_a: First pin to read pulses from.
+//| :param ~microcontroller.Pin pin_b: Second pin to read pulses from.
//|
-//| .. class:: IncrementalEncoder(pin_a, pin_b)
+//| For example::
//|
-//| Create an IncrementalEncoder object associated with the given pins. It tracks the positional
-//| state of an incremental rotary encoder (also known as a quadrature encoder.) Position is
-//| relative to the position when the object is contructed.
+//| import rotaryio
+//| import time
+//| from board import *
//|
-//| :param ~microcontroller.Pin pin_a: First pin to read pulses from.
-//| :param ~microcontroller.Pin pin_b: Second pin to read pulses from.
-//|
-//| For example::
-//|
-//| import rotaryio
-//| import time
-//| from board import *
-//|
-//| enc = rotaryio.IncrementalEncoder(D1, D2)
-//| last_position = None
-//| while True:
-//| position = enc.position
-//| if last_position == None or position != last_position:
-//| print(position)
-//| last_position = position
+//| enc = rotaryio.IncrementalEncoder(D1, D2)
+//| last_position = None
+//| while True:
+//| position = enc.position
+//| if last_position == None or position != last_position:
+//| print(position)
+//| last_position = position"""
+//| ...
//|
STATIC mp_obj_t rotaryio_incrementalencoder_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_pin_a, ARG_pin_b };
@@ -73,13 +69,8 @@ STATIC mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type,
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);
- assert_pin(args[ARG_pin_a].u_obj, false);
- const mcu_pin_obj_t* pin_a = MP_OBJ_TO_PTR(args[ARG_pin_a].u_obj);
- assert_pin_free(pin_a);
-
- assert_pin(args[ARG_pin_b].u_obj, false);
- const mcu_pin_obj_t* pin_b = MP_OBJ_TO_PTR(args[ARG_pin_b].u_obj);
- assert_pin_free(pin_b);
+ const mcu_pin_obj_t* pin_a = validate_obj_is_free_pin(args[ARG_pin_a].u_obj);
+ const mcu_pin_obj_t* pin_b = validate_obj_is_free_pin(args[ARG_pin_b].u_obj);
rotaryio_incrementalencoder_obj_t *self = m_new_obj(rotaryio_incrementalencoder_obj_t);
self->base.type = &rotaryio_incrementalencoder_type;
@@ -89,9 +80,9 @@ STATIC mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type,
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: deinit()
-//|
-//| Deinitializes the IncrementalEncoder and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitializes the IncrementalEncoder and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t rotaryio_incrementalencoder_deinit(mp_obj_t self_in) {
rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -106,16 +97,16 @@ STATIC void check_for_deinit(rotaryio_incrementalencoder_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t rotaryio_incrementalencoder_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -125,10 +116,9 @@ STATIC mp_obj_t rotaryio_incrementalencoder_obj___exit__(size_t n_args, const mp
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rotaryio_incrementalencoder___exit___obj, 4, 4, rotaryio_incrementalencoder_obj___exit__);
-//| .. attribute:: position
-//|
-//| The current position in terms of pulses. The number of pulses per rotation is defined by the
-//| specific hardware.
+//| position: Any = ...
+//| """The current position in terms of pulses. The number of pulses per rotation is defined by the
+//| specific hardware."""
//|
STATIC mp_obj_t rotaryio_incrementalencoder_obj_get_position(mp_obj_t self_in) {
rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/rotaryio/__init__.c b/shared-bindings/rotaryio/__init__.c
index a0166771a..0fa457ca7 100644
--- a/shared-bindings/rotaryio/__init__.c
+++ b/shared-bindings/rotaryio/__init__.c
@@ -33,33 +33,19 @@
#include "shared-bindings/rotaryio/__init__.h"
#include "shared-bindings/rotaryio/IncrementalEncoder.h"
-//| :mod:`rotaryio` --- Support for reading rotation sensors
-//| ========================================================
-//|
-//| .. module:: rotaryio
-//| :synopsis: Support for reading rotation sensors
-//| :platform: SAMD
+//| """Support for reading rotation sensors
//|
//| 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.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| IncrementalEncoder
-//|
-//| .. warning:: This module is not available in some SAMD21 (aka M0) builds. See the
-//| :ref:`module-support-matrix` for more info.
+//| .. 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
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| :ref:`lifetime-and-contextmanagers` for more info."""
//|
STATIC const mp_rom_map_elem_t rotaryio_module_globals_table[] = {
diff --git a/shared-bindings/rtc/RTC.c b/shared-bindings/rtc/RTC.c
index 3ff09a4ec..58fe308f5 100644
--- a/shared-bindings/rtc/RTC.c
+++ b/shared-bindings/rtc/RTC.c
@@ -38,14 +38,12 @@
const rtc_rtc_obj_t rtc_rtc_obj = {{&rtc_rtc_type}};
-//| .. currentmodule:: rtc
+//| class RTC:
+//| """Real Time Clock"""
//|
-//| :class:`RTC` --- Real Time Clock
-//| --------------------------------
-//|
-//| .. class:: RTC()
-//|
-//| This class represents the onboard Real Time Clock. It is a singleton and will always return the same instance.
+//| def __init__(self, ):
+//| """This class represents the onboard Real Time Clock. It is a singleton and will always return the same instance."""
+//| ...
//|
STATIC mp_obj_t rtc_rtc_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// No arguments
@@ -55,25 +53,24 @@ STATIC mp_obj_t rtc_rtc_make_new(const mp_obj_type_t *type, size_t n_args, const
return (mp_obj_t)&rtc_rtc_obj;
}
-//| .. attribute:: datetime
+//| datetime: time.struct_time = ...
+//| """The current date and time of the RTC as a `time.struct_time`.
//|
-//| The current date and time of the RTC as a `time.struct_time`.
+//| This must be set to the current date and time whenever the board loses power::
//|
-//| This must be set to the current date and time whenever the board loses power::
+//| import rtc
+//| import time
//|
-//| import rtc
-//| import time
+//| r = rtc.RTC()
+//| r.datetime = time.struct_time((2019, 5, 29, 15, 14, 15, 0, -1, -1))
//|
-//| r = rtc.RTC()
-//| r.datetime = rtctime.struct_time((2019, 5, 29, 15, 14, 15, 0, -1, -1))
//|
+//| Once set, the RTC will automatically update this value as time passes. You can read this
+//| property to get a snapshot of the current time::
//|
-//| Once set, the RTC will automatically update this value as time passes. You can read this
-//| property to get a snapshot of the current time::
-//|
-//| current_time = r.datetime
-//| print(current_time)
-//| # struct_time(tm_year=2019, tm_month=5, ...)
+//| current_time = r.datetime
+//| print(current_time)
+//| # struct_time(tm_year=2019, tm_month=5, ...)"""
//|
STATIC mp_obj_t rtc_rtc_obj_get_datetime(mp_obj_t self_in) {
timeutils_struct_time_t tm;
@@ -97,12 +94,11 @@ const mp_obj_property_t rtc_rtc_datetime_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: calibration
-//|
-//| The RTC calibration value as an `int`.
+//| calibration: int = ...
+//| """The RTC calibration value as an `int`.
//|
//| A positive value speeds up the clock and a negative value slows it down.
-//| Range and value is hardware specific, but one step is often approximately 1 ppm.
+//| Range and value is hardware specific, but one step is often approximately 1 ppm."""
//|
STATIC mp_obj_t rtc_rtc_obj_get_calibration(mp_obj_t self_in) {
int calibration = common_hal_rtc_get_calibration();
diff --git a/shared-bindings/rtc/__init__.c b/shared-bindings/rtc/__init__.c
index 22eda9b66..b204d511c 100644
--- a/shared-bindings/rtc/__init__.c
+++ b/shared-bindings/rtc/__init__.c
@@ -31,23 +31,11 @@
#include "shared-bindings/rtc/RTC.h"
#include "shared-bindings/time/__init__.h"
-//| :mod:`rtc` --- Real Time Clock
-//| ========================================================
-//|
-//| .. module:: rtc
-//| :synopsis: Real Time Clock
-//| :platform: SAMD21, SAMD51, nRF52
+//| """Real Time Clock
//|
//| The `rtc` module provides support for a Real Time Clock. You can access and manage the
//| RTC using :class:`rtc.RTC`. It also backs the :func:`time.time` and :func:`time.localtime`
-//| functions using the onboard RTC if present.
-//|
-//| Classes
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| RTC
+//| functions using the onboard RTC if present."""
//|
void rtc_reset(void) {
@@ -62,22 +50,22 @@ mp_obj_t rtc_get_time_source_time(void) {
return struct_time_from_tm(&tm);
}
-//| .. function:: set_time_source(rtc)
-//|
-//| Sets the RTC time source used by :func:`time.localtime`.
-//| The default is :class:`rtc.RTC`, but it's useful to use this to override the
-//| time source for testing purposes. For example::
+//| def set_time_source(rtc: Any) -> Any:
+//| """Sets the RTC time source used by :func:`time.localtime`.
+//| The default is :class:`rtc.RTC`, but it's useful to use this to override the
+//| time source for testing purposes. For example::
//|
-//| import rtc
-//| import time
+//| import rtc
+//| import time
//|
-//| class RTC(object):
-//| @property
-//| def datetime(self):
-//| return time.struct_time((2018, 3, 17, 21, 1, 47, 0, 0, 0))
+//| class RTC(object):
+//| @property
+//| def datetime(self):
+//| return time.struct_time((2018, 3, 17, 21, 1, 47, 0, 0, 0))
//|
-//| r = RTC()
-//| rtc.set_time_source(r)
+//| r = RTC()
+//| rtc.set_time_source(r)"""
+//| ...
//|
STATIC mp_obj_t rtc_set_time_source(mp_obj_t time_source) {
MP_STATE_VM(rtc_time_source) = time_source;
diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c
new file mode 100644
index 000000000..1d8c4bafb
--- /dev/null
+++ b/shared-bindings/sdcardio/SDCard.c
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the Micro Python 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/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/objarray.h"
+
+#include "shared-bindings/sdcardio/SDCard.h"
+#include "shared-module/sdcardio/SDCard.h"
+#include "common-hal/busio/SPI.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "supervisor/flash.h"
+
+//| class SDCard:
+//| """SD Card Block Interface
+//|
+//| Controls an SD card over SPI. This built-in module has higher read
+//| performance than the library adafruit_sdcard, but it is only compatible with
+//| `busio.SPI`, not `bitbangio.SPI`. Usually an SDCard object is used
+//| with ``storage.VfsFat`` to allow file I/O to an SD card."""
+//|
+//| def __init__(bus:busio.SPI, cs=digitalio.DigitalInOut, baudrate=8000000):
+//| """Construct an SPI SD Card object with the given properties
+//|
+//| :param busio.SPI spi: The SPI bus
+//| :param microcontroller.Pin cs: The chip select connected to the card
+//| :param int baudrate: The SPI data rate to use after card setup
+//|
+//| Note that during detection and configuration, a hard-coded low baudrate is used.
+//| Data transfers use the specified baurate (rounded down to one that is supported by
+//| the microcontroller)
+//|
+//| Example usage:
+//|
+//| .. code-block:: python
+//|
+//| import os
+//|
+//| import board
+//| import sdcardio
+//| import storage
+//|
+//| sd = sdcardio.SDCard(board.SPI(), board.SD_CS)
+//| vfs = storage.VfsFat(sd)
+//| storage.mount(vfs, '/sd')
+//| os.listdir('/sd')"""
+
+STATIC mp_obj_t sdcardio_sdcard_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, ARG_cs, ARG_baudrate, ARG_sdio, NUM_ARGS };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = mp_const_none } },
+ { MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = mp_const_none } },
+ { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 8000000} },
+ { MP_QSTR_sdio, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_int = 8000000} },
+ };
+ MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
+ 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_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj);
+ mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj);
+
+ sdcardio_sdcard_obj_t *self = m_new_obj(sdcardio_sdcard_obj_t);
+ self->base.type = &sdcardio_SDCard_type;
+
+ common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int);
+
+ return self;
+}
+
+
+//| def count() -> int:
+//| """Returns the total number of sectors
+//|
+//| Due to technical limitations, this is a function and not a property.
+//|
+//| :return: The number of 512-byte blocks, as a number"""
+//|
+mp_obj_t sdcardio_sdcard_count(mp_obj_t self_in) {
+ sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
+ return mp_obj_new_int_from_ull(common_hal_sdcardio_sdcard_get_blockcount(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count);
+
+//| def deinit() -> None:
+//| """Disable permanently.
+//|
+//| :return: None"""
+//|
+mp_obj_t sdcardio_sdcard_deinit(mp_obj_t self_in) {
+ sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
+ common_hal_sdcardio_sdcard_deinit(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit);
+
+
+//| def readblocks(start_block: int, buf: bytearray) -> None:
+//|
+//| """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.
+//|
+//| :return: None"""
+//|
+
+mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
+ uint32_t start_block = mp_obj_get_int(start_block_in);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
+ sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
+ int result = common_hal_sdcardio_sdcard_readblocks(self, start_block, &bufinfo);
+ if (result < 0) {
+ mp_raise_OSError(-result);
+ }
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, sdcardio_sdcard_readblocks);
+
+//| def writeblocks(start_block: int, buf: bytearray) -> 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.
+//|
+//| :return: None"""
+//|
+
+mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
+ uint32_t start_block = mp_obj_get_int(start_block_in);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
+ int result = common_hal_sdcardio_sdcard_writeblocks(self, start_block, &bufinfo);
+ if (result < 0) {
+ mp_raise_OSError(-result);
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, sdcardio_sdcard_writeblocks);
+
+STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdcardio_sdcard_readblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdcardio_sdcard_writeblocks_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(sdcardio_sdcard_locals_dict, sdcardio_sdcard_locals_dict_table);
+
+const mp_obj_type_t sdcardio_SDCard_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SDCard,
+ .make_new = sdcardio_sdcard_make_new,
+ .locals_dict = (mp_obj_dict_t*)&sdcardio_sdcard_locals_dict,
+};
diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h
new file mode 100644
index 000000000..5986d5b81
--- /dev/null
+++ b/shared-bindings/sdcardio/SDCard.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries
+ * 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
+
+extern const mp_obj_type_t sdcardio_SDCard_type;
diff --git a/shared-bindings/sdcardio/__init__.c b/shared-bindings/sdcardio/__init__.c
new file mode 100644
index 000000000..746aa5588
--- /dev/null
+++ b/shared-bindings/sdcardio/__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/sdcardio/SDCard.h"
+
+//| """Interface to an SD card via the SPI bus"""
+
+STATIC const mp_rom_map_elem_t sdcardio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdcardio) },
+ { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdcardio_SDCard_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(sdcardio_module_globals, sdcardio_module_globals_table);
+
+const mp_obj_module_t sdcardio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&sdcardio_module_globals,
+};
diff --git a/shared-bindings/sdcardio/__init__.h b/shared-bindings/sdcardio/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-bindings/sdcardio/__init__.h
diff --git a/shared-bindings/sdioio/SDCard.c b/shared-bindings/sdioio/SDCard.c
new file mode 100644
index 000000000..77b41ce12
--- /dev/null
+++ b/shared-bindings/sdioio/SDCard.c
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+// This file contains all of the Python API definitions for the
+// sdioio.SDCard class.
+
+#include <string.h>
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/sdioio/SDCard.h"
+#include "shared-bindings/util.h"
+
+#include "lib/utils/buffer_helper.h"
+#include "lib/utils/context_manager_helpers.h"
+#include "py/mperrno.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+//| class SDCard:
+//| """SD Card Block Interface with SDIO
+//|
+//| Controls an SD card over SDIO. SDIO is a parallel protocol designed
+//| for SD cards. It uses a clock pin, a command pin, and 1 or 4
+//| data pins. It can be operated at a high frequency such as
+//| 25MHz. Usually an SDCard object is used with ``storage.VfsFat``
+//| to allow file I/O to an SD card."""
+//|
+//| def __init__(*, clock: digitalio.DigitalInOut, command: digitalio.DigitalInOut, data: List[digitalio.DigitalInOut], frequency: int):
+//| """Construct an SDIO SD Card object with the given properties
+//|
+//| :param ~microcontroller.Pin clock: the pin to use for the clock.
+//| :param ~microcontroller.Pin command: the pin to use for the command.
+//| :param data: A sequence of pins to use for data.
+//| :param frequency: The frequency of the bus in Hz
+//|
+//| Example usage:
+//|
+//| .. code-block:: python
+//|
+//| import os
+//|
+//| import board
+//| import sdioio
+//| import storage
+//|
+//| sd = sdioio.SDCard(
+//| clock=board.SDIO_CLOCK,
+//| command=board.SDIO_COMMAND,
+//| data=board.SDIO_DATA,
+//| frequency=25000000)
+//| vfs = storage.VfsFat(sd)
+//| storage.mount(vfs, '/sd')
+//| os.listdir('/sd')"""
+//| ...
+//|
+
+STATIC mp_obj_t sdioio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ sdioio_sdcard_obj_t *self = m_new_obj(sdioio_sdcard_obj_t);
+ self->base.type = &sdioio_SDCard_type;
+ enum { ARG_clock, ARG_command, ARG_data, ARG_frequency, NUM_ARGS };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ },
+ { MP_QSTR_command, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ },
+ { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ },
+ { MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT },
+ };
+ MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
+ 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* clock = validate_obj_is_free_pin(args[ARG_clock].u_obj);
+ const mcu_pin_obj_t* command = validate_obj_is_free_pin(args[ARG_command].u_obj);
+ mcu_pin_obj_t *data_pins[4];
+ uint8_t num_data;
+ validate_list_is_free_pins(MP_QSTR_data, data_pins, MP_ARRAY_SIZE(data_pins), args[ARG_data].u_obj, &num_data);
+
+ common_hal_sdioio_sdcard_construct(self, clock, command, num_data, data_pins, args[ARG_frequency].u_int);
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void check_for_deinit(sdioio_sdcard_obj_t *self) {
+ if (common_hal_sdioio_sdcard_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| def configure(*, frequency=0, width=0) -> None:
+//| """Configures the SDIO bus.
+//|
+//| :param int frequency: the desired clock rate in Hertz. The actual clock rate may be higher or lower due to the granularity of available clock settings. Check the `frequency` attribute for the actual clock rate.
+//| :param int width: the number of data lines to use. Must be 1 or 4 and must also not exceed the number of data lines at construction
+//|
+//| .. note:: Leaving a value unspecified or 0 means the current setting is kept"""
+//|
+STATIC mp_obj_t sdioio_sdcard_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_frequency, ARG_width, NUM_ARGS };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ };
+ sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ check_for_deinit(self);
+ 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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t frequency = args[ARG_frequency].u_int;
+ if (frequency < 0) {
+ mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_baudrate);
+ }
+
+ uint8_t width = args[ARG_width].u_int;
+ if (width != 0 && width != 1 && width != 4) {
+ mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_width);
+ }
+
+ if (!common_hal_sdioio_sdcard_configure(self, frequency, width)) {
+ mp_raise_OSError(MP_EIO);
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(sdioio_sdcard_configure_obj, 1, sdioio_sdcard_configure);
+
+//| def count() -> int:
+//| """Returns the total number of sectors
+//|
+//| Due to technical limitations, this is a function and not a property.
+//|
+//| :return: The number of 512-byte blocks, as a number"""
+//|
+STATIC mp_obj_t sdioio_sdcard_count(mp_obj_t self_in) {
+ sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_sdioio_sdcard_get_count(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_count_obj, sdioio_sdcard_count);
+
+//| def readblocks(start_block: int, buf: bytearray) -> None:
+//|
+//| """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.
+//|
+//| :return: None"""
+mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
+ uint32_t start_block = mp_obj_get_int(start_block_in);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
+ sdioio_sdcard_obj_t *self = (sdioio_sdcard_obj_t*)self_in;
+ int result = common_hal_sdioio_sdcard_readblocks(self, start_block, &bufinfo);
+ if (result < 0) {
+ mp_raise_OSError(-result);
+ }
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks);
+
+//| def writeblocks(start_block: int, buf: bytearray) -> 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.
+//|
+//| :return: None"""
+//|
+mp_obj_t sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
+ uint32_t start_block = mp_obj_get_int(start_block_in);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
+ sdioio_sdcard_obj_t *self = (sdioio_sdcard_obj_t*)self_in;
+ int result = common_hal_sdioio_sdcard_writeblocks(self, start_block, &bufinfo);
+ if (result < 0) {
+ mp_raise_OSError(-result);
+ }
+ return mp_const_none;
+}
+
+MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_writeblocks_obj, sdioio_sdcard_writeblocks);
+
+//| @property
+//| def frequency(self) -> int:
+//| """The actual SDIO bus frequency. This may not match the frequency
+//| requested due to internal limitations."""
+//| ...
+//|
+STATIC mp_obj_t sdioio_sdcard_obj_get_frequency(mp_obj_t self_in) {
+ sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_sdioio_sdcard_get_frequency(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_get_frequency_obj, sdioio_sdcard_obj_get_frequency);
+
+const mp_obj_property_t sdioio_sdcard_frequency_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&sdioio_sdcard_get_frequency_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| @property
+//| def width(self) -> int:
+//| """The actual SDIO bus width, in bits"""
+//| ...
+//|
+STATIC mp_obj_t sdioio_sdcard_obj_get_width(mp_obj_t self_in) {
+ sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_sdioio_sdcard_get_width(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_get_width_obj, sdioio_sdcard_obj_get_width);
+
+const mp_obj_property_t sdioio_sdcard_width_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&sdioio_sdcard_get_width_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| def deinit() -> None:
+//| """Disable permanently.
+//|
+//| :return: None"""
+STATIC mp_obj_t sdioio_sdcard_obj_deinit(mp_obj_t self_in) {
+ sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_sdioio_sdcard_deinit(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_deinit_obj, sdioio_sdcard_obj_deinit);
+
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers.
+//| Provided by context manager helper."""
+//| ...
+//|
+
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
+//|
+STATIC mp_obj_t sdioio_sdcard_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_sdioio_sdcard_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sdioio_sdcard_obj___exit___obj, 4, 4, sdioio_sdcard_obj___exit__);
+
+STATIC const mp_rom_map_elem_t sdioio_sdcard_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdioio_sdcard_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&sdioio_sdcard_obj___exit___obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&sdioio_sdcard_configure_obj) },
+ { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&sdioio_sdcard_frequency_obj) },
+ { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&sdioio_sdcard_width_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdioio_sdcard_count_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdioio_sdcard_readblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdioio_sdcard_writeblocks_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(sdioio_sdcard_locals_dict, sdioio_sdcard_locals_dict_table);
+
+const mp_obj_type_t sdioio_SDCard_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SDCard,
+ .make_new = sdioio_sdcard_make_new,
+ .locals_dict = (mp_obj_dict_t*)&sdioio_sdcard_locals_dict,
+};
diff --git a/shared-bindings/sdioio/SDCard.h b/shared-bindings/sdioio/SDCard.h
new file mode 100644
index 000000000..7f62ee7a6
--- /dev/null
+++ b/shared-bindings/sdioio/SDCard.h
@@ -0,0 +1,66 @@
+/*
+ * 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_BUSIO_SDIO_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SDIO_H
+
+#include "py/obj.h"
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/sdioio/SDCard.h"
+
+// Type object used in Python. Should be shared between ports.
+extern const mp_obj_type_t sdioio_SDCard_type;
+
+// Construct an underlying SDIO object.
+extern void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self,
+ const mcu_pin_obj_t * clock, const mcu_pin_obj_t * command,
+ uint8_t num_data, mcu_pin_obj_t ** data, uint32_t frequency);
+
+extern void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self);
+extern bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self);
+
+extern bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t baudrate, uint8_t width);
+
+extern void common_hal_sdioio_sdcard_unlock(sdioio_sdcard_obj_t *self);
+
+// Return actual SDIO bus frequency.
+uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t* self);
+
+// Return SDIO bus width.
+uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t* self);
+
+// Return number of device blocks
+uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t* self);
+
+// Read or write blocks
+int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t* self, uint32_t start_block, mp_buffer_info_t *bufinfo);
+int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t* self, uint32_t start_block, mp_buffer_info_t *bufinfo);
+
+// This is used by the supervisor to claim SDIO devices indefinitely.
+extern void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SDIO_H
diff --git a/shared-bindings/sdioio/__init__.c b/shared-bindings/sdioio/__init__.c
new file mode 100644
index 000000000..b88e5c3a9
--- /dev/null
+++ b/shared-bindings/sdioio/__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/sdioio/SDCard.h"
+
+//| """Interface to an SD card via the SDIO bus"""
+
+STATIC const mp_rom_map_elem_t sdioio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdio) },
+ { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdioio_SDCard_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(sdioio_module_globals, sdioio_module_globals_table);
+
+const mp_obj_module_t sdioio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&sdioio_module_globals,
+};
diff --git a/shared-bindings/sdioio/__init__.h b/shared-bindings/sdioio/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-bindings/sdioio/__init__.h
diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c
index 2d6c16e90..19c4850cd 100644
--- a/shared-bindings/socket/__init__.c
+++ b/shared-bindings/socket/__init__.c
@@ -37,27 +37,22 @@
#include "shared-module/network/__init__.h"
-//| :mod:`socket` --- TCP, UDP and RAW socket support
-//| =================================================
+//| """TCP, UDP and RAW socket support
//|
-//| .. module:: socket
-//| :synopsis: TCP, UDP and RAW sockets
-//| :platform: SAMD21, SAMD51
-//|
-//| Create TCP, UDP and RAW sockets for communicating over the Internet.
+//| Create TCP, UDP and RAW sockets for communicating over the Internet."""
//|
STATIC const mp_obj_type_t socket_type;
-//| .. currentmodule:: socket
-//|
-//| .. class:: socket(family, type, proto)
+//| class socket:
//|
-//| Create a new socket
+//| def __init__(self, family: int, type: int, proto: int):
+//| """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)"""
+//| ...
//|
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) {
@@ -98,11 +93,11 @@ STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
}
}
-//| .. method:: bind(address)
+//| def bind(self, address: tuple) -> Any:
+//| """Bind a socket to an address
//|
-//| Bind a socket to an address
-//|
-//| :param ~tuple address: tuple of (remote_address, remote_port)
+//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| ...
//|
STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
@@ -125,11 +120,11 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
-//| .. method:: listen(backlog)
-//|
-//| Set socket to listen for incoming connections
+//| def listen(self, backlog: int) -> Any:
+//| """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"""
+//| ...
//|
STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
@@ -150,11 +145,10 @@ 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);
-//| .. method:: accept()
-//|
-//| 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)
+//| def accept(self, ) -> Any:
+//| """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 socket_accept(mp_obj_t self_in) {
@@ -188,11 +182,11 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
-//| .. method:: connect(address)
-//|
-//| Connect a socket to a remote address
+//| def connect(self, address: tuple) -> Any:
+//| """Connect a socket to a remote address
//|
-//| :param ~tuple address: tuple of (remote_address, remote_port)
+//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| ...
//|
STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
@@ -215,12 +209,12 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
-//| .. method:: send(bytes)
-//|
-//| Send some bytes to the connected remote address.
-//| Suits sockets of type SOCK_STREAM
+//| def send(self, bytes: bytes) -> Any:
+//| """Send some bytes to the connected remote address.
+//| Suits sockets of type SOCK_STREAM
//|
-//| :param ~bytes bytes: some bytes to send
+//| :param ~bytes bytes: some bytes to send"""
+//| ...
//|
STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
@@ -252,19 +246,20 @@ STATIC mp_int_t _socket_recv_into(mod_network_socket_obj_t *sock, byte *buf, mp_
}
-//| .. method:: recv_into(buffer[, bufsize])
+//| def recv_into(self, buffer: bytearray, bufsize: int) -> Any:
+//| """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.
//|
-//| 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.
//|
-//| 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."""
+//| ...
//|
-//| :param bytearray buffer: buffer to receive into
-//| :param int bufsize: optionally, a maximum number of bytes to read.
STATIC mp_obj_t socket_recv_into(size_t n_args, const mp_obj_t *args) {
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -287,13 +282,14 @@ STATIC mp_obj_t socket_recv_into(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_into_obj, 2, 3, socket_recv_into);
-//| .. method:: recv(bufsize)
+//| def recv(self, bufsize: int) -> Any:
+//| """Reads some bytes from the connected remote address.
+//| Suits sockets of type SOCK_STREAM
+//| Returns a bytes() of length <= bufsize
//|
-//| Reads some bytes from the connected remote address.
-//| 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
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -313,13 +309,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);
-//| .. method:: sendto(bytes, address)
+//| def sendto(self, bytes: bytes, address: tuple) -> Any:
+//| """Send some bytes to a specific address.
+//| Suits sockets of type SOCK_DGRAM
//|
-//| 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 ~bytes bytes: some bytes to send
+//| :param ~tuple address: tuple of (remote_address, remote_port)"""
+//| ...
//|
STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
@@ -347,16 +343,16 @@ 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);
-//| .. method:: recvfrom(bufsize)
-//|
-//| Reads some bytes from the connected remote address.
-//| Suits sockets of type SOCK_STREAM
+//| def recvfrom(self, bufsize: int) -> Any:
+//| """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
+//| 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
+//| :param ~int bufsize: maximum number of bytes to receive"""
+//| ...
//|
STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
@@ -386,9 +382,9 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
-//| .. method:: setsockopt(level, optname, value)
-//|
-//| Sets socket options
+//| def setsockopt(self, level: Any, optname: Any, value: Any) -> Any:
+//| """Sets socket options"""
+//| ...
//|
STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
@@ -420,11 +416,11 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
-//| .. method:: settimeout(value)
+//| def settimeout(self, value: int) -> Any:
+//| """Set the timeout value for this socket.
//|
-//| 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."""
+//| ...
//|
STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
@@ -451,11 +447,11 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
-//| .. method:: setblocking(flag)
-//|
-//| Set the blocking behaviour of this socket.
+//| def setblocking(self, flag: bool) -> Any:
+//| """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."""
+//| ...
//|
// method socket.setblocking(flag)
@@ -513,13 +509,13 @@ STATIC const mp_obj_type_t socket_type = {
.locals_dict = (mp_obj_dict_t*)&socket_locals_dict,
};
-//| .. function:: getaddrinfo(host, port)
-//|
-//| Gets the address information for a hostname and port
+//| def getaddrinfo(host: Any, port: Any) -> Any:
+//| """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.
+//| 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 socket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c
index ba439b951..3abc5512c 100644
--- a/shared-bindings/storage/__init__.c
+++ b/shared-bindings/storage/__init__.c
@@ -35,26 +35,21 @@
#include "shared-bindings/storage/__init__.h"
#include "supervisor/shared/translate.h"
-//| :mod:`storage` --- storage management
-//| ========================================================
-//|
-//| .. module:: storage
-//| :synopsis: storage management
-//| :platform: SAMD21, SAMD51
+//| """Storage management
//|
//| The `storage` provides storage management functionality such as mounting and
//| unmounting which is typically handled by the operating system hosting Python.
//| CircuitPython does not have an OS, so this module provides this functionality
-//| directly.
+//| directly."""
//|
-//| .. function:: mount(filesystem, mount_path, *, readonly=False)
-//|
-//| Mounts the given filesystem object at the given path.
+//| def mount(filesystem: Any, mount_path: Any, *, readonly: bool = False) -> Any:
+//| """Mounts the given filesystem object at the given path.
//|
-//| This is the CircuitPython analog to the UNIX ``mount`` command.
+//| This is the CircuitPython analog to the UNIX ``mount`` command.
//|
-//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
+//| :param bool readonly: True when the filesystem should be readonly to CircuitPython."""
+//| ...
//|
mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly };
@@ -85,12 +80,12 @@ mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
}
MP_DEFINE_CONST_FUN_OBJ_KW(storage_mount_obj, 2, storage_mount);
-//| .. function:: umount(mount)
-//|
-//| Unmounts the given filesystem object or if *mount* is a path, then unmount
-//| the filesystem mounted at that location.
+//| def umount(mount: Any) -> Any:
+//| """Unmounts the given filesystem object or if *mount* is a path, then unmount
+//| the filesystem mounted at that location.
//|
-//| This is the CircuitPython analog to the UNIX ``umount`` command.
+//| This is the CircuitPython analog to the UNIX ``umount`` command."""
+//| ...
//|
mp_obj_t storage_umount(mp_obj_t mnt_in) {
if (MP_OBJ_IS_STR(mnt_in)) {
@@ -103,15 +98,15 @@ mp_obj_t storage_umount(mp_obj_t mnt_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(storage_umount_obj, storage_umount);
-//| .. function:: remount(mount_path, readonly=False, *, disable_concurrent_write_protection=False)
+//| def remount(mount_path: Any, readonly: bool = False, *, disable_concurrent_write_protection: bool = False) -> Any:
+//| """Remounts the given path with new parameters.
//|
-//| Remounts the given path with new parameters.
-//|
-//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
-//| :param bool disable_concurrent_write_protection: When True, the check that makes sure the
-//| underlying filesystem data is written by one computer is disabled. Disabling the protection
-//| allows CircuitPython and a host to write to the same filesystem with the risk that the
-//| filesystem will be corrupted.
+//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
+//| :param bool disable_concurrent_write_protection: When True, the check that makes sure the
+//| underlying filesystem data is written by one computer is disabled. Disabling the protection
+//| allows CircuitPython and a host to write to the same filesystem with the risk that the
+//| filesystem will be corrupted."""
+//| ...
//|
mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly, ARG_disable_concurrent_write_protection };
@@ -133,28 +128,29 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
}
MP_DEFINE_CONST_FUN_OBJ_KW(storage_remount_obj, 1, storage_remount);
-//| .. function:: getmount(mount_path)
-//|
-//| Retrieves the mount object associated with the mount path
+//| def getmount(mount_path: Any) -> Any:
+//| """Retrieves the mount object associated with the mount path"""
+//| ...
//|
mp_obj_t storage_getmount(const mp_obj_t mnt_in) {
return common_hal_storage_getmount(mp_obj_str_get_str(mnt_in));
}
MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount);
-//| .. function:: erase_filesystem()
+//| def erase_filesystem() -> Any:
+//| """Erase and re-create the ``CIRCUITPY`` filesystem.
//|
-//| Erase and re-create the ``CIRCUITPY`` filesystem.
+//| On boards that present USB-visible ``CIRCUITPY`` drive (e.g., SAMD21 and SAMD51),
+//| then call `microcontroller.reset()` to restart CircuitPython and have the
+//| host computer remount CIRCUITPY.
//|
-//| On boards that present USB-visible ``CIRCUITPY`` drive (e.g., SAMD21 and SAMD51),
-//| then call `microcontroller.reset()` to restart CircuitPython and have the
-//| host computer remount CIRCUITPY.
+//| This function can be called from the REPL when ``CIRCUITPY``
+//| has become corrupted.
//|
-//| This function can be called from the REPL when ``CIRCUITPY``
-//| has become corrupted.
+//| .. warning:: All the data on ``CIRCUITPY`` will be lost, and
+//| CircuitPython will restart on certain boards."""
+//| ...
//|
-//| .. warning:: All the data on ``CIRCUITPY`` will be lost, and
-//| CircuitPython will restart on certain boards.
mp_obj_t storage_erase_filesystem(void) {
common_hal_storage_erase_filesystem();
@@ -171,55 +167,55 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_getmount), MP_ROM_PTR(&storage_getmount_obj) },
{ MP_ROM_QSTR(MP_QSTR_erase_filesystem), MP_ROM_PTR(&storage_erase_filesystem_obj) },
- //| .. class:: VfsFat(block_device)
- //|
- //| Create a new VfsFat filesystem around the given block device.
- //|
- //| :param block_device: Block device the the filesystem lives on
- //|
- //| .. attribute:: label
- //|
- //| The filesystem label, up to 11 case-insensitive bytes. Note that
- //| this property can only be set when the device is writable by the
- //| microcontroller.
- //|
- //| .. method:: mkfs()
- //|
- //| Format the block device, deleting any data that may have been there
- //|
- //| .. method:: open(path, mode)
- //|
- //| Like builtin ``open()``
- //|
- //| .. method:: ilistdir([path])
- //|
- //| Return an iterator whose values describe files and folders within
- //| ``path``
- //|
- //| .. method:: mkdir(path)
- //|
- //| Like `os.mkdir`
- //|
- //| .. method:: rmdir(path)
- //|
- //| Like `os.rmdir`
- //|
- //| .. method:: stat(path)
- //|
- //| Like `os.stat`
- //|
- //| .. method:: statvfs(path)
- //|
- //| Like `os.statvfs`
- //|
- //| .. method:: mount(readonly, mkfs)
- //|
- //| Don't call this directly, call `storage.mount`.
- //|
- //| .. method:: umount()
- //|
- //| Don't call this directly, call `storage.umount`.
- //|
+//| class VfsFat:
+//| def __init__(self, block_device: Any):
+//| """Create a new VfsFat filesystem around the given block device.
+//|
+//| :param block_device: Block device the the filesystem lives on"""
+//|
+//| label: Any = ...
+//| """The filesystem label, up to 11 case-insensitive bytes. Note that
+//| this property can only be set when the device is writable by the
+//| microcontroller."""
+//| ...
+//|
+//| def mkfs(self) -> Any:
+//| """Format the block device, deleting any data that may have been there"""
+//| ...
+//|
+//| def open(self, path: Any, mode: Any) -> Any:
+//| """Like builtin ``open()``"""
+//| ...
+//|
+//| def ilistdir(self, path: Any) -> Any:
+//| """Return an iterator whose values describe files and folders within
+//| ``path``"""
+//| ...
+//|
+//| def mkdir(self, path: Any) -> Any:
+//| """Like `os.mkdir`"""
+//| ...
+//|
+//| def rmdir(self, path: Any) -> Any:
+//| """Like `os.rmdir`"""
+//| ...
+//|
+//| def stat(self, path: Any) -> Any:
+//| """Like `os.stat`"""
+//| ...
+//|
+//| def statvfs(self, path: Any) -> Any:
+//| """Like `os.statvfs`"""
+//| ...
+//|
+//| def mount(self, readonly: Any, mkfs: Any) -> Any:
+//| """Don't call this directly, call `storage.mount`."""
+//| ...
+//|
+//| def umount(self) -> Any:
+//| """Don't call this directly, call `storage.umount`."""
+//| ...
+//|
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
};
diff --git a/shared-bindings/struct/__init__.c b/shared-bindings/struct/__init__.c
index ea14b3763..256b385c8 100644
--- a/shared-bindings/struct/__init__.c
+++ b/shared-bindings/struct/__init__.c
@@ -38,12 +38,7 @@
#include "shared-module/struct/__init__.h"
#include "supervisor/shared/translate.h"
-//| :mod:`struct` --- manipulation of c-style data
-//| ========================================================
-//|
-//| .. module:: struct
-//| :synopsis: byte data control
-//| :platform: SAMD21
+//| """Manipulation of c-style data
//|
//| This module implements a subset of the corresponding CPython module,
//| as described below. For more information, refer to the original CPython
@@ -52,13 +47,13 @@
//| Supported size/byte order prefixes: *@*, *<*, *>*, *!*.
//|
//| Supported format codes: *b*, *B*, *x*, *h*, *H*, *i*, *I*, *l*, *L*, *q*, *Q*,
-//| *s*, *P*, *f*, *d* (the latter 2 depending on the floating-point support).
+//| *s*, *P*, *f*, *d* (the latter 2 depending on the floating-point support)."""
//|
-//| .. function:: calcsize(fmt)
-//|
-//| Return the number of bytes needed to store the given fmt.
+//| def calcsize(fmt: str) -> int:
+//| """Return the number of bytes needed to store the given fmt."""
+//| ...
//|
STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
@@ -67,10 +62,10 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize);
-//| .. function:: pack(fmt, *values)
-//|
-//| Pack the values according to the format string fmt.
-//| The return value is a bytes object encoding the values.
+//| def pack(fmt: Any, *values: Any) -> Any:
+//| """Pack the values according to the format string fmt.
+//| The return value is a bytes object encoding the values."""
+//| ...
//|
STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) {
@@ -85,10 +80,10 @@ 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);
-//| .. function:: pack_into(fmt, buffer, offset, *values)
-//|
-//| 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.
+//| def pack_into(fmt: Any, buffer: Any, offset: Any, *values: Any) -> Any:
+//| """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."""
+//| ...
//|
STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) {
@@ -111,11 +106,11 @@ 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);
-//| .. function:: unpack(fmt, data)
-//|
-//| 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.
+//| def unpack(fmt: Any, data: Any) -> 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."""
+//| ...
//|
STATIC mp_obj_t struct_unpack(size_t n_args, const mp_obj_t *args) {
@@ -129,12 +124,12 @@ 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);
-//| .. function:: unpack_from(fmt, data, offset=0)
-//|
-//| 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
-//| as the size required by the form.
+//| def unpack_from(fmt: Any, data: Any, offset: Any = 0) -> 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
+//| as the size required by the form."""
+//| ...
//|
STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c
index 746dfe5ee..a420d5b80 100755
--- a/shared-bindings/supervisor/Runtime.c
+++ b/shared-bindings/supervisor/Runtime.c
@@ -29,35 +29,30 @@
#include "shared-bindings/supervisor/Runtime.h"
//TODO: add USB, REPL to description once they're operational
-//| .. currentmodule:: supervisor
+//| class Runtime:
+//| """Current status of runtime objects.
//|
-//| :class:`Runtime` --- Supervisor Runtime information
-//| ----------------------------------------------------
+//| Usage::
//|
-//| Get current status of runtime objects.
-//|
-//| Usage::
-//|
-//| import supervisor
-//| if supervisor.runtime.serial_connected:
-//| print("Hello World!")
+//| import supervisor
+//| if supervisor.runtime.serial_connected:
+//| print("Hello World!")"""
//|
-//| .. class:: Runtime()
-//|
-//| You cannot create an instance of `supervisor.Runtime`.
-//| Use `supervisor.runtime` to access the sole instance available.
+//| def __init__(self, ):
+//| """You cannot create an instance of `supervisor.Runtime`.
+//| Use `supervisor.runtime` to access the sole instance available."""
+//| ...
//|
-//| .. attribute:: runtime.serial_connected
-//|
-//| Returns the USB serial communication status (read-only).
+//| serial_connected: bool = ...
+//| """Returns the USB serial communication status (read-only).
//|
//| .. note::
//|
//| SAMD: Will return ``True`` if the USB serial connection
//| has been established at any point. Will not reset if
-//| USB is disconnected but power remains (e.g. battery connected)
+//| USB is disconnected but power remains (e.g. battery connected)"""
//|
STATIC mp_obj_t supervisor_get_serial_connected(mp_obj_t self){
@@ -78,11 +73,10 @@ const mp_obj_property_t supervisor_serial_connected_obj = {
};
-//| .. attribute:: runtime.serial_bytes_available
-//|
-//| Returns the whether any bytes are available to read
-//| on the USB serial input. Allows for polling to see whether
-//| to call the built-in input() or wait. (read-only)
+//| serial_bytes_available: int = ...
+//| """Returns the whether any bytes are available to read
+//| on the USB serial input. Allows for polling to see whether
+//| to call the built-in input() or wait. (read-only)"""
//|
STATIC mp_obj_t supervisor_get_serial_bytes_available(mp_obj_t self){
if (!common_hal_get_serial_bytes_available()) {
diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c
index 2705c8e58..1830308b7 100644
--- a/shared-bindings/supervisor/__init__.c
+++ b/shared-bindings/supervisor/__init__.c
@@ -36,33 +36,18 @@
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/Runtime.h"
-//| :mod:`supervisor` --- Supervisor settings
-//| =================================================
-//|
-//| .. module:: supervisor
-//| :synopsis: Supervisor settings
-//| :platform: SAMD21/51 (All), nRF (Runtime only)
-//|
-//| The `supervisor` module. (TODO: expand description)
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Runtime
+//| """Supervisor settings"""
//|
-//| .. attribute:: runtime
-//|
-//| Runtime information, such as `runtime.serial_connected`
-//| (USB serial connection status).
-//| This object is the sole instance of `supervisor.Runtime`.
+//| runtime: Runtime = ...
+//| """Runtime information, such as ``runtime.serial_connected``
+//| (USB serial connection status).
+//| This object is the sole instance of `supervisor.Runtime`."""
//|
-//| .. method:: enable_autoreload()
-//|
-//| Enable autoreload based on USB file write activity.
+//| def enable_autoreload(self) -> None:
+//| """Enable autoreload based on USB file write activity."""
+//| ...
//|
STATIC mp_obj_t supervisor_enable_autoreload(void) {
autoreload_enable();
@@ -70,10 +55,10 @@ STATIC mp_obj_t supervisor_enable_autoreload(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_enable_autoreload_obj, supervisor_enable_autoreload);
-//| .. method:: disable_autoreload()
-//|
-//| Disable autoreload based on USB file write activity until
-//| `enable_autoreload` is called.
+//| def disable_autoreload(self) -> None:
+//| """Disable autoreload based on USB file write activity until
+//| `enable_autoreload` is called."""
+//| ...
//|
STATIC mp_obj_t supervisor_disable_autoreload(void) {
autoreload_disable();
@@ -81,10 +66,10 @@ STATIC mp_obj_t supervisor_disable_autoreload(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_disable_autoreload_obj, supervisor_disable_autoreload);
-//| .. method:: set_rgb_status_brightness()
-//|
-//| Set brightness of status neopixel from 0-255
-//| `set_rgb_status_brightness` is called.
+//| def set_rgb_status_brightness(self, brightness: int) -> None:
+//| """Set brightness of status neopixel from 0-255
+//| `set_rgb_status_brightness` is called."""
+//| ...
//|
STATIC mp_obj_t supervisor_set_rgb_status_brightness(mp_obj_t lvl){
// This must be int. If cast to uint8_t first, will never raise a ValueError.
@@ -97,9 +82,9 @@ 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);
-//| .. method:: reload()
-//|
-//| Reload the main Python code and run it (equivalent to hitting Ctrl-D at the REPL).
+//| def reload(self) -> None:
+//| """Reload the main Python code and run it (equivalent to hitting Ctrl-D at the REPL)."""
+//| ...
//|
STATIC mp_obj_t supervisor_reload(void) {
reload_requested = true;
@@ -108,9 +93,9 @@ STATIC mp_obj_t supervisor_reload(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
-//| .. method:: set_next_stack_limit(size)
-//|
-//| Set the size of the stack for the next vm run. If its too large, the default will be used.
+//| def set_next_stack_limit(self, size: int) -> None:
+//| """Set the size of the stack for the next vm run. If its too large, the default will be used."""
+//| ...
//|
STATIC mp_obj_t supervisor_set_next_stack_limit(mp_obj_t size_obj) {
mp_int_t size = mp_obj_get_int(size_obj);
diff --git a/shared-bindings/supervisor/__init__.h b/shared-bindings/supervisor/__init__.h
index d2e568945..b79bdacca 100755
--- a/shared-bindings/supervisor/__init__.h
+++ b/shared-bindings/supervisor/__init__.h
@@ -36,4 +36,4 @@ extern const super_runtime_obj_t common_hal_supervisor_runtime_obj;
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SUPERVISOR___INIT___H \ No newline at end of file
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SUPERVISOR___INIT___H
diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c
index 9c01fba20..5c045fdee 100644
--- a/shared-bindings/terminalio/Terminal.c
+++ b/shared-bindings/terminalio/Terminal.c
@@ -37,16 +37,13 @@
#include "shared-bindings/fontio/BuiltinFont.h"
#include "supervisor/shared/translate.h"
-
-//| .. currentmodule:: terminalio
-//|
-//| :class:`Terminal` -- display a character stream with a TileGrid
-//| ================================================================
+//| class Terminal:
+//| """Display a character stream with a TileGrid"""
//|
-//| .. class:: Terminal(tilegrid, font)
-//|
-//| Terminal manages tile indices and cursor position based on VT100 commands. The font should be
-//| a `fontio.BuiltinFont` and the TileGrid's bitmap should match the font's bitmap.
+//| def __init__(self, tilegrid: Any, font: Any):
+//| """Terminal manages tile indices and cursor position based on VT100 commands. The font should be
+//| a `fontio.BuiltinFont` and the TileGrid's bitmap should match the font's bitmap."""
+//| ...
//|
STATIC mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -75,12 +72,12 @@ STATIC mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n
// These are standard stream methods. Code is in py/stream.c.
//
-//| .. method:: write(buf)
-//|
-//| Write the buffer of bytes to the bus.
+//| def write(self, buf: Any) -> Any:
+//| """Write the buffer of bytes to the bus.
//|
-//| :return: the number of bytes written
-//| :rtype: int or None
+//| :return: the number of bytes written
+//| :rtype: int or None"""
+//| ...
//|
STATIC mp_uint_t terminalio_terminal_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/terminalio/__init__.c b/shared-bindings/terminalio/__init__.c
index a9fe20f30..589211139 100644
--- a/shared-bindings/terminalio/__init__.c
+++ b/shared-bindings/terminalio/__init__.c
@@ -35,22 +35,10 @@
#include "py/runtime.h"
-//| :mod:`terminalio` --- Displays text in a TileGrid
-//| =================================================
-//|
-//| .. module:: terminalio
-//| :synopsis: Displays text in a TileGrid
+//| """Displays text in a TileGrid
//|
//| The `terminalio` module contains classes to display a character stream on a display. The built
-//| in font is available as ``terminalio.FONT``.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Terminal
-//|
+//| in font is available as ``terminalio.FONT``."""
//|
STATIC const mp_rom_map_elem_t terminalio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_terminalio) },
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index aa2f4fc6a..d50ce86f6 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -36,24 +36,19 @@
#include "shared-bindings/time/__init__.h"
#include "supervisor/shared/translate.h"
-//| :mod:`time` --- time and timing related functions
-//| ========================================================
-//|
-//| .. module:: time
-//| :synopsis: time and timing related functions
-//| :platform: SAMD21
+//| """time and timing related functions
//|
//| The `time` module is a strict subset of the CPython `cpython:time` module. So, code
//| written in MicroPython will work in CPython but not necessarily the other
-//| way around.
-//|
-//| .. function:: monotonic()
+//| way around."""
//|
-//| Returns an always increasing value of time with an unknown reference
-//| point. Only use it to compare against other values from `monotonic`.
+//| def monotonic() -> Any:
+//| """Returns an always increasing value of time with an unknown reference
+//| point. Only use it to compare against other values from `monotonic`.
//|
-//| :return: the current monotonic time
-//| :rtype: float
+//| :return: the current monotonic time
+//| :rtype: float"""
+//| ...
//|
STATIC mp_obj_t time_monotonic(void) {
uint64_t time64 = common_hal_time_monotonic();
@@ -62,11 +57,11 @@ STATIC mp_obj_t time_monotonic(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic);
-//| .. function:: sleep(seconds)
-//|
-//| Sleep for a given number of seconds.
+//| def sleep(seconds: float) -> Any:
+//| """Sleep for a given number of seconds.
//|
-//| :param float seconds: the time to sleep in fractional seconds
+//| :param float seconds: the time to sleep in fractional seconds"""
+//| ...
//|
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
#if MICROPY_PY_BUILTINS_FLOAT
@@ -97,21 +92,22 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp
return namedtuple_make_new(type, 9, tuple->items, NULL);
}
-//| .. class:: struct_time(time_tuple)
+//| class struct_time:
+//| def __init__(self, time_tuple: Any):
+//| """Structure used to capture a date and time. Note that it takes a tuple!
//|
-//| 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)``
//|
-//| :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)``
-//|
-//| * ``tm_year``: the year, 2017 for example
-//| * ``tm_month``: the month, range [1, 12]
-//| * ``tm_mday``: the day of the month, range [1, 31]
-//| * ``tm_hour``: the hour, range [0, 23]
-//| * ``tm_min``: the minute, range [0, 59]
-//| * ``tm_sec``: the second, range [0, 61]
-//| * ``tm_wday``: the day of the week, range [0, 6], Monday is 0
-//| * ``tm_yday``: the day of the year, range [1, 366], -1 indicates not known
-//| * ``tm_isdst``: 1 when in daylight savings, 0 when not, -1 if unknown.
+//| * ``tm_year``: the year, 2017 for example
+//| * ``tm_month``: the month, range [1, 12]
+//| * ``tm_mday``: the day of the month, range [1, 31]
+//| * ``tm_hour``: the hour, range [0, 23]
+//| * ``tm_min``: the minute, range [0, 59]
+//| * ``tm_sec``: the second, range [0, 61]
+//| * ``tm_wday``: the day of the week, range [0, 6], Monday is 0
+//| * ``tm_yday``: the day of the year, range [1, 366], -1 indicates not known
+//| * ``tm_isdst``: 1 when in daylight savings, 0 when not, -1 if unknown."""
+//| ...
//|
const mp_obj_namedtuple_type_t struct_time_type_obj = {
.base = {
@@ -188,18 +184,26 @@ void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm) {
tm->tm_yday = mp_obj_get_int(elems[7]);
// elems[8] tm_isdst is not supported
}
+#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
+// Function to return a NotImplementedError on platforms that don't
+// support long integers
+STATIC mp_obj_t time_not_implemented(void) {
+ mp_raise_NotImplementedError(translate("No long integer support"));
+}
+MP_DEFINE_CONST_FUN_OBJ_0(time_not_implemented_obj, time_not_implemented);
+#endif
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
mp_raise_RuntimeError(translate("RTC is not supported on this board"));
}
-//| .. function:: time()
+//| def time() -> Any:
+//| """Return the current time in seconds since since Jan 1, 1970.
//|
-//| Return the current time in seconds since since Jan 1, 1970.
-//|
-//| :return: the current time
-//| :rtype: int
+//| :return: the current time
+//| :rtype: int"""
+//| ...
//|
STATIC mp_obj_t time_time(void) {
timeutils_struct_time_t tm;
@@ -210,12 +214,12 @@ STATIC mp_obj_t time_time(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
-//| .. function:: monotonic_ns()
-//|
-//| Return the time of the specified clock clk_id in nanoseconds.
+//| def monotonic_ns() -> Any:
+//| """Return the time of the specified clock clk_id in nanoseconds.
//|
-//| :return: the current time
-//| :rtype: int
+//| :return: the current time
+//| :rtype: int"""
+//| ...
//|
STATIC mp_obj_t time_monotonic_ns(void) {
uint64_t time64 = common_hal_time_monotonic_ns();
@@ -223,15 +227,15 @@ STATIC mp_obj_t time_monotonic_ns(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns);
-//| .. function:: localtime([secs])
-//|
-//| Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in
-//| local time. If secs is not provided or None, the current time as returned
-//| by time() is used.
-//| The earliest date for which it can generate a time is Jan 1, 2000.
+//| def localtime(secs: Any) -> Any:
+//| """Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in
+//| local time. If secs is not provided or None, the current time as returned
+//| by time() is used.
+//| The earliest date for which it can generate a time is Jan 1, 2000.
//|
-//| :return: the current time
-//| :rtype: time.struct_time
+//| :return: the current time
+//| :rtype: time.struct_time"""
+//| ...
//|
STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
if (n_args == 0 || args[0] == mp_const_none) {
@@ -256,15 +260,15 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
-//| .. function:: mktime(t)
+//| def mktime(t: Any) -> Any:
+//| """This is the inverse function of localtime(). Its argument is the
+//| struct_time or full 9-tuple (since the dst flag is needed; use -1 as the
+//| dst flag if it is unknown) which expresses the time in local time, not UTC.
+//| The earliest date for which it can generate a time is Jan 1, 2000.
//|
-//| This is the inverse function of localtime(). Its argument is the
-//| struct_time or full 9-tuple (since the dst flag is needed; use -1 as the
-//| dst flag if it is unknown) which expresses the time in local time, not UTC.
-//| The earliest date for which it can generate a time is Jan 1, 2000.
-//|
-//| :return: seconds
-//| :rtype: int
+//| :return: seconds
+//| :rtype: int"""
+//| ...
//|
STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_obj_t *elem;
@@ -307,6 +311,12 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
{ MP_ROM_QSTR(MP_QSTR_monotonic_ns), MP_ROM_PTR(&time_monotonic_ns_obj) },
#endif
+ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
+ { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_not_implemented_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_not_implemented_obj) },
+ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_not_implemented_obj) },
+ { MP_ROM_QSTR(MP_QSTR_monotonic_ns), MP_ROM_PTR(&time_not_implemented_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c
index 33d369c74..4c1d534ea 100644
--- a/shared-bindings/touchio/TouchIn.c
+++ b/shared-bindings/touchio/TouchIn.c
@@ -38,27 +38,25 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: touchio
+//| class TouchIn:
+//| """Read the state of a capacitive touch sensor
//|
-//| :class:`TouchIn` -- Read the state of a capacitive touch sensor
-//| ===================================================================
+//| Usage::
//|
-//| Usage::
+//| import touchio
+//| from board import *
//|
-//| import touchio
-//| from board import *
-//|
-//| touch = touchio.TouchIn(A1)
-//| while True:
-//| if touch.value:
-//| print("touched!")
+//| touch = touchio.TouchIn(A1)
+//| while True:
+//| if touch.value:
+//| print("touched!")"""
//|
-//| .. class:: TouchIn(pin)
-//|
-//| Use the TouchIn on the given pin.
+//| def __init__(self, pin: microcontroller.Pin):
+//| """Use the TouchIn on the given pin.
//|
-//| :param ~microcontroller.Pin pin: the pin to read from
+//| :param ~microcontroller.Pin pin: the pin to read from"""
+//| ...
//|
STATIC mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type,
mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
@@ -66,10 +64,7 @@ STATIC mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type,
mp_arg_check_num(n_args, kw_args, 1, 1, false);
// 1st argument is the pin
- mp_obj_t pin_obj = args[0];
- assert_pin(pin_obj, false);
- const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj);
- assert_pin_free(pin);
+ const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
touchio_touchin_obj_t *self = m_new_obj(touchio_touchin_obj_t);
self->base.type = &touchio_touchin_type;
@@ -78,9 +73,9 @@ STATIC mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type,
return (mp_obj_t) self;
}
-//| .. method:: deinit()
-//|
-//| Deinitialises the TouchIn and releases any hardware resources for reuse.
+//| def deinit(self, ) -> Any:
+//| """Deinitialises the TouchIn and releases any hardware resources for reuse."""
+//| ...
//|
STATIC mp_obj_t touchio_touchin_deinit(mp_obj_t self_in) {
touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -95,16 +90,16 @@ STATIC void check_for_deinit(touchio_touchin_obj_t *self) {
}
}
-//| .. method:: __enter__()
-//|
-//| No-op used by Context Managers.
+//| def __enter__(self, ) -> Any:
+//| """No-op used by Context Managers."""
+//| ...
//|
// Provided by context manager helper.
-//| .. method:: __exit__()
-//|
-//| Automatically deinitializes the hardware when exiting a context. See
-//| :ref:`lifetime-and-contextmanagers` for more info.
+//| def __exit__(self, ) -> Any:
+//| """Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info."""
+//| ...
//|
STATIC mp_obj_t touchio_touchin_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
@@ -113,11 +108,10 @@ STATIC mp_obj_t touchio_touchin_obj___exit__(size_t n_args, const mp_obj_t *args
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(touchio_touchin___exit___obj, 4, 4, touchio_touchin_obj___exit__);
-//| .. attribute:: value
-//|
-//| Whether the touch pad is being touched or not. (read-only)
+//| value: Any = ...
+//| """Whether the touch pad is being touched or not. (read-only)
//|
-//| True when `raw_value` > `threshold`.
+//| True when `raw_value` > `threshold`."""
//|
STATIC mp_obj_t touchio_touchin_obj_get_value(mp_obj_t self_in) {
touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -134,9 +128,8 @@ const mp_obj_property_t touchio_touchin_value_obj = {
};
-//| .. attribute:: raw_value
-//|
-//| The raw touch measurement as an `int`. (read-only)
+//| raw_value: Any = ...
+//| """The raw touch measurement as an `int`. (read-only)"""
//|
STATIC mp_obj_t touchio_touchin_obj_get_raw_value(mp_obj_t self_in) {
touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -154,14 +147,13 @@ const mp_obj_property_t touchio_touchin_raw_value_obj = {
};
-//| .. attribute:: threshold
-//|
-//| Minimum `raw_value` needed to detect a touch (and for `value` to be `True`).
+//| threshold: Any = ...
+//| """Minimum `raw_value` needed to detect a touch (and for `value` to be `True`).
//|
//| When the **TouchIn** object is created, an initial `raw_value` is read from the pin,
//| and then `threshold` is set to be 100 + that value.
//|
-//| You can adjust `threshold` to make the pin more or less sensitive.
+//| You can adjust `threshold` to make the pin more or less sensitive."""
//|
STATIC mp_obj_t touchio_touchin_obj_get_threshold(mp_obj_t self_in) {
touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/touchio/__init__.c b/shared-bindings/touchio/__init__.c
index 6adbe09cf..92e067cf6 100644
--- a/shared-bindings/touchio/__init__.c
+++ b/shared-bindings/touchio/__init__.c
@@ -35,23 +35,11 @@
#include "py/runtime.h"
-//| :mod:`touchio` --- Touch related IO
-//| =================================================
-//|
-//| .. module:: touchio
-//| :synopsis: Hardware accelerated behavior
-//| :platform: SAMD21
+//| """Touch related IO
//|
//| The `touchio` module contains classes to provide access to touch IO typically
//| accelerated by hardware on the onboard microcontroller.
//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| TouchIn
-//|
//| 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
@@ -66,7 +54,7 @@
//| print(touch_pin.value)
//|
//| This example will initialize the the device, and print the
-//| :py:data:`~touchio.TouchIn.value`.
+//| :py:data:`~touchio.TouchIn.value`."""
//|
STATIC const mp_rom_map_elem_t touchio_module_globals_table[] = {
diff --git a/shared-bindings/uheap/__init__.c b/shared-bindings/uheap/__init__.c
index 0d699cd28..f089f2922 100644
--- a/shared-bindings/uheap/__init__.c
+++ b/shared-bindings/uheap/__init__.c
@@ -31,17 +31,13 @@
#include "shared-bindings/uheap/__init__.h"
-//| :mod:`uheap` --- Heap size analysis
-//| ================================================================
-//|
-//| .. module:: uheap
-//| :synopsis: Heap size analysis
+//| """Heap size analysis"""
//|
-//| .. function:: info(object)
-//|
-//| Prints memory debugging info for the given object and returns the
-//| estimated size.
+//| def info(object: Any) -> Any:
+//| """Prints memory debugging info for the given object and returns the
+//| estimated size."""
+//| ...
//|
STATIC mp_obj_t uheap_info(mp_obj_t obj) {
uint32_t size = shared_module_uheap_info(obj);
diff --git a/shared-bindings/ulab/__init__.pyi b/shared-bindings/ulab/__init__.pyi
new file mode 100644
index 000000000..e5de1391b
--- /dev/null
+++ b/shared-bindings/ulab/__init__.pyi
@@ -0,0 +1,169 @@
+"""Manipulate numeric data similar to numpy
+
+`ulab` is a numpy-like module for micropython, meant to simplify and
+speed up common mathematical operations on arrays. The primary goal was to
+implement a small subset of numpy that might be useful in the context of a
+microcontroller. This means low-level data processing of linear (array) and
+two-dimensional (matrix) data.
+
+`ulab` is adapted from micropython-ulab, and the original project's
+documentation can be found at
+https://micropython-ulab.readthedocs.io/en/latest/
+
+`ulab` is modeled after numpy, and aims to be a compatible subset where
+possible. Numpy's documentation can be found at
+https://docs.scipy.org/doc/numpy/index.html"""
+
+
+class array:
+ """1- and 2- dimensional array"""
+ def __init__(self, values, *, dtype=float):
+ """:param sequence values: Sequence giving the initial content of the array.
+ :param dtype: The type of array values, ``int8``, ``uint8``, ``int16``, ``uint16``, or ``float``
+
+ The `values` sequence can either be another ~ulab.array, sequence of numbers
+ (in which case a 1-dimensional array is created), or a sequence where each
+ subsequence has the same length (in which case a 2-dimensional array is
+ created).
+
+ Passing a ~ulab.array and a different dtype can be used to convert an array
+ from one dtype to another.
+
+ In many cases, it is more convenient to create an array from a function
+ like `zeros` or `linspace`.
+
+ `ulab.array` implements the buffer protocol, so it can be used in many
+ places an `array.array` can be used."""
+ ...
+
+ shape: tuple = ...
+ """The size of the array, a tuple of length 1 or 2"""
+
+ size: int = ...
+ """The number of elements in the array"""
+
+ itemsize: int = ...
+ """The number of elements in the array"""
+
+ def flatten(self, *, order='C'):
+ """:param order: Whether to flatten by rows ('C') or columns ('F')
+
+ Returns a new `ulab.array` object which is always 1 dimensional.
+ If order is 'C' (the default", then the data is ordered in rows;
+ If it is 'F', then the data is ordered in columns. "C" and "F" refer
+ to the typical storage organization of the C and Fortran languages."""
+ ...
+
+ def sort(self, *, axis=1):
+ """:param axis: Whether to sort elements within rows (0), columns (1), or elements (None)"""
+ ...
+
+ def transpose(self):
+ """Swap the rows and columns of a 2-dimensional array"""
+ ...
+
+ def __add__(self):
+ """Adds corresponding elements of the two arrays, or adds a number to all
+ elements of the array. If both arguments are arrays, their sizes must match."""
+ ...
+
+ def __sub__(self):
+ """Subtracts corresponding elements of the two arrays, or adds a number to all
+ elements of the array. If both arguments are arrays, their sizes must match."""
+ ...
+
+ def __mul__(self):
+ """Multiplies corresponding elements of the two arrays, or multiplies
+ all elements of the array by a number. If both arguments are arrays,
+ their sizes must match."""
+ ...
+
+ def __div__(self):
+ """Multiplies corresponding elements of the two arrays, or divides
+ all elements of the array by a number. If both arguments are arrays,
+ their sizes must match."""
+ ...
+
+ def __pow__():
+ """Computes the power (x**y) of corresponding elements of the the two arrays,
+ or one number and one array. If both arguments are arrays, their sizes
+ must match."""
+ ...
+
+ def __getitem__():
+ """Retrieve an element of the array."""
+ ...
+
+ def __setitem__():
+ """Set an element of the array."""
+ ...
+
+int8 = ...
+"""Type code for signed integers in the range -128 .. 127 inclusive, like the 'b' typecode of `array.array`"""
+
+int16 = ...
+"""Type code for signed integers in the range -32768 .. 32767 inclusive, like the 'h' typecode of `array.array`"""
+
+float = ...
+"""Type code for floating point values, like the 'f' typecode of `array.array`"""
+
+uint8 = ...
+"""Type code for unsigned integers in the range 0 .. 255 inclusive, like the 'H' typecode of `array.array`"""
+
+uint16 = ...
+"""Type code for unsigned integers in the range 0 .. 65535 inclusive, like the 'h' typecode of `array.array`"""
+
+def ones(shape, *, dtype=float):
+ """
+ .. param: shape
+ Shape of the array, either an integer (for a 1-D array) or a tuple of 2 integers (for a 2-D array)
+
+ .. param: dtype
+ Type of values in the array
+
+ Return a new array of the given shape with all elements set to 1."""
+ ...
+
+def zeros(shape, *, dtype):
+ """
+ .. param: shape
+ Shape of the array, either an integer (for a 1-D array) or a tuple of 2 integers (for a 2-D array)
+
+ .. param: dtype
+ Type of values in the array
+
+ Return a new array of the given shape with all elements set to 0."""
+ ...
+
+
+def eye(size, *, dtype=float):
+ """Return a new square array of size, with the diagonal elements set to 1
+ and the other elements set to 0."""
+ ...
+
+def linspace(start, stop, *, dtype=float, num=50, endpoint=True):
+ """
+ .. param: start
+
+ First value in the array
+
+ .. param: stop
+
+ Final value in the array
+
+ .. param int: num
+
+ Count of values in the array
+
+ .. param: dtype
+
+ Type of values in the array
+
+ .. param bool: endpoint
+
+ Whether the ``stop`` value is included. Note that even when
+ endpoint=True, the exact ``stop`` value may not be included due to the
+ inaccuracy of floating point arithmetic.
+
+ Return a new 1-D array with ``num`` elements ranging from ``start`` to ``stop`` linearly."""
+ ...
diff --git a/shared-bindings/ulab/approx/__init__.pyi b/shared-bindings/ulab/approx/__init__.pyi
new file mode 100644
index 000000000..7e012690f
--- /dev/null
+++ b/shared-bindings/ulab/approx/__init__.pyi
@@ -0,0 +1,51 @@
+"""Numerical approximation methods"""
+
+def bisect(fun, a, b, *, xtol=2.4e-7, maxiter=100) -> float:
+ """
+ :param callable f: The function to bisect
+ :param float a: The left side of the interval
+ :param float b: The right side of the interval
+ :param float xtol: The tolerance value
+ :param float maxiter: The maximum number of iterations to perform
+
+ Find a solution (zero) of the function ``f(x)`` on the interval
+ (``a``..``b``) using the bisection method. The result is accurate to within
+ ``xtol`` unless more than ``maxiter`` steps are required."""
+ ...
+
+def newton(fun, x0, *, xtol=2.4e-7, rtol=0.0, maxiter=50) -> float:
+ """
+ :param callable f: The function to bisect
+ :param float x0: The initial x value
+ :param float xtol: The absolute tolerance value
+ :param float rtol: The relative tolerance value
+ :param float maxiter: The maximum number of iterations to perform
+
+ Find a solution (zero) of the function ``f(x)`` using Newton's Method.
+ The result is accurate to within ``xtol * rtol * |f(x)|`` unless more than
+ ``maxiter`` steps are requried."""
+ ...
+
+def fmin(fun, x0, *, xatol=2.4e-7, fatol=2.4e-7, maxiter=200) -> float:
+ """
+ :param callable f: The function to bisect
+ :param float x0: The initial x value
+ :param float xatol: The absolute tolerance value
+ :param float fatol: The relative tolerance value
+
+ Find a minimum of the function ``f(x)`` using the downhill simplex method.
+ The located ``x`` is within ``fxtol`` of the actual minimum, and ``f(x)``
+ is within ``fatol`` of the actual minimum unless more than ``maxiter``
+ steps are requried."""
+ ...
+
+def interp(x: ulab.array, xp:ulab.array, fp:ulab.array, *, left=None, right=None) -> ulab.array:
+ """
+ :param ulab.array x: The x-coordinates at which to evaluate the interpolated values.
+ :param ulab.array xp: The x-coordinates of the data points, must be increasing
+ :param ulab.array fp: The y-coordinates of the data points, same length as xp
+ :param left: Value to return for ``x < xp[0]``, default is ``fp[0]``.
+ :param right: Value to return for ``x > xp[-1]``, default is ``fp[-1]``.
+
+ Returns the one-dimensional piecewise linear interpolant to a function with given discrete data points (xp, fp), evaluated at x."""
+ ...
diff --git a/shared-bindings/ulab/compare/__init__.pyi b/shared-bindings/ulab/compare/__init__.pyi
new file mode 100644
index 000000000..1606e43c2
--- /dev/null
+++ b/shared-bindings/ulab/compare/__init__.pyi
@@ -0,0 +1,38 @@
+"""Comparison functions"""
+
+def clip(x1, x2, x3):
+ """
+ Constrain the values from ``x1`` to be between ``x2`` and ``x3``.
+ ``x2`` is assumed to be less than or equal to ``x3``.
+
+ Arguments may be ulab arrays or numbers. All array arguments
+ must be the same size. If the inputs are all scalars, a 1-element
+ array is returned.
+
+ Shorthand for ``ulab.maximum(x2, ulab.minimum(x1, x3))``"""
+ ...
+
+def maximum(x1, x2):
+ """
+ Compute the element by element maximum of the arguments.
+
+ Arguments may be ulab arrays or numbers. All array arguments
+ must be the same size. If the inputs are both scalars, a number is
+ returned"""
+ ...
+
+def minimum(x1, x2):
+ """Compute the element by element minimum of the arguments.
+
+ Arguments may be ulab arrays or numbers. All array arguments
+ must be the same size. If the inputs are both scalars, a number is
+ returned"""
+ ...
+
+def equal(x1, x2):
+ """Return an array of bool which is true where x1[i] == x2[i] and false elsewhere"""
+ ...
+
+def not_equal(x1, x2):
+ """Return an array of bool which is false where x1[i] == x2[i] and true elsewhere"""
+ ...
diff --git a/shared-bindings/ulab/extras/__init__.pyi b/shared-bindings/ulab/extras/__init__.pyi
new file mode 100644
index 000000000..4da56a582
--- /dev/null
+++ b/shared-bindings/ulab/extras/__init__.pyi
@@ -0,0 +1,10 @@
+"""Additional functions not in numpy"""
+
+def spectrum(r):
+ """
+ :param ulab.array r: A 1-dimension array of values whose size is a power of 2
+
+ Computes the spectrum of the input signal. This is the absolute value of the (complex-valued) fft of the signal.
+
+ This function is similar to scipy's ``scipy.signal.spectrogram``."""
+ ...
diff --git a/shared-bindings/ulab/fft/__init__.pyi b/shared-bindings/ulab/fft/__init__.pyi
new file mode 100644
index 000000000..401ecb644
--- /dev/null
+++ b/shared-bindings/ulab/fft/__init__.pyi
@@ -0,0 +1,22 @@
+"""Frequency-domain functions"""
+
+def fft(r, c=None):
+ """
+ :param ulab.array r: A 1-dimension array of values whose size is a power of 2
+ :param ulab.array c: An optional 1-dimension array of values whose size is a power of 2, giving the complex part of the value
+ :return tuple (r, c): The real and complex parts of the FFT
+
+ Perform a Fast Fourier Transform from the time domain into the frequency domain
+
+ See also ~ulab.extras.spectrum, which computes the magnitude of the fft,
+ rather than separately returning its real and imaginary parts."""
+ ...
+
+def ifft(r, c=None):
+ """
+ :param ulab.array r: A 1-dimension array of values whose size is a power of 2
+ :param ulab.array c: An optional 1-dimension array of values whose size is a power of 2, giving the complex part of the value
+ :return tuple (r, c): The real and complex parts of the inverse FFT
+
+ Perform an Inverse Fast Fourier Transform from the frequeny domain into the time domain"""
+ ...
diff --git a/shared-bindings/ulab/filter/__init__.pyi b/shared-bindings/ulab/filter/__init__.pyi
new file mode 100644
index 000000000..5e7202e06
--- /dev/null
+++ b/shared-bindings/ulab/filter/__init__.pyi
@@ -0,0 +1,36 @@
+"""Filtering functions"""
+
+def convolve(r, c=None):
+ """
+ :param ulab.array a:
+ :param ulab.array v:
+
+ Returns the discrete, linear convolution of two one-dimensional sequences.
+ The result is always an array of float. Only the ``full`` mode is supported,
+ and the ``mode`` named parameter of numpy is not accepted. Note that all other
+ modes can be had by slicing a ``full`` result.
+
+ Convolution filters can implement high pass, low pass, band pass, etc.,
+ filtering operations. Convolution filters are typically constructed ahead
+ of time. This can be done using desktop python with scipy, or on web pages
+ such as https://fiiir.com/
+
+ Convolution is most time-efficient when both inputs are of float type."""
+ ...
+
+def sosfilt(sos : ulab.array, x : ulab.array, *, xi : Optional[ulab.array] = None) -> Union[ulab.array, Tuple[ulab.array, ulab.array]]:
+ """
+ :param ulab.array sos: Array of second-order filter coefficients, must have shape (n_sections, 6). Each row corresponds to a second-order section, with the first three columns providing the numerator coefficients and the last three providing the denominator coefficients.
+ :param ulab.array x: The data to be filtered
+ :param ulab.array zi: Optional initial conditions for the filter
+
+ :return: If ``xi`` is not specified, the filter result alone is returned. If ``xi`` is specified, the return value is a 2-tuple of the filter result and the final filter conditions.
+
+ Filter data along one dimension using cascaded second-order sections.
+
+ Filter a data sequence, x, using a digital IIR filter defined by sos.
+
+ The filter function is implemented as a series of second-order filters with direct-form II transposed structure. It is designed to minimize numerical precision errors for high-order filters.
+
+ Filter coefficients can be generated by using scipy's filter generators such as ``signal.ellip(..., output='sos')``."""
+ ...
diff --git a/shared-bindings/ulab/linalg/__init__.pyi b/shared-bindings/ulab/linalg/__init__.pyi
new file mode 100644
index 000000000..d16e61807
--- /dev/null
+++ b/shared-bindings/ulab/linalg/__init__.pyi
@@ -0,0 +1,57 @@
+"""Linear algebra functions"""
+
+
+def cholesky(A):
+ """
+ :param ~ulab.array A: a positive definite, symmetric square matrix
+ :return ~ulab.array L: a square root matrix in the lower triangular form
+ :raises ValueError: If the input does not fulfill the necessary conditions
+
+ The returned matrix satisfies the equation m=LL*"""
+ ...
+
+def det():
+ """
+ :param: m, a square matrix
+ :return float: The determinant of the matrix
+
+ Computes the eigenvalues and eigenvectors of a square matrix"""
+ ...
+
+def dot(m1, m2):
+ """
+ :param ~ulab.array m1: a matrix
+ :param ~ulab.array m2: a matrix
+
+ Computes the matrix product of two matrices
+
+ **WARNING:** Unlike ``numpy``, this function cannot be used to compute the dot product of two vectors"""
+ ...
+
+def eig(m):
+ """
+ :param m: a square matrix
+ :return tuple (eigenvectors, eigenvalues):
+
+ Computes the eigenvalues and eigenvectors of a square matrix"""
+ ...
+
+def inv(m):
+ """
+ :param ~ulab.array m: a square matrix
+ :return: The inverse of the matrix, if it exists
+ :raises ValueError: if the matrix is not invertible
+
+ Computes the inverse of a square matrix"""
+ ...
+
+def size(array):
+ """Return the total number of elements in the array, as an integer."""
+ ...
+
+def trace(m):
+ """
+ :param m: a square matrix
+
+ Compute the trace of the matrix, the sum of its diagonal elements."""
+ ...
diff --git a/shared-bindings/ulab/numerical/__init__.pyi b/shared-bindings/ulab/numerical/__init__.pyi
new file mode 100644
index 000000000..759678921
--- /dev/null
+++ b/shared-bindings/ulab/numerical/__init__.pyi
@@ -0,0 +1,57 @@
+"""Numerical and Statistical functions
+
+Most of these functions take an "axis" argument, which indicates whether to
+operate over the flattened array (None), rows (0), or columns (1)."""
+
+def argmax(array, *, axis=None):
+ """Return the index of the maximum element of the 1D array"""
+ ...
+
+def argmin(array, *, axis=None):
+ """Return the index of the minimum element of the 1D array"""
+ ...
+
+def argsort(array, *, axis=None):
+ """Returns an array which gives indices into the input array from least to greatest."""
+ ...
+
+def diff(array, *, axis=1):
+ """Return the numerical derivative of successive elements of the array, as
+ an array. axis=None is not supported."""
+ ...
+
+def flip(array, *, axis=None):
+ """Returns a new array that reverses the order of the elements along the
+ given axis, or along all axes if axis is None."""
+ ...
+
+def max(array, *, axis=None):
+ """Return the maximum element of the 1D array"""
+ ...
+
+def mean(array, *, axis=None):
+ """Return the mean element of the 1D array, as a number if axis is None, otherwise as an array."""
+ ...
+
+def min(array, *, axis=None):
+ """Return the minimum element of the 1D array"""
+ ...
+
+def roll(array, distance, *, axis=None):
+ """Shift the content of a vector by the positions given as the second
+ argument. If the ``axis`` keyword is supplied, the shift is applied to
+ the given axis. The array is modified in place."""
+ ...
+
+def std(array, *, axis=None):
+ """Return the standard deviation of the array, as a number if axis is None, otherwise as an array."""
+ ...
+
+def sum(array, *, axis=None):
+ """Return the sum of the array, as a number if axis is None, otherwise as an array."""
+ ...
+
+def sort(array, *, axis=0):
+ """Sort the array along the given axis, or along all axes if axis is None.
+ The array is modified in place."""
+ ...
diff --git a/shared-bindings/ulab/poly/__init__.pyi b/shared-bindings/ulab/poly/__init__.pyi
new file mode 100644
index 000000000..d051bbded
--- /dev/null
+++ b/shared-bindings/ulab/poly/__init__.pyi
@@ -0,0 +1,10 @@
+"""Polynomial functions"""
+
+def polyfit(x, y, degree):
+ """Return a polynomial of given degree that approximates the function
+ f(x)=y. If x is not supplied, it is the range(len(y))."""
+ ...
+
+def polyval(p, x):
+ """Evaluate the polynomial p at the points x. x must be an array."""
+ ...
diff --git a/shared-bindings/ulab/vector/__init__.pyi b/shared-bindings/ulab/vector/__init__.pyi
new file mode 100644
index 000000000..bf57e419c
--- /dev/null
+++ b/shared-bindings/ulab/vector/__init__.pyi
@@ -0,0 +1,118 @@
+"""Element-by-element functions
+
+These functions can operate on numbers, 1-D arrays, or 2-D arrays by
+applying the function to every element in the array. This is typically
+much more efficient than expressing the same operation as a Python loop."""
+
+def acos():
+ """Computes the inverse cosine function"""
+ ...
+
+def acosh():
+ """Computes the inverse hyperbolic cosine function"""
+ ...
+
+def asin():
+ """Computes the inverse sine function"""
+ ...
+
+def asinh():
+ """Computes the inverse hyperbolic sine function"""
+ ...
+
+def around(a, *, decimals):
+ """Returns a new float array in which each element is rounded to
+ ``decimals`` places."""
+ ...
+
+def atan():
+ """Computes the inverse tangent function; the return values are in the
+ range [-pi/2,pi/2]."""
+ ...
+
+def atan2(y,x):
+ """Computes the inverse tangent function of y/x; the return values are in
+ the range [-pi, pi]."""
+ ...
+
+def atanh():
+ """Computes the inverse hyperbolic tangent function"""
+ ...
+
+def ceil():
+ """Rounds numbers up to the next whole number"""
+ ...
+
+def cos():
+ """Computes the cosine function"""
+ ...
+
+def erf():
+ """Computes the error function, which has applications in statistics"""
+ ...
+
+def erfc():
+ """Computes the complementary error function, which has applications in statistics"""
+ ...
+
+def exp():
+ """Computes the exponent function."""
+ ...
+
+def expm1():
+ """Computes $e^x-1$. In certain applications, using this function preserves numeric accuracy better than the `exp` function."""
+ ...
+
+def floor():
+ """Rounds numbers up to the next whole number"""
+ ...
+
+def gamma():
+ """Computes the gamma function"""
+ ...
+
+def lgamma():
+ """Computes the natural log of the gamma function"""
+ ...
+
+def log():
+ """Computes the natural log"""
+ ...
+
+def log10():
+ """Computes the log base 10"""
+ ...
+
+def log2():
+ """Computes the log base 2"""
+ ...
+
+def sin():
+ """Computes the sine"""
+ ...
+
+def sinh():
+ """Computes the hyperbolic sine"""
+ ...
+
+def sqrt():
+ """Computes the square root"""
+ ...
+
+def tan():
+ """Computes the tangent"""
+ ...
+
+def tanh():
+ """Computes the hyperbolic tangent"""
+ ...
+
+def vectorize(f, *, otypes=None):
+ """
+ :param callable f: The function to wrap
+ :param otypes: List of array types that may be returned by the function. None is intepreted to mean the return value is float.
+
+ Wrap a Python function ``f`` so that it can be applied to arrays.
+
+ The callable must return only values of the types specified by otypes, or the result is undefined."""
+ ...
diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c
index b1097fb24..8c0c364ff 100644
--- a/shared-bindings/usb_hid/Device.c
+++ b/shared-bindings/usb_hid/Device.c
@@ -27,27 +27,25 @@
#include "py/objproperty.h"
#include "shared-bindings/usb_hid/Device.h"
-//| .. currentmodule:: usb_hid
+//| class Device:
+//| """HID Device
//|
-//| :class:`Device` -- HID Device
-//| ============================================
+//| Usage::
//|
-//| Usage::
+//| import usb_hid
//|
-//| import usb_hid
+//| mouse = usb_hid.devices[0]
//|
-//| mouse = usb_hid.devices[0]
-//|
-//| mouse.send_report()
+//| mouse.send_report()"""
//|
-//| .. class:: Device()
-//|
-//| Not currently dynamically supported.
-//|
-//| .. method:: send_report(buf)
+//| def __init__(self, ):
+//| """Not currently dynamically supported."""
+//| ...
//|
-//| Send a HID report.
+//| def send_report(self, buf: Any) -> Any:
+//| """Send a HID report."""
+//| ...
//|
STATIC mp_obj_t usb_hid_device_send_report(mp_obj_t self_in, mp_obj_t buffer) {
usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -60,9 +58,8 @@ 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);
-//| .. attribute:: usage_page
-//|
-//| The usage page of the device as an `int`. Can be thought of a category. (read-only)
+//| usage_page: Any = ...
+//| """The usage page of the device as an `int`. Can be thought of a category. (read-only)"""
//|
STATIC mp_obj_t usb_hid_device_obj_get_usage_page(mp_obj_t self_in) {
usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -77,12 +74,11 @@ const mp_obj_property_t usb_hid_device_usage_page_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: usage
-//|
-//| The functionality of the device as an int. (read-only)
+//| usage: Any = ...
+//| """The functionality of the device as an int. (read-only)
//|
//| For example, Keyboard is 0x06 within the generic desktop usage page 0x01.
-//| Mouse is 0x02 within the same usage page.
+//| Mouse is 0x02 within the same usage page."""
//|
STATIC mp_obj_t usb_hid_device_obj_get_usage(mp_obj_t self_in) {
usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/usb_hid/__init__.c b/shared-bindings/usb_hid/__init__.c
index 3ad5b06e0..e12ea8da4 100644
--- a/shared-bindings/usb_hid/__init__.c
+++ b/shared-bindings/usb_hid/__init__.c
@@ -31,27 +31,14 @@
#include "shared-bindings/usb_hid/__init__.h"
#include "shared-bindings/usb_hid/Device.h"
-//| :mod:`usb_hid` --- USB Human Interface Device
-//| ===========================================================
+//| """USB Human Interface Device
//|
-//| .. module:: usb_hid
-//| :synopsis: USB Human Interface Device
-//| :platform: SAMD21
-//|
-//| The `usb_hid` module allows you to output data as a HID device.
+//| The `usb_hid` module allows you to output data as a HID device."""
//|
-//| .. attribute:: usb_hid.devices
-//|
-//| Tuple of all active HID device interfaces.
-//|
-
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
+//| usb_hid.devices: Any = ...
+//| """Tuple of all active HID device interfaces."""
//|
-//| Device
STATIC const mp_rom_map_elem_t usb_hid_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid) },
{ MP_ROM_QSTR(MP_QSTR_devices), MP_ROM_PTR(&common_hal_usb_hid_devices) },
diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c
index e2df56e95..9d9310b47 100644
--- a/shared-bindings/usb_midi/PortIn.c
+++ b/shared-bindings/usb_midi/PortIn.c
@@ -35,39 +35,36 @@
#include "py/stream.h"
#include "supervisor/shared/translate.h"
-
-//| .. currentmodule:: usb_midi
-//|
-//| :class:`PortIn` -- receives midi commands over USB
-//| ===================================================
-//|
-//| .. class:: PortIn()
+//| class PortIn:
+//| """Receives midi commands over USB"""
//|
-//| You cannot create an instance of `usb_midi.PortIn`.
+//| def __init__(self):
+//| """You cannot create an instance of `usb_midi.PortIn`.
//|
-//| PortIn objects are constructed for every corresponding entry in the USB
-//| descriptor and added to the ``usb_midi.ports`` tuple.
+//| PortIn objects are constructed for every corresponding entry in the USB
+//| descriptor and added to the ``usb_midi.ports`` tuple."""
+//| ...
//|
// These are standard stream methods. Code is in py/stream.c.
//
-//| .. method:: read(nbytes=None)
-//|
-//| Read characters. If ``nbytes`` is specified then read at most that many
-//| bytes. Otherwise, read everything that arrives until the connection
-//| times out. Providing the number of bytes expected is highly recommended
-//| because it will be faster.
-//|
-//| :return: Data read
-//| :rtype: bytes or None
+//| def read(self, nbytes: Any = None) -> Any:
+//| """Read characters. If ``nbytes`` is specified then read at most that many
+//| bytes. Otherwise, read everything that arrives until the connection
+//| times out. Providing the number of bytes expected is highly recommended
+//| because it will be faster.
//|
-//| .. method:: readinto(buf, nbytes=None)
+//| :return: Data read
+//| :rtype: bytes or None"""
+//| ...
//|
-//| Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
-//| that many bytes. Otherwise, read at most ``len(buf)`` bytes.
+//| def readinto(self, buf: Any, nbytes: Any = None) -> Any:
+//| """Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
+//| that many bytes. Otherwise, read at most ``len(buf)`` bytes.
//|
-//| :return: number of bytes read and stored into ``buf``
-//| :rtype: bytes or None
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: bytes or None"""
+//| ...
//|
// These three methods are used by the shared stream methods.
diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c
index e3eddfaf5..14ed0e767 100644
--- a/shared-bindings/usb_midi/PortOut.c
+++ b/shared-bindings/usb_midi/PortOut.c
@@ -35,28 +35,24 @@
#include "py/stream.h"
#include "supervisor/shared/translate.h"
-
-//| .. currentmodule:: usb_midi
-//|
-//| :class:`PortOut` -- sends midi messages to a computer over USB
-//| ==============================================================
+//| class PortOut:
+//| """Sends midi messages to a computer over USB"""
//|
-//| .. class:: PortOut()
+//| def __init__(self, ):
+//| """You cannot create an instance of `usb_midi.PortOut`.
//|
-//| You cannot create an instance of `usb_midi.PortOut`.
-//|
-//| PortOut objects are constructed for every corresponding entry in the USB
-//| descriptor and added to the ``usb_midi.ports`` tuple.
+//| PortOut objects are constructed for every corresponding entry in the USB
+//| descriptor and added to the ``usb_midi.ports`` tuple."""
//|
// These are standard stream methods. Code is in py/stream.c.
//
-//| .. method:: write(buf)
-//|
-//| Write the buffer of bytes to the bus.
+//| def write(self, buf: Any) -> Any:
+//| """Write the buffer of bytes to the bus.
//|
-//| :return: the number of bytes written
-//| :rtype: int or None
+//| :return: the number of bytes written
+//| :rtype: int or None"""
+//| ...
//|
STATIC mp_uint_t usb_midi_portout_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c
index f57d3631b..5570b601c 100644
--- a/shared-bindings/usb_midi/__init__.c
+++ b/shared-bindings/usb_midi/__init__.c
@@ -35,22 +35,7 @@
#include "py/runtime.h"
-//| :mod:`usb_midi` --- MIDI over USB
-//| =================================================
-//|
-//| .. module:: usb_midi
-//| :synopsis: MIDI over USB
-//|
-//| The `usb_midi` module contains classes to transmit and receive MIDI messages over USB
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| PortIn
-//| PortOut
-//|
+//| """Classes to transmit and receive MIDI messages over USB"""
//|
mp_map_elem_t usb_midi_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_midi) },
diff --git a/shared-bindings/ustack/__init__.c b/shared-bindings/ustack/__init__.c
index 08b772e41..e5fac6941 100644
--- a/shared-bindings/ustack/__init__.c
+++ b/shared-bindings/ustack/__init__.c
@@ -31,17 +31,16 @@
#include "shared-bindings/ustack/__init__.h"
-//| :mod:`ustack` --- Stack information and analysis
-//| ========================================================
-//|
-//| .. module:: ustack
-//| :synopsis: stack information functions
+
+
+
+//| """Stack information and analysis"""
//|
#if MICROPY_MAX_STACK_USAGE
-//| .. function:: max_stack_usage()
-//|
-//| Return the maximum excursion of the stack so far.
+//| def max_stack_usage() -> int:
+//| """Return the maximum excursion of the stack so far."""
+//| ...
//|
STATIC mp_obj_t max_stack_usage(void) {
return MP_OBJ_NEW_SMALL_INT(shared_module_ustack_max_stack_usage());
@@ -50,21 +49,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(max_stack_usage_obj, max_stack_usage);
#endif // MICROPY_MAX_STACK_USAGE
-//| .. function:: stack_size()
-//|
-//| Return the size of the entire stack.
-//| Same as in micropython.mem_info(), but returns a value instead
-//| of just printing it.
+//| def stack_size() -> int:
+//| """Return the size of the entire stack.
+//| Same as in micropython.mem_info(), but returns a value instead
+//| of just printing it."""
+//| ...
//|
STATIC mp_obj_t stack_size(void) {
return MP_OBJ_NEW_SMALL_INT(shared_module_ustack_stack_size());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(stack_size_obj, stack_size);
-//| .. function:: stack_usage()
-//|
-//| Return how much stack is currently in use.
-//| Same as micropython.stack_use(); duplicated here for convenience.
+//| def stack_usage() -> Any:
+//| """Return how much stack is currently in use.
+//| Same as micropython.stack_use(); duplicated here for convenience."""
+//| ...
//|
STATIC mp_obj_t stack_usage(void) {
return MP_OBJ_NEW_SMALL_INT(shared_module_ustack_stack_usage());
diff --git a/shared-bindings/vectorio/Circle.c b/shared-bindings/vectorio/Circle.c
new file mode 100644
index 000000000..65923fd96
--- /dev/null
+++ b/shared-bindings/vectorio/Circle.c
@@ -0,0 +1,74 @@
+
+#include "shared-bindings/vectorio/Circle.h"
+
+
+#include <stdint.h>
+
+#include "py/objproperty.h"
+#include "py/objtype.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+//| class Circle:
+//|
+//| def __init__(self, radius: int):
+//| """Circle is positioned on screen by its center point.
+//|
+//| :param radius: The radius of the circle in pixels"""
+//|
+static mp_obj_t vectorio_circle_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_radius };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_INT },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t radius = args[ARG_radius].u_int;
+ if (radius < 1) {
+ mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_radius);
+ }
+
+ vectorio_circle_t *self = m_new_obj(vectorio_circle_t);
+ self->base.type = &vectorio_circle_type;
+ common_hal_vectorio_circle_construct(self, radius);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+
+//| radius : int = ...
+//| """The radius of the circle in pixels."""
+//|
+STATIC mp_obj_t vectorio_circle_obj_get_radius(mp_obj_t self_in) {
+ vectorio_circle_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_int(common_hal_vectorio_circle_get_radius(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(vectorio_circle_get_radius_obj, vectorio_circle_obj_get_radius);
+
+STATIC mp_obj_t vectorio_circle_obj_set_radius(mp_obj_t self_in, mp_obj_t radius) {
+ vectorio_circle_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_vectorio_circle_set_radius(self, mp_obj_get_int(radius));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(vectorio_circle_set_radius_obj, vectorio_circle_obj_set_radius);
+
+const mp_obj_property_t vectorio_circle_radius_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&vectorio_circle_get_radius_obj,
+ (mp_obj_t)&vectorio_circle_set_radius_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+STATIC const mp_rom_map_elem_t vectorio_circle_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_radius), MP_ROM_PTR(&vectorio_circle_radius_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(vectorio_circle_locals_dict, vectorio_circle_locals_dict_table);
+
+const mp_obj_type_t vectorio_circle_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Circle,
+ .make_new = vectorio_circle_make_new,
+ .locals_dict = (mp_obj_dict_t*)&vectorio_circle_locals_dict,
+};
diff --git a/shared-bindings/vectorio/Circle.h b/shared-bindings/vectorio/Circle.h
new file mode 100644
index 000000000..e8fc048eb
--- /dev/null
+++ b/shared-bindings/vectorio/Circle.h
@@ -0,0 +1,22 @@
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_CIRCLE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_CIRCLE_H
+
+#include "shared-module/vectorio/__init__.h"
+#include "shared-module/vectorio/Circle.h"
+#include "shared-module/displayio/area.h"
+
+extern const mp_obj_type_t vectorio_circle_type;
+
+void common_hal_vectorio_circle_construct(vectorio_circle_t *self, uint16_t radius);
+
+void common_hal_vectorio_circle_set_on_dirty(vectorio_circle_t *self, vectorio_event_t notification);
+
+uint32_t common_hal_vectorio_circle_get_pixel(void *circle, int16_t x, int16_t y);
+
+void common_hal_vectorio_circle_get_area(void *circle, displayio_area_t *out_area);
+
+
+int16_t common_hal_vectorio_circle_get_radius(void *circle);
+void common_hal_vectorio_circle_set_radius(void *circle, int16_t radius);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_CIRCLE_H
diff --git a/shared-bindings/vectorio/Polygon.c b/shared-bindings/vectorio/Polygon.c
new file mode 100644
index 000000000..3443d9e42
--- /dev/null
+++ b/shared-bindings/vectorio/Polygon.c
@@ -0,0 +1,94 @@
+
+#include "shared-module/vectorio/__init__.h"
+#include "shared-bindings/vectorio/Polygon.h"
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/objproperty.h"
+#include "py/objtype.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+
+#define VECTORIO_POLYGON_DEBUG(...) (void)0
+// #define VECTORIO_POLYGON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)
+
+
+//| from typing import List, Tuple
+//|
+//| class Polygon:
+//| def __init__(self, points: List[ Tuple[ x, y ], ... ] ):
+//| """Represents a closed shape by ordered vertices
+//|
+//| :param points: Vertices for the polygon"""
+//|
+static mp_obj_t vectorio_polygon_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_points_list };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_points, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ };
+ 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);
+
+ if (!MP_OBJ_IS_TYPE(args[ARG_points_list].u_obj, &mp_type_list)) {
+ mp_raise_TypeError_varg(translate("%q list must be a list"), MP_QSTR_point);
+ }
+
+ vectorio_polygon_t *self = m_new_obj(vectorio_polygon_t);
+ self->base.type = &vectorio_polygon_type;
+
+ common_hal_vectorio_polygon_construct(self, args[ARG_points_list].u_obj);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+
+//| points: List[ Tuple[ x, y ], ... ] = ...
+//| """Set a new look and shape for this polygon"""
+//|
+STATIC mp_obj_t vectorio_polygon_obj_get_points(mp_obj_t self_in) {
+ vectorio_polygon_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+
+ size_t len = 0;
+ mp_obj_t *items;
+ mp_obj_list_get(common_hal_vectorio_polygon_get_points(self), &len, &items);
+
+ for (size_t i = 0; i < len; i += 2) {
+ mp_obj_t tuple[] = { items[i], items[i+1] };
+ mp_obj_list_append(
+ list,
+ mp_obj_new_tuple(2, tuple)
+ );
+ }
+ return list;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(vectorio_polygon_get_points_obj, vectorio_polygon_obj_get_points);
+
+STATIC mp_obj_t vectorio_polygon_obj_set_points(mp_obj_t self_in, mp_obj_t points) {
+ vectorio_polygon_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_vectorio_polygon_set_points(self, points);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(vectorio_polygon_set_points_obj, vectorio_polygon_obj_set_points);
+
+const mp_obj_property_t vectorio_polygon_points_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&vectorio_polygon_get_points_obj,
+ (mp_obj_t)&vectorio_polygon_set_points_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t vectorio_polygon_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_points), MP_ROM_PTR(&vectorio_polygon_points_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(vectorio_polygon_locals_dict, vectorio_polygon_locals_dict_table);
+
+const mp_obj_type_t vectorio_polygon_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Polygon,
+ .make_new = vectorio_polygon_make_new,
+ .locals_dict = (mp_obj_dict_t*)&vectorio_polygon_locals_dict,
+};
diff --git a/shared-bindings/vectorio/Polygon.h b/shared-bindings/vectorio/Polygon.h
new file mode 100644
index 000000000..5594fbec4
--- /dev/null
+++ b/shared-bindings/vectorio/Polygon.h
@@ -0,0 +1,24 @@
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_POLYGON_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_POLYGON_H
+
+#include "shared-module/vectorio/Polygon.h"
+#include "shared-module/displayio/area.h"
+#include "shared-module/vectorio/__init__.h"
+
+extern const mp_obj_type_t vectorio_polygon_type;
+
+void common_hal_vectorio_polygon_construct(vectorio_polygon_t *self, mp_obj_t points_list);
+void common_hal_vectorio_polygon_set_on_dirty(vectorio_polygon_t *self, vectorio_event_t notification);
+
+
+uint32_t common_hal_vectorio_polygon_get_pixel(void *polygon, int16_t x, int16_t y);
+
+void common_hal_vectorio_polygon_get_area(void *polygon, displayio_area_t *out_area);
+
+
+
+mp_obj_t common_hal_vectorio_polygon_get_points(vectorio_polygon_t *self);
+void common_hal_vectorio_polygon_set_points(vectorio_polygon_t *self, mp_obj_t points_list);
+
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_POLYGON_H
diff --git a/shared-bindings/vectorio/Rectangle.c b/shared-bindings/vectorio/Rectangle.c
new file mode 100644
index 000000000..f04a25c35
--- /dev/null
+++ b/shared-bindings/vectorio/Rectangle.c
@@ -0,0 +1,52 @@
+
+#include "shared-bindings/vectorio/Rectangle.h"
+
+#include <stdint.h>
+
+#include "py/objtype.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+//| class Rectangle:
+//| def __init__(self, width: int, height: int):
+//| """Represents a rectangle by defining its bounds
+//|
+//| :param width: The number of pixels wide
+//| :param height: The number of pixels high"""
+//|
+static mp_obj_t vectorio_rectangle_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_width, ARG_height };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t width = args[ARG_width].u_int;
+ if (width < 1) {
+ mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_width);
+ }
+ mp_int_t height = args[ARG_height].u_int;
+ if (height < 1) {
+ mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_height);
+ }
+
+ vectorio_rectangle_t *self = m_new_obj(vectorio_rectangle_t);
+ self->base.type = &vectorio_rectangle_type;
+ common_hal_vectorio_rectangle_construct(self, width, height);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+
+STATIC const mp_rom_map_elem_t vectorio_rectangle_locals_dict_table[] = {
+};
+STATIC MP_DEFINE_CONST_DICT(vectorio_rectangle_locals_dict, vectorio_rectangle_locals_dict_table);
+
+const mp_obj_type_t vectorio_rectangle_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Rectangle,
+ .make_new = vectorio_rectangle_make_new,
+ .locals_dict = (mp_obj_dict_t*)&vectorio_rectangle_locals_dict,
+};
diff --git a/shared-bindings/vectorio/Rectangle.h b/shared-bindings/vectorio/Rectangle.h
new file mode 100644
index 000000000..bb461ed9d
--- /dev/null
+++ b/shared-bindings/vectorio/Rectangle.h
@@ -0,0 +1,15 @@
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_RECTANGLE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_RECTANGLE_H
+
+#include "shared-module/vectorio/Rectangle.h"
+#include "shared-module/displayio/area.h"
+
+extern const mp_obj_type_t vectorio_rectangle_type;
+
+void common_hal_vectorio_rectangle_construct(vectorio_rectangle_t *self, uint32_t width, uint32_t height);
+
+uint32_t common_hal_vectorio_rectangle_get_pixel(void *rectangle, int16_t x, int16_t y);
+
+void common_hal_vectorio_rectangle_get_area(void *rectangle, displayio_area_t *out_area);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_RECTANGLE_H
diff --git a/shared-bindings/vectorio/VectorShape.c b/shared-bindings/vectorio/VectorShape.c
new file mode 100644
index 000000000..c512bcd54
--- /dev/null
+++ b/shared-bindings/vectorio/VectorShape.c
@@ -0,0 +1,190 @@
+
+#include "shared-module/vectorio/__init__.h"
+#include "shared-bindings/vectorio/VectorShape.h"
+#include "shared-bindings/vectorio/Circle.h"
+#include "shared-bindings/vectorio/Polygon.h"
+#include "shared-bindings/vectorio/Rectangle.h"
+
+#include "shared-bindings/displayio/ColorConverter.h"
+#include "shared-bindings/displayio/Palette.h"
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/objtype.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+
+//| class VectorShape:
+//| def __init__(self, shape: vectorio.Polygon, pixel_shader: displayio.Palette, x: int=0, y: int=0):
+//| """Binds a vector shape to a location and pixel color
+//|
+//| :param shape: The shape to draw.
+//| :param pixel_shader: The pixel shader that produces colors from values
+//| :param x: Initial x position of the center axis of the shape within the parent.
+//| :param y: Initial y position of the center axis of the shape within the parent."""
+//| ...
+//|
+STATIC mp_obj_t vectorio_vector_shape_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_shape, ARG_pixel_shader, ARG_x, ARG_y };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_shape, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
+ { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
+ { MP_QSTR_x, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_y, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t pixel_shader = args[ARG_pixel_shader].u_obj;
+ if (!MP_OBJ_IS_TYPE(pixel_shader, &displayio_colorconverter_type) &&
+ !MP_OBJ_IS_TYPE(pixel_shader, &displayio_palette_type)) {
+ mp_raise_TypeError_varg(translate("unsupported %q type"), MP_QSTR_pixel_shader);
+ }
+
+ int16_t x = args[ARG_x].u_int;
+ int16_t y = args[ARG_y].u_int;
+
+ mp_obj_t shape = args[ARG_shape].u_obj;
+ vectorio_ishape_t ishape;
+ // Wire up shape functions
+ if (MP_OBJ_IS_TYPE(shape, &vectorio_polygon_type)) {
+ ishape.shape = shape;
+ ishape.get_area = &common_hal_vectorio_polygon_get_area;
+ ishape.get_pixel = &common_hal_vectorio_polygon_get_pixel;
+ } else if (MP_OBJ_IS_TYPE(shape, &vectorio_rectangle_type)) {
+ ishape.shape = shape;
+ ishape.get_area = &common_hal_vectorio_rectangle_get_area;
+ ishape.get_pixel = &common_hal_vectorio_rectangle_get_pixel;
+ } else if (MP_OBJ_IS_TYPE(shape, &vectorio_circle_type)) {
+ ishape.shape = shape;
+ ishape.get_area = &common_hal_vectorio_circle_get_area;
+ ishape.get_pixel = &common_hal_vectorio_circle_get_pixel;
+ } else {
+ mp_raise_TypeError_varg(translate("unsupported %q type"), MP_QSTR_shape);
+ }
+
+ vectorio_vector_shape_t *self = m_new_obj(vectorio_vector_shape_t);
+ self->base.type = &vectorio_vector_shape_type;
+ common_hal_vectorio_vector_shape_construct(self,
+ ishape, pixel_shader, x, y
+ );
+
+ // Wire up event callbacks
+ vectorio_event_t on_dirty = {
+ .obj = self,
+ .event = &common_hal_vectorio_vector_shape_set_dirty
+ };
+
+ if (MP_OBJ_IS_TYPE(shape, &vectorio_polygon_type)) {
+ common_hal_vectorio_polygon_set_on_dirty(self->ishape.shape, on_dirty);
+ } else if (MP_OBJ_IS_TYPE(shape, &vectorio_rectangle_type)) {
+ } else if (MP_OBJ_IS_TYPE(shape, &vectorio_circle_type)) {
+ common_hal_vectorio_circle_set_on_dirty(self->ishape.shape, on_dirty);
+ } else {
+ mp_raise_TypeError_varg(translate("unsupported %q type"), MP_QSTR_shape);
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+
+//| x: int = ...
+//| """X position of the center point of the shape in the parent."""
+//|
+STATIC mp_obj_t vectorio_vector_shape_obj_get_x(mp_obj_t self_in) {
+ vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(self_in);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_vectorio_vector_shape_get_x(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(vectorio_vector_shape_get_x_obj, vectorio_vector_shape_obj_get_x);
+
+STATIC mp_obj_t vectorio_vector_shape_obj_set_x(mp_obj_t self_in, mp_obj_t x_obj) {
+ vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_int_t x = mp_obj_get_int(x_obj);
+ common_hal_vectorio_vector_shape_set_x(self, x);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(vectorio_vector_shape_set_x_obj, vectorio_vector_shape_obj_set_x);
+
+const mp_obj_property_t vectorio_vector_shape_x_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&vectorio_vector_shape_get_x_obj,
+ (mp_obj_t)&vectorio_vector_shape_set_x_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+//| y: int = ...
+//| """Y position of the center point of the shape in the parent."""
+//|
+STATIC mp_obj_t vectorio_vector_shape_obj_get_y(mp_obj_t self_in) {
+ vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(self_in);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_vectorio_vector_shape_get_y(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(vectorio_vector_shape_get_y_obj, vectorio_vector_shape_obj_get_y);
+
+STATIC mp_obj_t vectorio_vector_shape_obj_set_y(mp_obj_t self_in, mp_obj_t y_obj) {
+ vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_int_t y = mp_obj_get_int(y_obj);
+ common_hal_vectorio_vector_shape_set_y(self, y);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(vectorio_vector_shape_set_y_obj, vectorio_vector_shape_obj_set_y);
+
+const mp_obj_property_t vectorio_vector_shape_y_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&vectorio_vector_shape_get_y_obj,
+ (mp_obj_t)&vectorio_vector_shape_set_y_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+//| pixel_shader: displayio.Palette = ...
+//| """The pixel shader of the shape."""
+//|
+STATIC mp_obj_t vectorio_vector_shape_obj_get_pixel_shader(mp_obj_t self_in) {
+ vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(self_in);
+ return common_hal_vectorio_vector_shape_get_pixel_shader(self);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(vectorio_vector_shape_get_pixel_shader_obj, vectorio_vector_shape_obj_get_pixel_shader);
+
+STATIC mp_obj_t vectorio_vector_shape_obj_set_pixel_shader(mp_obj_t self_in, mp_obj_t pixel_shader) {
+ vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(self_in);
+ if (!MP_OBJ_IS_TYPE(pixel_shader, &displayio_palette_type) && !MP_OBJ_IS_TYPE(pixel_shader, &displayio_colorconverter_type)) {
+ mp_raise_TypeError(translate("pixel_shader must be displayio.Palette or displayio.ColorConverter"));
+ }
+
+ common_hal_vectorio_vector_shape_set_pixel_shader(self, pixel_shader);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(vectorio_vector_shape_set_pixel_shader_obj, vectorio_vector_shape_obj_set_pixel_shader);
+
+const mp_obj_property_t vectorio_vector_shape_pixel_shader_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&vectorio_vector_shape_get_pixel_shader_obj,
+ (mp_obj_t)&vectorio_vector_shape_set_pixel_shader_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+STATIC const mp_rom_map_elem_t vectorio_vector_shape_locals_dict_table[] = {
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },
+ { MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&vectorio_vector_shape_y_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pixel_shader), MP_ROM_PTR(&vectorio_vector_shape_pixel_shader_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(vectorio_vector_shape_locals_dict, vectorio_vector_shape_locals_dict_table);
+
+const mp_obj_type_t vectorio_vector_shape_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_VectorShape,
+ .make_new = vectorio_vector_shape_make_new,
+ .locals_dict = (mp_obj_dict_t*)&vectorio_vector_shape_locals_dict,
+};
diff --git a/shared-bindings/vectorio/VectorShape.h b/shared-bindings/vectorio/VectorShape.h
new file mode 100644
index 000000000..d098504e9
--- /dev/null
+++ b/shared-bindings/vectorio/VectorShape.h
@@ -0,0 +1,27 @@
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_SHAPE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_SHAPE_H
+
+#include "shared-module/vectorio/VectorShape.h"
+#include "shared-module/displayio/area.h"
+
+extern const mp_obj_type_t vectorio_vector_shape_type;
+
+void common_hal_vectorio_vector_shape_construct(vectorio_vector_shape_t *self,
+ vectorio_ishape_t ishape,
+ mp_obj_t pixel_shader, uint16_t x, uint16_t y);
+
+void common_hal_vectorio_vector_shape_set_dirty(void *self);
+
+mp_int_t common_hal_vectorio_vector_shape_get_x(vectorio_vector_shape_t *self);
+void common_hal_vectorio_vector_shape_set_x(vectorio_vector_shape_t *self, mp_int_t x);
+
+mp_int_t common_hal_vectorio_vector_shape_get_y(vectorio_vector_shape_t *self);
+void common_hal_vectorio_vector_shape_set_y(vectorio_vector_shape_t *self, mp_int_t y);
+
+mp_obj_t common_hal_vectorio_vector_shape_get_pixel_shader(vectorio_vector_shape_t *self);
+void common_hal_vectorio_vector_shape_set_pixel_shader(vectorio_vector_shape_t *self, mp_obj_t pixel_shader);
+
+
+void vectorio_vector_shape_update_transform(vectorio_vector_shape_t *self, displayio_buffer_transform_t *group_transform);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_VECTORIO_SHAPE_H
diff --git a/shared-bindings/vectorio/__init__.c b/shared-bindings/vectorio/__init__.c
new file mode 100644
index 000000000..c74783426
--- /dev/null
+++ b/shared-bindings/vectorio/__init__.c
@@ -0,0 +1,27 @@
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/vectorio/Circle.h"
+#include "shared-bindings/vectorio/Polygon.h"
+#include "shared-bindings/vectorio/Rectangle.h"
+#include "shared-bindings/vectorio/VectorShape.h"
+
+//| """Lightweight 2d shapes for displays"""
+//|
+
+STATIC const mp_rom_map_elem_t vectorio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_vectorio) },
+ { MP_ROM_QSTR(MP_QSTR_Circle), MP_ROM_PTR(&vectorio_circle_type) },
+ { MP_ROM_QSTR(MP_QSTR_Polygon), MP_ROM_PTR(&vectorio_polygon_type) },
+ { MP_ROM_QSTR(MP_QSTR_Rectangle), MP_ROM_PTR(&vectorio_rectangle_type) },
+ { MP_ROM_QSTR(MP_QSTR_VectorShape), MP_ROM_PTR(&vectorio_vector_shape_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(vectorio_module_globals, vectorio_module_globals_table);
+
+const mp_obj_module_t vectorio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&vectorio_module_globals,
+};
diff --git a/shared-bindings/watchdog/WatchDogMode.c b/shared-bindings/watchdog/WatchDogMode.c
new file mode 100644
index 000000000..369454c11
--- /dev/null
+++ b/shared-bindings/watchdog/WatchDogMode.c
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Sean Cross 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/watchdog/WatchDogMode.h"
+
+//| class WatchDogMode:
+//| """run state of the watchdog timer"""
+//|
+//| def __init__(self, ):
+//| """Enum-like class to define the run mode of the watchdog timer."""
+//|
+//| RAISE: Any = ...
+//| """Raise an exception when the WatchDogTimer expires.
+//|
+//| :type watchdog.WatchDogMode:"""
+//|
+//| RESET: Any = ...
+//| """Reset the system if the WatchDogTimer expires.
+//|
+//| :type watchdog.WatchDogMode:"""
+//|
+const mp_obj_type_t watchdog_watchdogmode_type;
+
+const watchdog_watchdogmode_obj_t watchdog_watchdogmode_raise_obj = {
+ { &watchdog_watchdogmode_type },
+};
+
+const watchdog_watchdogmode_obj_t watchdog_watchdogmode_reset_obj = {
+ { &watchdog_watchdogmode_type },
+};
+
+watchdog_watchdogmode_t watchdog_watchdogmode_obj_to_type(mp_obj_t obj) {
+ if (obj == MP_ROM_PTR(&watchdog_watchdogmode_raise_obj)) {
+ return WATCHDOGMODE_RAISE;
+ } else if (obj == MP_ROM_PTR(&watchdog_watchdogmode_reset_obj)) {
+ return WATCHDOGMODE_RESET;
+ }
+ return WATCHDOGMODE_NONE;
+}
+
+mp_obj_t watchdog_watchdogmode_type_to_obj(watchdog_watchdogmode_t mode) {
+ switch (mode) {
+ case WATCHDOGMODE_RAISE:
+ return (mp_obj_t)MP_ROM_PTR(&watchdog_watchdogmode_raise_obj);
+ case WATCHDOGMODE_RESET:
+ return (mp_obj_t)MP_ROM_PTR(&watchdog_watchdogmode_reset_obj);
+ case WATCHDOGMODE_NONE:
+ default:
+ return (mp_obj_t)MP_ROM_PTR(&mp_const_none_obj);
+ }
+}
+
+STATIC const mp_rom_map_elem_t watchdog_watchdogmode_locals_dict_table[] = {
+ {MP_ROM_QSTR(MP_QSTR_RAISE), MP_ROM_PTR(&watchdog_watchdogmode_raise_obj)},
+ {MP_ROM_QSTR(MP_QSTR_RESET), MP_ROM_PTR(&watchdog_watchdogmode_reset_obj)},
+};
+STATIC MP_DEFINE_CONST_DICT(watchdog_watchdogmode_locals_dict, watchdog_watchdogmode_locals_dict_table);
+
+STATIC void watchdog_watchdogmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ qstr runmode = MP_QSTR_None;
+ if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&watchdog_watchdogmode_raise_obj)) {
+ runmode = MP_QSTR_RAISE;
+ }
+ else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&watchdog_watchdogmode_reset_obj)) {
+ runmode = MP_QSTR_RESET;
+ }
+ mp_printf(print, "%q.%q.%q", MP_QSTR_watchdog, MP_QSTR_WatchDogMode,
+ runmode);
+}
+
+const mp_obj_type_t watchdog_watchdogmode_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_WatchDogMode,
+ .print = watchdog_watchdogmode_print,
+ .locals_dict = (mp_obj_t)&watchdog_watchdogmode_locals_dict,
+};
diff --git a/shared-bindings/watchdog/WatchDogMode.h b/shared-bindings/watchdog/WatchDogMode.h
new file mode 100644
index 000000000..68022671f
--- /dev/null
+++ b/shared-bindings/watchdog/WatchDogMode.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Sean Cross 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_WATCHDOG_WATCHDOGMODE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGMODE_H
+
+#include "py/obj.h"
+
+typedef enum {
+ WATCHDOGMODE_NONE,
+ WATCHDOGMODE_RAISE,
+ WATCHDOGMODE_RESET,
+} watchdog_watchdogmode_t;
+
+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);
+
+typedef struct {
+ mp_obj_base_t base;
+} watchdog_watchdogmode_obj_t;
+extern const watchdog_watchdogmode_obj_t watchdog_watchdogmode_raise_obj;
+extern const watchdog_watchdogmode_obj_t watchdog_watchdogmode_reset_obj;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGMODE_H
diff --git a/shared-bindings/watchdog/WatchDogTimer.c b/shared-bindings/watchdog/WatchDogTimer.c
new file mode 100644
index 000000000..52bda4c77
--- /dev/null
+++ b/shared-bindings/watchdog/WatchDogTimer.c
@@ -0,0 +1,186 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 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 <math.h>
+#include <string.h>
+
+#include "py/obj.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+
+#include "common-hal/watchdog/WatchDogTimer.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/watchdog/__init__.h"
+#include "shared-bindings/watchdog/WatchDogTimer.h"
+
+#include "supervisor/port.h"
+
+//| class WatchDogTimer:
+//| """Timer that is used to detect code lock ups and automatically reset the microcontroller
+//| when one is detected.
+//|
+//| A lock up is detected when the watchdog hasn't been fed after a given duration. So, make
+//| sure to call `feed` within the timeout.
+//| """
+//|
+
+//| def __init__(self, ):
+//| """Not currently dynamically supported. Access the sole instance through `microcontroller.watchdog`."""
+//| ...
+//|
+
+//| def feed(self):
+//| """Feed the watchdog timer. This must be called regularly, otherwise
+//| the timer will expire."""
+//| ...
+//|
+STATIC mp_obj_t watchdog_watchdogtimer_feed(mp_obj_t self_in) {
+ watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ watchdog_watchdogmode_t current_mode = common_hal_watchdog_get_mode(self);
+
+ if (current_mode == WATCHDOGMODE_NONE) {
+ mp_raise_ValueError(translate("WatchDogTimer is not currently running"));
+ }
+ common_hal_watchdog_feed(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_feed_obj, watchdog_watchdogtimer_feed);
+
+//| def deinit(self):
+//| """Stop the watchdog timer. This may raise an error if the watchdog
+//| timer cannot be disabled on this platform."""
+//| ...
+//|
+STATIC mp_obj_t watchdog_watchdogtimer_deinit(mp_obj_t self_in) {
+ watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ watchdog_watchdogmode_t current_mode = common_hal_watchdog_get_mode(self);
+
+ if (current_mode == WATCHDOGMODE_RESET) {
+ mp_raise_NotImplementedError(translate("WatchDogTimer cannot be deinitialized once mode is set to RESET"));
+ }
+
+ common_hal_watchdog_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_deinit_obj, watchdog_watchdogtimer_deinit);
+
+//| timeout: float = ...
+//| """The maximum number of seconds that can elapse between calls
+//| to feed()"""
+//|
+STATIC mp_obj_t watchdog_watchdogtimer_obj_get_timeout(mp_obj_t self_in) {
+ watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_float(common_hal_watchdog_get_timeout(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_get_timeout_obj, watchdog_watchdogtimer_obj_get_timeout);
+
+STATIC mp_obj_t watchdog_watchdogtimer_obj_set_timeout(mp_obj_t self_in, mp_obj_t timeout_obj) {
+ watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_float_t timeout = mp_obj_get_float(timeout_obj);
+
+ if (timeout <= 0) {
+ mp_raise_ValueError(translate("watchdog timeout must be greater than 0"));
+ }
+
+ common_hal_watchdog_set_timeout(self, timeout);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(watchdog_watchdogtimer_set_timeout_obj, watchdog_watchdogtimer_obj_set_timeout);
+
+const mp_obj_property_t watchdog_watchdogtimer_timeout_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&watchdog_watchdogtimer_get_timeout_obj,
+ (mp_obj_t)&watchdog_watchdogtimer_set_timeout_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| mode: watchdog.WatchDogMode = ...
+//| """The current operating mode of the WatchDogTimer `watchdog.WatchDogMode`.
+//|
+//| Setting a WatchDogMode activates the WatchDog::
+//|
+//| import microcontroller
+//| import watchdog
+//|
+//| w = microcontroller.watchdog
+//| w.timeout = 5
+//| w.mode = watchdog.WatchDogMode.RAISE
+//|
+//|
+//| Once set, the WatchDogTimer will perform the specified action if the timer expires."""
+//|
+STATIC mp_obj_t watchdog_watchdogtimer_obj_get_mode(mp_obj_t self_in) {
+ watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return watchdog_watchdogmode_type_to_obj(common_hal_watchdog_get_mode(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_get_mode_obj, watchdog_watchdogtimer_obj_get_mode);
+
+STATIC mp_obj_t watchdog_watchdogtimer_obj_set_mode(mp_obj_t self_in, mp_obj_t mode_obj) {
+ watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ watchdog_watchdogmode_t current_mode = common_hal_watchdog_get_mode(self);
+ watchdog_watchdogmode_t new_mode = watchdog_watchdogmode_obj_to_type(mode_obj);
+ mp_float_t current_timeout = common_hal_watchdog_get_timeout(self);
+
+ // When setting the mode, the timeout value must be greater than zero
+ if (new_mode == WATCHDOGMODE_RESET || new_mode == WATCHDOGMODE_RAISE) {
+ if (current_timeout <= 0) {
+ mp_raise_ValueError(translate("WatchDogTimer.timeout must be greater than 0"));
+ }
+ }
+
+ // Don't allow changing the mode once the watchdog timer has been started
+ if (current_mode == WATCHDOGMODE_RESET && new_mode != WATCHDOGMODE_RESET) {
+ mp_raise_TypeError(translate("WatchDogTimer.mode cannot be changed once set to WatchDogMode.RESET"));
+ }
+
+ common_hal_watchdog_set_mode(self, new_mode);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(watchdog_watchdogtimer_set_mode_obj, watchdog_watchdogtimer_obj_set_mode);
+
+const mp_obj_property_t watchdog_watchdogtimer_mode_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&watchdog_watchdogtimer_get_mode_obj,
+ (mp_obj_t)&watchdog_watchdogtimer_set_mode_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t watchdog_watchdogtimer_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&watchdog_watchdogtimer_feed_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&watchdog_watchdogtimer_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&watchdog_watchdogtimer_timeout_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&watchdog_watchdogtimer_mode_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(watchdog_watchdogtimer_locals_dict, watchdog_watchdogtimer_locals_dict_table);
+
+const mp_obj_type_t watchdog_watchdogtimer_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_WatchDogTimer,
+ // .make_new = watchdog_watchdogtimer_make_new,
+ .locals_dict = (mp_obj_dict_t*)&watchdog_watchdogtimer_locals_dict,
+};
diff --git a/shared-bindings/watchdog/WatchDogTimer.h b/shared-bindings/watchdog/WatchDogTimer.h
new file mode 100644
index 000000000..48044748a
--- /dev/null
+++ b/shared-bindings/watchdog/WatchDogTimer.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Noralf Trønnes
+ *
+ * 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_WATCHDOG_WATCHDOGTIMER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGTIMER_H
+
+#include <py/obj.h>
+#include "shared-bindings/watchdog/WatchDogMode.h"
+
+typedef struct _watchdog_watchdogtimer_obj_t watchdog_watchdogtimer_obj_t;
+
+extern void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self);
+
+extern void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self, watchdog_watchdogmode_t);
+extern watchdog_watchdogmode_t common_hal_watchdog_get_mode(watchdog_watchdogtimer_obj_t *self);
+
+extern void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t timeout);
+extern mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self);
+
+extern void common_hal_watchdog_enable(watchdog_watchdogtimer_obj_t *self);
+extern void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self);
+
+extern const mp_obj_type_t watchdog_watchdogtimer_type;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGTIMER_H
diff --git a/shared-bindings/watchdog/__init__.c b/shared-bindings/watchdog/__init__.c
new file mode 100644
index 000000000..76e631729
--- /dev/null
+++ b/shared-bindings/watchdog/__init__.c
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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/runtime.h"
+#include "shared-bindings/watchdog/__init__.h"
+#include "shared-bindings/watchdog/WatchDogMode.h"
+
+//| """Watchdog Timer
+//|
+//| The `watchdog` module provides support for a Watchdog Timer. This timer will reset the device
+//| if it hasn't been fed after a specified amount of time. This is useful to ensure the board
+//| has not crashed or locked up. Note that on some platforms the watchdog timer cannot be disabled
+//| once it has been enabled.
+//|
+//| The `WatchDogTimer` is used to restart the system when the application crashes and ends
+//| up into a non recoverable state. Once started it cannot be stopped or
+//| reconfigured in any way. After enabling, the application must "feed" the
+//| watchdog periodically to prevent it from expiring and resetting the system.
+//|
+//| Example usage::
+//|
+//| from microcontroller import watchdog as w
+//| from watchdog import WatchDogMode
+//| w.timeout=2.5 # Set a timeout of 2.5 seconds
+//| w.mode = WatchDogMode.RAISE
+//| w.feed()"""
+//|
+
+const mp_obj_type_t mp_type_WatchDogTimeout = {
+ { &mp_type_type },
+ .name = MP_QSTR_WatchDogTimeout,
+ .make_new = mp_obj_exception_make_new,
+ .attr = mp_obj_exception_attr,
+ .parent = &mp_type_Exception,
+};
+
+mp_obj_exception_t mp_watchdog_timeout_exception = {
+ .base.type = &mp_type_WatchDogTimeout,
+ .traceback_alloc = 0,
+ .traceback_len = 0,
+ .traceback_data = NULL,
+ .args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj,
+};
+
+STATIC const mp_rom_map_elem_t watchdog_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_watchdog) },
+ { MP_ROM_QSTR(MP_QSTR_WatchDogMode), MP_ROM_PTR(&watchdog_watchdogmode_type) },
+ { MP_ROM_QSTR(MP_QSTR_WatchDogTimeout), MP_ROM_PTR(&mp_type_WatchDogTimeout) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(watchdog_module_globals, watchdog_module_globals_table);
+
+const mp_obj_module_t watchdog_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&watchdog_module_globals,
+};
diff --git a/shared-bindings/help.c b/shared-bindings/watchdog/__init__.h
index 4e7c3a78b..b5a0ad71d 100644
--- a/shared-bindings/help.c
+++ b/shared-bindings/watchdog/__init__.h
@@ -24,11 +24,11 @@
* THE SOFTWARE.
*/
-//| :func:`help` - Built-in method to provide helpful information
-//| ==============================================================
-//|
-//| .. function:: help(object=None)
-//|
-//| Prints a help method about the given object. When ``object`` is none,
-//| prints general port information.
-//|
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H
+
+extern const mp_obj_module_t watchdog_module;
+extern mp_obj_exception_t mp_watchdog_timeout_exception;
+extern const mp_obj_type_t mp_type_WatchDogTimeout;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H
diff --git a/shared-bindings/wiznet/__init__.c b/shared-bindings/wiznet/__init__.c
index e230deecc..0d3f1e4cd 100644
--- a/shared-bindings/wiznet/__init__.c
+++ b/shared-bindings/wiznet/__init__.c
@@ -35,21 +35,7 @@
#include "shared-module/network/__init__.h"
-//| :mod:`wiznet` --- Support for WizNet hardware
-//| =============================================
-//|
-//| .. module:: wiznet
-//| :synopsis: Support for WizNet hardware
-//| :platform: SAMD
-//|
-//| Support for WizNet hardware, including the WizNet 5500 Ethernet adaptor.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| wiznet5k
+//| """Support for WizNet hardware, including the WizNet 5500 Ethernet adaptor."""
//|
extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k;
@@ -66,4 +52,3 @@ const mp_obj_module_t wiznet_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_wiznet_globals,
};
-
diff --git a/shared-bindings/wiznet/wiznet5k.c b/shared-bindings/wiznet/wiznet5k.c
index ac89cc691..2f49dffea 100644
--- a/shared-bindings/wiznet/wiznet5k.c
+++ b/shared-bindings/wiznet/wiznet5k.c
@@ -46,25 +46,23 @@
#include "shared-module/network/__init__.h"
#include "shared-module/wiznet/wiznet5k.h"
-//| .. currentmodule:: wiznet
+//| class WIZNET5K:
+//| """Wrapper for Wiznet 5500 Ethernet interface"""
//|
-//| :class:`WIZNET5K` -- wrapper for Wiznet 5500 Ethernet interface
-//| ===============================================================
+//| def __init__(self, spi: busio.SPI, cs: microcontroller.Pin, rst: microcontroller.Pin, dhcp: bool = True):
+//| """Create a new WIZNET5500 interface using the specified pins
//|
-//| .. class:: WIZNET5K(spi, cs, rst, dhcp=True)
+//| :param ~busio.SPI spi: spi bus to use
+//| :param ~microcontroller.Pin cs: pin to use for Chip Select
+//| :param ~microcontroller.Pin rst: pin to use for Reset (optional)
+//| :param bool dhcp: boolean flag, whether to start DHCP automatically (optional, keyword only, default True)
//|
-//| Create a new WIZNET5500 interface using the specified pins
-//|
-//| :param ~busio.SPI spi: spi bus to use
-//| :param ~microcontroller.Pin cs: pin to use for Chip Select
-//| :param ~microcontroller.Pin rst: pin to use for Reset (optional)
-//| :param bool dhcp: boolean flag, whether to start DHCP automatically (optional, keyword only, default True)
-//|
-//| * The reset pin is optional: if supplied it is used to reset the
-//| wiznet board before initialization.
-//| * The SPI bus will be initialized appropriately by this library.
-//| * At present, the WIZNET5K object is a singleton, so only one WizNet
-//| interface is supported at a time.
+//| * The reset pin is optional: if supplied it is used to reset the
+//| wiznet board before initialization.
+//| * The SPI bus will be initialized appropriately by this library.
+//| * At present, the WIZNET5K object is a singleton, so only one WizNet
+//| interface is supported at a time."""
+//| ...
//|
STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -78,17 +76,16 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, cons
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);
// TODO check type of ARG_spi?
- assert_pin(args[ARG_cs].u_obj, false);
- assert_pin(args[ARG_rst].u_obj, true); // may be NULL
+ const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj);
+ const mcu_pin_obj_t *rst = validate_obj_is_free_pin_or_none(args[ARG_rst].u_obj);
- mp_obj_t ret = wiznet5k_create(args[ARG_spi].u_obj, args[ARG_cs].u_obj, args[ARG_rst].u_obj);
+ mp_obj_t ret = wiznet5k_create(args[ARG_spi].u_obj, cs, rst);
if (args[ARG_dhcp].u_bool) wiznet5k_start_dhcp();
return ret;
}
-//| .. attribute:: connected
-//|
-//| (boolean, readonly) is this device physically connected?
+//| connected: Any = ...
+//| """(boolean, readonly) is this device physically connected?"""
//|
STATIC mp_obj_t wiznet5k_connected_get_value(mp_obj_t self_in) {
@@ -104,11 +101,10 @@ const mp_obj_property_t wiznet5k_connected_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. attribute:: dhcp
+//| dhcp: Any = ...
+//| """(boolean, readwrite) is DHCP active on this device?
//|
-//| (boolean, readwrite) is DHCP active on this device?
-//|
-//| * set to True to activate DHCP, False to turn it off
+//| * set to True to activate DHCP, False to turn it off"""
//|
STATIC mp_obj_t wiznet5k_dhcp_get_value(mp_obj_t self_in) {
@@ -138,13 +134,13 @@ const mp_obj_property_t wiznet5k_dhcp_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: ifconfig(params=None)
-//|
-//| Called without parameters, returns a tuple of
-//| (ip_address, subnet_mask, gateway_address, dns_server)
+//| def ifconfig(self, params: Any = None) -> Any:
+//| """Called without parameters, returns a tuple of
+//| (ip_address, subnet_mask, gateway_address, dns_server)
//|
-//| Or can be called with the same tuple to set those parameters.
-//| Setting ifconfig parameters turns DHCP off, if it was on.
+//| Or can be called with the same tuple to set those parameters.
+//| Setting ifconfig parameters turns DHCP off, if it was on."""
+//| ...
//|
STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {