summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml3
-rw-r--r--locale/ID.po15
-rw-r--r--locale/circuitpython.pot12
-rw-r--r--locale/cs.po12
-rw-r--r--locale/de_DE.po15
-rw-r--r--locale/el.po12
-rw-r--r--locale/en_GB.po12
-rw-r--r--locale/es.po30
-rw-r--r--locale/fil.po15
-rw-r--r--locale/fr.po15
-rw-r--r--locale/hi.po12
-rw-r--r--locale/it_IT.po15
-rw-r--r--locale/ja.po15
-rw-r--r--locale/ko.po12
-rw-r--r--locale/nl.po15
-rw-r--r--locale/pl.po15
-rw-r--r--locale/pt_BR.po19
-rw-r--r--locale/sv.po19
-rw-r--r--locale/zh_Latn_pinyin.po31
-rw-r--r--ports/atmel-samd/boards/8086_commander/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/bdmicro_vina_d51/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk1
-rwxr-xr-xports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk1
-rwxr-xr-xports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/dynossat_edu_eps/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/dynossat_edu_obc/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk1
-rwxr-xr-xports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/nfc_copy_cat/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pybadge/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pycubed/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pygamer/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pyportal/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/serpente/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/snekboard/mpconfigboard.mk1
-rwxr-xr-xports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/sparkfun_qwiic_micro_with_flash/mpconfigboard.mk1
-rwxr-xr-xports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/stringcar_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/ugame10/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/common-hal/i2cperipheral/I2CPeripheral.c4
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wroom/board.c52
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h38
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.mk17
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wroom/pins.c48
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wroom/sdkconfig0
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wrover/board.c52
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h38
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.mk17
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wrover/pins.c48
-rw-r--r--ports/esp32s2/boards/franzininho_wifi_wrover/sdkconfig33
-rw-r--r--ports/nrf/boards/TG-Watch/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/aramcon_badge_2019/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/bastble/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/clue_nrf52840_express/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/hiibot_bluefi/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/ohs2020_badge/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/particle_argon/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/particle_boron/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/particle_xenon/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/pca10056/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/pitaya_go/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/simmel/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/sparkfun_nrf52840_micromod/README.md70
-rw-r--r--ports/nrf/boards/sparkfun_nrf52840_micromod/board.c38
-rw-r--r--ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.h53
-rw-r--r--ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.mk10
-rw-r--r--ports/nrf/boards/sparkfun_nrf52840_micromod/pins.c113
-rw-r--r--ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk1
-rw-r--r--ports/raspberrypi/Makefile3
-rw-r--r--ports/raspberrypi/bindings/rp2pio/StateMachine.c30
-rw-r--r--ports/raspberrypi/bindings/rp2pio/StateMachine.h5
-rw-r--r--ports/raspberrypi/bindings/rp2pio/__init__.c15
-rw-r--r--ports/raspberrypi/bindings/rp2pio/__init__.h29
-rw-r--r--ports/raspberrypi/common-hal/audiobusio/I2SOut.c1
-rw-r--r--ports/raspberrypi/common-hal/audiobusio/PDMIn.c2
-rw-r--r--ports/raspberrypi/common-hal/neopixel_write/__init__.c1
-rw-r--r--ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c170
-rw-r--r--ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.h40
-rw-r--r--ports/raspberrypi/common-hal/rotaryio/__init__.c1
-rw-r--r--ports/raspberrypi/common-hal/rotaryio/__init__.h0
-rw-r--r--ports/raspberrypi/common-hal/rp2pio/StateMachine.c71
-rw-r--r--ports/raspberrypi/common-hal/rp2pio/StateMachine.h4
-rw-r--r--ports/raspberrypi/common-hal/rp2pio/__init__.c44
-rw-r--r--ports/raspberrypi/common-hal/rtc/RTC.c14
-rw-r--r--ports/raspberrypi/mpconfigport.mk8
m---------ports/raspberrypi/sdk0
-rw-r--r--ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/meowbit_v121/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/pyb_nano_v2/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/thunderpack_v12/mpconfigboard.mk1
-rw-r--r--shared-bindings/countio/Counter.c3
-rw-r--r--shared-bindings/usb_cdc/Serial.c35
-rw-r--r--supervisor/flash.h2
-rw-r--r--supervisor/flash_root_pointers.h2
-rw-r--r--supervisor/shared/external_flash/external_flash.c3
-rw-r--r--supervisor/supervisor.mk1
149 files changed, 1299 insertions, 200 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 32e3bc900..f65618b40 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -314,6 +314,7 @@ jobs:
- "simmel"
- "snekboard"
- "sparkfun_lumidrive"
+ - "sparkfun_nrf52840_micromod"
- "sparkfun_nrf52840_mini"
- "sparkfun_qwiic_micro_no_flash"
- "sparkfun_qwiic_micro_with_flash"
@@ -450,6 +451,8 @@ jobs:
- "espressif_kaluga_1"
- "espressif_saola_1_wroom"
- "espressif_saola_1_wrover"
+ - "franzininho_wifi_wroom"
+ - "franzininho_wifi_wrover"
- "lilygo_ttgo_t8_s2_st7789"
- "microdev_micro_s2"
- "muselab_nanoesp32_s2"
diff --git a/locale/ID.po b/locale/ID.po
index b62425d49..fbcd82940 100644
--- a/locale/ID.po
+++ b/locale/ID.po
@@ -1061,10 +1061,6 @@ msgstr ""
msgid "Group already used"
msgstr "Grup sudah digunakan"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Grup penuh"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1819,6 +1815,10 @@ msgstr ""
"ideal. Jika ini tidak dapat dihindari, berikan allow_inefficient=True ke "
"konstruktor"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3795,6 +3795,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4296,6 +4300,9 @@ msgstr ""
msgid "zi must be of shape (n_section, 2)"
msgstr ""
+#~ msgid "Group full"
+#~ msgstr "Grup penuh"
+
#~ msgid "SDA or SCL needs a pull up"
#~ msgstr "SDA atau SCL membutuhkan pull up"
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 2e31d5dfc..afff80687 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -1042,10 +1042,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr ""
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1787,6 +1783,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3743,6 +3743,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
diff --git a/locale/cs.po b/locale/cs.po
index 73097ae16..57dd3cd76 100644
--- a/locale/cs.po
+++ b/locale/cs.po
@@ -1045,10 +1045,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr ""
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1790,6 +1786,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3746,6 +3746,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 455d1f897..b000590f7 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -1065,10 +1065,6 @@ msgstr "Generischer Fehler"
msgid "Group already used"
msgstr "Gruppe schon benutzt"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Gruppe voll"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1823,6 +1819,10 @@ msgstr ""
"Bytes verbraucht. Wenn dies nicht vermieden werden kann, übergeben Sie "
"allow_inefficient = True an den Konstruktor"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3832,6 +3832,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4339,6 +4343,9 @@ msgstr ""
msgid "zi must be of shape (n_section, 2)"
msgstr ""
+#~ msgid "Group full"
+#~ msgstr "Gruppe voll"
+
#~ msgid "bits must be 7, 8 or 9"
#~ msgstr "bits muss 7, 8 oder 9 sein"
diff --git a/locale/el.po b/locale/el.po
index b6bab075a..309d3b86a 100644
--- a/locale/el.po
+++ b/locale/el.po
@@ -1042,10 +1042,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr ""
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1787,6 +1783,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3743,6 +3743,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
diff --git a/locale/en_GB.po b/locale/en_GB.po
index 829c4fff9..6db894d45 100644
--- a/locale/en_GB.po
+++ b/locale/en_GB.po
@@ -1041,10 +1041,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr ""
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1786,6 +1782,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3742,6 +3742,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index 32c3ecfa0..ecd6b0042 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-03-02 02:24+0000\n"
+"PO-Revision-Date: 2021-03-07 15:50+0000\n"
"Last-Translator: Jose David M <jquintana202020@gmail.com>\n"
"Language-Team: \n"
"Language: es\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.5\n"
+"X-Generator: Weblate 4.5.1\n"
#: main.c
msgid ""
@@ -1069,10 +1069,6 @@ msgstr "Fallo Genérico"
msgid "Group already used"
msgstr "Grupo ya está siendo utilizado"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Group lleno"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1115,6 +1111,7 @@ msgstr "IV debe tener %d bytes de longitud"
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "In-buffer elements must be <= 4 bytes long"
msgstr ""
+"Los elementos del búfer de entrada deben ser de una longitud <= 4 bytes"
#: py/persistentcode.c
msgid ""
@@ -1742,7 +1739,7 @@ msgstr "Se acabaron los enchufes"
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "Out-buffer elements must be <= 4 bytes long"
-msgstr ""
+msgstr "Los elementos del búfer de salida deben ser de una longitud <= 4 bytes"
#: shared-bindings/bitops/__init__.c
#, c-format
@@ -1771,11 +1768,11 @@ msgstr ""
#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "PWM slice already in use"
-msgstr ""
+msgstr "Segmento PWM ya esta en uso"
#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "PWM slice channel A already in use"
-msgstr ""
+msgstr "Segmento del PWM canal A ya esta en uso"
#: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
@@ -1816,7 +1813,7 @@ msgstr "El pin es solo de entrada"
#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "Pin must be on PWM Channel B"
-msgstr ""
+msgstr "El pin debe estar en el PWM canal B"
#: ports/atmel-samd/common-hal/countio/Counter.c
msgid "Pin must support hardware interrupts"
@@ -1837,6 +1834,10 @@ msgstr ""
"ideales. Si esto no se puede evitar, pase allow_inefficient=True al "
"constructor"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr "Los pines deben compartir la división PWM"
@@ -2817,7 +2818,7 @@ msgstr "circulo solo puede ser registrado con un pariente"
#: shared-bindings/bitmaptools/__init__.c
msgid "clip point must be (x,y) tuple"
-msgstr ""
+msgstr "El punto clip debe ser una tupla (x, y)"
#: shared-bindings/msgpack/ExtType.c
msgid "code outside range 0~127"
@@ -3839,6 +3840,10 @@ msgstr "presionando botón de arranque al inicio.\n"
msgid "pressing both buttons at start up.\n"
msgstr "presionando ambos botones al inicio.\n"
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr "pull_threshold debe esta entre 1 y 32"
@@ -4342,6 +4347,9 @@ msgstr "zi debe ser de tipo flotante"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi debe ser una forma (n_section,2)"
+#~ msgid "Group full"
+#~ msgstr "Group lleno"
+
#~ msgid "In buffer elements must be 4 bytes long or less"
#~ msgstr ""
#~ "Los elementos del búfer de entrada deben ser de una longitud de 4 bytes o "
diff --git a/locale/fil.po b/locale/fil.po
index e88a9efca..046ed0e8f 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -1055,10 +1055,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Puno ang group"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1806,6 +1802,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3792,6 +3792,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4298,6 +4302,9 @@ msgstr ""
msgid "zi must be of shape (n_section, 2)"
msgstr ""
+#~ msgid "Group full"
+#~ msgstr "Puno ang group"
+
#~ msgid "bits must be 7, 8 or 9"
#~ msgstr "bits ay dapat 7, 8 o 9"
diff --git a/locale/fr.po b/locale/fr.po
index a66f7be55..a32590b68 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -1077,10 +1077,6 @@ msgstr "Échec génerique"
msgid "Group already used"
msgstr "Groupe déjà utilisé"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Groupe plein"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1845,6 +1841,10 @@ msgstr ""
"octets idéal. Si cela ne peut pas être évité, transmettez allow_inefficient "
"= True au constructeur"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr "Les broches doivent partager la tranche PWM"
@@ -3861,6 +3861,10 @@ msgstr "bouton boot appuyé lors du démarrage.\n"
msgid "pressing both buttons at start up.\n"
msgstr "les deux boutons appuyés lors du démarrage.\n"
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr "pull_threshold doit être entre 1 et 32"
@@ -4364,6 +4368,9 @@ msgstr "zi doit être de type float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi doit être de forme (n_section, 2)"
+#~ msgid "Group full"
+#~ msgstr "Groupe plein"
+
#~ msgid "UART not yet supported"
#~ msgstr "UART n'est pas encore supporté"
diff --git a/locale/hi.po b/locale/hi.po
index c272aeeb7..0ad1435b7 100644
--- a/locale/hi.po
+++ b/locale/hi.po
@@ -1042,10 +1042,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr ""
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1787,6 +1783,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3743,6 +3743,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 1be741f60..235855efd 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -1064,10 +1064,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Gruppo pieno"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1824,6 +1820,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3809,6 +3809,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4315,6 +4319,9 @@ msgstr ""
msgid "zi must be of shape (n_section, 2)"
msgstr ""
+#~ msgid "Group full"
+#~ msgstr "Gruppo pieno"
+
#~ msgid "bits must be 7, 8 or 9"
#~ msgstr "i bit devono essere 7, 8 o 9"
diff --git a/locale/ja.po b/locale/ja.po
index 04b5287af..8d1fa39e3 100644
--- a/locale/ja.po
+++ b/locale/ja.po
@@ -1053,10 +1053,6 @@ msgstr ""
msgid "Group already used"
msgstr "グループはすでに使われています"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "グループが一杯"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1803,6 +1799,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3773,6 +3773,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4274,6 +4278,9 @@ msgstr "ziはfloat値でなければなりません"
msgid "zi must be of shape (n_section, 2)"
msgstr ""
+#~ msgid "Group full"
+#~ msgstr "グループが一杯"
+
#~ msgid "bits must be 7, 8 or 9"
#~ msgstr "bitsは7, 8, 9のいずれかでなければなりません"
diff --git a/locale/ko.po b/locale/ko.po
index 25455fc7f..b3137c1b9 100644
--- a/locale/ko.po
+++ b/locale/ko.po
@@ -1045,10 +1045,6 @@ msgstr ""
msgid "Group already used"
msgstr ""
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr ""
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1790,6 +1786,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3747,6 +3747,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
diff --git a/locale/nl.po b/locale/nl.po
index e796cf916..d47469236 100644
--- a/locale/nl.po
+++ b/locale/nl.po
@@ -1054,10 +1054,6 @@ msgstr ""
msgid "Group already used"
msgstr "Groep al gebruikt"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Groep is vol"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1813,6 +1809,10 @@ msgstr ""
"gebruikt. Als dit niet kan worden vermeden, geef dan het argument "
"allow_inefficient=True aan de constructor"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3805,6 +3805,10 @@ msgstr "druk bootknop in bij opstarten.\n"
msgid "pressing both buttons at start up.\n"
msgstr "druk beide knoppen in bij opstarten.\n"
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4307,6 +4311,9 @@ msgstr "zi moet van type float zijn"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi moet vorm (n_section, 2) hebben"
+#~ msgid "Group full"
+#~ msgstr "Groep is vol"
+
#~ msgid "bits must be 7, 8 or 9"
#~ msgstr "bits moet 7, 8, of 9 zijn"
diff --git a/locale/pl.po b/locale/pl.po
index 18705581f..b51df842f 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -1053,10 +1053,6 @@ msgstr ""
msgid "Group already used"
msgstr "Grupa już używana"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Grupa pełna"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1801,6 +1797,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr ""
@@ -3765,6 +3765,10 @@ msgstr ""
msgid "pressing both buttons at start up.\n"
msgstr ""
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr ""
@@ -4266,6 +4270,9 @@ msgstr ""
msgid "zi must be of shape (n_section, 2)"
msgstr ""
+#~ msgid "Group full"
+#~ msgstr "Grupa pełna"
+
#~ msgid "bits must be 7, 8 or 9"
#~ msgstr "bits musi być 7, 8 lub 9"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 6ba5caa29..3adaa228a 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-03-03 17:42+0000\n"
+"PO-Revision-Date: 2021-03-09 16:55+0000\n"
"Last-Translator: Wellington Terumi Uemura <wellingtonuemura@gmail.com>\n"
"Language-Team: \n"
"Language: pt_BR\n"
@@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.5.1-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: main.c
msgid ""
@@ -1072,10 +1072,6 @@ msgstr "Falha Genérica"
msgid "Group already used"
msgstr "O grupo já está em uso"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Grupo cheio"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1839,6 +1835,10 @@ msgstr ""
"ideal. Caso isso não possa ser evitado, passe allow_inefficient=True ao "
"construtor"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr "Os pinos devem ser sequenciais"
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr "Os pinos devem compartilhar a fatia do PWM"
@@ -3851,6 +3851,10 @@ msgstr "pressionando o botão de boot na inicialização.\n"
msgid "pressing both buttons at start up.\n"
msgstr "pressionando ambos os botões durante a inicialização.\n"
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr "puxe as máscaras em conflito com as máscaras de direção"
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr "O pull_threshold deve ser entre 1 e 32"
@@ -4353,6 +4357,9 @@ msgstr "zi deve ser de um tipo float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi deve estar na forma (n_section, 2)"
+#~ msgid "Group full"
+#~ msgstr "Grupo cheio"
+
#~ msgid "In buffer elements must be 4 bytes long or less"
#~ msgstr "No buffer, os elementos devem ter 4 bytes ou menos"
diff --git a/locale/sv.po b/locale/sv.po
index 8fe6a7dd5..de7e81769 100644
--- a/locale/sv.po
+++ b/locale/sv.po
@@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-03-03 21:28+0000\n"
+"PO-Revision-Date: 2021-03-09 16:55+0000\n"
"Last-Translator: Jonny Bergdahl <jonny@bergdahl.it>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: sv\n"
@@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.5.1-dev\n"
+"X-Generator: Weblate 4.5.2-dev\n"
#: main.c
msgid ""
@@ -1059,10 +1059,6 @@ msgstr "Generiskt fel"
msgid "Group already used"
msgstr "Grupp används redan"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Gruppen är full"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1819,6 +1815,10 @@ msgstr ""
"%d byte. Om detta inte kan undvikas, skicka allow_inefficient=True till "
"konstruktorn"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr "Pinnarna måste vara i sekvens"
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr "Pinnar måste dela PWM-segment"
@@ -3808,6 +3808,10 @@ msgstr "trycka på startknappen vid start.\n"
msgid "pressing both buttons at start up.\n"
msgstr "trycka båda knapparna vid uppstart.\n"
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr "pull-mask är i konflikt med riktnings-mask"
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr "pull_threshold måste vara mellan 1 och 32"
@@ -4310,6 +4314,9 @@ msgstr "zi måste vara av typ float"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi måste vara i formen (n_section, 2)"
+#~ msgid "Group full"
+#~ msgstr "Gruppen är full"
+
#~ msgid "In buffer elements must be 4 bytes long or less"
#~ msgstr "Inbuffertelement måste vara 4 byte långa eller mindre"
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index 9945b88f4..bb3e9cd58 100644
--- a/locale/zh_Latn_pinyin.po
+++ b/locale/zh_Latn_pinyin.po
@@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: circuitpython-cn\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-03-01 15:19+0000\n"
+"PO-Revision-Date: 2021-03-09 01:49+0000\n"
"Last-Translator: hexthat <hexthat@gmail.com>\n"
"Language-Team: Chinese Hanyu Pinyin\n"
"Language: zh_Latn_pinyin\n"
@@ -15,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.5\n"
+"X-Generator: Weblate 4.5.1\n"
#: main.c
msgid ""
@@ -1058,10 +1058,6 @@ msgstr "tōng yòng gù zhàng"
msgid "Group already used"
msgstr "Jítuán yǐjīng shǐyòngguò"
-#: shared-module/displayio/Group.c
-msgid "Group full"
-msgstr "Fēnzǔ yǐ mǎn"
-
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/I2C.c
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
@@ -1103,7 +1099,7 @@ msgstr "IV bì xū wéi %d zì jié cháng"
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "In-buffer elements must be <= 4 bytes long"
-msgstr ""
+msgstr "huǎn chōng nèi yuán sù bì xū <= 4 zì jié cháng"
#: py/persistentcode.c
msgid ""
@@ -1726,7 +1722,7 @@ msgstr "tào jiē zì wài"
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "Out-buffer elements must be <= 4 bytes long"
-msgstr ""
+msgstr "huǎn chōng wài yuán sù bì xū <= 4 zì jié cháng"
#: shared-bindings/bitops/__init__.c
#, c-format
@@ -1754,11 +1750,11 @@ msgstr "Dāng biànliàng_pínlǜ shì False zài jiànzhú shí PWM pínlǜ bù
#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "PWM slice already in use"
-msgstr ""
+msgstr "yǐ jīng zài shǐ yòng de PWM qiē piàn"
#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "PWM slice channel A already in use"
-msgstr ""
+msgstr "PWM qiē piàn tōng dào A yǐ zài shǐ yòng zhōng"
#: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
@@ -1799,7 +1795,7 @@ msgstr "Yǐn jiǎo jǐn shūrù"
#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "Pin must be on PWM Channel B"
-msgstr ""
+msgstr "yǐn jiǎo bì xū zài Pwm pín dào B shàng"
#: ports/atmel-samd/common-hal/countio/Counter.c
msgid "Pin must support hardware interrupts"
@@ -1820,6 +1816,10 @@ msgstr ""
"duōzì jié. Rúguǒ wúfǎ bìmiǎn, qǐng jiāng allow_inefficient = True chuándì "
"gěigòuzào hánshù"
+#: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
+msgid "Pins must be sequential"
+msgstr ""
+
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Pins must share PWM slice"
msgstr "yǐn jiǎo bì xū gòng xiǎng PWM qiē piàn"
@@ -2785,7 +2785,7 @@ msgstr "quānzi zhǐ néng zài yī wèi jiāzhǎng zhōng zhùcè"
#: shared-bindings/bitmaptools/__init__.c
msgid "clip point must be (x,y) tuple"
-msgstr ""
+msgstr "jiá dian bì xū shì (x,y) kuài"
#: shared-bindings/msgpack/ExtType.c
msgid "code outside range 0~127"
@@ -3804,6 +3804,10 @@ msgstr "Zài qǐdòng shí àn qǐdòng ànniǔ.\n"
msgid "pressing both buttons at start up.\n"
msgstr "zài qǐdòng shí tóngshí àn xià liǎng gè ànniǔ.\n"
+#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+msgid "pull masks conflict with direction masks"
+msgstr ""
+
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c
msgid "pull_threshold must be between 1 and 32"
msgstr "lā lì yù zhí bì xū jiè yú 1 hé 32 zhī jiān"
@@ -4306,6 +4310,9 @@ msgstr "zi bìxū wèi fú diǎn xíng"
msgid "zi must be of shape (n_section, 2)"
msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)"
+#~ msgid "Group full"
+#~ msgstr "Fēnzǔ yǐ mǎn"
+
#~ msgid "In buffer elements must be 4 bytes long or less"
#~ msgstr ""
#~ "zài huǎn chōng yuán jiàn zhōng bì xū shì 4 zì jié cháng huò gèng shǎo"
diff --git a/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk b/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
index 295d7b2ae..dc56219fe 100644
--- a/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_SQ"
LONGINT_IMPL = NONE
diff --git a/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk b/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk
index 34301da3f..3b5b05020 100644
--- a/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk
@@ -9,7 +9,6 @@ CHIP_VARIANT = SAMD51P19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk b/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk
index 9c1d61ec7..fea765c3f 100644
--- a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "MX25L51245G","GD25S512MD"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/bdmicro_vina_d51/mpconfigboard.mk b/ports/atmel-samd/boards/bdmicro_vina_d51/mpconfigboard.mk
index f1b2f4c1d..de350f7ab 100644
--- a/ports/atmel-samd/boards/bdmicro_vina_d51/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/bdmicro_vina_d51/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51N20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "MX25L51245G","GD25S512MD"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk b/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
index 62399b1cd..9417c2302 100644
--- a/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "GD25Q16C, W25Q16JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk
index 6ea6a7211..e01e5ca4d 100755
--- a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk
index 13ae59de4..40b5815ed 100755
--- a/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, S25FL064L"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index e8993d44d..97434a90b 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
index 446d1177f..d6994a4c0 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
# Turn off features and optimizations for Crickit build to make room for additional frozen libs.
diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
index 1f9b98bec..ec8566671 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
# Turn off features and optimizations for Crickit build to make room for additional frozen libs.
diff --git a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
index 6eb76c182..9f54bd118 100644
--- a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_PM"
# No I2S on SAMD51G.
diff --git a/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk b/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk
index 99e13f791..48b22b394 100644
--- a/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk
@@ -9,7 +9,6 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 0
LONGINT_IMPL = MPZ
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = AT25DF081A
CIRCUITPY_AUDIOIO = 0
diff --git a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
index b1dad30eb..13e0f75c7 100644
--- a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
@@ -7,6 +7,5 @@ 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
diff --git a/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk
index ac14e7395..8b2ce7fbf 100644
--- a/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q32C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/dynossat_edu_eps/mpconfigboard.mk b/ports/atmel-samd/boards/dynossat_edu_eps/mpconfigboard.mk
index 2d5234f82..915270c57 100644
--- a/ports/atmel-samd/boards/dynossat_edu_eps/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/dynossat_edu_eps/mpconfigboard.mk
@@ -8,7 +8,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q32C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/dynossat_edu_obc/mpconfigboard.mk b/ports/atmel-samd/boards/dynossat_edu_obc/mpconfigboard.mk
index 360940cf1..8f552c5b4 100644
--- a/ports/atmel-samd/boards/dynossat_edu_obc/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/dynossat_edu_obc/mpconfigboard.mk
@@ -8,7 +8,6 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q32C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index 7d034828e..fcf1b4a1a 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
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 c3938345d..e29f3c0b2 100644
--- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
index 7a80eea9b..dd012cb48 100644
--- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "S25FL064L"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk
index 345ac33c5..4c0c5137c 100644
--- a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAME51J19A
CHIP_FAMILY = same51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
index 78959dcd0..a8b4460a6 100644
--- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk
index 9f9bb0501..2f4db69b4 100755
--- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMR21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
index 08eb5c98b..cd43dd4d6 100644
--- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51P20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
index 6950378d5..4661a7acd 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = NONE
diff --git a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk
index 4bf155288..1154d0bb1 100644
--- a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q64C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
index b5d22bbbf..467c6af47 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
index eb02d3c27..7a45ef21e 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk
index 44b28acbc..41e24f199 100644
--- a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 3
EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index 8b17f15ea..964d33553 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
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 58d4e4980..1e6347659 100644
--- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 3
EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index c2603002c..553bf14f2 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 3
EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
index 321ee5f47..8f4c3f890 100644
--- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q16JV_IM, W25Q16JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk
index 9b242a3ff..86a04be87 100644
--- a/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q64C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/nfc_copy_cat/mpconfigboard.mk b/ports/atmel-samd/boards/nfc_copy_cat/mpconfigboard.mk
index 1b4a16a08..eb7a87fea 100644
--- a/ports/atmel-samd/boards/nfc_copy_cat/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/nfc_copy_cat/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
LONGINT_IMPL = NONE
diff --git a/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk b/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk
index e5fa0cd84..85b2dd420 100644
--- a/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
index 7a213faf4..54f00b744 100644
--- a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk b/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk
index 5ae09294d..a88e5e5e5 100644
--- a/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pycubed/mpconfigboard.mk b/ports/atmel-samd/boards/pycubed/mpconfigboard.mk
index 09aef7d92..1eb3cd523 100644
--- a/ports/atmel-samd/boards/pycubed/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pycubed/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = W25Q80DV
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk b/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk
index 46df12c4f..0c459c309 100644
--- a/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = MR2xH40
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
index 2db6786bf..5cef7b44c 100644
--- a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q64C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk b/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk
index d001374a5..a58e01654 100644
--- a/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q64C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pyportal/mpconfigboard.mk b/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
index 149141a4e..e8c27ecbf 100644
--- a/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
index dbc2d5ae9..c9ffd0954 100644
--- a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk
index cf982cb8f..a88bea91d 100644
--- a/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk
@@ -9,7 +9,6 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 0
LONGINT_IMPL = MPZ
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
CIRCUITPY_AUDIOBUSIO = 0
diff --git a/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk b/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk
index 470e4d9dc..e964d65d5 100644
--- a/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk
@@ -9,7 +9,6 @@ CHIP_FAMILY = samd51
#QSPI_FLASH_FILESYSTEM = 0
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk b/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk
index e4472e05d..53aac7df2 100644
--- a/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAME54P20A
CHIP_FAMILY = same54
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "N25Q256A"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk
index f57e016b4..716356837 100644
--- a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51P19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/serpente/mpconfigboard.mk b/ports/atmel-samd/boards/serpente/mpconfigboard.mk
index e024736c9..32ba32f38 100644
--- a/ports/atmel-samd/boards/serpente/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/serpente/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q32C
LONGINT_IMPL = NONE
diff --git a/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk b/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk
index bf88cd52d..e64045f13 100644
--- a/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
index 72c98867e..90bc6076f 100644
--- a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q16JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk
index 29579904a..197dea6fe 100755
--- a/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_lumidrive/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32FV"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/sparkfun_qwiic_micro_with_flash/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_qwiic_micro_with_flash/mpconfigboard.mk
index dd01c9985..7c2fd57ea 100644
--- a/ports/atmel-samd/boards/sparkfun_qwiic_micro_with_flash/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_qwiic_micro_with_flash/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32FV"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
index 6db5596ba..a5cd49239 100755
--- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32FV"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk
index 567f1db20..e33035d94 100644
--- a/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk
@@ -8,7 +8,6 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = AT25SF041A
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk b/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk
index 12c35d2f9..ee3f21b05 100644
--- a/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/stringcar_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/stringcar_m0_express/mpconfigboard.mk
index 0f43ab800..91644386f 100644
--- a/ports/atmel-samd/boards/stringcar_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/stringcar_m0_express/mpconfigboard.mk
@@ -8,7 +8,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = AT25SF161
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
index ee82b99c9..59a40d3dc 100644
--- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index f3afa61a8..8c9dc7169 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = W25Q32BV
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk
index 498429c9e..373cbba99 100644
--- a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk
@@ -7,6 +7,5 @@ CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
index d1ada6429..74f438b71 100644
--- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
@@ -7,7 +7,6 @@ CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = S25FL216K
LONGINT_IMPL = NONE
diff --git a/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk
index 5062200e1..1c96e1d23 100644
--- a/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk
@@ -9,7 +9,6 @@ CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "GD25Q16C, GD25Q64C"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk
index e8f94a290..ce9c2585f 100644
--- a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk
@@ -11,7 +11,6 @@ CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "GD25Q64C, W25Q32JV_IQ"
LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/common-hal/i2cperipheral/I2CPeripheral.c b/ports/atmel-samd/common-hal/i2cperipheral/I2CPeripheral.c
index 84642d404..53cbe854f 100644
--- a/ports/atmel-samd/common-hal/i2cperipheral/I2CPeripheral.c
+++ b/ports/atmel-samd/common-hal/i2cperipheral/I2CPeripheral.c
@@ -58,6 +58,10 @@ void common_hal_i2cperipheral_i2c_peripheral_construct(i2cperipheral_i2c_periphe
samd_peripherals_sercom_clock_init(sercom, sercom_index);
+#ifdef SAM_D5X_E5X
+ sercom->I2CS.CTRLC.bit.SDASETUP = 0x08;
+#endif
+
sercom->I2CS.CTRLA.bit.SWRST = 1;
while (sercom->I2CS.CTRLA.bit.SWRST || sercom->I2CS.SYNCBUSY.bit.SWRST) {}
diff --git a/ports/esp32s2/boards/franzininho_wifi_wroom/board.c b/ports/esp32s2/boards/franzininho_wifi_wroom/board.c
new file mode 100644
index 000000000..aaef97c7d
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wroom/board.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "supervisor/board.h"
+#include "mpconfigboard.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+void board_init(void) {
+ // USB
+ common_hal_never_reset_pin(&pin_GPIO19);
+ common_hal_never_reset_pin(&pin_GPIO20);
+
+ // Debug UART
+#ifdef DEBUG
+ common_hal_never_reset_pin(&pin_GPIO43);
+ common_hal_never_reset_pin(&pin_GPIO44);
+#endif /* DEBUG */
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
+
+void board_deinit(void) {
+}
diff --git a/ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h b/ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h
new file mode 100644
index 000000000..0960e96b6
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython 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.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "Franzininho WIFI w/Wroom"
+#define MICROPY_HW_MCU_NAME "ESP32S2"
+
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO18)
+
+#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
+
+#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n")
+
+#define AUTORESET_DELAY_MS 500
diff --git a/ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.mk b/ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.mk
new file mode 100644
index 000000000..fc6c62257
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.mk
@@ -0,0 +1,17 @@
+USB_VID = 0x303A
+USB_PID = 0x80AA
+USB_PRODUCT = "Franzininho WIFI w/Wroom"
+USB_MANUFACTURER = "Espressif"
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
+
+# The default queue depth of 16 overflows on release builds,
+# so increase it to 32.
+CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
+
+CIRCUITPY_ESP_FLASH_MODE=dio
+CIRCUITPY_ESP_FLASH_FREQ=40m
+CIRCUITPY_ESP_FLASH_SIZE=4MB
+
+CIRCUITPY_MODULE=wroom
diff --git a/ports/esp32s2/boards/franzininho_wifi_wroom/pins.c b/ports/esp32s2/boards/franzininho_wifi_wroom/pins.c
new file mode 100644
index 000000000..0562d9331
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wroom/pins.c
@@ -0,0 +1,48 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
+ { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
+ { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
+ { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
+ { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
+ { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
+ { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
+ { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
+ { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
+ { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
+ { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) },
+ { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) },
+ { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) },
+ { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
+ { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) },
+ { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) },
+ { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) },
+ { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) },
+ { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
+ { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) },
+ { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) },
+ { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) },
+ { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) },
+ { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) },
+ { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) },
+ { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) },
+ { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) },
+ { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
+ { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
+ { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) },
+ { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) },
+ { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/esp32s2/boards/franzininho_wifi_wroom/sdkconfig b/ports/esp32s2/boards/franzininho_wifi_wroom/sdkconfig
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wroom/sdkconfig
diff --git a/ports/esp32s2/boards/franzininho_wifi_wrover/board.c b/ports/esp32s2/boards/franzininho_wifi_wrover/board.c
new file mode 100644
index 000000000..aaef97c7d
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wrover/board.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "supervisor/board.h"
+#include "mpconfigboard.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+void board_init(void) {
+ // USB
+ common_hal_never_reset_pin(&pin_GPIO19);
+ common_hal_never_reset_pin(&pin_GPIO20);
+
+ // Debug UART
+#ifdef DEBUG
+ common_hal_never_reset_pin(&pin_GPIO43);
+ common_hal_never_reset_pin(&pin_GPIO44);
+#endif /* DEBUG */
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
+
+void board_deinit(void) {
+}
diff --git a/ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h b/ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h
new file mode 100644
index 000000000..fd10ee0b5
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython 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.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "Franzininho WIFI w/Wrover"
+#define MICROPY_HW_MCU_NAME "ESP32S2"
+
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO18)
+
+#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
+
+#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n")
+
+#define AUTORESET_DELAY_MS 500
diff --git a/ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.mk b/ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.mk
new file mode 100644
index 000000000..c0c47cef1
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.mk
@@ -0,0 +1,17 @@
+USB_VID = 0x303A
+USB_PID = 0x80AD
+USB_PRODUCT = "Franzininho WIFI w/Wrover"
+USB_MANUFACTURER = "Espressif"
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
+
+# The default queue depth of 16 overflows on release builds,
+# so increase it to 32.
+CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
+
+CIRCUITPY_ESP_FLASH_MODE=dio
+CIRCUITPY_ESP_FLASH_FREQ=40m
+CIRCUITPY_ESP_FLASH_SIZE=4MB
+
+CIRCUITPY_MODULE=wrover
diff --git a/ports/esp32s2/boards/franzininho_wifi_wrover/pins.c b/ports/esp32s2/boards/franzininho_wifi_wrover/pins.c
new file mode 100644
index 000000000..0562d9331
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wrover/pins.c
@@ -0,0 +1,48 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
+ { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
+ { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
+ { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
+ { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
+ { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
+ { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
+ { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
+ { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
+ { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
+ { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) },
+ { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) },
+ { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) },
+ { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
+ { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) },
+ { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) },
+ { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) },
+ { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) },
+ { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
+ { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) },
+ { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) },
+ { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) },
+ { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) },
+ { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) },
+ { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) },
+ { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) },
+ { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) },
+ { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
+ { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
+ { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) },
+ { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) },
+ { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/esp32s2/boards/franzininho_wifi_wrover/sdkconfig b/ports/esp32s2/boards/franzininho_wifi_wrover/sdkconfig
new file mode 100644
index 000000000..9d8bbde96
--- /dev/null
+++ b/ports/esp32s2/boards/franzininho_wifi_wrover/sdkconfig
@@ -0,0 +1,33 @@
+CONFIG_ESP32S2_SPIRAM_SUPPORT=y
+
+#
+# SPI RAM config
+#
+# CONFIG_SPIRAM_TYPE_AUTO is not set
+CONFIG_SPIRAM_TYPE_ESPPSRAM16=y
+# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
+# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
+CONFIG_SPIRAM_SIZE=2097152
+
+#
+# PSRAM clock and cs IO for ESP32S2
+#
+CONFIG_DEFAULT_PSRAM_CLK_IO=30
+CONFIG_DEFAULT_PSRAM_CS_IO=26
+# end of PSRAM clock and cs IO for ESP32S2
+
+# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
+# CONFIG_SPIRAM_RODATA is not set
+# CONFIG_SPIRAM_SPEED_80M is not set
+CONFIG_SPIRAM_SPEED_40M=y
+# CONFIG_SPIRAM_SPEED_26M is not set
+# CONFIG_SPIRAM_SPEED_20M is not set
+CONFIG_SPIRAM=y
+CONFIG_SPIRAM_BOOT_INIT=y
+# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
+CONFIG_SPIRAM_USE_MEMMAP=y
+# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
+# CONFIG_SPIRAM_USE_MALLOC is not set
+CONFIG_SPIRAM_MEMTEST=y
+# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
+# end of SPI RAM config
diff --git a/ports/nrf/boards/TG-Watch/mpconfigboard.mk b/ports/nrf/boards/TG-Watch/mpconfigboard.mk
index f1aac6d71..8407d8487 100644
--- a/ports/nrf/boards/TG-Watch/mpconfigboard.mk
+++ b/ports/nrf/boards/TG-Watch/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "TG-Techie"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "GD25Q16C, W25Q128JV_SQ"
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
diff --git a/ports/nrf/boards/aramcon_badge_2019/mpconfigboard.mk b/ports/nrf/boards/aramcon_badge_2019/mpconfigboard.mk
index 09252ab4b..06cd9633d 100644
--- a/ports/nrf/boards/aramcon_badge_2019/mpconfigboard.mk
+++ b/ports/nrf/boards/aramcon_badge_2019/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "ARAMCON Badge Team"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
CIRCUITPY_DISPLAYIO = 1
diff --git a/ports/nrf/boards/bastble/mpconfigboard.mk b/ports/nrf/boards/bastble/mpconfigboard.mk
index eca900de7..417c99358 100644
--- a/ports/nrf/boards/bastble/mpconfigboard.mk
+++ b/ports/nrf/boards/bastble/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "ElectronicCats"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
index 6b5c0424f..bc0079037 100644
--- a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
+++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Adafruit Industries LLC"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/clue_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/clue_nrf52840_express/mpconfigboard.mk
index 16cb20824..f94e49e47 100644
--- a/ports/nrf/boards/clue_nrf52840_express/mpconfigboard.mk
+++ b/ports/nrf/boards/clue_nrf52840_express/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Adafruit Industries LLC"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.mk b/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.mk
index 5813e6136..6d0c13e45 100644
--- a/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.mk
+++ b/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Adafruit Industries LLC"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk
index 84861a1f0..b291203e2 100644
--- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk
+++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Adafruit Industries LLC"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/hiibot_bluefi/mpconfigboard.mk b/ports/nrf/boards/hiibot_bluefi/mpconfigboard.mk
index d60124348..c85b97894 100644
--- a/ports/nrf/boards/hiibot_bluefi/mpconfigboard.mk
+++ b/ports/nrf/boards/hiibot_bluefi/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "HiiBot"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q16JV_IQ"
diff --git a/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk
index d5587f4b9..57b39b512 100644
--- a/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk
+++ b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk
@@ -9,5 +9,4 @@ MCU_CHIP = nrf52840
CIRCUITPY_BITBANG_APA102 = 1
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk
index fc630e5bb..e7547af71 100644
--- a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk
+++ b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "Makerdiary"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25R6435F"
CIRCUITPY_ENABLE_MPY_NATIVE = 1
diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk
index 4e6aebc8e..cd19c25b1 100644
--- a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk
+++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "Makerdiary"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25R6435F"
CIRCUITPY_ENABLE_MPY_NATIVE = 1
diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk
index d69bc8235..7da9ed189 100644
--- a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk
+++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "makerdiary"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25R6435F"
diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
index b972bcbed..ef0992a74 100644
--- a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
+++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "Adafruit Industries LLC"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
CIRCUITPY__EVE = 1
diff --git a/ports/nrf/boards/ohs2020_badge/mpconfigboard.mk b/ports/nrf/boards/ohs2020_badge/mpconfigboard.mk
index 7d2c6de98..2e6e885f5 100644
--- a/ports/nrf/boards/ohs2020_badge/mpconfigboard.mk
+++ b/ports/nrf/boards/ohs2020_badge/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "OSHWA"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q128JV_SQ"
diff --git a/ports/nrf/boards/particle_argon/mpconfigboard.mk b/ports/nrf/boards/particle_argon/mpconfigboard.mk
index f8d3d2aca..eaed5527c 100644
--- a/ports/nrf/boards/particle_argon/mpconfigboard.mk
+++ b/ports/nrf/boards/particle_argon/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Particle"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25L3233F"
diff --git a/ports/nrf/boards/particle_boron/mpconfigboard.mk b/ports/nrf/boards/particle_boron/mpconfigboard.mk
index eada97a73..26fe7b83d 100644
--- a/ports/nrf/boards/particle_boron/mpconfigboard.mk
+++ b/ports/nrf/boards/particle_boron/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Particle"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25L3233F"
diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.mk b/ports/nrf/boards/particle_xenon/mpconfigboard.mk
index 6062da378..0722c4ac6 100644
--- a/ports/nrf/boards/particle_xenon/mpconfigboard.mk
+++ b/ports/nrf/boards/particle_xenon/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Particle"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25L3233F"
diff --git a/ports/nrf/boards/pca10056/mpconfigboard.mk b/ports/nrf/boards/pca10056/mpconfigboard.mk
index f24e6f667..48f68a30a 100644
--- a/ports/nrf/boards/pca10056/mpconfigboard.mk
+++ b/ports/nrf/boards/pca10056/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "Nordic Semiconductor"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25R6435F"
diff --git a/ports/nrf/boards/pitaya_go/mpconfigboard.mk b/ports/nrf/boards/pitaya_go/mpconfigboard.mk
index 247ddd8ac..14e2108b7 100644
--- a/ports/nrf/boards/pitaya_go/mpconfigboard.mk
+++ b/ports/nrf/boards/pitaya_go/mpconfigboard.mk
@@ -7,5 +7,4 @@ USB_MANUFACTURER = "Makerdiary"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25R6435F"
diff --git a/ports/nrf/boards/simmel/mpconfigboard.mk b/ports/nrf/boards/simmel/mpconfigboard.mk
index 283e3d169..005ec8af2 100644
--- a/ports/nrf/boards/simmel/mpconfigboard.mk
+++ b/ports/nrf/boards/simmel/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "Betrusted"
MCU_CHIP = nrf52833
# SPI_FLASH_FILESYSTEM = 1
-# EXTERNAL_FLASH_DEVICE_COUNT = 1
# EXTERNAL_FLASH_DEVICES = "MX25R1635F"
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/nrf/boards/sparkfun_nrf52840_micromod/README.md b/ports/nrf/boards/sparkfun_nrf52840_micromod/README.md
new file mode 100644
index 000000000..094102c27
--- /dev/null
+++ b/ports/nrf/boards/sparkfun_nrf52840_micromod/README.md
@@ -0,0 +1,70 @@
+# SparkFun MicroMod nRF52840 Processor
+
+Featuring the nRF52840 SoC from Nordic Semiconductor, the [SparkFun MicroMod nRF52840 Processor](https://www.sparkfun.com/products/16984) offers a powerful combination of ARM Cortex-M4 CPU and 2.4 GHz Bluetooth transceiver in the MicroMod form-factor with the M.2 MicroMod connector to allow you to plug in a compatible MicroMod Carrier Board with any number of peripherals.
+
+The MicroMod nRF52840 Processor features the same Raytac MDBT50Q-P1M found on our [Pro nRF52840 Mini](https://www.sparkfun.com/products/15025). This module includes an integrated trace antenna, fits the IC to an FCC-approved footprint along with including decoupling and timing mechanisms that would need to be designed into a circuit using the bare nRF52840 IC. The Bluetooth transceiver included on the nRF52840 boasts a BT 5.1 stack and supports Bluetooth 5, Bluetooth mesh, IEEE 802.15.4 (Zigbee & Thread) and 2.4Ghz RF wireless protocols (including Nordic's proprietary RF protocol) allowing you to pick which option works best for your application.
+
+We've also routed two I<sup>2</sup>C buses, 2 SPI buses, eleven GPIO, dedicated digital, analog, PWM & PDM pins along with multiple serial UARTS to cover nearly all of your peripheral needs.
+
+## CircuitPython Pin Defs
+
+CircuitPython pin definitions, while simialr to other boards represent a slight departure from just the typical `A` and `D` pin definitions. The majority of general pins are labled as `G` (or alternatively, `BUS`,) as the MicroMod system they build on uses those names to specify pins that may not be specficially analog or digital.
+
+This can be somewhat confusing, especially around the analog pins. Here's a quick pin-map. This pin map will use the label either on the [SparkFun MicroMod ATP Carrier Board](https://www.sparkfun.com/products/16885), or the pin name on the [graphical datasheet](https://cdn.sparkfun.com/assets/learn_tutorials/1/4/0/1/MicroMod_nRF52840_v1.0_Graphical_Datasheet.pdf). Some of the aditional aliases are just names to make naming consistent (e.g.: RTS/CTS), but they also can refer to additional functionality a pin may have (e.g.: NFC pins)
+
+MicroMod Pin # | ATP Pin Label | Pin Definition | Additional Definitons | Pin/Port Reference | Notes
+:--------------|:--------------|:--------------|:-----------------------|:-------------------|:------
+8 | G11 | | | (Not Connected) |
+10 | D0 | D0 | | P0_27 |
+11 | BOOT | BOOT | BUTTON1 | P0_07 |
+12 | SDA | SDA | | P0_08 |
+13 | RTS1 | RTS | RTS1 | P1_02 |
+14 | SCL | SCL | | P0_11 |
+15 | CTS1 | CTS | CTS1 | P1_09 |
+16 | /I2C INT | I2C_INT | P0_15 |
+17 | TX | TX | TX1 | P1_03 |
+18 | D1 | D1 | CAM_TRIG | P1_08 |
+19 | RX | RX | RX1 | P1_10 |
+20 | RX2 | RX2 | | P1_05 |
+22 | TX2 | TX2 | | P1_07 |
+32 | PWM0 | PWM0 | P0_06 |
+34 | A0 | A0 | ADC0 | P0_04 | Attached to AIN2
+38 | A1 | A1 | ADC1 | P0_05 | Attached to AIN3
+40 | G0 | G0 | BUS0 | P0_29 | Attached to AIN5
+42 | G1 | G1 | BUS1 | P0_03 | Attached to AIN1
+44 | G2 | G2 | BUS2 | P1_13 |
+46 | G3 | G3 | BUS3 | P1_12 |
+47 | PWM1 | PWM1 | P0_16 |
+48 | G4 | G4 | BUS4 | P1_11 |
+49 | BATT_VIN | BATT_VIN3 | | P0_30 | Attached to AIN6, will be battery voltage / 3. |
+50 | PDM_CLK | PDM_CLK | | P0_25 |
+51 | SDA1 | SDA1 | | P1_01 |
+52 | PDM_DATA | PDM_DATA | | P0_26 |
+53 | SCL1 | SCL1 | | P0_24 |
+55 | /CS | CS | | P0_20 |
+57 | SCK | SCK | | P0_28 | Attached to AIN4
+59 | COPI | COPI | MOSI | P0_31 | Attached to AIN7
+61 | CIPO | CIPO | MISO | P0_02 |
+63 | G10 | G10 | NFC2, ADC_DP, CAM_VSYNC | P0_10 | Attached to NFC2
+65 | G9 | G9 | NFC1, ADC_DM, CAM_HSYNC | P0_09 | Attached to NFC1
+67 | G8 | G8 | | P1_14 |
+69 | G7 | G7 | BUS7 | P1_04 |
+71 | G6 | G6 | BUS6 | P1_06 |
+73 | G5 | G5 | BUS5 | P0_15 |
+
+## Peripheral Naming
+
+CircuitPython attempts to stay in line with the naming of the serial peripheral naming in the MicroMod system. The bare UART pins are also named <pin>1. The UART 2 pins are named <pin>2. However, the I2C names on MicroMod are <I2C pin> and <I2C pin>1. Perhaps this will change in the future, but as of [Interface v1](https://cdn.sparkfun.com/assets/learn_tutorials/1/2/0/6/SparkFun_MicroMod_Interface_v1.0_-_Pin_Descriptions.pdf), it may lead to some confusion.
+
+
+## Bootloader Notes
+
+The MicroMod nRF52840 Processor needs to have the [Adafruit nRF52 UF2 bootloader](https://github.com/adafruit/Adafruit_nRF52_Bootloader/pull/194) flashed on it. [[TODO: LINK TO BUILD]]
+
+## Hardware Reference
+
+The MicroMod nRF52840 Processor hardware layout is open source:
+
+* [Schematic](https://cdn.sparkfun.com/assets/f/0/9/9/e/MicroMod_Processor_Board-nRF52840.pdf)
+* [Eagle Files](https://cdn.sparkfun.com/assets/3/0/5/d/a/MicroMod_Processor_Board-nRF52840.zip)
+* [Hookup Guide](https://learn.sparkfun.com/tutorials/micromod-nrf52840-processor-hookup-guide)
diff --git a/ports/nrf/boards/sparkfun_nrf52840_micromod/board.c b/ports/nrf/boards/sparkfun_nrf52840_micromod/board.c
new file mode 100644
index 000000000..781793328
--- /dev/null
+++ b/ports/nrf/boards/sparkfun_nrf52840_micromod/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 "supervisor/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.h b/ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.h
new file mode 100644
index 000000000..c53fc45d2
--- /dev/null
+++ b/ports/nrf/boards/sparkfun_nrf52840_micromod/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) 2021 Chris Marc Dailey
+ *
+ * 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 MICROPY_HW_BOARD_NAME "SparkFun MicroMod nRF52840"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_11)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_08)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_28)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P0_31)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_02)
+
+#define DEFAULT_UART_BUS_RX (&pin_P1_10)
+#define DEFAULT_UART_BUS_TX (&pin_P1_03)
+
+#define BOARD_HAS_32KHZ_XTAL (1)
+#define BOARD_HAS_CRYSTAL (1)
+
+#if QSPI_FLASH_FILESYSTEM
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 14) // Labeled 'SPI_COPI1/SDIO_CMD' in schematic.
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 21) // Labeled 'SPI_CIPO1/SDIO_DATA0' in schematic.
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 23) // Labeled 'SPI_DATA2' in schematic.
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(1, 0) // Labeled 'SPI_CS1/SDIO_DATA3' in schematic.
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) // Labeled 'SPI_SCK1/SDIO_CLK' in schematic.
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 12) // Labeled 'FLASH_CS' in schematic.
+#endif // QSPI_FLASH_FILESYSTEM
diff --git a/ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.mk b/ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.mk
new file mode 100644
index 000000000..4c4bcd089
--- /dev/null
+++ b/ports/nrf/boards/sparkfun_nrf52840_micromod/mpconfigboard.mk
@@ -0,0 +1,10 @@
+USB_VID = 0x1B4F
+USB_PID = 0x0021
+USB_PRODUCT = "SFE_nRF52840_MicroMod"
+USB_MANUFACTURER = "SparkFun Electronics"
+
+MCU_CHIP = nrf52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "W25Q128JV_PM"
diff --git a/ports/nrf/boards/sparkfun_nrf52840_micromod/pins.c b/ports/nrf/boards/sparkfun_nrf52840_micromod/pins.c
new file mode 100644
index 000000000..65700f24e
--- /dev/null
+++ b/ports/nrf/boards/sparkfun_nrf52840_micromod/pins.c
@@ -0,0 +1,113 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ // D pins (D0-D1)
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_27) }, // 0.27 - D0
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P1_08) }, // 1.08 - D1 | CAM_TRIG
+ { MP_ROM_QSTR(MP_QSTR_CAM_TRIG), MP_ROM_PTR(&pin_P1_08) }, // CAM_TRIG alias
+
+ // A pins (A0-A1)
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) }, // 0.04 - A0 | ADC0 (AIN2)
+ { MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_PTR(&pin_P0_04) }, // ADC0 alias
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) }, // 0.05 - A1 | ADC1 (AIN3)
+ { MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_PTR(&pin_P0_05) }, // ADC1 alias
+
+ // G pins (G0-G11, G11 NC)
+ { MP_ROM_QSTR(MP_QSTR_G0), MP_ROM_PTR(&pin_P0_29) }, // 0.29 - G0 | GPIO0 | BUS0 (AIN5)
+ { MP_ROM_QSTR(MP_QSTR_BUS0), MP_ROM_PTR(&pin_P0_29) }, // BUS0 alias
+ { MP_ROM_QSTR(MP_QSTR_G1), MP_ROM_PTR(&pin_P0_03) }, // 0.03 - G1 | GPIO1 | BUS1 (AIN1)
+ { MP_ROM_QSTR(MP_QSTR_BUS1), MP_ROM_PTR(&pin_P0_03) }, // BUS1 alias
+ { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_P1_13) }, // 1.13 - G2 | GPIO2 | BUS2
+ { MP_ROM_QSTR(MP_QSTR_BUS2), MP_ROM_PTR(&pin_P1_13) }, // BUS2 alias
+ { MP_ROM_QSTR(MP_QSTR_G3), MP_ROM_PTR(&pin_P1_12) }, // 1.12 - G3 | GPIO3 | BUS3
+ { MP_ROM_QSTR(MP_QSTR_BUS3), MP_ROM_PTR(&pin_P1_12) }, // BUS3 alias
+ { MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_P1_11) }, // 1.11 - G4 | GPIO4 | BUS4
+ { MP_ROM_QSTR(MP_QSTR_BUS4), MP_ROM_PTR(&pin_P1_11) }, // BUS4 alias
+ { MP_ROM_QSTR(MP_QSTR_G5), MP_ROM_PTR(&pin_P0_17) }, // 0.17 - G5 | GPIO5 | BUS5
+ { MP_ROM_QSTR(MP_QSTR_BUS5), MP_ROM_PTR(&pin_P0_17) }, // BUS5 alias
+ { MP_ROM_QSTR(MP_QSTR_G6), MP_ROM_PTR(&pin_P1_06) }, // 1.06 - G6 | GPIO6 | BUS6
+ { MP_ROM_QSTR(MP_QSTR_BUS6), MP_ROM_PTR(&pin_P1_06) }, // BUS6 alias
+ { MP_ROM_QSTR(MP_QSTR_G7), MP_ROM_PTR(&pin_P1_04) }, // 1.04 - G7 | GPIO7 | BUS7
+ { MP_ROM_QSTR(MP_QSTR_BUS7), MP_ROM_PTR(&pin_P1_04) }, // BUS7 alias
+ { MP_ROM_QSTR(MP_QSTR_G8), MP_ROM_PTR(&pin_P1_14) }, // 1.14 - G8 | GPIO8
+ { MP_ROM_QSTR(MP_QSTR_G9), MP_ROM_PTR(&pin_P0_09) }, // 0.09 - G9 | GPIO9/NFC1 | ADC_D- | CAM_HSYNC (NFC1)
+ { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) }, // NFC1 alias
+ { MP_ROM_QSTR(MP_QSTR_ADC_DM), MP_ROM_PTR(&pin_P0_09) }, // ADC_DM alias
+ { MP_ROM_QSTR(MP_QSTR_CAM_HSYNC), MP_ROM_PTR(&pin_P0_09) }, // CAM_HSYNC alias
+ { MP_ROM_QSTR(MP_QSTR_G10), MP_ROM_PTR(&pin_P0_10) }, // 0.10 - G10 | GPIO10/NFC2 | ADC_D+ | CAM_VSYNC (NFC2)
+ { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) }, // NFC2 alias
+ { MP_ROM_QSTR(MP_QSTR_ADC_DP), MP_ROM_PTR(&pin_P0_10) }, // ADC_DP alias
+ { MP_ROM_QSTR(MP_QSTR_CAM_VSYNC), MP_ROM_PTR(&pin_P0_10) }, // CAM_VSYNC alias
+ // NC - G11
+
+ // PWM pins (PWM0-PWM1)
+ { MP_ROM_QSTR(MP_QSTR_PWM0), MP_ROM_PTR(&pin_P0_06) }, // 0.06 - PWM0
+ { MP_ROM_QSTR(MP_QSTR_PWM1), MP_ROM_PTR(&pin_P0_16) }, // 0.16 - PWM1
+
+ // PDM
+ { MP_ROM_QSTR(MP_QSTR_PDM_CLK), MP_ROM_PTR(&pin_P0_25) }, // 0.25 - PDM_CLK | AUD_BCLK
+ { MP_ROM_QSTR(MP_QSTR_PDM_DATA), MP_ROM_PTR(&pin_P0_26) }, // 0.26 - PDM_DATA | AUD_LRCLK
+
+ // Battery Voltage Monitor
+ { MP_ROM_QSTR(MP_QSTR_BATT_VIN3), MP_ROM_PTR(&pin_P0_30) }, // 0.30 - BATT_VIN/3 (AIN6)
+
+ // I2C
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_08) }, // 0.08 - SDA
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_11) }, // 0.11 - SCL (TRACEDATA2)
+
+ { MP_ROM_QSTR(MP_QSTR_I2C_INT), MP_ROM_PTR(&pin_P0_15) }, // 0.15 - I2C_INT
+
+ { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_P1_01) }, // 1.01 - SDA1
+ { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_P0_24) }, // 0.24 - SCL1
+
+ // SPI
+ { MP_ROM_QSTR(MP_QSTR_CIPO), MP_ROM_PTR(&pin_P0_02) }, // 0.02 - CIPO | SPI_CIPO
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_02) }, // MISO alias
+ { MP_ROM_QSTR(MP_QSTR_COPI), MP_ROM_PTR(&pin_P0_31) }, // 0.31 - COPI | SPI_COPI (AIN7)
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_31) }, // MOSI alias
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_28) }, // 0.28 - SCK | SPI_SCK (AIN4)
+ { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_P0_20) }, // 0.20 - /CS | SPI_/CS
+
+ // QSPI, used by flash on this board, but is broken out
+ // on the MicroMod connector, to to the SDIO pins.
+ { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_P0_19) }, // 0.00 - SDIO SCK | Used as: QSPI flash SCK
+ { MP_ROM_QSTR(MP_QSTR_SPI_SCK1), MP_ROM_PTR(&pin_P0_19) }, // SPI_SCK1 alias
+ { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_P0_14) }, // 0.00 - SDIO CMD | Used as: QSPI flash D0 (or SDI)
+ { MP_ROM_QSTR(MP_QSTR_SPI_COPI1), MP_ROM_PTR(&pin_P0_14) }, // SPI_COPI1 alias
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_P0_21) },// 0.00 - SDIO DATA0 | Used as: QSPI flash D1 (or SDO)
+ { MP_ROM_QSTR(MP_QSTR_SPI_CIPO1), MP_ROM_PTR(&pin_P0_21) }, // SPI_CIPO1 alias
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_P0_22) },// 0.00 - SDIO DATA1 | Unused for flash.
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_P0_23) },// 0.00 - SDIO DATA2 | Used as: QSPI flash D2
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_P1_00) },// 0.00 - SDIO DATA3 | Use das: QSPI flash D3 (or /HOLD)
+ { MP_ROM_QSTR(MP_QSTR_SPI_CS1), MP_ROM_PTR(&pin_P1_00) }, // SPI_CS1 alias
+
+ // Reset Pin
+ { MP_ROM_QSTR(MP_QSTR_RESET), MP_ROM_PTR(&pin_P1_14) }, // 0.18 - /RESET (NRESET)
+
+ // LED
+ { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_P0_13) }, // 0.13 - LED_BUILTIN | STAT | Blue LED
+
+ // Button
+ { MP_ROM_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_P0_07) }, // 0.07 - /BOOT [Active Low] (TRACECLK) - Is button on carriers.
+ { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_P0_07) }, // BOOT alias
+
+ // UART
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P1_10) }, // 1.10 - UART RX | RX1
+ { MP_ROM_QSTR(MP_QSTR_RX1), MP_ROM_PTR(&pin_P1_10) }, // RX1 alias
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P1_03) }, // 1.03 - UART TX | TX1
+ { MP_ROM_QSTR(MP_QSTR_TX1), MP_ROM_PTR(&pin_P1_03) }, // TX1 alias
+ { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_PTR(&pin_P1_09) }, // 1.09 - UART CTS | CTS1 (TRACEDATA3)
+ { MP_ROM_QSTR(MP_QSTR_CTS1), MP_ROM_PTR(&pin_P1_09) }, // CTS1 alias
+ { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_PTR(&pin_P1_02) }, // 1.02 - UART RTS | RTS1
+ { MP_ROM_QSTR(MP_QSTR_RTS1), MP_ROM_PTR(&pin_P1_02) }, // RTS1 alias
+
+ { MP_ROM_QSTR(MP_QSTR_RX2), MP_ROM_PTR(&pin_P1_05) }, // 1.05 - UART RX | RX2
+ { MP_ROM_QSTR(MP_QSTR_TX2), MP_ROM_PTR(&pin_P1_07) }, // 1.07 - UART TX | TX2
+
+ // Board Objects
+ { 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/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk
index e8bd636ad..7808b1657 100644
--- a/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk
+++ b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk
@@ -6,5 +6,4 @@ USB_MANUFACTURER = "TinkeringTech LLC"
MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile
index ffd50299f..db4bd7958 100644
--- a/ports/raspberrypi/Makefile
+++ b/ports/raspberrypi/Makefile
@@ -106,7 +106,7 @@ INC += -I. \
-I$(BUILD)
# Pico specific configuration
-CFLAGS += -DPICO_ON_DEVICE=1 -DPICO_NO_BINARY_INFO=0 -DPICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 -DPICO_DIVIDER_CALL_IDIV0=0 -DPICO_DIVIDER_CALL_LDIV0=0 -DPICO_DIVIDER_HARDWARE=1 -DPICO_DOUBLE_ROM=1 -DPICO_FLOAT_ROM=1 -DPICO_MULTICORE=1 -DPICO_BITS_IN_RAM=0 -DPICO_DIVIDER_IN_RAM=0 -DPICO_DOUBLE_PROPAGATE_NANS=0 -DPICO_DOUBLE_IN_RAM=0 -DPICO_MEM_IN_RAM=0 -DPICO_FLOAT_IN_RAM=0 -DPICO_FLOAT_PROPAGATE_NANS=1 -DPICO_NO_FLASH=0 -DPICO_COPY_TO_RAM=0 -DPICO_DISABLE_SHARED_IRQ_HANDLERS=0
+CFLAGS += -DPICO_ON_DEVICE=1 -DPICO_NO_BINARY_INFO=0 -DPICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1 -DPICO_DIVIDER_CALL_IDIV0=0 -DPICO_DIVIDER_CALL_LDIV0=0 -DPICO_DIVIDER_HARDWARE=1 -DPICO_DOUBLE_ROM=1 -DPICO_FLOAT_ROM=1 -DPICO_MULTICORE=1 -DPICO_BITS_IN_RAM=0 -DPICO_DIVIDER_IN_RAM=0 -DPICO_DOUBLE_PROPAGATE_NANS=0 -DPICO_DOUBLE_IN_RAM=0 -DPICO_MEM_IN_RAM=0 -DPICO_FLOAT_IN_RAM=0 -DPICO_FLOAT_PROPAGATE_NANS=1 -DPICO_NO_FLASH=0 -DPICO_COPY_TO_RAM=0 -DPICO_DISABLE_SHARED_IRQ_HANDLERS=0 -DPICO_NO_BI_BOOTSEL_VIA_DOUBLE_RESET=0
OPTIMIZATION_FLAGS ?= -O3
# TinyUSB defines
CFLAGS += -DTUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX=1 -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
@@ -177,6 +177,7 @@ SRC_SDK := \
src/rp2_common/hardware_watchdog/watchdog.c \
src/rp2_common/hardware_xosc/xosc.c \
src/rp2_common/pico_bootrom/bootrom.c \
+ src/rp2_common/pico_bootsel_via_double_reset/pico_bootsel_via_double_reset.c \
src/rp2_common/pico_double/double_init_rom.c \
src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c \
src/rp2_common/pico_float/float_init_rom.c \
diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.c b/ports/raspberrypi/bindings/rp2pio/StateMachine.c
index 444e00ace..90fd7f95e 100644
--- a/ports/raspberrypi/bindings/rp2pio/StateMachine.c
+++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.c
@@ -69,6 +69,8 @@
//| initial_out_pin_direction: int = 0xffffffff,
//| first_in_pin: Optional[microcontroller.Pin] = None,
//| in_pin_count: int = 1,
+//| pull_in_pin_up: int = 0,
+//| pull_in_pin_down: int = 0,
//| first_set_pin: Optional[microcontroller.Pin] = None,
//| set_pin_count: int = 1,
//| initial_set_pin_state: int = 0,
@@ -99,6 +101,8 @@
//| :param int initial_out_pin_direction: the initial output direction for out pins starting at first_out_pin
//| :param ~microcontroller.Pin first_in_pin: the first pin to use with the IN instruction
//| :param int in_pin_count: the count of consecutive pins to use with IN starting at first_in_pin
+//| :param int pull_in_pin_up: a 1-bit in this mask sets pull up on the corresponding in pin
+//| :param int pull_in_pin_down: a 1-bit in this mask sets pull up on the corresponding in pin. Setting both pulls enables a "bus keep" function, i.e. a weak pull to whatever is current high/low state of GPIO.
//| :param ~microcontroller.Pin first_set_pin: the first pin to use with the SET instruction
//| :param int set_pin_count: the count of consecutive pins to use with SET starting at first_set_pin
//| :param int initial_set_pin_state: the initial output value for set pins starting at first_set_pin
@@ -133,6 +137,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
enum { ARG_program, ARG_frequency, ARG_init,
ARG_first_out_pin, ARG_out_pin_count, ARG_initial_out_pin_state, ARG_initial_out_pin_direction,
ARG_first_in_pin, ARG_in_pin_count,
+ ARG_pull_in_pin_up, ARG_pull_in_pin_down,
ARG_first_set_pin, ARG_set_pin_count, ARG_initial_set_pin_state, ARG_initial_set_pin_direction,
ARG_first_sideset_pin, ARG_sideset_pin_count, ARG_initial_sideset_pin_state, ARG_initial_sideset_pin_direction,
ARG_exclusive_pin_use,
@@ -151,6 +156,8 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
{ MP_QSTR_first_in_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_in_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
+ { MP_QSTR_pull_in_pin_up, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_pull_in_pin_down, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_first_set_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_set_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
@@ -233,7 +240,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
args[ARG_frequency].u_int,
init_bufinfo.buf, init_bufinfo.len / 2,
first_out_pin, args[ARG_out_pin_count].u_int, args[ARG_initial_out_pin_state].u_int, args[ARG_initial_out_pin_direction].u_int,
- first_in_pin, args[ARG_in_pin_count].u_int,
+ first_in_pin, args[ARG_in_pin_count].u_int, args[ARG_pull_in_pin_up].u_int, args[ARG_pull_in_pin_down].u_int,
first_set_pin, args[ARG_set_pin_count].u_int, args[ARG_initial_set_pin_state].u_int, args[ARG_initial_set_pin_direction].u_int,
first_sideset_pin, args[ARG_sideset_pin_count].u_int, args[ARG_initial_sideset_pin_state].u_int, args[ARG_initial_sideset_pin_direction].u_int,
args[ARG_exclusive_pin_use].u_bool,
@@ -548,6 +555,24 @@ const mp_obj_property_t rp2pio_statemachine_rxstall_obj = {
(mp_obj_t)&mp_const_none_obj},
};
+//| in_waiting: int
+//| """The number of words available to readinto"""
+//|
+
+STATIC mp_obj_t rp2pio_statemachine_obj_get_in_waiting(mp_obj_t self_in) {
+ rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_rp2pio_statemachine_get_in_waiting(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_in_waiting_obj, rp2pio_statemachine_obj_get_in_waiting);
+
+const mp_obj_property_t rp2pio_statemachine_in_waiting_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&rp2pio_statemachine_get_in_waiting_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
STATIC const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rp2pio_statemachine_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
@@ -563,7 +588,8 @@ STATIC const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&rp2pio_statemachine_write_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&rp2pio_statemachine_frequency_obj) },
- { MP_ROM_QSTR(MP_QSTR_rxstall), MP_ROM_PTR(&rp2pio_statemachine_rxstall_obj) }
+ { MP_ROM_QSTR(MP_QSTR_rxstall), MP_ROM_PTR(&rp2pio_statemachine_rxstall_obj) },
+ { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&rp2pio_statemachine_in_waiting_obj) },
};
STATIC MP_DEFINE_CONST_DICT(rp2pio_statemachine_locals_dict, rp2pio_statemachine_locals_dict_table);
diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.h b/ports/raspberrypi/bindings/rp2pio/StateMachine.h
index 36e44f191..3a0d4290d 100644
--- a/ports/raspberrypi/bindings/rp2pio/StateMachine.h
+++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.h
@@ -41,7 +41,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
size_t frequency,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count, uint32_t initial_out_pin_state, uint32_t initial_out_pin_direction,
- const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
+ const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count, uint32_t pull_pin_up, uint32_t pull_pin_down,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count, uint32_t initial_set_pin_state, uint32_t initial_set_pin_direction,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count, uint32_t initial_sideset_pin_state, uint32_t initial_sideset_pin_direction,
bool exclusive_pin_use,
@@ -69,5 +69,8 @@ void common_hal_rp2pio_statemachine_set_frequency(rp2pio_statemachine_obj_t* sel
bool common_hal_rp2pio_statemachine_get_rxstall(rp2pio_statemachine_obj_t* self);
void common_hal_rp2pio_statemachine_clear_rxfifo(rp2pio_statemachine_obj_t *self);
+size_t common_hal_rp2pio_statemachine_get_in_waiting(rp2pio_statemachine_obj_t *self);
+
+void common_hal_rp2pio_statemachine_set_interrupt_handler(rp2pio_statemachine_obj_t *self, void(*handler)(void*), void *arg, int mask);
#endif // MICROPY_INCLUDED_RASPBERRYPI_BINDINGS_RP2PIO_STATEMACHINE_H
diff --git a/ports/raspberrypi/bindings/rp2pio/__init__.c b/ports/raspberrypi/bindings/rp2pio/__init__.c
index dd5808cd5..7eab423e9 100644
--- a/ports/raspberrypi/bindings/rp2pio/__init__.c
+++ b/ports/raspberrypi/bindings/rp2pio/__init__.c
@@ -28,13 +28,28 @@
#include "py/runtime.h"
#include "bindings/rp2pio/StateMachine.h"
+#include "bindings/rp2pio/__init__.h"
//| """Hardware interface to RP2 series' programmable IO (PIO) peripheral."""
//|
+//| def pins_are_sequential(pins: List[microcontroller.Pin]) -> bool:
+//| """Return True if the pins have sequential GPIO numbers, False otherwise"""
+//| ...
+//|
+STATIC mp_obj_t rp2pio_pins_are_sequential(const mp_obj_t pins) {
+ size_t len;
+ mp_obj_t *items;
+ mp_obj_get_array(pins, &len, &items);
+ return mp_obj_new_bool(common_hal_rp2pio_pins_are_sequential(len, items));
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_pins_are_sequential_obj, rp2pio_pins_are_sequential);
+
STATIC const mp_rom_map_elem_t rp2pio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rp2pio) },
{ MP_ROM_QSTR(MP_QSTR_StateMachine), MP_ROM_PTR(&rp2pio_statemachine_type) },
+ { MP_ROM_QSTR(MP_QSTR_pins_are_sequential), MP_ROM_PTR(&rp2pio_pins_are_sequential_obj) },
};
STATIC MP_DEFINE_CONST_DICT(rp2pio_module_globals, rp2pio_module_globals_table);
diff --git a/ports/raspberrypi/bindings/rp2pio/__init__.h b/ports/raspberrypi/bindings/rp2pio/__init__.h
new file mode 100644
index 000000000..89dc7ff98
--- /dev/null
+++ b/ports/raspberrypi/bindings/rp2pio/__init__.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+bool common_hal_rp2pio_pins_are_sequential(size_t len, mp_obj_t *items);
diff --git a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c
index 83a443834..fa5852fce 100644
--- a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c
+++ b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c
@@ -122,6 +122,7 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t* self,
NULL, 0,
data, 1, 0, 0xffffffff, // out pin
NULL, 0, // in pins
+ 0, 0, // in pulls
NULL, 0, 0, 0x1f, // set pins
bit_clock, 2, 0, 0x1f, // sideset pins
true, // exclusive pin use
diff --git a/ports/raspberrypi/common-hal/audiobusio/PDMIn.c b/ports/raspberrypi/common-hal/audiobusio/PDMIn.c
index ffe09326f..883660271 100644
--- a/ports/raspberrypi/common-hal/audiobusio/PDMIn.c
+++ b/ports/raspberrypi/common-hal/audiobusio/PDMIn.c
@@ -68,6 +68,7 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
NULL, 0,
NULL, 1, 0, 0xffffffff, // out pin
data_pin, 1, // in pins
+ 0, 0, // in pulls
NULL, 0, 0, 0x1f, // set pins
clock_pin, 1, 0, 0x1f, // sideset pins
true, // exclusive pin use
@@ -92,6 +93,7 @@ void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) {
if (common_hal_audiobusio_pdmin_deinited(self)) {
return;
}
+ return common_hal_rp2pio_statemachine_deinit(&self->state_machine);
}
uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t* self) {
diff --git a/ports/raspberrypi/common-hal/neopixel_write/__init__.c b/ports/raspberrypi/common-hal/neopixel_write/__init__.c
index 1f0b71ca0..b57cb2bde 100644
--- a/ports/raspberrypi/common-hal/neopixel_write/__init__.c
+++ b/ports/raspberrypi/common-hal/neopixel_write/__init__.c
@@ -67,6 +67,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
NULL, 0, // init program
NULL, 1, // out
NULL, 1, // in
+ 0, 0, // in pulls
NULL, 1, // set
digitalinout->pin, 1, // sideset
0, pins_we_use, // initial pin state
diff --git a/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
new file mode 100644
index 000000000..b2225991d
--- /dev/null
+++ b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c
@@ -0,0 +1,170 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+
+#include <hardware/regs/pio.h>
+#include "common-hal/rotaryio/IncrementalEncoder.h"
+#include "bindings/rp2pio/__init__.h"
+#include "bindings/rp2pio/StateMachine.h"
+
+STATIC const uint16_t encoder[] = {
+ // again:
+ // in pins, 2
+ 0x4002,
+ // mov x, isr
+ 0xa026,
+ // jmp x!=y, push_data
+ 0x00a5,
+ // mov isr, null
+ 0xa0c3,
+ // jmp again
+ 0x0000,
+ // push_data:
+ // push
+ 0x8020,
+ // mov y, x
+ 0xa041,
+};
+
+STATIC const uint16_t encoder_init[] = {
+ // set y, 31
+ 0xe05f,
+};
+
+STATIC void incrementalencoder_interrupt_handler(void *self_in);
+
+void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self,
+ const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b) {
+ mp_obj_t pins[] = {MP_OBJ_FROM_PTR(pin_a), MP_OBJ_FROM_PTR(pin_b)};
+ if (!common_hal_rp2pio_pins_are_sequential(2, pins)) {
+ mp_raise_RuntimeError(translate("Pins must be sequential"));
+ }
+
+ self->position = 0;
+ self->quarter_count = 0;
+
+ common_hal_rp2pio_statemachine_construct(&self->state_machine,
+ encoder, MP_ARRAY_SIZE(encoder),
+ 1000000,
+ encoder_init, MP_ARRAY_SIZE(encoder_init), // init
+ NULL, 1, 0, 0xffffffff, // out pin
+ pin_a, 2, // in pins
+ 3, 0, // in pulls
+ NULL, 0, 0, 0x1f, // set pins
+ NULL, 0, 0, 0x1f, // sideset pins
+ true, // exclusive pin use
+ false, 32, false, // out settings
+ false, // Wait for txstall
+ false, 32, false); // in settings
+
+ common_hal_rp2pio_statemachine_run(&self->state_machine, encoder_init, MP_ARRAY_SIZE(encoder_init));
+
+ // We're guaranteed by the init code that some output will be available promptly
+ uint8_t state;
+ common_hal_rp2pio_statemachine_readinto(&self->state_machine, &state, 1, 1);
+ // Top two bits of self->last_state don't matter, because they'll be gone as soon as
+ // interrupt handler is called.
+ self->last_state = state & 3;
+
+ common_hal_rp2pio_statemachine_set_interrupt_handler(&self->state_machine, incrementalencoder_interrupt_handler, self, PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS);
+}
+
+bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t* self) {
+ return common_hal_rp2pio_statemachine_deinited(&self->state_machine);
+}
+
+void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t* self) {
+ if (common_hal_rotaryio_incrementalencoder_deinited(self)) {
+ return;
+ }
+ common_hal_rp2pio_statemachine_deinit(&self->state_machine);
+}
+
+mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self) {
+ return self->position;
+}
+
+void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self,
+ mp_int_t new_position) {
+ self->position = new_position;
+}
+
+STATIC void incrementalencoder_interrupt_handler(void *self_in) {
+ rotaryio_incrementalencoder_obj_t* self = self_in;
+ // This table also works for detent both at 11 and 00
+ // For 11 at detent:
+ // Turning cw: 11->01->00->10->11
+ // Turning ccw: 11->10->00->01->11
+ // For 00 at detent:
+ // Turning cw: 00->10->11->10->00
+ // Turning ccw: 00->01->11->10->00
+
+ // index table by state <oldA><oldB><newA><newB>
+ #define BAD 7
+ static const int8_t transitions[16] = {
+ 0, // 00 -> 00 no movement
+ -1, // 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent)
+ +1, // 00 -> 10 3/4 cw or 1/4 cw
+ BAD, // 00 -> 11 non-Gray-code transition
+ +1, // 01 -> 00 2/4 or 4/4 cw
+ 0, // 01 -> 01 no movement
+ BAD, // 01 -> 10 non-Gray-code transition
+ -1, // 01 -> 11 4/4 or 2/4 ccw
+ -1, // 10 -> 00 2/4 or 4/4 ccw
+ BAD, // 10 -> 01 non-Gray-code transition
+ 0, // 10 -> 10 no movement
+ +1, // 10 -> 11 4/4 or 2/4 cw
+ BAD, // 11 -> 00 non-Gray-code transition
+ +1, // 11 -> 01 1/4 or 3/4 cw
+ -1, // 11 -> 10 1/4 or 3/4 ccw
+ 0, // 11 -> 11 no movement
+ };
+
+ while (common_hal_rp2pio_statemachine_get_in_waiting(&self->state_machine)) {
+ // Bypass all the logic of StateMachine.c:_transfer, we need something
+ // very simple and fast for an interrupt!
+ uint8_t new = self->state_machine.pio->rxf[self->state_machine.state_machine];
+
+ // Shift the old AB bits to the "old" position, and set the new AB bits.
+ self->last_state = (self->last_state & 0x3) << 2 | (new & 0x3);
+
+ int8_t quarter_incr = transitions[self->last_state];
+ if (quarter_incr == BAD) {
+ // Missed a transition. We don't know which way we're going, so do nothing.
+ return;
+ }
+
+ self->quarter_count += quarter_incr;
+ if (self->quarter_count >= 4) {
+ self->position += 1;
+ self->quarter_count = 0;
+ } else if (self->quarter_count <= -4) {
+ self->position -= 1;
+ self->quarter_count = 0;
+ }
+ }
+}
diff --git a/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.h b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.h
new file mode 100644
index 000000000..ff5c874c8
--- /dev/null
+++ b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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.
+ */
+
+#pragma once
+
+#include "common-hal/rp2pio/StateMachine.h"
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ rp2pio_statemachine_obj_t state_machine;
+ uint8_t last_state:4; // <old A><old B><new A><new B>
+ int8_t quarter_count:4; // count intermediate transitions between detents
+ mp_int_t position;
+} rotaryio_incrementalencoder_obj_t;
diff --git a/ports/raspberrypi/common-hal/rotaryio/__init__.c b/ports/raspberrypi/common-hal/rotaryio/__init__.c
new file mode 100644
index 000000000..0aae79c26
--- /dev/null
+++ b/ports/raspberrypi/common-hal/rotaryio/__init__.c
@@ -0,0 +1 @@
+// No rotaryio module functions.
diff --git a/ports/raspberrypi/common-hal/rotaryio/__init__.h b/ports/raspberrypi/common-hal/rotaryio/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/raspberrypi/common-hal/rotaryio/__init__.h
diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c
index e81d721c6..672cd4d3c 100644
--- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c
@@ -27,6 +27,7 @@
#include "bindings/rp2pio/StateMachine.h"
#include "common-hal/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
@@ -52,6 +53,22 @@ STATIC uint32_t _current_pins[NUM_PIOS];
STATIC uint32_t _current_sm_pins[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC PIO pio_instances[2] = {pio0, pio1};
+typedef void (*interrupt_handler_type)(void*);
+STATIC interrupt_handler_type _interrupt_handler[NUM_PIOS][NUM_PIO_STATE_MACHINES];
+STATIC void *_interrupt_arg[NUM_PIOS][NUM_PIO_STATE_MACHINES];
+
+STATIC void rp2pio_statemachine_interrupt_handler(void);
+
+static void rp2pio_statemachine_set_pull(uint32_t pull_pin_up, uint32_t pull_pin_down, uint32_t pins_we_use) {
+ for (int i=0; i<TOTAL_GPIO_COUNT; i++) {
+ bool used = pins_we_use & (1 << i);
+ if(used) {
+ bool pull_up = pull_pin_up & (1 << i);
+ bool pull_down = pull_pin_down & (1 << i);
+ gpio_set_pulls(i, pull_up, pull_down);
+ }
+ }
+}
void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) {
uint8_t pio_index = pio_get_index(pio);
@@ -89,6 +106,7 @@ void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) {
}
}
_current_sm_pins[pio_index][sm] = 0;
+ pio->inte0 &= ~((PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS | PIO_IRQ0_INTF_SM0_TXNFULL_BITS | PIO_IRQ0_INTF_SM0_BITS) << sm);
pio_sm_unclaim(pio, sm);
}
@@ -136,6 +154,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
+ uint32_t pull_pin_up, uint32_t pull_pin_down,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count,
uint32_t initial_pin_state, uint32_t initial_pin_direction,
@@ -211,8 +230,11 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
pio_sm_set_pins_with_mask(self->pio, state_machine, initial_pin_state, pins_we_use);
pio_sm_set_pindirs_with_mask(self->pio, state_machine, initial_pin_direction, pins_we_use);
+ rp2pio_statemachine_set_pull(pull_pin_up, pull_pin_down, pins_we_use);
self->initial_pin_state = initial_pin_state;
self->initial_pin_direction = initial_pin_direction;
+ self->pull_pin_up = pull_pin_up;
+ self->pull_pin_down = pull_pin_down;
for (size_t pin_number = 0; pin_number < TOTAL_GPIO_COUNT; pin_number++) {
if ((pins_we_use & (1 << pin_number)) == 0) {
@@ -302,6 +324,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count, uint32_t initial_out_pin_state, uint32_t initial_out_pin_direction,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
+ uint32_t pull_pin_up, uint32_t pull_pin_down,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count, uint32_t initial_set_pin_state, uint32_t initial_set_pin_direction,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count, uint32_t initial_sideset_pin_state, uint32_t initial_sideset_pin_direction,
bool exclusive_pin_use,
@@ -444,12 +467,19 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
initial_pin_state = (initial_pin_state & ~sideset_mask) | mask_and_rotate(first_sideset_pin, sideset_pin_count, initial_sideset_pin_state);
initial_pin_direction = (initial_pin_direction & ~sideset_mask) | mask_and_rotate(first_sideset_pin, sideset_pin_count, initial_sideset_pin_direction);
+ // Deal with pull up/downs
+ uint32_t pull_up = mask_and_rotate(first_in_pin, in_pin_count, pull_pin_up);
+ uint32_t pull_down = mask_and_rotate(first_in_pin, in_pin_count, pull_pin_down);
+ if (initial_pin_direction & (pull_up | pull_down)) {
+ mp_raise_ValueError(translate("pull masks conflict with direction masks"));
+ }
bool ok = rp2pio_statemachine_construct(self,
program, program_len,
frequency,
init, init_len,
first_out_pin, out_pin_count,
first_in_pin, in_pin_count,
+ pull_up, pull_down,
first_set_pin, set_pin_count,
first_sideset_pin, sideset_pin_count,
initial_pin_state, initial_pin_direction,
@@ -470,6 +500,7 @@ void common_hal_rp2pio_statemachine_restart(rp2pio_statemachine_obj_t *self) {
uint32_t pins_we_use = _current_sm_pins[pio_index][self->state_machine];
pio_sm_set_pins_with_mask(self->pio, self->state_machine, self->initial_pin_state, pins_we_use);
pio_sm_set_pindirs_with_mask(self->pio, self->state_machine, self->initial_pin_direction, pins_we_use);
+ rp2pio_statemachine_set_pull(self->pull_pin_up, self->pull_pin_down, pins_we_use);
common_hal_rp2pio_statemachine_run(self, self->init, self->init_len);
pio_sm_set_enabled(self->pio, self->state_machine, true);
}
@@ -511,6 +542,10 @@ void common_hal_rp2pio_statemachine_set_frequency(rp2pio_statemachine_obj_t* sel
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins) {
uint8_t sm = self->state_machine;
uint8_t pio_index = pio_get_index(self->pio);
+ common_hal_mcu_disable_interrupts();
+ _interrupt_arg[pio_index][sm] = NULL;
+ _interrupt_handler[pio_index][sm] = NULL;
+ common_hal_mcu_enable_interrupts();
_never_reset[pio_index][sm] = false;
_reset_statemachine(self->pio, sm, leave_pins);
self->state_machine = NUM_PIO_STATE_MACHINES;
@@ -728,3 +763,39 @@ void common_hal_rp2pio_statemachine_clear_rxfifo(rp2pio_statemachine_obj_t *self
}
self->pio->fdebug = stall_mask;
}
+
+size_t common_hal_rp2pio_statemachine_get_in_waiting(rp2pio_statemachine_obj_t *self) {
+ uint8_t level = pio_sm_get_rx_fifo_level(self->pio, self->state_machine);
+ return level;
+}
+
+void common_hal_rp2pio_statemachine_set_interrupt_handler(rp2pio_statemachine_obj_t *self, void(*handler)(void*), void *arg, int mask) {
+ uint8_t pio_index = pio_get_index(self->pio);
+ uint8_t sm = self->state_machine;
+
+ common_hal_mcu_disable_interrupts();
+ uint32_t inte = self->pio->inte0;
+ inte &= ~((PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS | PIO_IRQ0_INTF_SM0_TXNFULL_BITS | PIO_IRQ0_INTF_SM0_BITS) << sm);
+ inte |= (mask << sm);
+ self->pio->inte0 = inte;
+ _interrupt_arg[pio_index][sm] = arg;
+ _interrupt_handler[pio_index][sm] = handler;
+ irq_set_exclusive_handler(PIO0_IRQ_0 + 2 * pio_index, rp2pio_statemachine_interrupt_handler);
+ irq_set_enabled(PIO0_IRQ_0 + 2 * pio_index, true);
+ common_hal_mcu_enable_interrupts();
+}
+
+STATIC void rp2pio_statemachine_interrupt_handler(void) {
+ for (size_t pio_index = 0; pio_index < NUM_PIOS; pio_index++) {
+ PIO pio = pio_instances[pio_index];
+ for (size_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) {
+ if (!_interrupt_handler[pio_index][sm]) {
+ continue;
+ }
+ uint32_t intf = (PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS | PIO_IRQ0_INTF_SM0_TXNFULL_BITS | PIO_IRQ0_INTF_SM0_BITS) << sm;
+ if (pio->ints0 & intf) {
+ _interrupt_handler[pio_index][sm](_interrupt_arg[pio_index][sm]);
+ }
+ }
+ }
+}
diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.h b/ports/raspberrypi/common-hal/rp2pio/StateMachine.h
index f084e0986..f40db61ea 100644
--- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.h
+++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.h
@@ -29,6 +29,7 @@
#include "py/obj.h"
+#include "common-hal/microcontroller/Pin.h"
#include "src/rp2_common/hardware_pio/include/hardware/pio.h"
typedef struct {
@@ -40,6 +41,8 @@ typedef struct {
size_t init_len;
uint32_t initial_pin_state;
uint32_t initial_pin_direction;
+ uint32_t pull_pin_up;
+ uint32_t pull_pin_down;
bool in;
bool out;
bool wait_for_txstall;
@@ -59,6 +62,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const uint16_t* init, size_t init_len,
const mcu_pin_obj_t * first_out_pin, uint8_t out_pin_count,
const mcu_pin_obj_t * first_in_pin, uint8_t in_pin_count,
+ uint32_t pull_pin_up, uint32_t pull_pin_down,
const mcu_pin_obj_t * first_set_pin, uint8_t set_pin_count,
const mcu_pin_obj_t * first_sideset_pin, uint8_t sideset_pin_count,
uint32_t initial_pin_state, uint32_t initial_pin_direction,
diff --git a/ports/raspberrypi/common-hal/rp2pio/__init__.c b/ports/raspberrypi/common-hal/rp2pio/__init__.c
index 21699dfa3..5ad52c751 100644
--- a/ports/raspberrypi/common-hal/rp2pio/__init__.c
+++ b/ports/raspberrypi/common-hal/rp2pio/__init__.c
@@ -1 +1,43 @@
-// Nothing yet.
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "bindings/rp2pio/__init__.h"
+
+bool common_hal_rp2pio_pins_are_sequential(size_t len, mp_obj_t *items) {
+ if(len == 0) {
+ return true;
+ }
+ mcu_pin_obj_t *last_pin = validate_obj_is_pin(items[0]);
+ for(int i=1; i<len; i++) {
+ mcu_pin_obj_t *pin = validate_obj_is_pin(items[i]);
+ if (pin->number != last_pin->number + 1) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/ports/raspberrypi/common-hal/rtc/RTC.c b/ports/raspberrypi/common-hal/rtc/RTC.c
index 89c23fc19..e6c5d8871 100644
--- a/ports/raspberrypi/common-hal/rtc/RTC.c
+++ b/ports/raspberrypi/common-hal/rtc/RTC.c
@@ -29,9 +29,23 @@
#include "py/runtime.h"
#include "src/rp2_common/hardware_rtc/include/hardware/rtc.h"
+#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h"
void common_hal_rtc_init(void) {
+ datetime_t t = {
+ .year = 2020,
+ .month = 1,
+ .day = 1,
+ .dotw = 3, // 0 is Sunday, so 3 is Wednesday
+ .hour = 0,
+ .min = 0,
+ .sec = 0
+ };
+
+ // Start the RTC
rtc_init();
+ rtc_set_datetime(&t);
+
}
void common_hal_rtc_get_time(timeutils_struct_time_t *tm) {
diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk
index 4c149cb2b..03de6ce5e 100644
--- a/ports/raspberrypi/mpconfigport.mk
+++ b/ports/raspberrypi/mpconfigport.mk
@@ -28,13 +28,15 @@ CIRCUITPY_FULL_BUILD = 1
CIRCUITPY_BITOPS = 1
CIRCUITPY_PWMIO = 1
CIRCUITPY_RGBMATRIX = 1
+CIRCUITPY_ROTARYIO = 1
# Things that need to be implemented.
-CIRCUITPY_FREQUENCYIO = 0 # Use PWM interally
+# Use PWM interally
+CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_NVM = 1
-CIRCUITPY_PULSEIO = 0 # Use PIO interally
-CIRCUITPY_ROTARYIO = 0 # Use PIO interally
+# Use PIO interally
+CIRCUITPY_PULSEIO = 0
CIRCUITPY_WATCHDOG = 1
# Audio via PWM
diff --git a/ports/raspberrypi/sdk b/ports/raspberrypi/sdk
-Subproject 55346c953012ef5b32f392fea3b42814db8df2a
+Subproject fc10a97c386f65c1a44c68684fe52a56aaf50df
diff --git a/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk b/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk
index 4d0bd4598..39bf7dc54 100644
--- a/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk
+++ b/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk
@@ -4,7 +4,6 @@ USB_PRODUCT = "Feather STM32F405 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
MCU_SERIES = F4
diff --git a/ports/stm/boards/meowbit_v121/mpconfigboard.mk b/ports/stm/boards/meowbit_v121/mpconfigboard.mk
index 86b0cb5ab..45a04a3a7 100644
--- a/ports/stm/boards/meowbit_v121/mpconfigboard.mk
+++ b/ports/stm/boards/meowbit_v121/mpconfigboard.mk
@@ -4,7 +4,6 @@ USB_PRODUCT = "Meowbit"
USB_MANUFACTURER = "Kittenbot"
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = W25Q16JV_IQ
# INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk b/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk
index 237dba921..cff8eea70 100644
--- a/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk
+++ b/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk
@@ -4,7 +4,6 @@ USB_PRODUCT = "PYB LR Nano V2"
USB_MANUFACTURER = "MicroPython Chinese Community"
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = W25Q64JV_IQ
MCU_SERIES = F4
diff --git a/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.mk b/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.mk
index 9b45a0fac..1d533e30f 100644
--- a/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.mk
+++ b/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.mk
@@ -4,7 +4,6 @@ USB_PRODUCT = "stm32f411ce blackpill"
USB_MANUFACTURER = "Unknown"
# SPI_FLASH_FILESYSTEM = 1
-# EXTERNAL_FLASH_DEVICE_COUNT = 1
# EXTERNAL_FLASH_DEVICES = xxxxxx #See supervisor/shared/external_flash/devices.h for options
# LONGINT_IMPL = MPZ
diff --git a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk
index 166b56b6e..f6fd42327 100644
--- a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk
+++ b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk
@@ -4,7 +4,6 @@ USB_PRODUCT = "stm32f411ce blackpill with flash"
USB_MANUFACTURER = "Unknown"
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 3
#See supervisor/shared/external_flash/devices.h for options
EXTERNAL_FLASH_DEVICES = GD25Q16C,W25Q64FV,W25Q64JV_IQ
LONGINT_IMPL = MPZ
diff --git a/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk b/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk
index 28874f9c6..b50cdb966 100644
--- a/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk
+++ b/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk
@@ -6,7 +6,6 @@ USB_MANUFACTURER = "STMicroelectronics"
INTERNAL_FLASH_FILESYSTEM = 1
# QSPI_FLASH_FILESYSTEM = 1
-# EXTERNAL_FLASH_DEVICE_COUNT = 1
# EXTERNAL_FLASH_DEVICES = N25Q128A
# LONGINT_IMPL = MPZ
diff --git a/ports/stm/boards/thunderpack_v12/mpconfigboard.mk b/ports/stm/boards/thunderpack_v12/mpconfigboard.mk
index 4436f04b7..1c09fe64c 100644
--- a/ports/stm/boards/thunderpack_v12/mpconfigboard.mk
+++ b/ports/stm/boards/thunderpack_v12/mpconfigboard.mk
@@ -9,7 +9,6 @@ CIRCUITPY_USB_HID = 0
LONGINT_IMPL = NONE
SPI_FLASH_FILESYSTEM = 1
-EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
CIRCUITPY_NVM = 1
diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c
index e51db2644..820db5ea9 100644
--- a/shared-bindings/countio/Counter.c
+++ b/shared-bindings/countio/Counter.c
@@ -22,9 +22,8 @@
//|
//| For example::
//|
+//| import board
//| import countio
-//| import time
-//| from board import *
//|
//| pin_counter = countio.Counter(board.D1)
//| #reset the count after 100 counts
diff --git a/shared-bindings/usb_cdc/Serial.c b/shared-bindings/usb_cdc/Serial.c
index c813dce5b..82355f897 100644
--- a/shared-bindings/usb_cdc/Serial.c
+++ b/shared-bindings/usb_cdc/Serial.c
@@ -40,12 +40,9 @@
//|
//| def __init__(self) -> None:
//| """You cannot create an instance of `usb_cdc.Serial`.
-//|
-//| Serial objects are pre-constructed for each CDC device in the USB
-//| descriptor and added to the ``usb_cdc.ports`` tuple."""
+//| The available instances are in the ``usb_cdc.serials`` tuple."""
//| ...
//|
-
//| def read(self, size: int = 1) -> bytes:
//| """Read at most ``size`` bytes. If ``size`` exceeds the internal buffer size
//| only the bytes in the buffer will be read. If `timeout` is > 0 or ``None``,
@@ -64,6 +61,29 @@
//| :rtype: bytes"""
//| ...
//|
+//| def readline(self, size: int = -1) -> Optional[bytes]:
+//| r"""Read a line ending in a newline character ("\\n"), including the newline.
+//| Return everything readable if no newline is found and ``timeout`` is 0.
+//| Return ``None`` in case of error.
+//|
+//| This is a binary stream: the newline character "\\n" cannot be changed.
+//| If the host computer transmits "\\r" it will also be included as part of the line.
+//|
+//| :param int size: maximum number of characters to read. ``-1`` means as many as possible.
+//| :return: the line read
+//| :rtype: bytes or None"""
+//| ...
+//|
+//| def readlines(self) -> List[Optional[bytes]]:
+//| """Read multiple lines as a list, using `readline()`.
+//|
+//| .. warning:: If ``timeout`` is ``None``,
+//| `readlines()` will never return, because there is no way to indicate end of stream.
+//|
+//| :return: a list of the line read
+//| :rtype: list"""
+//| ...
+//|
//| def write(self, buf: ReadableBuffer) -> int:
//| """Write as many bytes as possible from the buffer of bytes.
//|
@@ -124,7 +144,12 @@ STATIC mp_uint_t usb_cdc_serial_ioctl_stream(mp_obj_t self_in, mp_uint_t request
}
//| connected: bool
-//| """True if this Serial is connected to a host. (read-only)"""
+//| """True if this Serial is connected to a host. (read-only)
+//|
+//| .. note:: The host is considered to be connected if it is asserting DTR (Data Terminal Ready).
+//| Most terminal programs and ``pyserial`` assert DTR when opening a serial connection.
+//| However, the C# ``SerialPort`` API does not. You must set ``SerialPort.DtrEnable``.
+//| """
//|
STATIC mp_obj_t usb_cdc_serial_get_connected(mp_obj_t self_in) {
usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/supervisor/flash.h b/supervisor/flash.h
index cd69cbfa9..289c76c2d 100644
--- a/supervisor/flash.h
+++ b/supervisor/flash.h
@@ -31,7 +31,7 @@
#include "py/mpconfig.h"
-#ifdef EXTERNAL_FLASH_DEVICE_COUNT
+#ifdef EXTERNAL_FLASH_DEVICES
#include "supervisor/shared/external_flash/external_flash.h"
#else
#include "supervisor/shared/internal_flash.h"
diff --git a/supervisor/flash_root_pointers.h b/supervisor/flash_root_pointers.h
index 634ae58d3..a426b9c4e 100644
--- a/supervisor/flash_root_pointers.h
+++ b/supervisor/flash_root_pointers.h
@@ -26,7 +26,7 @@
#ifndef MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H
#define MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H
-#ifdef EXTERNAL_FLASH_DEVICE_COUNT
+#ifdef EXTERNAL_FLASH_DEVICES
#include "supervisor/shared/external_flash/external_flash_root_pointers.h"
#else
#include "supervisor/internal_flash_root_pointers.h"
diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c
index e2d767235..23727e7e7 100644
--- a/supervisor/shared/external_flash/external_flash.c
+++ b/supervisor/shared/external_flash/external_flash.c
@@ -45,7 +45,8 @@
// The currently cached sector in the cache, ram or flash based.
static uint32_t current_sector;
-const external_flash_device possible_devices[EXTERNAL_FLASH_DEVICE_COUNT] = {EXTERNAL_FLASH_DEVICES};
+STATIC const external_flash_device possible_devices[] = {EXTERNAL_FLASH_DEVICES};
+#define EXTERNAL_FLASH_DEVICE_COUNT MP_ARRAY_SIZE(possible_devices)
static const external_flash_device* flash_device = NULL;
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index 374b7a72b..083e7fb35 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -34,7 +34,6 @@ endif
# But that might not be true in the future.)
ifdef EXTERNAL_FLASH_DEVICES
CFLAGS += -DEXTERNAL_FLASH_DEVICES=$(EXTERNAL_FLASH_DEVICES) \
- -DEXTERNAL_FLASH_DEVICE_COUNT=$(EXTERNAL_FLASH_DEVICE_COUNT)
SRC_SUPERVISOR += supervisor/shared/external_flash/external_flash.c
ifeq ($(SPI_FLASH_FILESYSTEM),1)