summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorDavePutz <dwputz@gmail.com>2021-02-24 10:09:52 -0600
committerGitHub <noreply@github.com>2021-02-24 10:09:52 -0600
commiteeb89a97b4a8fa25fb38e4a5d5db78c0c3df9b15 (patch)
treee18ea9f61c7930d1f21d72fb69125a0270558038 /ports
parentcec921f3747beccff10c2d2dfbc237c305083f62 (diff)
parente41137c745af65b6342c7e2d3b09d8930eefedb0 (diff)
Merge pull request #41 from adafruit/main
Update from adafruit main
Diffstat (limited to 'ports')
-rw-r--r--ports/atmel-samd/Makefile2
-rw-r--r--ports/atmel-samd/boards/8086_commander/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk17
-rw-r--r--ports/atmel-samd/boards/cp_sapling_m0/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/datum_distance/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/datum_imu/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/datum_light/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/datum_weather/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/dynalora_usb/board.c37
-rw-r--r--ports/atmel-samd/boards/dynalora_usb/mpconfigboard.h36
-rw-r--r--ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk39
-rw-r--r--ports/atmel-samd/boards/dynalora_usb/pins.c41
-rw-r--r--ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk16
-rw-r--r--ports/atmel-samd/boards/ndgarage_ndbit6/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/neopixel_trinkey_m0/mpconfigboard.mk12
-rw-r--r--ports/atmel-samd/boards/pewpew10/mpconfigboard.mk8
-rw-r--r--ports/atmel-samd/boards/picoplanet/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk5
-rw-r--r--ports/atmel-samd/boards/pyruler/mpconfigboard.mk8
-rw-r--r--ports/atmel-samd/boards/qtpy_m0/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/serpente/mpconfigboard.mk14
-rw-r--r--ports/atmel-samd/boards/shirtty/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/sparkfun_qwiic_micro_no_flash/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/uchip/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/common-hal/_pew/PewPew.c6
-rw-r--r--ports/atmel-samd/common-hal/_pew/PewPew.h1
-rwxr-xr-xports/atmel-samd/common-hal/supervisor/Runtime.c4
-rw-r--r--ports/atmel-samd/mpconfigport.mk24
-rwxr-xr-xports/cxd56/common-hal/supervisor/Runtime.c4
-rw-r--r--ports/cxd56/mpconfigport.mk3
-rw-r--r--ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c106
-rw-r--r--ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.mk1
-rw-r--r--ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c3
-rw-r--r--ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk1
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk1
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/mpconfigboard.mk1
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_tinys2/board.c61
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h46
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.mk23
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_tinys2/pins.c79
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_tinys2/sdkconfig39
-rw-r--r--ports/esp32s2/common-hal/alarm/__init__.c8
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Pin.c2
-rw-r--r--ports/esp32s2/common-hal/socketpool/Socket.c17
-rw-r--r--ports/esp32s2/common-hal/ssl/SSLSocket.c18
-rw-r--r--ports/esp32s2/common-hal/supervisor/Runtime.c6
-rw-r--r--ports/esp32s2/mpconfigport.mk13
-rw-r--r--ports/litex/common-hal/supervisor/Runtime.c6
-rw-r--r--ports/litex/mpconfigport.mk3
-rw-r--r--ports/mimxrt10xx/common-hal/busio/SPI.c23
-rwxr-xr-xports/mimxrt10xx/common-hal/supervisor/Runtime.c4
-rw-r--r--ports/mimxrt10xx/mpconfigport.mk3
-rw-r--r--ports/nrf/bluetooth/ble_uart.c4
-rw-r--r--ports/nrf/boards/TG-Watch/mpconfigboard.h30
-rw-r--r--ports/nrf/boards/pca10100/mpconfigboard.mk1
-rw-r--r--ports/nrf/boards/simmel/mpconfigboard.mk3
-rwxr-xr-xports/nrf/common-hal/supervisor/Runtime.c4
-rw-r--r--ports/nrf/mpconfigport.mk3
-rw-r--r--ports/nrf/supervisor/serial.c10
-rw-r--r--ports/raspberrypi/Makefile2
-rw-r--r--ports/raspberrypi/audio_dma.c383
-rw-r--r--ports/raspberrypi/audio_dma.h91
-rw-r--r--ports/raspberrypi/bindings/rp2pio/StateMachine.c2
-rw-r--r--ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.h3
-rw-r--r--ports/raspberrypi/boards/pimoroni_keybow2040/board.c37
-rw-r--r--ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.h41
-rw-r--r--ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk11
-rw-r--r--ports/raspberrypi/boards/pimoroni_keybow2040/pins.c36
-rw-r--r--ports/raspberrypi/boards/pimoroni_picosystem/board.c37
-rw-r--r--ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.h49
-rw-r--r--ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.mk11
-rw-r--r--ports/raspberrypi/boards/pimoroni_picosystem/pins.c43
-rw-r--r--ports/raspberrypi/boards/pimoroni_tiny2040/board.c37
-rw-r--r--ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.h26
-rw-r--r--ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.mk11
-rw-r--r--ports/raspberrypi/boards/pimoroni_tiny2040/pins.c39
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/board.c44
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h17
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk9
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/pins.c49
-rw-r--r--ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.h3
-rw-r--r--ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c235
-rw-r--r--ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h47
-rw-r--r--ports/raspberrypi/common-hal/audiopwmio/__init__.c0
-rw-r--r--ports/raspberrypi/common-hal/neopixel_write/__init__.c5
-rw-r--r--ports/raspberrypi/common-hal/os/__init__.c65
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.c60
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.h4
-rw-r--r--ports/raspberrypi/common-hal/rp2pio/StateMachine.c26
-rwxr-xr-xports/raspberrypi/common-hal/supervisor/Runtime.c4
-rw-r--r--ports/raspberrypi/mpconfigport.h3
-rw-r--r--ports/raspberrypi/mpconfigport.mk13
-rw-r--r--ports/raspberrypi/supervisor/internal_flash.c5
-rw-r--r--ports/raspberrypi/supervisor/port.c5
-rw-r--r--ports/stm/boards/espruino_pico/mpconfigboard.mk1
-rw-r--r--ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk2
-rw-r--r--ports/stm/boards/thunderpack_v12/mpconfigboard.mk4
-rw-r--r--ports/stm/common-hal/busio/I2C.c92
-rw-r--r--ports/stm/common-hal/busio/I2C.h2
-rwxr-xr-xports/stm/common-hal/supervisor/Runtime.c6
-rw-r--r--ports/stm/mpconfigport.h6
-rw-r--r--ports/stm/mpconfigport.mk7
115 files changed, 2191 insertions, 254 deletions
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 58c1c0d60..48724af0c 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -122,7 +122,7 @@ CFLAGS += -ftree-vrp
$(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY))
#Debugging/Optimization
ifeq ($(DEBUG), 1)
- CFLAGS += -ggdb3 -Og
+ CFLAGS += -ggdb3 -Og -Os
# You may want to disable -flto if it interferes with debugging.
CFLAGS += -flto -flto-partition=none
# You may want to enable these flags to make setting breakpoints easier.
diff --git a/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk b/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
index f976dfe78..295d7b2ae 100644
--- a/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
@@ -15,8 +15,7 @@ CIRCUITPY_FULL_BUILD = 0
CIRCUITPY_USB_MIDI = 0
SUPEROPT_GC = 0
-
-CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_VM = 0
CIRCUITPY_GAMEPAD = 1
CIRCUITPY_BUSDEVICE = 1
diff --git a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
index 36d463697..1fd96b0ae 100644
--- a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
@@ -9,5 +9,6 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
+
SUPEROPT_GC = 0
SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
index 20307fc05..fabe52ce2 100644
--- a/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
@@ -12,4 +12,3 @@ CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
SUPEROPT_VM = 0
-CFLAGS_INLINE_LIMIT = 40
diff --git a/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk
index 07b1b9800..c16c53e6d 100644
--- a/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk
@@ -11,5 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk b/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk
index 6a2c89619..ec037837e 100644
--- a/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/bast_pro_mini_m0/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
index ae0b6837c..6d240686d 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
@@ -22,7 +22,7 @@ CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
SUPEROPT_GC = 0
-CFLAGS_INLINE_LIMIT = 40
+SUPEROPT_VM = 0
# Include these Python libraries in firmware.
diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
index aace5c0cb..2a97636de 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
@@ -25,25 +25,10 @@ CIRCUITPY_RTC = 0
CIRCUITPY_VECTORIO = 0
SUPEROPT_GC = 0
-CFLAGS_INLINE_LIMIT = 55
+SUPEROPT_VM = 0
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), ja)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 15
-endif
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/cp_sapling_m0/mpconfigboard.mk b/ports/atmel-samd/boards/cp_sapling_m0/mpconfigboard.mk
index 861a0a5f7..3799d7ef7 100644
--- a/ports/atmel-samd/boards/cp_sapling_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/cp_sapling_m0/mpconfigboard.mk
@@ -11,14 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/datum_distance/mpconfigboard.mk b/ports/atmel-samd/boards/datum_distance/mpconfigboard.mk
index ae05d32f2..22b55f6fd 100644
--- a/ports/atmel-samd/boards/datum_distance/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datum_distance/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/datum_imu/mpconfigboard.mk b/ports/atmel-samd/boards/datum_imu/mpconfigboard.mk
index 6fd05f403..7e9918291 100644
--- a/ports/atmel-samd/boards/datum_imu/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datum_imu/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/datum_light/mpconfigboard.mk b/ports/atmel-samd/boards/datum_light/mpconfigboard.mk
index d42a7869d..5916f23b3 100644
--- a/ports/atmel-samd/boards/datum_light/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datum_light/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/datum_weather/mpconfigboard.mk b/ports/atmel-samd/boards/datum_weather/mpconfigboard.mk
index d92cbc71b..1065fb50a 100644
--- a/ports/atmel-samd/boards/datum_weather/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datum_weather/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/dynalora_usb/board.c b/ports/atmel-samd/boards/dynalora_usb/board.c
new file mode 100644
index 000000000..84960e73c
--- /dev/null
+++ b/ports/atmel-samd/boards/dynalora_usb/board.c
@@ -0,0 +1,37 @@
+/*
+ * 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/atmel-samd/boards/dynalora_usb/mpconfigboard.h b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.h
new file mode 100644
index 000000000..12359ce8f
--- /dev/null
+++ b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.h
@@ -0,0 +1,36 @@
+#define MICROPY_HW_BOARD_NAME "DynaLoRa_USB"
+#define MICROPY_HW_MCU_NAME "samd21e18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA27)
+#define MICROPY_HW_NEOPIXEL (&pin_PA19)
+
+#define SPI_FLASH_MOSI_PIN &pin_PA04
+#define SPI_FLASH_MISO_PIN &pin_PA05
+#define SPI_FLASH_SCK_PIN &pin_PA07
+#define SPI_FLASH_CS_PIN &pin_PA06
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (0)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA01)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA00)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA17)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA16)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA18)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA00)
+#define DEFAULT_UART_BUS_TX (&pin_PA01)
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA23 1
+#define IGNORE_PIN_PA24 1
+
+// Not connected
+#define IGNORE_PIN_PA08 1
+#define IGNORE_PIN_PA14 1
+#define IGNORE_PIN_PA21 1
+#define IGNORE_PIN_PA22 1
+#define IGNORE_PIN_PA28 1
diff --git a/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk
new file mode 100644
index 000000000..ac14e7395
--- /dev/null
+++ b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk
@@ -0,0 +1,39 @@
+USB_VID = 0x04D8
+USB_PID = 0xEA2A
+USB_PRODUCT = "DynaLoRa_USB"
+USB_MANUFACTURER = "BHDynamics"
+
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = GD25Q32C
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_GAMEPAD = 0
+CIRCUITPY_DISPLAYIO = 0
+CIRCUITPY_FULL_BUILD = 0
+
+SUPEROPT_GC = 0
+
+CFLAGS_BOARD = --param max-inline-insns-auto=15
+ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
+CFLAGS_INLINE_LIMIT = 35
+endif
+ifeq ($(TRANSLATION), ja)
+RELEASE_NEEDS_CLEAN_BUILD = 1
+CFLAGS_INLINE_LIMIT = 35
+endif
+ifeq ($(TRANSLATION), de_DE)
+RELEASE_NEEDS_CLEAN_BUILD = 1
+CFLAGS_INLINE_LIMIT = 35
+SUPEROPT_VM = 0
+endif
+
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_RFM9x
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD
diff --git a/ports/atmel-samd/boards/dynalora_usb/pins.c b/ports/atmel-samd/boards/dynalora_usb/pins.c
new file mode 100644
index 000000000..25f498543
--- /dev/null
+++ b/ports/atmel-samd/boards/dynalora_usb/pins.c
@@ -0,0 +1,41 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA30) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA31) },
+
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA02) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_RADIO_CS), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_RADIO_INT), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_RADIO_RESET), MP_ROM_PTR(&pin_PA10) },
+
+ { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PA03) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA00) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA00) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI1), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_MISO1), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_SCK1), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_PA15) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk b/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk
index e45b5aae3..ffe76d930 100644
--- a/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk
@@ -12,3 +12,4 @@ CIRCUITPY_FULL_BUILD = 0
CIRCUITPY_RTC = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
index 69ebdfc23..183a80ffa 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk b/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk
index c040eb430..52fcaec02 100644
--- a/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk
@@ -11,9 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
index e1c0f4b9a..9d086c8f5 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
@@ -11,14 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
index 2b211abd4..6950378d5 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
@@ -25,22 +25,8 @@ CIRCUITPY_VECTORIO = 0
CFLAGS_INLINE_LIMIT = 55
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), ja)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/ndgarage_ndbit6/mpconfigboard.mk b/ports/atmel-samd/boards/ndgarage_ndbit6/mpconfigboard.mk
index 09804bc4e..3882e780e 100644
--- a/ports/atmel-samd/boards/ndgarage_ndbit6/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ndgarage_ndbit6/mpconfigboard.mk
@@ -12,3 +12,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk
index 193a0cf99..4ae1d8741 100644
--- a/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk
@@ -12,3 +12,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/neopixel_trinkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/neopixel_trinkey_m0/mpconfigboard.mk
index ab8065a9c..8607385d2 100644
--- a/ports/atmel-samd/boards/neopixel_trinkey_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/neopixel_trinkey_m0/mpconfigboard.mk
@@ -9,8 +9,6 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
-SUPEROPT_GC = 0
-
CIRCUITPY_ANALOGIO = 0
CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
@@ -28,16 +26,8 @@ CIRCUITPY_USB_MIDI = 1
CIRCUITPY_TOUCHIO = 1
CIRCUITPY_FULL_BUILD = 0
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
+SUPEROPT_GC = 0
SUPEROPT_VM = 0
-endif
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
diff --git a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
index fadcc2144..8b2ac7ff7 100644
--- a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
@@ -20,12 +20,6 @@ CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/pew-pewpew-standalone-10.x
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/picoplanet/mpconfigboard.mk b/ports/atmel-samd/boards/picoplanet/mpconfigboard.mk
index da97b90cc..e93155374 100644
--- a/ports/atmel-samd/boards/picoplanet/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/picoplanet/mpconfigboard.mk
@@ -11,14 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
index 8b7066ac7..b8ae77921 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
@@ -21,12 +21,11 @@ CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 1
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_FULL_BUILD = 0
-# Make more room.
+
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
# Include these Python libraries in firmware.
# FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_IRRemote
-
-CFLAGS_BOARD = --param max-inline-insns-auto=12
diff --git a/ports/atmel-samd/boards/pyruler/mpconfigboard.mk b/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
index 4484b4ed9..1a73ade94 100644
--- a/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
@@ -11,10 +11,6 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
CIRCUITPY_COUNTIO = 0
CIRCUITPY_RTC = 0
-SUPEROPT_GC = 0
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
+SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.mk b/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.mk
index e100e2da6..c214006ea 100644
--- a/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.mk
@@ -12,5 +12,3 @@ CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
SUPEROPT_VM = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
diff --git a/ports/atmel-samd/boards/serpente/mpconfigboard.mk b/ports/atmel-samd/boards/serpente/mpconfigboard.mk
index 09036875f..1f2c83316 100644
--- a/ports/atmel-samd/boards/serpente/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/serpente/mpconfigboard.mk
@@ -17,18 +17,4 @@ CIRCUITPY_GAMEPAD = 0
CIRCUITPY_BUSDEVICE = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
-ifeq ($(TRANSLATION), zh_Latn_pinyin)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), ja)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-endif
-ifeq ($(TRANSLATION), de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
SUPEROPT_VM = 0
-endif
diff --git a/ports/atmel-samd/boards/shirtty/mpconfigboard.mk b/ports/atmel-samd/boards/shirtty/mpconfigboard.mk
index 0b56e9ae0..70fe44723 100644
--- a/ports/atmel-samd/boards/shirtty/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/shirtty/mpconfigboard.mk
@@ -13,5 +13,4 @@ CIRCUITPY_I2CPERIPHERAL = 1
CIRCUITPY_TOUCHIO = 0
SUPEROPT_GC = 0
-
-CFLAGS_BOARD = --param max-inline-insns-auto=15
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/sparkfun_qwiic_micro_no_flash/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_qwiic_micro_no_flash/mpconfigboard.mk
index 22e2059a9..435ee87fd 100644
--- a/ports/atmel-samd/boards/sparkfun_qwiic_micro_no_flash/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_qwiic_micro_no_flash/mpconfigboard.mk
@@ -10,4 +10,6 @@ INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
+
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
index 3104be0a0..bafcc02a2 100644
--- a/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
@@ -10,10 +10,5 @@ INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
-ifeq ($(TRANSLATION),de_DE)
-RELEASE_NEEDS_CLEAN_BUILD = 1
-CFLAGS_INLINE_LIMIT = 35
-SUPEROPT_VM = 0
-endif
-
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
index 9460d0009..aef38661b 100644
--- a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
@@ -11,3 +11,4 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index 1f88fbead..6595fa164 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -12,4 +12,3 @@ CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
SUPEROPT_VM = 0
-CFLAGS_INLINE_LIMIT = 45
diff --git a/ports/atmel-samd/boards/uchip/mpconfigboard.mk b/ports/atmel-samd/boards/uchip/mpconfigboard.mk
index d08690a15..d6ba805b1 100644
--- a/ports/atmel-samd/boards/uchip/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/uchip/mpconfigboard.mk
@@ -10,7 +10,5 @@ INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
-# Always use aggressive inlining
-CFLAGS_INLINE_LIMIT = 45
-
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
diff --git a/ports/atmel-samd/common-hal/_pew/PewPew.c b/ports/atmel-samd/common-hal/_pew/PewPew.c
index cfdfe75d8..1e7561ac8 100644
--- a/ports/atmel-samd/common-hal/_pew/PewPew.c
+++ b/ports/atmel-samd/common-hal/_pew/PewPew.c
@@ -40,6 +40,7 @@
static uint8_t pewpew_tc_index = 0xff;
+static volatile uint16_t pewpew_ticks = 0;
void pewpew_interrupt_handler(uint8_t index) {
@@ -52,6 +53,7 @@ void pewpew_interrupt_handler(uint8_t index) {
}
pew_tick();
+ ++pewpew_ticks;
// Clear the interrupt bit.
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
@@ -123,3 +125,7 @@ void pew_reset(void) {
}
MP_STATE_VM(pew_singleton) = NULL;
}
+
+uint16_t pew_get_ticks() {
+ return pewpew_ticks;
+}
diff --git a/ports/atmel-samd/common-hal/_pew/PewPew.h b/ports/atmel-samd/common-hal/_pew/PewPew.h
index da1cae0a2..a9c3b6626 100644
--- a/ports/atmel-samd/common-hal/_pew/PewPew.h
+++ b/ports/atmel-samd/common-hal/_pew/PewPew.h
@@ -44,5 +44,6 @@ typedef struct {
void pew_init(void);
void pewpew_interrupt_handler(uint8_t index);
void pew_reset(void);
+uint16_t pew_get_ticks(void);
#endif // MICROPY_INCLUDED_PEW_PEWPEW_H
diff --git a/ports/atmel-samd/common-hal/supervisor/Runtime.c b/ports/atmel-samd/common-hal/supervisor/Runtime.c
index 6be38f216..974f26cec 100755
--- a/ports/atmel-samd/common-hal/supervisor/Runtime.c
+++ b/ports/atmel-samd/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
return (bool) serial_bytes_available();
}
diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk
index fb9cdf2e6..c77bf83f1 100644
--- a/ports/atmel-samd/mpconfigport.mk
+++ b/ports/atmel-samd/mpconfigport.mk
@@ -18,7 +18,16 @@ ifeq ($(LONGINT_IMPL),LONGLONG)
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=longlong
endif
+INTERNAL_LIBM = 1
+
+USB_SERIAL_NUMBER_LENGTH = 32
+
+# Number of USB endpoint pairs.
+USB_NUM_EP = 8
+
+######################################################################
# Put samd21-only choices here.
+
ifeq ($(CHIP_FAMILY),samd21)
# The ?='s allow overriding in mpconfigboard.mk.
@@ -39,8 +48,8 @@ CIRCUITPY_SDCARDIO ?= 0
# Not enough RAM for framebuffers
CIRCUITPY_FRAMEBUFFERIO ?= 0
-# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
-USB_MSC_EP_NUM_OUT = 1
+# Not enough room in 192kB or 256kB builds for secondary CDC.
+CIRCUITPY_USB_CDC ?= 0
CIRCUITPY_ULAB = 0
@@ -55,9 +64,13 @@ CIRCUITPY_TERMINALIO = 0
endif
endif # samd21
+######################################################################
+######################################################################
# Put samd51-only choices here.
+
ifeq ($(CHIP_FAMILY),samd51)
+
# No native touchio on SAMD51.
CIRCUITPY_TOUCHIO_USE_NATIVE = 0
@@ -70,9 +83,4 @@ CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FULL_BUILD)
CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD)
endif # samd51
-
-INTERNAL_LIBM = 1
-
-USB_SERIAL_NUMBER_LENGTH = 32
-
-USB_NUM_EP = 8
+######################################################################
diff --git a/ports/cxd56/common-hal/supervisor/Runtime.c b/ports/cxd56/common-hal/supervisor/Runtime.c
index a0d9e70ab..eeeb1430f 100755
--- a/ports/cxd56/common-hal/supervisor/Runtime.c
+++ b/ports/cxd56/common-hal/supervisor/Runtime.c
@@ -27,10 +27,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
return (bool) serial_bytes_available();
}
diff --git a/ports/cxd56/mpconfigport.mk b/ports/cxd56/mpconfigport.mk
index e1ffc79d0..33a993ad9 100644
--- a/ports/cxd56/mpconfigport.mk
+++ b/ports/cxd56/mpconfigport.mk
@@ -7,6 +7,9 @@ USB_CDC_EP_NUM_DATA_IN = 1
USB_MSC_EP_NUM_OUT = 5
USB_MSC_EP_NUM_IN = 4
+# Number of USB endpoint pairs.
+USB_NUM_EP = 6
+
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
CIRCUITPY_AUDIOBUSIO = 0
diff --git a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c
index aaef97c7d..4aa7b3b24 100644
--- a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c
+++ b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c
@@ -27,6 +27,109 @@
#include "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+
+#define DELAY 0x80
+
+// display init sequence according to LilyGO example app
+uint8_t display_init_sequence[] = {
+ // sw reset
+ 0x01, 0 | DELAY, 150,
+ // sleep out
+ 0x11, 0 | DELAY, 255,
+ // normal display mode on
+ 0x13, 0,
+ // display and color format settings
+ 0x36, 1, 0x08,
+ 0xB6, 2, 0x0A, 0x82,
+ 0x3A, 1 | DELAY, 0x55, 10,
+ // ST7789V frame rate setting
+ 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33,
+ // voltages: VGH / VGL
+ 0xB7, 1, 0x35,
+ // ST7789V power setting
+ 0xBB, 1, 0x28,
+ 0xC0, 1, 0x0C,
+ 0xC2, 2, 0x01, 0xFF,
+ 0xC3, 1, 0x10,
+ 0xC4, 1, 0x20,
+ 0xC6, 1, 0x0F,
+ 0xD0, 2, 0xA4, 0xA1,
+ // ST7789V gamma setting
+ 0xE0, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17,
+ 0xE1, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E,
+ 0x21, 0,
+ // display on
+ 0x29, 0 | DELAY, 255,
+ };
+
+static void display_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+
+ common_hal_busio_spi_construct(
+ spi,
+ &pin_GPIO36, // CLK
+ &pin_GPIO35, // MOSI
+ NULL // MISO not connected
+ );
+
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+
+ common_hal_displayio_fourwire_construct(
+ bus,
+ spi,
+ &pin_GPIO37, // DC
+ &pin_GPIO34, // CS
+ &pin_GPIO38, // RST
+ 40000000, // baudrate
+ 0, // polarity
+ 0 // phase
+ );
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+
+ // workaround as board_init() is called before reset_port() in main.c
+ pwmout_reset();
+
+ common_hal_displayio_display_construct(
+ display,
+ bus,
+ 240, // width (after rotation)
+ 135, // height (after rotation)
+ 52, // column start
+ 40, // row start
+ 90, // rotation
+ 16, // color depth
+ false, // grayscale
+ false, // pixels in a byte share a row. Only valid for depths < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ true, // reverse_pixels_in_word
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // write memory command
+ 0x37, // set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_GPIO33, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ false, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ true, // auto_refresh
+ 60, // native_frames_per_second
+ true, // backlight_on_high
+ false // SH1107_addressing
+ );
+
+ common_hal_never_reset_pin(&pin_GPIO33); // backlight pin
+}
void board_init(void) {
// USB
@@ -38,6 +141,9 @@ void board_init(void) {
common_hal_never_reset_pin(&pin_GPIO43);
common_hal_never_reset_pin(&pin_GPIO44);
#endif /* DEBUG */
+
+ // Display
+ display_init();
}
bool board_requests_safe_mode(void) {
diff --git a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.mk b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.mk
index 38a7ed1fb..79b45fd92 100644
--- a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.mk
+++ b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.mk
@@ -2,7 +2,6 @@ USB_VID = 0x303a
USB_PID = 0x8007
USB_PRODUCT = "TTGO T8 ESP32-S2"
USB_MANUFACTURER = "LILYGO"
-USB_DEVICES = "CDC,MSC,HID"
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
diff --git a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c
index bda0fd227..a30c6797a 100644
--- a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c
+++ b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c
@@ -1,4 +1,5 @@
#include "shared-bindings/board/__init__.h"
+#include "shared-module/displayio/__init__.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
@@ -41,13 +42,13 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO10) },
// 1.14 inch LCD ST7789
- { MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO38) },
{ MP_ROM_QSTR(MP_QSTR_LCD_BCKL), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_LCD_D_C), MP_ROM_PTR(&pin_GPIO37) },
+ { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },
// Peripheral Power control
{ MP_ROM_QSTR(MP_QSTR_PE_POWER), MP_ROM_PTR(&pin_GPIO14) },
diff --git a/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk b/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk
index 515617095..783e7ad4c 100644
--- a/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk
+++ b/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk
@@ -2,7 +2,6 @@ USB_VID = 0x239A
USB_PID = 0x80C6
USB_PRODUCT = "microS2"
USB_MANUFACTURER = "microDev"
-USB_DEVICES = "CDC,MSC,HID"
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
index 9857c0761..d045cc214 100644
--- a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
@@ -2,7 +2,6 @@ USB_VID = 0x239A
USB_PID = 0x80AC
USB_PRODUCT = "FeatherS2"
USB_MANUFACTURER = "UnexpectedMaker"
-USB_DEVICES = "CDC,MSC,HID"
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/mpconfigboard.mk b/ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/mpconfigboard.mk
index 9857c0761..d045cc214 100644
--- a/ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/mpconfigboard.mk
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2_prerelease/mpconfigboard.mk
@@ -2,7 +2,6 @@ USB_VID = 0x239A
USB_PID = 0x80AC
USB_PRODUCT = "FeatherS2"
USB_MANUFACTURER = "UnexpectedMaker"
-USB_DEVICES = "CDC,MSC,HID"
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
diff --git a/ports/esp32s2/boards/unexpectedmaker_tinys2/board.c b/ports/esp32s2/boards/unexpectedmaker_tinys2/board.c
new file mode 100644
index 000000000..d8fd3a0a2
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_tinys2/board.c
@@ -0,0 +1,61 @@
+/*
+ * 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 */
+
+ // SPI Flash and RAM
+ common_hal_never_reset_pin(&pin_GPIO26);
+ common_hal_never_reset_pin(&pin_GPIO27);
+ common_hal_never_reset_pin(&pin_GPIO28);
+ common_hal_never_reset_pin(&pin_GPIO29);
+ common_hal_never_reset_pin(&pin_GPIO30);
+ common_hal_never_reset_pin(&pin_GPIO31);
+ common_hal_never_reset_pin(&pin_GPIO32);
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
+
+void board_deinit(void) {
+}
diff --git a/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h b/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h
new file mode 100644
index 000000000..85f252328
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h
@@ -0,0 +1,46 @@
+/*
+ * 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 "TinyS2"
+#define MICROPY_HW_MCU_NAME "ESP32S2"
+
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO1)
+#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
+
+#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9)
+#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36)
+#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35)
+#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37)
+
+#define DEFAULT_UART_BUS_RX (&pin_GPIO44)
+#define DEFAULT_UART_BUS_TX (&pin_GPIO43)
diff --git a/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.mk b/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.mk
new file mode 100644
index 000000000..aa022e186
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.mk
@@ -0,0 +1,23 @@
+USB_VID = 0x303A
+USB_PID = 0x8002
+USB_PRODUCT = "TinyS2"
+USB_MANUFACTURER = "UnexpectedMaker"
+
+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=qio
+CIRCUITPY_ESP_FLASH_FREQ=80m
+CIRCUITPY_ESP_FLASH_SIZE=4MB
+
+# CIRCUITPY_MODULE=wroom
+
+CIRCUITPY_BITBANG_NEOPIXEL = 1
+
+# Include these Python libraries in firmware.
+# FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
diff --git a/ports/esp32s2/boards/unexpectedmaker_tinys2/pins.c b/ports/esp32s2/boards/unexpectedmaker_tinys2/pins.c
new file mode 100644
index 000000000..8ca7d9864
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_tinys2/pins.c
@@ -0,0 +1,79 @@
+#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_D4), MP_ROM_PTR(&pin_GPIO0) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
+ // { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO18) },
+ // { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO18) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
+ // { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO17) },
+ // { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO17) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
+ // { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO7) },
+ // { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO7) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
+ // { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO6) },
+ // { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO6) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
+ // { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) },
+ // { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO5) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) },
+ // { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO36) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) },
+ // { MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO35) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) },
+ // { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO37) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) },
+ // { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) },
+ // { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO37) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) },
+ { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
+ // { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO8) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
+ // { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO9) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) },
+ // { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO38) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
+ // { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO33) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) },
+ // { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO43) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
+
+ { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) },
+ // { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO44) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO2) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO1) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/esp32s2/boards/unexpectedmaker_tinys2/sdkconfig b/ports/esp32s2/boards/unexpectedmaker_tinys2/sdkconfig
new file mode 100644
index 000000000..91447cdc2
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_tinys2/sdkconfig
@@ -0,0 +1,39 @@
+CONFIG_ESP32S2_SPIRAM_SUPPORT=y
+
+#
+# SPI RAM config
+#
+# CONFIG_SPIRAM_TYPE_AUTO=y
+CONFIG_SPIRAM_TYPE_ESPPSRAM16=y
+# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
+# CONFIG_SPIRAM_TYPE_ESPPSRAM64=y
+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=y
+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
+
+#
+# LWIP
+#
+CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyS2"
+# end of LWIP
diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c
index 1cec5d4ae..be435e210 100644
--- a/ports/esp32s2/common-hal/alarm/__init__.c
+++ b/ports/esp32s2/common-hal/alarm/__init__.c
@@ -150,6 +150,14 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
void NORETURN alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_touch_touchalarm_prepare_for_deep_sleep();
+
+ // Disable brownout detection, which appears to be triggered sometimes when
+ // waking from deep sleep.
+ // See https://www.esp32.com/viewtopic.php?f=13&t=19208#p71084
+ // and https://github.com/adafruit/circuitpython/issues/4025#issuecomment-771027606
+ // TODO: We can remove this workaround when ESP-IDF handles this.
+ CLEAR_PERI_REG_MASK(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_RST_ENA);
+
// The ESP-IDF caches the deep sleep settings and applies them before sleep.
// We don't need to worry about resetting them in the interim.
esp_deep_sleep_start();
diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c
index fca89ce8e..ff6d0ed35 100644
--- a/ports/esp32s2/common-hal/microcontroller/Pin.c
+++ b/ports/esp32s2/common-hal/microcontroller/Pin.c
@@ -134,7 +134,7 @@ bool pin_number_is_free(gpio_num_t pin_number) {
uint8_t offset = pin_number / 32;
uint32_t mask = 1 << (pin_number % 32);
- return (never_reset_pins[offset] & mask) == 0 && (in_use[offset] & mask) == 0;
+ return (in_use[offset] & mask) == 0;
}
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c
index 1cdbc9058..5f93807bb 100644
--- a/ports/esp32s2/common-hal/socketpool/Socket.c
+++ b/ports/esp32s2/common-hal/socketpool/Socket.c
@@ -63,7 +63,7 @@ bool register_open_socket(socketpool_socket_obj_t* self) {
}
socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self,
- uint8_t* ip, uint *port) {
+ uint8_t* ip, uint32_t *port) {
struct sockaddr_in accept_addr;
socklen_t socklen = sizeof(accept_addr);
int newsoc = -1;
@@ -99,6 +99,7 @@ socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_o
sock->base.type = &socketpool_socket_type;
sock->num = newsoc;
sock->pool = self->pool;
+ sock->connected = true;
if (!register_open_socket(sock)) {
mp_raise_OSError(MP_EBADF);
@@ -113,7 +114,7 @@ socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_o
}
bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self,
- const char* host, size_t hostlen, uint8_t port) {
+ const char* host, size_t hostlen, uint32_t port) {
struct sockaddr_in bind_addr;
bind_addr.sin_addr.s_addr = inet_addr(host);
bind_addr.sin_family = AF_INET;
@@ -144,7 +145,7 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) {
}
bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self,
- const char* host, mp_uint_t hostlen, mp_int_t port) {
+ const char* host, size_t hostlen, uint32_t port) {
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
@@ -202,7 +203,7 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int back
}
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* self,
- uint8_t* buf, mp_uint_t len, uint8_t* ip, uint *port) {
+ uint8_t* buf, uint32_t len, uint8_t* ip, uint *port) {
struct sockaddr_in source_addr;
socklen_t socklen = sizeof(source_addr);
@@ -241,7 +242,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se
return received;
}
-mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
+mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, uint32_t len) {
int received = 0;
bool timed_out = false;
@@ -273,7 +274,7 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
return received;
}
-mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
+mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, uint32_t len) {
int sent = -1;
if (self->num != -1) {
// LWIP Socket
@@ -290,7 +291,7 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const
}
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self,
- const char* host, size_t hostlen, uint8_t port, const uint8_t* buf, mp_uint_t len) {
+ const char* host, size_t hostlen, uint32_t port, const uint8_t* buf, uint32_t len) {
// Set parameters
const struct addrinfo hints = {
@@ -322,6 +323,6 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self,
return bytes_sent;
}
-void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_uint_t timeout_ms) {
+void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, uint32_t timeout_ms) {
self->timeout_ms = timeout_ms;
}
diff --git a/ports/esp32s2/common-hal/ssl/SSLSocket.c b/ports/esp32s2/common-hal/ssl/SSLSocket.c
index 33507e0f4..10c29108c 100644
--- a/ports/esp32s2/common-hal/ssl/SSLSocket.c
+++ b/ports/esp32s2/common-hal/ssl/SSLSocket.c
@@ -35,19 +35,15 @@
#include "py/runtime.h"
#include "supervisor/shared/tick.h"
-void common_hal_ssl_sslsocket_settimeout(ssl_sslsocket_obj_t* self, mp_uint_t timeout_ms) {
- self->sock->timeout_ms = timeout_ms;
-}
-
ssl_sslsocket_obj_t* common_hal_ssl_sslsocket_accept(ssl_sslsocket_obj_t* self,
- uint8_t* ip, uint *port) {
+ uint8_t* ip, uint32_t *port) {
socketpool_socket_obj_t * sock = common_hal_socketpool_socket_accept(self->sock, ip, port);
ssl_sslsocket_obj_t * sslsock = common_hal_ssl_sslcontext_wrap_socket(self->ssl_context, sock, false, NULL);
return sslsock;
}
bool common_hal_ssl_sslsocket_bind(ssl_sslsocket_obj_t* self,
- const char* host, size_t hostlen, uint8_t port) {
+ const char* host, size_t hostlen, uint32_t port) {
return common_hal_socketpool_socket_bind(self->sock, host, hostlen, port);
}
@@ -58,7 +54,7 @@ void common_hal_ssl_sslsocket_close(ssl_sslsocket_obj_t* self) {
}
bool common_hal_ssl_sslsocket_connect(ssl_sslsocket_obj_t* self,
- const char* host, mp_uint_t hostlen, mp_int_t port) {
+ const char* host, size_t hostlen, uint32_t port) {
esp_tls_cfg_t* tls_config = NULL;
tls_config = &self->ssl_context->ssl_config;
int result = esp_tls_conn_new_sync(host, hostlen, port, tls_config, self->tls);
@@ -104,7 +100,7 @@ bool common_hal_ssl_sslsocket_listen(ssl_sslsocket_obj_t* self, int backlog) {
return common_hal_socketpool_socket_listen(self->sock, backlog);
}
-mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
+mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t* self, const uint8_t* buf, uint32_t len) {
int received = 0;
bool timed_out = false;
int status = 0;
@@ -155,7 +151,7 @@ mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t* self, const ui
return received;
}
-mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
+mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t* self, const uint8_t* buf, uint32_t len) {
int sent = -1;
sent = esp_tls_conn_write(self->tls, buf, len);
@@ -174,3 +170,7 @@ mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t* self, const uint8_t
}
return sent;
}
+
+void common_hal_ssl_sslsocket_settimeout(ssl_sslsocket_obj_t* self, uint32_t timeout_ms) {
+ self->sock->timeout_ms = timeout_ms;
+}
diff --git a/ports/esp32s2/common-hal/supervisor/Runtime.c b/ports/esp32s2/common-hal/supervisor/Runtime.c
index ea663f897..974f26cec 100644
--- a/ports/esp32s2/common-hal/supervisor/Runtime.c
+++ b/ports/esp32s2/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
- return (bool) serial_bytes_available();
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
+ return (bool) serial_bytes_available();
}
diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk
index b273c02ee..5073d8812 100644
--- a/ports/esp32s2/mpconfigport.mk
+++ b/ports/esp32s2/mpconfigport.mk
@@ -28,6 +28,8 @@ CIRCUITPY_FREQUENCYIO = 1
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_ROTARYIO = 1
CIRCUITPY_NVM = 1
+CIRCUITPY_PS2IO ?= 1
+CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1
# We don't have enough endpoints to include MIDI.
CIRCUITPY_USB_MIDI ?= 0
CIRCUITPY_USB_HID ?= 1
@@ -35,14 +37,9 @@ CIRCUITPY_USB_HID ?= 1
CIRCUITPY_USB_VENDOR ?= 0
CIRCUITPY_WIFI = 1
CIRCUITPY_WATCHDOG ?= 1
-CIRCUITPY_ESPIDF = 1
-
-ifndef CIRCUITPY_PS2IO
-CIRCUITPY_PS2IO = 1
-endif
-ifndef CIRCUITPY_TOUCHIO_USE_NATIVE
-CIRCUITPY_TOUCHIO_USE_NATIVE = 1
-endif
+CIRCUITPY_ESPIDF = 1
CIRCUITPY_MODULE ?= none
+
+USB_NUM_EP = 5
diff --git a/ports/litex/common-hal/supervisor/Runtime.c b/ports/litex/common-hal/supervisor/Runtime.c
index ea663f897..974f26cec 100644
--- a/ports/litex/common-hal/supervisor/Runtime.c
+++ b/ports/litex/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
- return (bool) serial_bytes_available();
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
+ return (bool) serial_bytes_available();
}
diff --git a/ports/litex/mpconfigport.mk b/ports/litex/mpconfigport.mk
index 003fb5c2c..af6a94e64 100644
--- a/ports/litex/mpconfigport.mk
+++ b/ports/litex/mpconfigport.mk
@@ -6,6 +6,9 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
# Internal math library is substantially smaller than toolchain one
INTERNAL_LIBM = 1
+# Number of USB endpoint pairs.
+USB_NUM_EP = 16
+
# Chip supplied serial number, in bytes
USB_SERIAL_NUMBER_LENGTH = 30
diff --git a/ports/mimxrt10xx/common-hal/busio/SPI.c b/ports/mimxrt10xx/common-hal/busio/SPI.c
index ce7cbea7e..00d8d9867 100644
--- a/ports/mimxrt10xx/common-hal/busio/SPI.c
+++ b/ports/mimxrt10xx/common-hal/busio/SPI.c
@@ -38,6 +38,8 @@
#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (CLOCK_GetDiv(kCLOCK_LpspiDiv) + 1))
+#define MAX_SPI_BUSY_RETRIES 100
+
//arrays use 0 based numbering: SPI1 is stored at index 0
#define MAX_SPI 4
STATIC bool reserved_spi[MAX_SPI];
@@ -289,7 +291,12 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
xfer.dataSize = len;
xfer.configFlags = kLPSPI_MasterPcs0;
- const status_t status = LPSPI_MasterTransferBlocking(self->spi, &xfer);
+ status_t status;
+ int retries = MAX_SPI_BUSY_RETRIES;
+ do {
+ status = LPSPI_MasterTransferBlocking(self->spi, &xfer);
+ } while (status == kStatus_LPSPI_Busy && --retries > 0);
+
if (status != kStatus_Success)
printf("%s: status %ld\r\n", __func__, status);
@@ -311,7 +318,12 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
xfer.rxData = data;
xfer.dataSize = len;
- const status_t status = LPSPI_MasterTransferBlocking(self->spi, &xfer);
+ status_t status;
+ int retries = MAX_SPI_BUSY_RETRIES;
+ do {
+ status = LPSPI_MasterTransferBlocking(self->spi, &xfer);
+ } while (status == kStatus_LPSPI_Busy && --retries > 0);
+
if (status != kStatus_Success)
printf("%s: status %ld\r\n", __func__, status);
@@ -333,7 +345,12 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_ou
xfer.rxData = data_in;
xfer.dataSize = len;
- const status_t status = LPSPI_MasterTransferBlocking(self->spi, &xfer);
+ status_t status;
+ int retries = MAX_SPI_BUSY_RETRIES;
+ do {
+ status = LPSPI_MasterTransferBlocking(self->spi, &xfer);
+ } while (status == kStatus_LPSPI_Busy && --retries > 0);
+
if (status != kStatus_Success)
printf("%s: status %ld\r\n", __func__, status);
diff --git a/ports/mimxrt10xx/common-hal/supervisor/Runtime.c b/ports/mimxrt10xx/common-hal/supervisor/Runtime.c
index 6be38f216..974f26cec 100755
--- a/ports/mimxrt10xx/common-hal/supervisor/Runtime.c
+++ b/ports/mimxrt10xx/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
return (bool) serial_bytes_available();
}
diff --git a/ports/mimxrt10xx/mpconfigport.mk b/ports/mimxrt10xx/mpconfigport.mk
index b4cc9586a..de594b14b 100644
--- a/ports/mimxrt10xx/mpconfigport.mk
+++ b/ports/mimxrt10xx/mpconfigport.mk
@@ -17,6 +17,9 @@ INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 32
USB_HIGHSPEED = 1
+# Number of USB endpoint pairs.
+USB_NUM_EP = 8
+
INTERNAL_FLASH_FILESYSTEM = 1
CIRCUITPY_AUDIOIO = 0
diff --git a/ports/nrf/bluetooth/ble_uart.c b/ports/nrf/bluetooth/ble_uart.c
index 1e7a319bd..1b87b82d1 100644
--- a/ports/nrf/bluetooth/ble_uart.c
+++ b/ports/nrf/bluetooth/ble_uart.c
@@ -40,7 +40,7 @@
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
-#if CIRCUITPY_SERIAL_BLE
+#if CIRCUITPY_REPL_BLE
static const char default_name[] = "CP-REPL"; // max 8 chars or uuid won't fit in adv data
static const char NUS_UUID[] = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
@@ -190,4 +190,4 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
}
}
-#endif // CIRCUITPY_SERIAL_BLE
+#endif // CIRCUITPY_REPL_BLE
diff --git a/ports/nrf/boards/TG-Watch/mpconfigboard.h b/ports/nrf/boards/TG-Watch/mpconfigboard.h
index 07a607b3d..1377c921e 100644
--- a/ports/nrf/boards/TG-Watch/mpconfigboard.h
+++ b/ports/nrf/boards/TG-Watch/mpconfigboard.h
@@ -30,27 +30,27 @@
#define MICROPY_HW_BOARD_NAME "TG-Watch"
#define MICROPY_HW_MCU_NAME "nRF52840"
-#define MICROPY_HW_NEOPIXEL (&pin_P0_16)
-#define MICROPY_HW_LED_STATUS (&pin_P1_15)
-
-// TG-Gui requires a deeper call stack than normal CircuitPython
+// TG-Gui requires a deeper call stack than normal CircuitPython, this is intentional overkill
#define CIRCUITPY_PYSTACK_SIZE 8192 // 1536 is the normal size, (32 bytes/frame * 48 frames)
-#define BOARD_HAS_CRYSTAL 0
+
+// the board has a 32mhz crystal but NOT a 32khz one
+#define BOARD_HAS_32KHZ_XTAL 0
+#define BOARD_HAS_CRYSTAL 1
#if QSPI_FLASH_FILESYSTEM
-#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17)
-#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 22)
-#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 23)
-#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21)
-#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
-#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20)
+ #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17)
+ #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 22)
+ #define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 23)
+ #define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21)
+ #define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
+ #define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20)
#endif
#if SPI_FLASH_FILESYSTEM
-#define SPI_FLASH_MOSI_PIN &pin_P0_17
-#define SPI_FLASH_MISO_PIN &pin_P0_22
-#define SPI_FLASH_SCK_PIN &pin_P0_19
-#define SPI_FLASH_CS_PIN &pin_P0_20
+ #define SPI_FLASH_MOSI_PIN &pin_P0_17
+ #define SPI_FLASH_MISO_PIN &pin_P0_22
+ #define SPI_FLASH_SCK_PIN &pin_P0_19
+ #define SPI_FLASH_CS_PIN &pin_P0_20
#endif
#define DEFAULT_I2C_BUS_SCL (&pin_P0_11)
diff --git a/ports/nrf/boards/pca10100/mpconfigboard.mk b/ports/nrf/boards/pca10100/mpconfigboard.mk
index c8cba2877..fbb9987c2 100644
--- a/ports/nrf/boards/pca10100/mpconfigboard.mk
+++ b/ports/nrf/boards/pca10100/mpconfigboard.mk
@@ -29,6 +29,7 @@ CIRCUITPY_BUSDEVICE = 0
MICROPY_PY_ASYNC_AWAIT = 0
SUPEROPT_GC = 0
+SUPEROPT_VM = 0
# Override optimization to keep binary small
OPTIMIZATION_FLAGS = -Os
diff --git a/ports/nrf/boards/simmel/mpconfigboard.mk b/ports/nrf/boards/simmel/mpconfigboard.mk
index 6bc05a7f0..52743d340 100644
--- a/ports/nrf/boards/simmel/mpconfigboard.mk
+++ b/ports/nrf/boards/simmel/mpconfigboard.mk
@@ -3,8 +3,6 @@ USB_PID = 0xc051
USB_PRODUCT = "Simmel"
USB_MANUFACTURER = "Betrusted"
-CIRCUITPY_DEVICES="CDC,MSC,HID"
-
MCU_CHIP = nrf52833
# SPI_FLASH_FILESYSTEM = 1
@@ -31,6 +29,7 @@ CIRCUITPY_RTC = 1
CIRCUITPY_SDCARDIO = 0
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_ULAB = 0
+CIRCUITPY_USB_CDC = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_WATCHDOG = 1
diff --git a/ports/nrf/common-hal/supervisor/Runtime.c b/ports/nrf/common-hal/supervisor/Runtime.c
index ea663f897..a24e86cdf 100755
--- a/ports/nrf/common-hal/supervisor/Runtime.c
+++ b/ports/nrf/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
return (bool) serial_bytes_available();
}
diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk
index 9560064fb..83924ff79 100644
--- a/ports/nrf/mpconfigport.mk
+++ b/ports/nrf/mpconfigport.mk
@@ -11,6 +11,9 @@ INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 16
+# Number of USB endpoint pairs.
+USB_NUM_EP = 8
+
# All nRF ports have longints.
LONGINT_IMPL = MPZ
diff --git a/ports/nrf/supervisor/serial.c b/ports/nrf/supervisor/serial.c
index b19e9267c..2c2c0116f 100644
--- a/ports/nrf/supervisor/serial.c
+++ b/ports/nrf/supervisor/serial.c
@@ -28,15 +28,15 @@
#include "supervisor/serial.h"
-#if CIRCUITPY_SERIAL_BLE
+#if CIRCUITPY_REPL_BLE
#include "ble_uart.h"
-#elif CIRCUITPY_SERIAL_UART
+#elif CIRCUITPY_REPL_UART
#include <string.h>
#include "nrf_gpio.h"
#include "nrfx_uarte.h"
#endif
-#if CIRCUITPY_SERIAL_BLE
+#if CIRCUITPY_REPL_BLE
void serial_init(void) {
ble_uart_init();
@@ -58,7 +58,7 @@ void serial_write(const char *text) {
ble_uart_stdout_tx_str(text);
}
-#elif CIRCUITPY_SERIAL_UART
+#elif CIRCUITPY_REPL_UART
uint8_t serial_received_char;
nrfx_uarte_t serial_instance = NRFX_UARTE_INSTANCE(0);
@@ -124,4 +124,4 @@ void serial_write_substring(const char *text, uint32_t len) {
}
}
-#endif // CIRCUITPY_SERIAL_UART
+#endif // CIRCUITPY_REPL_UART
diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile
index e1169ce7d..f5e65f256 100644
--- a/ports/raspberrypi/Makefile
+++ b/ports/raspberrypi/Makefile
@@ -196,8 +196,10 @@ SRC_C += \
bindings/rp2pio/__init__.c \
common-hal/rp2pio/StateMachine.c \
common-hal/rp2pio/__init__.c \
+ audio_dma.c \
background.c \
peripherals/pins.c \
+ extmod/crypto-algorithms/sha256.c \
fatfs_port.c \
lib/libc/string0.c \
lib/mp-readline/readline.c \
diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c
new file mode 100644
index 000000000..96317984d
--- /dev/null
+++ b/ports/raspberrypi/audio_dma.c
@@ -0,0 +1,383 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 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 "audio_dma.h"
+
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/audiocore/WaveFile.h"
+#include "supervisor/background_callback.h"
+
+#include "py/mpstate.h"
+#include "py/runtime.h"
+
+#include "src/rp2_common/hardware_irq/include/hardware/irq.h"
+
+#if CIRCUITPY_AUDIOPWMIO || CIRCUITPY_AUDIOBUSIO
+
+#define AUDIO_DMA_CHANNEL_COUNT NUM_DMA_CHANNELS
+
+void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer_length,
+ uint8_t** output_buffer, uint32_t* output_buffer_length) {
+ if (dma->first_buffer_free) {
+ *output_buffer = dma->first_buffer;
+ } else {
+ *output_buffer = dma->second_buffer;
+ }
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ if (dma->signed_to_unsigned ||
+ dma->unsigned_to_signed ||
+ dma->sample_spacing > 1 ||
+ (dma->sample_resolution != dma->output_resolution)) {
+ *output_buffer_length = buffer_length / dma->sample_spacing;
+ uint32_t out_i = 0;
+ if (dma->sample_resolution <= 8 && dma->output_resolution > 8) {
+ size_t shift = dma->output_resolution - dma->sample_resolution;
+
+ for (uint32_t i = 0; i < buffer_length; i += dma->sample_spacing) {
+ if (dma->signed_to_unsigned) {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t) ((int8_t*) buffer)[i] + 0x80) << shift;
+ } else if (dma->unsigned_to_signed) {
+ ((int16_t*) *output_buffer)[out_i] = ((int16_t) ((uint8_t*) buffer)[i] - 0x80) << shift;
+ } else {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t) ((uint8_t*) buffer)[i]) << shift;
+ }
+ out_i += 1;
+ }
+ } else if (dma->sample_resolution <= 8 && dma->output_resolution <= 8) {
+ for (uint32_t i = 0; i < buffer_length; i += dma->sample_spacing) {
+ if (dma->signed_to_unsigned) {
+ ((uint8_t*) *output_buffer)[out_i] = ((int8_t*) buffer)[i] + 0x80;
+ } else if (dma->unsigned_to_signed) {
+ ((int8_t*) *output_buffer)[out_i] = ((uint8_t*) buffer)[i] - 0x80;
+ } else {
+ ((uint8_t*) *output_buffer)[out_i] = ((uint8_t*) buffer)[i];
+ }
+ out_i += 1;
+ }
+ } else if (dma->sample_resolution > 8 && dma->output_resolution > 8) {
+ size_t shift = 16 - dma->output_resolution;
+ for (uint32_t i = 0; i < buffer_length / 2; i += dma->sample_spacing) {
+ if (dma->signed_to_unsigned) {
+ ((uint16_t*) *output_buffer)[out_i] = ((int16_t*) buffer)[i] + 0x8000;
+ } else if (dma->unsigned_to_signed) {
+ ((int16_t*) *output_buffer)[out_i] = ((uint16_t*) buffer)[i] - 0x8000;
+ } else {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t*) buffer)[i];
+ }
+ if (dma->output_resolution < 16) {
+ if (dma->output_signed) {
+ ((int16_t*) *output_buffer)[out_i] = ((int16_t*) *output_buffer)[out_i] >> shift;
+ } else {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t*) *output_buffer)[out_i] >> shift;
+ }
+ }
+ out_i += 1;
+ }
+ }
+ } else {
+ *output_buffer = buffer;
+ *output_buffer_length = buffer_length;
+ }
+ #pragma GCC diagnostic pop
+ dma->first_buffer_free = !dma->first_buffer_free;
+}
+
+void audio_dma_load_next_block(audio_dma_t* dma) {
+ uint8_t dma_channel = dma->channel[1];
+ if (dma->first_channel_free) {
+ dma_channel = dma->channel[0];
+ }
+ dma->first_channel_free = !dma->first_channel_free;
+
+ uint8_t* output_buffer;
+ uint32_t output_buffer_length;
+ audioio_get_buffer_result_t get_buffer_result;
+ uint8_t* buffer;
+ uint32_t buffer_length;
+ get_buffer_result = audiosample_get_buffer(dma->sample,
+ dma->single_channel, dma->audio_channel, &buffer, &buffer_length);
+
+ if (get_buffer_result == GET_BUFFER_ERROR) {
+ audio_dma_stop(dma);
+ return;
+ }
+
+ audio_dma_convert_signed(dma, buffer, buffer_length, &output_buffer, &output_buffer_length);
+
+ // If we don't have an output buffer, save the pointer to first_buffer for use in the single
+ // buffer special case.
+ if (dma->first_buffer == NULL) {
+ dma->first_buffer = output_buffer;
+ }
+
+ dma_channel_set_trans_count(dma_channel, output_buffer_length / dma->output_size, false /* trigger */);
+ dma_channel_set_read_addr(dma_channel, output_buffer, false /* trigger */);
+ if (get_buffer_result == GET_BUFFER_DONE) {
+ if (dma->loop) {
+ audiosample_reset_buffer(dma->sample, dma->single_channel, dma->audio_channel);
+ } else {
+ // Set channel trigger to ourselves so we don't keep going.
+ dma_channel_hw_t* c = &dma_hw->ch[dma_channel];
+ c->al1_ctrl = (c->al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (dma_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB);
+ }
+ }
+}
+
+// Playback should be shutdown before calling this.
+audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
+ mp_obj_t sample,
+ bool loop,
+ bool single_channel,
+ uint8_t audio_channel,
+ bool output_signed,
+ uint8_t output_resolution,
+ uint32_t output_register_address,
+ uint8_t dma_trigger_source) {
+ // Use two DMA channels to because the DMA can't wrap to itself without the
+ // buffer being power of two aligned.
+ dma->channel[0] = dma_claim_unused_channel(false);
+ dma->channel[1] = dma_claim_unused_channel(false);
+ if (dma->channel[0] == NUM_DMA_CHANNELS || dma->channel[1] == NUM_DMA_CHANNELS) {
+ if (dma->channel[0] < NUM_DMA_CHANNELS) {
+ dma_channel_unclaim(dma->channel[0]);
+ }
+ return AUDIO_DMA_DMA_BUSY;
+ }
+
+ dma->sample = sample;
+ dma->loop = loop;
+ dma->single_channel = single_channel;
+ dma->audio_channel = audio_channel;
+ dma->signed_to_unsigned = false;
+ dma->unsigned_to_signed = false;
+ dma->output_signed = output_signed;
+ dma->sample_spacing = 1;
+ dma->first_channel_free = true;
+ dma->output_resolution = output_resolution;
+ dma->sample_resolution = audiosample_bits_per_sample(sample);
+ audiosample_reset_buffer(sample, single_channel, audio_channel);
+
+ bool single_buffer;
+ bool samples_signed;
+ uint32_t max_buffer_length;
+ audiosample_get_buffer_structure(sample, single_channel, &single_buffer, &samples_signed,
+ &max_buffer_length, &dma->sample_spacing);
+
+ // Check to see if we have to scale the resolution up.
+ if (dma->sample_resolution <= 8 && dma->output_resolution > 8) {
+ max_buffer_length *= 2;
+ }
+ if (output_signed != samples_signed ||
+ dma->sample_spacing > 1 ||
+ (dma->sample_resolution != dma->output_resolution)) {
+ max_buffer_length /= dma->sample_spacing;
+ dma->first_buffer = (uint8_t*) m_realloc(dma->first_buffer, max_buffer_length);
+ if (dma->first_buffer == NULL) {
+ return AUDIO_DMA_MEMORY_ERROR;
+ }
+
+ dma->first_buffer_free = true;
+ if (!single_buffer) {
+ dma->second_buffer = (uint8_t*) m_realloc(dma->second_buffer, max_buffer_length);
+ if (dma->second_buffer == NULL) {
+ return AUDIO_DMA_MEMORY_ERROR;
+ }
+ }
+ dma->signed_to_unsigned = !output_signed && samples_signed;
+ dma->unsigned_to_signed = output_signed && !samples_signed;
+ }
+
+ if (output_resolution > 8) {
+ dma->output_size = 2;
+ } else {
+ dma->output_size = 1;
+ }
+ // Transfer both channels at once.
+ if (!single_channel && audiosample_channel_count(sample) == 2) {
+ dma->output_size *= 2;
+ }
+
+ enum dma_channel_transfer_size dma_size = DMA_SIZE_8;
+ if (dma->output_size == 2) {
+ dma_size = DMA_SIZE_16;
+ } else if (dma->output_size == 4) {
+ dma_size = DMA_SIZE_32;
+ }
+
+ for (size_t i = 0; i < 2; i++) {
+ dma_channel_config c = dma_channel_get_default_config(dma->channel[i]);
+ channel_config_set_transfer_data_size(&c, dma_size);
+ channel_config_set_dreq(&c, dma_trigger_source);
+ channel_config_set_read_increment(&c, true);
+ channel_config_set_write_increment(&c, false);
+ // Chain to the other channel by default.
+ channel_config_set_chain_to(&c, dma->channel[(i + 1) % 2]);
+ dma_channel_set_config(dma->channel[i], &c, false /* trigger */);
+ dma_channel_set_write_addr(dma->channel[i], (void*) output_register_address, false /* trigger */);
+ }
+
+ // We keep the audio_dma_t for internal use and the sample as a root pointer because it
+ // contains the audiodma structure.
+ MP_STATE_PORT(playing_audio)[dma->channel[0]] = dma;
+ MP_STATE_PORT(playing_audio)[dma->channel[1]] = dma;
+
+ // Load the first two blocks up front.
+ audio_dma_load_next_block(dma);
+ if (!single_buffer) {
+ audio_dma_load_next_block(dma);
+ }
+
+ // Special case the DMA for a single buffer. It's commonly used for a single wave length of sound
+ // and may be short. Therefore, we use DMA chaining to loop quickly without involving interrupts.
+ // On the RP2040 we chain by having a second DMA writing to the config registers of the first.
+ // Read and write addresses change with DMA so we need to reset the read address back to the
+ // start of the sample.
+ if (single_buffer) {
+ dma_channel_config c = dma_channel_get_default_config(dma->channel[1]);
+ channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
+ channel_config_set_dreq(&c, 0x3f); // dma as fast as possible
+ channel_config_set_read_increment(&c, false);
+ channel_config_set_write_increment(&c, false);
+ channel_config_set_chain_to(&c, dma->channel[1]); // Chain to ourselves so we stop.
+ dma_channel_configure(dma->channel[1], &c,
+ &dma_hw->ch[dma->channel[0]].al3_read_addr_trig, // write address
+ &dma->first_buffer, // read address
+ 1, // transaction count
+ false); // trigger
+ } else {
+ // Enable our DMA channels on DMA0 to the CPU. This will wake us up when
+ // we're WFI.
+ dma_hw->inte0 |= (1 << dma->channel[0]) | (1 << dma->channel[1]);
+ irq_set_mask_enabled(1 << DMA_IRQ_0, true);
+ }
+
+ dma_channel_start(dma->channel[0]);
+
+ return AUDIO_DMA_OK;
+}
+
+void audio_dma_stop(audio_dma_t* dma) {
+ // Disable our interrupts.
+ dma_hw->inte0 &= ~((1 << dma->channel[0]) | (1 << dma->channel[1]));
+ irq_set_mask_enabled(1 << DMA_IRQ_0, false);
+
+ // Run any remaining audio tasks because we remove ourselves from
+ // playing_audio.
+ RUN_BACKGROUND_TASKS;
+
+ for (size_t i = 0; i < 2; i++) {
+ size_t channel = dma->channel[i];
+
+ if (dma_channel_is_busy(channel)) {
+ dma_channel_abort(channel);
+ }
+ dma_channel_unclaim(channel);
+ MP_STATE_PORT(playing_audio)[channel] = NULL;
+ dma->channel[i] = NUM_DMA_CHANNELS;
+ }
+
+ // Hold onto our buffers.
+}
+
+// To pause we simply stop the DMA. It is the responsibility of the output peripheral
+// to hold the previous value.
+void audio_dma_pause(audio_dma_t* dma) {
+ dma_hw->ch[dma->channel[0]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS;
+ dma_hw->ch[dma->channel[1]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS;
+}
+
+void audio_dma_resume(audio_dma_t* dma) {
+ // Always re-enable the non-busy channel first so it's ready to continue when the busy channel
+ // finishes and chains to it. (An interrupt could make the time between enables long.)
+ size_t first = 0;
+ size_t second = 1;
+ if (dma_channel_is_busy(dma->channel[0])) {
+ first = 1;
+ second = 0;
+ }
+ dma_hw->ch[dma->channel[first]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS;
+ dma_hw->ch[dma->channel[second]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS;
+}
+
+bool audio_dma_get_paused(audio_dma_t* dma) {
+ if (dma->channel[0] >= AUDIO_DMA_CHANNEL_COUNT) {
+ return false;
+ }
+ uint32_t control = dma_hw->ch[dma->channel[0]].ctrl_trig;
+
+ return (control & DMA_CH0_CTRL_TRIG_EN_BITS) == 0;
+}
+
+void audio_dma_init(audio_dma_t* dma) {
+ dma->first_buffer = NULL;
+ dma->second_buffer = NULL;
+}
+
+void audio_dma_deinit(audio_dma_t* dma) {
+ m_free(dma->first_buffer);
+ dma->first_buffer = NULL;
+
+ m_free(dma->second_buffer);
+ dma->second_buffer = NULL;
+}
+
+bool audio_dma_get_playing(audio_dma_t* dma) {
+ if (dma->channel[0] == NUM_DMA_CHANNELS) {
+ return false;
+ }
+ if (!dma_channel_is_busy(dma->channel[0]) &&
+ !dma_channel_is_busy(dma->channel[1])) {
+ audio_dma_stop(dma);
+ return false;
+ }
+
+ return true;
+}
+
+// WARN(tannewt): DO NOT print from here, or anything it calls. Printing calls
+// background tasks such as this and causes a stack overflow.
+STATIC void dma_callback_fun(void *arg) {
+ audio_dma_t* dma = arg;
+ if (dma == NULL) {
+ return;
+ }
+
+ audio_dma_load_next_block(dma);
+}
+
+void isr_dma_0(void) {
+ for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) {
+ uint32_t mask = 1 << i;
+ if ((dma_hw->intr & mask) != 0 && MP_STATE_PORT(playing_audio)[i] != NULL) {
+ audio_dma_t* dma = MP_STATE_PORT(playing_audio)[i];
+ background_callback_add(&dma->callback, dma_callback_fun, (void*)dma);
+ dma_hw->ints0 = mask;
+ }
+ }
+}
+
+#endif
diff --git a/ports/raspberrypi/audio_dma.h b/ports/raspberrypi/audio_dma.h
new file mode 100644
index 000000000..1f739ff73
--- /dev/null
+++ b/ports/raspberrypi/audio_dma.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H
+#define MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H
+
+#include "py/obj.h"
+#include "supervisor/background_callback.h"
+
+#include "src/rp2_common/hardware_dma/include/hardware/dma.h"
+
+typedef struct {
+ mp_obj_t sample;
+ uint8_t channel[2];
+ uint8_t audio_channel;
+ uint8_t output_size;
+ uint8_t sample_spacing;
+ bool loop;
+ bool single_channel;
+ bool signed_to_unsigned;
+ bool unsigned_to_signed;
+ bool output_signed;
+ bool first_channel_free;
+ bool first_buffer_free;
+ uint8_t output_resolution; // in bits
+ uint8_t sample_resolution; // in bits
+ uint8_t* first_buffer;
+ uint8_t* second_buffer;
+ background_callback_t callback;
+} audio_dma_t;
+
+typedef enum {
+ AUDIO_DMA_OK,
+ AUDIO_DMA_DMA_BUSY,
+ AUDIO_DMA_MEMORY_ERROR,
+} audio_dma_result;
+
+
+void audio_dma_init(audio_dma_t* dma);
+void audio_dma_deinit(audio_dma_t* dma);
+void audio_dma_reset(void);
+
+// This sets everything up but doesn't start the timer.
+// Sample is the python object for the sample to play.
+// loop is true if we should loop the sample.
+// single_channel is true if we only output a single channel. When false, all channels will be
+// output.
+// audio_channel is the index of the channel to dma. single_channel must be false in this case.
+// output_signed is true if the dma'd data should be signed. False and it will be unsigned.
+// output_register_address is the address to copy data to.
+// dma_trigger_source is the DMA trigger source which cause another copy
+audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
+ mp_obj_t sample,
+ bool loop,
+ bool single_channel,
+ uint8_t audio_channel,
+ bool output_signed,
+ uint8_t output_resolution,
+ uint32_t output_register_address,
+ uint8_t dma_trigger_source);
+
+void audio_dma_stop(audio_dma_t* dma);
+bool audio_dma_get_playing(audio_dma_t* dma);
+void audio_dma_pause(audio_dma_t* dma);
+void audio_dma_resume(audio_dma_t* dma);
+bool audio_dma_get_paused(audio_dma_t* dma);
+
+#endif // MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H
diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.c b/ports/raspberrypi/bindings/rp2pio/StateMachine.c
index 0f6f84a56..34633949e 100644
--- a/ports/raspberrypi/bindings/rp2pio/StateMachine.c
+++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.c
@@ -189,7 +189,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
if (bufinfo.len % 2 != 0) {
mp_raise_ValueError(translate("Program size invalid"));
}
- if (bufinfo.len > 32) {
+ if (bufinfo.len > 64) {
mp_raise_ValueError(translate("Program too large"));
}
diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.h
index 6a2d063d7..f491a7769 100644
--- a/ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.h
+++ b/ports/raspberrypi/boards/adafruit_feather_rp2040/mpconfigboard.h
@@ -12,3 +12,6 @@
// #define DEFAULT_UART_BUS_RX (&pin_PA11)
// #define DEFAULT_UART_BUS_TX (&pin_PA10)
+
+// Flash chip is GD25Q32 connected over QSPI
+#define TOTAL_FLASH_SIZE (4 * 1024 * 1024)
diff --git a/ports/raspberrypi/boards/pimoroni_keybow2040/board.c b/ports/raspberrypi/boards/pimoroni_keybow2040/board.c
new file mode 100644
index 000000000..67486d4c2
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_keybow2040/board.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 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/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.h
new file mode 100644
index 000000000..234be27c2
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.h
@@ -0,0 +1,41 @@
+#define MICROPY_HW_BOARD_NAME "Pimoroni Keybow 2040"
+#define MICROPY_HW_MCU_NAME "rp2040"
+
+#define MICROPY_HW_SW0 (&pin_GPIO21)
+#define MICROPY_HW_SW1 (&pin_GPIO20)
+#define MICROPY_HW_SW2 (&pin_GPIO19)
+#define MICROPY_HW_SW3 (&pin_GPIO18)
+#define MICROPY_HW_SW4 (&pin_GPIO17)
+#define MICROPY_HW_SW5 (&pin_GPIO16)
+#define MICROPY_HW_SW6 (&pin_GPIO15)
+#define MICROPY_HW_SW7 (&pin_GPIO14)
+#define MICROPY_HW_SW8 (&pin_GPIO13)
+#define MICROPY_HW_SW9 (&pin_GPIO12)
+#define MICROPY_HW_SW10 (&pin_GPIO11)
+#define MICROPY_HW_SW11 (&pin_GPIO10)
+#define MICROPY_HW_SW12 (&pin_GPIO9)
+#define MICROPY_HW_SW13 (&pin_GPIO8)
+#define MICROPY_HW_SW14 (&pin_GPIO7)
+#define MICROPY_HW_SW15 (&pin_GPIO6)
+
+#define MICROPY_HW_USER_SW (&pin_GPIO23)
+
+#define MICROPY_HW_I2C_INT (&pin_GPIO3)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5)
+#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4)
+
+#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
+#define DEFAULT_UART_BUS_TX (&pin_GPIO0)
+
+#define TOTAL_FLASH_SIZE (2 * 1024 * 1024)
+
+// These pins are unconnected
+#define IGNORE_PIN_GPIO2 1
+#define IGNORE_PIN_GPIO22 1
+#define IGNORE_PIN_GPIO24 1
+#define IGNORE_PIN_GPIO25 1
+#define IGNORE_PIN_GPIO26 1
+#define IGNORE_PIN_GPIO27 1
+#define IGNORE_PIN_GPIO28 1
+#define IGNORE_PIN_GPIO29 1
diff --git a/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk
new file mode 100644
index 000000000..cf7429431
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk
@@ -0,0 +1,11 @@
+USB_VID = 0x16D0
+USB_PID = 0x08C6
+USB_PRODUCT = "Keybow 2040"
+USB_MANUFACTURER = "Pimoroni"
+
+CHIP_VARIANT = RP2040
+CHIP_FAMILY = rp2
+
+INTERNAL_FLASH_FILESYSTEM = 1
+
+CIRCUITPY__EVE = 1
diff --git a/ports/raspberrypi/boards/pimoroni_keybow2040/pins.c b/ports/raspberrypi/boards/pimoroni_keybow2040/pins.c
new file mode 100644
index 000000000..c4cdb7b29
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_keybow2040/pins.c
@@ -0,0 +1,36 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) },
+ { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) },
+ { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
+
+ { MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) },
+
+ { MP_ROM_QSTR(MP_QSTR_SW0), MP_ROM_PTR(&pin_GPIO21) },
+ { MP_ROM_QSTR(MP_QSTR_SW1), MP_ROM_PTR(&pin_GPIO20) },
+ { MP_ROM_QSTR(MP_QSTR_SW2), MP_ROM_PTR(&pin_GPIO19) },
+ { MP_ROM_QSTR(MP_QSTR_SW3), MP_ROM_PTR(&pin_GPIO18) },
+ { MP_ROM_QSTR(MP_QSTR_SW4), MP_ROM_PTR(&pin_GPIO17) },
+ { MP_ROM_QSTR(MP_QSTR_SW5), MP_ROM_PTR(&pin_GPIO16) },
+ { MP_ROM_QSTR(MP_QSTR_SW6), MP_ROM_PTR(&pin_GPIO15) },
+ { MP_ROM_QSTR(MP_QSTR_SW7), MP_ROM_PTR(&pin_GPIO14) },
+ { MP_ROM_QSTR(MP_QSTR_SW8), MP_ROM_PTR(&pin_GPIO13) },
+ { MP_ROM_QSTR(MP_QSTR_SW9), MP_ROM_PTR(&pin_GPIO12) },
+ { MP_ROM_QSTR(MP_QSTR_SW10), MP_ROM_PTR(&pin_GPIO11) },
+ { MP_ROM_QSTR(MP_QSTR_SW11), MP_ROM_PTR(&pin_GPIO10) },
+ { MP_ROM_QSTR(MP_QSTR_SW12), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_SW13), MP_ROM_PTR(&pin_GPIO8) },
+ { MP_ROM_QSTR(MP_QSTR_SW14), MP_ROM_PTR(&pin_GPIO7) },
+ { MP_ROM_QSTR(MP_QSTR_SW15), MP_ROM_PTR(&pin_GPIO6) },
+
+ { MP_ROM_QSTR(MP_QSTR_USER_SW), MP_ROM_PTR(&pin_GPIO23) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/raspberrypi/boards/pimoroni_picosystem/board.c b/ports/raspberrypi/boards/pimoroni_picosystem/board.c
new file mode 100644
index 000000000..67486d4c2
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_picosystem/board.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 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/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.h
new file mode 100644
index 000000000..a1395f17d
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.h
@@ -0,0 +1,49 @@
+#define MICROPY_HW_BOARD_NAME "Pimoroni PicoSystem"
+#define MICROPY_HW_MCU_NAME "rp2040"
+
+#define MICROPY_HW_VBUS_DETECT (&pin_GPIO2)
+
+#define MICROPY_HW_LCD_RESET (&pin_GPIO4)
+#define MICROPY_HW_LCD_CS (&pin_GPIO5)
+#define MICROPY_HW_LCD_SCLK (&pin_GPIO6)
+#define MICROPY_HW_LCD_MOSI (&pin_GPIO7)
+#define MICROPY_HW_LCD_VSYNC (&pin_GPIO8)
+#define MICROPY_HW_LCD_DS (&pin_GPIO9)
+
+#define MICROPY_HW_AUDIO (&pin_GPIO11)
+#define MICROPY_HW_BACKLIGHT (&pin_GPIO12)
+#define MICROPY_HW_VBUS_DETECT (&pin_GPIO2)
+
+#define MICROPY_HW_LED_G (&pin_GPIO13)
+#define MICROPY_HW_LED_R (&pin_GPIO14)
+#define MICROPY_HW_LED_B (&pin_GPIO15)
+
+#define MICROPY_HW_SW_Y (&pin_GPIO16)
+#define MICROPY_HW_SW_X (&pin_GPIO17)
+#define MICROPY_HW_SW_A (&pin_GPIO18)
+#define MICROPY_HW_SW_B (&pin_GPIO19)
+
+#define MICROPY_HW_SW_DOWN (&pin_GPIO20)
+#define MICROPY_HW_SW_RIGHT (&pin_GPIO21)
+#define MICROPY_HW_SW_LEFT (&pin_GPIO22)
+#define MICROPY_HW_SW_UP (&pin_GPIO23)
+
+#define MICROPY_HW_CHARGE_STAT (&pin_GPIO24)
+
+#define MICROPY_HW_BAT_SENSE (&pin_GPIO26)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6)
+#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO7)
+
+#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
+#define DEFAULT_UART_BUS_TX (&pin_GPIO0)
+
+#define TOTAL_FLASH_SIZE (16 * 1024 * 1024)
+
+// These pins are unconnected
+#define IGNORE_PIN_GPIO3 1
+#define IGNORE_PIN_GPIO10 1
+#define IGNORE_PIN_GPIO25 1
+#define IGNORE_PIN_GPIO27 1
+#define IGNORE_PIN_GPIO28 1
+#define IGNORE_PIN_GPIO29 1
diff --git a/ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.mk
new file mode 100644
index 000000000..c9d22549b
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_picosystem/mpconfigboard.mk
@@ -0,0 +1,11 @@
+USB_VID = 0x16D0
+USB_PID = 0x08C8
+USB_PRODUCT = "PicoSystem"
+USB_MANUFACTURER = "Pimoroni"
+
+CHIP_VARIANT = RP2040
+CHIP_FAMILY = rp2
+
+INTERNAL_FLASH_FILESYSTEM = 1
+
+CIRCUITPY__EVE = 1
diff --git a/ports/raspberrypi/boards/pimoroni_picosystem/pins.c b/ports/raspberrypi/boards/pimoroni_picosystem/pins.c
new file mode 100644
index 000000000..30aafacba
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_picosystem/pins.c
@@ -0,0 +1,43 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) },
+ { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) },
+ { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
+
+ { MP_ROM_QSTR(MP_QSTR_VBUS_DETECT), MP_ROM_PTR(&pin_GPIO2) },
+
+ { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_SCLK), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO7) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_VSYNC), MP_ROM_PTR(&pin_GPIO8) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO9) },
+
+ { MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pin_GPIO11) },
+ { MP_ROM_QSTR(MP_QSTR_BACKLIGHT), MP_ROM_PTR(&pin_GPIO12) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO13) },
+ { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO14) },
+ { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO15) },
+
+ { MP_ROM_QSTR(MP_QSTR_SW_Y), MP_ROM_PTR(&pin_GPIO16) },
+ { MP_ROM_QSTR(MP_QSTR_SW_X), MP_ROM_PTR(&pin_GPIO17) },
+ { MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO18) },
+ { MP_ROM_QSTR(MP_QSTR_SW_B), MP_ROM_PTR(&pin_GPIO19) },
+
+ { MP_ROM_QSTR(MP_QSTR_SW_DOWN), MP_ROM_PTR(&pin_GPIO20) },
+ { MP_ROM_QSTR(MP_QSTR_SW_RIGHT), MP_ROM_PTR(&pin_GPIO21) },
+ { MP_ROM_QSTR(MP_QSTR_SW_LEFT), MP_ROM_PTR(&pin_GPIO22) },
+ { MP_ROM_QSTR(MP_QSTR_SW_UP), MP_ROM_PTR(&pin_GPIO23) },
+
+ { MP_ROM_QSTR(MP_QSTR_CHARGE_STAT), MP_ROM_PTR(&pin_GPIO24) },
+
+ { MP_ROM_QSTR(MP_QSTR_BAT_SENSE), MP_ROM_PTR(&pin_GPIO26) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/raspberrypi/boards/pimoroni_tiny2040/board.c b/ports/raspberrypi/boards/pimoroni_tiny2040/board.c
new file mode 100644
index 000000000..67486d4c2
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_tiny2040/board.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 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/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.h
new file mode 100644
index 000000000..965dd0e04
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.h
@@ -0,0 +1,26 @@
+#define MICROPY_HW_BOARD_NAME "Pimoroni Tiny 2040"
+#define MICROPY_HW_MCU_NAME "rp2040"
+
+#define MICROPY_HW_LED_R (&pin_GPIO18)
+#define MICROPY_HW_LED_G (&pin_GPIO19)
+#define MICROPY_HW_LED_B (&pin_GPIO20)
+
+#define MICROPY_HW_USER_SW (&pin_GPIO23)
+
+#define TOTAL_FLASH_SIZE (8 * 1024 * 1024)
+
+// These pins are unconnected
+#define IGNORE_PIN_GPIO8 1
+#define IGNORE_PIN_GPIO9 1
+#define IGNORE_PIN_GPIO10 1
+#define IGNORE_PIN_GPIO11 1
+#define IGNORE_PIN_GPIO12 1
+#define IGNORE_PIN_GPIO13 1
+#define IGNORE_PIN_GPIO14 1
+#define IGNORE_PIN_GPIO15 1
+#define IGNORE_PIN_GPIO16 1
+#define IGNORE_PIN_GPIO17 1
+#define IGNORE_PIN_GPIO21 1
+#define IGNORE_PIN_GPIO22 1
+#define IGNORE_PIN_GPIO24 1
+#define IGNORE_PIN_GPIO25 1
diff --git a/ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.mk
new file mode 100644
index 000000000..75fe36a29
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_tiny2040/mpconfigboard.mk
@@ -0,0 +1,11 @@
+USB_VID = 0x16D0
+USB_PID = 0x08C7
+USB_PRODUCT = "Tiny 2040"
+USB_MANUFACTURER = "Pimoroni"
+
+CHIP_VARIANT = RP2040
+CHIP_FAMILY = rp2
+
+INTERNAL_FLASH_FILESYSTEM = 1
+
+CIRCUITPY__EVE = 1
diff --git a/ports/raspberrypi/boards/pimoroni_tiny2040/pins.c b/ports/raspberrypi/boards/pimoroni_tiny2040/pins.c
new file mode 100644
index 000000000..de79ee732
--- /dev/null
+++ b/ports/raspberrypi/boards/pimoroni_tiny2040/pins.c
@@ -0,0 +1,39 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
+ { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
+ { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) },
+ { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) },
+ { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO18) },
+ { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO19) },
+ { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO20) },
+
+ { MP_ROM_QSTR(MP_QSTR_USER_SW), MP_ROM_PTR(&pin_GPIO23) },
+
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
+ { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) },
+ { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
+ { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) },
+ { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) },
+
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
+ { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) },
+ { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
+ { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) },
+ { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/board.c b/ports/raspberrypi/boards/qtpy_rp2040/board.c
new file mode 100644
index 000000000..332145ab8
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/board.c
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 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 "shared-bindings/microcontroller/Pin.h"
+#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
+
+void board_init(void) {
+ common_hal_never_reset_pin(&pin_GPIO11);
+ gpio_init(11);
+ gpio_set_dir(11, GPIO_OUT);
+ gpio_put(11, true);
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h
new file mode 100644
index 000000000..3f4778457
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h
@@ -0,0 +1,17 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit QTPy RP2040"
+#define MICROPY_HW_MCU_NAME "rp2040"
+
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO12)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_GPIO25)
+#define DEFAULT_I2C_BUS_SDA (&pin_GPIO24)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6)
+#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3)
+#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4)
+
+// #define DEFAULT_UART_BUS_RX (&pin_PA11)
+// #define DEFAULT_UART_BUS_TX (&pin_PA10)
+
+// Flash chip is GD25Q32 connected over QSPI
+#define TOTAL_FLASH_SIZE (4 * 1024 * 1024)
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk
new file mode 100644
index 000000000..5e454e312
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk
@@ -0,0 +1,9 @@
+USB_VID = 0x239A
+USB_PID = 0x80F8
+USB_PRODUCT = "QT Py RP2040"
+USB_MANUFACTURER = "Adafruit"
+
+CHIP_VARIANT = RP2040
+CHIP_FAMILY = rp2
+
+INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/pins.c b/ports/raspberrypi/boards/qtpy_rp2040/pins.c
new file mode 100644
index 000000000..e0ebd0032
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/pins.c
@@ -0,0 +1,49 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO29) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO29) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO28) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO28) },
+
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO27) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO27) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO26) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO27) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO24) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO24) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO25) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO25) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO20) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO20) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO9) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO6) },
+
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO4) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO3) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO12) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO11) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_GPIO22) },
+ { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO23) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.h b/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.h
index 4b0a22028..a506fec49 100644
--- a/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.h
+++ b/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.h
@@ -13,3 +13,6 @@
// #define DEFAULT_UART_BUS_RX (&pin_PA11)
// #define DEFAULT_UART_BUS_TX (&pin_PA10)
+
+// Flash chip is W25Q16JVUXIQ connected over QSPI
+#define TOTAL_FLASH_SIZE (2 * 1024 * 1024)
diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
new file mode 100644
index 000000000..57605a1fb
--- /dev/null
+++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
@@ -0,0 +1,235 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 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 "common-hal/audiopwmio/PWMAudioOut.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "extmod/vfs_fat.h"
+#include "py/gc.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "shared-bindings/pwmio/PWMOut.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Processor.h"
+#include "supervisor/shared/tick.h"
+#include "supervisor/shared/translate.h"
+
+#include "src/rp2040/hardware_structs/include/hardware/structs/dma.h"
+#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
+
+#define NUM_DMA_TIMERS 4
+
+void audiopwmout_reset() {
+ for (size_t i = 0; i < NUM_DMA_TIMERS; i++) {
+ dma_hw->timer[i] = 0;
+ }
+}
+
+// Caller validates that pins are free.
+void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t quiescent_value) {
+ if (left_channel != NULL && right_channel != NULL) {
+ if (pwm_gpio_to_slice_num(left_channel->number) != pwm_gpio_to_slice_num(right_channel->number)) {
+ mp_raise_ValueError(translate("Pins must share PWM slice"));
+ }
+ if (pwm_gpio_to_channel(left_channel->number) != 0) {
+ mp_raise_ValueError(translate("Stereo left must be on PWM channel A"));
+ }
+ if (pwm_gpio_to_channel(right_channel->number) != 1) {
+ mp_raise_ValueError(translate("Stereo right must be on PWM channel B"));
+ }
+ }
+
+ // Typically pwmout doesn't let us change frequency with two objects on the
+ // same PWM slice. However, we have private access to it so we can do what
+ // we want. ;-) We mark ourselves variable only if we're a mono output to
+ // prevent other PWM use on the other channel. If stereo, we say fixed
+ // frequency so we can allocate with ourselves.
+ bool mono = right_channel == NULL;
+
+ // We don't actually know our frequency yet so just pick one that shouldn't
+ // match anyone else. (We'll only know the frequency once we play something
+ // back.)
+ uint32_t frequency = 12500;
+
+ // Make sure the PWMOut's are "deinited" by default.
+ self->left_pwm.pin = NULL;
+ self->right_pwm.pin = NULL;
+
+ pwmout_result_t result = common_hal_pwmio_pwmout_construct(&self->left_pwm,
+ left_channel, 0, frequency, mono);
+ if (result == PWMOUT_OK && right_channel != NULL) {
+ result = common_hal_pwmio_pwmout_construct(&self->right_pwm,
+ right_channel, 0, frequency, false);
+ if (result != PWMOUT_OK) {
+ common_hal_pwmio_pwmout_deinit(&self->left_pwm);
+ }
+ }
+ if (result != PWMOUT_OK) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+
+ claim_pin(left_channel);
+ if (right_channel != NULL) {
+ claim_pin(right_channel);
+ }
+
+ audio_dma_init(&self->dma);
+
+ self->quiescent_value = quiescent_value;
+}
+
+bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self) {
+ return common_hal_pwmio_pwmout_deinited(&self->left_pwm);
+}
+
+void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self) {
+ if (common_hal_audiopwmio_pwmaudioout_deinited(self)) {
+ return;
+ }
+ if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ }
+
+ // TODO: ramp the pwm down from quiescent value to 0
+ common_hal_pwmio_pwmout_deinit(&self->left_pwm);
+ common_hal_pwmio_pwmout_deinit(&self->right_pwm);
+
+ audio_dma_deinit(&self->dma);
+}
+
+void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop) {
+ if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ }
+
+ // TODO: Share pacing timers based on frequency.
+ size_t pacing_timer = NUM_DMA_TIMERS;
+ for (size_t i = 0; i < NUM_DMA_TIMERS; i++) {
+ if (dma_hw->timer[i] == 0) {
+ pacing_timer = i;
+ }
+ break;
+ }
+ if (pacing_timer == NUM_DMA_TIMERS) {
+ mp_raise_RuntimeError(translate("No DMA pacing timer found"));
+ }
+ uint32_t tx_register = (uint32_t) &pwm_hw->slice[self->left_pwm.slice].cc;
+ if (common_hal_pwmio_pwmout_deinited(&self->right_pwm)) {
+ // Shift the destination if we are outputting to the second PWM channel.
+ tx_register += self->left_pwm.channel * sizeof(uint16_t);
+ }
+
+ pwmio_pwmout_set_top(&self->left_pwm, 1023);
+
+ audio_dma_result result = audio_dma_setup_playback(
+ &self->dma,
+ sample,
+ loop,
+ false, // single channel
+ 0, // audio channel
+ false, // output signed
+ 10,
+ (uint32_t) tx_register, // output register
+ 0x3b + pacing_timer); // data request line
+
+ if (result == AUDIO_DMA_DMA_BUSY) {
+ // common_hal_audiobusio_i2sout_stop(self);
+ mp_raise_RuntimeError(translate("No DMA channel found"));
+ } else if (result == AUDIO_DMA_MEMORY_ERROR) {
+ // common_hal_audiobusio_i2sout_stop(self);
+ mp_raise_RuntimeError(translate("Unable to allocate buffers for signed conversion"));
+ }
+
+ // OK! We got all of the resources we need and dma is ready.
+ self->pacing_timer = pacing_timer;
+
+ // Playback with two independent clocks. One is the sample rate which
+ // determines when we push a new sample to the PWM slice. The second is the
+ // PWM frequency itself.
+
+ // Determine the DMA divisor. The RP2040 has four pacing timers we can use
+ // to trigger the DMA. Each has a 16 bit fractional divisor system clock * X / Y where X and Y
+ // are 16-bit.
+
+ uint32_t sample_rate = audiosample_sample_rate(sample);
+ uint32_t system_clock = common_hal_mcu_processor_get_frequency();
+ uint32_t best_numerator = 0;
+ uint32_t best_denominator = 0;
+ uint32_t best_error = system_clock;
+
+ for (uint32_t denominator = 0xffff; denominator > 0; denominator--) {
+ uint32_t numerator = (denominator * sample_rate) / system_clock;
+ uint32_t remainder = (denominator * sample_rate) % system_clock;
+ if (remainder > (system_clock / 2)) {
+ numerator += 1;
+ remainder = system_clock - remainder;
+ }
+ if (remainder < best_error) {
+ best_denominator = denominator;
+ best_numerator = numerator;
+ best_error = remainder;
+ // Stop early if we can't do better.
+ if (remainder == 0) {
+ break;
+ }
+ }
+ }
+
+ dma_hw->timer[pacing_timer] = best_numerator << 16 | best_denominator;
+}
+
+void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self) {
+ dma_hw->timer[self->pacing_timer] = 0;
+ self->pacing_timer = NUM_DMA_TIMERS;
+
+ audio_dma_stop(&self->dma);
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self) {
+ bool playing = audio_dma_get_playing(&self->dma);
+ if (!playing && self->pacing_timer < NUM_DMA_TIMERS) {
+ dma_hw->timer[self->pacing_timer] = 0;
+ self->pacing_timer = NUM_DMA_TIMERS;
+ }
+ return playing;
+}
+
+void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self) {
+ audio_dma_pause(&self->dma);
+}
+
+void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self) {
+ audio_dma_resume(&self->dma);
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self) {
+ return audio_dma_get_paused(&self->dma);
+}
diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h
new file mode 100644
index 000000000..2b43b8354
--- /dev/null
+++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_AUDIOPWMIO_PWMAUDIOOUT_H
+#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_AUDIOPWMIO_PWMAUDIOOUT_H
+
+#include "common-hal/pwmio/PWMOut.h"
+
+#include "audio_dma.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ pwmio_pwmout_obj_t left_pwm;
+ pwmio_pwmout_obj_t right_pwm;
+ audio_dma_t dma;
+ uint16_t quiescent_value;
+ uint8_t pacing_timer;
+} audiopwmio_pwmaudioout_obj_t;
+
+void audiopwmout_reset(void);
+
+void audiopwmout_background(void);
+
+#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_AUDIOPWMIO_PWMAUDIOOUT_H
diff --git a/ports/raspberrypi/common-hal/audiopwmio/__init__.c b/ports/raspberrypi/common-hal/audiopwmio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/raspberrypi/common-hal/audiopwmio/__init__.c
diff --git a/ports/raspberrypi/common-hal/neopixel_write/__init__.c b/ports/raspberrypi/common-hal/neopixel_write/__init__.c
index 10462b5a3..561d438e2 100644
--- a/ports/raspberrypi/common-hal/neopixel_write/__init__.c
+++ b/ports/raspberrypi/common-hal/neopixel_write/__init__.c
@@ -29,6 +29,7 @@
#include "bindings/rp2pio/StateMachine.h"
#include "common-hal/rp2pio/StateMachine.h"
#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
#include "supervisor/port.h"
@@ -89,7 +90,11 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
// Use a private deinit of the state machine that doesn't reset the pin.
rp2pio_statemachine_deinit(&state_machine, true);
+
+ // Reset the pin and release it from the PIO
gpio_init(digitalinout->pin->number);
+ common_hal_digitalio_digitalinout_switch_to_output((digitalio_digitalinout_obj_t*)digitalinout, false, DRIVE_MODE_PUSH_PULL);
+
// Update the next start.
next_start_raw_ticks = port_get_raw_ticks(NULL) + 1;
}
diff --git a/ports/raspberrypi/common-hal/os/__init__.c b/ports/raspberrypi/common-hal/os/__init__.c
index dcbd06e93..0df7653d3 100644
--- a/ports/raspberrypi/common-hal/os/__init__.c
+++ b/ports/raspberrypi/common-hal/os/__init__.c
@@ -30,6 +30,11 @@
#include "py/objtuple.h"
#include "py/qstr.h"
+#include "extmod/crypto-algorithms/sha256.h"
+
+#include "hardware/structs/rosc.h"
+
+#include <string.h>
STATIC const qstr os_uname_info_fields[] = {
MP_QSTR_sysname, MP_QSTR_nodename,
@@ -57,6 +62,64 @@ mp_obj_t common_hal_os_uname(void) {
return (mp_obj_t)&os_uname_info_obj;
}
+// NIST Special Publication 800-90B (draft) recommends several extractors,
+// including the SHA hash family and states that if the amount of entropy input
+// is twice the number of bits output from them, that output can be considered
+// essentially fully random. If every RANDOM_SAFETY_MARGIN bits from
+// `rosc_hw->randombit` have at least 1 bit of entropy, then this criterion is met.
+//
+// This works by seeding the `random_state` with plenty of random bits (SHA256
+// as entropy harvesting function), then using that state it as a counter input
+// (SHA256 as a CSPRNG), re-seeding at least every 256 blocks (8kB).
+//
+// In practice, `PractRand` doesn't detect any gross problems with the output
+// random numbers on samples of 1 to 8 megabytes, no matter the setting of
+// RANDOM_SAFETY_MARGIN. (it does detect "unusual" results from time to time,
+// as it will with any RNG)
+#define RANDOM_SAFETY_MARGIN (4)
+
+static BYTE random_state[SHA256_BLOCK_SIZE];
+static void seed_random_bits(BYTE out[SHA256_BLOCK_SIZE]) {
+ CRYAL_SHA256_CTX context;
+ sha256_init(&context);
+ for (int i=0; i<2*RANDOM_SAFETY_MARGIN; i++) {
+ for(int j=0; j<SHA256_BLOCK_SIZE; j++) {
+ out[j] = rosc_hw->randombit & 1;
+ for(int k=0; k<8; k++) {
+ out[j] = (out[j] << 1) ^ (rosc_hw->randombit & 1);
+ }
+ }
+ sha256_update(&context, out, SHA256_BLOCK_SIZE);
+ }
+ sha256_final(&context, out);
+}
+
+static void get_random_bits(BYTE out[SHA256_BLOCK_SIZE]) {
+ if (!random_state[0]++) {
+ seed_random_bits(random_state);
+ }
+ CRYAL_SHA256_CTX context;
+ sha256_init(&context);
+ sha256_update(&context, random_state, SHA256_BLOCK_SIZE);
+ sha256_final(&context, out);
+}
+
bool common_hal_os_urandom(uint8_t* buffer, uint32_t length) {
- return false;
+#define ROSC_POWER_SAVE (1) // assume ROSC is not necessarily active all the time
+#if ROSC_POWER_SAVE
+ uint32_t old_rosc_ctrl = rosc_hw->ctrl;
+ rosc_hw->ctrl = (old_rosc_ctrl & ~ROSC_CTRL_ENABLE_BITS) | (ROSC_CTRL_ENABLE_VALUE_ENABLE << 12);
+#endif
+ while (length) {
+ size_t n = MIN(length, SHA256_BLOCK_SIZE);
+ BYTE sha_buf[SHA256_BLOCK_SIZE];
+ get_random_bits(sha_buf);
+ memcpy(buffer, sha_buf, n);
+ buffer += n;
+ length -= n;
+ }
+#if ROSC_POWER_SAVE
+ rosc_hw->ctrl = old_rosc_ctrl;
+#endif
+ return true;
}
diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c
index 567ec5ef5..00b461880 100644
--- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c
+++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c
@@ -39,12 +39,24 @@
#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
uint32_t target_slice_frequencies[NUM_PWM_SLICES];
-uint32_t slice_fixed_frequency;
+uint32_t slice_variable_frequency;
#define CHANNELS_PER_SLICE 2
static uint32_t channel_use;
static uint32_t never_reset_channel;
+// Per the RP2040 datasheet:
+//
+// "A CC value of 0 will produce a 0% output, i.e. the output signal
+// is always low. A CC value of TOP + 1 (i.e. equal to the period, in
+// non-phase-correct mode) will produce a 100% output. For example, if
+// TOP is programmed to 254, the counter will have a period of 255
+// cycles, and CC values in the range of 0 to 255 inclusive will
+// produce duty cycles in the range 0% to 100% inclusive."
+//
+// So 65534 should be the maximum top value, and we'll set CC to be TOP+1 as appropriate.
+#define MAX_TOP 65534
+
static uint32_t _mask(uint8_t slice, uint8_t channel) {
return 1 << (slice * CHANNELS_PER_SLICE + channel);
}
@@ -76,7 +88,7 @@ void pwmout_reset(void) {
}
pwm_set_enabled(slice, false);
target_slice_frequencies[slice] = 0;
- slice_fixed_frequency &= ~(1 << slice);
+ slice_variable_frequency &= ~(1 << slice);
}
}
@@ -107,8 +119,8 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
if (variable_frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
- // If the other user wants to change frequency then we can't share either.
- if ((slice_fixed_frequency & (1 << slice)) != 0) {
+ // If the other user wants a variable frequency then we can't share either.
+ if ((slice_variable_frequency & (1 << slice)) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
// If we're both fixed frequency but we don't match target frequencies then we can't share.
@@ -118,9 +130,10 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
}
self->slice = slice;
self->channel = channel;
+
channel_use |= channel_use_mask;
- if (!variable_frequency) {
- slice_fixed_frequency |= 1 << slice;
+ if (variable_frequency) {
+ slice_variable_frequency |= 1 << slice;
}
if (target_slice_frequencies[slice] != frequency) {
@@ -153,7 +166,7 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (self->slice * CHANNELS_PER_SLICE + self->channel);
if ((channel_use & slice_mask) == 0) {
target_slice_frequencies[self->slice] = 0;
- slice_fixed_frequency &= ~(1 << self->slice);
+ slice_variable_frequency &= ~(1 << self->slice);
pwm_set_enabled(self->slice, false);
}
@@ -163,14 +176,30 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t* self, uint16_t duty) {
self->duty_cycle = duty;
- uint16_t actual_duty = duty * self->top / ((1 << 16) - 1);
- pwm_set_chan_level(self->slice, self->channel, actual_duty);
+ // Do arithmetic in 32 bits to prevent overflow.
+ uint16_t compare_count;
+ if (duty == 65535) {
+ // Ensure that 100% duty cycle is 100% full on and not rounded down,
+ // but do MIN() to keep value in range, just in case.
+ compare_count = MIN(UINT16_MAX, (uint32_t) self->top + 1);
+ } else {
+ compare_count= ((uint32_t) duty * self->top + MAX_TOP / 2) / MAX_TOP;
+ }
+ // compare_count is the CC register value, which should be TOP+1 for 100% duty cycle.
+ pwm_set_chan_level(self->slice, self->channel, compare_count);
}
uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t* self) {
return self->duty_cycle;
}
+void pwmio_pwmout_set_top(pwmio_pwmout_obj_t* self, uint16_t top) {
+ self->actual_frequency = common_hal_mcu_processor_get_frequency() / top;
+ self->top = top;
+ pwm_set_clkdiv_int_frac(self->slice, 1, 0);
+ pwm_set_wrap(self->slice, self->top);
+}
+
void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t frequency) {
if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) {
mp_raise_ValueError(translate("Invalid PWM frequency"));
@@ -179,7 +208,7 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t fr
target_slice_frequencies[self->slice] = frequency;
// For low frequencies use the divider to give us full resolution duty_cycle.
- if (frequency < (common_hal_mcu_processor_get_frequency() / (1 << 16))) {
+ if (frequency <= (common_hal_mcu_processor_get_frequency() / (1 << 16))) {
// Compute the divisor. It's an 8 bit integer and 4 bit fraction. Therefore,
// we compute everything * 16 for the fractional part.
// This is 1 << 12 because 4 bits are the * 16.
@@ -193,16 +222,17 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t fr
if (div16 >= (1 << 12)) {
div16 = (1 << 12) - 1;
}
- self->actual_frequency = frequency16 / div16;
- self->top = 1 << 16;
+ self->actual_frequency = (frequency16 + (div16 / 2)) / div16;
+ self->top = MAX_TOP;
pwm_set_clkdiv_int_frac(self->slice, div16 / 16, div16 % 16);
- pwm_set_wrap(self->slice, self->top - 1);
+ pwm_set_wrap(self->slice, self->top);
} else {
uint32_t top = common_hal_mcu_processor_get_frequency() / frequency;
self->actual_frequency = common_hal_mcu_processor_get_frequency() / top;
- self->top = top;
+ self->top = MIN(MAX_TOP, top);
pwm_set_clkdiv_int_frac(self->slice, 1, 0);
- pwm_set_wrap(self->slice, self->top - 1);
+ // Set TOP register. For 100% duty cycle, CC must be set to TOP+1.
+ pwm_set_wrap(self->slice, self->top);
}
common_hal_pwmio_pwmout_set_duty_cycle(self, self->duty_cycle);
}
diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.h b/ports/raspberrypi/common-hal/pwmio/PWMOut.h
index 50f84777b..0070e188b 100644
--- a/ports/raspberrypi/common-hal/pwmio/PWMOut.h
+++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.h
@@ -39,9 +39,11 @@ typedef struct {
bool variable_frequency;
uint16_t duty_cycle;
uint32_t actual_frequency;
- uint32_t top;
+ uint16_t top;
} pwmio_pwmout_obj_t;
void pwmout_reset(void);
+// Private API for AudioPWMOut.
+void pwmio_pwmout_set_top(pwmio_pwmout_obj_t* self, uint16_t top);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c
index 6510410b0..90c48130e 100644
--- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c
+++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c
@@ -546,15 +546,23 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
size_t tx_remaining = out_len;
while (rx_remaining || tx_remaining) {
- if (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) {
- *tx_destination = *data_out;
- data_out++;
- --tx_remaining;
- }
- if (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) {
- *data_in = (uint8_t) *rx_source;
- data_in++;
- --rx_remaining;
+ for (int i=0; i<32; i++) {
+ bool did_transfer = false;
+ if (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) {
+ *tx_destination = *data_out;
+ data_out++;
+ --tx_remaining;
+ did_transfer = true;
+ }
+ if (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) {
+ *data_in = (uint8_t) *rx_source;
+ data_in++;
+ --rx_remaining;
+ did_transfer = true;
+ }
+ if (!did_transfer) {
+ break;
+ }
}
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
diff --git a/ports/raspberrypi/common-hal/supervisor/Runtime.c b/ports/raspberrypi/common-hal/supervisor/Runtime.c
index 6be38f216..974f26cec 100755
--- a/ports/raspberrypi/common-hal/supervisor/Runtime.c
+++ b/ports/raspberrypi/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
return (bool) serial_bytes_available();
}
diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h
index 77d1ff080..e0d98579d 100644
--- a/ports/raspberrypi/mpconfigport.h
+++ b/ports/raspberrypi/mpconfigport.h
@@ -27,6 +27,8 @@
#ifndef __INCLUDED_MPCONFIGPORT_H
#define __INCLUDED_MPCONFIGPORT_H
+#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
+
#define MICROPY_PY_SYS_PLATFORM "RP2040"
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
@@ -41,6 +43,7 @@
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
+ mp_obj_t playing_audio[NUM_DMA_CHANNELS]; \
CIRCUITPY_COMMON_ROOT_POINTERS;
#endif // __INCLUDED_MPCONFIGPORT_H
diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk
index 8681e2994..ab85c59f9 100644
--- a/ports/raspberrypi/mpconfigport.mk
+++ b/ports/raspberrypi/mpconfigport.mk
@@ -24,11 +24,10 @@ CIRCUITPY_NEOPIXEL_WRITE = 0
endif
CIRCUITPY_FULL_BUILD = 1
+CIRCUITPY_BITOPS = 1
CIRCUITPY_PWMIO = 1
# Things that need to be implemented.
-CIRCUITPY_AUDIOBUSIO = 0 # Use PIO interally for I2S
-CIRCUITPY_AUDIOMP3 = 0
CIRCUITPY_COUNTIO = 0 # Use PWM interally
CIRCUITPY_FREQUENCYIO = 0 # Use PWM interally
CIRCUITPY_I2CPERIPHERAL = 0
@@ -37,11 +36,19 @@ CIRCUITPY_PULSEIO = 0 # Use PIO interally
CIRCUITPY_ROTARYIO = 0 # Use PIO interally
CIRCUITPY_WATCHDOG = 1
-# Things that are unsupported by the hardware.
+# Audio via PWM
CIRCUITPY_AUDIOIO = 0
+CIRCUITPY_AUDIOBUSIO ?= 0 # add this later
+CIRCUITPY_AUDIOCORE ?= 1
+CIRCUITPY_AUDIOPWMIO ?= 1
+
+# These libraries require Cortex M4+ for fancy math instructions.
+CIRCUITPY_AUDIOMIXER ?= 0
+CIRCUITPY_AUDIOMP3 ?= 0
INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 16
+# Number of USB endpoint pairs.
USB_NUM_EP = 8
diff --git a/ports/raspberrypi/supervisor/internal_flash.c b/ports/raspberrypi/supervisor/internal_flash.c
index d333830de..e8ee5cf1a 100644
--- a/ports/raspberrypi/supervisor/internal_flash.c
+++ b/ports/raspberrypi/supervisor/internal_flash.c
@@ -44,10 +44,7 @@
#include "src/rp2_common/hardware_flash/include/hardware/flash.h"
#include "src/common/pico_binary_info/include/pico/binary_info.h"
-#define RESERVED_FLASH 1 * 1024 * 1024
-
-// TODO: Parameterize flash size based on the configured flash.
-#define TOTAL_FLASH_SIZE 2 * 1024 * 1024
+#define RESERVED_FLASH (1 * 1024 * 1024)
// TODO: Split the caching out of supervisor/shared/external_flash so we can use it.
#define SECTOR_SIZE 4096
diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c
index 7c503514a..36d2e8275 100644
--- a/ports/raspberrypi/supervisor/port.c
+++ b/ports/raspberrypi/supervisor/port.c
@@ -32,6 +32,7 @@
#include "bindings/rp2pio/StateMachine.h"
#include "genhdr/mpversion.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
#include "shared-bindings/busio/I2C.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/microcontroller/__init__.h"
@@ -108,6 +109,10 @@ void reset_port(void) {
rtc_reset();
#endif
+ #if CIRCUITPY_AUDIOPWMIO
+ audiopwmout_reset();
+ #endif
+
reset_all_pins();
}
diff --git a/ports/stm/boards/espruino_pico/mpconfigboard.mk b/ports/stm/boards/espruino_pico/mpconfigboard.mk
index 81c3772e7..6d45769f2 100644
--- a/ports/stm/boards/espruino_pico/mpconfigboard.mk
+++ b/ports/stm/boards/espruino_pico/mpconfigboard.mk
@@ -21,5 +21,6 @@ LD_FILE = boards/STM32F401xd_fs.ld
# meantime
CIRCUITPY_ULAB = 0
CIRCUITPY_BUSDEVICE = 0
+CIRCUITPY_FRAMEBUFFERIO = 0
SUPEROPT_GC = 0
diff --git a/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk b/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk
index c99eb1a00..28874f9c6 100644
--- a/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk
+++ b/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.mk
@@ -16,5 +16,3 @@ MCU_PACKAGE = LQFP144
LD_COMMON = boards/common_default.ld
LD_FILE = boards/STM32F412_fs.ld
-
-CIRCUITPY_USB_HID = 1
diff --git a/ports/stm/boards/thunderpack_v12/mpconfigboard.mk b/ports/stm/boards/thunderpack_v12/mpconfigboard.mk
index a2e1da101..4436f04b7 100644
--- a/ports/stm/boards/thunderpack_v12/mpconfigboard.mk
+++ b/ports/stm/boards/thunderpack_v12/mpconfigboard.mk
@@ -2,7 +2,9 @@ USB_VID = 0x239A
USB_PID = 0x8071
USB_PRODUCT = "Thunderpack STM32F411"
USB_MANUFACTURER = "Jeremy Gillick"
-USB_DEVICES = "CDC,MSC"
+
+# Turn off HID devices
+CIRCUITPY_USB_HID = 0
LONGINT_IMPL = NONE
diff --git a/ports/stm/common-hal/busio/I2C.c b/ports/stm/common-hal/busio/I2C.c
index de69da211..7726b5e87 100644
--- a/ports/stm/common-hal/busio/I2C.c
+++ b/ports/stm/common-hal/busio/I2C.c
@@ -61,6 +61,7 @@ STATIC bool never_reset_i2c[MAX_I2C];
#define ALL_CLOCKS 0xFF
STATIC void i2c_clock_enable(uint8_t mask);
STATIC void i2c_clock_disable(uint8_t mask);
+STATIC void i2c_assign_irq(busio_i2c_obj_t *self, I2C_TypeDef * I2Cx);
void i2c_reset(void) {
uint16_t never_reset_mask = 0x00;
@@ -136,6 +137,10 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
i2c_clock_enable(1 << (self->sda->periph_index - 1));
reserved_i2c[self->sda->periph_index - 1] = true;
+ // Create root pointer and assign IRQ
+ MP_STATE_PORT(cpy_i2c_obj_all)[self->sda->periph_index - 1] = self;
+ i2c_assign_irq(self, I2Cx);
+
// Handle the HAL handle differences
#if (CPY_STM32H7 || CPY_STM32F7)
if (frequency == 400000) {
@@ -163,6 +168,13 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
}
common_hal_mcu_pin_claim(sda);
common_hal_mcu_pin_claim(scl);
+
+ self->frame_in_prog = false;
+
+ //start the receive interrupt chain
+ HAL_NVIC_DisableIRQ(self->irq); //prevent handle lock contention
+ HAL_NVIC_SetPriority(self->irq, 1, 0);
+ HAL_NVIC_EnableIRQ(self->irq);
}
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
@@ -229,15 +241,46 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
const uint8_t *data, size_t len, bool transmit_stop_bit) {
- HAL_StatusTypeDef result = HAL_I2C_Master_Transmit(&(self->handle), (uint16_t)(addr << 1),
+ HAL_StatusTypeDef result;
+ if (!transmit_stop_bit) {
+ uint32_t xfer_opt;
+ if (!self->frame_in_prog) {
+ xfer_opt = I2C_FIRST_FRAME;
+ } else {
+ // handle rare possibility of multiple restart writes in a row
+ xfer_opt = I2C_NEXT_FRAME;
+ }
+ result = HAL_I2C_Master_Seq_Transmit_IT(&(self->handle),
+ (uint16_t)(addr << 1), (uint8_t *)data,
+ (uint16_t)len, xfer_opt);
+ while (HAL_I2C_GetState(&(self->handle)) != HAL_I2C_STATE_READY)
+ {
+ RUN_BACKGROUND_TASKS;
+ }
+ self->frame_in_prog = true;
+ } else {
+ result = HAL_I2C_Master_Transmit(&(self->handle), (uint16_t)(addr << 1),
(uint8_t *)data, (uint16_t)len, 500);
+ }
return result == HAL_OK ? 0 : MP_EIO;
}
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
uint8_t *data, size_t len) {
- return HAL_I2C_Master_Receive(&(self->handle), (uint16_t)(addr<<1), data, (uint16_t)len, 500)
+ if (!self->frame_in_prog) {
+ return HAL_I2C_Master_Receive(&(self->handle), (uint16_t)(addr<<1), data, (uint16_t)len, 500)
== HAL_OK ? 0 : MP_EIO;
+ } else {
+ HAL_StatusTypeDef result = HAL_I2C_Master_Seq_Receive_IT(&(self->handle),
+ (uint16_t)(addr << 1), (uint8_t *)data,
+ (uint16_t)len, I2C_LAST_FRAME);
+ while (HAL_I2C_GetState(&(self->handle)) != HAL_I2C_STATE_READY)
+ {
+ RUN_BACKGROUND_TASKS;
+ }
+ self->frame_in_prog = false;
+ return result;
+ }
}
STATIC void i2c_clock_enable(uint8_t mask) {
@@ -294,3 +337,48 @@ STATIC void i2c_clock_disable(uint8_t mask) {
}
#endif
}
+
+STATIC void i2c_assign_irq(busio_i2c_obj_t *self, I2C_TypeDef * I2Cx) {
+ #ifdef I2C1
+ if (I2Cx == I2C1) {
+ self->irq = I2C1_EV_IRQn;
+ }
+ #endif
+ #ifdef I2C2
+ if (I2Cx == I2C2) {
+ self->irq = I2C2_EV_IRQn;
+ }
+ #endif
+ #ifdef I2C3
+ if (I2Cx == I2C3) {
+ self->irq = I2C3_EV_IRQn;
+ }
+ #endif
+ #ifdef I2C4
+ if (I2Cx == I2C4) {
+ self->irq = I2C4_EV_IRQn;
+ }
+ #endif
+}
+
+STATIC void call_hal_irq(int i2c_num) {
+ //Create casted context pointer
+ busio_i2c_obj_t * context = (busio_i2c_obj_t*)MP_STATE_PORT(cpy_i2c_obj_all)[i2c_num - 1];
+ if (context != NULL) {
+ HAL_NVIC_ClearPendingIRQ(context->irq);
+ HAL_I2C_EV_IRQHandler(&context->handle);
+ }
+}
+
+void I2C1_EV_IRQHandler(void) {
+ call_hal_irq(1);
+}
+void I2C2_EV_IRQHandler(void) {
+ call_hal_irq(2);
+}
+void I2C3_EV_IRQHandler(void) {
+ call_hal_irq(3);
+}
+void I2C4_EV_IRQHandler(void) {
+ call_hal_irq(4);
+}
diff --git a/ports/stm/common-hal/busio/I2C.h b/ports/stm/common-hal/busio/I2C.h
index 5ca2854eb..687e6a8c4 100644
--- a/ports/stm/common-hal/busio/I2C.h
+++ b/ports/stm/common-hal/busio/I2C.h
@@ -37,6 +37,8 @@
typedef struct {
mp_obj_base_t base;
I2C_HandleTypeDef handle;
+ IRQn_Type irq;
+ bool frame_in_prog;
bool has_lock;
const mcu_periph_obj_t *scl;
const mcu_periph_obj_t *sda;
diff --git a/ports/stm/common-hal/supervisor/Runtime.c b/ports/stm/common-hal/supervisor/Runtime.c
index ea663f897..974f26cec 100755
--- a/ports/stm/common-hal/supervisor/Runtime.c
+++ b/ports/stm/common-hal/supervisor/Runtime.c
@@ -28,10 +28,10 @@
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
-bool common_hal_get_serial_connected(void) {
+bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool) serial_connected();
}
-bool common_hal_get_serial_bytes_available(void) {
- return (bool) serial_bytes_available();
+bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
+ return (bool) serial_bytes_available();
}
diff --git a/ports/stm/mpconfigport.h b/ports/stm/mpconfigport.h
index 7cdab04f6..3f64e6565 100644
--- a/ports/stm/mpconfigport.h
+++ b/ports/stm/mpconfigport.h
@@ -52,10 +52,14 @@ extern uint8_t _ld_default_stack_size;
#define BOARD_NO_VBUS_SENSE (0)
#endif
-#define MAX_UART 10 //how many UART are implemented
+// Peripheral implementation counts
+#define MAX_UART 10
+#define MAX_I2C 4
+#define MAX_SPI 6
#define MICROPY_PORT_ROOT_POINTERS \
void *cpy_uart_obj_all[MAX_UART]; \
+ void *cpy_i2c_obj_all[MAX_I2C]; \
CIRCUITPY_COMMON_ROOT_POINTERS
#endif // __INCLUDED_MPCONFIGPORT_H
diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk
index bcecaa517..fe257fc50 100644
--- a/ports/stm/mpconfigport.mk
+++ b/ports/stm/mpconfigport.mk
@@ -8,6 +8,7 @@ ifeq ($(MCU_VARIANT),STM32F405xx)
CIRCUITPY_FRAMEBUFFERIO ?= 1
CIRCUITPY_RGBMATRIX ?= 1
CIRCUITPY_SDIOIO ?= 1
+ # Number of USB endpoint pairs.
USB_NUM_EP = 4
endif
@@ -23,6 +24,8 @@ ifeq ($(MCU_SERIES),F4)
CIRCUITPY_RTC ?= 0
CIRCUITPY_USB_MIDI ?= 0
CIRCUITPY_USB_HID ?= 0
+
+ USB_NUM_EP = 4
endif
ifeq ($(MCU_SERIES),H7)
@@ -40,6 +43,8 @@ ifeq ($(MCU_SERIES),H7)
CIRCUITPY_RTC ?= 0
CIRCUITPY_USB_HID ?= 0
CIRCUITPY_USB_MIDI ?= 0
+
+ USB_NUM_EP = 9
endif
ifeq ($(MCU_SERIES),F7)
@@ -56,4 +61,6 @@ ifeq ($(MCU_SERIES),F7)
CIRCUITPY_RTC ?= 0
CIRCUITPY_USB_HID ?= 0
CIRCUITPY_USB_MIDI ?= 0
+
+ USB_NUM_EP = 6
endif