summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-06-13 21:55:07 -0400
committerDan Halbert <halbert@halwitz.org>2019-06-13 21:55:07 -0400
commitbed6d43a768838fd3bc5d2048bf7acdc6e9b0a33 (patch)
tree814683e585940b502d4e47f8556a69045729c77a
parent6fed24e1b6fce58f2c06328b9bc8b8f9d9512b42 (diff)
parent6be7cf7440acb827d4b0f767b6083a859499b045 (diff)
merge from upstream; WIP redo Address; no more AddressType
-rw-r--r--.gitignore3
-rwxr-xr-x.travis.yml2
-rw-r--r--Makefile20
-rw-r--r--README.rst8
-rw-r--r--locale/ID.po21
-rw-r--r--locale/circuitpython.pot21
-rw-r--r--locale/de_DE.po21
-rw-r--r--locale/en_US.po21
-rw-r--r--locale/en_x_pirate.po21
-rw-r--r--locale/es.po21
-rw-r--r--locale/fil.po21
-rw-r--r--locale/fr.po21
-rw-r--r--locale/it_IT.po21
-rw-r--r--locale/pl.po21
-rw-r--r--locale/pt_BR.po21
-rw-r--r--locale/zh_Latn_pinyin.po21
-rwxr-xr-xmain.c5
-rw-r--r--ports/atmel-samd/Makefile14
-rw-r--r--ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk8
-rw-r--r--ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk14
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk17
-rw-r--r--ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk11
-rw-r--r--ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk13
-rwxr-xr-xports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk8
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk9
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk14
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/meowmeow/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk8
-rw-r--r--ports/atmel-samd/boards/pewpew10/mpconfigboard.mk15
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/pybadge/board.c4
-rw-r--r--ports/atmel-samd/boards/pybadge/mpconfigboard.mk20
-rw-r--r--ports/atmel-samd/boards/pygamer/mpconfigboard.mk20
-rw-r--r--ports/atmel-samd/boards/pygamer/pins.c3
-rw-r--r--ports/atmel-samd/boards/pyportal/mpconfigboard.mk9
-rw-r--r--ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/sam32/mpconfigboard.mk6
-rwxr-xr-xports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk11
-rwxr-xr-xports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk11
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/uchip/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/ugame10/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/common-hal/ps2io/Ps2.c441
-rw-r--r--ports/atmel-samd/common-hal/ps2io/Ps2.h (renamed from shared-bindings/bleio/AddressType.h)50
-rw-r--r--ports/atmel-samd/common-hal/ps2io/__init__.c1
-rw-r--r--ports/atmel-samd/eic_handler.c7
-rw-r--r--ports/atmel-samd/eic_handler.h1
-rw-r--r--ports/atmel-samd/supervisor/port.c1
-rw-r--r--ports/atmel-samd/tools/gen_pin_name_table.py3
-rw-r--r--ports/nrf/README.md1
-rw-r--r--ports/nrf/background.c4
-rw-r--r--ports/nrf/boards/electronut_labs_blip/README.md67
-rw-r--r--ports/nrf/boards/electronut_labs_blip/board.c38
-rw-r--r--ports/nrf/boards/electronut_labs_blip/mpconfigboard.h53
-rw-r--r--ports/nrf/boards/electronut_labs_blip/mpconfigboard.mk22
-rw-r--r--ports/nrf/boards/electronut_labs_blip/pins.c72
-rw-r--r--ports/nrf/common-hal/bleio/Adapter.c10
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.c1
-rw-r--r--ports/nrf/common-hal/bleio/Scanner.c5
-rw-r--r--ports/nrf/supervisor/port.c10
-rw-r--r--py/circuitpy_defns.mk11
-rw-r--r--py/circuitpy_mpconfig.h10
-rw-r--r--py/circuitpy_mpconfig.mk20
-rwxr-xr-xpy/gc.c4
-rw-r--r--py/gc.h1
-rw-r--r--py/modbuiltins.c6
-rw-r--r--py/py.mk17
-rw-r--r--py/vmentrytable.h4
-rw-r--r--requirements-dev.txt1
-rw-r--r--setup.py22
-rw-r--r--shared-bindings/_pew/PewPew.c15
-rw-r--r--shared-bindings/_pixelbuf/PixelBuf.c42
-rw-r--r--shared-bindings/_pixelbuf/__init__.c38
-rw-r--r--shared-bindings/analogio/AnalogIn.c9
-rw-r--r--shared-bindings/analogio/AnalogOut.c4
-rw-r--r--shared-bindings/audiobusio/I2SOut.c17
-rw-r--r--shared-bindings/audiobusio/PDMIn.c11
-rw-r--r--shared-bindings/audioio/AudioOut.c17
-rw-r--r--shared-bindings/audioio/Mixer.c14
-rw-r--r--shared-bindings/audioio/RawSample.c10
-rw-r--r--shared-bindings/audioio/WaveFile.c18
-rw-r--r--shared-bindings/bitbangio/I2C.c35
-rw-r--r--shared-bindings/bitbangio/OneWire.c12
-rw-r--r--shared-bindings/bitbangio/SPI.c40
-rw-r--r--shared-bindings/bleio/Address.c95
-rw-r--r--shared-bindings/bleio/Address.h8
-rw-r--r--shared-bindings/bleio/AddressType.c99
-rw-r--r--shared-bindings/bleio/CharacteristicBuffer.c16
-rw-r--r--shared-bindings/bleio/Peripheral.c1
-rw-r--r--shared-bindings/bleio/ScanEntry.c226
-rw-r--r--shared-bindings/bleio/Scanner.c4
-rw-r--r--shared-bindings/bleio/UUID.c16
-rw-r--r--shared-bindings/bleio/__init__.c5
-rw-r--r--shared-bindings/board/__init__.c7
-rw-r--r--shared-bindings/busio/I2C.c38
-rw-r--r--shared-bindings/busio/OneWire.c12
-rw-r--r--shared-bindings/busio/SPI.c47
-rw-r--r--shared-bindings/busio/UART.c24
-rw-r--r--shared-bindings/busio/__init__.c1
-rw-r--r--shared-bindings/digitalio/DigitalInOut.c29
-rw-r--r--shared-bindings/displayio/Display.h3
-rw-r--r--shared-bindings/displayio/TileGrid.c82
-rw-r--r--shared-bindings/displayio/TileGrid.h8
-rw-r--r--shared-bindings/displayio/__init__.c2
-rw-r--r--shared-bindings/frequencyio/FrequencyIn.c18
-rw-r--r--shared-bindings/help.c2
-rw-r--r--shared-bindings/i2cslave/I2CSlave.c4
-rw-r--r--shared-bindings/index.rst1
-rw-r--r--shared-bindings/microcontroller/Pin.c2
-rw-r--r--shared-bindings/microcontroller/RunMode.c14
-rw-r--r--shared-bindings/microcontroller/__init__.c16
-rw-r--r--shared-bindings/neopixel_write/__init__.c4
-rw-r--r--shared-bindings/network/__init__.c2
-rw-r--r--shared-bindings/ps2io/Ps2.c243
-rw-r--r--shared-bindings/ps2io/Ps2.h45
-rw-r--r--shared-bindings/ps2io/__init__.c73
-rw-r--r--shared-bindings/ps2io/__init__.h35
-rw-r--r--shared-bindings/pulseio/PWMOut.c16
-rw-r--r--shared-bindings/pulseio/PulseIn.c24
-rw-r--r--shared-bindings/pulseio/PulseOut.c4
-rw-r--r--shared-bindings/pulseio/__init__.c4
-rw-r--r--shared-bindings/rotaryio/IncrementalEncoder.c10
-rw-r--r--shared-bindings/socket/__init__.c2
-rw-r--r--shared-bindings/storage/__init__.c6
-rw-r--r--shared-bindings/struct/__init__.c8
-rw-r--r--shared-bindings/time/__init__.c33
-rw-r--r--shared-bindings/touchio/TouchIn.c14
-rw-r--r--shared-bindings/uheap/__init__.c2
-rw-r--r--shared-bindings/ustack/__init__.c6
-rw-r--r--shared-bindings/util.c8
-rw-r--r--shared-bindings/util.h2
-rw-r--r--shared-bindings/wiznet/wiznet5k.c2
-rw-r--r--shared-module/audioio/WaveFile.h2
-rw-r--r--shared-module/bleio/Address.h8
-rw-r--r--shared-module/bleio/ScanEntry.h2
-rw-r--r--shared-module/board/__init__.c2
-rw-r--r--shared-module/displayio/Display.c101
-rw-r--r--shared-module/displayio/Display.h38
-rw-r--r--shared-module/displayio/Group.c234
-rw-r--r--shared-module/displayio/Group.h14
-rw-r--r--shared-module/displayio/Palette.c6
-rw-r--r--shared-module/displayio/TileGrid.c388
-rw-r--r--shared-module/displayio/TileGrid.h37
-rw-r--r--shared-module/displayio/__init__.c337
-rw-r--r--shared-module/displayio/__init__.h7
-rw-r--r--shared-module/displayio/area.h73
-rw-r--r--supervisor/shared/display.c26
-rwxr-xr-xtools/build_release_files.py37
-rw-r--r--tools/gen_display_resources.py12
-rwxr-xr-xtools/git-checkout-latest-tag.sh3
175 files changed, 3341 insertions, 1216 deletions
diff --git a/.gitignore b/.gitignore
index 69f71847b..3e5bd2830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@
# Packages
############
+dist/
+*.egg-info
# Logs and Databases
######################
@@ -25,6 +27,7 @@
######################
build/
bin/
+circuitpython-stubs/
# Test failure outputs
######################
diff --git a/.travis.yml b/.travis.yml
index 6d849e229..1702089c3 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,7 @@ git:
# that SDK is shortest and add it there. In the case of major re-organizations,
# just try to make the builds "about equal in run time"
env:
- - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="circuitplayground_express mini_sam_m4 grandcentral_m4_express capablerobot_usbhub pca10056 pca10059 feather_nrf52840_express makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini electronut_labs_papyr" TRAVIS_SDK=arm:nrf
+ - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="circuitplayground_express mini_sam_m4 grandcentral_m4_express capablerobot_usbhub pygamer pca10056 pca10059 feather_nrf52840_express makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini electronut_labs_papyr electronut_labs_blip" TRAVIS_SDK=arm:nrf
- TRAVIS_BOARDS="metro_m0_express metro_m4_express metro_m4_airlift_lite pirkey_m0 trellis_m4_express trinket_m0 sparkfun_lumidrive sparkfun_redboard_turbo bast_pro_mini_m0" TRAVIS_SDK=arm
- TRAVIS_BOARDS="feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow sam32 uchip escornabot_makech" TRAVIS_SDK=arm
- TRAVIS_BOARDS="feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300 arduino_mkrzero pewpew10 kicksat-sprite ugame10 robohatmm1" TRAVIS_SDK=arm
diff --git a/Makefile b/Makefile
index 5d5d99fb8..8a4cf609f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# Makefile for Sphinx documentation
+# Top-level Makefile for documentation builds and miscellaneous tasks.
#
# You can set these variables from the command line.
@@ -17,6 +17,13 @@ CONFDIR = .
FORCE = -E
VERBOSE = -v
+# path to generated type stubs
+STUBDIR = circuitpython-stubs
+# Run "make VALIDATE= stubs" to avoid validating generated stub files
+VALIDATE = -v
+# path to pypi source distributions
+DISTDIR = dist
+
# Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the
# full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the
# executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
@@ -31,7 +38,7 @@ I18NSPHINXOPTS = $(BASEOPTS)
TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/nrf py shared-bindings shared-module supervisor
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext stubs
help:
@echo "Please use \`make <target>' where <target> is one of"
@@ -60,6 +67,7 @@ help:
clean:
rm -rf $(BUILDDIR)/*
+ rm -rf $(STUBDIR) $(DISTDIR) *.egg-info
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@@ -203,3 +211,11 @@ translate: locale/circuitpython.pot
check-translate: locale/circuitpython.pot $(wildcard locale/*.po)
$(PYTHON) tools/check_translations.py $^
+
+stubs:
+ rst2pyi $(VALIDATE) shared-bindings/ $(STUBDIR)
+ python setup.py sdist
+
+update-frozen-libraries:
+ @echo "Updating all frozen libraries to latest tagged version."
+ cd frozen; for library in *; do cd $$library; ../../tools/git-checkout-latest-tag.sh; cd ..; done
diff --git a/README.rst b/README.rst
index 53ac4cbcd..f5f9cccea 100644
--- a/README.rst
+++ b/README.rst
@@ -115,8 +115,8 @@ Behavior
output is written to ``boot_out.txt``.
- ``code.py`` (or ``main.py``) is run after every reload until it
finishes or is interrupted. After it is done running, the vm and
- hardware is reinitialized. **This means you cannot read state from
- ``code.py`` in the REPL anymore.** CircuitPython's goal for this
+ hardware is reinitialized. **This means you cannot read state from**
+ ``code.py`` **in the REPL anymore.** CircuitPython's goal for this
change includes reduce confusion about pins and memory being used.
- After ``code.py`` the REPL can be entered by pressing any key. It no
longer shares state with ``code.py`` so it is a fresh vm.
@@ -131,9 +131,9 @@ Behavior
``samd.disable_autoreload()``)
- Entering the REPL after the main code is finished requires a key press which enters the REPL and
disables autoreload.
-- Main is one of these: ``code.txt``, **``code.py``**, ``main.py``,
+- Main is one of these: ``code.txt``, ``code.py``, ``main.py``,
``main.txt``
-- Boot is one of these: ``settings.txt``, ``settings.py``, **``boot.py``**,
+- Boot is one of these: ``settings.txt``, ``settings.py``, ``boot.py``,
``boot.txt``
API
diff --git a/locale/ID.po b/locale/ID.po
index f5c0c0949..c1760e6b4 100644
--- a/locale/ID.po
+++ b/locale/ID.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -518,6 +518,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Channel EXTINT sedang digunakan"
@@ -546,6 +547,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -852,6 +857,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "LHS dari keyword arg harus menjadi sebuah id"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr ""
@@ -932,6 +941,10 @@ msgstr "Tidak ada GCLK yang kosong"
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1015,6 +1028,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Tambahkan module apapun pada filesystem\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2176,7 +2193,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 34070dc69..d32502e18 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:41-0700\n"
+"POT-Creation-Date: 2019-06-12 00:59-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -506,6 +506,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr ""
@@ -534,6 +535,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr ""
@@ -827,6 +832,10 @@ msgid "LHS of keyword arg must be an id"
msgstr ""
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr ""
@@ -907,6 +916,10 @@ msgstr ""
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -989,6 +1002,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2131,7 +2148,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 2cb97c3d3..2bdaaf712 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Pascal Deneaux\n"
"Language-Team: Sebastian Plamauer, Pascal Deneaux\n"
@@ -510,6 +510,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Drive mode wird nicht verwendet, wenn die Richtung input ist."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "EXTINT Kanal ist schon in Benutzung"
@@ -538,6 +539,10 @@ msgstr "Eine UUID wird erwartet"
msgid "Expected tuple of length %d, got %d"
msgstr "Habe ein Tupel der Länge %d erwartet aber %d erhalten"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr "Akquirieren des Mutex gescheitert"
@@ -833,6 +838,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "LHS des Schlüsselwortarguments muss eine id sein"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr "Layer muss eine Group- oder TileGrid-Unterklasse sein."
@@ -920,6 +929,10 @@ msgstr "Keine freien GCLKs"
msgid "No hardware random available"
msgstr "Kein hardware random verfügbar"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1004,6 +1017,10 @@ msgstr "Pixel außerhalb der Puffergrenzen"
msgid "Plus any modules on the filesystem\n"
msgstr "und alle Module im Dateisystem \n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2178,7 +2195,7 @@ msgstr "Objekt ist kein Iterator"
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "Objekt ist nicht in sequence"
diff --git a/locale/en_US.po b/locale/en_US.po
index ebc18cfae..152ece432 100644
--- a/locale/en_US.po
+++ b/locale/en_US.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -506,6 +506,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr ""
@@ -534,6 +535,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr ""
@@ -827,6 +832,10 @@ msgid "LHS of keyword arg must be an id"
msgstr ""
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr ""
@@ -907,6 +916,10 @@ msgstr ""
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -989,6 +1002,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2131,7 +2148,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po
index 04706abdc..d91dc95ca 100644
--- a/locale/en_x_pirate.po
+++ b/locale/en_x_pirate.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: @sommersoft, @MrCertainly\n"
@@ -510,6 +510,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Avast! EXTINT channel already in use"
@@ -538,6 +539,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr ""
@@ -831,6 +836,10 @@ msgid "LHS of keyword arg must be an id"
msgstr ""
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr ""
@@ -911,6 +920,10 @@ msgstr ""
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -993,6 +1006,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2135,7 +2152,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index 77739f49c..d954d574c 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -524,6 +524,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Modo Drive no se usa cuando la dirección es input."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "El canal EXTINT ya está siendo utilizado"
@@ -554,6 +555,10 @@ msgstr "Se espera un %q"
msgid "Expected tuple of length %d, got %d"
msgstr "Se esperaba un tuple de %d, se obtuvo %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -862,6 +867,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "LHS del agumento por palabra clave deberia ser un identificador"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr "Layer debe ser una subclase de Group o TileGrid."
@@ -946,6 +955,10 @@ msgstr "Sin GCLKs libres"
msgid "No hardware random available"
msgstr "No hay hardware random disponible"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1035,6 +1048,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Incapaz de montar de nuevo el sistema de archivos"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2213,7 +2230,7 @@ msgstr "objeto no es un iterator"
msgid "object not callable"
msgstr "objeto no puede ser llamado"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "objeto no en secuencia"
diff --git a/locale/fil.po b/locale/fil.po
index 5954e29b4..b6ad3643c 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-12-20 22:15-0800\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n"
@@ -519,6 +519,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Drive mode ay hindi ginagamit kapag ang direksyon ay input."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Ginagamit na ang EXTINT channel"
@@ -549,6 +550,10 @@ msgstr "Umasa ng %q"
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -857,6 +862,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "LHS ng keyword arg ay dapat na id"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr ""
@@ -941,6 +950,10 @@ msgstr "Walang libreng GCLKs"
msgid "No hardware random available"
msgstr "Walang magagamit na hardware random"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1028,6 +1041,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Kasama ang kung ano pang modules na sa filesystem\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2212,7 +2229,7 @@ msgstr "object ay hindi iterator"
msgid "object not callable"
msgstr "hindi matatawag ang object"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "object wala sa sequence"
diff --git a/locale/fr.po b/locale/fr.po
index 0bd0f8771..6fd6e9015 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2019-04-14 20:05+0100\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -522,6 +522,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Le mode Drive n'est pas utilisé quand la direction est 'input'."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Canal EXTINT déjà utilisé"
@@ -552,6 +553,10 @@ msgstr "Un UUID est attendu"
msgid "Expected tuple of length %d, got %d"
msgstr "Tuple de longueur %d attendu, obtenu %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -865,6 +870,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "La partie gauche de l'argument nommé doit être un identifiant"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr "'Layer' doit être un 'Group' ou une sous-classe 'TileGrid'."
@@ -949,6 +958,10 @@ msgstr "Pas de GCLK libre"
msgid "No hardware random available"
msgstr "Pas de source matérielle d'aléa disponible"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1045,6 +1058,10 @@ msgstr "Pixel au-delà des limites du tampon"
msgid "Plus any modules on the filesystem\n"
msgstr "Ainsi que tout autre module présent sur le système de fichiers\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger."
@@ -2247,7 +2264,7 @@ msgstr "l'objet n'est pas un itérateur"
msgid "object not callable"
msgstr "objet non appelable"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "l'objet n'est pas dans la séquence"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 12f21c38e..d89d4ae07 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -519,6 +519,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Canale EXTINT già in uso"
@@ -549,6 +550,10 @@ msgstr "Atteso un %q"
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -859,6 +864,10 @@ msgid "LHS of keyword arg must be an id"
msgstr ""
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr "Layer deve essere un Group o TileGrid subclass"
@@ -940,6 +949,10 @@ msgstr "Nessun GCLK libero"
msgid "No hardware random available"
msgstr "Nessun generatore hardware di numeri casuali disponibile"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1033,6 +1046,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Imposssibile rimontare il filesystem"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2208,7 +2225,7 @@ msgstr "l'oggetto non è un iteratore"
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "oggetto non in sequenza"
diff --git a/locale/pl.po b/locale/pl.po
index 1a7471f72..e7dc248be 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2019-03-19 18:37-0700\n"
"Last-Translator: Radomir Dopieralski <circuitpython@sheep.art.pl>\n"
"Language-Team: pl\n"
@@ -509,6 +509,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Tryb sterowania nieużywany w trybie wejścia."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Kanał EXTINT w użyciu"
@@ -537,6 +538,10 @@ msgstr "Oczekiwano UUID"
msgid "Expected tuple of length %d, got %d"
msgstr "Oczekiwano krotkę długości %d, otrzymano %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr "Nie udało się uzyskać blokady"
@@ -832,6 +837,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "Lewa strona argumentu nazwanego musi być nazwą"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr "Layer musi dziedziczyć z Group albo TileGrid"
@@ -917,6 +926,10 @@ msgstr "Brak wolnych GLCK"
msgid "No hardware random available"
msgstr "Brak generatora liczb losowych"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -999,6 +1012,10 @@ msgstr "Piksel poza granicami bufora"
msgid "Plus any modules on the filesystem\n"
msgstr "Oraz moduły w systemie plików\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr "Dowolny klawisz aby uruchomić konsolę. CTRL-D aby przeładować."
@@ -2156,7 +2173,7 @@ msgstr "obiekt nie jest iteratorem"
msgid "object not callable"
msgstr "obiekt nie jest wywoływalny"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "obiektu nie ma sekwencji"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 390610041..f08619187 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2018-10-02 21:14-0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -514,6 +514,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Canal EXTINT em uso"
@@ -544,6 +545,10 @@ msgstr "Esperado um"
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr "Falha ao enviar comando."
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -850,6 +855,10 @@ msgid "LHS of keyword arg must be an id"
msgstr ""
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr ""
@@ -930,6 +939,10 @@ msgstr "Não há GCLKs livre"
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr "Sem suporte de hardware no pino de clock"
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1016,6 +1029,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Não é possível remontar o sistema de arquivos"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr "Buffer Ps2 vazio"
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2165,7 +2182,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "objeto não em seqüência"
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index 82264cb52..dd61f1362 100644
--- a/locale/zh_Latn_pinyin.po
+++ b/locale/zh_Latn_pinyin.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: circuitpython-cn\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-06-11 14:59-0700\n"
"PO-Revision-Date: 2019-04-13 10:10-0700\n"
"Last-Translator: hexthat\n"
"Language-Team: Chinese Hanyu Pinyin\n"
@@ -510,6 +510,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Fāngxiàng shūrù shí qūdòng móshì méiyǒu shǐyòng."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "EXTINT píndào yǐjīng shǐyòng"
@@ -538,6 +539,10 @@ msgstr "Yùqí UUID"
msgid "Expected tuple of length %d, got %d"
msgstr "Qīwàng de chángdù wèi %d de yuán zǔ, dédào %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr "Wúfǎ huòdé mutex"
@@ -833,6 +838,10 @@ msgid "LHS of keyword arg must be an id"
msgstr "Guānjiàn zì arg de LHS bìxū shì id"
#: shared-module/displayio/Group.c
+msgid "Layer already in a group."
+msgstr ""
+
+#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
msgstr "Layer bìxū shì Group huò TileGrid zi lèi."
@@ -917,6 +926,10 @@ msgstr "Méiyǒu miǎnfèi de GCLKs"
msgid "No hardware random available"
msgstr "Méiyǒu kěyòng de yìngjiàn suíjī"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1004,6 +1017,10 @@ msgstr "Xiàngsù chāochū huǎnchōng qū biānjiè"
msgid "Plus any modules on the filesystem\n"
msgstr "Zài wénjiàn xìtǒng shàng tiānjiā rènhé mókuài\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr "Àn xià rènhé jiàn jìnrù REPL. Shǐyòng CTRL-D chóngxīn jiāzài."
@@ -2168,7 +2185,7 @@ msgstr "duìxiàng bùshì diédài qì"
msgid "object not callable"
msgstr "duìxiàng wúfǎ diàoyòng"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "duìxiàng bùshì xùliè"
diff --git a/main.c b/main.c
index 107b5b3c2..6d7502ba4 100755
--- a/main.c
+++ b/main.c
@@ -455,6 +455,11 @@ void gc_collect(void) {
// This collects root pointers from the VFS mount table. Some of them may
// have lost their references in the VM even though they are mounted.
gc_collect_root((void**)&MP_STATE_VM(vfs_mount_table), sizeof(mp_vfs_mount_t) / sizeof(mp_uint_t));
+
+ #if CIRCUITPY_DISPLAYIO
+ displayio_gc_collect();
+ #endif
+
// This naively collects all object references from an approximate stack
// range.
gc_collect_root((void**)sp, ((uint32_t)&_estack - sp) / sizeof(uint32_t));
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 9b110c1bb..8e3fe9460 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -99,10 +99,9 @@ endif
#Debugging/Optimization
ifeq ($(DEBUG), 1)
- # Turn on Python modules useful for debugging (e.g. uheap, ustack).
CFLAGS += -ggdb
# You may want to disable -flto if it interferes with debugging.
- CFLAGS += -flto
+ CFLAGS += -flto -flto-partition=none
# You may want to enable these flags to make setting breakpoints easier.
# CFLAGS += -fno-inline -fno-ipa-sra
ifeq ($(CHIP_FAMILY), samd21)
@@ -112,13 +111,18 @@ else
# -finline-limit can shrink the image size.
# -finline-limit=80 or so is similar to not having it on.
# There is no simple default value, though.
- ifeq ($(INTERNAL_FLASH_FILESYSTEM),1)
- CFLAGS += -finline-limit=50
+
+ # Do a default shrink for small builds.
+ ifndef CFLAGS_INLINE_LIMIT
+ ifeq ($(CIRCUITPY_SMALL_BUILD),1)
+ CFLAGS_INLINE_LIMIT = 50
+ endif
endif
+
ifdef CFLAGS_INLINE_LIMIT
CFLAGS += -finline-limit=$(CFLAGS_INLINE_LIMIT)
endif
- CFLAGS += -flto
+ CFLAGS += -flto -flto-partition=none
endif
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
diff --git a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
index bafb8a96c..a543468e5 100644
--- a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
@@ -4,9 +4,10 @@ USB_PID = 0x8053
USB_PRODUCT = "Arduino MKR1300"
USB_MANUFACTURER = "Arduino"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
index b6df8d6e2..5612eb88d 100644
--- a/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
@@ -1,12 +1,14 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
-USB_PID = 0x8035
+USB_PID = 0x8050
USB_PRODUCT = "Arduino MKRZero"
USB_MANUFACTURER = "Arduino"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
index af953e8c2..cbbf15a3e 100644
--- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x824D
USB_PRODUCT = "Arduino Zero"
USB_MANUFACTURER = "Arduino"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk b/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk
index 0e9bf7b45..08e42aa4e 100644
--- a/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk
@@ -4,9 +4,9 @@ USB_PID = 0xBAB3
USB_PRODUCT = "Bast Pro Mini M0"
USB_MANUFACTURER = "Electronic Cats"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk b/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
index 88a059dcf..97c8eb863 100644
--- a/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
@@ -4,6 +4,9 @@ USB_PID = 0xEDB3
USB_PRODUCT = "Programmable USB Hub"
USB_MANUFACTURER = "Capable Robot Components"
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
@@ -13,6 +16,3 @@ LONGINT_IMPL = MPZ
CIRCUITPY_AUDIOBUSIO = 0
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51G19A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk
index 9cdfca5b1..2399aad5c 100644
--- a/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk
@@ -4,9 +4,9 @@ USB_PID = 0xBAB2
USB_PRODUCT = "CatWAN USBStick"
USB_MANUFACTURER = "Electronic Cats"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index 652d20137..3c43776f5 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -4,6 +4,9 @@ USB_PID = 0x8019
USB_PRODUCT = "CircuitPlayground Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
@@ -14,8 +17,8 @@ CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CSLAVE = 0
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
+CFLAGS_INLINE_LIMIT = 55
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
@@ -24,10 +27,3 @@ FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor
-
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-CFLAGS_INLINE_LIMIT = 35
-else
-CFLAGS_INLINE_LIMIT = 55
-endif
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
index bdcb4d350..f456515f9 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
@@ -4,26 +4,23 @@ USB_PID = 0x8019
USB_PRODUCT = "CircuitPlayground Express with Crickit libraries"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
-# Turn off longints for Crickit build to make room for additional frozen libs.
-LONGINT_IMPL = NONE
+# Turn off features and optimizations for Crickit build to make room for additional frozen libs.
+LONGINT_IMPL = NONE
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_PIXELBUF = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CSLAVE = 0
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
-
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-CFLAGS_INLINE_LIMIT = 35
-else
+SUPEROPT_GC = 0
CFLAGS_INLINE_LIMIT = 55
-endif
+
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
diff --git a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
index 0444a37b9..72a191044 100644
--- a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
@@ -4,14 +4,15 @@ USB_PID = 0x8021
USB_PRODUCT = "CP32-M4"
USB_MANUFACTURER = "Nadda-Reel Company LLC"
+CHIP_VARIANT = SAMD51J20A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_PM"
-# No I2S on SAMD51G
+CIRCUITPY_PS2IO = 1
+# No I2S on SAMD51G.
CIRCUITPY_AUDIOBUSIO = 0
-# No touch on SAMD51 yet
+# No touch on SAMD51 yet.
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51J20A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
index e6b21e25b..794920fe3 100644
--- a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
@@ -4,17 +4,16 @@ USB_PID = 0x0001
USB_PRODUCT = "Datalore IP M4"
USB_MANUFACTURER = "TG-Boards"
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 3
EXTERNAL_FLASH_DEVICES = "GD25Q16C, W25Q16JV_IQ, W25Q16JV_IM"
-
LONGINT_IMPL = MPZ
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
-
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
-
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+CIRCUITPY_PS2IO = 1
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk b/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk
index 4d4649506..a2c182e68 100644
--- a/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0xBAB6
USB_PRODUCT = "Escornabot Makech"
USB_MANUFACTURER = "Electronic Cats"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
index 26e3b7d4d..a88dbd563 100644
--- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x8015
USB_PRODUCT = "Feather M0 Adalogger"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
index 102cb656f..076f1f8ff 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x8015
USB_PRODUCT = "Feather M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index a6190267d..756c293ad 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -4,15 +4,13 @@ USB_PID = 0x8023
USB_PRODUCT = "Feather M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
-
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
CFLAGS_INLINE_LIMIT = 60
-endif
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
index 620a0d505..5793d82e5 100644
--- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
@@ -4,6 +4,9 @@ USB_PID = 0x8023
USB_PRODUCT = "Feather M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
@@ -14,13 +17,8 @@ CIRCUITPY_BITBANGIO = 0
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CSLAVE = 0
-
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
-
-CFLAGS_INLINE_LIMIT = 50
-
CIRCUITPY_GAMEPAD = 0
+CFLAGS_INLINE_LIMIT = 50
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
index ce3f8668c..83d794d04 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x8015
USB_PRODUCT = "Feather M0 RFM69"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
index 282977338..a84e14f55 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x8015
USB_PRODUCT = "Feather M0 RFM9x"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
index 4bae6ffa7..33229044b 100644
--- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
@@ -4,10 +4,10 @@ USB_PID = 0x8023
USB_PRODUCT = "Feather M0 Supersized"
USB_MANUFACTURER = "Dave Astels"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "S25FL064L"
LONGINT_IMPL = MPZ
-
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
index 4fddcffc1..8169345f5 100644
--- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
@@ -4,17 +4,16 @@ USB_PID = 0x8026
USB_PRODUCT = "Feather M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
-QSPI_FLASH_FILESYSTEM = 1
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
-
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+CIRCUITPY_PS2IO = 1
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk
index d9350ea22..c4a3a5a19 100755
--- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk
@@ -4,6 +4,9 @@ USB_PID = 0x8023
USB_PRODUCT = "Feather RadioFruit Zigbee"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMR21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
@@ -13,6 +16,3 @@ LONGINT_IMPL = MPZ
CIRCUITPY_AUDIOBUSIO = 0
# No DAC on SAMR21G
CIRCUITPY_AUDIOIO = 0
-
-CHIP_VARIANT = SAMR21G18A
-CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
index 9f4a9fe83..6f44a22f8 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x801D
USB_PRODUCT = "Gemma M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
index 63158681b..13631a736 100644
--- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
@@ -4,14 +4,14 @@ USB_PID = 0x8032
USB_PRODUCT = "Grand Central M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
-QSPI_FLASH_FILESYSTEM = 1
+CHIP_VARIANT = SAMD51P20A
+CHIP_FAMILY = samd51
+QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
+CIRCUITPY_PS2IO = 1
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51P20A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
index 1df82ff44..8dfc741e5 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
@@ -4,6 +4,9 @@ USB_PID = 0xD1ED
USB_PRODUCT = "HalloWing M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
@@ -13,11 +16,7 @@ LONGINT_IMPL = MPZ
CIRCUITPY_I2CSLAVE = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_AUDIOBUSIO = 0
-
-CFLAGS_INLINE_LIMIT = 50
-
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
index 4f3e1ca66..e427e9430 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
@@ -4,17 +4,13 @@ USB_PID = 0x8012
USB_PRODUCT = "ItsyBitsy M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C"
LONGINT_IMPL = MPZ
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
-
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-CFLAGS_INLINE_LIMIT = 45
-else
-CFLAGS_INLINE_LIMIT = 70
-endif
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
index d4d674d9d..31bb38e20 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
@@ -4,15 +4,16 @@ USB_PID = 0x802C
USB_PRODUCT = "ItsyBitsy M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
+CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51G19A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
index e97a70105..5871cca2a 100644
--- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
@@ -4,14 +4,15 @@ USB_PID = 0xED94
USB_PRODUCT = "kicksat-sprite"
USB_MANUFACTURER = "maholli"
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 0
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
+# Not needed.
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_DISPLAYIO = 0
-
-CHIP_VARIANT = SAMD51G19A
-CHIP_FAMILY = samd51 \ No newline at end of file
diff --git a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk
index 3f9601d32..894e19a6b 100644
--- a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0xBAB1
USB_PRODUCT = "Meow Meow"
USB_MANUFACTURER = "Electronic Cats"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index ce9c4baba..93a8ffc11 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -4,16 +4,13 @@ USB_PID = 0x8014
USB_PRODUCT = "Metro M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
-
LONGINT_IMPL = MPZ
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
-
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-CFLAGS_INLINE_LIMIT = 50
-endif
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
index 654a84eb8..d7d0c1d6e 100644
--- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
@@ -4,17 +4,16 @@ USB_PID = 0x8038
USB_PRODUCT = "Metro M4 Airlift Lite"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 3
EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C"
-
LONGINT_IMPL = MPZ
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
-
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+CIRCUITPY_PS2IO = 1
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index 35162b678..829bf749f 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -4,17 +4,16 @@ USB_PID = 0x8021
USB_PRODUCT = "Metro M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 3
EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C"
-
LONGINT_IMPL = MPZ
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
-
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+CIRCUITPY_PS2IO = 1
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
index 27bad2693..a8f47dced 100644
--- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
@@ -4,16 +4,16 @@ USB_PID = 0x2017
USB_PRODUCT = "Mini SAM M4"
USB_MANUFACTURER = "Benjamin Shockley"
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q16JV_IM"
-
LONGINT_IMPL = MPZ
+CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51G19A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
index b36a21368..e24a29051 100644
--- a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
@@ -4,13 +4,12 @@ USB_PID = 0x801D
USB_PRODUCT = "PewPew 10.2"
USB_MANUFACTURER = "Radomir Dopieralski"
-INTERNAL_FLASH_FILESYSTEM = 1
-LONGINT_IMPL = NONE
-
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
-FROZEN_MPY_DIRS += $(TOP)/frozen/pew-pewpew-standalone-10.x
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+CIRCUITPY_SMALL_BUILD = 1
CIRCUITPY_PEW = 1
CIRCUITPY_ANALOGIO = 1
@@ -20,9 +19,7 @@ CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
-CIRCUITPY_SMALL_BUILD = 1
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-CFLAGS_INLINE_LIMIT = 40
-endif
+SUPEROPT_GC = 0
+
+FROZEN_MPY_DIRS += $(TOP)/frozen/pew-pewpew-standalone-10.x
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
index 4405b7a35..686c9099f 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
@@ -4,6 +4,9 @@ USB_PID = 0x8028
USB_PRODUCT = "pIRKey M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
@@ -19,11 +22,8 @@ CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 1
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_SMALL_BUILD = 1
-
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
-
-CFLAGS_INLINE_LIMIT = 25
+# Make more room.
+SUPEROPT_GC = 0
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
diff --git a/ports/atmel-samd/boards/pybadge/board.c b/ports/atmel-samd/boards/pybadge/board.c
index 2b0e334fa..64fb8e852 100644
--- a/ports/atmel-samd/boards/pybadge/board.c
+++ b/ports/atmel-samd/boards/pybadge/board.c
@@ -87,8 +87,8 @@ void board_init(void) {
display->base.type = &displayio_display_type;
common_hal_displayio_display_construct(display,
bus,
- 160, // Width
- 128, // Height
+ 160, // Width (after rotation)
+ 128, // Height (after rotation)
0, // column start
0, // row start
270, // rotation
diff --git a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
index aba0e333d..b8d10387b 100644
--- a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
@@ -1,25 +1,23 @@
LD_FILE = boards/samd51x19-bootloader-external-flash.ld
USB_VID = 0x239A
-USB_PID = 0x802C
+USB_PID = 0x8034
USB_PRODUCT = "PyBadge"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
-
+CIRCUITPY_AUDIOIO = 1
+CIRCUITPY_DISPLAYIO = 1
+CIRCUITPY_GAMEPAD = 1
CIRCUITPY_GAMEPADSHIFT = 1
-
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
-
CIRCUITPY_STAGE = 1
-CIRCUITPY_GAMEPAD = 1
-CIRCUITPY_DISPLAYIO = 1
-CIRCUITPY_AUDIOIO = 1
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge
diff --git a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
index 8523e31be..a1ff90747 100644
--- a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
@@ -1,25 +1,23 @@
LD_FILE = boards/samd51x19-bootloader-external-flash.ld
USB_VID = 0x239A
-USB_PID = 0x802E
+USB_PID = 0x803E
USB_PRODUCT = "PyGamer"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q64C
LONGINT_IMPL = MPZ
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
-
+CIRCUITPY_AUDIOIO = 1
+CIRCUITPY_DISPLAYIO = 1
+CIRCUITPY_GAMEPAD = 1
CIRCUITPY_GAMEPADSHIFT = 1
-
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
-
CIRCUITPY_STAGE = 1
-CIRCUITPY_GAMEPAD = 1
-CIRCUITPY_DISPLAYIO = 1
-CIRCUITPY_AUDIOIO = 1
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge
diff --git a/ports/atmel-samd/boards/pygamer/pins.c b/ports/atmel-samd/boards/pygamer/pins.c
index aa0c3e39b..9d0d196e7 100644
--- a/ports/atmel-samd/boards/pygamer/pins.c
+++ b/ports/atmel-samd/boards/pygamer/pins.c
@@ -43,6 +43,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB22) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB23) },
+ // SDCS, dup of D4
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PA14) },
+
// Special named pins
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA15) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PB04) },
diff --git a/ports/atmel-samd/boards/pyportal/mpconfigboard.mk b/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
index 34a94ac2b..996b17b3b 100644
--- a/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
@@ -1,17 +1,16 @@
LD_FILE = boards/samd51x20-bootloader-external-flash.ld
USB_VID = 0x239A
-USB_PID = 0x8032
+USB_PID = 0x8036
USB_PRODUCT = "PyPortal"
USB_MANUFACTURER = "Adafruit Industries LLC"
-QSPI_FLASH_FILESYSTEM = 1
+CHIP_VARIANT = SAMD51J20A
+CHIP_FAMILY = samd51
+QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51J20A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk b/ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk
index da7da2761..9523984b7 100644
--- a/ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk
@@ -4,23 +4,25 @@ USB_PID = 0x4D43
USB_PRODUCT = "Robo HAT MM1"
USB_MANUFACTURER = "Robotics Masters"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
# Non-Flash Edition
#INTERNAL_FLASH_FILESYSTEM = 1
#LONGINT_IMPL = NONE
+#SUPEROPT_GC = 0
# SPI-Flash Edition
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ"
LONGINT_IMPL = MPZ
-
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
-
# Make room for frozen Libraries
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
+CFLAGS_INLINE_LIMIT = 55
+
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_INA219
@@ -29,6 +31,3 @@ FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Crickit
#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor
#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw
-
-#Adding per @danh to reduce memory usage and get the latest changes in
-CFLAGS_INLINE_LIMIT = 55
diff --git a/ports/atmel-samd/boards/sam32/mpconfigboard.mk b/ports/atmel-samd/boards/sam32/mpconfigboard.mk
index d76696b39..ca1e11f01 100644
--- a/ports/atmel-samd/boards/sam32/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sam32/mpconfigboard.mk
@@ -4,11 +4,11 @@ USB_PID = 0xEDBE
USB_PRODUCT = "SAM32"
USB_MANUFACTURER = "maholli"
+CHIP_VARIANT = SAMD51J20A
+CHIP_FAMILY = samd51
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51J20A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk
index 4da42c02d..9d0ef1c04 100755
--- a/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk
@@ -4,16 +4,15 @@ USB_PID = 0x0017
USB_PRODUCT = "LUMIDrive Board"
USB_MANUFACTURER = "SparkFun Electronics"
-SPI_FLASH_FILESYSTEM = 1
-LONGINT_IMPL = MPZ
-
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
-CIRCUITPY_AUDIOIO = 0
-CIRCUITPY_AUDIOBUSIO = 0
-
+SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32FV"
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_AUDIOIO = 0
+CIRCUITPY_AUDIOBUSIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
index 9e45f8ad9..3be1a17d3 100755
--- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
@@ -4,16 +4,13 @@ USB_PID = 0x0015
USB_PRODUCT = "RedBoard Turbo Board"
USB_MANUFACTURER = "SparkFun Electronics"
-SPI_FLASH_FILESYSTEM = 1
-LONGINT_IMPL = MPZ
-
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32FV"
+LONGINT_IMPL = MPZ
-# Tweak inlining depending on language.
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-CFLAGS_INLINE_LIMIT = 50
-endif
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
index c0238ce80..c9d0baf11 100644
--- a/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x8D23
USB_PRODUCT = "SparkFun SAMD21 Dev Breakout"
USB_MANUFACTURER = "SparkFun"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
index 462e3e2ca..a6e216575 100644
--- a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x8D22
USB_PRODUCT = "SparkFun SAMD21 Mini Breakout"
USB_MANUFACTURER = "SparkFun"
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21G18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
index 93b07bc76..6d108e649 100644
--- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
@@ -4,15 +4,16 @@ USB_PID = 0x8030
USB_PRODUCT = "Trellis M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
+CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
# No touch on SAMD51 yet
CIRCUITPY_TOUCHIO = 0
-
-CHIP_VARIANT = SAMD51G19A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index 1c6f6db05..b4a00b654 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -4,9 +4,11 @@ USB_PID = 0x801F
USB_PRODUCT = "Trinket M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index c9c196da7..b9d36a741 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -4,10 +4,10 @@ USB_PID = 0x801F
USB_PRODUCT="Trinket M0 Haxpress"
USB_MANUFACTURER="Radomir Dopieralski"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = W25Q32BV
LONGINT_IMPL = MPZ
-
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/uchip/mpconfigboard.mk b/ports/atmel-samd/boards/uchip/mpconfigboard.mk
index b6710af6d..109492b76 100644
--- a/ports/atmel-samd/boards/uchip/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/uchip/mpconfigboard.mk
@@ -4,9 +4,9 @@ USB_PID = 0xED5F
USB_PRODUCT = "uChip CircuitPython"
USB_MANUFACTURER = "Itaca Innovation"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
-
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
index cafd84b21..a27ca8874 100644
--- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
@@ -4,14 +4,14 @@ USB_PID = 0x801F
USB_PRODUCT = "uGame10"
USB_MANUFACTURER = "Radomir Dopieralski"
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = S25FL216K
LONGINT_IMPL = MPZ
-CHIP_VARIANT = SAMD21E18A
-CHIP_FAMILY = samd21
-
CIRCUITPY_STAGE = 1
CIRCUITPY_MATH = 1
CIRCUITPY_AUDIOIO = 1
diff --git a/ports/atmel-samd/common-hal/ps2io/Ps2.c b/ports/atmel-samd/common-hal/ps2io/Ps2.c
new file mode 100644
index 000000000..6a06864f2
--- /dev/null
+++ b/ports/atmel-samd/common-hal/ps2io/Ps2.c
@@ -0,0 +1,441 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * 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 "common-hal/ps2io/Ps2.h"
+
+#include <stdint.h>
+
+#include "atmel_start_pins.h"
+#include "hal/include/hal_gpio.h"
+
+#include "background.h"
+#include "eic_handler.h"
+#include "mpconfigport.h"
+#include "py/gc.h"
+#include "py/runtime.h"
+#include "samd/external_interrupts.h"
+#include "samd/pins.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/ps2io/Ps2.h"
+#include "supervisor/shared/translate.h"
+
+#include "tick.h"
+
+#define STATE_IDLE 0
+#define STATE_RECV 1
+#define STATE_RECV_PARITY 2
+#define STATE_RECV_STOP 3
+#define STATE_RECV_ERR 10
+
+#define ERROR_STARTBIT 0x01
+#define ERROR_TIMEOUT 0x02
+#define ERROR_PARITY 0x04
+#define ERROR_STOPBIT 0x08
+#define ERROR_BUFFER 0x10
+
+#define ERROR_TX_CLKLO 0x100
+#define ERROR_TX_CLKHI 0x200
+#define ERROR_TX_ACKDATA 0x400
+#define ERROR_TX_ACKCLK 0x800
+#define ERROR_TX_RTS 0x1000
+#define ERROR_TX_NORESP 0x2000
+
+static void ps2_set_config(ps2io_ps2_obj_t* self) {
+ uint32_t sense_setting = EIC_CONFIG_SENSE0_FALL_Val;
+ set_eic_handler(self->channel, EIC_HANDLER_PS2);
+ turn_on_eic_channel(self->channel, sense_setting);
+}
+
+static void disable_interrupt(ps2io_ps2_obj_t* self) {
+ uint32_t mask = 1 << self->channel;
+ EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos;
+}
+
+static void resume_interrupt(ps2io_ps2_obj_t* self) {
+ disable_interrupt(self);
+
+ self->state = STATE_IDLE;
+ gpio_set_pin_function(self->clk_pin, GPIO_PIN_FUNCTION_A);
+ uint32_t mask = 1 << self->channel;
+ EIC->INTFLAG.reg = mask << EIC_INTFLAG_EXTINT_Pos;
+ EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos;
+
+ ps2_set_config(self);
+}
+
+static void clk_hi(ps2io_ps2_obj_t* self) {
+ // External pull-up
+ // Must set pull after setting direction.
+ gpio_set_pin_direction(self->clk_pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(self->clk_pin, GPIO_PULL_OFF);
+}
+
+static bool wait_clk_lo(ps2io_ps2_obj_t* self, uint32_t us) {
+ clk_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (gpio_get_pin_level(self->clk_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static bool wait_clk_hi(ps2io_ps2_obj_t* self, uint32_t us) {
+ clk_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (!gpio_get_pin_level(self->clk_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static void clk_lo(ps2io_ps2_obj_t* self) {
+ gpio_set_pin_pull_mode(self->clk_pin, GPIO_PULL_OFF);
+ gpio_set_pin_direction(self->clk_pin, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(self->clk_pin, 0);
+}
+
+static void data_hi(ps2io_ps2_obj_t* self) {
+ // External pull-up
+ gpio_set_pin_direction(self->data_pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(self->data_pin, GPIO_PULL_OFF);
+}
+
+static bool wait_data_lo(ps2io_ps2_obj_t* self, uint32_t us) {
+ data_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (gpio_get_pin_level(self->data_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static bool wait_data_hi(ps2io_ps2_obj_t* self, uint32_t us) {
+ data_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (!gpio_get_pin_level(self->data_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static void data_lo(ps2io_ps2_obj_t* self) {
+ gpio_set_pin_pull_mode(self->data_pin, GPIO_PULL_OFF);
+ gpio_set_pin_direction(self->data_pin, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(self->data_pin, 0);
+}
+
+static void idle(ps2io_ps2_obj_t* self) {
+ clk_hi(self);
+ data_hi(self);
+}
+
+static void inhibit(ps2io_ps2_obj_t* self) {
+ clk_lo(self);
+ data_hi(self);
+}
+
+static void delay_us(uint32_t t) {
+ common_hal_mcu_delay_us(t);
+}
+
+void ps2_interrupt_handler(uint8_t channel) {
+ // Grab the current time first.
+ uint32_t current_us;
+ uint64_t current_ms;
+ current_tick(&current_ms, &current_us);
+
+ ps2io_ps2_obj_t* self = get_eic_channel_data(channel);
+ int data_bit = gpio_get_pin_level(self->data_pin) ? 1 : 0;
+
+ // test for timeout
+ if (self->state != STATE_IDLE) {
+ int64_t diff_ms = current_ms - self->last_int_ms;
+ if (diff_ms >= 2) { // a.k.a. > 1.001ms
+ self->last_errors |= ERROR_TIMEOUT;
+ self->state = STATE_IDLE;
+ }
+ }
+
+ self->last_int_us = current_us;
+ self->last_int_ms = current_ms;
+
+ if (self->state == STATE_IDLE) {
+ self->bits = 0;
+ self->parity = false;
+ self->bitcount = 0;
+ self->state = STATE_RECV;
+ if (data_bit) {
+ // start bit should be 0
+ self->last_errors |= ERROR_STARTBIT;
+ self->state = STATE_RECV_ERR;
+ } else {
+ self->state = STATE_RECV;
+ }
+
+ } else if (self->state == STATE_RECV) {
+ if (data_bit) {
+ self->bits |= data_bit << self->bitcount;
+ self->parity = !self->parity;
+ }
+ ++self->bitcount;
+ if (self->bitcount >= 8) {
+ self->state = STATE_RECV_PARITY;
+ }
+
+ } else if (self->state == STATE_RECV_PARITY) {
+ ++self->bitcount;
+ if (data_bit) {
+ self->parity = !self->parity;
+ }
+ if (!self->parity) {
+ self->last_errors |= ERROR_PARITY;
+ self->state = STATE_RECV_ERR;
+ } else {
+ self->state = STATE_RECV_STOP;
+ }
+
+ } else if (self->state == STATE_RECV_STOP) {
+ ++self->bitcount;
+ if (! data_bit) {
+ self->last_errors |= ERROR_STOPBIT;
+ } else if (self->waiting_cmd_response) {
+ self->cmd_response = self->bits;
+ self->waiting_cmd_response = false;
+ } else if (self->bufcount >= sizeof(self->buffer)) {
+ self->last_errors |= ERROR_BUFFER;
+ } else {
+ self->buffer[self->bufposw] = self->bits;
+ self->bufposw = (self->bufposw + 1) % sizeof(self->buffer);
+ self->bufcount++;
+ }
+ self->state = STATE_IDLE;
+
+ } else if (self->state == STATE_RECV_ERR) {
+ // just count the bits until idle
+ if (++self->bitcount >= 10) {
+ self->state = STATE_IDLE;
+ }
+ }
+}
+
+void common_hal_ps2io_ps2_construct(ps2io_ps2_obj_t* self,
+ const mcu_pin_obj_t* data_pin, const mcu_pin_obj_t* clk_pin) {
+ if (!clk_pin->has_extint) {
+ mp_raise_RuntimeError(translate("No hardware support on clk pin"));
+ }
+ if (eic_get_enable() && !eic_channel_free(clk_pin->extint_channel)) {
+ mp_raise_RuntimeError(translate("EXTINT channel already in use"));
+ }
+
+ clk_hi(self);
+ data_hi(self);
+
+ self->channel = clk_pin->extint_channel;
+ self->clk_pin = clk_pin->number;
+ self->data_pin = data_pin->number;
+ self->state = STATE_IDLE;
+ self->bufcount = 0;
+ self->bufposr = 0;
+ self->bufposw = 0;
+ self->waiting_cmd_response = false;
+
+ set_eic_channel_data(clk_pin->extint_channel, (void*) self);
+
+ // Check to see if the EIC is enabled and start it up if its not.'
+ if (eic_get_enable() == 0) {
+ turn_on_external_interrupt_controller();
+ }
+
+ gpio_set_pin_function(clk_pin->number, GPIO_PIN_FUNCTION_A);
+ gpio_set_pin_function(data_pin->number, GPIO_PIN_FUNCTION_A);
+
+ turn_on_cpu_interrupt(self->channel);
+
+ claim_pin(clk_pin);
+ claim_pin(data_pin);
+
+ // Set config will enable the EIC.
+ ps2_set_config(self);
+}
+
+bool common_hal_ps2io_ps2_deinited(ps2io_ps2_obj_t* self) {
+ return self->clk_pin == NO_PIN;
+}
+
+void common_hal_ps2io_ps2_deinit(ps2io_ps2_obj_t* self) {
+ if (common_hal_ps2io_ps2_deinited(self)) {
+ return;
+ }
+ set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
+ turn_off_eic_channel(self->channel);
+ reset_pin_number(self->clk_pin);
+ reset_pin_number(self->data_pin);
+ self->clk_pin = NO_PIN;
+ self->data_pin = NO_PIN;
+}
+
+uint16_t common_hal_ps2io_ps2_get_len(ps2io_ps2_obj_t* self) {
+ return self->bufcount;
+}
+
+bool common_hal_ps2io_ps2_get_paused(ps2io_ps2_obj_t* self) {
+ uint32_t mask = 1 << self->channel;
+ return (EIC->INTENSET.reg & (mask << EIC_INTENSET_EXTINT_Pos)) == 0;
+}
+
+int16_t common_hal_ps2io_ps2_popleft(ps2io_ps2_obj_t* self)
+{
+ common_hal_mcu_disable_interrupts();
+ if (self->bufcount <= 0) {
+ common_hal_mcu_enable_interrupts();
+ return -1;
+ }
+ uint8_t b = self->buffer[self->bufposr];
+ self->bufposr = (self->bufposr + 1) % sizeof(self->buffer);
+ self->bufcount -= 1;
+ common_hal_mcu_enable_interrupts();
+ return b;
+}
+
+uint16_t common_hal_ps2io_ps2_clear_errors(ps2io_ps2_obj_t* self)
+{
+ common_hal_mcu_disable_interrupts();
+ uint16_t errors = self->last_errors;
+ self->last_errors = 0;
+ common_hal_mcu_enable_interrupts();
+ return errors;
+}
+
+// Based upon TMK implementation of PS/2 protocol
+// https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/protocol/ps2_interrupt.c
+
+int16_t common_hal_ps2io_ps2_sendcmd(ps2io_ps2_obj_t* self, uint8_t b)
+{
+ disable_interrupt(self);
+ inhibit(self);
+ delay_us(100);
+
+ /* RTS and start bit */
+ data_lo(self);
+ clk_hi(self);
+ if (!wait_clk_lo(self, 10000)) {
+ self->last_errors |= ERROR_TX_RTS;
+ goto ERROR;
+ }
+
+ bool parity = true;
+ for (uint8_t i = 0; i < 8; i++) {
+ delay_us(15);
+ if (b & (1 << i)) {
+ parity = !parity;
+ data_hi(self);
+ } else {
+ data_lo(self);
+ }
+ if (!wait_clk_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKHI;
+ goto ERROR;
+ }
+ if (!wait_clk_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKLO;
+ goto ERROR;
+ }
+ }
+
+ delay_us(15);
+ if (parity) {
+ data_hi(self);
+ } else {
+ data_lo(self);
+ }
+ if (!wait_clk_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKHI;
+ goto ERROR;
+ }
+ if (!wait_clk_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKLO;
+ goto ERROR;
+ }
+
+ /* Stop bit */
+ delay_us(15);
+ data_hi(self);
+
+ /* Ack */
+ if (!wait_data_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKDATA;
+ goto ERROR;
+ }
+ if (!wait_clk_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKCLK;
+ goto ERROR;
+ }
+
+ /* wait for idle state */
+ if (!wait_clk_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKCLK;
+ goto ERROR;
+ }
+ if (!wait_data_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKDATA;
+ goto ERROR;
+ }
+
+ /* Wait for response byte */
+ self->waiting_cmd_response = true;
+ idle(self);
+ resume_interrupt(self);
+
+ for (int i = 0; i < 25; ++i) {
+ delay_us(1000);
+ common_hal_mcu_disable_interrupts();
+ bool has_response = !self->waiting_cmd_response;
+ uint8_t response = self->cmd_response;
+ common_hal_mcu_enable_interrupts();
+
+ if (has_response) {
+ return response;
+ }
+ }
+
+ /* No response */
+ common_hal_mcu_disable_interrupts();
+ self->waiting_cmd_response = false;
+ self->last_errors |= ERROR_TX_NORESP;
+ common_hal_mcu_enable_interrupts();
+ return -1;
+
+ /* Other errors */
+ERROR:
+ idle(self);
+ resume_interrupt(self);
+ return -1;
+}
diff --git a/shared-bindings/bleio/AddressType.h b/ports/atmel-samd/common-hal/ps2io/Ps2.h
index e69caffab..cce6ae474 100644
--- a/shared-bindings/bleio/AddressType.h
+++ b/ports/atmel-samd/common-hal/ps2io/Ps2.h
@@ -1,9 +1,10 @@
/*
- * This file is part of the Micro Python project, http://micropython.org/
+ * This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,27 +25,38 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PS2IO_PS2_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PS2IO_PS2_H
-#include "py/obj.h"
-
-typedef enum {
- ADDRESS_PUBLIC,
- ADDRESS_RANDOM_STATIC,
- ADDRESS_RANDOM_PRIVATE_RESOLVABLE,
- ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE
-} bleio_address_type_t;
+#include "common-hal/microcontroller/Pin.h"
-extern const mp_obj_type_t bleio_addresstype_type;
+#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
-} bleio_addresstype_obj_t;
+ uint8_t channel;
+ uint8_t clk_pin;
+ uint8_t data_pin;
+
+ uint8_t state;
+ uint64_t last_int_ms;
+ uint32_t last_int_us;
+
+ uint16_t bits;
+ bool parity;
+ uint8_t bitcount;
+
+ uint8_t buffer[16];
+ uint8_t bufcount;
+ uint8_t bufposr;
+ uint8_t bufposw;
+
+ uint16_t last_errors;
+
+ bool waiting_cmd_response;
+ uint8_t cmd_response;
+} ps2io_ps2_obj_t;
-extern const bleio_addresstype_obj_t bleio_addresstype_public_obj;
-extern const bleio_addresstype_obj_t bleio_addresstype_random_static_obj;
-extern const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj;
-extern const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj;
+void ps2_interrupt_handler(uint8_t channel);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PS2IO_PS2_H
diff --git a/ports/atmel-samd/common-hal/ps2io/__init__.c b/ports/atmel-samd/common-hal/ps2io/__init__.c
new file mode 100644
index 000000000..ba4b4249f
--- /dev/null
+++ b/ports/atmel-samd/common-hal/ps2io/__init__.c
@@ -0,0 +1 @@
+// No ps2io module functions.
diff --git a/ports/atmel-samd/eic_handler.c b/ports/atmel-samd/eic_handler.c
index db5f260e5..30ecaa7ca 100644
--- a/ports/atmel-samd/eic_handler.c
+++ b/ports/atmel-samd/eic_handler.c
@@ -25,6 +25,7 @@
*/
#include "common-hal/pulseio/PulseIn.h"
+#include "common-hal/ps2io/Ps2.h"
#include "common-hal/rotaryio/IncrementalEncoder.h"
#include "shared-bindings/microcontroller/__init__.h"
//#include "samd/external_interrupts.h"
@@ -46,6 +47,12 @@ void shared_eic_handler(uint8_t channel) {
break;
#endif
+#if CIRCUITPY_PS2IO
+ case EIC_HANDLER_PS2:
+ ps2_interrupt_handler(channel);
+ break;
+#endif
+
#if CIRCUITPY_ROTARYIO
case EIC_HANDLER_INCREMENTAL_ENCODER:
incrementalencoder_interrupt_handler(channel);
diff --git a/ports/atmel-samd/eic_handler.h b/ports/atmel-samd/eic_handler.h
index 2f9ccd67f..71b0fce67 100644
--- a/ports/atmel-samd/eic_handler.h
+++ b/ports/atmel-samd/eic_handler.h
@@ -29,6 +29,7 @@
#define EIC_HANDLER_NO_INTERRUPT 0x0
#define EIC_HANDLER_PULSEIN 0x1
#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2
+#define EIC_HANDLER_PS2 0x3
void set_eic_handler(uint8_t channel, uint8_t eic_handler);
void shared_eic_handler(uint8_t channel);
diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c
index 4f53d30f9..37360deb0 100644
--- a/ports/atmel-samd/supervisor/port.c
+++ b/ports/atmel-samd/supervisor/port.c
@@ -52,6 +52,7 @@
#include "common-hal/pulseio/PulseIn.h"
#include "common-hal/pulseio/PulseOut.h"
#include "common-hal/pulseio/PWMOut.h"
+#include "common-hal/ps2io/Ps2.h"
#include "common-hal/rtc/RTC.h"
#include "common-hal/touchio/TouchIn.h"
#include "samd/cache.h"
diff --git a/ports/atmel-samd/tools/gen_pin_name_table.py b/ports/atmel-samd/tools/gen_pin_name_table.py
index 76c9cf255..ded64e5f6 100644
--- a/ports/atmel-samd/tools/gen_pin_name_table.py
+++ b/ports/atmel-samd/tools/gen_pin_name_table.py
@@ -156,6 +156,9 @@ capabilities = {
"PA14", "PA15", "PA16", "PA17", "PA18", "PA19", "PA20",
"PA21", "PA22", "PA23", "PA30", "PA31"]
},
+ "ps2io": {
+ "Ps2": ALL_BUT_USB,
+ },
"touchio": {
"TouchIn": ["PA02", "PA03", "PB08", "PB09", "PA04", "PA05", "PA06",
"PA07", "PB02", "PB03"]
diff --git a/ports/nrf/README.md b/ports/nrf/README.md
index 65a66b7b0..5f6d03720 100644
--- a/ports/nrf/README.md
+++ b/ports/nrf/README.md
@@ -79,6 +79,7 @@ feather_nrf52840_express | s140 | Peripheral and Scanner | UF
makerdiary_nrf52840_mdk | s140 | Peripheral and Scanner | pyocd or ARM mbed DAPLink
makerdiary_nrf52840_mdk_usb_dongle | s140 | Peripheral and Scanner | DFU bootloader & nrfutil
electronut_labs_papyr | s140 | Peripheral and Scanner | UF2 bootloader
+electronut_labs_blip | s140 | Peripheral and Scanner | Black Magic Probe
## Segger Targets
diff --git a/ports/nrf/background.c b/ports/nrf/background.c
index 3fb5febd3..9c4f3ab27 100644
--- a/ports/nrf/background.c
+++ b/ports/nrf/background.c
@@ -29,7 +29,7 @@
#include "supervisor/usb.h"
#include "supervisor/shared/stack.h"
-#ifdef CIRCUITPY_DISPLAYIO
+#if CIRCUITPY_DISPLAYIO
#include "shared-module/displayio/__init__.h"
#endif
@@ -48,7 +48,7 @@ void run_background_tasks(void) {
filesystem_background();
usb_background();
- #ifdef CIRCUITPY_DISPLAYIO
+ #if CIRCUITPY_DISPLAYIO
displayio_refresh_displays();
#endif
running_background_tasks = false;
diff --git a/ports/nrf/boards/electronut_labs_blip/README.md b/ports/nrf/boards/electronut_labs_blip/README.md
new file mode 100644
index 000000000..c34ef16f8
--- /dev/null
+++ b/ports/nrf/boards/electronut_labs_blip/README.md
@@ -0,0 +1,67 @@
+# Setup
+
+The `Electronut Labs Blip` board is a development board based on the `nRF52840` SoC from
+Nordic Semiconductors. It has a Black Magic Probe compatible programmer and debugger
+built in, along with temperature/humidity sensor, ambient light intensity sensor, and
+a 3-axis accelerometer. It can be used to prototype very low power devices. It also has
+provision for an SD card slot, which makes it a complete and versatile development board.
+
+Schematic, datasheet, pin mapping etc. can be found over [here](https://docs.electronut.in/blip/).
+
+Features:
+
+* Raytac MDBT50Q-1M module based on Nordic Semiconductor's nRF52840
+* LIS2DDH12 High-performance 3-axis "femto" accelerometer
+* Optical Sensor LTR-329ALS-01
+* Si7006-A20 I2C humidity and temperature sensor
+* On board STM32F103CBT6 as Black magic probe debugger
+* NFC Antenna
+* MicroSD slot
+* Power Supply: USB, JST connector for Li-ion/Li-po
+* BQ24079 battery charging and power management IC
+
+## Installing CircuitPython submodules
+
+Before you can build, you will need to run the following commands once, which
+will install the submodules that are part of the CircuitPython ecosystem, and
+build the `mpy-cross` tool:
+
+```
+$ cd circuitpython
+$ git submodule update --init
+$ make -C mpy-cross
+```
+
+## Building and Flashing CircuitPython
+
+No special notes for this, follow `ports/nrf` generic `README.md`.
+
+### Flashing CircuitPython with GDB using on board Black magic probe debugger
+
+```
+$ cd ports/nrf
+$ make V=1 SD=s140 SERIAL=/dev/ttyACM0 BOARD=electronut_labs_blip all
+...
+...
+LINK build-electronut_labs_blip-s140/firmware.elf
+
+778588 bytes free in flash out of 1048576 bytes ( 1024.0 kb ).
+228320 bytes free in ram for stack out of 245760 bytes ( 240.0 kb ).
+
+Create build-electronut_labs_blip-s140/firmware.bin
+Create build-electronut_labs_blip-s140/firmware.hex
+Create build-electronut_labs_blip-s140/firmware.uf2
+python3 ../../tools/uf2/utils/uf2conv.py -f 0xADA52840 -c -o "build-electronut_labs_blip-s140/firmware.uf2" build-electronut_labs_blip-s140/firmware.hex
+Converting to uf2, output size: 540160, start address: 0x26000
+Wrote 540160 bytes to build-electronut_labs_blip-s140/firmware.uf2.
+```
+
+Now you can use either `.hex` or `.elf` from the generated files inside
+`build-electronut_labs_blip-s140` directory. Now you can use `arm-none-eabi-gdb`
+to flash circuitpython on Blip.
+
+### Other tips
+
+Once circuitpython is running on your board, it will come up as a mass storage
+device named `CIRCUITPY`, where you can drop in your python code. The file names
+it looks for are `main.py`, `main.txt`, `code.py` or `code.txt`.
diff --git a/ports/nrf/boards/electronut_labs_blip/board.c b/ports/nrf/boards/electronut_labs_blip/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/electronut_labs_blip/board.c
@@ -0,0 +1,38 @@
+/*
+ * 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 "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h b/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h
new file mode 100644
index 000000000..21e8c3ef6
--- /dev/null
+++ b/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2019 tavish@electronut.in
+ *
+ * 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 "nrfx/hal/nrf_gpio.h"
+
+#define ELECTRONUT_LABS_PAPYR
+
+#define MICROPY_HW_BOARD_NAME "Electronut Labs Blip"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+#define MICROPY_PY_SYS_PLATFORM "ElectronutLabsPapyr"
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+// TODO #define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_11)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_12)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_25)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P1_02)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_24)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_08)
+#define DEFAULT_UART_BUS_TX (&pin_P0_06)
diff --git a/ports/nrf/boards/electronut_labs_blip/mpconfigboard.mk b/ports/nrf/boards/electronut_labs_blip/mpconfigboard.mk
new file mode 100644
index 000000000..bf82400d1
--- /dev/null
+++ b/ports/nrf/boards/electronut_labs_blip/mpconfigboard.mk
@@ -0,0 +1,22 @@
+USB_VID = 0x239A
+USB_PID = 0x803C
+USB_PRODUCT = "Blip"
+USB_MANUFACTURER = "Electronut Labs"
+
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+MCU_CHIP = nrf52840
+SD ?= s140
+SOFTDEV_VERSION ?= 6.1.0
+
+BOOT_SETTING_ADDR = 0xFF000
+
+ifeq ($(SD),)
+ LD_FILE = boards/nrf52840_1M_256k.ld
+else
+ LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld
+ CIRCUITPY_BLEIO = 1
+endif
+
+NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 \ No newline at end of file
diff --git a/ports/nrf/boards/electronut_labs_blip/pins.c b/ports/nrf/boards/electronut_labs_blip/pins.c
new file mode 100644
index 000000000..a8f9af1cd
--- /dev/null
+++ b/ports/nrf/boards/electronut_labs_blip/pins.c
@@ -0,0 +1,72 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) },
+
+ // odd row
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_P0_19) },
+ { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_P0_21) },
+ { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_D27), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_D29), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_D31), MP_ROM_PTR(&pin_P0_31) },
+ { MP_ROM_QSTR(MP_QSTR_D33), MP_ROM_PTR(&pin_P1_01) },
+ { MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_P1_04) },
+ { MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_P1_06) },
+
+ // even row
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_P0_16) },
+ { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_P0_22) },
+ { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_P0_23) },
+ { MP_ROM_QSTR(MP_QSTR_D28), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_D30), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_D32), MP_ROM_PTR(&pin_P1_00) },
+ { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_P1_03) },
+ { MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_P1_05) },
+ { MP_ROM_QSTR(MP_QSTR_D40), MP_ROM_PTR(&pin_P1_08) },
+
+ // SCL SDA as pins also
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_12) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P1_02) },
+ { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_P0_17) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_08) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P0_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_GREEN_LED), MP_ROM_PTR(&pin_P0_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_P1_07) },
+ { MP_ROM_QSTR(MP_QSTR_RESET), MP_ROM_PTR(&pin_P0_18) },
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/bleio/Adapter.c
index 540659aa1..120fcf055 100644
--- a/ports/nrf/common-hal/bleio/Adapter.c
+++ b/ports/nrf/common-hal/bleio/Adapter.c
@@ -136,17 +136,15 @@ void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) {
uint32_t err_code;
common_hal_bleio_adapter_set_enabled(true);
-
-#if (BLE_API_VERSION == 2)
- err_code = sd_ble_gap_address_get(&local_address);
-#else
err_code = sd_ble_gap_addr_get(&local_address);
-#endif
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg(translate("Failed to get local address"));
}
address->type = local_address.addr_type;
- memcpy(address->value, local_address.addr, BLEIO_ADDRESS_BYTES);
+
+ mp_buffer_info_t buf_info;
+ mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
+ memcpy(address->bytes, buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
}
diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c
index e522b50d2..e59676fde 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.c
+++ b/ports/nrf/common-hal/bleio/Peripheral.c
@@ -32,6 +32,7 @@
#include "ble_drv.h"
#include "ble_hci.h"
#include "nrf_soc.h"
+#include "py/gc.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "shared-bindings/bleio/Adapter.h"
diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/bleio/Scanner.c
index b76caaf21..08600bc0a 100644
--- a/ports/nrf/common-hal/bleio/Scanner.c
+++ b/ports/nrf/common-hal/bleio/Scanner.c
@@ -51,15 +51,14 @@ STATIC void on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) {
return;
}
- // TODO: Don't add new entry for each item, group by address and update
bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t);
entry->base.type = &bleio_scanentry_type;
entry->rssi = report->rssi;
+ memcpy(entry->address.bytes, report->data.p_data, NUM_BLEIO_ADDRESS_BYTES);
entry->address.type = report->peer_addr.addr_type;
- memcpy(entry->address.value, report->peer_addr.addr, BLEIO_ADDRESS_BYTES);
- entry->data = mp_obj_new_bytearray(report->data.len, report->data.p_data);
+ entry->data = mp_obj_new_bytes(report->data.p_data, report->data.len);
mp_obj_list_append(scanner->adv_reports, entry);
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index 85ecd6afe..8fbf75498 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -93,16 +93,22 @@ void reset_port(void) {
i2c_reset();
spi_reset();
uart_reset();
+
+#if CIRCUITPY_PULSEIO
pwmout_reset();
pulseout_reset();
pulsein_reset();
+#endif
+
timers_reset();
- #if CIRCUITPY_RTC
+#if CIRCUITPY_RTC
rtc_reset();
- #endif
+#endif
+#if CIRCUITPY_BLEIO
bleio_reset();
+#endif
reset_all_pins();
}
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 31af38d8d..fd43a11a6 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -162,6 +162,9 @@ endif
ifeq ($(CIRCUITPY_PULSEIO),1)
SRC_PATTERNS += pulseio/%
endif
+ifeq ($(CIRCUITPY_PS2IO),1)
+SRC_PATTERNS += ps2io/%
+endif
ifeq ($(CIRCUITPY_RANDOM),1)
SRC_PATTERNS += random/%
endif
@@ -251,6 +254,8 @@ $(filter $(SRC_PATTERNS), \
pulseio/PulseIn.c \
pulseio/PulseOut.c \
pulseio/__init__.c \
+ ps2io/Ps2.c \
+ ps2io/__init__.c \
rotaryio/IncrementalEncoder.c \
rotaryio/__init__.c \
rtc/RTC.c \
@@ -283,7 +288,6 @@ SRC_BINDINGS_ENUMS += \
SRC_BINDINGS_ENUMS += \
$(filter $(SRC_PATTERNS), \
bleio/Address.c \
- bleio/AddressType.c \
bleio/ScanEntry.c \
)
@@ -359,3 +363,8 @@ $(addprefix lib/,\
libm/atan2f.c \
)
endif
+
+.PHONY: check-release-needs-clean-build
+
+check-release-needs-clean-build:
+ @echo "RELEASE_NEEDS_CLEAN_BUILD = $(RELEASE_NEEDS_CLEAN_BUILD)"
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index f957886f4..2026185ef 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -72,6 +72,7 @@
#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_MEM_STATS (0)
#define MICROPY_NONSTANDARD_TYPECODES (0)
+#define MICROPY_OPT_COMPUTED_GOTO (1)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_PY_ARRAY (1)
@@ -89,6 +90,7 @@
#define MICROPY_PY_BUILTINS_MIN_MAX (1)
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#define MICROPY_PY_BUILTINS_REVERSED (1)
+#define MICROPY_PY_BUILTINS_ROUND_INT (1)
#define MICROPY_PY_BUILTINS_SET (1)
#define MICROPY_PY_BUILTINS_SLICE (1)
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
@@ -415,6 +417,13 @@ extern const struct _mp_obj_module_t pulseio_module;
#define PULSEIO_MODULE
#endif
+#if CIRCUITPY_PS2IO
+extern const struct _mp_obj_module_t ps2io_module;
+#define PS2IO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_ps2io), (mp_obj_t)&ps2io_module },
+#else
+#define PS2IO_MODULE
+#endif
+
#if CIRCUITPY_RANDOM
extern const struct _mp_obj_module_t random_module;
#define RANDOM_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module },
@@ -579,6 +588,7 @@ extern const struct _mp_obj_module_t ustack_module;
PEW_MODULE \
PIXELBUF_MODULE \
PULSEIO_MODULE \
+ PS2IO_MODULE \
RANDOM_MODULE \
RE_MODULE \
ROTARYIO_MODULE \
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index b436929e0..47303a73a 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -32,13 +32,13 @@
# CIRCUITPY_FULL_BUILD = 0
ifndef CIRCUITPY_FULL_BUILD
-ifeq ($(CIRCUITPY_SMALL_BUILD),1)
-CIRCUITPY_FULL_BUILD = 0
-CFLAGS += -DCIRCUITPY_FULL_BUILD=0
-else
-CIRCUITPY_FULL_BUILD = 1
-CFLAGS += -DCIRCUITPY_FULL_BUILD=1
-endif
+ ifeq ($(CIRCUITPY_SMALL_BUILD),1)
+ CIRCUITPY_FULL_BUILD = 0
+ CFLAGS += -DCIRCUITPY_FULL_BUILD=0
+ else
+ CIRCUITPY_FULL_BUILD = 1
+ CFLAGS += -DCIRCUITPY_FULL_BUILD=1
+ endif
endif
# All builtin modules are listed below, with default values (0 for off, 1 for on)
@@ -153,6 +153,12 @@ CIRCUITPY_PULSEIO = 1
endif
CFLAGS += -DCIRCUITPY_PULSEIO=$(CIRCUITPY_PULSEIO)
+# Only for SAMD boards for the moment
+ifndef CIRCUITPY_PS2IO
+CIRCUITPY_PS2IO = 0
+endif
+CFLAGS += -DCIRCUITPY_PS2IO=$(CIRCUITPY_PS2IO)
+
ifndef CIRCUITPY_RANDOM
CIRCUITPY_RANDOM = 1
endif
diff --git a/py/gc.c b/py/gc.c
index e9b85fa7c..10b36950c 100755
--- a/py/gc.c
+++ b/py/gc.c
@@ -383,6 +383,10 @@ void gc_collect_start(void) {
#endif
}
+void gc_collect_ptr(void *ptr) {
+ gc_mark(ptr);
+}
+
void gc_collect_root(void **ptrs, size_t len) {
for (size_t i = 0; i < len; i++) {
void *ptr = ptrs[i];
diff --git a/py/gc.h b/py/gc.h
index 757a2a6e0..02bf45158 100644
--- a/py/gc.h
+++ b/py/gc.h
@@ -43,6 +43,7 @@ bool gc_is_locked(void);
// A given port must implement gc_collect by using the other collect functions.
void gc_collect(void);
void gc_collect_start(void);
+void gc_collect_ptr(void *ptr);
void gc_collect_root(void **ptrs, size_t len);
void gc_collect_end(void);
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 124dcd05a..e764f1987 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -455,13 +455,13 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
return o_in;
}
- #if !MICROPY_PY_BUILTINS_ROUND_INT
- mp_raise_NotImplementedError(NULL);
- #else
mp_int_t num_dig = mp_obj_get_int(args[1]);
if (num_dig >= 0) {
return o_in;
}
+ #if !MICROPY_PY_BUILTINS_ROUND_INT
+ mp_raise_NotImplementedError(NULL);
+ #else
mp_obj_t mult = mp_binary_op(MP_BINARY_OP_POWER, MP_OBJ_NEW_SMALL_INT(10), MP_OBJ_NEW_SMALL_INT(-num_dig));
mp_obj_t half_mult = mp_binary_op(MP_BINARY_OP_FLOOR_DIVIDE, mult, MP_OBJ_NEW_SMALL_INT(2));
diff --git a/py/py.mk b/py/py.mk
index a69243b01..17cb79264 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -107,9 +107,9 @@ endif
# External modules written in C.
ifneq ($(USER_C_MODULES),)
-# pre-define USERMOD variables as expanded so that variables are immediate
+# pre-define USERMOD variables as expanded so that variables are immediate
# expanded as they're added to them
-SRC_USERMOD :=
+SRC_USERMOD :=
CFLAGS_USERMOD :=
LDFLAGS_USERMOD :=
$(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \
@@ -343,10 +343,23 @@ $(PY_BUILD)/qstr.o: $(HEADER_BUILD)/qstrdefs.generated.h
$(PY_BUILD)/nlr%.o: CFLAGS += -Os
# optimising gc for speed; 5ms down to 4ms on pybv2
+ifndef SUPEROPT_GC
+ SUPEROPT_GC = 1
+endif
+
+ifeq ($(SUPEROPT_GC),1)
$(PY_BUILD)/gc.o: CFLAGS += $(CSUPEROPT)
+endif
# optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster)
+ifndef SUPEROPT_VM
+ SUPEROPT_VM = 1
+endif
+
+ifeq ($(SUPEROPT_VM),1)
$(PY_BUILD)/vm.o: CFLAGS += $(CSUPEROPT)
+endif
+
# Optimizing vm.o for modern deeply pipelined CPUs with branch predictors
# may require disabling tail jump optimization. This will make sure that
# each opcode has its own dispatching jump which will improve branch
diff --git a/py/vmentrytable.h b/py/vmentrytable.h
index 615f4e2ce..a0e2d4065 100644
--- a/py/vmentrytable.h
+++ b/py/vmentrytable.h
@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
-#if __clang__
+#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
#endif // __clang__
@@ -113,6 +113,6 @@ static const void *const entry_table[256] = {
[MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE - 1] = &&entry_MP_BC_BINARY_OP_MULTI,
};
-#if __clang__
+#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 000000000..7cd491ade
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1 @@
+rst2pyi>=0.3.0
diff --git a/setup.py b/setup.py
new file mode 100644
index 000000000..1e0d81da3
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,22 @@
+from datetime import datetime
+from setuptools import setup
+from pathlib import Path
+
+stub_root = Path("circuitpython-stubs")
+stubs = [p.relative_to(stub_root).as_posix() for p in stub_root.glob("*.pyi")]
+
+now = datetime.utcnow()
+version = now.strftime("%Y.%m.%d")
+
+setup(
+ name="circuitpython-stubs",
+ description="PEP 561 type stubs for CircuitPython",
+ url="https://github.com/adafruit/circuitpython",
+ maintainer="CircuitPythonistas",
+ author_email="circuitpython@adafruit.com",
+ version=version,
+ license="MIT",
+ package_data={"circuitpython-stubs": stubs},
+ packages=["circuitpython-stubs"],
+ setup_requires=["setuptools>=38.6.0"],
+)
diff --git a/shared-bindings/_pew/PewPew.c b/shared-bindings/_pew/PewPew.c
index d7ae0116d..3ff208761 100644
--- a/shared-bindings/_pew/PewPew.c
+++ b/shared-bindings/_pew/PewPew.c
@@ -96,8 +96,9 @@ STATIC mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args,
mp_raise_TypeError(translate("Row entry must be digitalio.DigitalInOut"));
}
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(rows[i]);
- raise_error_if_deinited(
- common_hal_digitalio_digitalinout_deinited(pin));
+ if (common_hal_digitalio_digitalinout_deinited(pin)) {
+ raise_deinited_error();
+ }
}
for (size_t i = 0; i < cols_size; ++i) {
@@ -105,8 +106,9 @@ STATIC mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args,
mp_raise_TypeError(translate("Column entry must be digitalio.DigitalInOut"));
}
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(cols[i]);
- raise_error_if_deinited(
- common_hal_digitalio_digitalinout_deinited(pin));
+ if (common_hal_digitalio_digitalinout_deinited(pin)) {
+ raise_deinited_error();
+ }
}
if (!MP_OBJ_IS_TYPE(args[ARG_buttons].u_obj,
@@ -115,8 +117,9 @@ STATIC mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args,
}
digitalio_digitalinout_obj_t *buttons = MP_OBJ_TO_PTR(
args[ARG_buttons].u_obj);
- raise_error_if_deinited(
- common_hal_digitalio_digitalinout_deinited(buttons));
+ if (common_hal_digitalio_digitalinout_deinited(buttons)) {
+ raise_deinited_error();
+ }
pew_obj_t *pew = MP_STATE_VM(pew_singleton);
if (!pew) {
diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c
index 7c2766aa3..420720e62 100644
--- a/shared-bindings/_pixelbuf/PixelBuf.c
+++ b/shared-bindings/_pixelbuf/PixelBuf.c
@@ -51,7 +51,7 @@ extern const int32_t colorwheel(float pos);
//|
//| :class:`~_pixelbuf.PixelBuf` implements an RGB[W] bytearray abstraction.
//|
-//| .. class:: PixelBuf(size, buf, byteorder=BGR, bpp=3)
+//| .. class:: PixelBuf(size, buf, byteorder=BGR, brightness=0, rawbuf=None, offset=0, dotstar=False, auto_write=False, write_function=None, write_args=None)
//|
//| Create a PixelBuf object of the specified size, byteorder, and bits per pixel.
//|
@@ -66,14 +66,14 @@ extern const int32_t colorwheel(float pos);
//|
//| :param ~int size: Number of pixelsx
//| :param ~bytearray buf: Bytearray to store pixel data in
-//| :param ~_pixelbuf.ByteOrder byteorder: Byte order constant from `_pixelbuf` (also sets the bpp)
+//| :param ~_pixelbuf.ByteOrder byteorder: Byte order constant from `_pixelbuf`
//| :param ~float brightness: Brightness (0 to 1.0, default 1.0)
//| :param ~bytearray rawbuf: Bytearray to store raw pixel colors in
//| :param ~int offset: Offset from start of buffer (default 0)
//| :param ~bool dotstar: Dotstar mode (default False)
//| :param ~bool auto_write: Whether to automatically write pixels (Default False)
//| :param ~callable write_function: (optional) Callable to use to send pixels
-//| :param ~list write_args: (optional) Tuple or list of args to pass to ``write_function``. The
+//| :param ~list write_args: (optional) Tuple or list of args to pass to ``write_function``. The
//| PixelBuf instance is appended after these args.
//|
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) {
@@ -95,7 +95,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_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);
- if (mp_obj_is_subclass_fast(args[ARG_byteorder].u_obj, &pixelbuf_byteorder_type))
+ if (mp_obj_is_subclass_fast(args[ARG_byteorder].u_obj, &pixelbuf_byteorder_type))
mp_raise_TypeError_varg(translate("byteorder is not an instance of ByteOrder (got a %s)"), mp_obj_get_type_str(args[ARG_byteorder].u_obj));
pixelbuf_byteorder_obj_t *byteorder = (args[ARG_byteorder].u_obj == mp_const_none) ? MP_OBJ_FROM_PTR(&byteorder_BGR) : args[ARG_byteorder].u_obj;
@@ -122,7 +122,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_a
if (!MP_OBJ_IS_TYPE(args[ARG_write_args].u_obj, &mp_type_list) &&
!MP_OBJ_IS_TYPE(args[ARG_write_args].u_obj, &mp_type_tuple) &&
- args[ARG_write_args].u_obj != mp_const_none)
+ args[ARG_write_args].u_obj != mp_const_none)
{
mp_raise_ValueError(translate("write_args must be a list, tuple, or None"));
}
@@ -186,8 +186,8 @@ STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_a
else if (self->brightness > 1)
self->brightness = 1;
}
-
- if (self->dotstar_mode) {
+
+ if (self->dotstar_mode) {
// Initialize the buffer with the dotstar start bytes.
// Header and end must be setup by caller
for (uint i = 0; i < self->pixels * 4; i += 4) {
@@ -197,7 +197,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_a
}
}
}
-
+
return MP_OBJ_FROM_PTR(self);
}
@@ -227,7 +227,7 @@ const mp_obj_property_t pixelbuf_pixelbuf_bpp_obj = {
//| setting this value causes a recomputation of the values in buf.
//| If only a buf was provided, then the brightness only applies to
//| future pixel changes.
-//| In DotStar mode
+//| In DotStar mode
//|
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_brightness(mp_obj_t self_in) {
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
@@ -266,7 +266,7 @@ void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self) {
// Compensate for shifted buffer (bpp=3 dotstar)
for (uint i = 0; i < self->bytes; i++) {
// Don't adjust per-pixel luminance bytes in dotstar mode
- if (!self->dotstar_mode || (i % 4 != 0))
+ if (!self->dotstar_mode || (i % 4 != 0))
buf[i] = rawbuf[i] * self->brightness;
}
}
@@ -367,11 +367,13 @@ void call_write_function(pixelbuf_pixelbuf_obj_t *self) {
}
}
-
-
-//| .. method:: []
+//| .. method:: __getitem__(index)
+//|
+//| Returns the pixel value at the given index.
//|
-//| Get or set pixels. Supports individual pixels and slices.
+//| .. method:: __setitem__(index, value)
+//|
+//| Sets the pixel value at the given index.
//|
STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
@@ -380,7 +382,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
// delete item
// slice deletion
return MP_OBJ_NULL; // op not supported
- }
+ }
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (0) {
@@ -390,7 +392,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
if (!mp_seq_get_fast_slice_indexes(self->bytes, index_in, &slice))
mp_raise_NotImplementedError(translate("Only slices with step=1 (aka None) are supported"));
- if ((slice.stop * self->pixel_step) > self->bytes)
+ if ((slice.stop * self->pixel_step) > self->bytes)
mp_raise_IndexError(translate("Range out of bounds"));
if (value == MP_OBJ_SENTINEL) { // Get
@@ -422,8 +424,8 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
for (size_t i = slice.start; i < slice.stop; i++) {
mp_obj_t *item = src_objs[i-slice.start];
if (MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple) || MP_OBJ_IS_INT(value)) {
- pixelbuf_set_pixel(self->buf + (i * self->pixel_step),
- self->two_buffers ? self->rawbuf + (i * self->pixel_step) : NULL,
+ pixelbuf_set_pixel(self->buf + (i * self->pixel_step),
+ self->two_buffers ? self->rawbuf + (i * self->pixel_step) : NULL,
self->brightness, item, &self->byteorder, self->dotstar_mode);
}
}
@@ -438,14 +440,14 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
} else { // Single index rather than slice.
size_t index = mp_get_index(self->base.type, self->pixels, index_in, false);
size_t offset = (index * self->pixel_step);
- if (offset > self->bytes)
+ if (offset > self->bytes)
mp_raise_IndexError(translate("Pixel beyond bounds of buffer"));
if (value == MP_OBJ_SENTINEL) { // Get
uint8_t *pixelstart = (uint8_t *)(self->two_buffers ? self->rawbuf : self->buf) + offset;
return pixelbuf_get_pixel(pixelstart, &self->byteorder, self->dotstar_mode);
} else { // Store
- pixelbuf_set_pixel(self->buf + offset, self->two_buffers ? self->rawbuf + offset : NULL,
+ pixelbuf_set_pixel(self->buf + offset, self->two_buffers ? self->rawbuf + offset : NULL,
self->brightness, value, &self->byteorder, self->dotstar_mode);
if (self->auto_write)
call_write_function(self);
diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c
index 31defc7fb..48b9f1cef 100644
--- a/shared-bindings/_pixelbuf/__init__.c
+++ b/shared-bindings/_pixelbuf/__init__.c
@@ -53,7 +53,7 @@
//|
//| PixelBuf
-//| .. class:: ByteOrder
+//| .. class:: ByteOrder()
//|
//| Classes representing byteorders for circuitpython
@@ -169,34 +169,34 @@ const int32_t colorwheel(float pos) {
/// RGB
-//| .. class:: RGB
+//| .. data:: RGB
//|
//| * **order** Red, Green, Blue
//| * **bpp** 3
PIXELBUF_BYTEORDER(RGB, 3, 0, 1, 2, 3, false, false)
-//| .. class:: RBG
+//| .. data:: RBG
//|
//| * **order** Red, Blue, Green
//| * **bpp** 3
PIXELBUF_BYTEORDER(RBG, 3, 0, 2, 1, 3, false, false)
-//| .. class:: GRB
+//| .. data:: GRB
//|
//| * **order** Green, Red, Blue
//| * **bpp** 3
//|
//| Commonly used by NeoPixel.
PIXELBUF_BYTEORDER(GRB, 3, 1, 0, 2, 3, false, false)
-//| .. class:: GBR
+//| .. data:: GBR
//|
//| * **order** Green, Blue, Red
//| * **bpp** 3
PIXELBUF_BYTEORDER(GBR, 3, 1, 2, 0, 3, false, false)
-//| .. class:: BRG
+//| .. data:: BRG
//|
//| * **order** Blue, Red, Green
//| * **bpp** 3
PIXELBUF_BYTEORDER(BRG, 3, 2, 0, 1, 3, false, false)
-//| .. class:: BGR
+//| .. data:: BGR
//|
//| * **order** Blue, Green, Red
//| * **bpp** 3
@@ -205,19 +205,19 @@ PIXELBUF_BYTEORDER(BRG, 3, 2, 0, 1, 3, false, false)
PIXELBUF_BYTEORDER(BGR, 3, 2, 1, 0, 3, false, false)
// RGBW
-//| .. class:: RGBW
+//| .. data:: RGBW
//|
//| * **order** Red, Green, Blue, White
//| * **bpp** 4
//| * **has_white** True
PIXELBUF_BYTEORDER(RGBW, 4, 0, 1, 2, 3, true, false)
-//| .. class:: RBGW
+//| .. data:: RBGW
//|
//| * **order** Red, Blue, Green, White
//| * **bpp** 4
//| * **has_white** True
PIXELBUF_BYTEORDER(RBGW, 4, 0, 2, 1, 3, true, false)
-//| .. class:: GRBW
+//| .. data:: GRBW
//|
//| * **order** Green, Red, Blue, White
//| * **bpp** 4
@@ -225,19 +225,19 @@ PIXELBUF_BYTEORDER(RBGW, 4, 0, 2, 1, 3, true, false)
//|
//| Commonly used by RGBW NeoPixels.
PIXELBUF_BYTEORDER(GRBW, 4, 1, 0, 2, 3, true, false)
-//| .. class:: GBRW
+//| .. data:: GBRW
//|
//| * **order** Green, Blue, Red, White
//| * **bpp** 4
//| * **has_white** True
PIXELBUF_BYTEORDER(GBRW, 4, 1, 2, 0, 3, true, false)
-//| .. class:: BRGW
+//| .. data:: BRGW
//|
//| * **order** Blue, Red, Green, White
//| * **bpp** 4
//| * **has_white** True
PIXELBUF_BYTEORDER(BRGW, 4, 2, 0, 1, 3, true, false)
-//| .. class:: BGRW
+//| .. data:: BGRW
//|
//| * **order** Blue, Green, Red, White
//| * **bpp** 4
@@ -248,37 +248,37 @@ PIXELBUF_BYTEORDER(BGRW, 4, 2, 1, 0, 3, true, false)
// Luminosity chosen because the luminosity of a Dotstar at full bright
// burns the eyes like looking at the Sun.
// https://www.thesaurus.com/browse/luminosity?s=t
-//| .. class:: LRGB
+//| .. data:: LRGB
//|
//| * **order** *Luminosity*, Red, Green, Blue
//| * **bpp** 4
//| * **has_luminosity** True
PIXELBUF_BYTEORDER(LRGB, 4, 1, 2, 3, 0, false, true)
-//| .. class:: LRBG
+//| .. data:: LRBG
//|
//| * **order** *Luminosity*, Red, Blue, Green
//| * **bpp** 4
//| * **has_luminosity** True
PIXELBUF_BYTEORDER(LRBG, 4, 1, 3, 2, 0, false, true)
-//| .. class:: LGRB
+//| .. data:: LGRB
//|
//| * **order** *Luminosity*, Green, Red, Blue
//| * **bpp** 4
//| * **has_luminosity** True
PIXELBUF_BYTEORDER(LGRB, 4, 2, 1, 3, 0, false, true)
-//| .. class:: LGBR
+//| .. data:: LGBR
//|
//| * **order** *Luminosity*, Green, Blue, Red
//| * **bpp** 4
//| * **has_luminosity** True
PIXELBUF_BYTEORDER(LGBR, 4, 2, 3, 1, 0, false, true)
-//| .. class:: LBRG
+//| .. data:: LBRG
//|
//| * **order** *Luminosity*, Blue, Red, Green
//| * **bpp** 4
//| * **has_luminosity** True
PIXELBUF_BYTEORDER(LBRG, 4, 3, 1, 2, 0, false, true)
-//| .. class:: LBGR
+//| .. data:: LBGR
//|
//| * **order** *Luminosity*, Blue, Green, Red
//| * **bpp** 4
diff --git a/shared-bindings/analogio/AnalogIn.c b/shared-bindings/analogio/AnalogIn.c
index 116f82a03..a8bbbf59a 100644
--- a/shared-bindings/analogio/AnalogIn.c
+++ b/shared-bindings/analogio/AnalogIn.c
@@ -86,6 +86,11 @@ STATIC mp_obj_t analogio_analogin_deinit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(analogio_analogin_deinit_obj, analogio_analogin_deinit);
+STATIC void check_for_deinit(analogio_analogin_obj_t *self) {
+ if (common_hal_analogio_analogin_deinited(self)) {
+ raise_deinited_error();
+ }
+}
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -113,7 +118,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogin___exit___obj, 4, 4,
//|
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);
- raise_error_if_deinited(common_hal_analogio_analogin_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_analogio_analogin_get_value(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(analogio_analogin_get_value_obj, analogio_analogin_obj_get_value);
@@ -132,7 +137,7 @@ const mp_obj_property_t analogio_analogin_value_obj = {
//|
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);
- raise_error_if_deinited(common_hal_analogio_analogin_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_float(common_hal_analogio_analogin_get_reference_voltage(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(analogio_analogin_get_reference_voltage_obj,
diff --git a/shared-bindings/analogio/AnalogOut.c b/shared-bindings/analogio/AnalogOut.c
index dcbd7ecfb..0816da465 100644
--- a/shared-bindings/analogio/AnalogOut.c
+++ b/shared-bindings/analogio/AnalogOut.c
@@ -112,7 +112,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogout___exit___obj, 4, 4
//| 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);
- raise_error_if_deinited(common_hal_analogio_analogout_deinited(self));
+ if (common_hal_analogio_analogout_deinited(self)) {
+ raise_deinited_error();
+ }
uint32_t v = mp_obj_get_int(value);
if (v >= (1 << 16)) {
mp_raise_ValueError(translate("AnalogOut is only 16 bits. Value must be less than 65536."));
diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c
index 48424d073..980f11392 100644
--- a/shared-bindings/audiobusio/I2SOut.c
+++ b/shared-bindings/audiobusio/I2SOut.c
@@ -134,6 +134,11 @@ STATIC mp_obj_t audiobusio_i2sout_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_deinit_obj, audiobusio_i2sout_deinit);
+STATIC void check_for_deinit(audiobusio_i2sout_obj_t *self) {
+ if (common_hal_audiobusio_i2sout_deinited(self)) {
+ raise_deinited_error();
+ }
+}
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -169,7 +174,7 @@ STATIC mp_obj_t audiobusio_i2sout_obj_play(size_t n_args, const mp_obj_t *pos_ar
{ MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_audiobusio_i2sout_deinited(self));
+ check_for_deinit(self);
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);
@@ -186,7 +191,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audiobusio_i2sout_play_obj, 1, audiobusio_i2sout_obj_
//|
STATIC mp_obj_t audiobusio_i2sout_obj_stop(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audiobusio_i2sout_deinited(self));
+ check_for_deinit(self);
common_hal_audiobusio_i2sout_stop(self);
return mp_const_none;
}
@@ -198,7 +203,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_stop_obj, audiobusio_i2sout_obj_stop
//|
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);
- raise_error_if_deinited(common_hal_audiobusio_i2sout_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_audiobusio_i2sout_get_playing(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_get_playing_obj, audiobusio_i2sout_obj_get_playing);
@@ -216,7 +221,7 @@ const mp_obj_property_t audiobusio_i2sout_playing_obj = {
//|
STATIC mp_obj_t audiobusio_i2sout_obj_pause(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audiobusio_i2sout_deinited(self));
+ check_for_deinit(self);
if (!common_hal_audiobusio_i2sout_get_playing(self)) {
mp_raise_RuntimeError(translate("Not playing"));
@@ -232,7 +237,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_pause_obj, audiobusio_i2sout_obj_pau
//|
STATIC mp_obj_t audiobusio_i2sout_obj_resume(mp_obj_t self_in) {
audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audiobusio_i2sout_deinited(self));
+ check_for_deinit(self);
if (common_hal_audiobusio_i2sout_get_paused(self)) {
common_hal_audiobusio_i2sout_resume(self);
@@ -248,7 +253,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_resume_obj, audiobusio_i2sout_obj_re
//|
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);
- raise_error_if_deinited(common_hal_audiobusio_i2sout_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_audiobusio_i2sout_get_paused(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_get_paused_obj, audiobusio_i2sout_obj_get_paused);
diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c
index 5dca3fa59..0c92c2478 100644
--- a/shared-bindings/audiobusio/PDMIn.c
+++ b/shared-bindings/audiobusio/PDMIn.c
@@ -43,7 +43,7 @@
//|
//| 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)
+//| .. 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
@@ -156,6 +156,11 @@ STATIC mp_obj_t audiobusio_pdmin_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_pdmin_deinit_obj, audiobusio_pdmin_deinit);
+STATIC void check_for_deinit(audiobusio_pdmin_obj_t *self) {
+ if (common_hal_audiobusio_pdmin_deinited(self)) {
+ raise_deinited_error();
+ }
+}
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -188,7 +193,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4,
//|
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);
- raise_error_if_deinited(common_hal_audiobusio_pdmin_deinited(self));
+ check_for_deinit(self);
if (!MP_OBJ_IS_SMALL_INT(destination_length) || MP_OBJ_SMALL_INT_VALUE(destination_length) < 0) {
mp_raise_TypeError(translate("destination_length must be an int >= 0"));
}
@@ -223,7 +228,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(audiobusio_pdmin_record_obj, audiobusio_pdmin_obj_reco
//|
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);
- raise_error_if_deinited(common_hal_audiobusio_pdmin_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_audiobusio_pdmin_get_sample_rate(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_pdmin_get_sample_rate_obj, audiobusio_pdmin_obj_get_sample_rate);
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index 9cb98d1f8..571dcdaca 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -133,6 +133,11 @@ STATIC mp_obj_t audioio_audioout_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_deinit_obj, audioio_audioout_deinit);
+STATIC void check_for_deinit(audioio_audioout_obj_t *self) {
+ if (common_hal_audioio_audioout_deinited(self)) {
+ raise_deinited_error();
+ }
+}
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -170,7 +175,7 @@ STATIC mp_obj_t audioio_audioout_obj_play(size_t n_args, const mp_obj_t *pos_arg
{ MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_audioio_audioout_deinited(self));
+ check_for_deinit(self);
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);
@@ -187,7 +192,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audioio_audioout_play_obj, 1, audioio_audioout_obj_pl
//|
STATIC mp_obj_t audioio_audioout_obj_stop(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audioio_audioout_deinited(self));
+ check_for_deinit(self);
common_hal_audioio_audioout_stop(self);
return mp_const_none;
}
@@ -199,7 +204,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_stop_obj, audioio_audioout_obj_stop);
//|
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);
- raise_error_if_deinited(common_hal_audioio_audioout_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_audioio_audioout_get_playing(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_get_playing_obj, audioio_audioout_obj_get_playing);
@@ -217,7 +222,7 @@ const mp_obj_property_t audioio_audioout_playing_obj = {
//|
STATIC mp_obj_t audioio_audioout_obj_pause(mp_obj_t self_in) {
audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audioio_audioout_deinited(self));
+ check_for_deinit(self);
if (!common_hal_audioio_audioout_get_playing(self)) {
mp_raise_RuntimeError(translate("Not playing"));
@@ -233,7 +238,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_pause_obj, audioio_audioout_obj_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);
- raise_error_if_deinited(common_hal_audioio_audioout_deinited(self));
+ check_for_deinit(self);
if (common_hal_audioio_audioout_get_paused(self)) {
common_hal_audioio_audioout_resume(self);
@@ -249,7 +254,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_resume_obj, audioio_audioout_obj_resu
//|
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);
- raise_error_if_deinited(common_hal_audioio_audioout_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_audioio_audioout_get_paused(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_get_paused_obj, audioio_audioout_obj_get_paused);
diff --git a/shared-bindings/audioio/Mixer.c b/shared-bindings/audioio/Mixer.c
index 43ef2c524..dce4b3955 100644
--- a/shared-bindings/audioio/Mixer.c
+++ b/shared-bindings/audioio/Mixer.c
@@ -121,6 +121,12 @@ STATIC mp_obj_t audioio_mixer_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_deinit_obj, audioio_mixer_deinit);
+STATIC void check_for_deinit(audioio_mixer_obj_t *self) {
+ if (common_hal_audioio_mixer_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -157,7 +163,7 @@ STATIC mp_obj_t audioio_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args,
{ MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ check_for_deinit(self);
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);
@@ -178,7 +184,7 @@ STATIC mp_obj_t audioio_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_
{ MP_QSTR_voice, MP_ARG_INT, {.u_int = 0} },
};
audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ check_for_deinit(self);
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);
@@ -193,7 +199,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_stop_voice_obj, 1, audioio_mixer_obj_st
//|
STATIC mp_obj_t audioio_mixer_obj_get_playing(mp_obj_t self_in) {
audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_audioio_mixer_get_playing(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_playing_obj, audioio_mixer_obj_get_playing);
@@ -211,7 +217,7 @@ const mp_obj_property_t audioio_mixer_playing_obj = {
//|
STATIC mp_obj_t audioio_mixer_obj_get_sample_rate(mp_obj_t self_in) {
audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_mixer_get_sample_rate(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_sample_rate_obj, audioio_mixer_obj_get_sample_rate);
diff --git a/shared-bindings/audioio/RawSample.c b/shared-bindings/audioio/RawSample.c
index 7fc896449..62998f580 100644
--- a/shared-bindings/audioio/RawSample.c
+++ b/shared-bindings/audioio/RawSample.c
@@ -115,6 +115,12 @@ STATIC mp_obj_t audioio_rawsample_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_rawsample_deinit_obj, audioio_rawsample_deinit);
+STATIC void check_for_deinit(audioio_rawsample_obj_t *self) {
+ if (common_hal_audioio_rawsample_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -142,14 +148,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_rawsample___exit___obj, 4, 4,
//|
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);
- raise_error_if_deinited(common_hal_audioio_rawsample_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_rawsample_get_sample_rate(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_rawsample_get_sample_rate_obj, audioio_rawsample_obj_get_sample_rate);
STATIC mp_obj_t audioio_rawsample_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audioio_rawsample_deinited(self));
+ check_for_deinit(self);
common_hal_audioio_rawsample_set_sample_rate(self, mp_obj_get_int(sample_rate));
return mp_const_none;
}
diff --git a/shared-bindings/audioio/WaveFile.c b/shared-bindings/audioio/WaveFile.c
index cddeef769..242c915d3 100644
--- a/shared-bindings/audioio/WaveFile.c
+++ b/shared-bindings/audioio/WaveFile.c
@@ -41,11 +41,11 @@
//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
//| be 8 bit unsigned or 16 bit signed.
//|
-//| .. class:: WaveFile(filename)
+//| .. class:: WaveFile(file)
//|
//| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
-//| :param bytes-like file: Already opened wave file
+//| :param typing.BinaryIO file: Already opened wave file
//|
//| Playing a wave file from flash::
//|
@@ -92,6 +92,12 @@ STATIC mp_obj_t audioio_wavefile_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_deinit_obj, audioio_wavefile_deinit);
+STATIC void check_for_deinit(audioio_wavefile_obj_t *self) {
+ if (common_hal_audioio_wavefile_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -118,14 +124,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_wavefile___exit___obj, 4, 4,
//|
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);
- raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_sample_rate(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_sample_rate_obj, audioio_wavefile_obj_get_sample_rate);
STATIC mp_obj_t audioio_wavefile_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self));
+ check_for_deinit(self);
common_hal_audioio_wavefile_set_sample_rate(self, mp_obj_get_int(sample_rate));
return mp_const_none;
}
@@ -144,7 +150,7 @@ const mp_obj_property_t audioio_wavefile_sample_rate_obj = {
//|
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);
- raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_bits_per_sample(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_bits_per_sample_obj, audioio_wavefile_obj_get_bits_per_sample);
@@ -162,7 +168,7 @@ const mp_obj_property_t audioio_wavefile_bits_per_sample_obj = {
//|
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);
- raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_channel_count(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_channel_count_obj, audioio_wavefile_obj_get_channel_count);
diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c
index 374268e3d..0a3b03f51 100644
--- a/shared-bindings/bitbangio/I2C.c
+++ b/shared-bindings/bitbangio/I2C.c
@@ -42,7 +42,7 @@
//| :class:`I2C` --- Two wire serial protocol
//| ------------------------------------------
//|
-//| .. class:: I2C(scl, sda, \*, frequency=400000)
+//| .. class:: I2C(scl, sda, *, frequency=400000, timeout)
//|
//| 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
@@ -69,13 +69,12 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args,
const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
bitbangio_i2c_obj_t *self = m_new_obj(bitbangio_i2c_obj_t);
- raise_error_if_deinited(shared_module_bitbangio_i2c_deinited(self));
self->base.type = &bitbangio_i2c_type;
shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int);
return (mp_obj_t)self;
}
-//| .. method:: I2C.deinit()
+//| .. method:: deinit()
//|
//| Releases control of the underlying hardware so other classes can use it.
//|
@@ -86,13 +85,19 @@ STATIC mp_obj_t bitbangio_i2c_obj_deinit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_deinit_obj, bitbangio_i2c_obj_deinit);
-//| .. method:: I2C.__enter__()
+STATIC void check_for_deinit(bitbangio_i2c_obj_t *self) {
+ if (shared_module_bitbangio_i2c_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| .. method:: __enter__()
//|
//| No-op used in Context Managers.
//|
// Provided by context manager helper.
-//| .. method:: I2C.__exit__()
+//| .. method:: __exit__()
//|
//| Automatically deinitializes the hardware on context exit. See
//| :ref:`lifetime-and-contextmanagers` for more info.
@@ -110,7 +115,7 @@ static void check_lock(bitbangio_i2c_obj_t *self) {
}
}
-//| .. method:: I2C.scan()
+//| .. 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
@@ -118,7 +123,7 @@ static void check_lock(bitbangio_i2c_obj_t *self) {
//|
STATIC mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) {
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(shared_module_bitbangio_i2c_deinited(self));
+ check_for_deinit(self);
check_lock(self);
mp_obj_t list = mp_obj_new_list(0, NULL);
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
@@ -132,30 +137,30 @@ 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:: I2C.try_lock()
+//| .. method:: try_lock()
//|
//| 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);
- raise_error_if_deinited(shared_module_bitbangio_i2c_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(shared_module_bitbangio_i2c_try_lock(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_try_lock_obj, bitbangio_i2c_obj_try_lock);
-//| .. method:: I2C.unlock()
+//| .. method:: unlock()
//|
//| 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);
- raise_error_if_deinited(shared_module_bitbangio_i2c_deinited(self));
+ check_for_deinit(self);
shared_module_bitbangio_i2c_unlock(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
-//| .. method:: I2C.readfrom_into(address, buffer, \*, start=0, end=len(buffer))
+//| .. 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``.
@@ -179,7 +184,7 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(shared_module_bitbangio_i2c_deinited(self));
+ check_for_deinit(self);
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);
check_lock(self);
@@ -203,7 +208,7 @@ 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:: I2C.writeto(address, buffer, \*, start=0, end=len(buffer), stop=True)
+//| .. 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 if ``stop`` is set.
@@ -232,7 +237,7 @@ STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, m
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(shared_module_bitbangio_i2c_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
diff --git a/shared-bindings/bitbangio/OneWire.c b/shared-bindings/bitbangio/OneWire.c
index a3c53d2a5..73bedcd8d 100644
--- a/shared-bindings/bitbangio/OneWire.c
+++ b/shared-bindings/bitbangio/OneWire.c
@@ -91,6 +91,12 @@ STATIC mp_obj_t bitbangio_onewire_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_onewire_deinit_obj, bitbangio_onewire_deinit);
+STATIC void check_for_deinit(bitbangio_onewire_obj_t *self) {
+ if (shared_module_bitbangio_onewire_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -115,7 +121,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_onewire___exit___obj, 4, 4,
//|
STATIC mp_obj_t bitbangio_onewire_obj_reset(mp_obj_t self_in) {
bitbangio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(shared_module_bitbangio_onewire_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(shared_module_bitbangio_onewire_reset(self));
}
@@ -130,7 +136,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_onewire_reset_obj, bitbangio_onewire_obj_res
//|
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);
- raise_error_if_deinited(shared_module_bitbangio_onewire_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(shared_module_bitbangio_onewire_read_bit(self));
}
@@ -142,7 +148,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_onewire_read_bit_obj, bitbangio_onewire_obj_
//|
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);
- raise_error_if_deinited(shared_module_bitbangio_onewire_deinited(self));
+ check_for_deinit(self);
shared_module_bitbangio_onewire_write_bit(self, mp_obj_is_true(bool_obj));
return mp_const_none;
diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c
index 974ec99e2..88bd3d6cb 100644
--- a/shared-bindings/bitbangio/SPI.c
+++ b/shared-bindings/bitbangio/SPI.c
@@ -84,7 +84,7 @@ STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args,
return (mp_obj_t)self;
}
-//| .. method:: SPI.deinit()
+//| .. method:: deinit()
//|
//| Turn off the SPI bus.
//|
@@ -95,13 +95,19 @@ STATIC mp_obj_t bitbangio_spi_obj_deinit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_deinit_obj, bitbangio_spi_obj_deinit);
-//| .. method:: SPI.__enter__()
+STATIC void check_for_deinit(bitbangio_spi_obj_t *self) {
+ if (shared_module_bitbangio_spi_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
//|
// Provided by context manager helper.
-//| .. method:: SPI.__exit__()
+//| .. method:: __exit__()
//|
//| Automatically deinitializes the hardware when exiting a context. See
//| :ref:`lifetime-and-contextmanagers` for more info.
@@ -120,7 +126,7 @@ static void check_lock(bitbangio_spi_obj_t *self) {
}
}
-//| .. method:: SPI.configure(\*, baudrate=100000, polarity=0, phase=0, bits=8)
+//| .. method:: configure(*, baudrate=100000, polarity=0, phase=0, bits=8)
//|
//| Configures the SPI bus. Only valid when locked.
//|
@@ -139,7 +145,7 @@ STATIC mp_obj_t bitbangio_spi_configure(size_t n_args, const mp_obj_t *pos_args,
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
@@ -162,7 +168,7 @@ 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:: SPI.try_lock()
+//| .. method:: try_lock()
//|
//| Attempts to grab the SPI lock. Returns True on success.
//|
@@ -171,24 +177,24 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_configure_obj, 1, bitbangio_spi_configu
//|
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);
- raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(shared_module_bitbangio_spi_try_lock(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_try_lock_obj, bitbangio_spi_obj_try_lock);
-//| .. method:: SPI.unlock()
+//| .. method:: unlock()
//|
//| 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);
- raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
+ check_for_deinit(self);
shared_module_bitbangio_spi_unlock(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock);
-//| .. method:: SPI.write(buf)
+//| .. method:: write(buf)
//|
//| Write the data contained in ``buf``. Requires the SPI being locked.
//| If the buffer is empty, nothing happens.
@@ -196,7 +202,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock);
// 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) {
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
+ check_for_deinit(self);
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
if (src.len == 0) {
@@ -212,7 +218,7 @@ 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:: SPI.readinto(buf)
+//| .. method:: readinto(buf)
//|
//| Read into the buffer specified by ``buf`` while writing zeroes.
//| Requires the SPI being locked.
@@ -221,7 +227,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_spi_write_obj, bitbangio_spi_write);
// 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) {
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
+ check_for_deinit(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
if (bufinfo.len == 0) {
@@ -236,7 +242,7 @@ 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:: SPI.write_readinto(buffer_out, buffer_in, \*, out_start=0, out_end=len(buffer_out), in_start=0, in_end=len(buffer_in))
+//| .. 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]``
@@ -246,9 +252,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_spi_readinto_obj, 2, 2, bitbangio_
//| :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
+//| :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
+//| :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 };
@@ -261,7 +267,7 @@ STATIC mp_obj_t bitbangio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
+ check_for_deinit(self);
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);
diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c
index 226c011a3..7367da535 100644
--- a/shared-bindings/bleio/Address.c
+++ b/shared-bindings/bleio/Address.c
@@ -33,13 +33,6 @@
#include "shared-bindings/bleio/Address.h"
#include "shared-module/bleio/Address.h"
-#define ADDRESS_BYTE_LEN 12
-
-STATIC uint8_t xdigit_8b_value(byte nibble1, byte nibble2) {
- return unichar_xdigit_value(nibble1) | (unichar_xdigit_value(nibble2) << 4);
-}
-
-
//| .. currentmodule:: bleio
//|
//| :class:`Address` -- BLE address
@@ -48,30 +41,24 @@ STATIC uint8_t xdigit_8b_value(byte nibble1, byte nibble2) {
//| Encapsulates the address of a BLE device.
//|
-//| .. class:: Address(address)
+//| .. class:: Address(address, address_type)
//|
//| Create a new Address object encapsulating the address value.
//| The value itself can be one of:
//|
-//| :param buf: The address value to encapsulate
-//| - a buffer object (bytearray, bytes) of 6 bytes
-//|
-//| :param address: The address to encapsulate
+//| :param buf address: The address value to encapsulate. A buffer object (bytearray, bytes) of 6 bytes.
+//| :param int address_type: one of these integers:
+//| - `bleio.Address.PUBLIC` = 0
+//| - `bleio.Address.RANDOM_STATIC` = 1
+//| - `bleio.Address.RANDOM_PRIVATE_RESOLVABLE` = 2
+//| - `bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE` = 3
//|
-//| .. attribute:: type
-//|
-//| The address type. One of:
-//|
-//| - `bleio.AddressType.PUBLIC`
-//| - `bleio.AddressType.RANDOM_STATIC`
-//| - `bleio.AddressType.RANDOM_PRIVATE_RESOLVABLE`
-//| - `bleio.AddressType.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 };
+ enum { ARG_address, ARG_address_type };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_address, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_address_type, MP_ARG_INT, {.u_int = BLEIO_ADDRESS_TYPE_PUBLIC } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -79,44 +66,54 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
bleio_address_obj_t *self = m_new_obj(bleio_address_obj_t);
self->base.type = &bleio_address_type;
- self->type = ADDRESS_PUBLIC;
const mp_obj_t address = args[ARG_address].u_obj;
-
mp_buffer_info_t buf_info;
mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
- if (buf_info.len != BLEIO_ADDRESS_BYTES) {
- mp_raise_ValueError_varg(translate("Address must be %d bytes long"), BLEIO_ADDRESS_BYTES);
+ if (buf_info.len != NUM_BLEIO_ADDRESS_BYTES) {
+ mp_raise_ValueError_varg(translate("Address must be %d bytes long"), NUM_BLEIO_ADDRESS_BYTES);
}
- for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) {
- self->value[BLEIO_ADDRESS_BYTES - b - 1] = ((uint8_t*)buf_info.buf)[b];
+ memcpy(self->bytes, buf_info.buf, buf_info.len);
+
+ const mp_int_t address_type = args[ARG_address_type].u_int;
+ if (address_type < BLEIO_ADDRESS_TYPE_MIN || address_type > BLEIO_ADDRESS_TYPE_MAX) {
+ mp_raise_ValueError(translate("Address type out of range"));
}
+ self->type = address_type;
+
return MP_OBJ_FROM_PTR(self);
}
-STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+//| .. attribute:: address_bytes
+//|
+//| The bytes that make up the device address (read-only)
+//|
+//| - `bleio.Address.PUBLIC`
+//| - `bleio.Address.RANDOM_STATIC`
+//| - `bleio.Address.RANDOM_PRIVATE_RESOLVABLE`
+//| - `bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE`
+//|
+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);
- mp_printf(print, "Address('%02x:%02x:%02x:%02x:%02x:%02x')",
- self->value[5], self->value[4], self->value[3],
- self->value[2], self->value[1], self->value[0]);
+ return mp_obj_new_bytes(self->bytes, NUM_BLEIO_ADDRESS_BYTES);
}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_address_get_address_bytes_obj, bleio_address_get_address_bytes);
+//| .. attribute:: type
+//|
+//| The address type (read-only). One of these integers:
+//|
+//| - `bleio.Address.PUBLIC`
+//| - `bleio.Address.RANDOM_STATIC`
+//| - `bleio.Address.RANDOM_PRIVATE_RESOLVABLE`
+//| - `bleio.Address.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);
- if (self->type == ADDRESS_PUBLIC) {
- return (mp_obj_t)&bleio_addresstype_public_obj;
- } else if (self->type == ADDRESS_RANDOM_STATIC) {
- return (mp_obj_t)&bleio_addresstype_random_static_obj;
- } else if (self->type == ADDRESS_RANDOM_PRIVATE_RESOLVABLE) {
- return (mp_obj_t)&bleio_addresstype_random_private_resolvable_obj;
- } else if (self->type == ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE) {
- return (mp_obj_t)&bleio_addresstype_random_private_non_resolvable_obj;
- }
-
- return mp_const_none;
+ return MP_OBJ_NEW_SMALL_INT(self->type);
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_address_get_type_obj, bleio_address_get_type);
@@ -128,7 +125,14 @@ const mp_obj_property_t bleio_address_type_obj = {
};
STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) },
+ { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_get_address_bytes_obj) },
+ { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_get_type_obj) },
+ // These match the BLE_GAP_ADDR_TYPES values used by the nRF library.
+ { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_OBJ_NEW_SMALL_INT(0) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_OBJ_NEW_SMALL_INT(1) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(2) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(3) },
+
};
STATIC MP_DEFINE_CONST_DICT(bleio_address_locals_dict, bleio_address_locals_dict_table);
@@ -136,7 +140,6 @@ STATIC MP_DEFINE_CONST_DICT(bleio_address_locals_dict, bleio_address_locals_dict
const mp_obj_type_t bleio_address_type = {
{ &mp_type_type },
.name = MP_QSTR_Address,
- .print = bleio_address_print,
.make_new = bleio_address_make_new,
.locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict
};
diff --git a/shared-bindings/bleio/Address.h b/shared-bindings/bleio/Address.h
index 9c9e20968..ef84d7432 100644
--- a/shared-bindings/bleio/Address.h
+++ b/shared-bindings/bleio/Address.h
@@ -29,6 +29,14 @@
#include "py/objtype.h"
+#define BLEIO_ADDRESS_TYPE_PUBLIC (0)
+#define BLEIO_ADDRESS_TYPE_RANDOM_STATIC (1)
+#define BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_RESOLVABLE (2)
+#define BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE (3)
+
+#define BLEIO_ADDRESS_TYPE_MIN BLEIO_ADDRESS_TYPE_PUBLIC
+#define BLEIO_ADDRESS_TYPE_MAX BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
+
extern const mp_obj_type_t bleio_address_type;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H
diff --git a/shared-bindings/bleio/AddressType.c b/shared-bindings/bleio/AddressType.c
deleted file mode 100644
index cf2151c94..000000000
--- a/shared-bindings/bleio/AddressType.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * This file is part of the Micro Python project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Artur Pacholec
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "shared-bindings/bleio/AddressType.h"
-
-//| .. currentmodule:: bleio
-//|
-//| :class:`AddressType` -- defines the type of a BLE address
-//| =============================================================
-//|
-//| .. class:: bleio.AddressType
-//|
-//| Enum-like class to define the type of a BLE address, see also `bleio.Address`.
-//|
-//| .. data:: PUBLIC
-//|
-//| The address is public
-//|
-//| .. data:: RANDOM_STATIC
-//|
-//| The address is random static
-//|
-//| .. data:: RANDOM_PRIVATE_RESOLVABLE
-//|
-//| The address is random private resolvable
-//|
-//| .. data:: RANDOM_PRIVATE_NON_RESOLVABLE
-//|
-//| The address is private non-resolvable
-//|
-const mp_obj_type_t bleio_addresstype_type;
-
-const bleio_addresstype_obj_t bleio_addresstype_public_obj = {
- { &bleio_addresstype_type },
-};
-
-const bleio_addresstype_obj_t bleio_addresstype_random_static_obj = {
- { &bleio_addresstype_type },
-};
-
-const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj = {
- { &bleio_addresstype_type },
-};
-
-const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj = {
- { &bleio_addresstype_type },
-};
-
-STATIC const mp_rom_map_elem_t bleio_addresstype_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_PTR(&bleio_addresstype_public_obj) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_PTR(&bleio_addresstype_random_static_obj) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(bleio_addresstype_locals_dict, bleio_addresstype_locals_dict_table);
-
-STATIC void bleio_addresstype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- qstr type = MP_QSTR_PUBLIC;
-
- if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_static_obj)) {
- type = MP_QSTR_RANDOM_STATIC;
- } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj)) {
- type = MP_QSTR_RANDOM_PRIVATE_RESOLVABLE;
- } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj)) {
- type = MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE;
- }
-
- mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_AddressType, type);
-}
-
-const mp_obj_type_t bleio_addresstype_type = {
- { &mp_type_type },
- .name = MP_QSTR_AddressType,
- .print = bleio_addresstype_print,
- .locals_dict = (mp_obj_t)&bleio_addresstype_locals_dict,
-};
diff --git a/shared-bindings/bleio/CharacteristicBuffer.c b/shared-bindings/bleio/CharacteristicBuffer.c
index c368de361..a1dc663fd 100644
--- a/shared-bindings/bleio/CharacteristicBuffer.c
+++ b/shared-bindings/bleio/CharacteristicBuffer.c
@@ -47,7 +47,7 @@ STATIC void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self
//|
//| Accumulates a Characteristic's incoming values in a FIFO buffer.
//|
-//| .. class:: CharacteristicBuffer(Characteristic, *, timeout=1, buffer_size=64)
+//| .. class:: CharacteristicBuffer(characteristic, *, timeout=1, buffer_size=64)
//|
//| Create a new Characteristic object identified by the specified UUID.
//|
@@ -92,6 +92,12 @@ STATIC mp_obj_t bleio_characteristic_buffer_make_new(const mp_obj_type_t *type,
return MP_OBJ_FROM_PTR(self);
}
+STATIC void check_for_deinit(bleio_characteristic_buffer_obj_t *self) {
+ if (common_hal_bleio_characteristic_buffer_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
// These are standard stream methods. Code is in py/stream.c.
//
//| .. method:: read(nbytes=None)
@@ -122,7 +128,7 @@ STATIC mp_obj_t bleio_characteristic_buffer_make_new(const mp_obj_type_t *type,
// These three methods are used by the shared stream methods.
STATIC mp_uint_t bleio_characteristic_buffer_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_bleio_characteristic_buffer_deinited(self));
+ check_for_deinit(self);
raise_error_if_not_connected(self);
byte *buf = buf_in;
@@ -141,7 +147,7 @@ STATIC mp_uint_t bleio_characteristic_buffer_write(mp_obj_t self_in, const void
STATIC mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_bleio_characteristic_buffer_deinited(self));
+ check_for_deinit(self);
raise_error_if_not_connected(self);
if (!common_hal_bleio_characteristic_buffer_connected(self)) {
mp_raise_ValueError(translate("Not connected"));
@@ -170,7 +176,7 @@ STATIC mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t r
//|
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);
- raise_error_if_deinited(common_hal_bleio_characteristic_buffer_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_buffer_rx_characters_available(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_buffer_get_in_waiting_obj, bleio_characteristic_buffer_obj_get_in_waiting);
@@ -188,7 +194,7 @@ const mp_obj_property_t bleio_characteristic_buffer_in_waiting_obj = {
//|
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);
- raise_error_if_deinited(common_hal_bleio_characteristic_buffer_deinited(self));
+ check_for_deinit(self);
common_hal_bleio_characteristic_buffer_clear_rx_buffer(self);
return mp_const_none;
}
diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c
index 1d657635f..ca703bd53 100644
--- a/shared-bindings/bleio/Peripheral.c
+++ b/shared-bindings/bleio/Peripheral.c
@@ -35,7 +35,6 @@
#include "py/runtime.h"
#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/AddressType.h"
#include "shared-bindings/bleio/Characteristic.h"
#include "shared-bindings/bleio/Peripheral.h"
#include "shared-bindings/bleio/Service.h"
diff --git a/shared-bindings/bleio/ScanEntry.c b/shared-bindings/bleio/ScanEntry.c
index 67e4a38c0..475bade15 100644
--- a/shared-bindings/bleio/ScanEntry.c
+++ b/shared-bindings/bleio/ScanEntry.c
@@ -43,94 +43,21 @@
//| =========================================================
//|
//| Encapsulates information about a device that was received as a
-//| response to a BLE scan request.
+//| response to a BLE scan request. This object may only be created
+//| by a `bleio.Scanner`: it has no user-visible constructor.
//|
//| .. attribute:: address
//|
-//| The address of the device. (read-only)
-//| This attribute is of type `bleio.Address`.
+//| The address of the device (read-only), of type `bleio.Address`.
//|
-
-//| .. attribute:: manufacturer_specific_data
-//|
-//| The manufacturer-specific data present in the advertisement packet. (read-only)
-//|
-
-//| .. attribute:: name
-//|
-//| The name of the device. (read-only)
-//| Will be be `None` if the data was missing from the advertisement packet.
-//|
-
-//| .. attribute:: raw_data
-//|
-//| All the advertisement data present in the packet. (read-only)
-//|
-
-//| .. attribute:: rssi
-//|
-//| The signal strength of the device at the time of the scan. (read-only)
-//|
-
-//| .. attribute:: service_uuids
-//|
-//| The address of the device. (read-only)
-//| This attribute is a list of `bleio.UUID`.
-//| This attribute might be empty or incomplete, depending on the advertisement packet.
-//| Currently only 16-bit UUIDS are listed.
-//|
-
-//| .. attribute:: tx_power_level
-//|
-//| The transmit power level of the device. (read-only)
-//| Will be `None` if the data was missing from the advertisement packet.
-//|
-static uint8_t find_data_item(mp_obj_array_t *data_in, uint8_t type, uint8_t **data_out) {
- uint16_t i = 0;
- while (i < data_in->len) {
- const uint8_t item_len = ((uint8_t*)data_in->items)[i];
- const uint8_t item_type = ((uint8_t*)data_in->items)[i + 1];
- if (item_type != type) {
- i += (item_len + 1);
- continue;
- }
-
- *data_out = &((uint8_t*)data_in->items)[i + 2];
-
- return item_len;
- }
-
- return 0;
-}
-
-STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in);
-
-STATIC void bleio_scanentry_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- bleio_scanentry_obj_t *self = (bleio_scanentry_obj_t *)self_in;
- mp_printf(print, "ScanEntry(address: %02x:%02x:%02x:%02x:%02x:%02x",
- self->address.value[5], self->address.value[4], self->address.value[3],
- self->address.value[1], self->address.value[1], self->address.value[0]);
-
- const mp_obj_t name_obj = scanentry_get_name(self_in);
- if (name_obj != mp_const_none) {
- mp_obj_str_t *str = MP_OBJ_TO_PTR(name_obj);
- mp_printf(print, " name: %s", str->data);
- }
-
- mp_print_str(print, ")");
-}
-
STATIC mp_obj_t bleio_scanentry_get_address(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, (mp_obj_t)&mp_const_none_obj);
- bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj);
-
+ bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
+ memcpy(address->bytes, self->address.bytes, NUM_BLEIO_ADDRESS_BYTES);
address->type = self->address.type;
- memcpy(address->value, self->address.value, BLEIO_ADDRESS_BYTES);
-
- return obj;
+ return MP_OBJ_TO_PTR(address);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_address_obj, bleio_scanentry_get_address);
@@ -141,75 +68,13 @@ const mp_obj_property_t bleio_scanentry_address_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-STATIC mp_obj_t scanentry_get_manufacturer_specific_data(mp_obj_t self_in) {
- bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
- uint8_t *manuf_data;
-
- const uint8_t manuf_data_len = find_data_item(data, AdManufacturerSpecificData, &manuf_data);
- if (manuf_data_len == 0) {
- return mp_const_none;
- }
-
- return mp_obj_new_bytearray_by_ref(manuf_data_len, manuf_data);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_manufacturer_specific_data_obj, scanentry_get_manufacturer_specific_data);
-
-const mp_obj_property_t bleio_scanentry_manufacturer_specific_data_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&scanentry_get_manufacturer_specific_data_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in) {
- bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
- uint8_t *name;
-
- // Try for Complete but settle for Shortened
- uint8_t name_len = find_data_item(data, AdCompleteLocalName, &name);
- if (name_len == 0) {
- name_len = find_data_item(data, AdShortenedLocalName, &name);
- }
-
- if (name_len == 0) {
- return mp_const_none;
- }
-
- return mp_obj_new_str((const char*)name, name_len - 1);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_name_obj, scanentry_get_name);
-
-const mp_obj_property_t bleio_scanentry_name_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bluepy_scanentry_get_name_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
+//| .. attribute:: raw_data
+//|
+//| All the advertisement data present in the packet, returned as a ``bytes`` object. (read-only)
+//|
STATIC mp_obj_t scanentry_get_raw_data(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- mp_obj_t entries = mp_obj_new_list(0, NULL);
-
- mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
-
- uint16_t i = 0;
- while (i < data->len) {
- mp_obj_tuple_t *entry = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
-
- const uint8_t item_len = ((uint8_t*)data->items)[i];
- const uint8_t item_type = ((uint8_t*)data->items)[i + 1];
-
- entry->items[0] = MP_OBJ_NEW_SMALL_INT(item_type);
- entry->items[1] = mp_obj_new_bytearray(item_len - 1, &((uint8_t*)data->items)[i + 2]);
- mp_obj_list_append(entries, MP_OBJ_FROM_PTR(entry));
-
- i += (item_len + 1);
- }
-
- return entries;
+ return self->data;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_raw_data_obj, scanentry_get_raw_data);
@@ -220,6 +85,10 @@ const mp_obj_property_t bleio_scanentry_raw_data_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)
+//|
STATIC mp_obj_t scanentry_get_rssi(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -234,68 +103,10 @@ const mp_obj_property_t bleio_scanentry_rssi_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-STATIC mp_obj_t scanentry_get_service_uuids(mp_obj_t self_in) {
- bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
- uint8_t *uuids;
-
- // Try for Complete but settle for Incomplete
- uint8_t uuids_len = find_data_item(data, AdCompleteListOf16BitServiceClassUUIDs, &uuids);
- if (uuids_len == 0) {
- uuids_len = find_data_item(data, AdIncompleteListOf16BitServiceClassUUIDs, &uuids);
- }
-
- mp_obj_t entries = mp_obj_new_list(0, NULL);
- for (size_t i = 0; i < uuids_len / sizeof(uint16_t); ++i) {
- const mp_obj_t uuid_int = mp_obj_new_int(uuids[sizeof(uint16_t) * i] | (uuids[sizeof(uint16_t) * i + 1] << 8));
- const mp_obj_t uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, &uuid_int, NULL);
-
- mp_obj_list_append(entries, uuid_obj);
- }
-
- // TODO: 32-bit UUIDs
- // TODO: 128-bit UUIDs
-
- return entries;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_service_uuids_obj, scanentry_get_service_uuids);
-
-const mp_obj_property_t bleio_scanentry_service_uuids_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&scanentry_get_service_uuids_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-STATIC mp_obj_t scanentry_get_tx_power_level(mp_obj_t self_in) {
- bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
- uint8_t *tx_power;
-
- const uint8_t tx_power_len = find_data_item(data, AdTxPowerLevel, &tx_power);
- if (tx_power_len == 0) {
- return mp_const_none;
- }
-
- return mp_obj_new_int((int8_t)(*tx_power));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_tx_power_level_obj, scanentry_get_tx_power_level);
-
-const mp_obj_property_t bleio_scanentry_tx_power_level_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&scanentry_get_tx_power_level_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
STATIC const mp_rom_map_elem_t bleio_scanentry_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_scanentry_address_obj) },
- { MP_ROM_QSTR(MP_QSTR_manufacturer_specific_data), MP_ROM_PTR(&bleio_scanentry_manufacturer_specific_data_obj) },
- { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_scanentry_name_obj) },
- { MP_ROM_QSTR(MP_QSTR_raw_data), MP_ROM_PTR(&bleio_scanentry_raw_data_obj) },
- { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) },
- { MP_ROM_QSTR(MP_QSTR_service_uuids), MP_ROM_PTR(&bleio_scanentry_service_uuids_obj) },
- { MP_ROM_QSTR(MP_QSTR_tx_power_level), MP_ROM_PTR(&bleio_scanentry_tx_power_level_obj) },
+ { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_scanentry_address_obj) },
+ { MP_ROM_QSTR(MP_QSTR_raw_data), MP_ROM_PTR(&bleio_scanentry_raw_data_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table);
@@ -303,6 +114,5 @@ STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_
const mp_obj_type_t bleio_scanentry_type = {
{ &mp_type_type },
.name = MP_QSTR_ScanEntry,
- .print = bleio_scanentry_print,
.locals_dict = (mp_obj_dict_t*)&bleio_scanentry_locals_dict
};
diff --git a/shared-bindings/bleio/Scanner.c b/shared-bindings/bleio/Scanner.c
index 5615ce103..a249d5343 100644
--- a/shared-bindings/bleio/Scanner.c
+++ b/shared-bindings/bleio/Scanner.c
@@ -80,8 +80,8 @@ STATIC mp_obj_t bleio_scanner_scan(size_t n_args, const mp_obj_t *pos_args, mp_m
enum { ARG_timeout, ARG_interval, ARG_window };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
diff --git a/shared-bindings/bleio/UUID.c b/shared-bindings/bleio/UUID.c
index d054ea719..f79dfa675 100644
--- a/shared-bindings/bleio/UUID.c
+++ b/shared-bindings/bleio/UUID.c
@@ -47,10 +47,11 @@
//| 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 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'
//|
//| :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,6 +126,8 @@ STATIC mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, co
//|
//| The 16-bit part of the UUID. (read-only)
//|
+//| :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);
return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_uuid_get_uuid16(self));
@@ -141,9 +144,11 @@ const mp_obj_property_t bleio_uuid_uuid16_obj = {
//| .. attribute:: uuid128
//|
-//| The 128-bit value of the UUID, returned as bytes.
+//| The 128-bit value of the UUID
//| Raises AttributeError if this is a 16-bit UUID. (read-only)
//|
+//| :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);
@@ -165,9 +170,10 @@ const mp_obj_property_t bleio_uuid_uuid128_obj = {
//| .. attribute:: size
//|
-//| Returns 128 if this UUID represents a 128-bit vendor-specific UUID.
-//| Returns 16 if this UUID represents a 16-bit Bluetooth SIG assigned UUID. (read-only)
-//| 32-bit UUIDs are not currently supported.
+//| 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
//|
STATIC mp_obj_t bleio_uuid_get_size(mp_obj_t self_in) {
bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c
index 4b98e4673..06c00d588 100644
--- a/shared-bindings/bleio/__init__.c
+++ b/shared-bindings/bleio/__init__.c
@@ -27,7 +27,6 @@
#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Address.h"
-#include "shared-bindings/bleio/AddressType.h"
#include "shared-bindings/bleio/Characteristic.h"
#include "shared-bindings/bleio/CharacteristicBuffer.h"
#include "shared-bindings/bleio/Descriptor.h"
@@ -52,7 +51,6 @@
//| :maxdepth: 3
//|
//| Address
-//| AddressType
//| AdvertisementData
//| Adapter
//| Characteristic
@@ -87,9 +85,6 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
// Properties
{ MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
-
- // Enum-like Classes.
- { MP_ROM_QSTR(MP_QSTR_AddressType), MP_ROM_PTR(&bleio_addresstype_type) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table);
diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c
index 82a0cab67..47e2d64bc 100644
--- a/shared-bindings/board/__init__.c
+++ b/shared-bindings/board/__init__.c
@@ -34,7 +34,6 @@
//|
//| .. module:: board
//| :synopsis: Board specific pin names
-//| :platform: SAMD21
//|
//| Common container for board base pin names. These will vary from board to
//| board so don't expect portability when using this module.
@@ -42,7 +41,7 @@
//| .. warning:: The board module varies by board. The APIs documented here may or may not be
//| available on a specific board.
-//| .. method:: I2C()
+//| .. function:: I2C()
//|
//| Returns the `busio.I2C` object for the board designated SDA and SCL pins. It is a singleton.
//|
@@ -66,7 +65,7 @@ mp_obj_t board_i2c(void) {
MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c);
-//| .. method:: SPI()
+//| .. function:: SPI()
//|
//| Returns the `busio.SPI` object for the board designated SCK, MOSI and MISO pins. It is a
//| singleton.
@@ -90,7 +89,7 @@ mp_obj_t board_spi(void) {
#endif
MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi);
-//| .. method:: UART()
+//| .. function:: UART()
//|
//| Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton.
//|
diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c
index e17a72b48..0e639f0b5 100644
--- a/shared-bindings/busio/I2C.c
+++ b/shared-bindings/busio/I2C.c
@@ -41,7 +41,7 @@
//| :class:`I2C` --- Two wire serial protocol
//| ------------------------------------------
//|
-//| .. class:: I2C(scl, sda, \*, frequency=400000)
+//| .. 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
@@ -82,7 +82,7 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, con
return (mp_obj_t)self;
}
-//| .. method:: I2C.deinit()
+//| .. method:: deinit()
//|
//| Releases control of the underlying hardware so other classes can use it.
//|
@@ -93,13 +93,19 @@ STATIC mp_obj_t busio_i2c_obj_deinit(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_deinit_obj, busio_i2c_obj_deinit);
-//| .. method:: I2C.__enter__()
+STATIC void check_for_deinit(busio_i2c_obj_t *self) {
+ if (common_hal_busio_i2c_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| .. method:: __enter__()
//|
//| No-op used in Context Managers.
//|
// Provided by context manager helper.
-//| .. method:: I2C.__exit__()
+//| .. method:: __exit__()
//|
//| Automatically deinitializes the hardware on context exit. See
//| :ref:`lifetime-and-contextmanagers` for more info.
@@ -118,7 +124,7 @@ static void check_lock(busio_i2c_obj_t *self) {
}
}
-//| .. method:: I2C.scan()
+//| .. method:: scan()
//|
//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a
//| list of those that respond.
@@ -128,7 +134,7 @@ static void check_lock(busio_i2c_obj_t *self) {
//|
STATIC mp_obj_t busio_i2c_scan(mp_obj_t self_in) {
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_busio_i2c_deinited(self));
+ check_for_deinit(self);
check_lock(self);
mp_obj_t list = mp_obj_new_list(0, NULL);
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
@@ -142,7 +148,7 @@ 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:: I2C.try_lock()
+//| .. method:: try_lock()
//|
//| Attempts to grab the I2C lock. Returns True on success.
//|
@@ -151,24 +157,24 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_scan_obj, busio_i2c_scan);
//|
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);
- raise_error_if_deinited(common_hal_busio_i2c_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_busio_i2c_try_lock(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_try_lock_obj, busio_i2c_obj_try_lock);
-//| .. method:: I2C.unlock()
+//| .. method:: unlock()
//|
//| 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);
- raise_error_if_deinited(common_hal_busio_i2c_deinited(self));
+ check_for_deinit(self);
common_hal_busio_i2c_unlock(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
-//| .. method:: I2C.readfrom_into(address, buffer, \*, start=0, end=len(buffer))
+//| .. 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``.
@@ -181,7 +187,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
//| :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 end: Index to write up to but not include. Defaults to ``len(buffer)``
//|
STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
@@ -192,7 +198,7 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args,
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_busio_i2c_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
@@ -216,7 +222,7 @@ 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:: I2C.writeto(address, buffer, \*, start=0, end=len(buffer), stop=True)
+//| .. 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 if ``stop`` is set.
@@ -231,7 +237,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in
//| :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 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
//|
@@ -245,7 +251,7 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_busio_i2c_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
diff --git a/shared-bindings/busio/OneWire.c b/shared-bindings/busio/OneWire.c
index ceba4f8ee..aca2a3ef2 100644
--- a/shared-bindings/busio/OneWire.c
+++ b/shared-bindings/busio/OneWire.c
@@ -91,6 +91,12 @@ STATIC mp_obj_t busio_onewire_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(busio_onewire_deinit_obj, busio_onewire_deinit);
+STATIC void check_for_deinit(busio_onewire_obj_t *self) {
+ if (common_hal_busio_onewire_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -118,7 +124,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_onewire___exit___obj, 4, 4, bus
//|
STATIC mp_obj_t busio_onewire_obj_reset(mp_obj_t self_in) {
busio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_busio_onewire_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_busio_onewire_reset(self));
}
@@ -133,7 +139,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_onewire_reset_obj, busio_onewire_obj_reset);
//|
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);
- raise_error_if_deinited(common_hal_busio_onewire_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_busio_onewire_read_bit(self));
}
@@ -145,7 +151,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_onewire_read_bit_obj, busio_onewire_obj_read_bit
//|
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);
- raise_error_if_deinited(common_hal_busio_onewire_deinited(self));
+ check_for_deinit(self);
common_hal_busio_onewire_write_bit(self, mp_obj_is_true(bool_obj));
return mp_const_none;
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index f690eea18..a7d7d515c 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -95,7 +95,7 @@ STATIC mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, con
return (mp_obj_t)self;
}
-//| .. method:: SPI.deinit()
+//| .. method:: deinit()
//|
//| Turn off the SPI bus.
//|
@@ -106,13 +106,13 @@ 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:: SPI.__enter__()
+//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
//|
// Provided by context manager helper.
-//| .. method:: SPI.__exit__()
+//| .. method:: __exit__()
//|
//| Automatically deinitializes the hardware when exiting a context. See
//| :ref:`lifetime-and-contextmanagers` for more info.
@@ -124,14 +124,20 @@ STATIC mp_obj_t busio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_spi_obj___exit___obj, 4, 4, busio_spi_obj___exit__);
-static void check_lock(busio_spi_obj_t *self) {
+STATIC void check_lock(busio_spi_obj_t *self) {
asm("");
if (!common_hal_busio_spi_has_lock(self)) {
mp_raise_RuntimeError(translate("Function requires lock"));
}
}
-//| .. method:: SPI.configure(\*, baudrate=100000, polarity=0, phase=0, bits=8)
+STATIC void check_for_deinit(busio_spi_obj_t *self) {
+ if (common_hal_busio_spi_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| .. method:: configure(*, baudrate=100000, polarity=0, phase=0, bits=8)
//|
//| Configures the SPI bus. The SPI object must be locked.
//|
@@ -162,7 +168,7 @@ STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
@@ -188,7 +194,7 @@ 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:: SPI.try_lock()
+//| .. method:: try_lock()
//|
//| Attempts to grab the SPI lock. Returns True on success.
//|
@@ -197,31 +203,30 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_configure_obj, 1, busio_spi_configure);
//|
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);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
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:: SPI.unlock()
+//| .. method:: unlock()
//|
//| 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);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_for_deinit(self);
common_hal_busio_spi_unlock(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock);
-//| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer))
+//| .. 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.
//|
//| :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
+//| :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 };
@@ -231,7 +236,7 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
@@ -255,7 +260,7 @@ 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:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0)
+//| .. method:: readinto(buffer, *, start=0, end=None, write_value=0)
//|
//| Read into ``buffer`` while writing ``write_value`` for each byte read.
//| The SPI object must be locked.
@@ -263,7 +268,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write);
//|
//| :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
+//| :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) {
@@ -275,7 +280,7 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
{ MP_QSTR_write_value,MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
@@ -298,7 +303,7 @@ 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:: SPI.write_readinto(buffer_out, buffer_in, \*, out_start=0, out_end=len(buffer_out), in_start=0, in_end=len(buffer_in))
+//| .. 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.
@@ -309,9 +314,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 2, busio_spi_readinto);
//| :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
+//| :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
+//| :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 };
@@ -324,7 +329,7 @@ STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_for_deinit(self);
check_lock(self);
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);
@@ -367,7 +372,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_read
//|
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);
- raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_busio_spi_get_frequency(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_get_frequency_obj, busio_spi_obj_get_frequency);
diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c
index 94ad1bd3e..c7eef8c43 100644
--- a/shared-bindings/busio/UART.c
+++ b/shared-bindings/busio/UART.c
@@ -46,7 +46,7 @@
//| =================================================
//|
//|
-//| .. class:: UART(tx, rx, \*, baudrate=9600, bits=8, parity=None, stop=1, timeout=1, receiver_buffer_size=64)
+//| .. 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.
@@ -137,6 +137,12 @@ STATIC mp_obj_t busio_uart_obj_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_deinit_obj, busio_uart_obj_deinit);
+STATIC void check_for_deinit(busio_uart_obj_t *self) {
+ if (common_hal_busio_uart_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -196,7 +202,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_
// 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) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
byte *buf = buf_in;
// make sure we want at least 1 char
@@ -209,7 +215,7 @@ STATIC mp_uint_t busio_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size,
STATIC mp_uint_t busio_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
const byte *buf = buf_in;
return common_hal_busio_uart_write(self, buf, size, errcode);
@@ -217,7 +223,7 @@ STATIC mp_uint_t busio_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_
STATIC mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
mp_uint_t ret;
if (request == MP_IOCTL_POLL) {
mp_uint_t flags = arg;
@@ -241,14 +247,14 @@ STATIC mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t
//|
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);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_busio_uart_get_baudrate(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_get_baudrate_obj, busio_uart_obj_get_baudrate);
STATIC mp_obj_t busio_uart_obj_set_baudrate(mp_obj_t self_in, mp_obj_t baudrate) {
busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
common_hal_busio_uart_set_baudrate(self, mp_obj_get_int(baudrate));
return mp_const_none;
}
@@ -268,7 +274,7 @@ const mp_obj_property_t busio_uart_baudrate_obj = {
//|
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);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_busio_uart_rx_characters_available(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_get_in_waiting_obj, busio_uart_obj_get_in_waiting);
@@ -286,13 +292,13 @@ const mp_obj_property_t busio_uart_in_waiting_obj = {
//|
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);
- raise_error_if_deinited(common_hal_busio_uart_deinited(self));
+ check_for_deinit(self);
common_hal_busio_uart_clear_rx_buffer(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_reset_input_buffer_obj, busio_uart_obj_reset_input_buffer);
-//| .. class:: busio.UART.Parity
+//| .. class:: busio.UART.Parity()
//|
//| Enum-like class to define the parity used to verify correct data transfer.
//|
diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c
index 958ee062a..ff2933dc6 100644
--- a/shared-bindings/busio/__init__.c
+++ b/shared-bindings/busio/__init__.c
@@ -35,7 +35,6 @@
#include "shared-bindings/busio/OneWire.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/busio/UART.h"
-#include "shared-bindings/busio/__init__.h"
#include "py/runtime.h"
diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c
index 1ced15137..6587ee7ea 100644
--- a/shared-bindings/digitalio/DigitalInOut.c
+++ b/shared-bindings/digitalio/DigitalInOut.c
@@ -105,6 +105,12 @@ STATIC mp_obj_t digitalio_digitalinout_obj___exit__(size_t n_args, const mp_obj_
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(digitalio_digitalinout_obj___exit___obj, 4, 4, digitalio_digitalinout_obj___exit__);
+STATIC void check_for_deinit(digitalio_digitalinout_obj_t *self) {
+ if (common_hal_digitalio_digitalinout_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//|
//| .. method:: switch_to_output(value=False, drive_mode=digitalio.DriveMode.PUSH_PULL)
//|
@@ -121,7 +127,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_
{ MP_QSTR_drive_mode, MP_ARG_OBJ, {.u_rom_obj = &digitalio_drive_mode_push_pull_obj} },
};
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
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);
@@ -158,7 +164,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
};
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
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);
@@ -191,7 +197,7 @@ extern const digitalio_digitalio_direction_obj_t digitalio_digitalio_direction_o
STATIC mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
if (direction == DIRECTION_INPUT) {
return (mp_obj_t)&digitalio_direction_input_obj;
@@ -202,7 +208,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_direction_obj, digitalio_di
STATIC mp_obj_t digitalio_digitalinout_obj_set_direction(mp_obj_t self_in, mp_obj_t value) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
if (value == &digitalio_direction_input_obj) {
common_hal_digitalio_digitalinout_switch_to_input(self, PULL_NONE);
} else if (value == &digitalio_direction_output_obj) {
@@ -227,7 +233,7 @@ const mp_obj_property_t digitalio_digitalio_direction_obj = {
//|
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);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
bool value = common_hal_digitalio_digitalinout_get_value(self);
return mp_obj_new_bool(value);
}
@@ -235,7 +241,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_value_obj, digitalio_digita
STATIC mp_obj_t digitalio_digitalinout_obj_set_value(mp_obj_t self_in, mp_obj_t value) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
if (common_hal_digitalio_digitalinout_get_direction(self) == DIRECTION_INPUT) {
mp_raise_AttributeError(translate("Cannot set value when direction is input."));
return mp_const_none;
@@ -261,7 +267,7 @@ const mp_obj_property_t digitalio_digitalinout_value_obj = {
//|
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);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
if (common_hal_digitalio_digitalinout_get_direction(self) == DIRECTION_INPUT) {
mp_raise_AttributeError(translate("Drive mode not used when direction is input."));
return mp_const_none;
@@ -276,7 +282,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_drive_mode_obj, digitalio_d
STATIC mp_obj_t digitalio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_obj_t drive_mode) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
if (common_hal_digitalio_digitalinout_get_direction(self) == DIRECTION_INPUT) {
mp_raise_AttributeError(translate("Drive mode not used when direction is input."));
return mp_const_none;
@@ -309,7 +315,7 @@ const mp_obj_property_t digitalio_digitalio_drive_mode_obj = {
//|
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);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
if (common_hal_digitalio_digitalinout_get_direction(self) == DIRECTION_OUTPUT) {
mp_raise_AttributeError(translate("Pull not used when direction is output."));
return mp_const_none;
@@ -326,7 +332,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_pull_obj, digitalio_digital
STATIC mp_obj_t digitalio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t pull_obj) {
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
+ check_for_deinit(self);
if (common_hal_digitalio_digitalinout_get_direction(self) == DIRECTION_OUTPUT) {
mp_raise_AttributeError(translate("Pull not used when direction is output."));
return mp_const_none;
@@ -381,7 +387,6 @@ digitalio_digitalinout_obj_t *assert_digitalinout(mp_obj_t obj) {
mp_raise_TypeError(translate("argument num/types mismatch"));
}
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(obj);
- raise_error_if_deinited(
- common_hal_digitalio_digitalinout_deinited(pin));
+ check_for_deinit(pin);
return pin;
}
diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h
index 3136ae88a..5a027561b 100644
--- a/shared-bindings/displayio/Display.h
+++ b/shared-bindings/displayio/Display.h
@@ -53,12 +53,13 @@ void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self);
bool displayio_display_begin_transaction(displayio_display_obj_t* self);
void displayio_display_end_transaction(displayio_display_obj_t* self);
+// The second point of the region is exclusive.
void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
bool displayio_display_frame_queued(displayio_display_obj_t* self);
bool displayio_display_refresh_queued(displayio_display_obj_t* self);
void displayio_display_finish_refresh(displayio_display_obj_t* self);
-void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
+void displayio_display_send_pixels(displayio_display_obj_t* self, uint8_t* pixels, uint32_t length);
bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self);
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness);
diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c
index 6d18ac78f..6ba4914a0 100644
--- a/shared-bindings/displayio/TileGrid.c
+++ b/shared-bindings/displayio/TileGrid.c
@@ -64,7 +64,7 @@
//| :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 in default_tile: Default tile index to show.
+//| :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.
//|
@@ -196,6 +196,83 @@ 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.
+//|
+STATIC mp_obj_t displayio_tilegrid_obj_get_flip_x(mp_obj_t self_in) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+ return mp_obj_new_bool(common_hal_displayio_tilegrid_get_flip_x(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_tilegrid_get_flip_x_obj, displayio_tilegrid_obj_get_flip_x);
+
+STATIC mp_obj_t displayio_tilegrid_obj_set_flip_x(mp_obj_t self_in, mp_obj_t flip_x_obj) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+
+ common_hal_displayio_tilegrid_set_flip_x(self, mp_obj_is_true(flip_x_obj));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_set_flip_x_obj, displayio_tilegrid_obj_set_flip_x);
+
+const mp_obj_property_t displayio_tilegrid_flip_x_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_tilegrid_get_flip_x_obj,
+ (mp_obj_t)&displayio_tilegrid_set_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.
+//|
+STATIC mp_obj_t displayio_tilegrid_obj_get_flip_y(mp_obj_t self_in) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+ return mp_obj_new_bool(common_hal_displayio_tilegrid_get_flip_y(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_tilegrid_get_flip_y_obj, displayio_tilegrid_obj_get_flip_y);
+
+STATIC mp_obj_t displayio_tilegrid_obj_set_flip_y(mp_obj_t self_in, mp_obj_t flip_y_obj) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+
+ common_hal_displayio_tilegrid_set_flip_y(self, mp_obj_is_true(flip_y_obj));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_set_flip_y_obj, displayio_tilegrid_obj_set_flip_y);
+
+const mp_obj_property_t displayio_tilegrid_flip_y_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_tilegrid_get_flip_y_obj,
+ (mp_obj_t)&displayio_tilegrid_set_flip_y_obj,
+ (mp_obj_t)&mp_const_none_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.
+//|
+STATIC mp_obj_t displayio_tilegrid_obj_get_transpose_xy(mp_obj_t self_in) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+ return mp_obj_new_bool(common_hal_displayio_tilegrid_get_transpose_xy(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_tilegrid_get_transpose_xy_obj, displayio_tilegrid_obj_get_transpose_xy);
+
+STATIC mp_obj_t displayio_tilegrid_obj_set_transpose_xy(mp_obj_t self_in, mp_obj_t transpose_xy_obj) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+
+ common_hal_displayio_tilegrid_set_transpose_xy(self, mp_obj_is_true(transpose_xy_obj));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_set_transpose_xy_obj, displayio_tilegrid_obj_set_transpose_xy);
+
+const mp_obj_property_t displayio_tilegrid_transpose_xy_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_tilegrid_get_transpose_xy_obj,
+ (mp_obj_t)&displayio_tilegrid_set_transpose_xy_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
//| .. attribute:: pixel_shader
//|
//| The pixel shader of the tilegrid.
@@ -292,6 +369,9 @@ STATIC const mp_rom_map_elem_t displayio_tilegrid_locals_dict_table[] = {
// Properties
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&displayio_tilegrid_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&displayio_tilegrid_y_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flip_x), MP_ROM_PTR(&displayio_tilegrid_flip_x_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flip_y), MP_ROM_PTR(&displayio_tilegrid_flip_y_obj) },
+ { MP_ROM_QSTR(MP_QSTR_transpose_xy), MP_ROM_PTR(&displayio_tilegrid_transpose_xy_obj) },
{ MP_ROM_QSTR(MP_QSTR_pixel_shader), MP_ROM_PTR(&displayio_tilegrid_pixel_shader_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_tilegrid_locals_dict, displayio_tilegrid_locals_dict_table);
diff --git a/shared-bindings/displayio/TileGrid.h b/shared-bindings/displayio/TileGrid.h
index 15a71b53b..1f9995a94 100644
--- a/shared-bindings/displayio/TileGrid.h
+++ b/shared-bindings/displayio/TileGrid.h
@@ -42,6 +42,14 @@ void common_hal_displayio_tilegrid_set_y(displayio_tilegrid_t *self, mp_int_t y)
mp_obj_t common_hal_displayio_tilegrid_get_pixel_shader(displayio_tilegrid_t *self);
void common_hal_displayio_tilegrid_set_pixel_shader(displayio_tilegrid_t *self, mp_obj_t pixel_shader);
+
+bool common_hal_displayio_tilegrid_get_flip_x(displayio_tilegrid_t *self);
+void common_hal_displayio_tilegrid_set_flip_x(displayio_tilegrid_t *self, bool flip_x);
+bool common_hal_displayio_tilegrid_get_flip_y(displayio_tilegrid_t *self);
+void common_hal_displayio_tilegrid_set_flip_y(displayio_tilegrid_t *self, bool flip_y);
+bool common_hal_displayio_tilegrid_get_transpose_xy(displayio_tilegrid_t *self);
+void common_hal_displayio_tilegrid_set_transpose_xy(displayio_tilegrid_t *self, bool transpose_xy);
+
uint16_t common_hal_displayio_tilegrid_get_width(displayio_tilegrid_t *self);
uint16_t common_hal_displayio_tilegrid_get_height(displayio_tilegrid_t *self);
diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c
index 44b1e0b07..9dc17103b 100644
--- a/shared-bindings/displayio/__init__.c
+++ b/shared-bindings/displayio/__init__.c
@@ -69,7 +69,7 @@
//|
-//| .. method:: release_displays()
+//| .. 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
diff --git a/shared-bindings/frequencyio/FrequencyIn.c b/shared-bindings/frequencyio/FrequencyIn.c
index 908cb307d..e2b924c07 100644
--- a/shared-bindings/frequencyio/FrequencyIn.c
+++ b/shared-bindings/frequencyio/FrequencyIn.c
@@ -109,6 +109,12 @@ STATIC mp_obj_t frequencyio_frequencyin_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_deinit_obj, frequencyio_frequencyin_deinit);
+STATIC void check_for_deinit(frequencyio_frequencyin_obj_t *self) {
+ if (common_hal_frequencyio_frequencyin_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -133,7 +139,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(frequencyio_frequencyin___exit___obj,
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_pause(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+ check_for_deinit(self);
common_hal_frequencyio_frequencyin_pause(self);
return mp_const_none;
@@ -146,7 +152,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_pause_obj, frequencyio_frequen
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_resume(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+ check_for_deinit(self);
common_hal_frequencyio_frequencyin_resume(self);
return mp_const_none;
@@ -160,7 +166,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_resume_obj, frequencyio_freque
STATIC mp_obj_t frequencyio_frequencyin_obj_clear(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+ check_for_deinit(self);
common_hal_frequencyio_frequencyin_clear(self);
return mp_const_none;
@@ -178,7 +184,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_clear_obj, frequencyio_frequen
//|
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);
- raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_frequencyio_frequencyin_get_capture_period(self));
}
@@ -186,7 +192,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequency_get_capture_period_obj, frequenc
STATIC mp_obj_t frequencyio_frequencyin_obj_set_capture_period(mp_obj_t self_in, mp_obj_t capture_period) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+ check_for_deinit(self);
common_hal_frequencyio_frequencyin_set_capture_period(self, mp_obj_get_int(capture_period));
return mp_const_none;
@@ -206,7 +212,7 @@ const mp_obj_property_t frequencyio_frequencyin_capture_period_obj = {
//|
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);
- raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+ check_for_deinit(self);
//return MP_OBJ_NEW_SMALL_INT(common_hal_frequencyio_frequencyin_get_item(self));
return mp_obj_new_int_from_float(common_hal_frequencyio_frequencyin_get_item(self));
diff --git a/shared-bindings/help.c b/shared-bindings/help.c
index e0770ff3c..4e7c3a78b 100644
--- a/shared-bindings/help.c
+++ b/shared-bindings/help.c
@@ -27,7 +27,7 @@
//| :func:`help` - Built-in method to provide helpful information
//| ==============================================================
//|
-//| .. method:: help(object=None)
+//| .. 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/i2cslave/I2CSlave.c b/shared-bindings/i2cslave/I2CSlave.c
index 090a53581..2598accbb 100644
--- a/shared-bindings/i2cslave/I2CSlave.c
+++ b/shared-bindings/i2cslave/I2CSlave.c
@@ -150,7 +150,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cslave_i2c_slave___exit___obj, 4, 4
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]);
- raise_error_if_deinited(common_hal_i2cslave_i2c_slave_deinited(self));
+ 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)} },
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index 4f2e28702..8f9bbbb31 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -53,6 +53,7 @@ Module Supported Ports
`nvm` **SAMD Express**
`os` **All Supported**
`pulseio` **SAMD/SAMD Express**
+`ps2io` **SAMD/SAMD Express**
`random` **All Supported**
`rotaryio` **SAMD51, SAMD Express**
`storage` **All Supported**
diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c
index e79663107..3635f0afb 100644
--- a/shared-bindings/microcontroller/Pin.c
+++ b/shared-bindings/microcontroller/Pin.c
@@ -40,7 +40,7 @@
//|
//| Identifies an IO pin on the microcontroller.
//|
-//| .. class:: Pin
+//| .. class:: Pin()
//|
//| Identifies an IO pin on the microcontroller. They are fixed by the
//| hardware so they cannot be constructed on demand. Instead, use
diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c
index 7c3f84fca..913242ad2 100644
--- a/shared-bindings/microcontroller/RunMode.c
+++ b/shared-bindings/microcontroller/RunMode.c
@@ -31,24 +31,30 @@
//| :class:`RunMode` -- run state of the microcontroller
//| =============================================================
//|
-//| .. class:: microcontroller.RunMode
+//| .. class:: RunMode()
//|
//| Enum-like class to define the run mode of the microcontroller and
//| CircuitPython.
//|
-//| .. data:: NORMAL
+//| .. attribute:: NORMAL
//|
//| Run CircuitPython as normal.
//|
-//| .. data:: SAFE_MODE
+//| :type microcontroller.RunMode:
+//|
+//| .. attribute:: SAFE_MODE
//|
//| Run CircuitPython in safe mode. User code will not be run and the
//| file system will be writeable over USB.
//|
-//| .. data:: BOOTLOADER
+//| :type microcontroller.RunMode:
+//|
+//| .. attribute:: BOOTLOADER
//|
//| Run the bootloader.
//|
+//| :type microcontroller.RunMode:
+//|
const mp_obj_type_t mcu_runmode_type;
const mcu_runmode_obj_t mcu_runmode_normal_obj = {
diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c
index da8d0bd94..090c4564d 100644
--- a/shared-bindings/microcontroller/__init__.c
+++ b/shared-bindings/microcontroller/__init__.c
@@ -62,14 +62,14 @@
//| RunMode
//|
-//| .. attribute:: cpu
+//| .. data:: cpu
//|
//| CPU information and control, such as ``cpu.temperature`` and ``cpu.frequency``
//| (clock frequency).
//| This object is the sole instance of `microcontroller.Processor`.
//|
-//| .. method:: delay_us(delay)
+//| .. 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
@@ -87,7 +87,7 @@ 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);
-//| .. method:: disable_interrupts()
+//| .. function:: disable_interrupts()
//|
//| Disable all interrupts. Be very careful, this can stall everything.
//|
@@ -97,7 +97,7 @@ STATIC mp_obj_t mcu_disable_interrupts(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_disable_interrupts_obj, mcu_disable_interrupts);
-//| .. method:: enable_interrupts()
+//| .. function:: enable_interrupts()
//|
//| Enable the interrupts that were enabled at the last disable.
//|
@@ -107,7 +107,7 @@ STATIC mp_obj_t mcu_enable_interrupts(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupts);
-//| .. method:: on_next_reset(run_mode)
+//| .. function:: on_next_reset(run_mode)
//|
//| Configure the run mode used the next time the microcontroller is reset but
//| not powered down.
@@ -132,7 +132,7 @@ 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);
-//| .. method:: reset()
+//| .. function:: reset()
//|
//| Reset the microcontroller. After reset, the microcontroller will enter the
//| run mode last set by `on_next_reset`.
@@ -148,11 +148,13 @@ STATIC mp_obj_t mcu_reset(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
-//| .. attribute:: nvm
+//| .. data:: nvm
//|
//| Available non-volatile memory.
//| This object is the sole instance of `nvm.ByteArray` when available or ``None`` otherwise.
//|
+//| :type: nvm.ByteArray or None
+//|
//| :mod:`microcontroller.pin` --- Microcontroller pin names
//| --------------------------------------------------------
diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c
index 05d6fd97a..1ee66337b 100644
--- a/shared-bindings/neopixel_write/__init__.c
+++ b/shared-bindings/neopixel_write/__init__.c
@@ -55,11 +55,11 @@
//| pixel_off = bytearray([0, 0, 0])
//| neopixel_write.neopixel_write(pin, pixel_off)
//|
-//| .. method:: neopixel_write.neopixel_write(digitalinout, buf)
+//| .. function:: neopixel_write(digitalinout, buf)
//|
//| Write buf out on the given DigitalInOut.
//|
-//| :param ~digitalio.DigitalInOut gpio: the DigitalInOut to output with
+//| :param ~digitalio.DigitalInOut digitalinout: the DigitalInOut to output with
//| :param bytearray 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) {
diff --git a/shared-bindings/network/__init__.c b/shared-bindings/network/__init__.c
index 1067ea549..01763a73c 100644
--- a/shared-bindings/network/__init__.c
+++ b/shared-bindings/network/__init__.c
@@ -49,7 +49,7 @@
//| It is used by the 'socket' module to look up a suitable
//| NIC when a socket is created.
//|
-//| .. function:: route
+//| .. function:: route()
//|
//| Returns a list of all configured NICs.
//|
diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c
new file mode 100644
index 000000000..fb5c24b85
--- /dev/null
+++ b/shared-bindings/ps2io/Ps2.c
@@ -0,0 +1,243 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * 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 "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/ps2io/Ps2.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: ps2io
+//|
+//| :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.
+//|
+//| .. class:: Ps2(data_pin, clock_pin)
+//|
+//| Create a Ps2 object associated with the given pins.
+//|
+//| :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.
+//|
+//| Read one byte from PS/2 keyboard and turn on Scroll Lock LED::
+//|
+//| import ps2io
+//| import board
+//|
+//| kbd = ps2io.Ps2(board.D10, board.D11)
+//|
+//| while len(kbd) == 0:
+//| pass
+//|
+//| 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 };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_datapin, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_clkpin, 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);
+ 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);
+
+ ps2io_ps2_obj_t *self = m_new_obj(ps2io_ps2_obj_t);
+ self->base.type = &ps2io_ps2_type;
+
+ common_hal_ps2io_ps2_construct(self, datapin, clkpin);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| 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);
+ common_hal_ps2io_ps2_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_deinit_obj, ps2io_ps2_deinit);
+
+STATIC void check_for_deinit(ps2io_ps2_obj_t *self) {
+ if (common_hal_ps2io_ps2_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
+//| .. method:: __enter__()
+//|
+//| 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.
+//|
+STATIC mp_obj_t ps2io_ps2_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_ps2io_ps2_deinit(args[0]);
+ return mp_const_none;
+}
+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.
+//|
+STATIC mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) {
+ ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ int b = common_hal_ps2io_ps2_popleft(self);
+ if (b < 0) {
+ mp_raise_IndexError(translate("Pop from an empty Ps2 buffer"));
+ }
+ return MP_OBJ_NEW_SMALL_INT(b);
+}
+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()`.
+//|
+//| 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
+//|
+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);
+ check_for_deinit(self);
+ mp_int_t cmd = mp_obj_get_int(ob) & 0xff;
+ int resp = common_hal_ps2io_ps2_sendcmd(self, cmd);
+ if (resp < 0) {
+ mp_raise_RuntimeError(translate("Failed sending command."));
+ }
+ return MP_OBJ_NEW_SMALL_INT(resp);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(ps2io_ps2_sendcmd_obj, ps2io_ps2_obj_sendcmd);
+
+//| .. method:: clear_errors()
+//|
+//| Returns and clears a bitmap with latest recorded communication errors.
+//|
+//| Reception errors (arise asynchronously, as data is received):
+//|
+//| 0x01: start bit not 0
+//|
+//| 0x02: timeout
+//|
+//| 0x04: parity bit error
+//|
+//| 0x08: stop bit not 1
+//|
+//| 0x10: buffer overflow, newest data discarded
+//|
+//| Transmission errors (can only arise in the course of sendcmd()):
+//|
+//| 0x100: clock pin didn't go to LO in time
+//|
+//| 0x200: clock pin didn't go to HI in time
+//|
+//| 0x400: data pin didn't ACK
+//|
+//| 0x800: clock pin didn't ACK
+//|
+//| 0x1000: device didn't respond to RTS
+//|
+//| 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);
+ check_for_deinit(self);
+
+ return MP_OBJ_NEW_SMALL_INT(common_hal_ps2io_ps2_clear_errors(self));
+}
+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()`.
+//|
+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);
+ check_for_deinit(self);
+ uint16_t len = common_hal_ps2io_ps2_get_len(self);
+ switch (op) {
+ case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0);
+ case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len);
+ default: return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC const mp_rom_map_elem_t ps2io_ps2_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&ps2io_ps2_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&ps2io_ps2___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&ps2io_ps2_popleft_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sendcmd), MP_ROM_PTR(&ps2io_ps2_sendcmd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_clear_errors), MP_ROM_PTR(&ps2io_ps2_clear_errors_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(ps2io_ps2_locals_dict, ps2io_ps2_locals_dict_table);
+
+const mp_obj_type_t ps2io_ps2_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Ps2,
+ .make_new = ps2io_ps2_make_new,
+ .unary_op = ps2_unary_op,
+ .locals_dict = (mp_obj_dict_t*)&ps2io_ps2_locals_dict,
+};
diff --git a/shared-bindings/ps2io/Ps2.h b/shared-bindings/ps2io/Ps2.h
new file mode 100644
index 000000000..523869d55
--- /dev/null
+++ b/shared-bindings/ps2io/Ps2.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * 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_PS2IO_PS2_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO_PS2_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/ps2io/Ps2.h"
+
+extern const mp_obj_type_t ps2io_ps2_type;
+
+extern void common_hal_ps2io_ps2_construct(ps2io_ps2_obj_t* self,
+ const mcu_pin_obj_t* data_pin, const mcu_pin_obj_t* clk_pin);
+extern void common_hal_ps2io_ps2_deinit(ps2io_ps2_obj_t* self);
+extern bool common_hal_ps2io_ps2_deinited(ps2io_ps2_obj_t* self);
+extern uint16_t common_hal_ps2io_ps2_get_len(ps2io_ps2_obj_t* self);
+extern int16_t common_hal_ps2io_ps2_popleft(ps2io_ps2_obj_t* self);
+extern int16_t common_hal_ps2io_ps2_sendcmd(ps2io_ps2_obj_t* self, uint8_t b);
+extern uint16_t common_hal_ps2io_ps2_clear_errors(ps2io_ps2_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO_PS2_H
diff --git a/shared-bindings/ps2io/__init__.c b/shared-bindings/ps2io/__init__.c
new file mode 100644
index 000000000..ec7c43e51
--- /dev/null
+++ b/shared-bindings/ps2io/__init__.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/ps2io/Ps2.h"
+
+//| :mod:`ps2io` --- Support for PS/2 protocol
+//| =====================================================
+//|
+//| .. module:: ps2io
+//| :synopsis: Support for PS/2 based devices
+//| :platform: SAMD21
+//|
+//| 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.
+//|
+
+//| 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 ps2io_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ps2io) },
+ { MP_ROM_QSTR(MP_QSTR_Ps2), MP_ROM_PTR(&ps2io_ps2_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(ps2io_module_globals, ps2io_module_globals_table);
+
+const mp_obj_module_t ps2io_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&ps2io_module_globals,
+};
diff --git a/shared-bindings/ps2io/__init__.h b/shared-bindings/ps2io/__init__.h
new file mode 100644
index 000000000..1ff3d97b5
--- /dev/null
+++ b/shared-bindings/ps2io/__init__.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * 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_PS2IO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO___INIT___H
diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c
index 37939a07a..40981e0a8 100644
--- a/shared-bindings/pulseio/PWMOut.c
+++ b/shared-bindings/pulseio/PWMOut.c
@@ -42,7 +42,7 @@
//|
//| PWMOut can be used to output a PWM signal on a given pin.
//|
-//| .. class:: PWMOut(pin, \*, duty_cycle=0, frequency=500, variable_frequency=False)
+//| .. class:: PWMOut(pin, *, duty_cycle=0, frequency=500, variable_frequency=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
@@ -133,6 +133,12 @@ STATIC mp_obj_t pulseio_pwmout_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pwmout_deinit_obj, pulseio_pwmout_deinit);
+STATIC void check_for_deinit(pulseio_pwmout_obj_t *self) {
+ if (common_hal_pulseio_pwmout_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -158,14 +164,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pwmout___exit___obj, 4, 4, pu
//| be half high and then half low.
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);
- raise_error_if_deinited(common_hal_pulseio_pwmout_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_pulseio_pwmout_get_duty_cycle(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pwmout_get_duty_cycle_obj, pulseio_pwmout_obj_get_duty_cycle);
STATIC mp_obj_t pulseio_pwmout_obj_set_duty_cycle(mp_obj_t self_in, mp_obj_t duty_cycle) {
pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_pulseio_pwmout_deinited(self));
+ check_for_deinit(self);
mp_int_t duty = mp_obj_get_int(duty_cycle);
if (duty < 0 || duty > 0xffff) {
mp_raise_ValueError(translate("PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)"));
@@ -189,14 +195,14 @@ const mp_obj_property_t pulseio_pwmout_duty_cycle_obj = {
//|
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);
- raise_error_if_deinited(common_hal_pulseio_pwmout_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_pulseio_pwmout_get_frequency(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pwmout_get_frequency_obj, pulseio_pwmout_obj_get_frequency);
STATIC mp_obj_t pulseio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t frequency) {
pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_pulseio_pwmout_deinited(self));
+ check_for_deinit(self);
if (!common_hal_pulseio_pwmout_get_variable_frequency(self)) {
mp_raise_AttributeError(translate(
"PWM frequency not writable when variable_frequency is False on "
diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c
index 426ac4384..8b69109f0 100644
--- a/shared-bindings/pulseio/PulseIn.c
+++ b/shared-bindings/pulseio/PulseIn.c
@@ -45,7 +45,7 @@
//| The pulsed signal consists of timed active and idle periods. Unlike PWM,
//| there is no set duration for active and idle pairs.
//|
-//| .. class:: PulseIn(pin, maxlen=2, \*, idle_state=False)
+//| .. class:: PulseIn(pin, maxlen=2, *, idle_state=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
@@ -114,6 +114,12 @@ STATIC mp_obj_t pulseio_pulsein_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_deinit_obj, pulseio_pulsein_deinit);
+STATIC void check_for_deinit(pulseio_pulsein_obj_t *self) {
+ if (common_hal_pulseio_pulsein_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -138,7 +144,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulsein___exit___obj, 4, 4, p
//|
STATIC mp_obj_t pulseio_pulsein_obj_pause(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
common_hal_pulseio_pulsein_pause(self);
return mp_const_none;
@@ -162,7 +168,7 @@ STATIC mp_obj_t pulseio_pulsein_obj_resume(size_t n_args, const mp_obj_t *pos_ar
{ MP_QSTR_trigger_duration, MP_ARG_INT, {.u_int = 0} },
};
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
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);
@@ -178,7 +184,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pulseio_pulsein_resume_obj, 1, pulseio_pulsein_obj_re
//|
STATIC mp_obj_t pulseio_pulsein_obj_clear(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
common_hal_pulseio_pulsein_clear(self);
return mp_const_none;
@@ -191,7 +197,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_clear_obj, pulseio_pulsein_obj_clear);
//|
STATIC mp_obj_t pulseio_pulsein_obj_popleft(mp_obj_t self_in) {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_pulseio_pulsein_popleft(self));
}
@@ -204,7 +210,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_popleft_obj, pulseio_pulsein_obj_pople
//|
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);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_pulseio_pulsein_get_maxlen(self));
}
@@ -224,7 +230,7 @@ const mp_obj_property_t pulseio_pulsein_maxlen_obj = {
//|
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);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_pulseio_pulsein_get_paused(self));
}
@@ -248,7 +254,7 @@ const mp_obj_property_t pulseio_pulsein_paused_obj = {
//|
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);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
uint16_t len = common_hal_pulseio_pulsein_get_len(self);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0);
@@ -272,7 +278,7 @@ STATIC mp_obj_t pulsein_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t va
mp_raise_AttributeError(translate("Cannot delete values"));
} else {
pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self));
+ check_for_deinit(self);
if (MP_OBJ_IS_TYPE(index_obj, &mp_type_slice)) {
mp_raise_NotImplementedError(translate("Slices not supported"));
diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c
index 493b7e2ff..172459e5d 100644
--- a/shared-bindings/pulseio/PulseOut.c
+++ b/shared-bindings/pulseio/PulseOut.c
@@ -127,7 +127,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulseout___exit___obj, 4, 4,
//|
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);
- raise_error_if_deinited(common_hal_pulseio_pulseout_deinited(self));
+ if (common_hal_pulseio_pulseout_deinited(self)) {
+ raise_deinited_error();
+ }
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(pulses, &bufinfo, MP_BUFFER_READ);
diff --git a/shared-bindings/pulseio/__init__.c b/shared-bindings/pulseio/__init__.c
index 1114b604b..a3cec3dca 100644
--- a/shared-bindings/pulseio/__init__.c
+++ b/shared-bindings/pulseio/__init__.c
@@ -54,10 +54,6 @@
//| PWMOut
//|
-//| .. warning:: This module is not available in some SAMD21 builds. See the
-//| :ref:`module-support-matrix` for more info.
-//|
-
//| All classes change hardware state and should be deinitialized when they
//| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See
diff --git a/shared-bindings/rotaryio/IncrementalEncoder.c b/shared-bindings/rotaryio/IncrementalEncoder.c
index 5d2264ffc..f2f157847 100644
--- a/shared-bindings/rotaryio/IncrementalEncoder.c
+++ b/shared-bindings/rotaryio/IncrementalEncoder.c
@@ -100,6 +100,12 @@ STATIC mp_obj_t rotaryio_incrementalencoder_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(rotaryio_incrementalencoder_deinit_obj, rotaryio_incrementalencoder_deinit);
+STATIC void check_for_deinit(rotaryio_incrementalencoder_obj_t *self) {
+ if (common_hal_rotaryio_incrementalencoder_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -126,7 +132,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rotaryio_incrementalencoder___exit___
//|
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);
- raise_error_if_deinited(common_hal_rotaryio_incrementalencoder_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_int(common_hal_rotaryio_incrementalencoder_get_position(self));
}
@@ -134,7 +140,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(rotaryio_incrementalencoder_get_position_obj, rotaryio
STATIC mp_obj_t rotaryio_incrementalencoder_obj_set_position(mp_obj_t self_in, mp_obj_t new_position) {
rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_rotaryio_incrementalencoder_deinited(self));
+ check_for_deinit(self);
common_hal_rotaryio_incrementalencoder_set_position(self, mp_obj_get_int(new_position));
return mp_const_none;
diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c
index 085d4e690..6d04a9893 100644
--- a/shared-bindings/socket/__init__.c
+++ b/shared-bindings/socket/__init__.c
@@ -51,7 +51,7 @@ STATIC const mp_obj_type_t socket_type;
//| .. currentmodule:: socket
//|
-//| .. class:: socket(family, type, proto, ...)
+//| .. class:: socket(family, type, proto)
//|
//| Create a new socket
//|
diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c
index 4db3a9fec..ba439b951 100644
--- a/shared-bindings/storage/__init__.c
+++ b/shared-bindings/storage/__init__.c
@@ -48,7 +48,7 @@
//| directly.
//|
-//| .. function:: mount(filesystem, mount_path, \*, readonly=False)
+//| .. function:: mount(filesystem, mount_path, *, readonly=False)
//|
//| Mounts the given filesystem object at the given path.
//|
@@ -183,7 +183,7 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
//| this property can only be set when the device is writable by the
//| microcontroller.
//|
- //| .. method:: mkfs
+ //| .. method:: mkfs()
//|
//| Format the block device, deleting any data that may have been there
//|
@@ -216,7 +216,7 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = {
//|
//| Don't call this directly, call `storage.mount`.
//|
- //| .. method:: umount
+ //| .. method:: umount()
//|
//| Don't call this directly, call `storage.umount`.
//|
diff --git a/shared-bindings/struct/__init__.c b/shared-bindings/struct/__init__.c
index 9240a15bb..ea14b3763 100644
--- a/shared-bindings/struct/__init__.c
+++ b/shared-bindings/struct/__init__.c
@@ -67,9 +67,9 @@ 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, v1, v2, ...)
+//| .. function:: pack(fmt, *values)
//|
-//| Pack the values v1, v2, ... according to the format string fmt.
+//| Pack the values according to the format string fmt.
//| The return value is a bytes object encoding the values.
//|
@@ -85,9 +85,9 @@ 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, v1, v2, ...)
+//| .. function:: pack_into(fmt, buffer, offset, *values)
//|
-//| Pack the values v1, v2, ... according to the format string fmt into a buffer
+//| 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.
//|
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index 3babe2db4..70c01c2d8 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -47,7 +47,7 @@
//| written in MicroPython will work in CPython but not necessarily the other
//| way around.
//|
-//| .. method:: monotonic()
+//| .. function:: monotonic()
//|
//| Returns an always increasing value of time with an unknown reference
//| point. Only use it to compare against other values from `monotonic`.
@@ -62,7 +62,7 @@ STATIC mp_obj_t time_monotonic(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic);
-//| .. method:: sleep(seconds)
+//| .. function:: sleep(seconds)
//|
//| Sleep for a given number of seconds.
//|
@@ -95,19 +95,20 @@ 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((tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst))
+//| .. class:: struct_time(time_tuple)
//|
//| Structure used to capture a date and time. Note that it takes a tuple!
//|
-//| :param int tm_year: the year, 2017 for example
-//| :param int tm_mon: the month, range [1, 12]
-//| :param int tm_mday: the day of the month, range [1, 31]
-//| :param int tm_hour: the hour, range [0, 23]
-//| :param int tm_min: the minute, range [0, 59]
-//| :param int tm_sec: the second, range [0, 61]
-//| :param int tm_wday: the day of the week, range [0, 6], Monday is 0
-//| :param int tm_yday: the day of the year, range [1, 366], -1 indicates not known
-//| :param int tm_isdst: 1 when in daylight savings, 0 when not, -1 if unknown.
+//| :param Tuple[tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst] time_tuple: Tuple of time info.
+//| * the year, 2017 for example
+//| * the month, range [1, 12]
+//| * the day of the month, range [1, 31]
+//| * the hour, range [0, 23]
+//| * the minute, range [0, 59]
+//| * the second, range [0, 61]
+//| * the day of the week, range [0, 6], Monday is 0
+//| * the day of the year, range [1, 366], -1 indicates not known
+//| * 1 when in daylight savings, 0 when not, -1 if unknown.
//|
const mp_obj_namedtuple_type_t struct_time_type_obj = {
.base = {
@@ -190,7 +191,7 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
mp_raise_RuntimeError(translate("RTC is not supported on this board"));
}
-//| .. method:: time()
+//| .. function:: time()
//|
//| Return the current time in seconds since since Jan 1, 1970.
//|
@@ -206,7 +207,7 @@ STATIC mp_obj_t time_time(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
-//| .. method:: monotonic_ns()
+//| .. function:: monotonic_ns()
//|
//| Return the time of the specified clock clk_id in nanoseconds.
//|
@@ -219,7 +220,7 @@ STATIC mp_obj_t time_monotonic_ns(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns);
-//| .. method:: localtime([secs])
+//| .. 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
@@ -245,7 +246,7 @@ 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);
-//| .. method:: mktime(t)
+//| .. function:: mktime(t)
//|
//| 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
diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c
index 3b26aca8c..78fceef41 100644
--- a/shared-bindings/touchio/TouchIn.c
+++ b/shared-bindings/touchio/TouchIn.c
@@ -88,6 +88,12 @@ STATIC mp_obj_t touchio_touchin_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(touchio_touchin_deinit_obj, touchio_touchin_deinit);
+STATIC void check_for_deinit(touchio_touchin_obj_t *self) {
+ if (common_hal_touchio_touchin_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
@@ -114,7 +120,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(touchio_touchin___exit___obj, 4, 4, t
//|
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);
- raise_error_if_deinited(common_hal_touchio_touchin_deinited(self));
+ check_for_deinit(self);
return mp_obj_new_bool(common_hal_touchio_touchin_get_value(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(touchio_touchin_get_value_obj, touchio_touchin_obj_get_value);
@@ -133,7 +139,7 @@ const mp_obj_property_t touchio_touchin_value_obj = {
//|
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);
- raise_error_if_deinited(common_hal_touchio_touchin_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_touchio_touchin_get_raw_value(self));
}
@@ -158,7 +164,7 @@ const mp_obj_property_t touchio_touchin_raw_value_obj = {
//|
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);
- raise_error_if_deinited(common_hal_touchio_touchin_deinited(self));
+ check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_touchio_touchin_get_threshold(self));
}
@@ -166,7 +172,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(touchio_touchin_get_threshold_obj, touchio_touchin_obj
STATIC mp_obj_t touchio_touchin_obj_set_threshold(mp_obj_t self_in, mp_obj_t threshold_obj) {
touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- raise_error_if_deinited(common_hal_touchio_touchin_deinited(self));
+ check_for_deinit(self);
uint32_t new_threshold = mp_obj_get_int(threshold_obj);
if (new_threshold < 0 || new_threshold > UINT16_MAX) {
// I would use MP_STRINGIFY(UINT16_MAX), but that prints "0xffff" instead of 65536.
diff --git a/shared-bindings/uheap/__init__.c b/shared-bindings/uheap/__init__.c
index df18237ac..0d699cd28 100644
--- a/shared-bindings/uheap/__init__.c
+++ b/shared-bindings/uheap/__init__.c
@@ -38,7 +38,7 @@
//| :synopsis: Heap size analysis
//|
-//| .. method:: info(object)
+//| .. function:: info(object)
//|
//| Prints memory debugging info for the given object and returns the
//| estimated size.
diff --git a/shared-bindings/ustack/__init__.c b/shared-bindings/ustack/__init__.c
index c4391c132..08b772e41 100644
--- a/shared-bindings/ustack/__init__.c
+++ b/shared-bindings/ustack/__init__.c
@@ -39,7 +39,7 @@
//|
#if MICROPY_MAX_STACK_USAGE
-//| .. method:: max_stack_usage()
+//| .. function:: max_stack_usage()
//|
//| Return the maximum excursion of the stack so far.
//|
@@ -50,7 +50,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(max_stack_usage_obj, max_stack_usage);
#endif // MICROPY_MAX_STACK_USAGE
-//| .. method:: stack_size()
+//| .. function:: stack_size()
//|
//| Return the size of the entire stack.
//| Same as in micropython.mem_info(), but returns a value instead
@@ -61,7 +61,7 @@ STATIC mp_obj_t stack_size(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(stack_size_obj, stack_size);
-//| .. method:: stack_usage()
+//| .. function:: stack_usage()
//|
//| Return how much stack is currently in use.
//| Same as micropython.stack_use(); duplicated here for convenience.
diff --git a/shared-bindings/util.c b/shared-bindings/util.c
index 80a0bdaeb..c1ca01e0a 100644
--- a/shared-bindings/util.c
+++ b/shared-bindings/util.c
@@ -32,11 +32,9 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-// Check if pin is None. If so, deinit() has already been called on the object, so complain.
-void raise_error_if_deinited(bool deinited) {
- if (deinited) {
- mp_raise_ValueError(translate("Object has been deinitialized and can no longer be used. Create a new object."));
- }
+// If so, deinit() has already been called on the object, so complain.
+void raise_deinited_error(void) {
+ mp_raise_ValueError(translate("Object has been deinitialized and can no longer be used. Create a new object."));
}
diff --git a/shared-bindings/util.h b/shared-bindings/util.h
index b26ed7e93..33454f10e 100644
--- a/shared-bindings/util.h
+++ b/shared-bindings/util.h
@@ -27,7 +27,7 @@
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_UTIL_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_UTIL_H
-void raise_error_if_deinited(bool deinited);
+void raise_deinited_error(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_UTIL_H
diff --git a/shared-bindings/wiznet/wiznet5k.c b/shared-bindings/wiznet/wiznet5k.c
index 878095b2a..ac89cc691 100644
--- a/shared-bindings/wiznet/wiznet5k.c
+++ b/shared-bindings/wiznet/wiznet5k.c
@@ -138,7 +138,7 @@ const mp_obj_property_t wiznet5k_dhcp_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-//| .. method:: ifconfig(...)
+//| .. method:: ifconfig(params=None)
//|
//| Called without parameters, returns a tuple of
//| (ip_address, subnet_mask, gateway_address, dns_server)
diff --git a/shared-module/audioio/WaveFile.h b/shared-module/audioio/WaveFile.h
index 75a46c03b..2cee2b1d2 100644
--- a/shared-module/audioio/WaveFile.h
+++ b/shared-module/audioio/WaveFile.h
@@ -44,7 +44,7 @@ typedef struct {
uint32_t bytes_remaining;
uint8_t channel_count;
- uint16_t sample_rate;
+ uint32_t sample_rate;
uint32_t len;
pyb_file_obj_t* file;
diff --git a/shared-module/bleio/Address.h b/shared-module/bleio/Address.h
index f0998c163..65f493c16 100644
--- a/shared-module/bleio/Address.h
+++ b/shared-module/bleio/Address.h
@@ -27,14 +27,12 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H
#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H
-#include "shared-bindings/bleio/AddressType.h"
-
-#define BLEIO_ADDRESS_BYTES 6
+#define NUM_BLEIO_ADDRESS_BYTES 6
typedef struct {
mp_obj_base_t base;
- bleio_address_type_t type;
- uint8_t value[BLEIO_ADDRESS_BYTES];
+ uint8_t type;
+ uint8_t bytes[NUM_BLEIO_ADDRESS_BYTES];
} bleio_address_obj_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H
diff --git a/shared-module/bleio/ScanEntry.h b/shared-module/bleio/ScanEntry.h
index 2f01669e2..6ae7334a8 100644
--- a/shared-module/bleio/ScanEntry.h
+++ b/shared-module/bleio/ScanEntry.h
@@ -31,9 +31,9 @@
typedef struct {
mp_obj_base_t base;
- bleio_address_obj_t address;
bool connectable;
int8_t rssi;
+ bleio_address_obj_t address;
mp_obj_t data;
} bleio_scanentry_obj_t;
diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c
index ac4de2fe5..be8502bc0 100644
--- a/shared-module/board/__init__.c
+++ b/shared-module/board/__init__.c
@@ -103,7 +103,7 @@ void reset_board_busses(void) {
#endif
#if BOARD_SPI
bool display_using_spi = false;
- #ifdef CIRCUITPY_DISPLAYIO
+ #if CIRCUITPY_DISPLAYIO
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].fourwire_bus.bus == spi_singleton) {
display_using_spi = true;
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index 3b1613974..0ae88300a 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -107,28 +107,26 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
supervisor_start_terminal(width, height);
- // Set the group after initialization otherwise we may send pixels while we delay in
- // initialization.
- self->refresh = true;
- self->current_group = &circuitpython_splash;
-
self->width = width;
self->height = height;
rotation = rotation % 360;
- self->mirror_x = false;
- self->mirror_y = false;
- self->transpose_xy = false;
+ self->transform.x = 0;
+ self->transform.y = 0;
+ self->transform.scale = 1;
+ self->transform.mirror_x = false;
+ self->transform.mirror_y = false;
+ self->transform.transpose_xy = false;
if (rotation == 0 || rotation == 180) {
if (rotation == 180) {
- self->mirror_x = true;
- self->mirror_y = true;
+ self->transform.mirror_x = true;
+ self->transform.mirror_y = true;
}
} else {
- self->transpose_xy = true;
- if (rotation == 90) {
- self->mirror_y = true;
+ self->transform.transpose_xy = true;
+ if (rotation == 270) {
+ self->transform.mirror_y = true;
} else {
- self->mirror_x = true;
+ self->transform.mirror_x = true;
}
}
@@ -148,13 +146,52 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
}
}
}
+
+ self->area.x1 = 0;
+ self->area.y1 = 0;
+ self->area.next = NULL;
+
+ self->transform.dx = 1;
+ self->transform.dy = 1;
+ if (self->transform.transpose_xy) {
+ self->area.x2 = height;
+ self->area.y2 = width;
+ if (self->transform.mirror_x) {
+ self->transform.x = height;
+ self->transform.dx = -1;
+ }
+ if (self->transform.mirror_y) {
+ self->transform.y = width;
+ self->transform.dy = -1;
+ }
+ } else {
+ self->area.x2 = width;
+ self->area.y2 = height;
+ if (self->transform.mirror_x) {
+ self->transform.x = width;
+ self->transform.dx = -1;
+ }
+ if (self->transform.mirror_y) {
+ self->transform.y = height;
+ self->transform.dy = -1;
+ }
+ }
+
+ // Set the group after initialization otherwise we may send pixels while we delay in
+ // initialization.
+ common_hal_displayio_display_show(self, &circuitpython_splash);
}
void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
if (root_group == NULL) {
root_group = &circuitpython_splash;
}
+ if (root_group == self->current_group) {
+ return;
+ }
+ displayio_group_update_transform(root_group, &self->transform);
self->current_group = root_group;
+ self->full_refresh = true;
common_hal_displayio_display_refresh_soon(self);
}
@@ -162,6 +199,15 @@ void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self) {
self->refresh = true;
}
+const displayio_area_t* displayio_display_get_refresh_areas(displayio_display_obj_t *self) {
+ if (self->full_refresh) {
+ self->area.next = NULL;
+ return &self->area;
+ } else {
+ return displayio_group_get_refresh_areas(self->current_group, NULL);
+ }
+}
+
int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self) {
uint64_t last_refresh = self->last_refresh;
// Don't try to refresh if we got an exception.
@@ -224,7 +270,6 @@ void displayio_display_end_transaction(displayio_display_obj_t* self) {
}
void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
-
self->send(self->bus, true, &self->set_column_command, 1);
bool isCommand = self->data_as_commands;
if (self->single_byte_bounds) {
@@ -255,13 +300,16 @@ void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint1
}
}
-bool displayio_display_frame_queued(displayio_display_obj_t* self) {
- // Refresh at ~30 fps.
- return (ticks_ms - self->last_refresh) > 32;
+void displayio_display_start_refresh(displayio_display_obj_t* self) {
+ self->last_refresh = ticks_ms;
}
-bool displayio_display_refresh_queued(displayio_display_obj_t* self) {
- return self->refresh || (self->current_group != NULL && displayio_group_needs_refresh(self->current_group));
+bool displayio_display_frame_queued(displayio_display_obj_t* self) {
+ if (self->current_group == NULL) {
+ return false;
+ }
+ // Refresh at ~60 fps.
+ return (ticks_ms - self->last_refresh) > 16;
}
void displayio_display_finish_refresh(displayio_display_obj_t* self) {
@@ -269,11 +317,12 @@ void displayio_display_finish_refresh(displayio_display_obj_t* self) {
displayio_group_finish_refresh(self->current_group);
}
self->refresh = false;
+ self->full_refresh = false;
self->last_refresh = ticks_ms;
}
-void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
- self->send(self->bus, false, (uint8_t*) pixels, length * 4);
+void displayio_display_send_pixels(displayio_display_obj_t* self, uint8_t* pixels, uint32_t length) {
+ self->send(self->bus, false, pixels, length);
}
void displayio_display_update_backlight(displayio_display_obj_t* self) {
@@ -298,3 +347,11 @@ void release_display(displayio_display_obj_t* self) {
common_hal_digitalio_digitalinout_deinit(&self->backlight_inout);
}
}
+
+bool displayio_display_fill_area(displayio_display_obj_t *self, displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
+ return displayio_group_fill_area(self->current_group, area, mask, buffer);
+}
+
+bool displayio_display_clip_area(displayio_display_obj_t *self, const displayio_area_t* area, displayio_area_t* clipped) {
+ return displayio_area_compute_overlap(&self->area, area, clipped);
+}
diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h
index 52f98a252..fa8902ced 100644
--- a/shared-module/displayio/Display.h
+++ b/shared-module/displayio/Display.h
@@ -31,6 +31,8 @@
#include "shared-bindings/displayio/Group.h"
#include "shared-bindings/pulseio/PWMOut.h"
+#include "shared-module/displayio/area.h"
+
typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
typedef void (*display_bus_send)(mp_obj_t bus, bool command, uint8_t *data, uint32_t data_length);
typedef void (*display_bus_end_transaction)(mp_obj_t bus);
@@ -38,19 +40,8 @@ typedef void (*display_bus_end_transaction)(mp_obj_t bus);
typedef struct {
mp_obj_base_t base;
mp_obj_t bus;
- uint16_t width;
- uint16_t height;
- uint16_t color_depth;
- uint8_t set_column_command;
- uint8_t set_row_command;
- uint8_t write_ram_command;
displayio_group_t *current_group;
- bool refresh;
uint64_t last_refresh;
- int16_t colstart;
- int16_t rowstart;
- bool single_byte_bounds;
- bool data_as_commands;
display_bus_begin_transaction begin_transaction;
display_bus_send send;
display_bus_end_transaction end_transaction;
@@ -59,14 +50,29 @@ typedef struct {
pulseio_pwmout_obj_t backlight_pwm;
};
uint64_t last_backlight_refresh;
- bool auto_brightness:1;
- bool updating_backlight:1;
- bool mirror_x;
- bool mirror_y;
- bool transpose_xy;
+ displayio_buffer_transform_t transform;
+ displayio_area_t area;
+ uint16_t width;
+ uint16_t height;
+ uint16_t color_depth;
+ int16_t colstart;
+ int16_t rowstart;
+ uint8_t set_column_command;
+ uint8_t set_row_command;
+ uint8_t write_ram_command;
+ bool refresh;
+ bool single_byte_bounds;
+ bool data_as_commands;
+ bool auto_brightness;
+ bool updating_backlight;
+ bool full_refresh; // New group means we need to refresh the whole display.
} displayio_display_obj_t;
+void displayio_display_start_refresh(displayio_display_obj_t* self);
+const displayio_area_t* displayio_display_get_refresh_areas(displayio_display_obj_t *self);
+bool displayio_display_fill_area(displayio_display_obj_t *self, displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
void displayio_display_update_backlight(displayio_display_obj_t* self);
+bool displayio_display_clip_area(displayio_display_obj_t *self, const displayio_area_t* area, displayio_area_t* clipped);
void release_display(displayio_display_obj_t* self);
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
diff --git a/shared-module/displayio/Group.c b/shared-module/displayio/Group.c
index 40f112bf1..15060e87b 100644
--- a/shared-module/displayio/Group.c
+++ b/shared-module/displayio/Group.c
@@ -38,9 +38,85 @@ uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self) {
return self->scale;
}
+bool displayio_group_get_previous_area(displayio_group_t *self, displayio_area_t* area) {
+ bool first = true;
+ for (size_t i = 0; i < self->size; i++) {
+ mp_obj_t layer = self->children[i].native;
+ displayio_area_t layer_area;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ if (!displayio_tilegrid_get_previous_area(layer, &layer_area)) {
+ continue;
+ }
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ if (!displayio_group_get_previous_area(layer, &layer_area)) {
+ continue;
+ }
+ }
+ if (first) {
+ displayio_area_copy(&layer_area, area);
+ first = false;
+ } else {
+ displayio_area_expand(area, &layer_area);
+ }
+ }
+ if (self->item_removed) {
+ if (first) {
+ displayio_area_copy(&self->dirty_area, area);
+ first = false;
+ } else {
+ displayio_area_expand(area, &self->dirty_area);
+ }
+ }
+ return !first;
+}
+
+static void _update_child_transforms(displayio_group_t* self) {
+ if (!self->in_group) {
+ return;
+ }
+ for (size_t i = 0; i < self->size; i++) {
+ mp_obj_t layer = self->children[i].native;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ displayio_tilegrid_update_transform(layer, &self->absolute_transform);
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ displayio_group_update_transform(layer, &self->absolute_transform);
+ }
+ }
+}
+
+void displayio_group_update_transform(displayio_group_t *self,
+ const displayio_buffer_transform_t* parent_transform) {
+ self->in_group = parent_transform != NULL;
+ if (self->in_group) {
+ int16_t x = self->x;
+ int16_t y = self->y;
+ if (parent_transform->transpose_xy) {
+ x = y;
+ y = self->x;
+ }
+ self->absolute_transform.x = parent_transform->x + parent_transform->dx * x;
+ self->absolute_transform.y = parent_transform->y + parent_transform->dy * y;
+ self->absolute_transform.dx = parent_transform->dx * self->scale;
+ self->absolute_transform.dy = parent_transform->dy * self->scale;
+ self->absolute_transform.transpose_xy = parent_transform->transpose_xy;
+ self->absolute_transform.mirror_x = parent_transform->mirror_x;
+ self->absolute_transform.mirror_y = parent_transform->mirror_y;
+
+ self->absolute_transform.scale = parent_transform->scale * self->scale;
+ }
+ _update_child_transforms(self);
+}
+
void common_hal_displayio_group_set_scale(displayio_group_t* self, uint32_t scale) {
- self->needs_refresh = self->scale != scale;
+ if (self->scale == scale) {
+ return;
+ }
+ uint8_t parent_scale = self->absolute_transform.scale / self->scale;
+ self->absolute_transform.dx = self->absolute_transform.dx / self->scale * scale;
+ self->absolute_transform.dy = self->absolute_transform.dy / self->scale * scale;
+ self->absolute_transform.scale = parent_scale * scale;
self->scale = scale;
+ _update_child_transforms(self);
}
mp_int_t common_hal_displayio_group_get_x(displayio_group_t* self) {
@@ -48,8 +124,19 @@ mp_int_t common_hal_displayio_group_get_x(displayio_group_t* self) {
}
void common_hal_displayio_group_set_x(displayio_group_t* self, mp_int_t x) {
- self->needs_refresh = self->x != x;
+ if (self->x == x) {
+ return;
+ }
+ if (self->absolute_transform.transpose_xy) {
+ int16_t dy = self->absolute_transform.dy / self->scale;
+ self->absolute_transform.y += dy * (x - self->x);
+ } else {
+ int16_t dx = self->absolute_transform.dx / self->scale;
+ self->absolute_transform.x += dx * (x - self->x);
+ }
+
self->x = x;
+ _update_child_transforms(self);
}
mp_int_t common_hal_displayio_group_get_y(displayio_group_t* self) {
@@ -57,21 +144,75 @@ mp_int_t common_hal_displayio_group_get_y(displayio_group_t* self) {
}
void common_hal_displayio_group_set_y(displayio_group_t* self, mp_int_t y) {
- self->needs_refresh = self->y != y;
+ if (self->y == y) {
+ return;
+ }
+ if (self->absolute_transform.transpose_xy) {
+ int8_t dx = self->absolute_transform.dx / self->scale;
+ self->absolute_transform.x += dx * (y - self->y);
+ } else {
+ int8_t dy = self->absolute_transform.dy / self->scale;
+ self->absolute_transform.y += dy * (y - self->y);
+ }
self->y = y;
+ _update_child_transforms(self);
}
-void common_hal_displayio_group_insert(displayio_group_t* self, size_t index, mp_obj_t layer) {
- if (self->size == self->max_size) {
- mp_raise_RuntimeError(translate("Group full"));
- }
+static mp_obj_t _add_layer(displayio_group_t* self, mp_obj_t layer) {
mp_obj_t native_layer = mp_instance_cast_to_native_base(layer, &displayio_group_type);
if (native_layer == MP_OBJ_NULL) {
native_layer = mp_instance_cast_to_native_base(layer, &displayio_tilegrid_type);
+ if (native_layer == MP_OBJ_NULL) {
+ mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass."));
+ }
+ displayio_tilegrid_t* tilegrid = native_layer;
+ if (tilegrid->in_group) {
+ mp_raise_ValueError(translate("Layer already in a group."));
+ } else {
+ tilegrid->in_group = true;
+ }
+ displayio_tilegrid_update_transform(tilegrid, &self->absolute_transform);
+ } else {
+ displayio_group_t* group = native_layer;
+ if (group->in_group) {
+ mp_raise_ValueError(translate("Layer already in a group."));
+ } else {
+ group->in_group = true;
+ }
+ displayio_group_update_transform(group, &self->absolute_transform);
}
- if (native_layer == MP_OBJ_NULL) {
- mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass."));
+ return native_layer;
+}
+
+static void _remove_layer(displayio_group_t* self, size_t index) {
+ mp_obj_t layer = self->children[index].native;
+ displayio_area_t layer_area;
+ bool rendered_last_frame = false;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ displayio_tilegrid_t* tilegrid = layer;
+ rendered_last_frame = displayio_tilegrid_get_previous_area(tilegrid, &layer_area);
+ displayio_tilegrid_update_transform(tilegrid, NULL);
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ displayio_group_t* group = layer;
+ rendered_last_frame = displayio_group_get_previous_area(group, &layer_area);
+ displayio_group_update_transform(group, NULL);
+ }
+ if (!rendered_last_frame) {
+ return;
+ }
+ if (!self->item_removed) {
+ displayio_area_copy(&layer_area, &self->dirty_area);
+ } else {
+ displayio_area_expand(&self->dirty_area, &layer_area);
}
+ self->item_removed = true;
+}
+
+void common_hal_displayio_group_insert(displayio_group_t* self, size_t index, mp_obj_t layer) {
+ if (self->size == self->max_size) {
+ mp_raise_RuntimeError(translate("Group full"));
+ }
+ mp_obj_t native_layer = _add_layer(self, layer);
// Shift everything right.
for (size_t i = self->size; i > index; i--) {
self->children[i] = self->children[i - 1];
@@ -79,19 +220,19 @@ void common_hal_displayio_group_insert(displayio_group_t* self, size_t index, mp
self->children[index].native = native_layer;
self->children[index].original = layer;
self->size++;
- self->needs_refresh = true;
}
mp_obj_t common_hal_displayio_group_pop(displayio_group_t* self, size_t index) {
self->size--;
mp_obj_t item = self->children[index].original;
+ _remove_layer(self, index);
+
// Shift everything left.
for (size_t i = index; i < self->size; i++) {
self->children[i] = self->children[i + 1];
}
self->children[self->size].native = NULL;
self->children[self->size].original = NULL;
- self->needs_refresh = true;
return item;
}
@@ -113,16 +254,10 @@ mp_obj_t common_hal_displayio_group_get(displayio_group_t* self, size_t index) {
}
void common_hal_displayio_group_set(displayio_group_t* self, size_t index, mp_obj_t layer) {
- mp_obj_t native_layer = mp_instance_cast_to_native_base(layer, &displayio_group_type);
- if (native_layer == MP_OBJ_NULL) {
- native_layer = mp_instance_cast_to_native_base(layer, &displayio_tilegrid_type);
- }
- if (native_layer == MP_OBJ_NULL) {
- mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass."));
- }
+ mp_obj_t native_layer = _add_layer(self, layer);
+ _remove_layer(self, index);
self->children[index].native = native_layer;
self->children[index].original = layer;
- self->needs_refresh = true;
}
void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y) {
@@ -130,65 +265,58 @@ void displayio_group_construct(displayio_group_t* self, displayio_group_child_t*
self->y = y;
self->children = child_array;
self->max_size = max_size;
- self->needs_refresh = false;
+ self->item_removed = false;
self->scale = scale;
+ self->in_group = false;
}
-bool displayio_group_get_pixel(displayio_group_t *self, int16_t x, int16_t y, uint16_t* pixel) {
- x -= self->x;
- y -= self->y;
- // When we are scaled we need to substract all but one to ensure -scale to 0 divide down to -1.
- // Normally -scale to scale both divide down to 0 because 0 is unsigned.
- if (x < 0) {
- x -= self->scale - 1;
- }
- if (y < 0) {
- y -= self->scale - 1;
- }
- x /= self->scale;
- y /= self->scale;
+bool displayio_group_fill_area(displayio_group_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t* buffer) {
+ // Track if any of the layers finishes filling in the given area. We can ignore any remaining
+ // layers at that point.
+ bool full_coverage = false;
for (int32_t i = self->size - 1; i >= 0 ; i--) {
mp_obj_t layer = self->children[i].native;
if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
- if (displayio_tilegrid_get_pixel(layer, x, y, pixel)) {
- return true;
+ if (displayio_tilegrid_fill_area(layer, area, mask, buffer)) {
+ full_coverage = true;
+ break;
}
} else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
- if (displayio_group_get_pixel(layer, x, y, pixel)) {
- return true;
+ if (displayio_group_fill_area(layer, area, mask, buffer)) {
+ full_coverage = true;
+ break;
}
}
}
- return false;
+ return full_coverage;
}
-bool displayio_group_needs_refresh(displayio_group_t *self) {
- if (self->needs_refresh) {
- return true;
- }
+void displayio_group_finish_refresh(displayio_group_t *self) {
+ self->item_removed = false;
for (int32_t i = self->size - 1; i >= 0 ; i--) {
mp_obj_t layer = self->children[i].native;
if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
- if (displayio_tilegrid_needs_refresh(layer)) {
- return true;
- }
+ displayio_tilegrid_finish_refresh(layer);
} else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
- if (displayio_group_needs_refresh(layer)) {
- return true;
- }
+ displayio_group_finish_refresh(layer);
}
}
- return false;
}
-void displayio_group_finish_refresh(displayio_group_t *self) {
- self->needs_refresh = false;
+displayio_area_t* displayio_group_get_refresh_areas(displayio_group_t *self, displayio_area_t* tail) {
+ if (self->item_removed) {
+ self->dirty_area.next = tail;
+ tail = &self->dirty_area;
+ }
+
for (int32_t i = self->size - 1; i >= 0 ; i--) {
mp_obj_t layer = self->children[i].native;
if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
- displayio_tilegrid_finish_refresh(layer);
+ tail = displayio_tilegrid_get_refresh_areas(layer, tail);
} else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
- displayio_group_finish_refresh(layer);
+ tail = displayio_group_get_refresh_areas(layer, tail);
}
}
+
+ return tail;
}
diff --git a/shared-module/displayio/Group.h b/shared-module/displayio/Group.h
index 7826b9e66..7ce19a4cd 100644
--- a/shared-module/displayio/Group.h
+++ b/shared-module/displayio/Group.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include "py/obj.h"
+#include "shared-module/displayio/area.h"
typedef struct {
mp_obj_t native;
@@ -39,18 +40,23 @@ typedef struct {
typedef struct {
mp_obj_base_t base;
+ displayio_group_child_t* children;
int16_t x;
int16_t y;
uint16_t scale;
uint16_t size;
uint16_t max_size;
- displayio_group_child_t* children;
- bool needs_refresh;
+ bool item_removed;
+ bool in_group;
+ displayio_buffer_transform_t absolute_transform;
+ displayio_area_t dirty_area; // Catch all for changed area
} displayio_group_t;
void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y);
-bool displayio_group_get_pixel(displayio_group_t *group, int16_t x, int16_t y, uint16_t *pixel);
-bool displayio_group_needs_refresh(displayio_group_t *self);
+bool displayio_group_get_previous_area(displayio_group_t *group, displayio_area_t* area);
+bool displayio_group_fill_area(displayio_group_t *group, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
+void displayio_group_update_transform(displayio_group_t *group, const displayio_buffer_transform_t* parent_transform);
void displayio_group_finish_refresh(displayio_group_t *self);
+displayio_area_t* displayio_group_get_refresh_areas(displayio_group_t *self, displayio_area_t* tail);
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_GROUP_H
diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c
index e810be875..8dc6e766b 100644
--- a/shared-module/displayio/Palette.c
+++ b/shared-module/displayio/Palette.c
@@ -53,7 +53,11 @@ void common_hal_displayio_palette_set_color(displayio_palette_t* self, uint32_t
uint32_t packed = r5 << 11 | g6 << 5 | b5;
// swap bytes
packed = __builtin_bswap16(packed);
- self->colors[palette_index / 2] = masked | packed << shift;
+ uint32_t final_color = masked | packed << shift;
+ if (self->colors[palette_index / 2] == final_color) {
+ return;
+ }
+ self->colors[palette_index / 2] = final_color;
self->needs_refresh = true;
}
diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c
index 3212dfe8b..97b704c40 100644
--- a/shared-module/displayio/TileGrid.c
+++ b/shared-module/displayio/TileGrid.c
@@ -56,31 +56,123 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_
self->bitmap_width_in_tiles = bitmap_width_in_tiles;
self->width_in_tiles = width;
self->height_in_tiles = height;
- self->total_width = width * tile_width;
- self->total_height = height * tile_height;
+ self->x = x;
+ self->y = y;
+ self->pixel_width = width * tile_width;
+ self->pixel_height = height * tile_height;
self->tile_width = tile_width;
self->tile_height = tile_height;
self->bitmap = bitmap;
self->pixel_shader = pixel_shader;
- self->x = x;
- self->y = y;
+ self->in_group = false;
+ self->first_draw = true;
+ self->flip_x = false;
+ self->flip_y = false;
+ self->transpose_xy = false;
}
+bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_area_t* area) {
+ if (self->first_draw) {
+ return false;
+ }
+ displayio_area_copy(&self->previous_area, area);
+ return true;
+}
+
+void _update_current_x(displayio_tilegrid_t *self) {
+ int16_t width;
+ if (self->transpose_xy) {
+ width = self->pixel_height;
+ } else {
+ width = self->pixel_width;
+ }
+ if (self->absolute_transform->transpose_xy) {
+ self->current_area.y1 = self->absolute_transform->y + self->absolute_transform->dy * self->x;
+ self->current_area.y2 = self->absolute_transform->y + self->absolute_transform->dy * (self->x + width);
+ if (self->current_area.y2 < self->current_area.y1) {
+ int16_t temp = self->current_area.y2;
+ self->current_area.y2 = self->current_area.y1;
+ self->current_area.y1 = temp;
+ }
+ } else {
+ self->current_area.x1 = self->absolute_transform->x + self->absolute_transform->dx * self->x;
+ self->current_area.x2 = self->absolute_transform->x + self->absolute_transform->dx * (self->x + width);
+ if (self->current_area.x2 < self->current_area.x1) {
+ int16_t temp = self->current_area.x2;
+ self->current_area.x2 = self->current_area.x1;
+ self->current_area.x1 = temp;
+ }
+ }
+}
+
+void _update_current_y(displayio_tilegrid_t *self) {
+ int16_t height;
+ if (self->transpose_xy) {
+ height = self->pixel_width;
+ } else {
+ height = self->pixel_height;
+ }
+ if (self->absolute_transform->transpose_xy) {
+ self->current_area.x1 = self->absolute_transform->x + self->absolute_transform->dx * self->y;
+ self->current_area.x2 = self->absolute_transform->x + self->absolute_transform->dx * (self->y + height);
+ if (self->current_area.x2 < self->current_area.x1) {
+ int16_t temp = self->current_area.x2;
+ self->current_area.x2 = self->current_area.x1;
+ self->current_area.x1 = temp;
+ }
+ } else {
+ self->current_area.y1 = self->absolute_transform->y + self->absolute_transform->dy * self->y;
+ self->current_area.y2 = self->absolute_transform->y + self->absolute_transform->dy * (self->y + height);
+ if (self->current_area.y2 < self->current_area.y1) {
+ int16_t temp = self->current_area.y2;
+ self->current_area.y2 = self->current_area.y1;
+ self->current_area.y1 = temp;
+ }
+ }
+}
+
+void displayio_tilegrid_update_transform(displayio_tilegrid_t *self,
+ const displayio_buffer_transform_t* absolute_transform) {
+ self->in_group = absolute_transform != NULL;
+ self->absolute_transform = absolute_transform;
+ if (absolute_transform != NULL) {
+ self->moved = !self->first_draw;
+
+ _update_current_x(self);
+ _update_current_y(self);
+ } else {
+ self->first_draw = true;
+ }
+}
mp_int_t common_hal_displayio_tilegrid_get_x(displayio_tilegrid_t *self) {
return self->x;
}
void common_hal_displayio_tilegrid_set_x(displayio_tilegrid_t *self, mp_int_t x) {
- self->needs_refresh = self->x != x;
+ if (self->x == x) {
+ return;
+ }
+
+ self->moved = !self->first_draw;
+
self->x = x;
+ if (self->absolute_transform != NULL) {
+ _update_current_x(self);
+ }
}
mp_int_t common_hal_displayio_tilegrid_get_y(displayio_tilegrid_t *self) {
return self->y;
}
void common_hal_displayio_tilegrid_set_y(displayio_tilegrid_t *self, mp_int_t y) {
- self->needs_refresh = self->y != y;
+ if (self->y == y) {
+ return;
+ }
+ self->moved = !self->first_draw;
self->y = y;
+ if (self->absolute_transform != NULL) {
+ _update_current_y(self);
+ }
}
mp_obj_t common_hal_displayio_tilegrid_get_pixel_shader(displayio_tilegrid_t *self) {
@@ -89,10 +181,9 @@ mp_obj_t common_hal_displayio_tilegrid_get_pixel_shader(displayio_tilegrid_t *se
void common_hal_displayio_tilegrid_set_pixel_shader(displayio_tilegrid_t *self, mp_obj_t pixel_shader) {
self->pixel_shader = pixel_shader;
- self->needs_refresh = true;
+ self->full_change = true;
}
-
uint16_t common_hal_displayio_tilegrid_get_width(displayio_tilegrid_t *self) {
return self->width_in_tiles;
}
@@ -121,21 +212,78 @@ void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t
return;
}
tiles[y * self->width_in_tiles + x] = tile_index;
- self->needs_refresh = true;
+ displayio_area_t temp_area;
+ displayio_area_t* tile_area;
+ if (!self->partial_change) {
+ tile_area = &self->dirty_area;
+ } else {
+ tile_area = &temp_area;
+ }
+ tile_area->x1 = x * self->tile_width;
+ tile_area->x2 = tile_area->x1 + self->tile_width;
+ tile_area->y1 = y * self->tile_height;
+ tile_area->y2 = tile_area->y1 + self->tile_height;
+ if (self->partial_change) {
+ displayio_area_expand(&self->dirty_area, &temp_area);
+ }
+
+ self->partial_change = true;
+}
+
+bool common_hal_displayio_tilegrid_get_flip_x(displayio_tilegrid_t *self) {
+ return self->flip_x;
+}
+
+void common_hal_displayio_tilegrid_set_flip_x(displayio_tilegrid_t *self, bool flip_x) {
+ if (self->flip_x == flip_x) {
+ return;
+ }
+ self->flip_x = flip_x;
+ self->full_change = true;
+}
+
+bool common_hal_displayio_tilegrid_get_flip_y(displayio_tilegrid_t *self) {
+ return self->flip_y;
+}
+
+void common_hal_displayio_tilegrid_set_flip_y(displayio_tilegrid_t *self, bool flip_y) {
+ if (self->flip_y == flip_y) {
+ return;
+ }
+ self->flip_y = flip_y;
+ self->full_change = true;
}
+bool common_hal_displayio_tilegrid_get_transpose_xy(displayio_tilegrid_t *self) {
+ return self->transpose_xy;
+}
+
+void common_hal_displayio_tilegrid_set_transpose_xy(displayio_tilegrid_t *self, bool transpose_xy) {
+ if (self->transpose_xy == transpose_xy) {
+ return;
+ }
+ self->transpose_xy = transpose_xy;
+
+ // Square TileGrids do not change dimensions when transposed.
+ if (self->pixel_width == self->pixel_height) {
+ self->full_change = true;
+ return;
+ }
+
+ _update_current_x(self);
+ _update_current_y(self);
+
+ self->moved = true;
+}
void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y) {
self->top_left_x = x;
self->top_left_y = y;
+ self->full_change = true;
}
-bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t y, uint16_t* pixel) {
- x -= self->x;
- y -= self->y;
- if (y < 0 || y >= self->total_height || x >= self->total_width || x < 0) {
- return false;
- }
+bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
+ // If no tiles are present we have no impact.
uint8_t* tiles = self->tiles;
if (self->inline_tiles) {
tiles = (uint8_t*) &self->tiles;
@@ -143,46 +291,143 @@ bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t
if (tiles == NULL) {
return false;
}
- uint16_t tile_location = ((y / self->tile_height + self->top_left_y) % self->height_in_tiles) * self->width_in_tiles + (x / self->tile_width + self->top_left_x) % self->width_in_tiles;
- uint8_t tile = tiles[tile_location];
- uint16_t tile_x = tile_x = (tile % self->bitmap_width_in_tiles) * self->tile_width + x % self->tile_width;
- uint16_t tile_y = tile_y = (tile / self->bitmap_width_in_tiles) * self->tile_height + y % self->tile_height;
- uint32_t value = 0;
- if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
- value = common_hal_displayio_bitmap_get_pixel(self->bitmap, tile_x, tile_y);
- } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
- value = common_hal_displayio_shape_get_pixel(self->bitmap, tile_x, tile_y);
- } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
- value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ displayio_area_t overlap;
+ if (!displayio_area_compute_overlap(area, &self->current_area, &overlap)) {
+ return false;
}
- if (self->pixel_shader == mp_const_none) {
- *pixel = value;
- return true;
- } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) && displayio_palette_get_color(self->pixel_shader, value, pixel)) {
- return true;
- } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type) && common_hal_displayio_colorconverter_convert(self->pixel_shader, value, pixel)) {
- return true;
+ int16_t x_stride = 1;
+ int16_t y_stride = displayio_area_width(area);
+
+ bool flip_x = self->flip_x;
+ bool flip_y = self->flip_y;
+ if (self->transpose_xy != self->absolute_transform->transpose_xy) {
+ bool temp_flip = flip_x;
+ flip_x = flip_y;
+ flip_y = temp_flip;
}
- return false;
-}
+ // How many pixels are outside of our area between us and the start of the row.
+ uint16_t start = 0;
+ if ((self->absolute_transform->dx < 0) != flip_x) {
+ start += (area->x2 - area->x1 - 1) * x_stride;
+ x_stride *= -1;
+ }
+ if ((self->absolute_transform->dy < 0) != flip_y) {
+ start += (area->y2 - area->y1 - 1) * y_stride;
+ y_stride *= -1;
+ }
-bool displayio_tilegrid_needs_refresh(displayio_tilegrid_t *self) {
- if (self->needs_refresh) {
- return true;
- } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
- return displayio_palette_needs_refresh(self->pixel_shader);
- } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
- return displayio_colorconverter_needs_refresh(self->pixel_shader);
+ // Track if this layer finishes filling in the given area. We can ignore any remaining
+ // layers at that point.
+ bool full_coverage = displayio_area_equal(area, &overlap);
+
+ // TODO(tannewt): Skip coverage tracking if all pixels outside the overlap have already been
+ // set and our palette is all opaque.
+
+ // TODO(tannewt): Check to see if the pixel_shader has any transparency. If it doesn't then we
+ // can either return full coverage or bulk update the mask.
+ displayio_area_t transformed;
+ displayio_area_transform_within(flip_x != (self->absolute_transform->dx < 0), flip_y != (self->absolute_transform->dy < 0), self->transpose_xy != self->absolute_transform->transpose_xy,
+ &overlap,
+ &self->current_area,
+ &transformed);
+
+ int16_t start_x = (transformed.x1 - self->current_area.x1);
+ int16_t end_x = (transformed.x2 - self->current_area.x1);
+ int16_t start_y = (transformed.y1 - self->current_area.y1);
+ int16_t end_y = (transformed.y2 - self->current_area.y1);
+
+ int16_t y_shift = 0;
+ int16_t x_shift = 0;
+ if ((self->absolute_transform->dx < 0) != flip_x) {
+ x_shift = area->x2 - overlap.x2;
+ } else {
+ x_shift = overlap.x1 - area->x1;
+ }
+ if ((self->absolute_transform->dy < 0) != flip_y) {
+ y_shift = area->y2 - overlap.y2;
+ } else {
+ y_shift = overlap.y1 - area->y1;
}
- return false;
+ // This untransposes x and y so it aligns with bitmap rows.
+ if (self->transpose_xy != self->absolute_transform->transpose_xy) {
+ int16_t temp_stride = x_stride;
+ x_stride = y_stride;
+ y_stride = temp_stride;
+ int16_t temp_shift = x_shift;
+ x_shift = y_shift;
+ y_shift = temp_shift;
+ }
+
+ for (int16_t y = start_y; y < end_y; y++) {
+ int16_t row_start = start + (y - start_y + y_shift) * y_stride;
+ int16_t local_y = y / self->absolute_transform->scale;
+ for (int16_t x = start_x; x < end_x; x++) {
+ // Compute the destination pixel in the buffer and mask based on the transformations.
+ int16_t offset = row_start + (x - start_x + x_shift) * x_stride;
+
+ // This is super useful for debugging out range accesses. Uncomment to use.
+ // if (offset < 0 || offset >= (int32_t) displayio_area_size(area)) {
+ // asm("bkpt");
+ // }
+
+ // Check the mask first to see if the pixel has already been set.
+ if ((mask[offset / 32] & (1 << (offset % 32))) != 0) {
+ continue;
+ }
+ int16_t local_x = x / self->absolute_transform->scale;
+ uint16_t tile_location = ((local_y / self->tile_height + self->top_left_y) % self->height_in_tiles) * self->width_in_tiles + (local_x / self->tile_width + self->top_left_x) % self->width_in_tiles;
+ uint8_t tile = tiles[tile_location];
+ uint16_t tile_x = (tile % self->bitmap_width_in_tiles) * self->tile_width + local_x % self->tile_width;
+ uint16_t tile_y = (tile / self->bitmap_width_in_tiles) * self->tile_height + local_y % self->tile_height;
+
+ uint32_t value = 0;
+ // We always want to read bitmap pixels by row first and then transpose into the destination
+ // buffer because most bitmaps are row associated.
+ if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
+ value = common_hal_displayio_bitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
+ value = common_hal_displayio_shape_get_pixel(self->bitmap, tile_x, tile_y);
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
+ value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ }
+
+ uint16_t* pixel = ((uint16_t*) buffer) + offset;
+ if (self->pixel_shader == mp_const_none) {
+ *pixel = value;
+ return true;
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
+ if (!displayio_palette_get_color(self->pixel_shader, value, pixel)) {
+ // A pixel is transparent so we haven't fully covered the area ourselves.
+ full_coverage = false;
+ } else {
+ mask[offset / 32] |= 1 << (offset % 32);
+ }
+ } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
+ if (!common_hal_displayio_colorconverter_convert(self->pixel_shader, value, pixel)) {
+ // A pixel is transparent so we haven't fully covered the area ourselves.
+ full_coverage = false;
+ } else {
+ mask[offset / 32] |= 1 << (offset % 32);
+ }
+ }
+ }
+ }
+ return full_coverage;
}
void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
- self->needs_refresh = false;
+ if (self->moved || self->first_draw) {
+ displayio_area_copy(&self->current_area, &self->previous_area);
+ }
+
+ self->moved = false;
+ self->full_change = false;
+ self->partial_change = false;
+ self->first_draw = false;
if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
displayio_palette_finish_refresh(self->pixel_shader);
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
@@ -191,3 +436,58 @@ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
// TODO(tannewt): We could double buffer changes to position and move them over here.
// That way they won't change during a refresh and tear.
}
+
+displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *self, displayio_area_t* tail) {
+ if (self->moved && !self->first_draw) {
+ displayio_area_union(&self->previous_area, &self->current_area, &self->dirty_area);
+ if (displayio_area_size(&self->dirty_area) <= 2 * self->pixel_width * self->pixel_height) {
+ self->dirty_area.next = tail;
+ return &self->dirty_area;
+ }
+ self->previous_area.next = tail;
+ self->current_area.next = &self->previous_area;
+ return &self->current_area;
+ }
+
+ // We must recheck if our sources require a refresh because needs_refresh may or may not have
+ // been called.
+ self->full_change = self->full_change ||
+ (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) &&
+ displayio_palette_needs_refresh(self->pixel_shader)) ||
+ (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type) &&
+ displayio_colorconverter_needs_refresh(self->pixel_shader));
+ if (self->full_change || self->first_draw) {
+ self->current_area.next = tail;
+ return &self->current_area;
+ }
+
+ if (self->partial_change) {
+ if (self->absolute_transform->transpose_xy) {
+ int16_t x1 = self->dirty_area.x1;
+ self->dirty_area.x1 = self->absolute_transform->x + self->absolute_transform->dx * (self->y + self->dirty_area.y1);
+ self->dirty_area.y1 = self->absolute_transform->y + self->absolute_transform->dy * (self->x + x1);
+ int16_t x2 = self->dirty_area.x2;
+ self->dirty_area.x2 = self->absolute_transform->x + self->absolute_transform->dx * (self->y + self->dirty_area.y2);
+ self->dirty_area.y2 = self->absolute_transform->y + self->absolute_transform->dy * (self->x + x2);
+ } else {
+ self->dirty_area.x1 = self->absolute_transform->x + self->absolute_transform->dx * (self->x + self->dirty_area.x1);
+ self->dirty_area.y1 = self->absolute_transform->y + self->absolute_transform->dy * (self->y + self->dirty_area.y1);
+ self->dirty_area.x2 = self->absolute_transform->x + self->absolute_transform->dx * (self->x + self->dirty_area.x2);
+ self->dirty_area.y2 = self->absolute_transform->y + self->absolute_transform->dy * (self->y + self->dirty_area.y2);
+ }
+ if (self->dirty_area.y2 < self->dirty_area.y1) {
+ int16_t temp = self->dirty_area.y2;
+ self->dirty_area.y2 = self->dirty_area.y1;
+ self->dirty_area.y1 = temp;
+ }
+ if (self->dirty_area.x2 < self->dirty_area.x1) {
+ int16_t temp = self->dirty_area.x2;
+ self->dirty_area.x2 = self->dirty_area.x1;
+ self->dirty_area.x1 = temp;
+ }
+
+ self->dirty_area.next = tail;
+ return &self->dirty_area;
+ }
+ return tail;
+}
diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h
index 59645553d..4d97eccc2 100644
--- a/shared-module/displayio/TileGrid.h
+++ b/shared-module/displayio/TileGrid.h
@@ -31,29 +31,52 @@
#include <stdint.h>
#include "py/obj.h"
+#include "shared-module/displayio/area.h"
typedef struct {
mp_obj_base_t base;
mp_obj_t bitmap;
mp_obj_t pixel_shader;
- uint16_t x;
- uint16_t y;
+ int16_t x;
+ int16_t y;
+ uint16_t pixel_width;
+ uint16_t pixel_height;
uint16_t bitmap_width_in_tiles;
uint16_t width_in_tiles;
uint16_t height_in_tiles;
- uint16_t total_width;
- uint16_t total_height;
uint16_t tile_width;
uint16_t tile_height;
uint16_t top_left_x;
uint16_t top_left_y;
uint8_t* tiles;
- bool needs_refresh;
+ const displayio_buffer_transform_t* absolute_transform;
+ displayio_area_t dirty_area; // Stored as a relative area until the refresh area is fetched.
+ displayio_area_t previous_area; // Stored as an absolute area.
+ displayio_area_t current_area; // Stored as an absolute area so it applies across frames.
+ bool partial_change;
+ bool full_change;
+ bool first_draw;
+ bool moved;
bool inline_tiles;
+ bool in_group;
+ bool flip_x;
+ bool flip_y;
+ bool transpose_xy;
} displayio_tilegrid_t;
-bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t y, uint16_t *pixel);
-bool displayio_tilegrid_needs_refresh(displayio_tilegrid_t *self);
+// Updating the screen is a three stage process.
+
+// The first stage is used to determine i
+displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *self, displayio_area_t* tail);
+
+// Area is always in absolute screen coordinates. Update transform is used to inform TileGrids how
+// they relate to it.
+bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
+void displayio_tilegrid_update_transform(displayio_tilegrid_t *group, const displayio_buffer_transform_t* parent_transform);
+
+// Fills in area with the maximum bounds of all related pixels in the last rendered frame. Returns
+// false if the tilegrid wasn't rendered in the last frame.
+bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_area_t* area);
void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self);
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index 156640440..b6709e0eb 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -1,8 +1,10 @@
#include <string.h>
+
#include "shared-module/displayio/__init__.h"
#include "lib/utils/interrupt_char.h"
+#include "py/gc.h"
#include "py/reload.h"
#include "py/runtime.h"
#include "shared-bindings/board/__init__.h"
@@ -10,6 +12,7 @@
#include "shared-bindings/displayio/Display.h"
#include "shared-bindings/displayio/Group.h"
#include "shared-bindings/displayio/Palette.h"
+#include "shared-module/displayio/area.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/display.h"
#include "supervisor/memory.h"
@@ -17,14 +20,83 @@
primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
-static inline void swap(uint16_t* a, uint16_t* b) {
- uint16_t temp = *a;
- *a = *b;
- *b = temp;
+bool refresh_area(displayio_display_obj_t* display, const displayio_area_t* area) {
+ uint16_t buffer_size = 512;
+
+ displayio_area_t clipped;
+ // Clip the area to the display by overlapping the areas. If there is no overlap then we're done.
+ if (!displayio_display_clip_area(display, area, &clipped)) {
+ return true;
+ }
+ uint16_t subrectangles = 1;
+ uint16_t rows_per_buffer = displayio_area_height(&clipped);
+ if (displayio_area_size(area) > buffer_size) {
+ rows_per_buffer = buffer_size / displayio_area_width(&clipped);
+ subrectangles = displayio_area_height(&clipped) / rows_per_buffer;
+ if (displayio_area_height(&clipped) % rows_per_buffer != 0) {
+ subrectangles++;
+ }
+ buffer_size = rows_per_buffer * displayio_area_width(&clipped);
+ }
+ uint32_t buffer[buffer_size / 2];
+ uint16_t remaining_rows = displayio_area_height(&clipped);
+
+ for (uint16_t j = 0; j < subrectangles; j++) {
+ displayio_area_t subrectangle = {
+ .x1 = clipped.x1,
+ .y1 = clipped.y1 + rows_per_buffer * j,
+ .x2 = clipped.x2,
+ .y2 = clipped.y1 + rows_per_buffer * (j + 1)
+ };
+ if (remaining_rows < rows_per_buffer) {
+ subrectangle.y2 = subrectangle.y1 + remaining_rows;
+ }
+ remaining_rows -= rows_per_buffer;
+
+ displayio_display_begin_transaction(display);
+ displayio_display_set_region_to_update(display, subrectangle.x1, subrectangle.y1,
+ subrectangle.x2, subrectangle.y2);
+ displayio_display_end_transaction(display);
+
+ uint32_t mask[(buffer_size / 32) + 1];
+ for (uint16_t k = 0; k < (buffer_size / 32) + 1; k++) {
+ mask[k] = 0x00000000;
+ }
+
+ bool full_coverage = displayio_display_fill_area(display, &subrectangle, mask, buffer);
+ if (!full_coverage) {
+ uint32_t index = 0;
+ uint32_t current_mask = 0;
+ for (int16_t y = subrectangle.y1; y < subrectangle.y2; y++) {
+ for (int16_t x = subrectangle.x1; x < subrectangle.x2; x++) {
+ if (index % 32 == 0) {
+ current_mask = mask[index / 32];
+ }
+ if ((current_mask & (1 << (index % 32))) == 0) {
+ ((uint16_t*) buffer)[index] = 0x0000;
+ }
+ index++;
+ }
+ }
+ }
+
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't acquire display bus; skip the rest of the data. Try next display.
+ return false;
+ }
+ displayio_display_send_pixels(display, (uint8_t*) buffer, displayio_area_size(&subrectangle) * sizeof(uint16_t));
+ displayio_display_end_transaction(display);
+
+ // TODO(tannewt): Make refresh displays faster so we don't starve other
+ // background tasks.
+ usb_background();
+ }
+ return true;
}
// Check for recursive calls to displayio_refresh_displays.
bool refresh_displays_in_progress = false;
+uint32_t frame_count = 0;
void displayio_refresh_displays(void) {
if (mp_hal_is_interrupted()) {
@@ -55,105 +127,19 @@ void displayio_refresh_displays(void) {
// Too soon. Try next display.
continue;
}
- if (displayio_display_refresh_queued(display)) {
- // We compute the pixels. r and c are row and column to match the display memory
- // structure. x and y match location within the groups.
- uint16_t c0 = 0;
- uint16_t r0 = 0;
- uint16_t c1 = display->width;
- uint16_t r1 = display->height;
- if (display->transpose_xy) {
- swap(&c1, &r1);
- }
-
- if (!displayio_display_begin_transaction(display)) {
- // Can't acquire display bus; skip updating this display. Try next display.
- continue;
- }
- displayio_display_set_region_to_update(display, c0, r0, c1, r1);
- displayio_display_end_transaction(display);
-
- uint16_t x0 = 0;
- uint16_t x1 = display->width - 1;
- uint16_t startx = 0;
- int8_t dx = 1;
- if (display->mirror_x) {
- dx = -1;
- startx = x1;
- }
- uint16_t y0 = 0;
- uint16_t y1 = display->height - 1;
- uint16_t starty = 0;
- int8_t dy = 1;
- if (display->mirror_y) {
- dy = -1;
- starty = y1;
- }
-
- bool transpose = false;
- if (display->transpose_xy) {
- transpose = true;
- int8_t temp_dx = dx;
- dx = dy;
- dy = temp_dx;
-
- swap(&starty, &startx);
- swap(&x0, &y0);
- swap(&x1, &y1);
- }
-
- size_t index = 0;
- uint16_t buffer_size = 256;
- uint32_t buffer[buffer_size / 2];
- bool skip_this_display = false;
-
- for (uint16_t y = starty; y0 <= y && y <= y1; y += dy) {
- for (uint16_t x = startx; x0 <= x && x <= x1; x += dx) {
- uint16_t* pixel = &(((uint16_t*)buffer)[index]);
- *pixel = 0;
-
- if (display->current_group != NULL) {
- if (transpose) {
- displayio_group_get_pixel(display->current_group, y, x, pixel);
- } else {
- displayio_group_get_pixel(display->current_group, x, y, pixel);
- }
- }
-
- index += 1;
- // The buffer is full, send it.
- if (index >= buffer_size) {
- if (!displayio_display_begin_transaction(display)) {
- // Can't acquire display bus; skip the rest of the data. Try next display.
- index = 0;
- skip_this_display = true;
- break;
- }
- displayio_display_send_pixels(display, buffer, buffer_size / 2);
- displayio_display_end_transaction(display);
- // TODO(tannewt): Make refresh displays faster so we don't starve other
- // background tasks.
- usb_background();
- index = 0;
- }
- }
- }
-
- if (skip_this_display) {
- // Go on to next display.
- continue;
- }
- // Send the remaining data.
- if (index) {
- if (!displayio_display_begin_transaction(display)) {
- // Can't get display bus. Skip the rest of the data. Try next display.
- continue;
- }
- displayio_display_send_pixels(display, buffer, index * 2);
- }
- displayio_display_end_transaction(display);
+ if (!displayio_display_begin_transaction(display)) {
+ // Can't acquire display bus; skip updating this display. Try next display.
+ continue;
+ }
+ displayio_display_end_transaction(display);
+ displayio_display_start_refresh(display);
+ const displayio_area_t* current_area = displayio_display_get_refresh_areas(display);
+ while (current_area != NULL) {
+ refresh_area(display, current_area);
+ current_area = current_area->next;
}
displayio_display_finish_refresh(display);
+ frame_count++;
}
// All done.
@@ -181,7 +167,6 @@ void common_hal_displayio_release_displays(void) {
}
void reset_displays(void) {
- #if CIRCUITPY_DISPLAYIO
// The SPI buses used by FourWires may be allocated on the heap so we need to move them inline.
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].fourwire_bus.base.type != &displayio_fourwire_type) {
@@ -218,5 +203,151 @@ void reset_displays(void) {
display->auto_brightness = true;
common_hal_displayio_display_show(display, &circuitpython_splash);
}
- #endif
+}
+
+void displayio_gc_collect(void) {
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].display.base.type == NULL) {
+ continue;
+ }
+
+ // Alternatively, we could use gc_collect_root over the whole object,
+ // but this is more precise, and is the only field that needs marking.
+ gc_collect_ptr(displays[i].display.current_group);
+
+ }
+}
+
+void displayio_area_expand(displayio_area_t* original, const displayio_area_t* addition) {
+ if (addition->x1 < original->x1) {
+ original->x1 = addition->x1;
+ }
+ if (addition->y1 < original->y1) {
+ original->y1 = addition->y1;
+ }
+ if (addition->x2 > original->x2) {
+ original->x2 = addition->x2;
+ }
+ if (addition->y2 > original->y2) {
+ original->y2 = addition->y2;
+ }
+}
+
+void displayio_area_copy(const displayio_area_t* src, displayio_area_t* dst) {
+ dst->x1 = src->x1;
+ dst->y1 = src->y1;
+ dst->x2 = src->x2;
+ dst->y2 = src->y2;
+}
+
+void displayio_area_scale(displayio_area_t* area, uint16_t scale) {
+ area->x1 *= scale;
+ area->y1 *= scale;
+ area->x2 *= scale;
+ area->y2 *= scale;
+}
+
+void displayio_area_shift(displayio_area_t* area, int16_t dx, int16_t dy) {
+ area->x1 += dx;
+ area->y1 += dy;
+ area->x2 += dx;
+ area->y2 += dy;
+}
+
+bool displayio_area_compute_overlap(const displayio_area_t* a,
+ const displayio_area_t* b,
+ displayio_area_t* overlap) {
+ overlap->x1 = a->x1;
+ if (b->x1 > overlap->x1) {
+ overlap->x1 = b->x1;
+ }
+ overlap->x2 = a->x2;
+ if (b->x2 < overlap->x2) {
+ overlap->x2 = b->x2;
+ }
+ if (overlap->x1 >= overlap->x2) {
+ return false;
+ }
+ overlap->y1 = a->y1;
+ if (b->y1 > overlap->y1) {
+ overlap->y1 = b->y1;
+ }
+ overlap->y2 = a->y2;
+ if (b->y2 < overlap->y2) {
+ overlap->y2 = b->y2;
+ }
+ if (overlap->y1 >= overlap->y2) {
+ return false;
+ }
+ return true;
+}
+
+void displayio_area_union(const displayio_area_t* a,
+ const displayio_area_t* b,
+ displayio_area_t* u) {
+ u->x1 = a->x1;
+ if (b->x1 < u->x1) {
+ u->x1 = b->x1;
+ }
+ u->x2 = a->x2;
+ if (b->x2 > u->x2) {
+ u->x2 = b->x2;
+ }
+
+ u->y1 = a->y1;
+ if (b->y1 < u->y1) {
+ u->y1 = b->y1;
+ }
+ u->y2 = a->y2;
+ if (b->y2 > u->y2) {
+ u->y2 = b->y2;
+ }
+}
+
+uint16_t displayio_area_width(const displayio_area_t* area) {
+ return area->x2 - area->x1;
+}
+
+uint16_t displayio_area_height(const displayio_area_t* area) {
+ return area->y2 - area->y1;
+}
+
+uint32_t displayio_area_size(const displayio_area_t* area) {
+ return displayio_area_width(area) * displayio_area_height(area);
+}
+
+bool displayio_area_equal(const displayio_area_t* a, const displayio_area_t* b) {
+ return a->x1 == b->x1 &&
+ a->y1 == b->y1 &&
+ a->x2 == b->x2 &&
+ a->y2 == b->y2;
+}
+
+// Original and whole must be in the same coordinate space.
+void displayio_area_transform_within(bool mirror_x, bool mirror_y, bool transpose_xy,
+ const displayio_area_t* original,
+ const displayio_area_t* whole,
+ displayio_area_t* transformed) {
+ if (mirror_x) {
+ transformed->x1 = whole->x1 + (whole->x2 - original->x2);
+ transformed->x2 = whole->x2 - (original->x1 - whole->x1);
+ } else {
+ transformed->x1 = original->x1;
+ transformed->x2 = original->x2;
+ }
+ if (mirror_y) {
+ transformed->y1 = whole->y1 + (whole->y2 - original->y2);
+ transformed->y2 = whole->y2 - (original->y1 - whole->y1);
+ } else {
+ transformed->y1 = original->y1;
+ transformed->y2 = original->y2;
+ }
+ if (transpose_xy) {
+ int16_t y1 = transformed->y1;
+ int16_t y2 = transformed->y2;
+ transformed->y1 = whole->y1 + (transformed->x1 - whole->x1);
+ transformed->y2 = whole->y1 + (transformed->x2 - whole->x1);
+ transformed->x2 = whole->x1 + (y2 - whole->y1);
+ transformed->x1 = whole->x1 + (y1 - whole->y1);
+ }
}
diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h
index 5b56ed55c..18c1a4f4a 100644
--- a/shared-module/displayio/__init__.h
+++ b/shared-module/displayio/__init__.h
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO___INIT___H
#include "shared-bindings/displayio/Display.h"
#include "shared-bindings/displayio/FourWire.h"
@@ -46,5 +46,6 @@ extern displayio_group_t circuitpython_splash;
void displayio_refresh_displays(void);
void reset_displays(void);
+void displayio_gc_collect(void);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO___INIT___H
diff --git a/shared-module/displayio/area.h b/shared-module/displayio/area.h
new file mode 100644
index 000000000..ec7c389b4
--- /dev/null
+++ b/shared-module/displayio/area.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 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_MODULE_DISPLAYIO_AREA_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_AREA_H
+
+// Implementations are in __init__.c
+typedef struct _displayio_area_t displayio_area_t;
+
+struct _displayio_area_t {
+ int16_t x1;
+ int16_t y1;
+ int16_t x2; // Second point is exclusive.
+ int16_t y2;
+ const displayio_area_t* next; // Next area in the linked list.
+};
+
+typedef struct {
+ uint16_t x;
+ uint16_t y;
+ int8_t dx;
+ int8_t dy;
+ uint8_t scale;
+ uint16_t width;
+ uint16_t height;
+ bool mirror_x;
+ bool mirror_y;
+ bool transpose_xy;
+} displayio_buffer_transform_t;
+
+void displayio_area_union(const displayio_area_t* a,
+ const displayio_area_t* b,
+ displayio_area_t* u);
+void displayio_area_expand(displayio_area_t* original, const displayio_area_t* addition);
+void displayio_area_copy(const displayio_area_t* src, displayio_area_t* dst);
+void displayio_area_scale(displayio_area_t* area, uint16_t scale);
+void displayio_area_shift(displayio_area_t* area, int16_t dx, int16_t dy);
+bool displayio_area_compute_overlap(const displayio_area_t* a,
+ const displayio_area_t* b,
+ displayio_area_t* overlap);
+uint16_t displayio_area_width(const displayio_area_t* area);
+uint16_t displayio_area_height(const displayio_area_t* area);
+uint32_t displayio_area_size(const displayio_area_t* area);
+bool displayio_area_equal(const displayio_area_t* a, const displayio_area_t* b);
+void displayio_area_transform_within(bool mirror_x, bool mirror_y, bool transpose_xy,
+ const displayio_area_t* original,
+ const displayio_area_t* whole,
+ displayio_area_t* transformed);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_AREA_H
diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c
index 0b3fbe178..c3afb3e00 100644
--- a/supervisor/shared/display.c
+++ b/supervisor/shared/display.c
@@ -50,6 +50,10 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
}
width_in_tiles = (width_px - blinka_bitmap.width * scale) / (grid->tile_width * scale);
uint16_t height_in_tiles = height_px / (grid->tile_height * scale);
+ uint16_t remaining_pixels = height_px % (grid->tile_height * scale);
+ if (remaining_pixels > 0) {
+ height_in_tiles += 1;
+ }
circuitpython_splash.scale = scale;
uint16_t total_tiles = width_in_tiles * height_in_tiles;
@@ -67,11 +71,13 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
if (tiles == NULL) {
return;
}
-
+ if (remaining_pixels > 0) {
+ grid->y -= (grid->tile_height - remaining_pixels);
+ }
grid->width_in_tiles = width_in_tiles;
grid->height_in_tiles = height_in_tiles;
- grid->total_width = width_in_tiles * grid->tile_width;
- grid->total_height = height_in_tiles * grid->tile_height;
+ grid->pixel_width = width_in_tiles * grid->tile_width;
+ grid->pixel_height = height_in_tiles * grid->tile_height;
grid->tiles = tiles;
supervisor_terminal.cursor_x = 0;
@@ -159,18 +165,22 @@ displayio_tilegrid_t blinka_sprite = {
.pixel_shader = &blinka_palette,
.x = 0,
.y = 0,
+ .pixel_width = 16,
+ .pixel_height = 16,
.bitmap_width_in_tiles = 1,
.width_in_tiles = 1,
.height_in_tiles = 1,
- .total_width = 16,
- .total_height = 16,
.tile_width = 16,
.tile_height = 16,
.top_left_x = 16,
.top_left_y = 16,
.tiles = 0,
- .needs_refresh = false,
- .inline_tiles = true
+ .partial_change = false,
+ .full_change = false,
+ .first_draw = true,
+ .moved = false,
+ .inline_tiles = true,
+ .in_group = true
};
displayio_group_child_t splash_children[2] = {
@@ -186,5 +196,5 @@ displayio_group_t circuitpython_splash = {
.size = 2,
.max_size = 2,
.children = splash_children,
- .needs_refresh = true
+ .item_removed = false
};
diff --git a/tools/build_release_files.py b/tools/build_release_files.py
index 872302a4f..e29b098c7 100755
--- a/tools/build_release_files.py
+++ b/tools/build_release_files.py
@@ -1,3 +1,5 @@
+#! /usr/bin/env python3
+
import os
import sys
import subprocess
@@ -6,7 +8,7 @@ import build_board_info as build_info
import time
for port in build_info.SUPPORTED_PORTS:
- result = subprocess.run("rm -rf ../ports/{}/build*".format(port), shell=True)
+ result = subprocess.run("rm -rf ../ports/{port}/build*".format(port=port), shell=True)
ROSIE_SETUPS = ["rosie-ci"]
rosie_ok = {}
@@ -37,7 +39,25 @@ for board in build_boards:
bin_directory = "../bin/{board}/{language}".format(board=board, language=language)
os.makedirs(bin_directory, exist_ok=True)
start_time = time.monotonic()
- make_result = subprocess.run("make -C ../ports/" + board_info["port"] + " TRANSLATION=" + language + " BOARD=" + board, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ # Normally different language builds are all done based on the same set of compiled sources.
+ # But sometimes a particular language needs to be built from scratch, if, for instance,
+ # CFLAGS_INLINE_LIMIT is set for a particular language to make it fit.
+ clean_build_check_result = subprocess.run(
+ "make -C ../ports/{port} TRANSLATION={language} BOARD={board} check-release-needs-clean-build | fgrep 'RELEASE_NEEDS_CLEAN_BUILD = 1'".format(
+ port = board_info["port"], language=language, board=board),
+ shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ clean_build = clean_build_check_result.returncode == 0
+
+ build_dir = "build-{board}".format(board=board)
+ if clean_build:
+ build_dir += "-{language}".format(language=language)
+
+ make_result = subprocess.run(
+ "make -C ../ports/{port} TRANSLATION={language} BOARD={board} BUILD={build}".format(
+ port = board_info["port"], language=language, board=board, build=build_dir),
+ shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
build_duration = time.monotonic() - start_time
success = "\033[32msucceeded\033[0m"
if make_result.returncode != 0:
@@ -47,11 +67,14 @@ for board in build_boards:
other_output = ""
for extension in board_info["extensions"]:
- temp_filename = "../ports/{port}/build-{board}/firmware.{extension}".format(port=board_info["port"], board=board, extension=extension)
+ temp_filename = "../ports/{port}/{build}/firmware.{extension}".format(
+ port=board_info["port"], build=build_dir, extension=extension)
for alias in board_info["aliases"] + [board]:
- bin_directory = "../bin/{alias}/{language}".format(alias=alias, language=language)
+ bin_directory = "../bin/{alias}/{language}".format(
+ alias=alias, language=language)
os.makedirs(bin_directory, exist_ok=True)
- final_filename = "adafruit-circuitpython-{alias}-{language}-{version}.{extension}".format(alias=alias, language=language, version=version, extension=extension)
+ final_filename = "adafruit-circuitpython-{alias}-{language}-{version}.{extension}".format(
+ alias=alias, language=language, version=version, extension=extension)
final_filename = os.path.join(bin_directory, final_filename)
try:
shutil.copyfile(temp_filename, final_filename)
@@ -62,7 +85,9 @@ for board in build_boards:
if travis:
print('travis_fold:start:adafruit-bins-{}-{}\\r'.format(language, board))
- print("Build {} for {} took {:.2f}s and {}".format(board, language, build_duration, success))
+ print("Build {board} for {language}{clean_build} took {build_duration:.2f}s and {success}".format(
+ board=board, language=language, clean_build=(" (clean_build)" if clean_build else ""),
+ build_duration=build_duration, success=success))
if make_result.returncode != 0:
print(make_result.stdout.decode("utf-8"))
print(other_output)
diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py
index ebea9dccc..7b28c3105 100644
--- a/tools/gen_display_resources.py
+++ b/tools/gen_display_resources.py
@@ -122,16 +122,20 @@ displayio_tilegrid_t supervisor_terminal_text_grid = {{
.pixel_shader = &supervisor_terminal_color,
.x = 16,
.y = 0,
+ .pixel_width = {1},
+ .pixel_height = {2},
.bitmap_width_in_tiles = {0},
.width_in_tiles = 1,
.height_in_tiles = 1,
- .total_width = {1},
- .total_height = {2},
.tile_width = {1},
.tile_height = {2},
.tiles = NULL,
- .needs_refresh = false,
- .inline_tiles = false
+ .partial_change = false,
+ .full_change = false,
+ .first_draw = true,
+ .moved = false,
+ .inline_tiles = false,
+ .in_group = true
}};
""".format(len(all_characters), tile_x, tile_y))
diff --git a/tools/git-checkout-latest-tag.sh b/tools/git-checkout-latest-tag.sh
new file mode 100755
index 000000000..f6242a946
--- /dev/null
+++ b/tools/git-checkout-latest-tag.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+git fetch --tags
+git checkout $(git describe --tags `git rev-list --tags --max-count=1`)