diff --git a/.github/workflows/bundle_cron.yml b/.github/workflows/bundle_cron.yml new file mode 100644 index 0000000000000..606707d4102f1 --- /dev/null +++ b/.github/workflows/bundle_cron.yml @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2019 Michael Schroeder +# +# SPDX-License-Identifier: MIT + +name: Update Bundles + +on: + schedule: + - cron: 0 5 * * * + workflow_dispatch: + +jobs: + check-repo-owner: + # This job is so the entire workflow will end successfully and give some + # output to explain why it hasn't run on a non-Adafruit fork. + runs-on: ubuntu-latest + steps: + - name: repository + env: + OWNER_IS_ADAFRUIT: ${{ startswith(github.repository, 'adafruit/') }} + run: | + echo "This workflow will only run if Adafruit is the repository owner." + echo "Repository owner is Adafruit: $OWNER_IS_ADAFRUIT" + update-bundles: + runs-on: ubuntu-latest + # Only run the build on Adafruit's repository. Forks won't have the secrets. + # It's necessary to do this here, since 'schedule' events cannot (currently) + # be limited (they run on all forks' default branches). + if: startswith(github.repository, 'adafruit/') + steps: + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: 3.12 + - name: Load contributor cache + uses: actions/cache@v4 + with: + key: "contributor-cache" + path: "contributors.json" + - name: Versions + run: | + python3 --version + - uses: actions/checkout@v4 + with: + repository: 'adafruit/adabot' + submodules: true + - name: Install deps + run: | + pip install -r requirements.txt + - name: Run adabot.circuitpython_bundle + env: + ADABOT_EMAIL: ${{ secrets.ADABOT_EMAIL }} + ADABOT_GITHUB_USER: ${{ secrets.ADABOT_GITHUB_USER }} + ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} + BIGQUERY_PRIVATE_KEY: ${{ secrets.BIGQUERY_PRIVATE_KEY }} + BIGQUERY_CLIENT_EMAIL: ${{ secrets.BIGQUERY_CLIENT_EMAIL }} + run: | + python3 -u -m adabot.circuitpython_bundle diff --git a/.github/workflows/learn_cron.yml b/.github/workflows/learn_cron.yml new file mode 100644 index 0000000000000..6100e6637c20e --- /dev/null +++ b/.github/workflows/learn_cron.yml @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Tag Learning System Guides + +on: + schedule: + - cron: 0 5 * * * + +jobs: + check-repo-owner: + # This job is so the entire workflow will end successfully and give some + # output to explain why it hasn't run on a non-Adafruit fork. + runs-on: ubuntu-latest + if: ${{ (github.repository_owner != 'adafruit') }} + steps: + - run: | + echo "This workflow is only intended to run in the adafruit fork" + + update-learn: + runs-on: ubuntu-latest + # Only run the build if the access token has been configured. This will be + # the case on Adafruit's repository. It's necessary to do this here, since + # 'schedule' events cannot (currently) be limited (they run on all forks' + # default branches). + if: ${{ (github.repository_owner == 'adafruit') }} + steps: + - uses: actions/checkout@v4 + with: + repository: ${{ github.repository_owner }}/Adafruit_Learning_System_Guides + token: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} + - name: Tag a release + env: + ADABOT_EMAIL: ${{ secrets.ADABOT_EMAIL }} + run: | + git config --global user.name adabot + git config --global user.email "$ADABOT_EMAIL" + TAG_NAME=`date +%Y%m%d` + git tag $TAG_NAME + git push origin $TAG_NAME diff --git a/.github/workflows/reports_cron.yml b/.github/workflows/reports_cron.yml new file mode 100644 index 0000000000000..b4e9a43024e27 --- /dev/null +++ b/.github/workflows/reports_cron.yml @@ -0,0 +1,91 @@ +# SPDX-FileCopyrightText: 2019 Michael Schroeder +# +# SPDX-License-Identifier: MIT + +name: Run Daily Reports + +on: + schedule: + # The actor (github.actor) that runs the cron job may be the user who created the cron job + # initially. It does not appear to be settable via a secret or environment variable. + - cron: 15 5 * * * + workflow_dispatch: + + +jobs: + check-repo-owner: + # This job is so the entire workflow will end successfully and give some + # output to explain why it hasn't run on a non-Adafruit fork. + runs-on: ubuntu-latest + steps: + - name: repository + env: + OWNER_IS_ADAFRUIT: ${{ startswith(github.repository, 'adafruit/') }} + run: | + echo "This workflow will only run if Adafruit is the repository owner." + echo "Repository owner is Adafruit: $OWNER_IS_ADAFRUIT" + run-reports: + runs-on: ubuntu-latest + # Only run the build on Adafruit's repository. Forks won't have the secrets. + # It's necessary to do this here, since 'schedule' events cannot (currently) + # be limited (they run on all forks' default branches). + if: startswith(github.repository, 'adafruit/') + env: + ADABOT_GITHUB_USER: ${{ secrets.ADABOT_GITHUB_USER }} + ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} + RTD_TOKEN: ${{ secrets.RTD_TOKEN }} + BIGQUERY_PRIVATE_KEY: ${{ secrets.BIGQUERY_PRIVATE_KEY }} + BIGQUERY_CLIENT_EMAIL: ${{ secrets.BIGQUERY_CLIENT_EMAIL }} + steps: + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + - name: Versions + run: | + python3 --version + - uses: actions/checkout@v4 + with: + repository: 'adafruit/adabot' + submodules: true + - name: Install deps + run: | + pip install -r requirements.txt + - name: Make Directory For Report Files + run: mkdir -p bin/adabot + - name: Set Date Variable + id: today + run: | + echo date=$( + date +%Y%m%d + ) >> $GITHUB_OUTPUT + - name: Run adabot.circuitpython_libraries + env: + # LIB_CHECK_CP_FILE is for circuitpython_libraries.py output + LIB_CHECK_CP_FILE: bin/adabot/circuitpython_library_report_${{ steps.today.outputs.date }}.txt + run: | + python3 -u -m adabot.circuitpython_libraries -o $LIB_CHECK_CP_FILE + continue-on-error: true + - name: Run adabot.circuitpython_library_download_stats + env: + # LIB_DL_STATS_FILE is for future Bundle and PyPi download stats script + LIB_DL_STATS_FILE: bin/adabot/library_download_stats_${{ steps.today.outputs.date }}.txt + run: | + python3 -u -m adabot.circuitpython_library_download_stats -o $LIB_DL_STATS_FILE + continue-on-error: true + - name: Run adabot.arduino_libraries + env: + # LIB_CHECK_ARD_FILE is for arduino_libraries.py output + LIB_CHECK_ARD_FILE: bin/adabot/arduino_library_report_${{ steps.today.outputs.date }}.txt + run: | + python3 -u -m adabot.arduino_libraries -o $LIB_CHECK_ARD_FILE + continue-on-error: true + - name: Check For Files + run: | + ls bin/adabot + - name: Upload Reports To AWS S3 + if: ${{ github.event_name != 'workflow_dispatch' }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/adabot/ s3://adafruit-circuit-python/adabot/bin/reports/ --recursive --no-progress --region us-east-1" diff --git a/.gitmodules b/.gitmodules index b1ec0f9faee7f..7eaa0b04142b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -143,7 +143,7 @@ [submodule "ports/espressif/esp-idf"] path = ports/espressif/esp-idf url = https://github.com/adafruit/esp-idf.git - branch = circuitpython-v5.4.1 + branch = circuitpython-v5.5.1 [submodule "ports/espressif/esp-protocols"] path = ports/espressif/esp-protocols url = https://github.com/adafruit/esp-protocols.git @@ -172,7 +172,7 @@ url = https://github.com/adafruit/Adafruit_CircuitPython_SimpleMath [submodule "ports/raspberrypi/sdk"] path = ports/raspberrypi/sdk - url = https://github.com/adafruit/pico-sdk.git + url = https://github.com/raspberrypi/pico-sdk.git branch = force_inline_critical_section_2.1.1 [submodule "data/nvm.toml"] path = data/nvm.toml diff --git a/Makefile b/Makefile index f2fc070a6331d..c2aebc61f1c0b 100644 --- a/Makefile +++ b/Makefile @@ -299,6 +299,9 @@ update-frozen-libraries: one-of-each: samd21 litex mimxrt10xx nordic stm +analog: + $(MAKE) -C ports/analog/ BOARD=apard32690 + samd21: $(MAKE) -C ports/atmel-samd BOARD=trinket_m0 diff --git a/docs/workflows.md b/docs/workflows.md index 761504144d8b9..84d7530e2fe99 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -44,6 +44,12 @@ A few boards have SD card automounting. (This is based on the ``DEFAULT_SD`` set ``mpconfigboard.h``.) The card is writable from CircuitPython by default and read-only to the host. `storage.remount()` can be used to remount the drive to the host as read-write. +On most other boards, except for ``atmel-samd`` boards, an SD card mounted in user code +at ``/sd`` will become visible after a few seconds on the attached host computer, as an +additional drive besides CIRCUITPY and (if present) CPSAVES. It will present with the volume +label on the SD card. Depending on the host operating system settings, the drive may or may not be +auto-mounted on the host. Host writes to drives mounted by user code will not trigger a reload. + ### CDC serial CircuitPython exposes one CDC USB interface for CircuitPython serial. This is a standard serial USB interface. diff --git a/extmod/vfs.h b/extmod/vfs.h index 67d5d9239a33e..699232e56cd87 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -52,6 +52,8 @@ #define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020) // Bit set when something has claimed the right to mutate the blockdev. #define MP_BLOCKDEV_FLAG_LOCKED (0x0040) +// Ignore write protections. Used to override other flags temporarily. +#define MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION (0x0080) // constants for block protocol ioctl #define MP_BLOCKDEV_IOCTL_INIT (1) diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 5011a820af864..6267452cd32c7 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -427,13 +427,10 @@ static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs); static mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); - // Read-only device indicated by writeblocks[0] == MP_OBJ_NULL. - // User can specify read-only device by: - // 1. readonly=True keyword argument - // 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already) - if (mp_obj_is_true(readonly)) { - self->blockdev.writeblocks[0] = MP_OBJ_NULL; - } + // CIRCUITPY-CHANGE: Use MP_BLOCKDEV_FLAG_USB_WRITABLE instead of writeblocks[0] =/!= MP_OBJ_NULL + // to specify read-write. + // If readonly to Python, it's writable by USB and vice versa. + filesystem_set_writable_by_usb(self, mp_obj_is_true(readonly)); // check if we need to make the filesystem FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index 6f500104d1e86..591da07eb5630 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -43,6 +43,9 @@ #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" +// CIRCUITPY-CHANGE +#include "supervisor/filesystem.h" + typedef void *bdev_t; static fs_user_mount_t *disk_get_device(void *bdev) { return (fs_user_mount_t *)bdev; @@ -153,7 +156,8 @@ DRESULT disk_ioctl( if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { // error initialising stat = STA_NOINIT; - } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { + // CIRCUITPY-CHANGE: writability from Python check + } else if (!filesystem_is_writable_by_python(vfs)) { stat = STA_PROTECT; } else { stat = 0; diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar index 163f2f166aee1..4b0ba649e5abd 160000 --- a/frozen/Adafruit_CircuitPython_DotStar +++ b/frozen/Adafruit_CircuitPython_DotStar @@ -1 +1 @@ -Subproject commit 163f2f166aee11d82303492bb1e5af4937e57b62 +Subproject commit 4b0ba649e5abdebead5b9a47a6c695d67c2c25fa diff --git a/frozen/Adafruit_CircuitPython_FakeRequests b/frozen/Adafruit_CircuitPython_FakeRequests index aa034280ebfed..020121e90c630 160000 --- a/frozen/Adafruit_CircuitPython_FakeRequests +++ b/frozen/Adafruit_CircuitPython_FakeRequests @@ -1 +1 @@ -Subproject commit aa034280ebfed80c245827ff1d49a098ace64b03 +Subproject commit 020121e90c6306147f91b8079b75f3d14ff86138 diff --git a/frozen/Adafruit_CircuitPython_HTTPServer b/frozen/Adafruit_CircuitPython_HTTPServer index b70106b17bbfa..c43147a016ffd 160000 --- a/frozen/Adafruit_CircuitPython_HTTPServer +++ b/frozen/Adafruit_CircuitPython_HTTPServer @@ -1 +1 @@ -Subproject commit b70106b17bbfa0070f8573e1e06e384d9d4577de +Subproject commit c43147a016ffd13c57a0923730bc6a83afefb4ad diff --git a/frozen/Adafruit_CircuitPython_LED_Animation b/frozen/Adafruit_CircuitPython_LED_Animation index 5d13d0966a775..8af05705962e8 160000 --- a/frozen/Adafruit_CircuitPython_LED_Animation +++ b/frozen/Adafruit_CircuitPython_LED_Animation @@ -1 +1 @@ -Subproject commit 5d13d0966a775369eca5b137cfef9583dfa8bb42 +Subproject commit 8af05705962e8bb7d2f8003e6a70916a9a51b863 diff --git a/frozen/Adafruit_CircuitPython_PortalBase b/frozen/Adafruit_CircuitPython_PortalBase index 3dce5bca3bcd2..d26e2324de496 160000 --- a/frozen/Adafruit_CircuitPython_PortalBase +++ b/frozen/Adafruit_CircuitPython_PortalBase @@ -1 +1 @@ -Subproject commit 3dce5bca3bcd27354becc6d3ecf82244f1e26ffe +Subproject commit d26e2324de496761e0aa72abc30ba07cdce8814b diff --git a/frozen/Adafruit_CircuitPython_SSD1680 b/frozen/Adafruit_CircuitPython_SSD1680 index b7d511711c8f5..d6aa01c4f8fa1 160000 --- a/frozen/Adafruit_CircuitPython_SSD1680 +++ b/frozen/Adafruit_CircuitPython_SSD1680 @@ -1 +1 @@ -Subproject commit b7d511711c8f5557082d9c4307a89ecdec608727 +Subproject commit d6aa01c4f8fa1004430bfcdd4db2219183425693 diff --git a/frozen/Adafruit_CircuitPython_UC8151D b/frozen/Adafruit_CircuitPython_UC8151D index 776b932ebf769..4ebf9c2854376 160000 --- a/frozen/Adafruit_CircuitPython_UC8151D +++ b/frozen/Adafruit_CircuitPython_UC8151D @@ -1 +1 @@ -Subproject commit 776b932ebf76937e464ab2656834e7a1c1e3434b +Subproject commit 4ebf9c2854376a06766a6ae4732a4537a766fb75 diff --git a/frozen/Adafruit_CircuitPython_Wiznet5k b/frozen/Adafruit_CircuitPython_Wiznet5k index 6b3484d1ee243..736241c7a22f8 160000 --- a/frozen/Adafruit_CircuitPython_Wiznet5k +++ b/frozen/Adafruit_CircuitPython_Wiznet5k @@ -1 +1 @@ -Subproject commit 6b3484d1ee243a7e8bc0513ab84956e1b6e2a520 +Subproject commit 736241c7a22f86dcf8ff73a77c4536cedfdc4cdd diff --git a/lib/littlefs/lfs1.c b/lib/littlefs/lfs1.c index 6a3fd670012cc..ec18dc470258c 100644 --- a/lib/littlefs/lfs1.c +++ b/lib/littlefs/lfs1.c @@ -2141,7 +2141,7 @@ int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *cfg) { .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, .d.nlen = sizeof(superblock.d.magic), .d.version = LFS1_DISK_VERSION, - .d.magic = {"littlefs"}, + .d.magic = {'l', 'i', 't', 't', 'l', 'e', 'f', 's'}, .d.block_size = lfs1->cfg->block_size, .d.block_count = lfs1->cfg->block_count, .d.root = {lfs1->root[0], lfs1->root[1]}, diff --git a/lib/protomatter b/lib/protomatter index 0bd9873153ab0..f83bac7e42107 160000 --- a/lib/protomatter +++ b/lib/protomatter @@ -1 +1 @@ -Subproject commit 0bd9873153ab0a91d6737c392622159a4515a2e5 +Subproject commit f83bac7e421077812523fddb83d3e25f29753315 diff --git a/lib/tinyusb b/lib/tinyusb index 542e5b4550a01..c1bf19ed6cf1e 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 542e5b4550a01d034b78308d77c408ed89427513 +Subproject commit c1bf19ed6cf1eaa791f221c1bc5ce4b3d069f76d diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 262b5de769c89..1e167c30353dd 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -130,6 +130,7 @@ msgstr "" msgid "%q indices must be integers, not %s" msgstr "" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "" @@ -158,6 +159,10 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" +#: py/runtime.c +msgid "%q moved from %q to %q" +msgstr "" + #: py/argcheck.c msgid "%q must be %d" msgstr "" @@ -237,6 +242,7 @@ msgstr "" msgid "%q out of bounds" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -498,7 +504,8 @@ msgstr "" msgid "All SPI peripherals are in use" msgstr "" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "" @@ -649,6 +656,7 @@ msgstr "" msgid "Boot device must be first (interface #0)." msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "" @@ -844,6 +852,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -987,7 +999,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -1045,6 +1057,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1247,6 +1263,10 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1339,6 +1359,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1394,6 +1415,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1894,6 +1919,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1986,6 +2012,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -2117,6 +2147,10 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" @@ -2160,6 +2194,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2168,6 +2206,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" diff --git a/locale/cs.po b/locale/cs.po index 58785e0a5d75a..fa1cb2d40b738 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -141,6 +141,7 @@ msgstr "Index %q je mimo rozsah" msgid "%q indices must be integers, not %s" msgstr "Indexy %q musí být celá čísla, nikoli %s" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "Inicializace %q selhala" @@ -169,6 +170,10 @@ msgstr "Délka %q musí být <= %d" msgid "%q length must be >= %d" msgstr "Délka %q musí být >= %d" +#: py/runtime.c +msgid "%q moved from %q to %q" +msgstr "" + #: py/argcheck.c msgid "%q must be %d" msgstr "%q musí být %d" @@ -248,6 +253,7 @@ msgstr "%q musí být mocnina 2" msgid "%q out of bounds" msgstr "%q je mimo hranice" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -509,7 +515,8 @@ msgstr "Všechny RX FIFO jsou používány" msgid "All SPI peripherals are in use" msgstr "Všechny SPI periferie jsou používány" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Všechny UART periferie jsou používány" @@ -662,6 +669,7 @@ msgstr "Velikost bitmapy a počet bitů na hodnotu se musí shodovat" msgid "Boot device must be first (interface #0)." msgstr "Bootovací zařízení musí být první (rozhraní #0)." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "RX a TX jsou vyžadovány pro kontrolu toku" @@ -861,6 +869,10 @@ msgstr "Pole souřadnic mají různé délky" msgid "Coordinate arrays types have different sizes" msgstr "" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -1005,7 +1017,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "Chyba alokace %q bufferu" @@ -1063,6 +1075,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "Nepodařilo se uvolnit mutex, err 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1267,6 +1283,10 @@ msgstr "Chyba přerušení." msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1359,6 +1379,7 @@ msgstr "Chybná velikost" msgid "Invalid socket for TLS" msgstr "Chybný soket pro TLS" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1414,6 +1435,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1917,6 +1942,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -2009,6 +2035,10 @@ msgstr "Konfigurace SPI selhala" msgid "SPI init error" msgstr "Chyba inicializace SPI" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "SPI periferie je používána" @@ -2140,6 +2170,10 @@ msgstr "Čas je v minulosti." msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Časový limit je příliš dlouhý: maximální limit je %d vteřin" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "V samplu je příliš mnoho kanálů" @@ -2184,6 +2218,10 @@ msgstr "De-inicializace UART" msgid "UART init" msgstr "Inicializace UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "UART periférie je používána" @@ -2192,6 +2230,14 @@ msgstr "UART periférie je používána" msgid "UART re-init" msgstr "Opětovná inicializace UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "Zápis na UART" diff --git a/locale/el.po b/locale/el.po index 082ae20351e3b..91624ceb08672 100644 --- a/locale/el.po +++ b/locale/el.po @@ -145,6 +145,7 @@ msgstr "%q δείκτης εκτός εμβέλειας" msgid "%q indices must be integers, not %s" msgstr "%q δείκτες πρέπει να είναι ακέραιοι, όχι %s" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "%q εκκίνηση απέτυχε" @@ -173,6 +174,10 @@ msgstr "%q μήκος πρέπει να είναι <= %d" msgid "%q length must be >= %d" msgstr "%q μήκος πρέπει να είναι >= %d" +#: py/runtime.c +msgid "%q moved from %q to %q" +msgstr "%q μετακινήθηκε από το %q στο %q" + #: py/argcheck.c msgid "%q must be %d" msgstr "%q πρέπει να είναι %d" @@ -252,6 +257,7 @@ msgstr "%q πρέπει να είναι δύναμη του 2" msgid "%q out of bounds" msgstr "%q εκτός ορίων" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -513,7 +519,8 @@ msgstr "Όλα τα RX FIFOs είναι σε χρήση" msgid "All SPI peripherals are in use" msgstr "Όλα τα SPI περιφεριακά είναι σε χρήση" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Όλα τα UART περιφεριακά ειναι σε χρήση" @@ -666,6 +673,7 @@ msgstr "Το μέγεθος του bitmap και τα bits ανα τιμή πρ msgid "Boot device must be first (interface #0)." msgstr "Η συσκευή εκκίνησης πρέπει να επιλεχθεί πρώτα (διεπαφή #0)." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "Και RX και TX απαιτούνται για έλεγχο flow" @@ -867,6 +875,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -1013,7 +1025,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -1071,6 +1083,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1273,6 +1289,10 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1365,6 +1385,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1420,6 +1441,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1922,6 +1947,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -2014,6 +2040,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -2145,6 +2175,10 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" @@ -2188,6 +2222,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2196,6 +2234,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" @@ -4537,9 +4583,6 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" -#~ msgid "%q moved from %q to %q" -#~ msgstr "%q μετακινήθηκε από το %q στο %q" - #, c-format #~ msgid "%%c requires int or char" #~ msgstr "%%c απαιτεί ακέραιο ή χαρακτήρα" diff --git a/locale/hi.po b/locale/hi.po index 8e4aa0990aee7..1ab48338ebaba 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -132,6 +132,7 @@ msgstr "" msgid "%q indices must be integers, not %s" msgstr "" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "" @@ -160,6 +161,10 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" +#: py/runtime.c +msgid "%q moved from %q to %q" +msgstr "" + #: py/argcheck.c msgid "%q must be %d" msgstr "" @@ -239,6 +244,7 @@ msgstr "" msgid "%q out of bounds" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -500,7 +506,8 @@ msgstr "" msgid "All SPI peripherals are in use" msgstr "" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "" @@ -651,6 +658,7 @@ msgstr "" msgid "Boot device must be first (interface #0)." msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "" @@ -846,6 +854,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -989,7 +1001,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -1047,6 +1059,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1249,6 +1265,10 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1341,6 +1361,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1396,6 +1417,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1896,6 +1921,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1988,6 +2014,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -2119,6 +2149,10 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" @@ -2162,6 +2196,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2170,6 +2208,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" diff --git a/locale/ko.po b/locale/ko.po index 8bde494eeec78..35bfed4de08e9 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -143,6 +143,7 @@ msgstr "%q 인덱스 범위를 벗어났습니다" msgid "%q indices must be integers, not %s" msgstr "%q 인덱스는 %s 가 아닌 정수 여야합니다" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "%q 초기화 실패" @@ -171,6 +172,11 @@ msgstr "%q 길이는 <= %d>여야 합니다" msgid "%q length must be >= %d" msgstr "%q 길이는 >= %d이어야 합니다" +#: py/runtime.c +#, fuzzy +msgid "%q moved from %q to %q" +msgstr "%q가 %q에서 %q로 이동했습니다" + #: py/argcheck.c msgid "%q must be %d" msgstr "%q는 %d이어야 합니다" @@ -256,6 +262,7 @@ msgstr "%q는 2의 거듭제곱이어야 합니다" msgid "%q out of bounds" msgstr "%q가 경계를 벗어남" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -531,7 +538,8 @@ msgstr "모든 RX FIFOs가 사용 중입니다" msgid "All SPI peripherals are in use" msgstr "사용중인 모든 SPI주변 기기" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "사용중인 모든 UART주변 기기" @@ -692,6 +700,7 @@ msgstr "비트맵 크기와 값 당 비트가 일치해야 합니다" msgid "Boot device must be first (interface #0)." msgstr "부팅 장치는 첫 번째(인터페이스 #0)여야 합니다." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "플로우 제어에 RX와 TX가 모두 필요합니다" @@ -890,6 +899,10 @@ msgstr "좌표 배열의 길이가 다릅니다" msgid "Coordinate arrays types have different sizes" msgstr "좌표 배열 유형은 크기가 다릅니다" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -1037,7 +1050,7 @@ msgstr "" "서비스 TXT 레코드를 추가하는 것에 실패했습니다; txt_records에서 비문자열 또" "는 바이트가 발견되었습니다" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "%q 버퍼 할당에 실패했습니다" @@ -1095,6 +1108,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "뮤텍스 해제에 실패했습니다, 오류 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1300,6 +1317,10 @@ msgstr "인터럽트 오류." msgid "Interrupted by output function" msgstr "출력 함수로 인해 종료되었다" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1392,6 +1413,7 @@ msgstr "잘못된 크기" msgid "Invalid socket for TLS" msgstr "TLS에 대한 잘못된 소켓" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1447,6 +1469,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "매핑은 투플이어야 합니다" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1970,6 +1996,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -2062,6 +2089,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -2193,6 +2224,10 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" @@ -2236,6 +2271,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2244,6 +2283,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" @@ -4586,10 +4633,6 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" -#, fuzzy -#~ msgid "%q moved from %q to %q" -#~ msgstr "%q가 %q에서 %q로 이동했습니다" - #, c-format #~ msgid "%%c requires int or char" #~ msgstr "%%c 전수(int)또는 캐릭터(char)필요합니다" diff --git a/locale/ru.po b/locale/ru.po index d3d9415230455..af7c8bca194d2 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -145,6 +145,7 @@ msgstr "Индекс %q вне диапазона" msgid "%q indices must be integers, not %s" msgstr "Индексы %q должны быть целыми числами, а не %s" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "Инициализация %q не удалась" @@ -173,6 +174,10 @@ msgstr "Длинна %q должна быть <= %d" msgid "%q length must be >= %d" msgstr "Длинна %q должна быть >= %d" +#: py/runtime.c +msgid "%q moved from %q to %q" +msgstr "%q переместился из %q в %q" + #: py/argcheck.c msgid "%q must be %d" msgstr "%q должно быть %d" @@ -252,6 +257,7 @@ msgstr "%q должен быть во 2-й степени" msgid "%q out of bounds" msgstr "%q за пределом" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -513,7 +519,8 @@ msgstr "Все RX FIFO уже используются" msgid "All SPI peripherals are in use" msgstr "Все периферийные устройства SPI уже используются" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Все периферийные устройства UART уже используются" @@ -667,6 +674,7 @@ msgstr "" msgid "Boot device must be first (interface #0)." msgstr "Загрузочное устройство должно быть первым (интерфейс #0)." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "Для управления потоком требуется как RX так и TX" @@ -870,6 +878,10 @@ msgstr "Координатные массивы имеют разные длин msgid "Coordinate arrays types have different sizes" msgstr "Типы массивов координат имеют разные размеры" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -1018,7 +1030,7 @@ msgstr "" "Не удалось добавить служебную TXT-запись; в txt_records обнаружена нестрока " "или байт" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "Не удалось выделить буфер %q" @@ -1076,6 +1088,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "Не удалось освободить mutex, ошибка 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1288,6 +1304,10 @@ msgstr "Прерванная ошибка." msgid "Interrupted by output function" msgstr "Прерывается функцией выхода" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1380,6 +1400,7 @@ msgstr "Неверный размер" msgid "Invalid socket for TLS" msgstr "Неверный сокет для TLS" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1435,6 +1456,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "Сопоставление должно быть кортежом" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1947,6 +1972,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -2039,6 +2065,10 @@ msgstr "Сбой конфигурации SPI" msgid "SPI init error" msgstr "Ошибка инициализации SPI" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "Используемое периферийное устройство SPI" @@ -2175,6 +2205,10 @@ msgstr "Время в прошлом." msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Таймаут слишком длинный: максимальная длина таймаута %d секунд" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "Слишком много каналов в выборке" @@ -2218,6 +2252,10 @@ msgstr "Деинициализация UART" msgid "UART init" msgstr "Инициализация UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "Используемое периферийное устройство UART" @@ -2226,6 +2264,14 @@ msgstr "Используемое периферийное устройство U msgid "UART re-init" msgstr "Повторная инициализация UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "Запись UART" @@ -4604,9 +4650,6 @@ msgstr "zi должно быть типа float" msgid "zi must be of shape (n_section, 2)" msgstr "zi должен иметь форму (n_section, 2)" -#~ msgid "%q moved from %q to %q" -#~ msgstr "%q переместился из %q в %q" - #~ msgid "start/end indices" #~ msgstr "Начальные/конечные индексы" diff --git a/locale/tr.po b/locale/tr.po index 10a288553a698..758137eae21f8 100644 --- a/locale/tr.po +++ b/locale/tr.po @@ -143,6 +143,7 @@ msgstr "%q indeksi aralık dışında" msgid "%q indices must be integers, not %s" msgstr "%q indeksleri integer olmalı, %s değil" +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "%q init başarısız oldu" @@ -171,6 +172,10 @@ msgstr "%q boyutu <= %d olmalıdır" msgid "%q length must be >= %d" msgstr "%q boyutu >= %d olmalıdır" +#: py/runtime.c +msgid "%q moved from %q to %q" +msgstr "" + #: py/argcheck.c msgid "%q must be %d" msgstr "%q, %d olmalıdır" @@ -250,6 +255,7 @@ msgstr "%q, 2'nin kuvveti olmalıdır" msgid "%q out of bounds" msgstr "%q sınırların dışında" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c @@ -511,7 +517,8 @@ msgstr "Tüm RX FIFO'ları kullanımda" msgid "All SPI peripherals are in use" msgstr "Tüm SPI çevre birimleri kullanımda" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Tüm UART çevre birimleri kullanımda" @@ -664,6 +671,7 @@ msgstr "Bitmap boyutu ve bit başına değer uyuşmalı" msgid "Boot device must be first (interface #0)." msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "Hem RX hem de TX akış kontrolü için gerekli" @@ -860,6 +868,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + #: ports/espressif/common-hal/rclcpy/Publisher.c msgid "Could not publish to ROS topic" msgstr "" @@ -1003,7 +1015,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -1061,6 +1073,10 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "Muteks serbest bırakılamadı, err 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + #: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Failed to set hostname" msgstr "" @@ -1267,6 +1283,10 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c #: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c @@ -1360,6 +1380,7 @@ msgstr "Geçersiz boyut" msgid "Invalid socket for TLS" msgstr "TLS için geçersiz soket" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" @@ -1415,6 +1436,10 @@ msgstr "" msgid "Mapping must be a tuple" msgstr "Map tuple olmalıdır" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1918,6 +1943,7 @@ msgstr "" msgid "ROS topic failed to initialize" msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -2010,6 +2036,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -2141,6 +2171,10 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" @@ -2184,6 +2218,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2192,6 +2230,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" diff --git a/main.c b/main.c index 1f387b7ca3ceb..91687ff2f8bc7 100644 --- a/main.c +++ b/main.c @@ -211,14 +211,22 @@ static void start_mp(safe_mode_t safe_mode) { static void stop_mp(void) { #if MICROPY_VFS - mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); // Unmount all heap allocated vfs mounts. - while (gc_nbytes(vfs) > 0) { + mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); + do { + if (gc_ptr_on_heap(vfs)) { + // mp_vfs_umount will splice out an unmounted vfs from the vfs_mount_table linked list. + mp_vfs_umount(vfs->obj); + // Start over at the beginning of the list since the first entry may have been removed. + vfs = MP_STATE_VM(vfs_mount_table); + continue; + } vfs = vfs->next; - } - MP_STATE_VM(vfs_mount_table) = vfs; + } while (vfs != NULL); + // The last vfs is CIRCUITPY and the root directory. + vfs = MP_STATE_VM(vfs_mount_table); while (vfs->next != NULL) { vfs = vfs->next; } @@ -855,6 +863,14 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { boot_output = &boot_text; #endif + // Get the base filesystem. + fs_user_mount_t *vfs = filesystem_circuitpy(); + FATFS *fs = &vfs->fatfs; + + // Allow boot.py access to CIRCUITPY, and allow writes to boot_out.txt. + // We can't use the regular flags for this, because they might get modified inside boot.py. + filesystem_set_ignore_write_protection(vfs, true); + // Write version info mp_printf(&mp_plat_print, "%s\nBoard ID:%s\n", MICROPY_FULL_VERSION_INFO, CIRCUITPY_BOARD_ID); #if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH > 0 @@ -873,10 +889,6 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - // Get the base filesystem. - fs_user_mount_t *vfs = filesystem_circuitpy(); - FATFS *fs = &vfs->fatfs; - boot_output = NULL; #if CIRCUITPY_STATUS_BAR supervisor_status_bar_resume(); @@ -898,9 +910,6 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { // in case power is momentary or will fail shortly due to, say a low, battery. mp_hal_delay_ms(1000); - // USB isn't up, so we can write the file. - // operating at the oofatfs (f_open) layer means the usb concurrent write permission - // is not even checked! f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS); UINT chars_written; f_write(&boot_output_file, boot_text.buf, boot_text.len, &chars_written); @@ -908,6 +917,9 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { filesystem_flush(); } #endif + + // Back to regular filesystem protections. + filesystem_set_ignore_write_protection(vfs, false); } cleanup_after_vm(_exec_result.exception); @@ -1179,10 +1191,6 @@ void gc_collect(void) { gc_collect_end(); } -// Ports may provide an implementation of this function if it is needed -MP_WEAK void port_gc_collect(void) { -} - size_t gc_get_max_new_split(void) { return port_heap_get_largest_free_size(); } diff --git a/ports/analog/Makefile b/ports/analog/Makefile index ce9082c5e255a..0ae276985f7f4 100644 --- a/ports/analog/Makefile +++ b/ports/analog/Makefile @@ -6,12 +6,13 @@ # # SPDX-License-Identifier: MIT +BOARD ?= apard32690 +CROSS_COMPILE = arm-none-eabi- + # Includes mpconfigboard.mk & mpconfigport.mk, # along with numerous other shared environment makefiles. include ../../py/circuitpy_mkenv.mk -CROSS_COMPILE = arm-none-eabi- - # MCU_SERIES e.g. "max32" # MCU_VARIANT e.g. "max32690" # defined in mpconfigboard.mk @@ -20,6 +21,7 @@ MCU_SERIES_UPPER := $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') MCU_VARIANT_LOWER := $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]') MCU_VARIANT_UPPER := $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') + # ******************************************************************************* #### MSDK INCLUDES #### # Necessary for msdk makefiles @@ -59,6 +61,7 @@ DIE_TYPE=me18 endif PERIPH_SRC = $(ADI_PERIPH)/Source +PERIPH_INC = $(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) INC += -I. INC += -I../.. @@ -75,7 +78,7 @@ INC += \ -I$(TOP)/lib/cmsis/inc \ -I$(CMSIS_ROOT)/Include \ -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Include \ - -I$(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) \ + -I$(PERIPH_INC) \ -I$(PERIPH_SRC)/SYS \ -I$(PERIPH_SRC)/CTB \ -I$(PERIPH_SRC)/DMA \ @@ -85,7 +88,9 @@ INC += \ -I$(PERIPH_SRC)/TMR \ -I$(PERIPH_SRC)/RTC \ -I$(PERIPH_SRC)/UART \ - -I$(PERIPH_SRC)/TRNG + -I$(PERIPH_SRC)/TRNG \ + -I$(PERIPH_SRC)/I2C \ + -I$(PERIPH_SRC)/SPI INC += -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC @@ -120,13 +125,20 @@ SRC_MAX32 += \ $(PERIPH_SRC)/UART/uart_$(DIE_TYPE).c \ $(PERIPH_SRC)/UART/uart_revb.c \ $(PERIPH_SRC)/TRNG/trng_revb.c \ - $(PERIPH_SRC)/TRNG/trng_$(DIE_TYPE).c + $(PERIPH_SRC)/TRNG/trng_$(DIE_TYPE).c \ + $(PERIPH_SRC)/I2C/i2c_$(DIE_TYPE).c \ + $(PERIPH_SRC)/I2C/i2c_reva.c \ + $(PERIPH_SRC)/SPI/spi_$(DIE_TYPE).c \ + $(PERIPH_SRC)/SPI/spi_reva1.c SRC_C += $(SRC_MAX32) \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ peripherals/$(MCU_VARIANT_LOWER)/pins.c \ - peripherals/$(MCU_VARIANT_LOWER)/gpios.c + peripherals/$(MCU_VARIANT_LOWER)/gpios.c \ + peripherals/$(MCU_VARIANT_LOWER)/max32_uart.c \ + peripherals/$(MCU_VARIANT_LOWER)/max32_i2c.c \ + peripherals/$(MCU_VARIANT_LOWER)/max32_spi.c # ******************************************************************************* ### Compiler & Linker Flags ### @@ -267,11 +279,16 @@ flash-msdk: -f interface/cmsis-dap.cfg -f target/$(MCU_VARIANT_LOWER).cfg \ -c "program $(BUILD)/firmware.elf verify; init; reset; exit" +flash-openocd-jlink: + $(OPENOCD) -s $(OPENOCD_SCRIPTS) \ + -f interface/jlink.cfg -f target/$(MCU_VARIANT_LOWER).cfg \ + -c "program $(BUILD)/firmware.elf verify; init; reset; exit" + # flash target using JLink JLINK_DEVICE = $(MCU_VARIANT_LOWER) JLINKEXE ?= JLink.exe -JLINKEXE += -if SWD -device ${JLINK_DEVICE} -speed 10000 +JLINKEXE += -if SWD -device ${JLINK_DEVICE} -speed 4000 COMMAND_FILE := tools/flash_max32.jlink flash-jlink: $(BUILD)/firmware.bin diff --git a/ports/analog/background.c b/ports/analog/background.c index ffad007ffa51c..ad840c6dcdabc 100644 --- a/ports/analog/background.c +++ b/ports/analog/background.c @@ -19,19 +19,13 @@ extern const mxc_gpio_cfg_t led_pin[]; extern const int num_leds; /** NOTE: ALL "ticks" refer to a 1/1024 s period */ -static int status_led_ticks = 0; +static int status_ticks = 0; // This function is where port-specific background // tasks should be performed // Execute port specific actions during background tick. Only if ticks are enabled. void port_background_tick(void) { - status_led_ticks++; - - // Set an LED approx. 1/s - if (status_led_ticks > 1024) { - MXC_GPIO_OutToggle(led_pin[2].port, led_pin[2].mask); - status_led_ticks = 0; - } + status_ticks++; } // Execute port specific actions during background tasks. This is before the diff --git a/ports/analog/common-hal/busio/I2C.c b/ports/analog/common-hal/busio/I2C.c new file mode 100644 index 0000000000000..336c04fe039f9 --- /dev/null +++ b/ports/analog/common-hal/busio/I2C.c @@ -0,0 +1,256 @@ +/* + * This file is part of Adafruit for EFR32 project + * + * The MIT License (MIT) + * + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/busio/I2C.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "max32_port.h" + +#define I2C_PRIORITY 1 + +// Set each bit to indicate an active I2c +static uint8_t i2c_active = 0; +static volatile int i2c_err; + +// I2C struct for configuring GPIO pins +extern const mxc_gpio_cfg_t i2c_maps[NUM_I2C]; + +// Construct I2C protocol, this function init i2c peripheral +void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, + const mcu_pin_obj_t *scl, + const mcu_pin_obj_t *sda, + uint32_t frequency, uint32_t timeout) { + // Check for NULL Pointers && valid I2C settings + assert(self); + + /* NOTE: The validate_obj_is_free_pin() calls in shared-bindings/busio/I2C.c + will ensure that scl and sda are both pins and cannot be null + ref: https://github.com/adafruit/circuitpython/pull/10413 + */ + + // Assign I2C ID based on pins + int i2c_id = pinsToI2c(sda, scl); + if (i2c_id == -1) { + return; + } else { + self->i2c_id = i2c_id; + self->i2c_regs = MXC_I2C_GET_I2C(i2c_id); + } + + // Check for valid I2C controller + assert((self->i2c_id >= 0) && (self->i2c_id < NUM_I2C)); + assert(!(i2c_active & (1 << self->i2c_id))); + + // Attach I2C pins + self->sda = sda; + self->scl = scl; + common_hal_mcu_pin_claim(self->sda); + common_hal_mcu_pin_claim(self->scl); + + // Clear all flags + MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); + + // Init as master, no slave address + MXC_I2C_Shutdown(self->i2c_regs); + MXC_I2C_Init(self->i2c_regs, 1, 0); + + // Set frequency arg (CircuitPython shared-bindings validate) + MXC_I2C_SetFrequency(self->i2c_regs, frequency); + + // Indicate to this module that the I2C is active + i2c_active |= (1 << self->i2c_id); + + // Set the timeout to a default value + if (timeout > 100) { + self->timeout = 1; + } else { + self->timeout = timeout; + } + + return; +} + +// Never reset I2C obj when reload +void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { + common_hal_never_reset_pin(self->sda); + common_hal_never_reset_pin(self->scl); +} + +// Check I2C status, deinited or not +bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { + return self->sda == NULL; +} + +// Deinit i2c obj, reset I2C pin +void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { + MXC_I2C_Shutdown(self->i2c_regs); + + common_hal_reset_pin(self->sda); + common_hal_reset_pin(self->scl); + + self->sda = NULL; + self->scl = NULL; +} + +// Probe device in I2C bus +bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { + uint32_t int_fl0; + bool ret = 0; + + // If not in Master mode, error out (can happen in some error conditions) + if (!(self->i2c_regs->ctrl & MXC_F_I2C_CTRL_MST_MODE)) { + return false; + } + + // Clear FIFOs & all interrupt flags + MXC_I2C_ClearRXFIFO(self->i2c_regs); + MXC_I2C_ClearTXFIFO(self->i2c_regs); + MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); + + // Pre-load target address into transmit FIFO + addr = (addr << 1); + self->i2c_regs->fifo = addr; + + // Set start bit & wait for it to clear + MXC_I2C_Start(self->i2c_regs); + + // wait for ACK/NACK + while (!(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_ACK) && + !(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_NACK_ERR)) { + } + + // Save interrupt flags for ACK/NACK checking + int_fl0 = self->i2c_regs->intfl0; + + // Set / Wait for stop + MXC_I2C_Stop(self->i2c_regs); + + // Wait for controller not busy, then clear flags + while (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) { + ; + } + MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); + + if (int_fl0 & MXC_F_I2C_INTFL0_ADDR_ACK) { + ret = true; + } else { + ret = false; + } + return ret; +} + +// Lock I2C bus +bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + + if (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) { + return false; + } else { + self->has_lock = true; + return true; + } +} + +// Check I2C lock status +bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) { + return self->has_lock; +} + +// Unlock I2C bus +void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { + self->has_lock = false; +} + +// Write data to the device selected by address +uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, + const uint8_t *data, size_t len) { + + int ret; + mxc_i2c_req_t wr_req = { + .addr = addr, + .i2c = self->i2c_regs, + .tx_buf = (uint8_t *)data, + .tx_len = len, + .rx_buf = NULL, + .rx_len = 0, + .callback = NULL + }; + ret = MXC_I2C_MasterTransaction(&wr_req); + if (ret) { + return MP_EIO; + } + + return 0; +} + +// Read into buffer from the device selected by address +uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, + uint16_t addr, + uint8_t *data, size_t len) { + + int ret; + mxc_i2c_req_t rd_req = { + .addr = addr, + .i2c = self->i2c_regs, + .tx_buf = NULL, + .tx_len = 0, + .rx_buf = data, + .rx_len = len, + .callback = NULL + }; + ret = MXC_I2C_MasterTransaction(&rd_req); + if (ret) { + // Return I/O error + return MP_EIO; + } + + return 0; +} + +// Write the bytes from out_data to the device selected by address +uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, + uint8_t *out_data, size_t out_len, + uint8_t *in_data, size_t in_len) { + + int ret; + mxc_i2c_req_t wr_rd_req = { + .addr = addr, + .i2c = self->i2c_regs, + .tx_buf = out_data, + .tx_len = out_len, + .rx_buf = in_data, + .rx_len = in_len, + .callback = NULL + }; + ret = MXC_I2C_MasterTransaction(&wr_rd_req); + if (ret) { + return MP_EIO; + } + + return 0; +} diff --git a/ports/analog/common-hal/busio/I2C.h b/ports/analog/common-hal/busio/I2C.h new file mode 100644 index 0000000000000..55c230ee2f97f --- /dev/null +++ b/ports/analog/common-hal/busio/I2C.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +// HAL-specific +#include "i2c.h" +#include "gpio.h" + +// Define a struct for what BUSIO.I2C should carry +typedef struct { + mp_obj_base_t base; + + int i2c_id; + mxc_i2c_regs_t *i2c_regs; + const mcu_pin_obj_t *scl; + const mcu_pin_obj_t *sda; + const int frequency; + + uint32_t timeout; + bool has_lock; +} busio_i2c_obj_t; diff --git a/ports/analog/common-hal/busio/SPI.c b/ports/analog/common-hal/busio/SPI.c new file mode 100644 index 0000000000000..b4a519c37a72d --- /dev/null +++ b/ports/analog/common-hal/busio/SPI.c @@ -0,0 +1,316 @@ +/* + * This file is part of Adafruit for EFR32 project + * + * The MIT License (MIT) + * + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/busio/SPI.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "supervisor/board.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "max32_port.h" +#include "spi_reva1.h" + +// Note that any bugs introduced in this file can cause crashes +// at startupfor chips using external SPI flash. + +#define SPI_PRIORITY 1 + +typedef enum { + SPI_FREE = 0, + SPI_BUSY, + SPI_NEVER_RESET, +} spi_status_t; + +// Set each bit to indicate an active SPI +static uint8_t spi_active = 0; +static spi_status_t spi_status[NUM_SPI]; +static volatile int spi_err; + +// Construct SPI protocol, this function init SPI peripheral +void common_hal_busio_spi_construct(busio_spi_obj_t *self, + const mcu_pin_obj_t *sck, + const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso, + bool half_duplex) { + int err = 0; + + // Check for NULL Pointer + assert(self); + + // Assign SPI ID based on pins + int spi_id = pinsToSpi(mosi, miso, sck); + if (spi_id == -1) { + return; + } else { + self->spi_id = spi_id; + self->spi_regs = MXC_SPI_GET_SPI(spi_id); + } + + // Other pins default to true + mxc_spi_pins_t spi_pins = { + .clock = TRUE, + .mosi = TRUE, + .miso = TRUE, + .ss0 = FALSE, + .ss1 = FALSE, + .ss2 = FALSE, + .vddioh = true, + .drvstr = MXC_GPIO_DRVSTR_0 + }; + + assert((self->spi_id >= 0) && (self->spi_id < NUM_SPI)); + + // Init SPI controller + if ((mosi != NULL) && (miso != NULL) && (sck != NULL)) { + // spi, mastermode, quadModeUsed, numSubs, ssPolarity, frequency + err = MXC_SPI_Init(self->spi_regs, MXC_SPI_TYPE_CONTROLLER, MXC_SPI_INTERFACE_STANDARD, + 1, 0x01, 1000000, spi_pins); + MXC_GPIO_SetVSSEL(MXC_GPIO_GET_GPIO(sck->port), MXC_GPIO_VSSEL_VDDIOH, (sck->mask | miso->mask | mosi->mask | MXC_GPIO_PIN_0)); + if (err) { + // NOTE: Reuse existing messages from locales/circuitpython.pot to save space + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_SPI); + } + } else { + mp_raise_NotImplementedError(MP_ERROR_TEXT("SPI needs MOSI, MISO, and SCK")); + } + + // Attach SPI pins + self->mosi = mosi; + self->miso = miso; + self->sck = sck; + common_hal_mcu_pin_claim(self->mosi); + common_hal_mcu_pin_claim(self->miso); + common_hal_mcu_pin_claim(self->sck); + + // Indicate to this module that the SPI is active + spi_active |= (1 << self->spi_id); + + return; +} + +// Never reset SPI when reload +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + common_hal_never_reset_pin(self->mosi); + common_hal_never_reset_pin(self->miso); + common_hal_never_reset_pin(self->sck); + common_hal_never_reset_pin(self->nss); + + spi_status[self->spi_id] = SPI_NEVER_RESET; +} + +// Check SPI status, deinited or not +bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { + return self->sck == NULL; +} + +// Deinit SPI obj +void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { + + MXC_SPI_Shutdown(self->spi_regs); + common_hal_reset_pin(self->mosi); + common_hal_reset_pin(self->miso); + common_hal_reset_pin(self->sck); + common_hal_reset_pin(self->nss); + + self->mosi = NULL; + self->miso = NULL; + self->sck = NULL; + self->nss = NULL; +} + +// Configures the SPI bus. The SPI object must be locked. +bool common_hal_busio_spi_configure(busio_spi_obj_t *self, + uint32_t baudrate, + uint8_t polarity, + uint8_t phase, + uint8_t bits) { + + mxc_spi_clkmode_t clk_mode; + int ret; + + self->baudrate = baudrate; + self->polarity = polarity; + self->phase = phase; + self->bits = bits; + + switch ((polarity << 1) | (phase)) { + case 0b00: + clk_mode = MXC_SPI_CLKMODE_0; + break; + case 0b01: + clk_mode = MXC_SPI_CLKMODE_1; + break; + case 0b10: + clk_mode = MXC_SPI_CLKMODE_2; + break; + case 0b11: + clk_mode = MXC_SPI_CLKMODE_3; + break; + default: + // should not be reachable; validated in shared-bindings/busio/SPI.c + return false; + } + + ret = MXC_SPI_SetFrequency(self->spi_regs, baudrate); + if (ret) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_baudrate); + return false; + } + ret = MXC_SPI_SetDataSize(self->spi_regs, bits); + if (ret == E_BAD_PARAM) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_bits); + return false; + } else if (ret == E_BAD_STATE) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid state")); + } + ret = MXC_SPI_SetMode(self->spi_regs, clk_mode); + if (ret) { + mp_raise_ValueError(MP_ERROR_TEXT("Failed to set SPI Clock Mode")); + return false; + } + return true; +} + +// Lock SPI bus +bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (spi_status[self->spi_id] != SPI_BUSY) { + self->has_lock = true; + return true; + } else { + return false; + } +} + +// Check SPI lock status +bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) { + return self->has_lock; +} + +// Unlock SPI bus +void common_hal_busio_spi_unlock(busio_spi_obj_t *self) { + self->has_lock = false; +} + +// Write the data contained in buffer +bool common_hal_busio_spi_write(busio_spi_obj_t *self, + const uint8_t *data, + size_t len) { + int ret = 0; + + mxc_spi_req_t wr_req = { + .spi = self->spi_regs, + .ssIdx = 0, + .txCnt = 0, + .rxCnt = 0, + .txData = (uint8_t *)data, + .txLen = len, + .rxData = NULL, + .rxLen = 0, + .ssDeassert = 1, + .completeCB = NULL, + .txDummyValue = 0xFF, + }; + ret = MXC_SPI_MasterTransaction(&wr_req); + if (ret) { + return false; + } else { + return true; + } +} + +// Read data into buffer +bool common_hal_busio_spi_read(busio_spi_obj_t *self, + uint8_t *data, size_t len, + uint8_t write_value) { + + int ret = 0; + + mxc_spi_req_t rd_req = { + .spi = self->spi_regs, + .ssIdx = 0, + .txCnt = 0, + .rxCnt = 0, + .txData = NULL, + .txLen = len, + .rxData = data, + .rxLen = len, + .ssDeassert = 1, + .completeCB = NULL, + .txDummyValue = write_value, + }; + ret = MXC_SPI_MasterTransaction(&rd_req); + if (ret) { + return false; + } else { + return true; + } +} + +// Write out the data in data_out +// while simultaneously reading data into data_in +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, + const uint8_t *data_out, + uint8_t *data_in, + size_t len) { + + int ret = 0; + + mxc_spi_req_t rd_req = { + .spi = self->spi_regs, + .ssIdx = 0, + .txCnt = 0, + .rxCnt = 0, + .txData = (uint8_t *)data_out, + .txLen = len, + .rxData = data_in, + .rxLen = len, + .ssDeassert = 1, + .completeCB = NULL, + .txDummyValue = 0xFF, + }; + ret = MXC_SPI_MasterTransaction(&rd_req); + if (ret) { + return false; + } else { + return true; + } +} + +// Get SPI baudrate +uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self) { + return self->baudrate; +} + +// Get SPI phase +uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t *self) { + return self->phase; +} + +// Get SPI polarity +uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) { + return self->polarity; +} diff --git a/ports/analog/common-hal/busio/SPI.h b/ports/analog/common-hal/busio/SPI.h new file mode 100644 index 0000000000000..d10601876fb5e --- /dev/null +++ b/ports/analog/common-hal/busio/SPI.h @@ -0,0 +1,41 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_SPI_H +#define MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_SPI_H + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +// HAL-specific +#include "spi.h" + +// Define a struct for what BUSIO.SPI should carry +typedef struct { + mp_obj_base_t base; + + // Spi regs & pins + int spi_id; + mxc_spi_regs_t *spi_regs; + const mcu_pin_obj_t *sck; + const mcu_pin_obj_t *mosi; + const mcu_pin_obj_t *miso; + const mcu_pin_obj_t *nss; + + // Configuration + uint32_t baudrate; + uint16_t prescaler; + uint8_t polarity; + uint8_t phase; + uint8_t bits; + + // Synch data + bool has_lock; +} busio_spi_obj_t; + +void spi_reset(void); + +#endif // MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_SPI_H diff --git a/ports/analog/common-hal/busio/UART.c b/ports/analog/common-hal/busio/UART.c new file mode 100644 index 0000000000000..be7851f52a21c --- /dev/null +++ b/ports/analog/common-hal/busio/UART.c @@ -0,0 +1,460 @@ +/* + * This file is part of Adafruit for EFR32 project + * + * The MIT License (MIT) + * + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + * + * 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. + */ + +#if CIRCUITPY_BUSIO_UART + +#include "mpconfigport.h" +#include "supervisor/shared/tick.h" + +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/UART.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared/readline/readline.h" +#include "shared/runtime/interrupt_char.h" + +#include "py/gc.h" +#include "py/ringbuf.h" +#include "py/mperrno.h" +#include "py/mpprint.h" +#include "py/runtime.h" + +#include "max32_port.h" +#include "UART.h" +#include "nvic_table.h" + +// UART IRQ Priority +#define UART_PRIORITY 1 + +typedef enum { + UART_9600 = 9600, + UART_14400 = 14400, + UART_19200 = 19200, + UART_38400 = 38400, + UART_57600 = 57600, + UART_115200 = 115200, + UART_230400 = 230400, + UART_460800 = 460800, + UART_921600 = 921600, +} uart_valid_baudrates; + +typedef enum { + UART_FREE = 0, + UART_BUSY, + UART_NEVER_RESET, +} uart_status_t; + +static uint32_t timeout_ms = 0; + +// Set each bit to indicate an active UART +// will be checked by ISR Handler for which ones to call +static uint8_t uarts_active = 0; +static uart_status_t uart_status[NUM_UARTS]; +static volatile int uart_err; +static uint8_t uart_never_reset_mask = 0; +static busio_uart_obj_t *context; + +static bool isValidBaudrate(uint32_t baudrate) { + switch (baudrate) { + case UART_9600: + return true; + break; + case UART_14400: + return true; + break; + case UART_19200: + return true; + break; + case UART_38400: + return true; + break; + case UART_57600: + return true; + break; + case UART_115200: + return true; + break; + case UART_230400: + return true; + break; + case UART_460800: + return true; + break; + case UART_921600: + return true; + break; + default: + return false; + break; + } +} + +static mxc_uart_parity_t convertParity(busio_uart_parity_t busio_parity) { + switch (busio_parity) { + case BUSIO_UART_PARITY_NONE: + return MXC_UART_PARITY_DISABLE; + case BUSIO_UART_PARITY_EVEN: + return MXC_UART_PARITY_EVEN_0; + case BUSIO_UART_PARITY_ODD: + return MXC_UART_PARITY_ODD_0; + default: + // not reachable due to validation in shared-bindings/busio/SPI.c + return MXC_UART_PARITY_DISABLE; + } +} + +void uart_isr(void) { + for (int i = 0; i < NUM_UARTS; i++) { + if (uarts_active & (1 << i)) { + MXC_UART_AsyncHandler(MXC_UART_GET_UART(i)); + } + } +} + +// Callback gets called when AsyncRequest is COMPLETE +// (e.g. txLen == txCnt) +static volatile void uartCallback(mxc_uart_req_t *req, int error) { + uart_status[MXC_UART_GET_IDX(req->uart)] = UART_FREE; + uart_err = error; + + MXC_SYS_Crit_Enter(); + ringbuf_put_n(context->ringbuf, req->rxData, req->rxLen); + MXC_SYS_Crit_Exit(); +} + +// Construct an underlying UART object. +void common_hal_busio_uart_construct(busio_uart_obj_t *self, + const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, + const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, + const mcu_pin_obj_t *rs485_dir, bool rs485_invert, + uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop, + mp_float_t timeout, uint16_t receiver_buffer_size, byte *receiver_buffer, + bool sigint_enabled) { + int err, temp; + + // Check for NULL Pointers && valid UART settings + assert(self); + + // Assign UART ID based on pins + temp = pinsToUart(tx, rx); + if (temp == -1) { + // Error will be indicated by pinsToUart(tx, rx) function + return; + } else { + self->uart_id = temp; + self->uart_regs = MXC_UART_GET_UART(temp); + } + assert((self->uart_id >= 0) && (self->uart_id < NUM_UARTS)); + + // Check for size of ringbuffer, desire powers of 2 + // At least use 1 byte if no size is given + assert((receiver_buffer_size & (receiver_buffer_size - 1)) == 0); + if (receiver_buffer_size == 0) { + receiver_buffer_size += 1; + } + + // Indicate RS485 not implemented + if ((rs485_dir != NULL) || (rs485_invert)) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("RS485")); + } + + if ((rx != NULL) && (tx != NULL)) { + err = MXC_UART_Init(self->uart_regs, baudrate, MXC_UART_IBRO_CLK); + if (err != E_NO_ERROR) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_UART); + } + + // attach & configure pins + self->tx_pin = tx; + self->rx_pin = rx; + common_hal_mcu_pin_claim(self->tx_pin); + common_hal_mcu_pin_claim(self->rx_pin); + } else { + mp_raise_NotImplementedError(MP_ERROR_TEXT("UART needs TX & RX")); + } + + if ((cts) && (rts)) { + MXC_UART_SetFlowCtrl(self->uart_regs, MXC_UART_FLOW_EN, 8); + self->cts_pin = cts; + self->rts_pin = rts; + common_hal_mcu_pin_claim(self->cts_pin); + common_hal_mcu_pin_claim(self->rts_pin); + } else if (cts || rts) { + mp_raise_ValueError(MP_ERROR_TEXT("Both RX and TX required for flow control")); + } + + // Set stop bits & data size + assert((stop == 1) || (stop == 2)); + mp_arg_validate_int(bits, 8, MP_QSTR_bits); + MXC_UART_SetDataSize(self->uart_regs, bits); + MXC_UART_SetStopBits(self->uart_regs, stop); + + // Set parity + MXC_UART_SetParity(self->uart_regs, convertParity(parity)); + + // attach UART parameters + self->stop_bits = stop; // must be 1 or 2 + self->bits = bits; + self->parity = parity; + self->baudrate = baudrate; + self->error = E_NO_ERROR; + + // Indicate to this module that the UART is active + uarts_active |= (1 << self->uart_id); + + // Set the timeout to a default value + if (((timeout < 0.0) || (timeout > 100.0))) { + self->timeout = 1.0; + } else { + self->timeout = timeout; + } + + // Initialize ringbuffer + if (receiver_buffer == NULL) { + self->ringbuf = m_malloc_without_collect(receiver_buffer_size); + if (!ringbuf_alloc(self->ringbuf, receiver_buffer_size)) { + m_malloc_fail(receiver_buffer_size); + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("Failed to allocate %q buffer"), + MP_QSTR_UART); + } + } else { + if (!(ringbuf_init(self->ringbuf, receiver_buffer, receiver_buffer_size))) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("Failed to allocate %q buffer"), + MP_QSTR_UART); + } + } + + context = self; + + // Setup UART interrupt + NVIC_ClearPendingIRQ(MXC_UART_GET_IRQ(self->uart_id)); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + NVIC_SetPriority(MXC_UART_GET_IRQ(self->uart_id), UART_PRIORITY); + NVIC_SetVector(MXC_UART_GET_IRQ(self->uart_id), (uint32_t)uart_isr); + + NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + + return; +} + +void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { + assert(self); + + if (!common_hal_busio_uart_deinited(self)) { + // First disable the ISR to avoid pre-emption + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + + // Shutdown the UART Controller + MXC_UART_Shutdown(self->uart_regs); + self->error = E_UNINITIALIZED; + + assert(self->rx_pin && self->tx_pin); + reset_pin_number(self->rx_pin->port, self->rx_pin->mask); + reset_pin_number(self->tx_pin->port, self->tx_pin->mask); + + if (self->cts_pin && self->rts_pin) { + reset_pin_number(self->cts_pin->port, self->cts_pin->mask); + reset_pin_number(self->rts_pin->port, self->rts_pin->mask); + } + + self->tx_pin = NULL; + self->rx_pin = NULL; + self->cts_pin = NULL; + self->rts_pin = NULL; + + ringbuf_deinit(self->ringbuf); + + // Indicate to this module that the UART is not active + uarts_active &= ~(1 << self->uart_id); + } +} + +bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { + if (uarts_active & (1 << self->uart_id)) { + return false; + } else { + return true; + }; +} + +// Read characters. len is in characters. +size_t common_hal_busio_uart_read(busio_uart_obj_t *self, + uint8_t *data, size_t len, int *errcode) { + int err; + uint32_t start_time = 0; + static size_t bytes_remaining; + + // Setup globals & status tracking + uart_err = E_NO_ERROR; + uarts_active |= (1 << self->uart_id); + uart_status[self->uart_id] = UART_BUSY; + bytes_remaining = len; + + mxc_uart_req_t uart_rd_req; + uart_rd_req.rxCnt = 0; + uart_rd_req.txCnt = 0; + uart_rd_req.rxData = data; + uart_rd_req.txData = NULL; + uart_rd_req.rxLen = bytes_remaining; + uart_rd_req.txLen = 0; + uart_rd_req.uart = self->uart_regs; + uart_rd_req.callback = (void *)uartCallback; + + // Initiate the read transaction + start_time = supervisor_ticks_ms64(); + err = MXC_UART_TransactionAsync(&uart_rd_req); + if (err != E_NO_ERROR) { + *errcode = err; + MXC_UART_AbortAsync(self->uart_regs); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("UART read error")); + } + + // Wait for transaction completion or timeout + while ((uart_status[self->uart_id] != UART_FREE) && + (supervisor_ticks_ms64() - start_time < (self->timeout * 1000))) { + } + + // If the timeout gets hit, abort and error out + if (uart_status[self->uart_id] != UART_FREE) { + MXC_UART_AbortAsync(self->uart_regs); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + mp_raise_RuntimeError(MP_ERROR_TEXT("UART transaction timeout")); + } + // Check for errors from the callback + else if (uart_err != E_NO_ERROR) { + mp_raise_RuntimeError(MP_ERROR_TEXT("UART read error")); + MXC_UART_AbortAsync(self->uart_regs); + } + + // Copy the data from the ringbuf (or return error) + MXC_SYS_Crit_Enter(); + err = ringbuf_get_n(context->ringbuf, data, len); + MXC_SYS_Crit_Exit(); + + return err; +} + +// Write characters. len is in characters NOT bytes! +// This function blocks until the timeout finishes +size_t common_hal_busio_uart_write(busio_uart_obj_t *self, + const uint8_t *data, size_t len, int *errcode) { + int err; + static size_t bytes_remaining; + + // Setup globals & status tracking + uart_err = E_NO_ERROR; + uarts_active |= (1 << self->uart_id); + uart_status[self->uart_id] = UART_BUSY; + bytes_remaining = len; + + mxc_uart_req_t uart_wr_req = {}; + + // Setup transaction + uart_wr_req.rxCnt = 0; + uart_wr_req.txCnt = 0; + uart_wr_req.rxData = NULL; + uart_wr_req.txData = data; + uart_wr_req.txLen = bytes_remaining; + uart_wr_req.rxLen = 0; + uart_wr_req.uart = self->uart_regs; + uart_wr_req.callback = (void *)uartCallback; + + // Start the transaction + err = MXC_UART_TransactionAsync(&uart_wr_req); + if (err != E_NO_ERROR) { + *errcode = err; + MXC_UART_AbortAsync(self->uart_regs); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + mp_raise_ValueError(MP_ERROR_TEXT("All UART peripherals are in use")); + } + + // Wait for transaction completion + while (uart_status[self->uart_id] != UART_FREE) { + // Call the handler and abort if errors + uart_err = MXC_UART_AsyncHandler(self->uart_regs); + if (uart_err != E_NO_ERROR) { + MXC_UART_AbortAsync(self->uart_regs); + } + } + // Check for errors from the callback + if (uart_err != E_NO_ERROR) { + MXC_UART_AbortAsync(self->uart_regs); + } + + return len; +} + +uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { + return self->baudrate; +} + +// Validate baudrate +void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { + if (isValidBaudrate(baudrate)) { + self->baudrate = baudrate; + } else { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_baudrate); + } +} + +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return self->timeout; +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + if (timeout > 100.0) { + mp_raise_ValueError(MP_ERROR_TEXT("Timeout must be < 100 seconds")); + } + + timeout_ms = 1000 * (uint32_t)timeout; + self->timeout = (uint32_t)timeout; + + return; +} + +uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { + return ringbuf_num_filled(self->ringbuf); +} + +void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { + MXC_UART_ClearRXFIFO(self->uart_regs); + ringbuf_clear(self->ringbuf); +} + +bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { + return !(MXC_UART_GetStatus(self->uart_regs) & (MXC_F_UART_STATUS_TX_BUSY)); +} + +void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { + common_hal_never_reset_pin(self->tx_pin); + common_hal_never_reset_pin(self->rx_pin); + common_hal_never_reset_pin(self->cts_pin); + common_hal_never_reset_pin(self->rts_pin); + uart_never_reset_mask |= (1 << (self->uart_id)); +} + +#endif // CIRCUITPY_BUSIO_UART diff --git a/ports/analog/common-hal/busio/UART.h b/ports/analog/common-hal/busio/UART.h new file mode 100644 index 0000000000000..296c738772e68 --- /dev/null +++ b/ports/analog/common-hal/busio/UART.h @@ -0,0 +1,39 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_UART_H +#define MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_UART_H + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" +#include "py/ringbuf.h" + +#include "max32_port.h" + +// Define a struct for what BUSIO.UART should contain +typedef struct { + mp_obj_base_t base; + int error; + float timeout; + + int uart_id; + int uart_map; + mxc_uart_regs_t *uart_regs; + ringbuf_t *ringbuf; + bool parity; + uint8_t bits; + uint8_t stop_bits; + uint32_t baudrate; + + const mcu_pin_obj_t *rx_pin; + const mcu_pin_obj_t *tx_pin; + const mcu_pin_obj_t *rts_pin; + const mcu_pin_obj_t *cts_pin; +} busio_uart_obj_t; + +void uart_reset(void); + +#endif // MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_UART_H diff --git a/ports/analog/common-hal/busio/__init__.c b/ports/analog/common-hal/busio/__init__.c new file mode 100644 index 0000000000000..ff05be051bb25 --- /dev/null +++ b/ports/analog/common-hal/busio/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT diff --git a/ports/analog/common-hal/digitalio/DigitalInOut.c b/ports/analog/common-hal/digitalio/DigitalInOut.c index 7d4048d77e70e..93e2242fbb6f6 100644 --- a/ports/analog/common-hal/digitalio/DigitalInOut.c +++ b/ports/analog/common-hal/digitalio/DigitalInOut.c @@ -107,7 +107,7 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( if (self->pin->port < 4) { // Check that I/O mode is enabled and we don't have in AND out on at the same time - MP_STATIC_ASSERT(!((port->en0 & mask) && (port->inen & mask) && (port->outen & mask))); + MP_STATIC_ASSERT_NONCONSTEXPR(!((port->en0 & mask) && (port->inen & mask) && (port->outen & mask))); if ((port->en0 & mask) && (port->outen & mask)) { return DIRECTION_OUTPUT; diff --git a/ports/analog/common-hal/microcontroller/Pin.c b/ports/analog/common-hal/microcontroller/Pin.c index 4545aa039c2fa..83e2f3b9c3a76 100644 --- a/ports/analog/common-hal/microcontroller/Pin.c +++ b/ports/analog/common-hal/microcontroller/Pin.c @@ -37,7 +37,7 @@ void reset_all_pins(void) { } void reset_pin_number(uint8_t pin_port, uint8_t pin_pad) { - if (pin_port == INVALID_PIN || pin_port > NUM_GPIO_PORTS) { + if ((pin_port == INVALID_PIN) || (pin_port > NUM_GPIO_PORTS)) { return; } diff --git a/ports/analog/common-hal/rtc/RTC.c b/ports/analog/common-hal/rtc/RTC.c new file mode 100644 index 0000000000000..c9d2258c1ece1 --- /dev/null +++ b/ports/analog/common-hal/rtc/RTC.c @@ -0,0 +1,42 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Nick Moore for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" +#include "shared/timeutils/timeutils.h" +#include "supervisor/port.h" + +// This is the time in seconds since 2000 that the RTC was started. +// TODO: Change the offset to ticks so that it can be a subsecond adjustment. +static uint32_t rtc_offset = 0; + +void common_hal_rtc_get_time(timeutils_struct_time_t *tm) { + uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024; + timeutils_seconds_since_2000_to_struct_time(rtc_offset + ticks_s, tm); +} + +void common_hal_rtc_set_time(timeutils_struct_time_t *tm) { + uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024; + uint32_t epoch_s = timeutils_seconds_since_2000( + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec + ); + rtc_offset = epoch_s - ticks_s; +} + +// the calibration function will be implemented in near future +// the RTC oscillator on my MAX32690-APARD is only off by 0.001 second +// the inaccuracy is still tolerable +int common_hal_rtc_get_calibration(void) { + return 0; +} + +void common_hal_rtc_set_calibration(int calibration) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_calibration); +} diff --git a/ports/analog/common-hal/rtc/RTC.h b/ports/analog/common-hal/rtc/RTC.h new file mode 100644 index 0000000000000..590bc93ab5231 --- /dev/null +++ b/ports/analog/common-hal/rtc/RTC.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Noralf Trønnes +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern void rtc_reset(void); diff --git a/ports/analog/common-hal/rtc/__init__.c b/ports/analog/common-hal/rtc/__init__.c new file mode 100644 index 0000000000000..ddf788bb0b5ad --- /dev/null +++ b/ports/analog/common-hal/rtc/__init__.c @@ -0,0 +1,6 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT diff --git a/ports/analog/max32_port.h b/ports/analog/max32_port.h index 5d92fcfe6d3ee..89830e96b0a49 100644 --- a/ports/analog/max32_port.h +++ b/ports/analog/max32_port.h @@ -22,29 +22,34 @@ #include "system_max32690.h" #include "max32690.h" +// UART Ports & pins +#include "peripherals/max32690/max32_uart.h" +#include "peripherals/max32690/max32_i2c.h" +#include "peripherals/max32690/max32_spi.h" + /** START: GPIO4 Handling specific to MAX32690 */ -#define GPIO4_PIN_MASK 0x00000003 -#define GPIO4_RESET_MASK 0xFFFFFF77 -#define GPIO4_OUTEN_MASK(mask) \ + #define GPIO4_PIN_MASK 0x00000003 + #define GPIO4_RESET_MASK 0xFFFFFF77 + #define GPIO4_OUTEN_MASK(mask) \ (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_OE_POS) | \ ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_OE_POS - 1))) -#define GPIO4_PULLDIS_MASK(mask) \ + #define GPIO4_PULLDIS_MASK(mask) \ (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_PE_POS) | \ ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_PE_POS - 1))) -#define GPIO4_DATAOUT_MASK(mask) \ + #define GPIO4_DATAOUT_MASK(mask) \ (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_DO_POS) | \ ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1))) -#define GPIO4_DATAOUT_GET_MASK(mask) \ + #define GPIO4_DATAOUT_GET_MASK(mask) \ ((((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_DO) >> MXC_F_MCR_GPIO4_CTRL_P40_DO_POS) | \ ((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_DO) >> \ (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1))) & \ mask) -#define GPIO4_DATAIN_MASK(mask) \ + #define GPIO4_DATAIN_MASK(mask) \ ((((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_IN) >> MXC_F_MCR_GPIO4_CTRL_P40_IN_POS) | \ ((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_IN) >> \ (MXC_F_MCR_GPIO4_CTRL_P41_IN_POS - 1))) & \ mask) -#define GPIO4_AFEN_MASK(mask) \ + #define GPIO4_AFEN_MASK(mask) \ (((mask & (1 << 0)) << MXC_F_MCR_OUTEN_PDOWN_OUT_EN_POS) | \ ((mask & (1 << 1)) >> (MXC_F_MCR_OUTEN_SQWOUT_EN_POS + 1))) /** END: GPIO4 Handling specific to MAX32690 */ diff --git a/ports/analog/mpconfigport.mk b/ports/analog/mpconfigport.mk index 67f1f79fb8121..f1cd0bb2901e9 100644 --- a/ports/analog/mpconfigport.mk +++ b/ports/analog/mpconfigport.mk @@ -22,9 +22,8 @@ INTERNAL_FLASH_FILESYSTEM = 1 #################################################################################### # These modules are implemented in ports//common-hal: -# Plan to implement -CIRCUITPY_BUSIO ?= 0 -CIRCUITPY_RTC ?= 0 +CIRCUITPY_BUSIO ?= 1 +CIRCUITPY_RTC ?= 1 # Other modules (may or may not implement): CIRCUITPY_ANALOGIO ?= 0 diff --git a/ports/analog/peripherals/max32690/gpios.h b/ports/analog/peripherals/max32690/gpios.h index 4677bf8f33dbe..fe91227728291 100644 --- a/ports/analog/peripherals/max32690/gpios.h +++ b/ports/analog/peripherals/max32690/gpios.h @@ -4,6 +4,8 @@ // // SPDX-License-Identifier: MIT +#pragma once + #include "py/obj.h" #include "py/mphal.h" diff --git a/ports/analog/peripherals/max32690/max32_i2c.c b/ports/analog/peripherals/max32690/max32_i2c.c new file mode 100644 index 0000000000000..4b9ec8b4db264 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_i2c.c @@ -0,0 +1,75 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/I2C.h" +#include "max32_i2c.h" +#include "max32690.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + + +/* Note: The MAX32690 assigns the same alternate function to multiple sets + * of pins. The drivers will enable both sets so that either can be used. + * Users should ensure the unused set is left unconnected. + * + * See MAX32690 Rev A2 Errata #16: + * https://www.analog.com/media/en/technical-documentation/data-sheets/max32690_a2_errata_rev2.pdf + * + * Additionally, note that the TQFN package does not expose some of the duplicate pins. For this package, + * enabling the un-routed GPIOs has been shown to cause initialization issues with the I2C block. + * To work around this, "MAX32690GTK_PACKAGE_TQFN" can be defined by the build system. The recommend place + * to do it is in the "board.mk" file of the BSP. This will prevent the inaccessible pins from being configured. + */ + +const mxc_gpio_cfg_t i2c_maps[NUM_I2C] = { + // I2C0 + { MXC_GPIO2, (MXC_GPIO_PIN_7 | MXC_GPIO_PIN_8), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C1 + { MXC_GPIO0, (MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C2 + { MXC_GPIO1, (MXC_GPIO_PIN_7 | MXC_GPIO_PIN_8), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0 }, +}; +#ifndef MAX32690GTK_PACKAGE_TQFN +const mxc_gpio_cfg_t i2c_maps_extra[NUM_I2C] = { + // I2C0A + { MXC_GPIO0, (MXC_GPIO_PIN_30 | MXC_GPIO_PIN_31), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_PULL_UP, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0 }, + // I2C1A + { MXC_GPIO2, (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_PULL_UP, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0 }, + // I2C2C + { MXC_GPIO0, (MXC_GPIO_PIN_13 | MXC_GPIO_PIN_14), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; +#endif + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl) { + for (int i = 0; i < NUM_I2C; i++) { + if ((i2c_maps[i].port == (MXC_GPIO_GET_GPIO(sda->port))) + && (i2c_maps[i].mask == ((sda->mask) | (scl->mask)))) { + return i; + } + } + + // Additional for loop to cover alternate potential I2C maps + #ifndef MAX32690GTK_PACKAGE_TQFN + for (int i = 0; i < NUM_I2C; i++) { + if ((i2c_maps_extra[i].port == (MXC_GPIO_GET_GPIO(sda->port))) + && (i2c_maps_extra[i].mask == ((sda->mask) | (scl->mask)))) { + return i; + } + } + #endif + + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32690/max32_i2c.h b/ports/analog/peripherals/max32690/max32_i2c.h new file mode 100644 index 0000000000000..b64cfd308dcf5 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_i2c.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "i2c_regs.h" +#include "mxc_sys.h" +#include "i2c.h" +#include "peripherals/pins.h" + +#define NUM_I2C 3 + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); diff --git a/ports/analog/peripherals/max32690/max32_spi.c b/ports/analog/peripherals/max32690/max32_spi.c new file mode 100644 index 0000000000000..c78fd64dbd705 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_spi.c @@ -0,0 +1,44 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/SPI.h" +#include "max32_spi.h" +#include "max32690.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { + // SPI0 + { MXC_GPIO2, (MXC_GPIO_PIN_27 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI1 + { MXC_GPIO1, (MXC_GPIO_PIN_26 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI2 + { MXC_GPIO2, (MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3 | MXC_GPIO_PIN_4), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI3 + { MXC_GPIO0, (MXC_GPIO_PIN_16 | MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI4 + { MXC_GPIO1, (MXC_GPIO_PIN_1 | MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck) { + for (int i = 0; i < NUM_SPI; i++) { + if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) + && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32690/max32_spi.h b/ports/analog/peripherals/max32690/max32_spi.h new file mode 100644 index 0000000000000..76bb48a59a7e5 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_spi.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "spi_regs.h" +#include "mxc_sys.h" +#include "spi.h" +#include "peripherals/pins.h" + +#define NUM_SPI 5 + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck); diff --git a/ports/analog/peripherals/max32690/max32_uart.c b/ports/analog/peripherals/max32690/max32_uart.c new file mode 100644 index 0000000000000..7d37708797415 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_uart.c @@ -0,0 +1,36 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/UART.h" +#include "max32_uart.h" +#include "max32690.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t uart_maps[NUM_UARTS] = { + { MXC_GPIO2, (MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO2, (MXC_GPIO_PIN_14 | MXC_GPIO_PIN_16), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO1, (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO3, (MXC_GPIO_PIN_0 | MXC_GPIO_PIN_1), MXC_GPIO_FUNC_ALT2, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 } +}; + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { + for (int i = 0; i < NUM_UARTS; i++) { + if ((uart_maps[i].port == (MXC_GPIO_GET_GPIO(tx->port))) + && (uart_maps[i].mask == ((tx->mask) | (rx->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32690/max32_uart.h b/ports/analog/peripherals/max32690/max32_uart.h new file mode 100644 index 0000000000000..f03b500a3c507 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_uart.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "uart_regs.h" +#include "mxc_sys.h" +#include "uart.h" +#include "peripherals/pins.h" + +#define NUM_UARTS 4 + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); diff --git a/ports/analog/supervisor/port.c b/ports/analog/supervisor/port.c index ff05ff2d28709..40e8e1d605038 100644 --- a/ports/analog/supervisor/port.c +++ b/ports/analog/supervisor/port.c @@ -39,6 +39,7 @@ // Sys includes #include "max32_port.h" +#include "nvic_table.h" // Timers #include "mxc_delay.h" @@ -72,12 +73,21 @@ volatile uint32_t system_ticks = 0; void SysTick_Handler(void) { system_ticks++; + + MXC_DelayHandler(); } safe_mode_t port_init(void) { int err = E_NO_ERROR; + // Set Vector Table to RAM & configure ARM core to use RAM-based ISRs + // This allows definition of ISRs with custom names + // + // Useful for mapping ISRs with names not related to a specific IRQn. + // Source: https://arm-software.github.io/CMSIS_5/Core/html/using_VTOR_pg.html + NVIC_SetRAM(); + // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); NVIC_EnableIRQ(SysTick_IRQn); diff --git a/ports/analog/tools/debug-dap.gdb b/ports/analog/tools/debug-dap.gdb new file mode 100644 index 0000000000000..d0aa7e2b13fa0 --- /dev/null +++ b/ports/analog/tools/debug-dap.gdb @@ -0,0 +1,3 @@ +target remote :3333 +break main +continue diff --git a/ports/analog/tools/debug-dap.sh b/ports/analog/tools/debug-dap.sh new file mode 100644 index 0000000000000..df2964fcb122a --- /dev/null +++ b/ports/analog/tools/debug-dap.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Primer on taking cmd line args in Linux shell scripts +# $0 is the script itself +# $1 $2 $3 are arg1, arg2, arg3, etc + +# Export OCD Path +### USER ACTION: Replace with your path to OpenOCD ### +OCD_PATH="~/MaximSDK/Tools/OpenOCD" + +# Call openocd to setup the debug server, storing the PID for OpenOCD +sh -c "openocd -s $OCD_PATH/scripts -f interface/cmsis-dap.cfg -f target/$1.cfg -c \"init; reset halt\" " & + +# Allow enough time for OCD server to set up +# + wait for the sleep to finish +sleep 3 & +wait $! + +# spawn the gdb process and store the gdb_pid +gdb-multiarch build-apard32690/firmware.elf -x "tools/debug-dap.gdb" + +# when gdb exits, kill all openocd processes +killall openocd diff --git a/ports/analog/tools/flash_max32.jlink b/ports/analog/tools/flash_max32.jlink index 4c9cbacb96fee..0453f4cb077fd 100644 --- a/ports/analog/tools/flash_max32.jlink +++ b/ports/analog/tools/flash_max32.jlink @@ -1,6 +1,7 @@ -si 1 +selectinterface swd erase -loadbin build-APARD/firmware.bin 0x10000000 -r -g +loadbin build-apard32690/firmware.bin 0x10000000 +reset +halt +go exit diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index e25b74d9a2893..e39804015063b 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -39,14 +39,14 @@ uint8_t find_sync_event_channel_raise(void) { } void audio_dma_disable_channel(uint8_t channel) { - if (channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (channel == NO_DMA_CHANNEL) { return; } dma_disable_channel(channel); } void audio_dma_enable_channel(uint8_t channel) { - if (channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (channel == NO_DMA_CHANNEL) { return; } dma_enable_channel(channel); @@ -171,8 +171,8 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, bool output_signed, uint32_t output_register_address, uint8_t dma_trigger_source) { - uint8_t dma_channel = dma_allocate_channel(true); - if (dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { + uint8_t dma_channel = dma_allocate_audio_channel(); + if (dma_channel == NO_DMA_CHANNEL) { return AUDIO_DMA_DMA_BUSY; } @@ -298,14 +298,14 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, void audio_dma_stop(audio_dma_t *dma) { uint8_t channel = dma->dma_channel; - if (channel < AUDIO_DMA_CHANNEL_COUNT) { + if (channel != NO_DMA_CHANNEL) { audio_dma_disable_channel(channel); disable_event_channel(dma->event_channel); MP_STATE_PORT(playing_audio)[channel] = NULL; audio_dma_state[channel] = NULL; dma_free_channel(dma->dma_channel); } - dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT; + dma->dma_channel = NO_DMA_CHANNEL; dma->playing_in_progress = false; } @@ -318,7 +318,7 @@ void audio_dma_resume(audio_dma_t *dma) { } bool audio_dma_get_paused(audio_dma_t *dma) { - if (dma->dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (dma->dma_channel == NO_DMA_CHANNEL) { return false; } uint32_t status = dma_transfer_status(dma->dma_channel); @@ -327,7 +327,7 @@ bool audio_dma_get_paused(audio_dma_t *dma) { } void audio_dma_init(audio_dma_t *dma) { - dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT; + dma->dma_channel = NO_DMA_CHANNEL; } void audio_dma_reset(void) { @@ -341,7 +341,7 @@ void audio_dma_reset(void) { } bool audio_dma_get_playing(audio_dma_t *dma) { - if (dma->dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (dma->dma_channel == NO_DMA_CHANNEL) { return false; } return dma->playing_in_progress; diff --git a/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk index 33165c8cfc5d0..9a2cdcd668ed2 100644 --- a/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk @@ -18,7 +18,7 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" -LONGINT_IMPL = NONE +LONGINT_IMPL = MPZ # the M0 Coin has limited functionality and many modules can be eliminated @@ -26,7 +26,7 @@ LONGINT_IMPL = NONE # Disable modules that are unusable on this special-purpose board. -CIRCUITPY_FULL_BUILD = 0 +CIRCUITPY_FULL_BUILD = 1 CIRCUITPY_AUDIOIO = 1 CIRCUITPY_DISPLAYIO = 0 @@ -38,7 +38,8 @@ CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 CIRCUITPY_USB_HID = 1 CIRCUITPY_USB_MIDI = 0 - +CIRCUITPY_NEOPIXEL_WRITE = 1 +CIRCUITPY_PIXELBUF = 1 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID diff --git a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk index 7c301e3ea9692..121becc472d36 100755 --- a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk @@ -11,4 +11,5 @@ EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ CIRCUITPY_CODEOP = 0 -CIRCUITPY_JPEGIO = 0 +CIRCUITPY_ERRNO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index 004181148415a..1152fb4acc419 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -10,4 +10,6 @@ SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ +CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index be48cb810550e..8fdf20f186b00 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -20,6 +20,8 @@ #define SPI_FLASH_SCK_PIN &pin_PA09 #define SPI_FLASH_CS_PIN &pin_PA13 +#define BOARD_HAS_CRYSTAL 1 + #define DEFAULT_I2C_BUS_SCL (&pin_PA23) #define DEFAULT_I2C_BUS_SDA (&pin_PA22) diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index 573a69bee327c..dd58e8d1ce5a7 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -11,3 +11,5 @@ EXTERNAL_FLASH_DEVICES = "S25FL064L" LONGINT_IMPL = MPZ CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk index a7c18acba3c55..ee414b6e214b0 100644 --- a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk @@ -17,6 +17,7 @@ CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_GIFIO = 0 CIRCUITPY_I2CTARGET = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_PS2IO = 0 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_LTO_PARTITION = one diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk index 4958581056e68..f780ea4aa3d0f 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -14,6 +14,7 @@ CIRCUITPY__EVE = 1 CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_VECTORIO = 0 diff --git a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk index 3dbef7c576a13..76c60b4464639 100644 --- a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk @@ -16,6 +16,7 @@ CIRCUITPY_EPAPERDISPLAY = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_I2CDISPLAYBUS = 0 CIRCUITPY_I2CTARGET = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_PARALLELDISPLAYBUS = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_SHARPDISPLAY = 0 diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk index 27bf8c165da88..be22cb94fae92 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk @@ -10,11 +10,13 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "GD25Q16C,W25Q16JVxQ" LONGINT_IMPL = MPZ +CIRCUITPY__EVE = 1 CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_GIFIO = 0 CIRCUITPY_JPEGIO = 0 -CIRCUITPY_TILEPALETTEMAPPER = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 CIRCUITPY_BITBANG_APA102 = 1 diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index d758d6878fb7f..d4801359cf8c5 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -11,4 +11,5 @@ EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk index 69cd5b0e2863e..cb7e690c6c02d 100644 --- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk @@ -11,9 +11,13 @@ EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ CIRCUITPY__EVE = 0 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 + # We don't have room for the fonts for terminalio for certain languages, # so turn off terminalio, and if it's off and displayio is on, diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk index 55a307ed4e308..d5aef01a0374f 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk @@ -14,6 +14,7 @@ CIRCUITPY__EVE = 1 CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_VECTORIO = 0 diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk index 73c56fb5fbab3..8fae53c0101f9 100644 --- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk @@ -10,9 +10,13 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q16JVxM, W25Q16JVxQ" LONGINT_IMPL = MPZ +CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 CIRCUITPY_BITBANG_APA102 = 1 diff --git a/ports/atmel-samd/boards/openbook_m4/board.c b/ports/atmel-samd/boards/openbook_m4/board.c index 95027e817e8b8..fb75cac3a4ee7 100644 --- a/ports/atmel-samd/boards/openbook_m4/board.c +++ b/ports/atmel-samd/boards/openbook_m4/board.c @@ -53,42 +53,24 @@ void board_init(void) { epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct(display, - bus, - start_sequence, - sizeof(start_sequence), - 0, // start up time - stop_sequence, - sizeof(stop_sequence), - 300, // width - 400, // height - 300, // RAM width - 400, // RAM height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x13, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command (can add this for grayscale eventually) - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, // refresh_display_sequence - sizeof(refresh_sequence), - 40, // refresh_time - &pin_PA01, // busy_pin - false, // busy_state - 5, // seconds_per_frame - false, // chip_select (don't always toggle chip select) - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = start_sequence; + args.start_sequence_len = sizeof(start_sequence); + args.stop_sequence = stop_sequence; + args.stop_sequence_len = sizeof(stop_sequence); + args.width = 300; + args.height = 400; + args.ram_width = 300; + args.ram_height = 400; + args.rotation = 270; + args.write_black_ram_command = 0x13; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 40.0; + args.busy_pin = &pin_PA01; + args.seconds_per_frame = 5.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk index dd8afd51f6e60..4ade6a148315d 100644 --- a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk +++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk @@ -9,6 +9,14 @@ CHIP_FAMILY = samd51 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_SHARPDISPLAY = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk index d19e606319b63..441853c554df9 100644 --- a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk +++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk @@ -9,3 +9,6 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk index 64049e8d5981c..b34dfb3d2e624 100755 --- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk @@ -11,4 +11,5 @@ EXTERNAL_FLASH_DEVICES = "W25Q32FV" LONGINT_IMPL = MPZ CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c index a1a67d0408247..f409563f5ed69 100644 --- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -364,7 +364,7 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) { // output_buffer_length is the number of slots, not the number of bytes. uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self, uint16_t *output_buffer, uint32_t output_buffer_length) { - uint8_t dma_channel = dma_allocate_channel(true); + uint8_t dma_channel = dma_allocate_audio_channel(); pdmin_event_channel = find_sync_event_channel_raise(); pdmin_dma_block_done = false; diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index e13b5410ae32a..da108709feaff 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -135,6 +135,7 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { if (common_hal_busio_i2c_deinited(self)) { return; } + allow_reset_sercom(self->i2c_desc.device.hw); i2c_m_sync_disable(&self->i2c_desc); i2c_m_sync_deinit(&self->i2c_desc); diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index 5d7633be7f8d3..5dd7bedebc394 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -21,7 +21,17 @@ #include "samd/dma.h" #include "samd/sercom.h" -void setup_pin(const mcu_pin_obj_t *pin, uint32_t pinmux); + +static void setup_pin(const mcu_pin_obj_t *pin, uint32_t pinmux, const enum gpio_direction direction) { + gpio_set_pin_direction(pin->number, direction); + gpio_set_pin_pull_mode(pin->number, GPIO_PULL_OFF); + gpio_set_pin_function(pin->number, pinmux); + if (direction == GPIO_DIRECTION_OUT) { + // Use strong drive strength for SPI outputs. + hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin->number), GPIO_PIN(pin->number)); + } + claim_pin(pin); +} void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, @@ -128,6 +138,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // Pads must be set after spi_m_sync_init(), which uses default values from // the prototypical SERCOM. + // Set to SPI host mode and choose pads. hri_sercomspi_write_CTRLA_MODE_bf(sercom, 3); hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo); hri_sercomspi_write_CTRLA_DIPO_bf(sercom, miso_pad); @@ -141,20 +152,20 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_OSError(MP_EIO); } - setup_pin(clock, clock_pinmux); + setup_pin(clock, clock_pinmux, GPIO_DIRECTION_OUT); self->clock_pin = clock->number; if (mosi_none) { self->MOSI_pin = NO_PIN; } else { - setup_pin(mosi, mosi_pinmux); + setup_pin(mosi, mosi_pinmux, GPIO_DIRECTION_OUT); self->MOSI_pin = mosi->number; } if (miso_none) { self->MISO_pin = NO_PIN; } else { - setup_pin(miso, miso_pinmux); + setup_pin(miso, miso_pinmux, GPIO_DIRECTION_IN); self->MISO_pin = miso->number; } @@ -317,11 +328,3 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) { void *hw = self->spi_desc.dev.prvt; return hri_sercomspi_get_CTRLA_CPOL_bit(hw); } - -void setup_pin(const mcu_pin_obj_t *pin, uint32_t pinmux) { - gpio_set_pin_direction(pin->number, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(pin->number, GPIO_PULL_OFF); - gpio_set_pin_function(pin->number, pinmux); - claim_pin(pin); - hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin->number), GPIO_PIN(pin->number)); -} diff --git a/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c index a6d8fef0f394b..56eb82678ec01 100644 --- a/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c +++ b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c @@ -135,7 +135,8 @@ void common_hal_imagecapture_parallelimagecapture_singleshot_capture(imagecaptur mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_RW); - uint8_t dma_channel = dma_allocate_channel(true); + // Allocate a permanent channel (not really audio). + uint8_t dma_channel = dma_allocate_audio_channel(); uint32_t *dest = bufinfo.buf; size_t count = bufinfo.len / 4; // PCC receives 4 bytes (2 pixels) at a time diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c index c6cd4605784ab..a8c87d82ed268 100644 --- a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c @@ -17,6 +17,10 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + if (!pin_a->has_extint) { raise_ValueError_invalid_pin_name(MP_QSTR_pin_a); } @@ -83,10 +87,13 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o turn_off_eic_channel(self->eic_channel_b); reset_pin_number(self->pin_a); - self->pin_a = NO_PIN; - reset_pin_number(self->pin_b); - self->pin_b = NO_PIN; + + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { + self->pin_a = NO_PIN; } void incrementalencoder_interrupt_handler(uint8_t channel) { diff --git a/ports/atmel-samd/common-hal/spitarget/SPITarget.c b/ports/atmel-samd/common-hal/spitarget/SPITarget.c index b9062911cc353..e5011b141fc12 100644 --- a/ports/atmel-samd/common-hal/spitarget/SPITarget.c +++ b/ports/atmel-samd/common-hal/spitarget/SPITarget.c @@ -192,7 +192,7 @@ void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t * self->miso_packet = miso_packet; Sercom *sercom = self->spi_desc.dev.prvt; - self->running_dma = shared_dma_transfer_start(sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0); + shared_dma_transfer_start(&self->running_dma, sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0); // There is an issue where if an unexpected SPI transfer is received before the user calls "end" for the in-progress, expected // transfer, the SERCOM has an error and gets confused. This can be detected from INTFLAG.ERROR. I think the code in @@ -200,7 +200,7 @@ void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t * // s->SPI.DATA.reg) is supposed to fix this, but experimentation seems to show that it does not in fact fix anything. Anyways, if // the ERROR bit is set, let's just reset the peripheral and then setup the transfer again -- that seems to work. if (hri_sercomspi_get_INTFLAG_ERROR_bit(sercom)) { - shared_dma_transfer_close(self->running_dma); + shared_dma_transfer_close(&self->running_dma); // disable the sercom spi_m_sync_disable(&self->spi_desc); @@ -223,19 +223,19 @@ void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t * spi_m_sync_enable(&self->spi_desc); hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK); - self->running_dma = shared_dma_transfer_start(sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0); + shared_dma_transfer_start(&self->running_dma, sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0); } } bool common_hal_spitarget_spi_target_transfer_is_finished(spitarget_spi_target_obj_t *self) { - return self->running_dma.failure == 1 || shared_dma_transfer_finished(self->running_dma); + return self->running_dma.failure == 1 || shared_dma_transfer_finished(&self->running_dma); } int common_hal_spitarget_spi_target_transfer_close(spitarget_spi_target_obj_t *self) { if (self->running_dma.failure == 1) { return 0; } - int res = shared_dma_transfer_close(self->running_dma); + int res = shared_dma_transfer_close(&self->running_dma); self->running_dma.failure = 1; self->mosi_packet = NULL; diff --git a/ports/atmel-samd/common-hal/spitarget/SPITarget.h b/ports/atmel-samd/common-hal/spitarget/SPITarget.h index 50f2bcb33094b..9fff23c174370 100644 --- a/ports/atmel-samd/common-hal/spitarget/SPITarget.h +++ b/ports/atmel-samd/common-hal/spitarget/SPITarget.h @@ -18,7 +18,7 @@ typedef struct { uint8_t *mosi_packet; const uint8_t *miso_packet; - dma_descr_t running_dma; + dma_transfer_t running_dma; } spitarget_spi_target_obj_t; #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals index d3210221bbd01..863e615ff98c3 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit d3210221bbd018ae9d0183ea4640c42cf4bce672 +Subproject commit 863e615ff98c3a8aa904e87a157553559c933b81 diff --git a/ports/cxd56/mpconfigport.h b/ports/cxd56/mpconfigport.h index 3bcb252868786..f0a57248bebef 100644 --- a/ports/cxd56/mpconfigport.h +++ b/ports/cxd56/mpconfigport.h @@ -8,6 +8,9 @@ #define MICROPY_PY_SYS_PLATFORM "CXD56" +// SD card socket on board is configured for sdioio, which is not supported for automatic USB presentation. +#define CIRCUITPY_SDCARD_USB (0) + // 64kiB stack #define CIRCUITPY_DEFAULT_STACK_SIZE (0x10000) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index a063101991fdb..b6ddc27e4084c 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -8,6 +8,8 @@ include ../../py/circuitpy_mkenv.mk ifeq ($(IDF_TARGET),esp32s3) BT_IDF_TARGET = esp32c3 +else ifeq ($(IDF_TARGET),esp32c61) +BT_IDF_TARGET = esp32c6 else BT_IDF_TARGET = $(IDF_TARGET) endif @@ -64,6 +66,7 @@ INC += \ -isystem esp-idf/components/esp_driver_i2s/include \ -isystem esp-idf/components/esp_driver_$(IDF_TARGET)/include \ -isystem esp-idf/components/esp_driver_ledc/include \ + -isystem esp-idf/components/esp_driver_parlio/include \ -isystem esp-idf/components/esp_driver_pcnt/include \ -isystem esp-idf/components/esp_driver_rmt/include \ -isystem esp-idf/components/esp_driver_sdio/include \ @@ -149,6 +152,8 @@ CFLAGS += -DSTACK_CANARY_VALUE=0xa5a5a5a5 REGISTRATION_FUNCTIONS = \ -u ld_include_highint_hdl \ -u __cxx_fatal_exception \ + -u __cxx_init_dummy \ + -u __cxa_guard_dummy \ -u esp_app_desc \ -u esp_timer_init_include_func \ -u uart_vfs_include_dev_init \ @@ -156,13 +161,17 @@ REGISTRATION_FUNCTIONS = \ -u __ubsan_include \ -u esp_system_include_startup_funcs \ -u esp_efuse_startup_include_func \ - -u newlib_include_heap_impl \ - -u newlib_include_syscalls_impl \ - -u newlib_include_pthread_impl \ - -u newlib_include_assert_impl \ - -u newlib_include_init_funcs \ + -u esp_libc_include_heap_impl \ + -u esp_libc_include_reent_syscalls_impl \ + -u esp_libc_include_syscalls_impl \ + -u esp_libc_include_pthread_impl \ + -u esp_libc_include_assert_impl \ + -u esp_libc_include_getentropy_impl \ + -u esp_libc_include_init_funcs \ + -u esp_libc_init_funcs \ -u include_esp_phy_override \ - -u vfs_include_syscalls_impl + -u vfs_include_syscalls_impl \ + -u esp_vfs_include_nullfs_register #Debugging/Optimization @@ -196,7 +205,6 @@ CFLAGS += $(INC) -Werror -Wall -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_D # Most current ESPs have nano versions of newlib in ROM so we use them. ifneq ($(IDF_TARGET),esp32c6) CFLAGS += --specs=nano.specs - LDFLAGS += -T$(IDF_TARGET).rom.newlib-nano.ld else LDFLAGS += -T$(IDF_TARGET).rom.newlib-normal.ld endif @@ -222,7 +230,6 @@ else ifeq ($(IDF_TARGET_ARCH),riscv) -Trom.api.ld endif -$(BUILD)/lib/tlsf/tlsf.o: CFLAGS += -Wno-cast-align LDFLAGS += $(CFLAGS) -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref -Wl,--undefined=uxTopUsedPriority @@ -244,7 +251,9 @@ LDFLAGS += \ ifeq ($(IDF_TARGET),esp32) LDFLAGS += \ -Tesp32.rom.newlib-data.ld \ - -Tesp32.rom.newlib-funcs.ld \ + -Tesp32.rom.syscalls.ld \ + -Tesp32.rom.libc-funcs.ld \ + -Tesp32.rom.newlib-reent-funcs.ld \ -Tesp32.rom.spiflash_legacy.ld CHIP_COMPONENTS = \ @@ -254,7 +263,9 @@ else ifeq ($(IDF_TARGET),esp32c2) LDFLAGS += \ -Tesp32c2.rom.ble.ld \ -Tesp32c2.rom.heap.ld \ + -Tesp32c2.rom.libc.ld \ -Tesp32c2.rom.newlib.ld \ + -Tesp32c2.rom.newlib-nano.ld \ -Tesp32c2.rom.version.ld \ -Tesp32c2.rom.systimer.ld \ -Tesp32c2.rom.wdt.ld @@ -267,6 +278,7 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32c3) LDFLAGS += \ -Tesp32c3.rom.newlib.ld \ + -Tesp32c3.rom.libc.ld \ -Tesp32c3.rom.version.ld \ -Tesp32c3.rom.eco3_bt_funcs.ld \ -Tesp32c3.rom.eco3.ld \ @@ -280,6 +292,7 @@ LDFLAGS += \ -Tesp32c6.rom.phy.ld \ -Tesp32c6.rom.pp.ld \ -Tesp32c6.rom.net80211.ld \ + -Tesp32c6.rom.libc.ld \ -Tesp32c6.rom.newlib.ld \ -Tesp32c6.rom.coexist.ld \ -Tesp32c6.rom.heap.ld \ @@ -287,11 +300,29 @@ LDFLAGS += \ -Tesp32c6.rom.wdt.ld +CHIP_COMPONENTS = \ + esp_driver_tsens + +else ifeq ($(IDF_TARGET),esp32c61) +LDFLAGS += \ + -Tesp32c61.rom.phy.ld \ + -Tesp32c61.rom.pp.ld \ + -Tesp32c61.rom.net80211.ld \ + -Tesp32c61.rom.libc.ld \ + -Tesp32c61.rom.newlib.ld \ + -Tesp32c61.rom.version.ld \ + -Tesp32c61.rom.coexist.ld \ + -Tesp32c61.rom.heap.ld \ + -Tesp32c61.rom.systimer.ld \ + -Tesp32c61.rom.wdt.ld + + CHIP_COMPONENTS = \ esp_driver_tsens else ifeq ($(IDF_TARGET),esp32p4) LDFLAGS += \ + -Tesp32p4.rom.libc.ld \ -Tesp32p4.rom.newlib.ld \ -Tesp32p4.rom.systimer.ld \ -Tesp32p4.rom.wdt.ld @@ -303,6 +334,7 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32h2) LDFLAGS += \ -Tesp32h2.rom.heap.ld \ + -Tesp32h2.rom.libc.ld \ -Tesp32h2.rom.newlib.ld \ -Tesp32h2.rom.systimer.ld \ -Tesp32h2.rom.wdt.ld @@ -312,8 +344,9 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32s2) LDFLAGS += \ + -Tesp32s2.rom.libc-funcs.ld \ -Tesp32s2.rom.newlib-data.ld \ - -Tesp32s2.rom.newlib-funcs.ld \ + -Tesp32s2.rom.newlib-reent-funcs.ld \ -Tesp32s2.rom.spiflash_legacy.ld CHIP_COMPONENTS = \ @@ -322,6 +355,7 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32s3) LDFLAGS += \ + -Tesp32s3.rom.libc.ld \ -Tesp32s3.rom.newlib.ld \ -Tesp32s3.rom.version.ld \ -Tesp32s3.rom.systimer.ld \ @@ -350,6 +384,8 @@ else ifeq ($(IDF_TARGET),esp32c3) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32C3 else ifeq ($(IDF_TARGET),esp32c6) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32C6 +else ifeq ($(IDF_TARGET),esp32c61) +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32C61 else ifeq ($(IDF_TARGET),esp32p4) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32P4 else ifeq ($(IDF_TARGET),esp32h2) @@ -662,7 +698,8 @@ ifneq ($(IDF_TARGET),esp32p4) BINARY_BLOBS = esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libphy.a endif ifneq ($(CIRCUITPY_WIFI),0) - BINARY_BLOBS += esp-idf/components/esp_coex/lib/$(IDF_TARGET)/libcoexist.a $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS)) + BINARY_BLOBS += $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS)) + BINARY_BLOBS += esp-idf/components/esp_coex/lib/$(IDF_TARGET)/libcoexist.a ifneq ($(IDF_TARGET),esp32c2) BINARY_BLOBS += $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, libmesh.a libwapi.a) endif @@ -682,6 +719,7 @@ ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) BLE_IMPL_esp32c2 := libble BLE_IMPL_esp32c3 := esp32c3 BLE_IMPL_esp32c6 := libble + BLE_IMPL_esp32c61 := libble BLE_IMPL_esp32h2 := libble BLE_IMPL = $(BLE_IMPL_$(IDF_TARGET)) @@ -700,8 +738,8 @@ ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) ifeq ($(BLE_IMPL),libble) BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a - ifeq ($(IDF_TARGET),esp32c6) - BINARY_BLOBS += esp-idf/components/bt/controller/lib_$(IDF_TARGET)/$(IDF_TARGET)-bt-lib/$(IDF_TARGET)/libble_app.a + ifeq ($(BT_IDF_TARGET),esp32c6) + BINARY_BLOBS += esp-idf/components/bt/controller/lib_$(BT_IDF_TARGET)/$(BT_IDF_TARGET)-bt-lib/$(IDF_TARGET)/libble_app.a else BINARY_BLOBS += esp-idf/components/bt/controller/lib_$(IDF_TARGET)/$(IDF_TARGET)-bt-lib/libble_app.a endif @@ -769,6 +807,8 @@ else ifeq ($(IDF_TARGET),esp32c3) BOOTLOADER_OFFSET = 0x0 else ifeq ($(IDF_TARGET),esp32c6) BOOTLOADER_OFFSET = 0x0 +else ifeq ($(IDF_TARGET),esp32c61) +BOOTLOADER_OFFSET = 0x0 else ifeq ($(IDF_TARGET),esp32p4) BOOTLOADER_OFFSET = 0x2000 else ifeq ($(IDF_TARGET),esp32s3) @@ -782,7 +822,7 @@ endif IDF_CMAKE_TARGETS = \ bootloader/bootloader.bin \ - esp-idf/esp_system/__ldgen_output_sections.ld \ + __ldgen_output_sections.ld \ $(foreach component, $(ESP_IDF_COMPONENTS_LINK), esp-idf/$(component)/lib$(component).a) PARTITION_TABLE_OFFSET = 0x8000 diff --git a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c index c4311474f6061..d37233b7f2420 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c @@ -217,75 +217,54 @@ void board_init(void) { display->base.type = &epaperdisplay_epaperdisplay_type; if (is_ssd1680) { - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - ssd1680_display_start_sequence, sizeof(ssd1680_display_start_sequence), - 0, // start up time - ssd1680_display_stop_sequence, sizeof(ssd1680_display_stop_sequence), - 296, // width - 128, // height - 250, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - 0x44, // set_column_window_command - 0x45, // set_row_window_command - 0x4e, // set_current_column_command - 0x4f, // set_current_row_command - 0x24, // write_black_ram_command - false, // black_bits_inverted - 0x26, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - ssd1680_display_refresh_sequence, sizeof(ssd1680_display_refresh_sequence), - 1.0, // refresh_time - &pin_GPIO5, // busy_pin - true, // busy_state - 5.0, // seconds_per_frame - false, // always_toggle_chip_select - true, // grayscale - false, // acep - false, // spectra6 - true, // two_byte_sequence_length - true); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = ssd1680_display_start_sequence; + args.start_sequence_len = sizeof(ssd1680_display_start_sequence); + args.stop_sequence = ssd1680_display_stop_sequence; + args.stop_sequence_len = sizeof(ssd1680_display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 250; + args.ram_height = 296; + args.rotation = 270; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4e; + args.set_current_row_command = 0x4f; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.refresh_sequence = ssd1680_display_refresh_sequence; + args.refresh_sequence_len = sizeof(ssd1680_display_refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO5; + args.busy_state = true; + args.seconds_per_frame = 5.0; + args.grayscale = true; + args.two_byte_sequence_length = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } else { - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - il0373_display_start_sequence, sizeof(il0373_display_start_sequence), - 0, // start up time - il0373_display_stop_sequence, sizeof(il0373_display_stop_sequence), - 296, // width - 128, // height - 160, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x10, // write_black_ram_command - false, // black_bits_inverted - 0x13, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - il0373_display_refresh_sequence, sizeof(il0373_display_refresh_sequence), - 1.0, // refresh_time - &pin_GPIO5, // busy_pin - false, // busy_state - 5.0, // seconds_per_frame - false, // always_toggle_chip_select - true, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = il0373_display_start_sequence; + args.start_sequence_len = sizeof(il0373_display_start_sequence); + args.stop_sequence = il0373_display_stop_sequence; + args.stop_sequence_len = sizeof(il0373_display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 160; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = 0x10; + args.write_color_ram_command = 0x13; + args.refresh_sequence = il0373_display_refresh_sequence; + args.refresh_sequence_len = sizeof(il0373_display_refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO5; + args.seconds_per_frame = 5.0; + args.grayscale = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } } diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk index 515b6da5c07c4..9ca2eee157748 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk +++ b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk @@ -9,4 +9,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 2MB CIRCUITPY_DUALBANK = 0 +CIRCUITPY_JPEGIO = 0 + CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig index e962866216039..5fd531f274a6a 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig +++ b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig @@ -9,6 +9,18 @@ # # end of LWIP +# +# Wireless Coexistence +# +# CONFIG_ESP_COEX_SW_COEXIST_ENABLE is not set +# end of Wireless Coexistence + +# +# LibC +# +# CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS is not set +# end of LibC + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c index b7f8bc50e714a..04f5f92f85ba9 100644 --- a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c +++ b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c @@ -63,43 +63,30 @@ void board_init(void) { 0, // Polarity 0); // Phase -// Set up the DisplayIO epaper object + // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 1, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 400, // width - 300, // height - 400, // ram_width - 300, // ram_height - 0, // colstart - 0, // rowstart - 0, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x24, // write_black_ram_command - false, // black_bits_inverted - 0x26, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO48, // busy_pin - true, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 1.0; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 400; + args.height = 300; + args.ram_width = 400; + args.ram_height = 300; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO48; + args.busy_state = true; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/board.c b/ports/espressif/boards/espressif_esp32c3_lyra_v2/board.c new file mode 100644 index 0000000000000..b3b20cfe2d3f0 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.h b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.h new file mode 100644 index 0000000000000..d38d4f4d09fdf --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Board setup +#define MICROPY_HW_BOARD_NAME "ESP32-C3-Lyra-V2" +#define MICROPY_HW_MCU_NAME "ESP32-C3N4" + +// Status LED +#define MICROPY_HW_NEOPIXEL (&pin_GPIO10) +#define MICROPY_HW_NEOPIXEL_COUNT (1) + +// Default bus pins +#define DEFAULT_UART_BUS_RX (&pin_GPIO20) +#define DEFAULT_UART_BUS_TX (&pin_GPIO21) + +// Serial over UART +#define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX +#define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.mk new file mode 100644 index 0000000000000..4b23a76ba6a15 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.mk @@ -0,0 +1,10 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x00C3A000 + +IDF_TARGET = esp32c3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/pins.c b/ports/espressif/boards/espressif_esp32c3_lyra_v2/pins.c new file mode 100644 index 0000000000000..5f7c3d084dd3f --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/pins.c @@ -0,0 +1,41 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_MTMS), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_MTDI), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_MTCK), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_MTDO), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/sdkconfig b/ports/espressif/boards/espressif_esp32c3_lyra_v2/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/board.c b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.h b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.h new file mode 100644 index 0000000000000..d901bfb37ba28 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-C61-DevKitC-1-N8R2" +#define MICROPY_HW_MCU_NAME "ESP32C61" + +#define DEFAULT_UART_BUS_RX (&pin_GPIO10) +#define DEFAULT_UART_BUS_TX (&pin_GPIO11) diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.mk new file mode 100644 index 0000000000000..1092a874a6868 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.mk @@ -0,0 +1,13 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x00C61001 + +IDF_TARGET = esp32c61 +IDF_TARGET_ARCH = riscv + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/pins.c b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/pins.c new file mode 100644 index 0000000000000..901e52166576b --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/pins.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_IO24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_IO28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_IO29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/sdkconfig b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/heltec_vision_master_e290/board.c b/ports/espressif/boards/heltec_vision_master_e290/board.c index 5911506ae2c3c..9749f5c704881 100644 --- a/ports/espressif/boards/heltec_vision_master_e290/board.c +++ b/ports/espressif/boards/heltec_vision_master_e290/board.c @@ -61,43 +61,37 @@ void board_init(void) { 0, // Polarity 0); // Phase -// Set up the DisplayIO epaper object + // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 296, // width - 128, // height - 250, // ram_width - 296, // ram_height - 8, // colstart - 0, // rowstart - 90, // rotation - 0x44, // set_column_window_command - 0x45, // set_row_window_command - 0x4E, // set_current_column_command - 0x4F, // set_current_row_command - 0x24, // write_black_ram_command - false, // black_bits_inverted - 0x26, // write_color_ram_command - false, // color_bits_inverted - 0xFF0000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO6, // busy_pin - true, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - true); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 250; + args.ram_height = 296; + args.colstart = 8; + args.rotation = 90; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4E; + args.set_current_row_command = 0x4F; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.highlight_color = 0xFF0000; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO6; + args.busy_state = true; + args.seconds_per_frame = 2.0; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/espressif/boards/heltec_wireless_paper/board.c b/ports/espressif/boards/heltec_wireless_paper/board.c index 89e7a054b50c2..c796a9be8843d 100644 --- a/ports/espressif/boards/heltec_wireless_paper/board.c +++ b/ports/espressif/boards/heltec_wireless_paper/board.c @@ -101,43 +101,29 @@ void board_init(void) { 0, // Polarity 0); // Phase -// Set up the DisplayIO epaper object + // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 250, // width - 122, // height - 128, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x13, // write_black_ram_command - false, // black_bits_inverted - 0x10, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO7, // busy_pin - false, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 250; + args.height = 122; + args.ram_width = 128; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = 0x13; + args.write_color_ram_command = 0x10; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO7; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk b/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk index cd18ccf8a5a81..bc30ae3afd5e9 100644 --- a/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk @@ -13,4 +13,4 @@ CIRCUITPY_ESP_FLASH_SIZE = 8MB CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_MAX3421E = 0 -SRC_C += boards/$(BOARD)/cardputer_keyboard.c +SRC_C += module/cardputer_keyboard.c diff --git a/ports/espressif/boards/m5stack_cardputer_ros/cardputer_keyboard.c b/ports/espressif/boards/m5stack_cardputer_ros/cardputer_keyboard.c deleted file mode 100644 index 73880f66e19d9..0000000000000 --- a/ports/espressif/boards/m5stack_cardputer_ros/cardputer_keyboard.c +++ /dev/null @@ -1,238 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft -// -// SPDX-License-Identifier: MIT - -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" - -#include "supervisor/shared/serial.h" -#include "shared-bindings/keypad/EventQueue.h" -#include "shared-bindings/keypad_demux/DemuxKeyMatrix.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "shared-module/keypad/EventQueue.h" -#include "shared-module/keypad_demux/DemuxKeyMatrix.h" -#include "supervisor/shared/reload.h" - -#include "keymap.h" - -//| """M5Stack Cardputer keyboard integration. -//| """ -//| -//| """The KEYBOARD object is an instance of DemuxKeyMatrix, configured with correct pins. -//| The pins cannot be used for any other purposes (even though exposed in the board module). -//| By default all keyboard events are consumed and routed to the standard input - there is -//| not much use of the KEYBOARD object in this configuration - just read the input via sys.stdin. -//| -//| If you need to manually process individual key up / key down events via KEYBOARD.events, -//| call `detach_serial()`. -//| """" -//| KEYBOARD: keypad_demux.DemuxKeymatrix -//| -keypad_demux_demuxkeymatrix_obj_t cardputer_keyboard_obj; -bool cardputer_keyboard_serial_attached = false; - -void cardputer_keyboard_init(void); -void keyboard_seq(const char *seq); -void update_keyboard(keypad_eventqueue_obj_t *queue); - -//| def detach_serial() -> None: -//| """Stops consuming keyboard events and routing them to sys.stdin.""" -//| ... -//| -static mp_obj_t detach_serial(void) { - cardputer_keyboard_serial_attached = false; - common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard_obj.events, NULL); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_0(detach_serial_obj, detach_serial); - -//| def attach_serial() -> None: -//| """Starts consuming keyboard events and routing them to sys.stdin.""" -//| ... -//| -static mp_obj_t attach_serial(void) { - common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard_obj.events, update_keyboard); - cardputer_keyboard_serial_attached = true; - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_0(attach_serial_obj, attach_serial); - -//| def key_to_char(key: int, shifted: bool) -> str | None: -//| """Converts a key index to the respective key (with or without shift modifier). -//| Returns None for functional & modifier keys or whenever not 0 <= key < 56. -//| """ -//| ... -//| -static mp_obj_t key_to_char(mp_obj_t key_obj, mp_obj_t shifted_obj) { - mp_int_t key = mp_obj_get_int(key_obj); - if (key < 0 || key > (mp_int_t)(sizeof keymap / sizeof *keymap) || keymap[key] == 0) { - return mp_const_none; - } else if (shifted_obj == mp_const_true) { - return mp_obj_new_str(&keymap_shifted[key], 1); - } else { - return mp_obj_new_str(&keymap[key], 1); - } -} -static MP_DEFINE_CONST_FUN_OBJ_2(key_to_char_obj, key_to_char); - -// Ring buffer of characters consumed from keyboard events (when serial attached) -ringbuf_t keyqueue; -char keybuf[32]; - -keypad_event_obj_t event; -char keystate[56]; - -// Keyboard pins -const mcu_pin_obj_t *row_addr_pins[] = { - &pin_GPIO8, - &pin_GPIO9, - &pin_GPIO11, -}; - -const mcu_pin_obj_t *column_pins[] = { - &pin_GPIO13, - &pin_GPIO15, - &pin_GPIO3, - &pin_GPIO4, - &pin_GPIO5, - &pin_GPIO6, - &pin_GPIO7 -}; - -void cardputer_keyboard_init(void) { - cardputer_keyboard_obj.base.type = &keypad_demux_demuxkeymatrix_type; - common_hal_keypad_demux_demuxkeymatrix_construct( - &cardputer_keyboard_obj, // self - 3, // num_row_addr_pins - row_addr_pins, // row_addr_pins - 7, // num_column_pins - column_pins, // column_pins - true, // columns_to_anodes - false, // transpose - 0.01f, // interval - 20, // max_events - 2 // debounce_threshold - ); - demuxkeymatrix_never_reset(&cardputer_keyboard_obj); - - ringbuf_init(&keyqueue, (uint8_t *)keybuf, sizeof(keybuf)); - attach_serial(); -} - -// Overrides the weakly linked function from supervisor/shared/serial.c -void board_serial_init(void) { - cardputer_keyboard_init(); -} - -// Overrides the weakly linked function from supervisor/shared/serial.c -bool board_serial_connected(void) { - return cardputer_keyboard_serial_attached; -} - -// Overrides the weakly linked function from supervisor/shared/serial.c -uint32_t board_serial_bytes_available(void) { - if (cardputer_keyboard_serial_attached) { - return ringbuf_num_filled(&keyqueue); - } else { - return 0; - } -} - -// Overrides the weakly linked function from supervisor/shared/serial.c -char board_serial_read(void) { - if (cardputer_keyboard_serial_attached) { - return ringbuf_get(&keyqueue); - } else { - return 0; - } -} - -void keyboard_seq(const char *seq) { - while (*seq) { - ringbuf_put(&keyqueue, *seq++); - } -} - -void update_keyboard(keypad_eventqueue_obj_t *queue) { - uint8_t ascii = 0; - - if (common_hal_keypad_eventqueue_get_length(queue) == 0) { - return; - } - - while (common_hal_keypad_eventqueue_get_into(queue, &event)) { - if (event.pressed) { - keystate[event.key_number] = 1; - - if (keystate[KEY_CTRL]) { - if (keystate[KEY_ALT] && keystate[KEY_BACKSPACE]) { - reload_initiate(RUN_REASON_REPL_RELOAD); - } - ascii = keymap[event.key_number]; - if (ascii >= 'a' && ascii <= 'z') { - ascii -= 'a' - 1; - } - - if (ascii == mp_interrupt_char) { - mp_sched_keyboard_interrupt(); - } - } else if (keystate[KEY_SHIFT]) { - ascii = keymap_shifted[event.key_number]; - } else if (keystate[KEY_FN] && event.key_number != KEY_FN) { - switch (event.key_number | FN_MOD) - { - case KEY_DOWN: - keyboard_seq("\e[B"); - break; - case KEY_UP: - keyboard_seq("\e[A"); - break; - case KEY_DELETE: - keyboard_seq("\e[3~"); - break; - case KEY_LEFT: - keyboard_seq("\e[D"); - break; - case KEY_RIGHT: - keyboard_seq("\e[C"); - break; - case KEY_ESC: - ringbuf_put(&keyqueue, '\e'); - break; - } - } else { - ascii = keymap[event.key_number]; - } - - if (ascii > 0) { - if (keystate[KEY_ALT]) { - ringbuf_put(&keyqueue, '\e'); - } else if (keystate[KEY_OPT]) { - ringbuf_put(&keyqueue, '\x10'); - } - ringbuf_put(&keyqueue, ascii); - } - } else { - keystate[event.key_number] = 0; - } - } -} - -static const mp_rom_map_elem_t cardputer_keyboard_module_globals_table[] = { - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cardputer_keyboard)}, - {MP_ROM_QSTR(MP_QSTR_KEYBOARD), MP_ROM_PTR(&cardputer_keyboard_obj)}, - {MP_ROM_QSTR(MP_QSTR_attach_serial), MP_ROM_PTR(&attach_serial_obj)}, - {MP_ROM_QSTR(MP_QSTR_detach_serial), MP_ROM_PTR(&detach_serial_obj)}, - {MP_ROM_QSTR(MP_QSTR_key_to_char), MP_ROM_PTR(&key_to_char_obj)}, -}; -MP_DEFINE_CONST_DICT(cardputer_keyboard_module_globals, cardputer_keyboard_module_globals_table); - -const mp_obj_module_t cardputer_keyboard_module = { - .base = {&mp_type_module}, - .globals = (mp_obj_dict_t *)&cardputer_keyboard_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_cardputer_keyboard, cardputer_keyboard_module); diff --git a/ports/espressif/boards/m5stack_cardputer_ros/keymap.h b/ports/espressif/boards/m5stack_cardputer_ros/keymap.h deleted file mode 100644 index 0256fafaa0f57..0000000000000 --- a/ports/espressif/boards/m5stack_cardputer_ros/keymap.h +++ /dev/null @@ -1,214 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#define SHIFT_MOD 0x40 -#define FN_MOD 0x80 - -#define KEY_OPT 0 -#define KEY_Z 1 -#define KEY_C 2 -#define KEY_B 3 -#define KEY_M 4 -#define KEY_DOT 5 -#define KEY_SPACE 6 -#define KEY_SHIFT 7 -#define KEY_S 8 -#define KEY_F 9 -#define KEY_H 10 -#define KEY_K 11 -#define KEY_SEMICOLON 12 -#define KEY_ENTER 13 -#define KEY_Q 14 -#define KEY_E 15 -#define KEY_T 16 -#define KEY_U 17 -#define KEY_O 18 -#define KEY_LEFT_BRACKET 19 -#define KEY_BACKSLASH 20 -#define KEY_1 21 -#define KEY_3 22 -#define KEY_5 23 -#define KEY_7 24 -#define KEY_9 25 -#define KEY_UNDERSCORE 26 -#define KEY_BACKSPACE 27 -#define KEY_CTRL 28 -#define KEY_ALT 29 -#define KEY_X 30 -#define KEY_V 31 -#define KEY_N 32 -#define KEY_COMMA 33 -#define KEY_SLASH 34 -#define KEY_FN 35 -#define KEY_A 36 -#define KEY_D 37 -#define KEY_G 38 -#define KEY_J 39 -#define KEY_L 40 -#define KEY_APOSTROPHE 41 -#define KEY_TAB 42 -#define KEY_W 43 -#define KEY_R 44 -#define KEY_Y 45 -#define KEY_I 46 -#define KEY_P 47 -#define KEY_RIGHT_BRACKET 48 -#define KEY_GRAVE 49 -#define KEY_2 50 -#define KEY_4 51 -#define KEY_6 52 -#define KEY_8 53 -#define KEY_0 54 -#define KEY_EQUALS 55 - -#define KEY_GREATER (5 | SHIFT_MOD) -#define KEY_COLON (12 | SHIFT_MOD) -#define KEY_LEFT_CURLY_BRACKET (19 | SHIFT_MOD) -#define KEY_PIPE (20 | SHIFT_MOD) -#define KEY_EXCLAMATION (21 | SHIFT_MOD) -#define KEY_HASH (22 | SHIFT_MOD) -#define KEY_PERCENT (23 | SHIFT_MOD) -#define KEY_AMPERSAND (24 | SHIFT_MOD) -#define KEY_OPEN_PARENTHESIS (25 | SHIFT_MOD) -#define KEY_MINUS (26 | SHIFT_MOD) -#define KEY_LESS (33 | SHIFT_MOD) -#define KEY_QUESTION (34 | SHIFT_MOD) -#define KEY_DOUBLE_QUOTE (41 | SHIFT_MOD) -#define KEY_RIGHT_CURLY_BRACKET (48 | SHIFT_MOD) -#define KEY_TILDE (49 | SHIFT_MOD) -#define KEY_AT (50 | SHIFT_MOD) -#define KEY_DOLLAR (51 | SHIFT_MOD) -#define KEY_CARET (52 | SHIFT_MOD) -#define KEY_ASTERISK (53 | SHIFT_MOD) -#define KEY_CLOSE_PARENTHESIS (54 | SHIFT_MOD) -#define KEY_PLUS (55 | SHIFT_MOD) - -#define KEY_DOWN (5 | FN_MOD) -#define KEY_UP (12 | FN_MOD) -#define KEY_DELETE (27 | FN_MOD) -#define KEY_LEFT (33 | FN_MOD) -#define KEY_RIGHT (34 | FN_MOD) -#define KEY_ESC (49 | FN_MOD) - -const char keymap[56] = { - 0, // KEY_OPT - 'z', // KEY_Z - 'c', // KEY_C - 'b', // KEY_B - 'm', // KEY_M - '.', // KEY_DOT - ' ', // KEY_SPACE - 0, // KEY_SHIFT - 's', // KEY_S - 'f', // KEY_F - 'h', // KEY_H - 'k', // KEY_K - ';', // KEY_SEMICOLON - '\r',// KEY_ENTER - 'q', // KEY_Q - 'e', // KEY_E - 't', // KEY_T - 'u', // KEY_U - 'o', // KEY_O - '[', // KEY_LEFT_BRACKET - '\\',// KEY_BACKSLASH - '1', // KEY_1 - '3', // KEY_3 - '5', // KEY_5 - '7', // KEY_7 - '9', // KEY_9 - '_', // KEY_UNDERSCORE - '\b',// KEY_BACKSPACE - 0, // KEY_CTRL - 0, // KEY_ALT - 'x', // KEY_X - 'v', // KEY_V - 'n', // KEY_N - ',', // KEY_COMMA - '/', // KEY_SLASH - 0, // KEY_FN - 'a', // KEY_A - 'd', // KEY_D - 'g', // KEY_G - 'j', // KEY_J - 'l', // KEY_L - '\'',// KEY_APOSTROPHE - '\t',// KEY_TAB - 'w', // KEY_W - 'r', // KEY_R - 'y', // KEY_Y - 'i', // KEY_I - 'p', // KEY_P - ']', // KEY_RIGHT_BRACKET - '`', // KEY_GRAVE - '2', // KEY_2 - '4', // KEY_4 - '6', // KEY_6 - '8', // KEY_8 - '0', // KEY_0 - '=' // KEY_EQUALS -}; - -const char keymap_shifted[56] = { - 0, // KEY_OPT - 'Z', // KEY_Z - 'C', // KEY_C - 'B', // KEY_B - 'M', // KEY_M - '>', // KEY_DOT -> '>' - ' ', // KEY_SPACE - 0, // KEY_SHIFT - 'S', // KEY_S - 'F', // KEY_F - 'H', // KEY_H - 'K', // KEY_K - ':', // KEY_SEMICOLON -> ':' - '\r',// KEY_ENTER - 'Q', // KEY_Q - 'E', // KEY_E - 'T', // KEY_T - 'U', // KEY_U - 'O', // KEY_O - '{', // KEY_LEFT_BRACKET -> '{' - '|', // KEY_BACKSLASH -> '|' - '!', // KEY_1 -> '!' - '#', // KEY_3 -> '#' - '%', // KEY_5 -> '%' - '&', // KEY_7 -> '&' - '(', // KEY_9 -> '(' - '-', // KEY_UNDERSCORE -> '-' - '\b',// KEY_BACKSPACE - 0, // KEY_CTRL - 0, // KEY_ALT - 'X', // KEY_X - 'V', // KEY_V - 'N', // KEY_N - '<', // KEY_COMMA -> '<' - '?', // KEY_SLASH -> '?' - 0, // KEY_FN - 'A', // KEY_A - 'D', // KEY_D - 'G', // KEY_G - 'J', // KEY_J - 'L', // KEY_L - '"', // KEY_APOSTROPHE -> '"' - '\t',// KEY_TAB - 'W', // KEY_W - 'R', // KEY_R - 'Y', // KEY_Y - 'I', // KEY_I - 'P', // KEY_P - '}', // KEY_RIGHT_BRACKET -> '}' - '~', // KEY_GRAVE -> '~' - '@', // KEY_2 -> '@' - '$', // KEY_4 -> '$' - '^', // KEY_6 -> '^' - '*', // KEY_8 -> '*' - ')', // KEY_0 -> ')' - '+' // KEY_EQUALS -> '+' -}; diff --git a/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk index 573f947f0a8f5..ede48c2f01523 100644 --- a/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk @@ -15,4 +15,4 @@ CIRCUITPY_RCLCPY = 1 CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_MAX3421E = 0 -SRC_C += boards/$(BOARD)/cardputer_keyboard.c +SRC_C += module/cardputer_keyboard.c diff --git a/ports/espressif/boards/m5stack_cores3/pins.c b/ports/espressif/boards/m5stack_cores3/pins.c index 2ebb225277ded..8b40d9e84842a 100644 --- a/ports/espressif/boards/m5stack_cores3/pins.c +++ b/ports/espressif/boards/m5stack_cores3/pins.c @@ -28,42 +28,59 @@ CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1) static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - // M5 Bus (except I2S & PORT B) + // M5 Bus (except I2S) { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO37) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO35) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, { MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_PORTC_RX), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_A18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, { MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_PORTC_TX), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_A17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) }, - // Port B - { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, - // I2S { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO34) }, { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO33) }, - { MP_ROM_QSTR(MP_QSTR_IS2_DATA), MP_ROM_PTR(&pin_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_IS2_MASTER_CLOCK), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA_OUT), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA_IN), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MASTER_CLOCK), MP_ROM_PTR(&pin_GPIO0) }, // Camera { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, diff --git a/ports/espressif/boards/m5stack_dinmeter/board.c b/ports/espressif/boards/m5stack_dinmeter/board.c new file mode 100644 index 0000000000000..cd49318fd1cec --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/board.c @@ -0,0 +1,107 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "mpconfigboard.h" +#include "supervisor/board.h" +#include "supervisor/shared/serial.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "py/runtime.h" +#include "py/ringbuf.h" +#include "shared/runtime/interrupt_char.h" + + +uint8_t display_init_sequence[] = { + 0x01, 0x80, 0x96, // SWRESET and Delay 150ms + 0x11, 0x80, 0xff, // SLPOUT and Delay + 0xb1, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR1 + 0xb2, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR2 + 0xb3, 0x06, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, // _FRMCTR3 + 0xb4, 0x01, 0x07, // _INVCTR line inversion + 0xc0, 0x03, 0xa2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA + 0xc1, 0x01, 0xc5, // _PWCTR2 VGH=14.7V, VGL=-7.35V + 0xc2, 0x02, 0x0a, 0x00, // _PWCTR3 Opamp current small, Boost frequency + 0xc3, 0x02, 0x8a, 0x2a, + 0xc4, 0x02, 0x8a, 0xee, + 0xc5, 0x01, 0x0e, // _VMCTR1 VCOMH = 4V, VOML = -1.1V + 0x36, 0x01, 0xc8, // MADCTL Rotate display + 0x21, 0x00, // _INVON + 0x3a, 0x01, 0x05, // COLMOD - 16bit color + 0xe0, 0x10, 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, // _GMCTRP1 Gamma + 0xe1, 0x10, 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, // _GMCTRN1 + 0x13, 0x80, 0x0a, // _NORON + 0x29, 0x80, 0x64 // _DISPON +}; + + +// Overrides the weakly linked function from supervisor/shared/board.c +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + // see here for inspiration: https://github.com/m5stack/M5GFX/blob/33d7d3135e816a86a008fae8ab3757938cee95d2/src/M5GFX.cpp#L1350 + common_hal_fourwire_fourwire_construct( + bus, + spi, + &pin_GPIO4, // DC + &pin_GPIO7, // CS + &pin_GPIO8, // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 240, // width (after rotation) + 135, // height (after rotation) + 40, // column start + 52, // row start + 0, // 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 + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO9, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 80, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + // Hold pin must be set high to avoid a power off when battery powered + if (pin_number == 46) { + // Turn on hold output + config_pin_as_output_with_level(pin_number, true); + return true; + } + return false; +} + +// TODO: Should we turn off the display when asleep, in board_deinit() ? diff --git a/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.h b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.h new file mode 100644 index 0000000000000..2d69e61ea950a --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 CDarius +// SPDX-FileCopyrightText: Copyright (c) 2025 juergenpabel +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack DinMeter" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_I2C (2) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO12, .sda = &pin_GPIO11}, \ + {.scl = &pin_GPIO15, .sda = &pin_GPIO13}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO6, .mosi = &pin_GPIO5}} + +#define CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP (1) diff --git a/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.mk b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.mk new file mode 100644 index 0000000000000..81a23af1fe464 --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.mk @@ -0,0 +1,15 @@ +USB_VID = 0x303A +USB_PID = 0x830B + +USB_PRODUCT = "DinMeter" +USB_MANUFACTURER = "M5Stack" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +# Very few pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/m5stack_dinmeter/pins.c b/ports/espressif/boards/m5stack_dinmeter/pins.c new file mode 100644 index 0000000000000..f75e05e848b0b --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/pins.c @@ -0,0 +1,61 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2025 Juergen Pabel +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Port A + { MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + // Port B + { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + + // Encoder + { MP_ROM_QSTR(MP_QSTR_ENC_A), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_ENC_B), MP_ROM_PTR(&pin_GPIO40) }, + + // Button + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + // Misc + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_KNOB_BUTTON), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_POWER_HOLD), MP_ROM_PTR(&pin_GPIO46) }, + + // Display + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_I2C), MP_ROM_PTR(&board_porta_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_dinmeter/sdkconfig b/ports/espressif/boards/m5stack_dinmeter/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/board.c b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.h b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.h new file mode 100644 index 0000000000000..2114fecf373a4 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Prokyber Ai-On-The-Edge-Cam" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO12) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO48) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.mk b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.mk new file mode 100644 index 0000000000000..82419bb80745c --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x1209 +USB_PID = 0xDABB +USB_PRODUCT = "AI-ON-THE-EDGE-CAM" +USB_MANUFACTURER = "Prokyber" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m +CIRCUITPY_ESP_PSRAM_SIZE = 8MB diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/pins.c b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/pins.c new file mode 100644 index 0000000000000..68dc40781a480 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/pins.c @@ -0,0 +1,106 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" + +static const mp_rom_obj_tuple_t camera_data_tuple = { + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO9), + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO10), + MP_ROM_PTR(&pin_GPIO47), + MP_ROM_PTR(&pin_GPIO18), + MP_ROM_PTR(&pin_GPIO17), + MP_ROM_PTR(&pin_GPIO16), + } +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_PER_EN), MP_ROM_PTR(&pin_GPIO46) }, + + // SD + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + + // Ethernet + { MP_ROM_QSTR(MP_QSTR_ETH_RST), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_INT), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_MOSI), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_MISO), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_CLK), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + + // LEDs + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + // I2C + { 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_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_VSYNC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_HREF), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA9), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA8), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA7), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA6), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA2), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA5), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA3), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA4), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_SIOD), MP_ROM_PTR(&pin_GPIO4) }, // SDA + { MP_ROM_QSTR(MP_QSTR_CAMERA_SIOC), MP_ROM_PTR(&pin_GPIO5) }, // SCL + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/sdkconfig b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/sdkconfig new file mode 100644 index 0000000000000..ac1c535717672 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP +CONFIG_OV2640_SUPPORT=y +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/sqfmi_watchy/board.c b/ports/espressif/boards/sqfmi_watchy/board.c index 535a3e11006fe..297190b53e200 100644 --- a/ports/espressif/boards/sqfmi_watchy/board.c +++ b/ports/espressif/boards/sqfmi_watchy/board.c @@ -160,41 +160,33 @@ void board_init(void) { epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - (double)0.01, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 200, // width - 200, // height - 200, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 0, // rotation - 0x44, // set_column_window_command - 0x45, // set_row_window_command - 0x4E, // set_current_column_command - 0x4F, // set_current_row_command - 0x24, // write_black_ram_command - true, // black_bits_inverted - 0x26, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), - (double)1.0, // refresh_time - &pin_GPIO19, // busy_pin - true, // busy_state - (double)5.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - true // address_little_endian - ); + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 0.01; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 200; + args.height = 200; + args.ram_width = 200; + args.ram_height = 296; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4E; + args.set_current_row_command = 0x4F; + args.write_black_ram_command = 0x24; + args.black_bits_inverted = true; + args.write_color_ram_command = 0x26; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO19; + args.busy_state = true; + args.seconds_per_frame = 5.0; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } bool board_requests_safe_mode(void) { diff --git a/ports/espressif/common-hal/_bleio/Characteristic.c b/ports/espressif/common-hal/_bleio/Characteristic.c index 7e917d6334b6b..805c6d160f325 100644 --- a/ports/espressif/common-hal/_bleio/Characteristic.c +++ b/ports/espressif/common-hal/_bleio/Characteristic.c @@ -120,7 +120,7 @@ void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { return; } if (self->current_value != NULL) { - if (gc_nbytes(self->current_value) > 0) { + if (gc_ptr_on_heap(self->current_value)) { m_free(self->current_value); } else { port_free(self->current_value); diff --git a/ports/espressif/common-hal/alarm/pin/PinAlarm.c b/ports/espressif/common-hal/alarm/pin/PinAlarm.c index 8e3e46785f2e7..97ad3b2a94255 100644 --- a/ports/espressif/common-hal/alarm/pin/PinAlarm.c +++ b/ports/espressif/common-hal/alarm/pin/PinAlarm.c @@ -14,10 +14,12 @@ #include "esp_sleep.h" #include "hal/gpio_ll.h" +#include "driver/gpio.h" #include "esp_debug_helpers.h" #ifdef SOC_PM_SUPPORT_EXT0_WAKEUP #include "soc/rtc_cntl_reg.h" +#include "soc/rtc_io_reg.h" #endif #include "driver/rtc_io.h" @@ -358,38 +360,40 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob if (gpio_isr_register(gpio_interrupt, NULL, 0, &gpio_interrupt_handle) != ESP_OK) { mp_raise_ValueError(MP_ERROR_TEXT("Can only alarm on RTC IO from deep sleep.")); } - for (size_t i = 0; i < 64; i++) { - uint64_t mask = 1ull << i; + for (gpio_num_t pin = 0; pin < SOC_GPIO_PIN_COUNT; pin++) { + uint64_t mask = 1ULL << pin; bool high = (high_alarms & mask) != 0; bool low = (low_alarms & mask) != 0; bool pull = (pull_pins & mask) != 0; if (!(high || low)) { continue; } - if (rtc_gpio_is_valid_gpio(i)) { + if (rtc_gpio_is_valid_gpio(pin)) { #ifdef SOC_PM_SUPPORT_RTC_PERIPH_PD - rtc_gpio_deinit(i); + rtc_gpio_deinit(pin); #endif } - gpio_int_type_t interrupt_mode = GPIO_INTR_DISABLE; - gpio_pull_mode_t pull_mode = GPIO_FLOATING; + gpio_set_direction(pin, GPIO_MODE_INPUT); + if (pull) { + if (high) { + ESP_ERROR_CHECK(gpio_set_pull_mode(pin, GPIO_PULLDOWN_ONLY)); + } else { + ESP_ERROR_CHECK(gpio_set_pull_mode(pin, GPIO_PULLUP_ONLY)); + } + } else { + ESP_ERROR_CHECK(gpio_set_pull_mode(pin, GPIO_FLOATING)); + } + gpio_int_type_t intr = GPIO_INTR_DISABLE; if (high) { - interrupt_mode = GPIO_INTR_HIGH_LEVEL; - pull_mode = GPIO_PULLDOWN_ONLY; + intr = GPIO_INTR_HIGH_LEVEL; } if (low) { - interrupt_mode = GPIO_INTR_LOW_LEVEL; - pull_mode = GPIO_PULLUP_ONLY; - } - gpio_set_direction(i, GPIO_MODE_DEF_INPUT); - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[i], PIN_FUNC_GPIO); - if (pull) { - gpio_set_pull_mode(i, pull_mode); + intr = GPIO_INTR_LOW_LEVEL; } - never_reset_pin_number(i); - // Sets interrupt type and wakeup bits. - gpio_wakeup_enable(i, interrupt_mode); - gpio_intr_enable(i); + never_reset_pin_number(pin); + gpio_wakeup_enable(pin, intr); + gpio_set_intr_type(pin, intr); + gpio_intr_enable(pin); } // Wait for any pulls to settle. mp_hal_delay_ms(50); diff --git a/ports/espressif/common-hal/analogbufio/BufferedIn.c b/ports/espressif/common-hal/analogbufio/BufferedIn.c index aac7ad28daf25..20c5c060574aa 100644 --- a/ports/espressif/common-hal/analogbufio/BufferedIn.c +++ b/ports/espressif/common-hal/analogbufio/BufferedIn.c @@ -33,7 +33,7 @@ #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define ADC_RESULT_BYTE 2 #define ADC_CONV_LIMIT_EN 0 -#elif defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4) +#elif defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C61) #define ADC_RESULT_BYTE 4 #define ADC_CONV_LIMIT_EN 0 #elif defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/ports/espressif/common-hal/analogio/AnalogIn.c b/ports/espressif/common-hal/analogio/AnalogIn.c index 16340e91ac91c..34cd5b846cf22 100644 --- a/ports/espressif/common-hal/analogio/AnalogIn.c +++ b/ports/espressif/common-hal/analogio/AnalogIn.c @@ -32,6 +32,8 @@ #define DATA_WIDTH ADC_BITWIDTH_12 #elif defined(CONFIG_IDF_TARGET_ESP32C6) #define DATA_WIDTH ADC_BITWIDTH_12 +#elif defined(CONFIG_IDF_TARGET_ESP32C61) +#define DATA_WIDTH ADC_BITWIDTH_12 #elif defined(CONFIG_IDF_TARGET_ESP32P4) #define DATA_WIDTH ADC_BITWIDTH_12 #elif defined(CONFIG_IDF_TARGET_ESP32S2) @@ -86,10 +88,8 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { adc_cali_scheme_ver_t supported_schemes; adc_cali_check_scheme(&supported_schemes); - #ifndef CONFIG_IDF_TARGET_ESP32P4 adc_cali_scheme_ver_t calibration_scheme = 0; adc_cali_handle_t calibration; - #endif #if defined(ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED) && ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED adc_cali_curve_fitting_config_t config = { .unit_id = self->pin->adc_index, @@ -137,11 +137,7 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { // This corrects non-linear regions of the ADC range with a LUT, so it's a better reading than raw int voltage; - #ifdef CONFIG_IDF_TARGET_ESP32P4 - voltage = 0; - #else adc_cali_raw_to_voltage(calibration, adc_reading, &voltage); - #endif #if defined(ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED) && ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED if (calibration_scheme == ADC_CALI_SCHEME_VER_CURVE_FITTING) { diff --git a/ports/espressif/common-hal/digitalio/DigitalInOut.c b/ports/espressif/common-hal/digitalio/DigitalInOut.c index ed537419405b3..e4272ba1ff5ff 100644 --- a/ports/espressif/common-hal/digitalio/DigitalInOut.c +++ b/ports/espressif/common-hal/digitalio/DigitalInOut.c @@ -11,8 +11,11 @@ #include "hal/gpio_hal.h" static bool _pin_is_input(uint8_t pin_number) { - const uint32_t iomux = READ_PERI_REG(GPIO_PIN_MUX_REG[pin_number]); - return (iomux & FUN_IE) != 0; + gpio_io_config_t config; + if (gpio_get_io_config((gpio_num_t)pin_number, &config) != ESP_OK) { + return false; + } + return config.ie; } void digitalio_digitalinout_preserve_for_deep_sleep(size_t n_dios, digitalio_digitalinout_obj_t *preserve_dios[]) { @@ -113,10 +116,12 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode( digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( digitalio_digitalinout_obj_t *self) { - if (GPIO_HAL_GET_HW(GPIO_PORT_0)->pin[self->pin->number].pad_driver == 1) { + gpio_io_config_t config; + if (gpio_get_io_config((gpio_num_t)self->pin->number, &config) != ESP_OK) { + // Should it fail closed or open? return DRIVE_MODE_OPEN_DRAIN; } - return DRIVE_MODE_PUSH_PULL; + return config.od ? DRIVE_MODE_OPEN_DRAIN : DRIVE_MODE_PUSH_PULL; } digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( @@ -134,11 +139,10 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( digitalio_digitalinout_obj_t *self) { - gpio_num_t gpio_num = self->pin->number; - if (REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU)) { - return PULL_UP; - } else if (REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD)) { - return PULL_DOWN; + gpio_io_config_t config; + if (gpio_get_io_config((gpio_num_t)self->pin->number, &config) != ESP_OK) { + // Should it fail closed or open? + return PULL_NONE; } - return PULL_NONE; + return config.pd ? PULL_DOWN : PULL_UP; } diff --git a/ports/espressif/common-hal/espnow/ESPNow.c b/ports/espressif/common-hal/espnow/ESPNow.c index 79bded96fb41d..ae11db250321c 100644 --- a/ports/espressif/common-hal/espnow/ESPNow.c +++ b/ports/espressif/common-hal/espnow/ESPNow.c @@ -56,7 +56,7 @@ typedef struct { // Callback triggered when a sent packet is acknowledged by the peer (or not). // Just count the number of responses and number of failures. // These are used in the send() logic. -static void send_cb(const uint8_t *mac, esp_now_send_status_t status) { +static void send_cb(const esp_now_send_info_t *tx_info, esp_now_send_status_t status) { espnow_obj_t *self = MP_STATE_PORT(espnow_singleton); if (status == ESP_NOW_SEND_SUCCESS) { self->send_success++; diff --git a/ports/espressif/common-hal/microcontroller/Pin.c b/ports/espressif/common-hal/microcontroller/Pin.c index 70912afb545b4..922cde763e363 100644 --- a/ports/espressif/common-hal/microcontroller/Pin.c +++ b/ports/espressif/common-hal/microcontroller/Pin.c @@ -146,6 +146,29 @@ static const uint64_t pin_mask_reset_forbidden = #endif #endif // ESP32C6 + #if defined(CONFIG_IDF_TARGET_ESP32C61) + // Never ever reset pins used to communicate with SPI flash. + GPIO_SEL_15 | // SPICS0 (flash CS#) + GPIO_SEL_16 | // SPIQ (MISO/SIO1) + GPIO_SEL_17 | // SPIWP (WP#/SIO2) + GPIO_SEL_19 | // SPIHD (HOLD#/SIO3) + GPIO_SEL_20 | // SPICLK (CLK) + GPIO_SEL_21 | // SPID (MOSI/SIO0) + #if CIRCUITPY_ESP_USB_SERIAL_JTAG + // Never ever reset serial/JTAG communication pins. + GPIO_SEL_12 | // USB D- + GPIO_SEL_13 | // USB D+ + #endif + #if defined(CONFIG_SPIRAM) + GPIO_SEL_14 | // SPICS1 (PSRAM CS#); keep if PSRAM in use + #endif + #if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) && CONFIG_ESP_CONSOLE_UART_DEFAULT && CONFIG_ESP_CONSOLE_UART_NUM == 0 + // Never reset debug UART/console pins. + GPIO_SEL_10 | + GPIO_SEL_11 | + #endif + #endif // ESP32C6 + #if defined(CONFIG_IDF_TARGET_ESP32H2) // Never ever reset pins used to communicate with the in-package SPI flash. GPIO_SEL_15 | @@ -370,9 +393,8 @@ void reset_all_pins(void) { gpio_deep_sleep_hold_dis(); #endif - for (uint8_t i = 0; i < GPIO_PIN_COUNT; i++) { - uint32_t iomux_address = GPIO_PIN_MUX_REG[i]; - if (iomux_address == 0 || + for (gpio_num_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) { + if (!GPIO_IS_VALID_GPIO(i) || _never_reset(i) || _skip_reset_once(i) || _preserved_pin(i)) { diff --git a/ports/espressif/common-hal/microcontroller/Processor.c b/ports/espressif/common-hal/microcontroller/Processor.c index 8a6a14c0236f5..0056465f1c5cd 100644 --- a/ports/espressif/common-hal/microcontroller/Processor.c +++ b/ports/espressif/common-hal/microcontroller/Processor.c @@ -59,7 +59,7 @@ uint32_t common_hal_mcu_processor_get_frequency(void) { // If the requested frequency is not supported by the hardware, return the next lower supported frequency static uint32_t get_valid_cpu_frequency(uint32_t requested_freq_mhz) { - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) uint32_t valid_cpu_frequencies[] = {20, 40, 80, 160}; #elif defined(CONFIG_IDF_TARGET_ESP32C2) uint32_t valid_cpu_frequencies[] = {20, 40, 80, 120}; @@ -126,6 +126,8 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SYS_0_REG); #elif defined(CONFIG_IDF_TARGET_ESP32C2) uint32_t mac_address_part = REG_READ(EFUSE_RD_BLK2_DATA0_REG); + #elif defined(CONFIG_IDF_TARGET_ESP32C61) + uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SYS0_REG); #else uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SPI_SYS_0_REG); #endif @@ -145,6 +147,8 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { mac_address_part = REG_READ(EFUSE_RD_MAC_SYS_1_REG); #elif defined(CONFIG_IDF_TARGET_ESP32C2) mac_address_part = REG_READ(EFUSE_RD_BLK2_DATA1_REG); + #elif defined(CONFIG_IDF_TARGET_ESP32C61) + mac_address_part = REG_READ(EFUSE_RD_MAC_SYS1_REG); #else mac_address_part = REG_READ(EFUSE_RD_MAC_SPI_SYS_1_REG); #endif diff --git a/ports/espressif/common-hal/microcontroller/__init__.c b/ports/espressif/common-hal/microcontroller/__init__.c index 918366b8933c4..d23afce4d999e 100644 --- a/ports/espressif/common-hal/microcontroller/__init__.c +++ b/ports/espressif/common-hal/microcontroller/__init__.c @@ -36,6 +36,9 @@ #elif defined(CONFIG_IDF_TARGET_ESP32C6) #include "soc/lp_aon_reg.h" #include "esp32c6/rom/rtc.h" +#elif defined(CONFIG_IDF_TARGET_ESP32C61) +#include "soc/lp_aon_reg.h" +#include "esp32c61/rom/rtc.h" #elif defined(CONFIG_IDF_TARGET_ESP32P4) #include "esp32p4/rom/rtc.h" #elif defined(CONFIG_IDF_TARGET_ESP32S2) @@ -83,7 +86,7 @@ void common_hal_mcu_enable_interrupts(void) { void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { switch (runmode) { case RUNMODE_UF2: - #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) mp_arg_error_invalid(MP_QSTR_run_mode); #else // 0x11F2 is APP_REQUEST_UF2_RESET_HINT & is defined by TinyUF2 diff --git a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c index 7721b5e197f49..52c4b67bf4efe 100644 --- a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +++ b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c @@ -18,7 +18,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/runtime.h" -#include "driver/gpio.h" +#include /* * Current pin limitations for ESP32-S2 ParallelBus: diff --git a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h index 4724ba7231a4e..114a1e527a6d5 100644 --- a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h +++ b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h @@ -8,7 +8,7 @@ #include "common-hal/digitalio/DigitalInOut.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include typedef struct { mp_obj_base_t base; diff --git a/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c b/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c index ba8b70221b729..f65c7fdd9f110 100644 --- a/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c @@ -21,6 +21,10 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode // // These routines also implicitly configure the weak internal pull-ups, as expected // in CircuitPython. + + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + pcnt_unit_config_t unit_config = { // Set counter limit .low_limit = INT16_MIN, @@ -87,6 +91,10 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o pcnt_del_channel(self->channel_a); pcnt_del_channel(self->channel_b); pcnt_del_unit(self->unit); + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { self->unit = NULL; } diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index 0a36eff95b454..5128e93c8589e 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -483,7 +483,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, socklen_t socklen = sizeof(error_code); result = getsockopt(self->num, SOL_SOCKET, SO_ERROR, &error_code, &socklen); if (result < 0 || error_code != 0) { - mp_raise_OSError(errno); + mp_raise_OSError(error_code); } self->connected = true; return; diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index 1a4c014bfbc5b..0eacd2bab3ec0 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -146,8 +146,8 @@ void common_hal_wifi_init(bool user_initiated) { common_hal_wifi_radio_obj.base.type = &wifi_radio_type; if (!wifi_ever_inited) { - ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(esp_netif_init()); wifi_ever_inited = true; } @@ -175,6 +175,7 @@ void common_hal_wifi_init(bool user_initiated) { &self->handler_instance_got_ip)); wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t result = esp_wifi_init(&config); #ifdef CONFIG_ESP32_WIFI_NVS_ENABLED // Generally we don't use this because we store ssid and passwords ourselves in the filesystem. esp_err_t err = nvs_flash_init(); @@ -185,8 +186,10 @@ void common_hal_wifi_init(bool user_initiated) { err = nvs_flash_init(); } ESP_ERROR_CHECK(err); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH)); + #else + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); #endif - esp_err_t result = esp_wifi_init(&config); if (result == ESP_ERR_NO_MEM) { if (gc_alloc_possible()) { mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to allocate Wifi memory")); diff --git a/ports/espressif/esp-idf b/ports/espressif/esp-idf index f50ec8ecdb31f..f4fddd2d05b44 160000 --- a/ports/espressif/esp-idf +++ b/ports/espressif/esp-idf @@ -1 +1 @@ -Subproject commit f50ec8ecdb31f681e6a778f145de95f849c1089d +Subproject commit f4fddd2d05b44d1d606b546b596d17de0a73e9eb diff --git a/ports/espressif/esp-idf-config/sdkconfig-debug.defaults b/ports/espressif/esp-idf-config/sdkconfig-debug.defaults index a9c8e34e54706..368ba81bb4aa7 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-debug.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-debug.defaults @@ -7,6 +7,21 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y # end of Compiler options +# Bootloader config +# +# +# Log +# +# +# Format +# +CONFIG_BOOTLOADER_LOG_COLORS=y +# end of Format + +# end of Log + +# end of Bootloader config + # # Component config # @@ -19,6 +34,17 @@ CONFIG_ESP_CONSOLE_SECONDARY_NONE=y # CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG is not set # end of ESP System Settings +# +# Log +# +# +# Format +# +CONFIG_LOG_COLORS=y +# end of Format + +# end of Log + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults index 85dde905f3caa..63f42cac95244 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults @@ -49,6 +49,12 @@ CONFIG_ESP_PHY_ENABLE_USB=y CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 # end of Wi-Fi +# +# mbedTLS +# +# CONFIG_MBEDTLS_HARDWARE_SHA is not set +# end of mbedTLS + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c61.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c61.defaults new file mode 100644 index 0000000000000..85dde905f3caa --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c61.defaults @@ -0,0 +1,54 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y +# +# NimBLE Options +# +CONFIG_BT_NIMBLE_LOG_LEVEL_NONE=y +CONFIG_BT_NIMBLE_NVS_PERSIST=y +# +# Memory Settings +# +CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=20 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70 +# end of Memory Settings + +CONFIG_BT_NIMBLE_EXT_ADV=y +# end of NimBLE Options + +# end of Bluetooth + +# +# Driver Configurations +# +# +# PCNT Configuration +# +CONFIG_PCNT_CTRL_FUNC_IN_IRAM=y +# end of PCNT Configuration + +# end of Driver Configurations + +# +# PHY +# +CONFIG_ESP_PHY_ENABLE_USB=y +# end of PHY + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 +# end of Wi-Fi + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults index 5c748bd0e6f02..101f90f9fa4fe 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults @@ -55,7 +55,7 @@ CONFIG_ULP_COPROC_ENABLED=y CONFIG_ULP_COPROC_TYPE_FSM=y CONFIG_ULP_COPROC_TYPE_RISCV=y # Note: enabling both ULPs simultaneously only works due to a modification of adafruit/esp-idf # (see adafruit/esp-idf/pull/16) until espressif/esp-idf/issues/12999 is fixed. -CONFIG_ULP_COPROC_RESERVE_MEM=8176 +CONFIG_ULP_COPROC_RESERVE_MEM=8144 # end of Ultra Low Power (ULP) Co-processor # diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults index fe3c3e0a2da88..2553c648018bd 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults @@ -95,7 +95,7 @@ CONFIG_ULP_COPROC_ENABLED=y CONFIG_ULP_COPROC_TYPE_FSM=y CONFIG_ULP_COPROC_TYPE_RISCV=y # Note: enabling both ULPs simultaneously only works due to a modification of adafruit/esp-idf # (see adafruit/esp-idf/pull/16) until espressif/esp-idf/issues/12999 is fixed. -CONFIG_ULP_COPROC_RESERVE_MEM=8176 +CONFIG_ULP_COPROC_RESERVE_MEM=8144 # end of Ultra Low Power (ULP) Co-processor # end of Component config diff --git a/ports/espressif/esp-idf-config/sdkconfig-opt.defaults b/ports/espressif/esp-idf-config/sdkconfig-opt.defaults index 16f5b990386a1..0da23e8122762 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-opt.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-opt.defaults @@ -38,6 +38,24 @@ CONFIG_ESP_CONSOLE_SECONDARY_NONE=y CONFIG_LOG_DEFAULT_LEVEL_NONE=y # end of Log output +# +# Log +# +# +# Log Level +# +# +# Level Settings +# +# CONFIG_LOG_DYNAMIC_LEVEL_CONTROL is not set +CONFIG_LOG_TAG_LEVEL_IMPL_NONE=y +# CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST is not set +# end of Level Settings + +# end of Log Level + +# end of Log + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig.defaults b/ports/espressif/esp-idf-config/sdkconfig.defaults index b54f599b2a5b7..5c4d6a31a62c1 100644 --- a/ports/espressif/esp-idf-config/sdkconfig.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig.defaults @@ -20,6 +20,12 @@ CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=y CONFIG_GPTIMER_ISR_IRAM_SAFE=y # end of GPTimer Configuration +# +# Touch Configuration +# +CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN=y +# end of Touch Configuration + # end of Driver Configurations # @@ -59,6 +65,13 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 CONFIG_FREERTOS_HZ=1000 # end of Kernel +# +# LibC +# +# end of LWIP +CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y +# end of LibC + # # LWIP # @@ -71,16 +84,6 @@ CONFIG_LWIP_IPV6_AUTOCONFIG=y CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=0 CONFIG_LWIP_IPV6_DHCP6=y # -# TCP -# -CONFIG_LWIP_MAX_ACTIVE_TCP=4 -CONFIG_LWIP_MAX_LISTENING_TCP=4 -CONFIG_LWIP_TCP_SYNMAXRTX=6 -CONFIG_LWIP_TCP_SND_BUF_DEFAULT=2880 -CONFIG_LWIP_TCP_WND_DEFAULT=2880 -CONFIG_LWIP_TCP_RTO_TIME=3000 -# end of TCP - # end of LWIP # diff --git a/ports/espressif/boards/m5stack_cardputer/cardputer_keyboard.c b/ports/espressif/module/cardputer_keyboard.c similarity index 83% rename from ports/espressif/boards/m5stack_cardputer/cardputer_keyboard.c rename to ports/espressif/module/cardputer_keyboard.c index 73880f66e19d9..548275001acc5 100644 --- a/ports/espressif/boards/m5stack_cardputer/cardputer_keyboard.c +++ b/ports/espressif/module/cardputer_keyboard.c @@ -16,7 +16,7 @@ #include "shared-module/keypad_demux/DemuxKeyMatrix.h" #include "supervisor/shared/reload.h" -#include "keymap.h" +#include "cardputer_keymap.h" //| """M5Stack Cardputer keyboard integration. //| """ @@ -31,12 +31,13 @@ //| """" //| KEYBOARD: keypad_demux.DemuxKeymatrix //| -keypad_demux_demuxkeymatrix_obj_t cardputer_keyboard_obj; -bool cardputer_keyboard_serial_attached = false; -void cardputer_keyboard_init(void); -void keyboard_seq(const char *seq); -void update_keyboard(keypad_eventqueue_obj_t *queue); +keypad_demux_demuxkeymatrix_obj_t cardputer_keyboard; +static bool cardputer_keyboard_serial_attached = false; + +// Forward declarations. +static void keyboard_seq(const char *seq); +static void update_keyboard(keypad_eventqueue_obj_t *queue); //| def detach_serial() -> None: //| """Stops consuming keyboard events and routing them to sys.stdin.""" @@ -44,7 +45,7 @@ void update_keyboard(keypad_eventqueue_obj_t *queue); //| static mp_obj_t detach_serial(void) { cardputer_keyboard_serial_attached = false; - common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard_obj.events, NULL); + common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard.events, NULL); return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_0(detach_serial_obj, detach_serial); @@ -54,7 +55,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(detach_serial_obj, detach_serial); //| ... //| static mp_obj_t attach_serial(void) { - common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard_obj.events, update_keyboard); + common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard.events, update_keyboard); cardputer_keyboard_serial_attached = true; return mp_const_none; } @@ -79,20 +80,20 @@ static mp_obj_t key_to_char(mp_obj_t key_obj, mp_obj_t shifted_obj) { static MP_DEFINE_CONST_FUN_OBJ_2(key_to_char_obj, key_to_char); // Ring buffer of characters consumed from keyboard events (when serial attached) -ringbuf_t keyqueue; -char keybuf[32]; +static ringbuf_t keyqueue; +static char keybuf[32]; keypad_event_obj_t event; -char keystate[56]; +static char keystate[56] = {0}; // Keyboard pins -const mcu_pin_obj_t *row_addr_pins[] = { +static const mcu_pin_obj_t *row_addr_pins[] = { &pin_GPIO8, &pin_GPIO9, &pin_GPIO11, }; -const mcu_pin_obj_t *column_pins[] = { +static const mcu_pin_obj_t *column_pins[] = { &pin_GPIO13, &pin_GPIO15, &pin_GPIO3, @@ -102,22 +103,22 @@ const mcu_pin_obj_t *column_pins[] = { &pin_GPIO7 }; -void cardputer_keyboard_init(void) { - cardputer_keyboard_obj.base.type = &keypad_demux_demuxkeymatrix_type; +static void cardputer_keyboard_init(void) { common_hal_keypad_demux_demuxkeymatrix_construct( - &cardputer_keyboard_obj, // self - 3, // num_row_addr_pins - row_addr_pins, // row_addr_pins - 7, // num_column_pins - column_pins, // column_pins - true, // columns_to_anodes - false, // transpose - 0.01f, // interval - 20, // max_events - 2 // debounce_threshold + &cardputer_keyboard, // self + MP_ARRAY_SIZE(row_addr_pins), // num_row_addr_pins + row_addr_pins, // row_addr_pins + MP_ARRAY_SIZE(column_pins), // num_column_pins + column_pins, // column_pins + true, // columns_to_anodes + false, // transpose + 0.01f, // interval + 20, // max_events + 2, // debounce_threshold + false // use_gc_allocator ); - demuxkeymatrix_never_reset(&cardputer_keyboard_obj); + demuxkeymatrix_never_reset(&cardputer_keyboard); ringbuf_init(&keyqueue, (uint8_t *)keybuf, sizeof(keybuf)); attach_serial(); } @@ -150,13 +151,13 @@ char board_serial_read(void) { } } -void keyboard_seq(const char *seq) { +static void keyboard_seq(const char *seq) { while (*seq) { ringbuf_put(&keyqueue, *seq++); } } -void update_keyboard(keypad_eventqueue_obj_t *queue) { +static void update_keyboard(keypad_eventqueue_obj_t *queue) { uint8_t ascii = 0; if (common_hal_keypad_eventqueue_get_length(queue) == 0) { @@ -223,7 +224,7 @@ void update_keyboard(keypad_eventqueue_obj_t *queue) { static const mp_rom_map_elem_t cardputer_keyboard_module_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cardputer_keyboard)}, - {MP_ROM_QSTR(MP_QSTR_KEYBOARD), MP_ROM_PTR(&cardputer_keyboard_obj)}, + {MP_ROM_QSTR(MP_QSTR_KEYBOARD), MP_ROM_PTR(&cardputer_keyboard)}, {MP_ROM_QSTR(MP_QSTR_attach_serial), MP_ROM_PTR(&attach_serial_obj)}, {MP_ROM_QSTR(MP_QSTR_detach_serial), MP_ROM_PTR(&detach_serial_obj)}, {MP_ROM_QSTR(MP_QSTR_key_to_char), MP_ROM_PTR(&key_to_char_obj)}, diff --git a/ports/espressif/boards/m5stack_cardputer/keymap.h b/ports/espressif/module/cardputer_keymap.h similarity index 100% rename from ports/espressif/boards/m5stack_cardputer/keymap.h rename to ports/espressif/module/cardputer_keymap.h diff --git a/ports/espressif/mpconfigport.h b/ports/espressif/mpconfigport.h index 712eb67f1f42a..031676cf4d8ae 100644 --- a/ports/espressif/mpconfigport.h +++ b/ports/espressif/mpconfigport.h @@ -27,7 +27,7 @@ // Nearly all boards have this because it is used to enter the ROM bootloader. #ifndef CIRCUITPY_BOOT_BUTTON - #if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) + #if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C61) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO9) #elif !defined(CONFIG_IDF_TARGET_ESP32) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index f05df8c07c87a..f133e86c6e068 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -17,6 +17,9 @@ CROSS_COMPILE = riscv32-esp-elf- else ifeq ($(IDF_TARGET),esp32c6) IDF_TARGET_ARCH = riscv CROSS_COMPILE = riscv32-esp-elf- +else ifeq ($(IDF_TARGET),esp32c61) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- else ifeq ($(IDF_TARGET),esp32h2) IDF_TARGET_ARCH = riscv CROSS_COMPILE = riscv32-esp-elf- @@ -54,6 +57,10 @@ CIRCUITPY_HASHLIB_MBEDTLS_ONLY = 0 CIRCUITPY_PORT_SERIAL = 1 +CIRCUITPY_LIB_TLSF = 0 + +CIRCUITPY_LIBC_STRING0 = 0 + # These modules are implemented in ports//common-hal: CIRCUITPY__EVE ?= 1 CIRCUITPY_ALARM ?= 1 @@ -61,7 +68,7 @@ CIRCUITPY_ALARM_TOUCH ?= 0 CIRCUITPY_ANALOGBUFIO ?= 1 CIRCUITPY_AUDIOBUSIO ?= 1 CIRCUITPY_AUDIOBUSIO_PDMIN ?= 0 -CIRCUITPY_AUDIOIO ?= 0 +CIRCUITPY_AUDIOIO ?= 1 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BLEIO_NATIVE ?= 1 CIRCUITPY_CANIO ?= 1 @@ -89,11 +96,11 @@ CIRCUITPY_WATCHDOG ?= 1 CIRCUITPY_WIFI ?= 1 CIRCUITPY_SOCKETPOOL_IPV6 ?= 1 -# Conditionally turn off modules/features +# Conditionally turn off modules/features per chip type +#### esp32 ############################################################ ifeq ($(IDF_TARGET),esp32) # Modules CIRCUITPY_ALARM_TOUCH = 1 -CIRCUITPY_AUDIOIO ?= 1 CIRCUITPY_RGBMATRIX = 0 # SDMMC not supported yet @@ -102,6 +109,7 @@ CIRCUITPY_SDIOIO = 0 # Has no USB CIRCUITPY_USB_DEVICE = 0 +#### esp32c2 ########################################################## else ifeq ($(IDF_TARGET),esp32c2) # C2 ROM spits out the UART at 74880 when connected to a 26mhz crystal! @@ -128,6 +136,9 @@ CIRCUITPY_ANALOGBUFIO = 0 # No I2S CIRCUITPY_AUDIOBUSIO = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No RMT CIRCUITPY_NEOPIXEL_WRITE = 0 CIRCUITPY_PULSEIO = 0 @@ -142,6 +153,7 @@ CIRCUITPY_TOUCHIO_USE_NATIVE = 0 CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 +#### esp32c3 ########################################################## else ifeq ($(IDF_TARGET),esp32c3) # Modules CIRCUITPY_ESPCAMERA = 0 @@ -151,6 +163,9 @@ CIRCUITPY_MEMORYMAP = 0 # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No PCNT peripheral CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_COUNTIO = 0 @@ -165,6 +180,7 @@ CIRCUITPY_TOUCHIO_USE_NATIVE = 0 CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 +#### esp32c6 ########################################################## else ifeq ($(IDF_TARGET),esp32c6) # Modules CIRCUITPY_ESPCAMERA = 0 @@ -172,6 +188,9 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No space for this CIRCUITPY_AUDIOBUSIO = 0 @@ -187,6 +206,46 @@ CIRCUITPY_TOUCHIO_USE_NATIVE = 0 CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 +#### esp32c6 ########################################################## +else ifeq ($(IDF_TARGET),esp32c61) +# Modules +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_ESPULP = 0 +CIRCUITPY_MEMORYMAP = 0 +CIRCUITPY_RGBMATRIX = 0 + +# No DAC +CIRCUITPY_AUDIOIO = 0 + +# No space for this +CIRCUITPY_AUDIOBUSIO = 0 + +# No I80 support from the IDF +CIRCUITPY_PARALLELDISPLAYBUS = 0 + +# No SDMMC +CIRCUITPY_SDIOIO = 0 + +CIRCUITPY_TOUCHIO ?= 1 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 +# Features +CIRCUITPY_USB_DEVICE = 0 +CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 + +# No TWAI on chip +CIRCUITPY_CANIO = 0 + +# No RMT on chip +CIRCUITPY_NEOPIXEL_WRITE = 0 +CIRCUITPY_PULSEIO = 0 +CIRCUITPY_RGBMATRIX = 0 + +# No PCNT on chip +CIRCUITPY_COUNTIO = 0 +CIRCUITPY_ROTARYIO = 0 +CIRCUITPY_FREQUENCYIO = 0 + +#### esp32h2 ########################################################## else ifeq ($(IDF_TARGET),esp32h2) # Modules CIRCUITPY_ESPCAMERA = 0 @@ -194,6 +253,9 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 @@ -210,8 +272,12 @@ CIRCUITPY_WIFI = 0 CIRCUITPY_MAX3421E = 0 +#### esp32p4 ########################################################## else ifeq ($(IDF_TARGET),esp32p4) +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No wifi # TODO: Support ESP32-C6 coprocessor on some boards. CIRCUITPY_BLEIO_NATIVE = 0 @@ -246,10 +312,12 @@ CIRCUITPY_PARALLELDISPLAYBUS = 0 # Library doesn't support P4 yet it seems CIRCUITPY_ESPCAMERA = 0 +#### esp32s2 ########################################################## else ifeq ($(IDF_TARGET),esp32s2) # Modules -CIRCUITPY_ALARM_TOUCH = 1 +CIRCUITPY_ALARM_TOUCH = $(CIRCUITPY_ALARM) CIRCUITPY_AUDIOIO ?= 1 + # No BLE in hw CIRCUITPY_BLEIO_NATIVE = 0 @@ -258,12 +326,19 @@ CIRCUITPY_SDIOIO = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 0 +#### esp32s3 ########################################################## else ifeq ($(IDF_TARGET),esp32s3) + # Modules -CIRCUITPY_ALARM_TOUCH = 1 +CIRCUITPY_ALARM_TOUCH = $(CIRCUITPY_ALARM) CIRCUITPY_AUDIOBUSIO_PDMIN = 1 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 0 + +# No DAC +CIRCUITPY_AUDIOIO = 0 + endif +#### end chip-specific choices ######################################## # No room for large modules on 2MB boards # 2MB boards have a single firmware partition, and can't do dualbank. diff --git a/ports/espressif/peripherals/esp32c61/pins.c b/ports/espressif/peripherals/esp32c61/pins.c new file mode 100644 index 0000000000000..a32e1e8da9856 --- /dev/null +++ b/ports/espressif/peripherals/esp32c61/pins.c @@ -0,0 +1,38 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +const mcu_pin_obj_t pin_GPIO0 = PIN(0, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO1 = PIN(1, ADC_UNIT_1, ADC_CHANNEL_0, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO3 = PIN(3, ADC_UNIT_1, ADC_CHANNEL_1, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_1, ADC_CHANNEL_2, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO5 = PIN(5, ADC_UNIT_1, ADC_CHANNEL_3, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO6 = PIN(6, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO7 = PIN(7, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO8 = PIN(8, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO9 = PIN(9, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO10 = PIN(10, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO11 = PIN(11, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO15 = PIN(15, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO16 = PIN(16, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO17 = PIN(17, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO18 = PIN(18, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO19 = PIN(19, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO20 = PIN(20, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO21 = PIN(21, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO22 = PIN(22, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO23 = PIN(23, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO24 = PIN(24, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO25 = PIN(25, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO26 = PIN(26, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO27 = PIN(27, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO28 = PIN(28, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO29 = PIN(29, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/esp32c61/pins.h b/ports/espressif/peripherals/esp32c61/pins.h new file mode 100644 index 0000000000000..908c9fe29f0e2 --- /dev/null +++ b/ports/espressif/peripherals/esp32c61/pins.h @@ -0,0 +1,72 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// DO NOT include this file directly. +// Use shared-bindings/microcontroller/Pin.h instead. +// This ensures that all necessary includes are already included. + +#pragma once + +#define GPIO0_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO0; +#define GPIO1_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO1; +#define GPIO2_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO2; +#define GPIO3_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO3; +#define GPIO4_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO4; +#define GPIO5_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO5; +#define GPIO6_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO6; +#define GPIO7_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO7; +#define GPIO8_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO8; +#define GPIO9_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO9; +#define GPIO10_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO10; +#define GPIO11_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO11; +#define GPIO12_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO12; +#define GPIO13_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO13; +#define GPIO14_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO14; +#define GPIO15_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO15; +#define GPIO16_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO16; +#define GPIO17_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO17; +#define GPIO18_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO18; +#define GPIO19_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO19; +#define GPIO20_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO20; +#define GPIO21_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO21; +#define GPIO22_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO22; +#define GPIO23_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO23; +#define GPIO24_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO24; +#define GPIO25_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO25; +#define GPIO26_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO26; +#define GPIO27_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO27; +#define GPIO28_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO28; +#define GPIO29_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO29; diff --git a/ports/espressif/peripherals/pins.h b/ports/espressif/peripherals/pins.h index f89855e308f59..bbe42be1bcae2 100644 --- a/ports/espressif/peripherals/pins.h +++ b/ports/espressif/peripherals/pins.h @@ -14,7 +14,7 @@ #include "components/hal/include/hal/gpio_types.h" #include "components/hal/include/hal/adc_types.h" -#include "components/hal/include/hal/touch_sensor_types.h" +#include "components/hal/include/hal/touch_sensor_legacy_types.h" typedef struct { mp_obj_base_t base; @@ -52,6 +52,8 @@ extern const mp_obj_type_t mcu_pin_type; #include "esp32c3/pins.h" #elif defined(CONFIG_IDF_TARGET_ESP32C6) #include "esp32c6/pins.h" +#elif defined(CONFIG_IDF_TARGET_ESP32C61) +#include "esp32c61/pins.h" #elif defined(CONFIG_IDF_TARGET_ESP32P4) #include "esp32p4/pins.h" #elif defined(CONFIG_IDF_TARGET_ESP32H2) diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 48ae29ab4f927..72c92c98baea2 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -216,6 +216,11 @@ static void _never_reset_spi_ram_flash(void) { never_reset_pin_number(bootloader_flash_get_wp_pin()); } #endif // CONFIG_IDF_TARGET_ESP32 + #if defined(CONFIG_IDF_TARGET_ESP32C61) + #if defined(CONFIG_SPIRAM) + common_hal_never_reset_pin(&pin_GPIO14); + #endif + #endif } safe_mode_t port_init(void) { @@ -271,7 +276,7 @@ safe_mode_t port_init(void) { common_hal_never_reset_pin(&pin_GPIO40); common_hal_never_reset_pin(&pin_GPIO41); common_hal_never_reset_pin(&pin_GPIO42); - #elif defined(CONFIG_IDF_TARGET_ESP32P4) + #elif defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C61) common_hal_never_reset_pin(&pin_GPIO3); common_hal_never_reset_pin(&pin_GPIO4); common_hal_never_reset_pin(&pin_GPIO5); diff --git a/ports/espressif/supervisor/usb.c b/ports/espressif/supervisor/usb.c index 612abaa808ae2..274542ef22a7d 100644 --- a/ports/espressif/supervisor/usb.c +++ b/ports/espressif/supervisor/usb.c @@ -54,31 +54,6 @@ static void usb_device_task(void *param) { vTaskDelay(1); } } - -/** - * Callback invoked when received an "wanted" char. - * @param itf Interface index (for multiple cdc interfaces) - * @param wanted_char The wanted char (set previously) - */ -void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void)itf; // not used - // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB. - // So, we must notify the other task when a CTRL-C is received. - port_wake_main_task(); - // Workaround for using shared/runtime/interrupt_char.c - // Compare mp_interrupt_char with wanted_char and ignore if not matched - if (mp_interrupt_char == wanted_char) { - tud_cdc_read_flush(); // flush read fifo - mp_sched_keyboard_interrupt(); - } -} - -void tud_cdc_rx_cb(uint8_t itf) { - (void)itf; - // Workaround for "press any key to enter REPL" response being delayed on espressif. - // Wake main task when any key is pressed. - port_wake_main_task(); -} #endif // CIRCUITPY_USB_DEVICE void init_usb_hardware(void) { diff --git a/ports/espressif/tools/build_memory_info.py b/ports/espressif/tools/build_memory_info.py index 9a3c55501388e..0cf609c4d63f4 100644 --- a/ports/espressif/tools/build_memory_info.py +++ b/ports/espressif/tools/build_memory_info.py @@ -61,6 +61,12 @@ ("LP SRAM", (0x5000_0000,), 16 * 1024), ("HP SRAM", (0x4080_0000,), 512 * 1024), ], + "esp32c61": [ + # Name, Start, Length + ("LP SRAM", (0x5000_0000,), 16 * 1024), + ("HP SRAM", (0x4080_0000,), 320 * 1024), + ("PSRAM", (0x4200_0000,), 2 * 1024 * 1024), + ], "esp32h2": [ # Name, Start, Length ("LP SRAM", (0x5000_0000,), 4 * 1024), diff --git a/ports/espressif/tools/decode_backtrace.py b/ports/espressif/tools/decode_backtrace.py index 024e636207ec8..16cef9e0822cc 100644 --- a/ports/espressif/tools/decode_backtrace.py +++ b/ports/espressif/tools/decode_backtrace.py @@ -12,20 +12,41 @@ board = sys.argv[1] print(board) +elfs = [ + f"build-{board}/firmware.elf", + # Add additional ELF files here such as the ROM ELF files from: + # https://github.com/espressif/esp-rom-elfs/releases + # "/home/tannewt/Downloads/esp-rom-elfs-20241011/esp32c6_rev0_rom.elf", +] + while True: + print('"Backtrace:" or "Stack memory:". CTRL-D to finish multiline paste') addresses = input("? ") if addresses.startswith("Backtrace:"): addresses = addresses[len("Backtrace:") :] - if addresses.startswith("Stack memory:"): - addresses = addresses[len("Stack memory:") :] - addresses = addresses.strip().split() - addresses = [address.split(":")[0] for address in addresses] + addresses = addresses.strip().split() + addresses = [address.split(":")[0] for address in addresses] + elif addresses.startswith("Stack memory:"): + addresses = [] + extra_lines = sys.stdin.readlines() + for line in extra_lines: + if not line.strip(): + continue + addresses.extend(line.split(":")[1].strip().split()) for address in addresses: - result = subprocess.run( - ["xtensa-esp32s2-elf-addr2line", "-aipfe", "build-{}/firmware.elf".format(board)] - + [address], - capture_output=True, - ) - stdout = result.stdout.decode("utf-8") - if "?? ??" not in stdout: - print(stdout.strip()) + if address == "0xa5a5a5a5": + # Skip stack fill value. + continue + for elf in elfs: + result = subprocess.run( + ["riscv32-esp-elf-addr2line", "-aipfe", elf, address], + capture_output=True, + ) + stdout = result.stdout.decode("utf-8") + if not stdout: + continue + if "?? ??" not in stdout: + print(stdout.strip()) + break + + print("loop") diff --git a/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c b/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c index c71f8b212e183..211b5c186f3fa 100644 --- a/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c @@ -26,6 +26,9 @@ static void encoder_change(void *self_in) { void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + self->pin_a = pin_a; self->pin_b = pin_b; @@ -49,7 +52,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode } bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self) { - return !self->pin_a; + return self->pin_a == NULL; } void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t *self) { @@ -62,6 +65,9 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o common_hal_reset_pin(self->pin_a); common_hal_reset_pin(self->pin_b); + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { self->pin_a = NULL; - self->pin_b = NULL; } diff --git a/ports/mimxrt10xx/common-hal/usb_host/Port.c b/ports/mimxrt10xx/common-hal/usb_host/Port.c index 31af4ed582332..a7e73ab5b5c49 100644 --- a/ports/mimxrt10xx/common-hal/usb_host/Port.c +++ b/ports/mimxrt10xx/common-hal/usb_host/Port.c @@ -47,5 +47,8 @@ usb_host_port_obj_t *common_hal_usb_host_port_construct(const mcu_pin_obj_t *dp, self->dp = dp; self->dm = dm; + claim_pin(dp); + claim_pin(dm); + return self; } diff --git a/ports/nordic/common-hal/_bleio/Characteristic.c b/ports/nordic/common-hal/_bleio/Characteristic.c index 1975c2c3d79ce..51335be9e59be 100644 --- a/ports/nordic/common-hal/_bleio/Characteristic.c +++ b/ports/nordic/common-hal/_bleio/Characteristic.c @@ -80,7 +80,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, // to allocate. self->initial_value_len = initial_value_bufinfo->len; if (gc_alloc_possible()) { - if (gc_nbytes(initial_value_bufinfo->buf) > 0) { + if (gc_ptr_on_heap(initial_value_bufinfo->buf)) { uint8_t *initial_value = m_malloc_without_collect(self->initial_value_len); memcpy(initial_value, initial_value_bufinfo->buf, self->initial_value_len); self->initial_value = initial_value; diff --git a/ports/nordic/common-hal/_bleio/Service.c b/ports/nordic/common-hal/_bleio/Service.c index edd67a5fe739d..1bd75f8a48114 100644 --- a/ports/nordic/common-hal/_bleio/Service.c +++ b/ports/nordic/common-hal/_bleio/Service.c @@ -131,7 +131,7 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_desc_md.read_perm); // If the description is on the Python heap, then have the SD copy it. If not, assume it's // static and will live for longer than the SD. - user_desc_md.vloc = gc_nbytes(user_description) > 0 ? BLE_GATTS_VLOC_STACK : BLE_GATTS_VLOC_USER; + user_desc_md.vloc = gc_ptr_on_heap(user_description) ? BLE_GATTS_VLOC_STACK : BLE_GATTS_VLOC_USER; char_md.p_user_desc_md = &user_desc_md; char_md.p_char_user_desc = (const uint8_t *)user_description; char_md.char_user_desc_max_size = strlen(user_description); diff --git a/ports/nordic/common-hal/busio/UART.c b/ports/nordic/common-hal/busio/UART.c index 0dfe6ae3f5de2..6939486a5e673 100644 --- a/ports/nordic/common-hal/busio/UART.c +++ b/ports/nordic/common-hal/busio/UART.c @@ -122,7 +122,7 @@ void uart_reset(void) { void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { // Don't never reset objects on the heap. - if (gc_alloc_possible() && gc_nbytes(self) > 0) { + if (gc_alloc_possible() && gc_ptr_on_heap(self)) { return; } for (size_t i = 0; i < MP_ARRAY_SIZE(nrfx_uartes); i++) { @@ -346,7 +346,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, RUN_BACKGROUND_TASKS; } - if (!nrfx_is_in_ram(data) && gc_alloc_possible() && gc_nbytes(tx_buf) > 0) { + if (!nrfx_is_in_ram(data) && gc_alloc_possible() && gc_ptr_on_heap(tx_buf)) { gc_free(tx_buf); } diff --git a/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c b/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c index b0617fae7e566..2e8b308ff64d9 100644 --- a/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c @@ -32,6 +32,9 @@ static void _intr_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + self->pin_a = pin_a->number; self->pin_b = pin_b->number; @@ -78,6 +81,10 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o nrfx_gpiote_in_uninit(self->pin_b); reset_pin_number(self->pin_a); reset_pin_number(self->pin_b); + + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { self->pin_a = NO_PIN; - self->pin_b = NO_PIN; } diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index ba2db8a750825..b75d542325166 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -25,7 +25,8 @@ INC_CYW43 := \ CFLAGS_CYW43 := \ -DCYW43_LWIP=1 \ -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 \ - -DCYW43_USE_SPI \ + -DCYW43_USE_SPI=1 \ + -DUSE_SDIOIT=0 \ -DIGNORE_GPIO25 \ -DIGNORE_GPIO23 \ -DIGNORE_GPIO24 \ @@ -125,6 +126,7 @@ INC += \ -isystem sdk/src/rp2_common/hardware_powman/include/ \ -isystem sdk/src/rp2_common/hardware_pwm/include/ \ -isystem sdk/src/rp2_common/hardware_resets/include/ \ + -isystem sdk/src/rp2_common/hardware_rcp/include/ \ -isystem sdk/src/rp2_common/hardware_rtc/include/ \ -isystem sdk/src/rp2_common/hardware_spi/include/ \ -isystem sdk/src/rp2_common/hardware_sync/include/ \ @@ -149,6 +151,7 @@ INC += \ -isystem sdk/src/rp2_common/pico_float/include/ \ -isystem sdk/src/rp2_common/pico_runtime/include/ \ -isystem sdk/src/rp2_common/pico_runtime_init/include/ \ + -isystem sdk/src/rp2_common/pico_platform_common/include/ \ -isystem sdk/src/rp2_common/pico_platform_compiler/include/ \ -isystem sdk/src/rp2_common/pico_platform_sections/include/ \ -isystem sdk/src/rp2_common/pico_platform_panic/include/ \ diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.h b/ports/raspberrypi/bindings/rp2pio/StateMachine.h index afdffd1eccd3b..16f884bcfca32 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.h +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.h @@ -42,6 +42,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self); bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self); +void common_hal_rp2pio_statemachine_mark_deinit(rp2pio_statemachine_obj_t *self); void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self); diff --git a/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c b/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c index b7e75a475fd09..35e128627bc0b 100644 --- a/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c +++ b/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c @@ -251,75 +251,62 @@ void board_init(void) { if ((vid_setting == 1) || // DCNextGen SSD1681 BWR rotated 270 (vid_setting == 3) || // Explorer SSD1681 BW rotated 0 (vid_setting == 4)) { // Explorer SSD1681 BWR rotated 0 - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - _start_sequence_ssd1681, sizeof(_start_sequence_ssd1681), - 1.0, // start up time - _stop_sequence_ssd1681, sizeof(_stop_sequence_ssd1681), - WIDTH, // width - HEIGHT, // height - WIDTH, // ram_width - HEIGHT + 0x60, // ram_height RAM is actually only 200 bits high but we use 296 to match the 9 bits - 0, // colstart - 0, // rowstart - rotation, // rotation - SSD_SET_RAMXPOS, // set_column_window_command - SSD_SET_RAMYPOS, // set_row_window_command - SSD_SET_RAMXCOUNT, // set_current_column_command - SSD_SET_RAMYCOUNT, // set_current_row_command - SSD_WRITE_RAM_BLK, // write_black_ram_command - false, // black_bits_inverted - SSD_WRITE_RAM_RED, // write_color_ram_command - false, // color_bits_inverted - 0xFF0000, // highlight_color (RED for tri-color display) - 0x000000, // highlight_color2 - _refresh_sequence_ssd1681, sizeof(_refresh_sequence_ssd1681), // refresh_display_command - refresh_time, // refresh_time - &pin_GPIO9, // DEFAULT_SPI_BUS_BUSY, // busy_pin - true, // busy_state - seconds_per_frame, // seconds_per_frame (does not seem the user can change this) - true, // always_toggle_chip_select - false, // not grayscale - false, // not acep - false, // not spectra6 - false, // not two_byte_sequence_length - true); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = _start_sequence_ssd1681; + args.start_sequence_len = sizeof(_start_sequence_ssd1681); + args.start_up_time = 1.0; + args.stop_sequence = _stop_sequence_ssd1681; + args.stop_sequence_len = sizeof(_stop_sequence_ssd1681); + args.width = WIDTH; + args.height = HEIGHT; + args.ram_width = WIDTH; + args.ram_height = HEIGHT + 0x60; + args.rotation = rotation; + args.set_column_window_command = SSD_SET_RAMXPOS; + args.set_row_window_command = SSD_SET_RAMYPOS; + args.set_current_column_command = SSD_SET_RAMXCOUNT; + args.set_current_row_command = SSD_SET_RAMYCOUNT; + args.write_black_ram_command = SSD_WRITE_RAM_BLK; + args.write_color_ram_command = SSD_WRITE_RAM_RED; + args.highlight_color = 0xFF0000; + args.refresh_sequence = _refresh_sequence_ssd1681; + args.refresh_sequence_len = sizeof(_refresh_sequence_ssd1681); + args.refresh_time = refresh_time; + args.busy_pin = &pin_GPIO9; + args.busy_state = true; + args.seconds_per_frame = seconds_per_frame; + args.always_toggle_chip_select = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } else if (vid_setting == 2) { // Explorer SSD1608 BW - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - _start_sequence_ssd1608, sizeof(_start_sequence_ssd1608), - 1.0, // start up time - _stop_sequence_ssd1608, sizeof(_stop_sequence_ssd1608), - WIDTH, // width - HEIGHT, // height - WIDTH, // ram_width - HEIGHT /* + 0x60 */, // ram_height RAM is actually only 200 bits high but we use 296 to match the 9 bits - 0, // colstart - 0, // rowstart - rotation, // rotation - SSD_SET_RAMXPOS, // set_column_window_command - SSD_SET_RAMYPOS, // set_row_window_command - SSD_SET_RAMXCOUNT, // set_current_column_command - SSD_SET_RAMYCOUNT, // set_current_row_command - SSD_WRITE_RAM_BLK, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color (RED for tri-color display) - 0x000000, // highlight_color2 - _refresh_sequence_ssd1608, sizeof(_refresh_sequence_ssd1608), // refresh_display_command - refresh_time, // refresh_time - &pin_GPIO9, // DEFAULT_SPI_BUS_BUSY, // busy_pin - true, // busy_state - seconds_per_frame, // seconds_per_frame (does not seem the user can change this) - true, // always_toggle_chip_select - false, // not grayscale - false, // not acep - false, // not spectra6 - false, // not two_byte_sequence_length - true); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = _start_sequence_ssd1608; + args.start_sequence_len = sizeof(_start_sequence_ssd1608); + args.start_up_time = 1.0; + args.stop_sequence = _stop_sequence_ssd1608; + args.stop_sequence_len = sizeof(_stop_sequence_ssd1608); + args.width = WIDTH; + args.height = HEIGHT; + args.ram_width = WIDTH; + args.ram_height = HEIGHT; + args.rotation = rotation; + args.set_column_window_command = SSD_SET_RAMXPOS; + args.set_row_window_command = SSD_SET_RAMYPOS; + args.set_current_column_command = SSD_SET_RAMXCOUNT; + args.set_current_row_command = SSD_SET_RAMYCOUNT; + args.write_black_ram_command = SSD_WRITE_RAM_BLK; + args.write_color_ram_command = NO_COMMAND; + args.refresh_sequence = _refresh_sequence_ssd1608; + args.refresh_sequence_len = sizeof(_refresh_sequence_ssd1608); + args.refresh_time = refresh_time; + args.busy_pin = &pin_GPIO9; + args.busy_state = true; + args.seconds_per_frame = seconds_per_frame; + args.always_toggle_chip_select = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } else { // what should happen if this firmware is installed on some other board? // currently, we mark the display as None diff --git a/ports/raspberrypi/boards/pimoroni_badger2040/board.c b/ports/raspberrypi/boards/pimoroni_badger2040/board.c index 392a57cdc0c1b..07cc512b9a58e 100644 --- a/ports/raspberrypi/boards/pimoroni_badger2040/board.c +++ b/ports/raspberrypi/boards/pimoroni_badger2040/board.c @@ -273,40 +273,27 @@ void board_init(void) { // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 296, // width - 128, // height - 160, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - DTM2, // write_black_ram_command - true, // black_bits_inverted - DTM1, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO26, // busy_pin - false, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 160; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = DTM2; + args.black_bits_inverted = true; + args.write_color_ram_command = DTM1; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO26; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/raspberrypi/boards/pimoroni_badger2040w/board.c b/ports/raspberrypi/boards/pimoroni_badger2040w/board.c index 01c448cd7ad52..b992bcd6a1e37 100644 --- a/ports/raspberrypi/boards/pimoroni_badger2040w/board.c +++ b/ports/raspberrypi/boards/pimoroni_badger2040w/board.c @@ -273,40 +273,27 @@ void board_init(void) { // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 296, // width - 128, // height - 160, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - DTM2, // write_black_ram_command - true, // black_bits_inverted - DTM1, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO26, // busy_pin - false, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 160; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = DTM2; + args.black_bits_inverted = true; + args.write_color_ram_command = DTM1; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO26; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c index c7901b8649d78..4bf7518c6a8df 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c @@ -67,40 +67,26 @@ void board_init(void) { epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 1.0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 600, // width - 448, // height - 640, // ram_width - 480, // ram_height - 0, // colstart - 0, // rowstart - 0, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x10, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), - 28.0, // refresh_time - NULL, // busy_pin - false, // busy_state - 40.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - true, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 1.0; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 600; + args.height = 448; + args.ram_width = 640; + args.ram_height = 480; + args.write_black_ram_command = 0x10; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 28.0; + args.busy_pin = NULL; + args.seconds_per_frame = 40.0; + args.acep = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c index 764c85ecb6bcf..763a91a255569 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c @@ -126,40 +126,27 @@ void board_init(void) { epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 1.0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 800, // width - 480, // height - 800, // ram_width - 480, // ram_height - 0, // colstart - 0, // rowstart - 180, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x10, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - 0x000000, // highlight_color2 - refresh_sequence, sizeof(refresh_sequence), - 28.0, // refresh_time - NULL, // busy_pin - false, // busy_state - 30.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - true, // acep - false, // spectra6 - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 1.0; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 800; + args.height = 480; + args.ram_width = 800; + args.ram_height = 480; + args.rotation = 180; + args.write_black_ram_command = 0x10; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 28.0; + args.busy_pin = NULL; + args.seconds_per_frame = 30.0; + args.acep = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h index 72b1e1d04399f..097cbd8baa301 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h +++ b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h @@ -5,7 +5,7 @@ // SPDX-License-Identifier: MIT #define MICROPY_HW_BOARD_NAME "Pimoroni Plasma 2350" -#define MICROPY_HW_MCU_NAME "rp2350b" +#define MICROPY_HW_MCU_NAME "rp2350a" #define CIRCUITPY_RGB_STATUS_INVERTED_PWM #define CIRCUITPY_RGB_STATUS_R (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h index d9e62abb1edd2..576299d939cfb 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h @@ -5,7 +5,7 @@ // SPDX-License-Identifier: MIT #define MICROPY_HW_BOARD_NAME "Pimoroni Plasma 2350W" -#define MICROPY_HW_MCU_NAME "rp2350A" +#define MICROPY_HW_MCU_NAME "rp2350a" #define CIRCUITPY_RGB_STATUS_INVERTED_PWM #define CIRCUITPY_RGB_STATUS_R (&pin_GPIO16) diff --git a/ports/raspberrypi/common-hal/busio/SPI.c b/ports/raspberrypi/common-hal/busio/SPI.c index d20bc4d7d10aa..4735d1284f98e 100644 --- a/ports/raspberrypi/common-hal/busio/SPI.c +++ b/ports/raspberrypi/common-hal/busio/SPI.c @@ -182,7 +182,10 @@ static bool _transfer(busio_spi_obj_t *self, chan_tx = dma_claim_unused_channel(false); chan_rx = dma_claim_unused_channel(false); } - bool use_dma = chan_rx >= 0 && chan_tx >= 0; + bool has_dma_channels = chan_rx >= 0 && chan_tx >= 0; + // Only use DMA if both data buffers are in SRAM. Otherwise, we'll stall the DMA with PSRAM or flash cache misses. + bool data_in_sram = data_in >= (uint8_t *)SRAM_BASE && data_out >= (uint8_t *)SRAM_BASE; + bool use_dma = has_dma_channels && data_in_sram; if (use_dma) { dma_channel_config c = dma_channel_get_default_config(chan_tx); channel_config_set_transfer_data_size(&c, DMA_SIZE_8); diff --git a/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c index 113bd1900dd88..d71ff60b2ebc3 100644 --- a/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c @@ -43,6 +43,9 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { const mcu_pin_obj_t *pins[] = { pin_a, pin_b }; + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + // Start out with swapped to match behavior with other ports. self->swapped = true; if (!common_hal_rp2pio_pins_are_sequential(2, pins)) { @@ -89,6 +92,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode } bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self) { + // Use the deinit state of the PIO state machine. return common_hal_rp2pio_statemachine_deinited(&self->state_machine); } @@ -100,6 +104,11 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o common_hal_rp2pio_statemachine_deinit(&self->state_machine); } +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { + // Use the deinit state of the PIO state machine. + common_hal_rp2pio_statemachine_mark_deinit(&self->state_machine); +} + static void incrementalencoder_interrupt_handler(void *self_in) { rotaryio_incrementalencoder_obj_t *self = self_in; diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index fefecf05ff715..71050677f225f 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -523,9 +523,10 @@ static void consider_instruction(introspect_t *state, uint16_t full_instruction, } } if (instruction == pio_instr_bits_wait) { - uint16_t wait_source = (full_instruction & 0x0060) >> 5; - uint16_t wait_index = (full_instruction & 0x001f) + state->inputs.pio_gpio_offset; - if (wait_source == 0 && !PIO_PINMASK_IS_SET(state->inputs.pins_we_use, wait_index)) { // GPIO + const uint16_t wait_source = (full_instruction & 0x0060) >> 5; + const uint16_t wait_index = full_instruction & 0x001f; + const uint16_t wait_pin = wait_index + state->inputs.pio_gpio_offset; + if (wait_source == 0 && !PIO_PINMASK_IS_SET(state->inputs.pins_we_use, wait_pin)) { // GPIO mp_raise_ValueError_varg(MP_ERROR_TEXT("%q[%u] uses extra pin"), what_program, i); } else if (wait_source == 1) { // Input pin if (!state->inputs.has_in_pin) { @@ -627,6 +628,9 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, int mov_status_type, int mov_status_n) { + // Ensure object starts in its deinit state. + common_hal_rp2pio_statemachine_mark_deinit(self); + // First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false. pio_pinmask_t pins_we_use = wait_gpio_mask; PIO_PINMASK_MERGE(pins_we_use, _check_pins_free(first_out_pin, out_pin_count, exclusive_pin_use)); @@ -743,7 +747,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, mov_status_type, mov_status_n); if (!ok) { // indicate state machine never inited - self->state_machine = NUM_PIO_STATE_MACHINES; + common_hal_rp2pio_statemachine_mark_deinit(self); mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use")); } } @@ -826,6 +830,10 @@ void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self) { rp2pio_statemachine_deinit(self, false); } +void common_hal_rp2pio_statemachine_mark_deinit(rp2pio_statemachine_obj_t *self) { + self->state_machine = NUM_PIO_STATE_MACHINES; +} + void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self) { rp2pio_statemachine_never_reset(self->pio, self->state_machine); // TODO: never reset all the pins @@ -853,25 +861,64 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, // This implementation is based on SPI but varies because the tx and rx buffers // may be different lengths and occur at different times or speeds. - // Use DMA for large transfers if channels are available. - // Don't exceed FIFO size. - const size_t dma_min_size_threshold = self->fifo_depth; int chan_tx = -1; int chan_rx = -1; size_t len = MAX(out_len, in_len); bool tx = data_out != NULL; bool rx = data_in != NULL; - bool use_dma = len >= dma_min_size_threshold || swap_out || swap_in; + bool free_data_out = false; + bool free_data_in = false; + uint8_t *sram_data_out = (uint8_t *)data_out; + uint8_t *sram_data_in = data_in; + bool tx_fits_in_fifo = (out_len / out_stride_in_bytes) <= self->fifo_depth; + bool rx_fits_in_fifo = (in_len / in_stride_in_bytes) <= self->fifo_depth; + bool use_dma = !(tx_fits_in_fifo && rx_fits_in_fifo) || swap_out || swap_in; + if (use_dma) { - // Use DMA channels to service the two FIFOs + // We can only reliably use DMA for SRAM buffers. So, if we're given PSRAM buffers, + // then copy them to SRAM first. If we can't, then fail. + // Use DMA channels to service the two FIFOs. Fail if we can't allocate DMA channels. if (tx) { + if (data_out < (uint8_t *)SRAM_BASE) { + // Try to allocate a temporary buffer for DMA transfer + uint8_t *temp_buffer = (uint8_t *)port_malloc(len, true); + if (temp_buffer == NULL) { + mp_printf(&mp_plat_print, "Failed to allocate temporary buffer for DMA tx\n"); + return false; + } + memcpy(temp_buffer, data_out, len); + sram_data_out = temp_buffer; + free_data_out = true; + } chan_tx = dma_claim_unused_channel(false); // DMA allocation failed... if (chan_tx < 0) { + if (free_data_out) { + port_free(sram_data_out); + } + if (free_data_in) { + port_free(sram_data_in); + } return false; } } if (rx) { + if (data_in < (uint8_t *)SRAM_BASE) { + // Try to allocate a temporary buffer for DMA transfer + uint8_t *temp_buffer = (uint8_t *)port_malloc(len, true); + if (temp_buffer == NULL) { + mp_printf(&mp_plat_print, "Failed to allocate temporary buffer for DMA rx\n"); + if (chan_tx >= 0) { + dma_channel_unclaim(chan_tx); + } + if (free_data_out) { + port_free(sram_data_out); + } + return false; + } + sram_data_in = temp_buffer; + free_data_in = true; + } chan_rx = dma_claim_unused_channel(false); // DMA allocation failed... if (chan_rx < 0) { @@ -879,6 +926,12 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, if (chan_tx >= 0) { dma_channel_unclaim(chan_tx); } + if (free_data_out) { + port_free(sram_data_out); + } + if (free_data_in) { + port_free(sram_data_in); + } return false; } } @@ -910,7 +963,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, channel_config_set_bswap(&c, swap_out); dma_channel_configure(chan_tx, &c, tx_destination, - data_out, + sram_data_out, out_len / out_stride_in_bytes, false); channel_mask |= 1u << chan_tx; @@ -923,7 +976,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, channel_config_set_write_increment(&c, true); channel_config_set_bswap(&c, swap_in); dma_channel_configure(chan_rx, &c, - data_in, + sram_data_in, rx_source, in_len / in_stride_in_bytes, false); @@ -950,8 +1003,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, self->pio->fdebug = stall_mask; } - // If we have claimed only one channel successfully, we should release immediately. This also - // releases the DMA after use_dma has been done. + // Release the DMA channels after use_dma has been done. if (chan_rx >= 0) { dma_channel_unclaim(chan_rx); } @@ -960,31 +1012,31 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, } if (!use_dma && !(self->user_interruptible && mp_hal_is_interrupted())) { - // Use software for small transfers, or if couldn't claim two DMA channels + // Use software for small transfers size_t rx_remaining = in_len / in_stride_in_bytes; size_t tx_remaining = out_len / out_stride_in_bytes; while (rx_remaining || tx_remaining) { while (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) { if (out_stride_in_bytes == 1) { - *tx_destination = *data_out; + *tx_destination = *sram_data_out; } else if (out_stride_in_bytes == 2) { - *((uint16_t *)tx_destination) = *((uint16_t *)data_out); + *((uint16_t *)tx_destination) = *((uint16_t *)sram_data_out); } else if (out_stride_in_bytes == 4) { - *((uint32_t *)tx_destination) = *((uint32_t *)data_out); + *((uint32_t *)tx_destination) = *((uint32_t *)sram_data_out); } - data_out += out_stride_in_bytes; + sram_data_out += out_stride_in_bytes; --tx_remaining; } while (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) { if (in_stride_in_bytes == 1) { - *data_in = (uint8_t)*rx_source; + *sram_data_in = (uint8_t)*rx_source; } else if (in_stride_in_bytes == 2) { - *((uint16_t *)data_in) = *((uint16_t *)rx_source); + *((uint16_t *)sram_data_in) = *((uint16_t *)rx_source); } else if (in_stride_in_bytes == 4) { - *((uint32_t *)data_in) = *((uint32_t *)rx_source); + *((uint32_t *)sram_data_in) = *((uint32_t *)rx_source); } - data_in += in_stride_in_bytes; + sram_data_in += in_stride_in_bytes; --rx_remaining; } RUN_BACKGROUND_TASKS; @@ -996,7 +1048,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, self->pio->fdebug = stall_mask; } // Wait for the state machine to finish transmitting the data we've queued - // up. + // up (either from the CPU or via DMA.) if (tx) { while (!pio_sm_is_tx_fifo_empty(self->pio, self->state_machine) || (self->wait_for_txstall && (self->pio->fdebug & stall_mask) == 0)) { @@ -1006,6 +1058,14 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, } } } + if (free_data_out) { + port_free(sram_data_out); + } + if (free_data_in) { + // Copy the data from the SRAM buffer to the user PSRAM buffer. + memcpy(data_in, sram_data_in, len); + port_free(sram_data_in); + } return true; } diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index 018365def8c75..aeab1498510a0 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -89,7 +89,7 @@ static mp_obj_t socketpool_ip_addr_and_port_to_tuple(const ip_addr_t *addr, int // socket API. // Extension to lwIP error codes -// Matches lwIP 2.0.3 +// Matches lwIP 2.2.1 #undef _ERR_BADF #define _ERR_BADF -17 static const int error_lookup_table[] = { @@ -473,7 +473,12 @@ static mp_uint_t lwip_tcp_send(socketpool_socket_obj_t *socket, const byte *buf, MICROPY_PY_LWIP_ENTER - u16_t available = tcp_sndbuf(socket->pcb.tcp); + // If the socket is still connecting then don't let data be written to it. + // Otherwise, get the number of available bytes in the output buffer. + u16_t available = 0; + if (socket->state != STATE_CONNECTING) { + available = tcp_sndbuf(socket->pcb.tcp); + } if (available == 0) { // Non-blocking socket @@ -490,7 +495,8 @@ static mp_uint_t lwip_tcp_send(socketpool_socket_obj_t *socket, const byte *buf, // If peer fully closed socket, we would have socket->state set to ERR_RST (connection // reset) by error callback. // Avoid sending too small packets, so wait until at least 16 bytes available - while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) { + while (socket->state == STATE_CONNECTING + || (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16)) { MICROPY_PY_LWIP_EXIT if (socket->timeout != (unsigned)-1 && mp_hal_ticks_ms() - start > socket->timeout) { *_errno = MP_ETIMEDOUT; @@ -531,9 +537,10 @@ static mp_uint_t lwip_tcp_send(socketpool_socket_obj_t *socket, const byte *buf, MICROPY_PY_LWIP_REENTER } - // If the output buffer is getting full then send the data to the lower layers - if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) { - err = tcp_output(socket->pcb.tcp); + // Use nagle algorithm to determine when to send segment buffer (can be + // disabled with TCP_NODELAY socket option) + if (err == ERR_OK) { + err = tcp_output_nagle(socket->pcb.tcp); } MICROPY_PY_LWIP_EXIT @@ -551,6 +558,12 @@ static mp_uint_t lwip_tcp_receive(socketpool_socket_obj_t *socket, byte *buf, mp // Check for any pending errors STREAM_ERROR_CHECK(socket); + if (socket->state == STATE_LISTENING) { + // original socket in listening state, not the accepted connection. + *_errno = MP_ENOTCONN; + return -1; + } + if (socket->incoming.pbuf == NULL) { // Non-blocking socket diff --git a/ports/raspberrypi/common-hal/usb_host/Port.c b/ports/raspberrypi/common-hal/usb_host/Port.c index 5439b39bf3aa3..b8a49725030ea 100644 --- a/ports/raspberrypi/common-hal/usb_host/Port.c +++ b/ports/raspberrypi/common-hal/usb_host/Port.c @@ -146,6 +146,8 @@ usb_host_port_obj_t *common_hal_usb_host_port_construct(const mcu_pin_obj_t *dp, self->base.type = &usb_host_port_type; self->dp = dp; self->dm = dm; + claim_pin(dp); + claim_pin(dm); PIO pio = pio_get_instance(pio_cfg.pio_tx_num); diff --git a/ports/raspberrypi/lib/Pico-PIO-USB b/ports/raspberrypi/lib/Pico-PIO-USB index 032a469e79f6a..675543bcc9baa 160000 --- a/ports/raspberrypi/lib/Pico-PIO-USB +++ b/ports/raspberrypi/lib/Pico-PIO-USB @@ -1 +1 @@ -Subproject commit 032a469e79f6a4ba40760d7868e6db26e15002d7 +Subproject commit 675543bcc9baa8170f868ab7ba316d418dbcf41f diff --git a/ports/raspberrypi/lib/cyw43-driver b/ports/raspberrypi/lib/cyw43-driver index c1075d4bc4404..dd7568229f3bf 160000 --- a/ports/raspberrypi/lib/cyw43-driver +++ b/ports/raspberrypi/lib/cyw43-driver @@ -1 +1 @@ -Subproject commit c1075d4bc440422cf2b2fd12c64a1f53f77660ee +Subproject commit dd7568229f3bf7a37737b9e1ef250c26efe75b23 diff --git a/ports/raspberrypi/lwip_src/lwip_mem.c b/ports/raspberrypi/lwip_src/lwip_mem.c index 244f51e289bc9..23b185354b072 100644 --- a/ports/raspberrypi/lwip_src/lwip_mem.c +++ b/ports/raspberrypi/lwip_src/lwip_mem.c @@ -8,10 +8,12 @@ #include #include "lib/tlsf/tlsf.h" #include "lwip_mem.h" +#include "shared-bindings/microcontroller/__init__.h" #include "supervisor/port_heap.h" void *lwip_heap_malloc(size_t size) { - return port_malloc(size, true); + void *ptr = port_malloc(size, true); + return ptr; } void lwip_heap_free(void *ptr) { diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index 1404b2b06777c..bbce13d13811f 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -59,6 +59,9 @@ CIRCUITPY_CYW43_INIT_DELAY ?= 1000 endif ifeq ($(CHIP_VARIANT),RP2350) +# RP2350 has PSRAM that is not DMA-capable +CIRCUITPY_ALL_MEMORY_DMA_CAPABLE = 0 + # This needs to be implemented. CIRCUITPY_ALARM = 0 # Default PICODVI on because it doesn't require much code in RAM to talk to HSTX. diff --git a/ports/raspberrypi/sdk b/ports/raspberrypi/sdk index 96b363a15598d..a1438dff1d38b 160000 --- a/ports/raspberrypi/sdk +++ b/ports/raspberrypi/sdk @@ -1 +1 @@ -Subproject commit 96b363a15598d0a17a77542ba63150b7d3fa5fd5 +Subproject commit a1438dff1d38bd9c65dbd693f0e5db4b9ae91779 diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 4be42380491cb..66e63248c4810 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -264,33 +264,52 @@ void port_heap_init(void) { void *port_malloc(size_t size, bool dma_capable) { if (!dma_capable && _psram_size > 0) { + common_hal_mcu_disable_interrupts(); void *block = tlsf_malloc(_psram_heap, size); + common_hal_mcu_enable_interrupts(); if (block) { return block; } } + common_hal_mcu_disable_interrupts(); void *block = tlsf_malloc(_heap, size); + common_hal_mcu_enable_interrupts(); return block; } void port_free(void *ptr) { + common_hal_mcu_disable_interrupts(); if (((size_t)ptr) < SRAM_BASE) { tlsf_free(_psram_heap, ptr); } else { tlsf_free(_heap, ptr); } + common_hal_mcu_enable_interrupts(); } void *port_realloc(void *ptr, size_t size, bool dma_capable) { if (_psram_size > 0 && ((ptr != NULL && ((size_t)ptr) < SRAM_BASE) || (ptr == NULL && !dma_capable))) { + common_hal_mcu_disable_interrupts(); void *block = tlsf_realloc(_psram_heap, ptr, size); + common_hal_mcu_enable_interrupts(); if (block) { return block; } } - return tlsf_realloc(_heap, ptr, size); + common_hal_mcu_disable_interrupts(); + void *new_ptr = tlsf_realloc(_heap, ptr, size); + common_hal_mcu_enable_interrupts(); + return new_ptr; } +#if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE +bool port_buffer_is_dma_capable(const void *ptr) { + // For RP2350, DMA can only access SRAM, not PSRAM + // PSRAM addresses are below SRAM_BASE + return ptr != NULL && ((size_t)ptr) >= SRAM_BASE; +} +#endif + static bool max_size_walker(void *ptr, size_t size, int used, void *user) { size_t *max_size = (size_t *)user; if (!used && *max_size < size) { diff --git a/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk b/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk index d1df685c6764e..31c2b7e2874f9 100644 --- a/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk +++ b/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk @@ -1,5 +1,5 @@ USB_VID = 0X1B4F -USB_PID = 0x0027 +USB_PID = 0x0029 USB_PRODUCT = "SparkFun STM32 MicroMod Processor" USB_MANUFACTURER = "SparkFun Electronics" diff --git a/py/builtinimport.c b/py/builtinimport.c index 17b3f11c4a001..e4e06d8e2cc8b 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -451,7 +451,9 @@ static mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, if (stat == MP_IMPORT_STAT_NO_EXIST) { // Not found -- fail. - #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE + // CIRCUITPY-CHANGE: always the use more verbose error message that names missing module. + // Otherwise `import a` where `a` imports `b`, but `b` is missing will give a confusing error. + #if 0 && (MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE) mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found")); #else mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("no module named '%q'"), full_mod_name); diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index d6569bc39bd8e..f4ac2350ffbf1 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -992,7 +992,6 @@ endif # Sources used in all ports except unix. SRC_CIRCUITPY_COMMON = \ - shared/libc/string0.c \ shared/readline/readline.c \ lib/oofatfs/ff.c \ lib/oofatfs/ffunicode.c \ @@ -1004,6 +1003,10 @@ SRC_CIRCUITPY_COMMON = \ shared/runtime/stdout_helpers.c \ shared/runtime/sys_stdio_mphal.c +ifeq ($(CIRCUITPY_LIBC_STRING0),1) +SRC_CIRCUITPY_COMMON += shared/libc/string0.c +endif + ifeq ($(CIRCUITPY_QRIO),1) SRC_CIRCUITPY_COMMON += lib/quirc/lib/decode.c lib/quirc/lib/identify.c lib/quirc/lib/quirc.c lib/quirc/lib/version_db.c $(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-type-limits -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 3ca06f7a0fd3a..2754d57b01c9b 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -345,6 +345,9 @@ typedef long mp_off_t; #endif +// For easy debugging printf's. +#define PLAT_PRINTF(...) mp_printf(&mp_plat_print, __VA_ARGS__) + #if MICROPY_PY_ASYNC_AWAIT && !CIRCUITPY_TRACEBACK #error CIRCUITPY_ASYNCIO requires CIRCUITPY_TRACEBACK #endif @@ -453,6 +456,7 @@ void background_callback_run_all(void); #define MICROPY_VM_HOOK_LOOP RUN_BACKGROUND_TASKS; #define MICROPY_VM_HOOK_RETURN RUN_BACKGROUND_TASKS; +#define MICROPY_INTERNAL_EVENT_HOOK (RUN_BACKGROUND_TASKS) // CIRCUITPY_AUTORELOAD_DELAY_MS = 0 will completely disable autoreload. #ifndef CIRCUITPY_AUTORELOAD_DELAY_MS @@ -513,6 +517,18 @@ void background_callback_run_all(void); // USB settings +#ifndef CIRCUITPY_SDCARD_USB +#if CIRCUITPY_USB_DEVICE +#define CIRCUITPY_SDCARD_USB (CIRCUITPY_SDCARDIO && CIRCUITPY_USB_MSC) +#else +#define CIRCUITPY_SDCARD_USB (0) +#endif +#endif + +#if CIRCUITPY_SDCARD_USB && !(CIRCUITPY_SDCARDIO) +#error CIRCUITPY_SDCARD_USB requires CIRCUITPY_SDCARDIO +#endif + // Debug level for TinyUSB. Only outputs over debug UART so it doesn't cause // additional USB logging. #ifndef CIRCUITPY_DEBUG_TINYUSB diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 2009c4e177da6..09ef4361427da 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -62,6 +62,15 @@ CFLAGS += -DCIRCUITPY_FULL_BUILD=$(CIRCUITPY_FULL_BUILD) # increased build time CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 9 +# By default, use our copy of TLSF. Some vendor SDKs may provide their own +# implementation of TLSF, which can be used instead by setting CIRCUITPY_LIB_TLSF=0. +CIRCUITPY_LIB_TLSF ?= 1 + +# By default, use our copy of string0 (memcpy and friends) because it is optimized. Some vendor SDKs +# or ROMs may provide their own implementation of string0, which can be used instead by setting +# CIRCUITPY_LIBC_STRING0=0. +CIRCUITPY_LIBC_STRING0 ?= 1 + # Reduce the size of in-flash properties. Requires support in the .ld linker # file, so not enabled by default. CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 0 @@ -98,6 +107,11 @@ CFLAGS += -DCIRCUITPY_ALARM=$(CIRCUITPY_ALARM) CIRCUITPY_ALARM_TOUCH ?= $(CIRCUITPY_ALARM) CFLAGS += -DCIRCUITPY_ALARM_TOUCH=$(CIRCUITPY_ALARM_TOUCH) +# Enable DMA buffer management for platforms where not all memory is DMA-capable +# Platforms with PSRAM or other non-DMA memory should set this to 0 +CIRCUITPY_ALL_MEMORY_DMA_CAPABLE ?= 1 +CFLAGS += -DCIRCUITPY_ALL_MEMORY_DMA_CAPABLE=$(CIRCUITPY_ALL_MEMORY_DMA_CAPABLE) + CIRCUITPY_ANALOGBUFIO ?= 0 CFLAGS += -DCIRCUITPY_ANALOGBUFIO=$(CIRCUITPY_ANALOGBUFIO) diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 7818bb4f46da8..d6596337ae5a6 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -150,27 +150,27 @@ typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t; static const reg_name_t reg_name_table[] = { - {0, "r0\0"}, - {1, "r1\0"}, - {2, "r2\0"}, - {3, "r3\0"}, - {4, "r4\0"}, - {5, "r5\0"}, - {6, "r6\0"}, - {7, "r7\0"}, - {8, "r8\0"}, - {9, "r9\0"}, - {10, "r10"}, - {11, "r11"}, - {12, "r12"}, - {13, "r13"}, - {14, "r14"}, - {15, "r15"}, - {10, "sl\0"}, - {11, "fp\0"}, - {13, "sp\0"}, - {14, "lr\0"}, - {15, "pc\0"}, + {0, {'r', '0' }}, + {1, {'r', '1' }}, + {2, {'r', '2' }}, + {3, {'r', '3' }}, + {4, {'r', '4' }}, + {5, {'r', '5' }}, + {6, {'r', '6' }}, + {7, {'r', '7' }}, + {8, {'r', '8' }}, + {9, {'r', '9' }}, + {10, {'r', '1', '0' }}, + {11, {'r', '1', '1' }}, + {12, {'r', '1', '2' }}, + {13, {'r', '1', '3' }}, + {14, {'r', '1', '4' }}, + {15, {'r', '1', '5' }}, + {10, {'s', 'l' }}, + {11, {'f', 'p' }}, + {13, {'s', 'p' }}, + {14, {'l', 'r' }}, + {15, {'p', 'c' }}, }; #define MAX_SPECIAL_REGISTER_NAME_LENGTH 7 @@ -368,20 +368,20 @@ typedef struct _cc_name_t { byte cc; byte name[2]; } cc_name_t; static const cc_name_t cc_name_table[] = { - { ASM_THUMB_CC_EQ, "eq" }, - { ASM_THUMB_CC_NE, "ne" }, - { ASM_THUMB_CC_CS, "cs" }, - { ASM_THUMB_CC_CC, "cc" }, - { ASM_THUMB_CC_MI, "mi" }, - { ASM_THUMB_CC_PL, "pl" }, - { ASM_THUMB_CC_VS, "vs" }, - { ASM_THUMB_CC_VC, "vc" }, - { ASM_THUMB_CC_HI, "hi" }, - { ASM_THUMB_CC_LS, "ls" }, - { ASM_THUMB_CC_GE, "ge" }, - { ASM_THUMB_CC_LT, "lt" }, - { ASM_THUMB_CC_GT, "gt" }, - { ASM_THUMB_CC_LE, "le" }, + { ASM_THUMB_CC_EQ, { 'e', 'q' }}, + { ASM_THUMB_CC_NE, { 'n', 'e' }}, + { ASM_THUMB_CC_CS, { 'c', 's' }}, + { ASM_THUMB_CC_CC, { 'c', 'c' }}, + { ASM_THUMB_CC_MI, { 'm', 'i' }}, + { ASM_THUMB_CC_PL, { 'p', 'l' }}, + { ASM_THUMB_CC_VS, { 'v', 's' }}, + { ASM_THUMB_CC_VC, { 'v', 'c' }}, + { ASM_THUMB_CC_HI, { 'h', 'i' }}, + { ASM_THUMB_CC_LS, { 'l', 's' }}, + { ASM_THUMB_CC_GE, { 'g', 'e' }}, + { ASM_THUMB_CC_LT, { 'l', 't' }}, + { ASM_THUMB_CC_GT, { 'g', 't' }}, + { ASM_THUMB_CC_LE, { 'l', 'e' }}, }; typedef struct _format_4_op_t { byte op; @@ -389,21 +389,21 @@ typedef struct _format_4_op_t { byte op; } format_4_op_t; #define X(x) (((x) >> 4) & 0xff) // only need 1 byte to distinguish these ops static const format_4_op_t format_4_op_table[] = { - { X(ASM_THUMB_FORMAT_4_EOR), "eor" }, - { X(ASM_THUMB_FORMAT_4_LSL), "lsl" }, - { X(ASM_THUMB_FORMAT_4_LSR), "lsr" }, - { X(ASM_THUMB_FORMAT_4_ASR), "asr" }, - { X(ASM_THUMB_FORMAT_4_ADC), "adc" }, - { X(ASM_THUMB_FORMAT_4_SBC), "sbc" }, - { X(ASM_THUMB_FORMAT_4_ROR), "ror" }, - { X(ASM_THUMB_FORMAT_4_TST), "tst" }, - { X(ASM_THUMB_FORMAT_4_NEG), "neg" }, - { X(ASM_THUMB_FORMAT_4_CMP), "cmp" }, - { X(ASM_THUMB_FORMAT_4_CMN), "cmn" }, - { X(ASM_THUMB_FORMAT_4_ORR), "orr" }, - { X(ASM_THUMB_FORMAT_4_MUL), "mul" }, - { X(ASM_THUMB_FORMAT_4_BIC), "bic" }, - { X(ASM_THUMB_FORMAT_4_MVN), "mvn" }, + { X(ASM_THUMB_FORMAT_4_EOR), {'e', 'o', 'r' }}, + { X(ASM_THUMB_FORMAT_4_LSL), {'l', 's', 'l' }}, + { X(ASM_THUMB_FORMAT_4_LSR), {'l', 's', 'r' }}, + { X(ASM_THUMB_FORMAT_4_ASR), {'a', 's', 'r' }}, + { X(ASM_THUMB_FORMAT_4_ADC), {'a', 'd', 'c' }}, + { X(ASM_THUMB_FORMAT_4_SBC), {'s', 'b', 'c' }}, + { X(ASM_THUMB_FORMAT_4_ROR), {'r', 'o', 'r' }}, + { X(ASM_THUMB_FORMAT_4_TST), {'t', 's', 't' }}, + { X(ASM_THUMB_FORMAT_4_NEG), {'n', 'e', 'g' }}, + { X(ASM_THUMB_FORMAT_4_CMP), {'c', 'm', 'p' }}, + { X(ASM_THUMB_FORMAT_4_CMN), {'c', 'm', 'n' }}, + { X(ASM_THUMB_FORMAT_4_ORR), {'o', 'r', 'r' }}, + { X(ASM_THUMB_FORMAT_4_MUL), {'m', 'u', 'l' }}, + { X(ASM_THUMB_FORMAT_4_BIC), {'b', 'i', 'c' }}, + { X(ASM_THUMB_FORMAT_4_MVN), {'m', 'v', 'n' }}, }; #undef X @@ -428,10 +428,10 @@ typedef struct _format_vfp_op_t { char name[3]; } format_vfp_op_t; static const format_vfp_op_t format_vfp_op_table[] = { - { 0x30, "add" }, - { 0x34, "sub" }, - { 0x20, "mul" }, - { 0x80, "div" }, + { 0x30, {'a', 'd', 'd' }}, + { 0x34, {'s', 'u', 'b' }}, + { 0x20, {'m', 'u', 'l' }}, + { 0x80, {'d', 'i', 'v' }}, }; // shorthand alias for whether we allow ARMv7-M instructions diff --git a/py/gc.c b/py/gc.c index 2cf4dbb64a83b..c6da81d495c10 100644 --- a/py/gc.c +++ b/py/gc.c @@ -446,7 +446,7 @@ bool gc_is_locked(void) { } // CIRCUITPY-CHANGE: additional function -bool gc_ptr_on_heap(void *ptr) { +bool gc_ptr_on_heap(const void *ptr) { for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { if (ptr >= (void *)area->gc_pool_start // must be above start of pool && ptr < (void *)area->gc_pool_end) { // must be below end of pool diff --git a/py/gc.h b/py/gc.h index ebc32b080fb47..0752478d1f286 100644 --- a/py/gc.h +++ b/py/gc.h @@ -87,7 +87,7 @@ void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move); // CIRCUITPY-CHANGE // True if the pointer is on the MP heap. Doesn't require that it is the start // of a block. -bool gc_ptr_on_heap(void *ptr); +bool gc_ptr_on_heap(const void *ptr); typedef struct _gc_info_t { size_t total; diff --git a/py/misc.h b/py/misc.h index eb7fc54be6fec..22f32147124fc 100644 --- a/py/misc.h +++ b/py/misc.h @@ -54,7 +54,14 @@ typedef unsigned int uint; #define MP_STRINGIFY(x) MP_STRINGIFY_HELPER(x) // Static assertion macro +#if defined(__cplusplus) +#define MP_STATIC_ASSERT(cond) static_assert((cond), #cond) +#elif __GNUC__ >= 5 || __STDC_VERSION__ >= 201112L +#define MP_STATIC_ASSERT(cond) _Static_assert((cond), #cond) +#else #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) +#endif + // In C++ things like comparing extern const pointers are not constant-expressions so cannot be used // in MP_STATIC_ASSERT. Note that not all possible compiler versions will reject this. Some gcc versions // do, others only with -Werror=vla, msvc always does. @@ -63,7 +70,10 @@ typedef unsigned int uint; #if defined(_MSC_VER) || defined(__cplusplus) #define MP_STATIC_ASSERT_NONCONSTEXPR(cond) ((void)1) #else -#define MP_STATIC_ASSERT_NONCONSTEXPR(cond) MP_STATIC_ASSERT(cond) +#if defined(__clang__) +#pragma GCC diagnostic ignored "-Wgnu-folding-constant" +#endif +#define MP_STATIC_ASSERT_NONCONSTEXPR(cond) ((void)sizeof(char[1 - 2 * !(cond)])) #endif // Round-up integer division diff --git a/py/objdeque.c b/py/objdeque.c index 264c795801ba4..4e1ee82e9d4de 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -46,6 +46,11 @@ static mp_obj_t mp_obj_deque_extend(mp_obj_t self_in, mp_obj_t arg_in); static mp_obj_t mp_obj_new_deque_it(mp_obj_t deque, mp_obj_iter_buf_t *iter_buf); #endif +// CIRCUITPY-CHANGE +static mp_obj_deque_t *native_deque(mp_obj_t self_in) { + return MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_deque))); +} + static mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 3, false); @@ -79,7 +84,8 @@ static size_t deque_len(mp_obj_deque_t *self) { } static mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->i_get != self->i_put); @@ -98,7 +104,8 @@ static mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } static mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); size_t new_i_put = self->i_put + 1; if (new_i_put == self->alloc) { @@ -123,7 +130,8 @@ static mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) { static MP_DEFINE_CONST_FUN_OBJ_2(deque_append_obj, mp_obj_deque_append); static mp_obj_t mp_obj_deque_appendleft(mp_obj_t self_in, mp_obj_t arg) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); size_t new_i_get = self->i_get - 1; if (self->i_get == 0) { @@ -162,7 +170,8 @@ static mp_obj_t mp_obj_deque_extend(mp_obj_t self_in, mp_obj_t arg_in) { static MP_DEFINE_CONST_FUN_OBJ_2(deque_extend_obj, mp_obj_deque_extend); static mp_obj_t deque_popleft(mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); if (self->i_get == self->i_put) { mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty")); @@ -180,7 +189,8 @@ static mp_obj_t deque_popleft(mp_obj_t self_in) { static MP_DEFINE_CONST_FUN_OBJ_1(deque_popleft_obj, deque_popleft); static mp_obj_t deque_pop(mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); if (self->i_get == self->i_put) { mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty")); @@ -205,7 +215,8 @@ static mp_obj_t deque_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { // delete not supported, fall back to mp_obj_subscr() error message return MP_OBJ_NULL; } - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); size_t offset = mp_get_index(self->base.type, deque_len(self), index, false); size_t index_val = self->i_get + offset; @@ -226,7 +237,8 @@ static mp_obj_t deque_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if 0 static mp_obj_t deque_clear(mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); self->i_get = self->i_put = 0; mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items)); return mp_const_none; @@ -286,7 +298,8 @@ typedef struct _mp_obj_deque_it_t { static mp_obj_t deque_it_iternext(mp_obj_t self_in) { mp_obj_deque_it_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_deque_t *deque = MP_OBJ_TO_PTR(self->deque); + // CIRCUITPY-CHANGE + mp_obj_deque_t *deque = native_deque(self->deque); if (self->cur != deque->i_put) { mp_obj_t o_out = deque->items[self->cur]; if (++self->cur == deque->alloc) { @@ -298,9 +311,10 @@ static mp_obj_t deque_it_iternext(mp_obj_t self_in) { } } -static mp_obj_t mp_obj_new_deque_it(mp_obj_t deque, mp_obj_iter_buf_t *iter_buf) { - mp_obj_deque_t *deque_ = MP_OBJ_TO_PTR(deque); - size_t i_get = deque_->i_get; +static mp_obj_t mp_obj_new_deque_it(mp_obj_t deque_in, mp_obj_iter_buf_t *iter_buf) { + // CIRCUITPY-CHANGE + mp_obj_deque_t *deque = native_deque(deque_in); + size_t i_get = deque->i_get; assert(sizeof(mp_obj_deque_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_deque_it_t *o = (mp_obj_deque_it_t *)iter_buf; o->base.type = &mp_type_polymorph_iter; diff --git a/py/objtuple.c b/py/objtuple.c index 42e8d56a806cc..e0b31edaf2376 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -250,6 +250,9 @@ MP_DEFINE_CONST_OBJ_TYPE( // the zero-length tuple const mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0}; +// CIRCUITPY-CHANGE: No change here, but implementation was copied for +// mp_obj_new_port_tuple in supervisor/shared/port.c, which allocates using port_malloc(). +// Change that to match if this changes. mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) { if (n == 0) { return mp_const_empty_tuple; diff --git a/py/persistentcode.c b/py/persistentcode.c index 1976729f4d879..93f4c33deb4e2 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -471,6 +471,9 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { read_bytes(reader, header, sizeof(header)); byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); // CIRCUITPY-CHANGE: 'C', not 'M' + if (header[0] == 'M') { + mp_raise_ValueError(MP_ERROR_TEXT("MicroPython .mpy file; use CircuitPython mpy-cross")); + } if (header[0] != 'C' || header[1] != MPY_VERSION || (arch != MP_NATIVE_ARCH_NONE && MPY_FEATURE_DECODE_SUB_VERSION(header[2]) != MPY_SUB_VERSION) diff --git a/py/scheduler.c b/py/scheduler.c index 5984346a6f68a..92e5af6b31b20 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -277,10 +277,6 @@ void mp_event_wait_indefinite(void) { MICROPY_EVENT_POLL_HOOK #else mp_event_handle_nowait(); - - // CIRCUITPY-CHANGE: don't starve CircuitPython background tasks - RUN_BACKGROUND_TASKS; - MICROPY_INTERNAL_WFE(-1); #endif } @@ -293,10 +289,6 @@ void mp_event_wait_ms(mp_uint_t timeout_ms) { MICROPY_EVENT_POLL_HOOK #else mp_event_handle_nowait(); - - // CIRCUITPY-CHANGE: don't starve CircuitPython background tasks - RUN_BACKGROUND_TASKS; - MICROPY_INTERNAL_WFE(timeout_ms); #endif } diff --git a/requirements-dev.txt b/requirements-dev.txt index 261a5cc2c7fe8..0e8426d5174d4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -25,7 +25,8 @@ intelhex # for building & testing natmods pyelftools -cryptography +# newer versions break ESP-IDF now +cryptography<45 # for web workflow minify minify_html diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 92b910c8b2e0f..839b8b19addfa 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -339,7 +339,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args if (args[ARG_prefixes].u_obj != MP_OBJ_NULL) { mp_get_buffer_raise(args[ARG_prefixes].u_obj, &prefix_bufinfo, MP_BUFFER_READ); // An empty buffer may not be on the heap, but that doesn't matter. - if (prefix_bufinfo.len > 0 && gc_nbytes(prefix_bufinfo.buf) == 0) { + if (prefix_bufinfo.len > 0 && !gc_ptr_on_heap(prefix_bufinfo.buf)) { mp_raise_ValueError(MP_ERROR_TEXT("Prefix buffer must be on the heap")); } } diff --git a/shared-bindings/audiodelays/Chorus.c b/shared-bindings/audiodelays/Chorus.c index c6bfa2ffa7eb1..87922ff110b1b 100644 --- a/shared-bindings/audiodelays/Chorus.c +++ b/shared-bindings/audiodelays/Chorus.c @@ -206,11 +206,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_get_playing_obj, audiodelays_chorus MP_PROPERTY_GETTER(audiodelays_chorus_playing_obj, (mp_obj_t)&audiodelays_chorus_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Chorus: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Chorus""" //| ... //| static mp_obj_t audiodelays_chorus_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -228,7 +232,7 @@ static mp_obj_t audiodelays_chorus_obj_play(size_t n_args, const mp_obj_t *pos_a mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiodelays_chorus_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_chorus_play_obj, 1, audiodelays_chorus_obj_play); diff --git a/shared-bindings/audiodelays/Echo.c b/shared-bindings/audiodelays/Echo.c index 5ae849b19aa41..dbb496c61b975 100644 --- a/shared-bindings/audiodelays/Echo.c +++ b/shared-bindings/audiodelays/Echo.c @@ -230,11 +230,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_playing_obj, audiodelays_echo_obj MP_PROPERTY_GETTER(audiodelays_echo_playing_obj, (mp_obj_t)&audiodelays_echo_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Echo: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Echo""" //| ... //| static mp_obj_t audiodelays_echo_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -252,7 +256,7 @@ static mp_obj_t audiodelays_echo_obj_play(size_t n_args, const mp_obj_t *pos_arg mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiodelays_echo_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_echo_play_obj, 1, audiodelays_echo_obj_play); diff --git a/shared-bindings/audiodelays/MultiTapDelay.c b/shared-bindings/audiodelays/MultiTapDelay.c index 5b057eaf80d1b..2126dbf990435 100644 --- a/shared-bindings/audiodelays/MultiTapDelay.c +++ b/shared-bindings/audiodelays/MultiTapDelay.c @@ -233,11 +233,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_get_playing_obj, audiodela MP_PROPERTY_GETTER(audiodelays_multi_tap_delay_playing_obj, (mp_obj_t)&audiodelays_multi_tap_delay_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> MultiTapDelay: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: MultiTapDelay""" //| ... //| static mp_obj_t audiodelays_multi_tap_delay_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -255,7 +259,7 @@ static mp_obj_t audiodelays_multi_tap_delay_obj_play(size_t n_args, const mp_obj mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiodelays_multi_tap_delay_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_multi_tap_delay_play_obj, 1, audiodelays_multi_tap_delay_obj_play); diff --git a/shared-bindings/audiodelays/PitchShift.c b/shared-bindings/audiodelays/PitchShift.c index df2189945aa5d..b94df7d9edd08 100644 --- a/shared-bindings/audiodelays/PitchShift.c +++ b/shared-bindings/audiodelays/PitchShift.c @@ -190,11 +190,15 @@ MP_PROPERTY_GETTER(audiodelays_pitch_shift_playing_obj, (mp_obj_t)&audiodelays_pitch_shift_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> PitchShift: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: PitchShift""" //| ... //| static mp_obj_t audiodelays_pitch_shift_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -211,7 +215,7 @@ static mp_obj_t audiodelays_pitch_shift_obj_play(size_t n_args, const mp_obj_t * mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiodelays_pitch_shift_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_pitch_shift_play_obj, 1, audiodelays_pitch_shift_obj_play); diff --git a/shared-bindings/audiofilters/Distortion.c b/shared-bindings/audiofilters/Distortion.c index cb888d0c71b7b..8de4c1d1ea331 100644 --- a/shared-bindings/audiofilters/Distortion.c +++ b/shared-bindings/audiofilters/Distortion.c @@ -309,11 +309,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_playing_obj, audiofilters_ MP_PROPERTY_GETTER(audiofilters_distortion_playing_obj, (mp_obj_t)&audiofilters_distortion_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Distortion: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Distortion""" //| ... //| static mp_obj_t audiofilters_distortion_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -331,7 +335,7 @@ static mp_obj_t audiofilters_distortion_obj_play(size_t n_args, const mp_obj_t * mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiofilters_distortion_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiofilters_distortion_play_obj, 1, audiofilters_distortion_obj_play); diff --git a/shared-bindings/audiofilters/Filter.c b/shared-bindings/audiofilters/Filter.c index 2a4887a4d42a2..426fff226168f 100644 --- a/shared-bindings/audiofilters/Filter.c +++ b/shared-bindings/audiofilters/Filter.c @@ -179,11 +179,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_get_playing_obj, audiofilters_filt MP_PROPERTY_GETTER(audiofilters_filter_playing_obj, (mp_obj_t)&audiofilters_filter_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Filter: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Filter""" //| ... //| static mp_obj_t audiofilters_filter_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -201,7 +205,7 @@ static mp_obj_t audiofilters_filter_obj_play(size_t n_args, const mp_obj_t *pos_ mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiofilters_filter_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiofilters_filter_play_obj, 1, audiofilters_filter_obj_play); diff --git a/shared-bindings/audiofilters/Phaser.c b/shared-bindings/audiofilters/Phaser.c index e7ddd986176b3..9f713afce5f72 100644 --- a/shared-bindings/audiofilters/Phaser.c +++ b/shared-bindings/audiofilters/Phaser.c @@ -214,11 +214,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_get_playing_obj, audiofilters_phas MP_PROPERTY_GETTER(audiofilters_phaser_playing_obj, (mp_obj_t)&audiofilters_phaser_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Phaser: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Phaser""" //| ... //| static mp_obj_t audiofilters_phaser_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -236,7 +240,7 @@ static mp_obj_t audiofilters_phaser_obj_play(size_t n_args, const mp_obj_t *pos_ mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiofilters_phaser_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiofilters_phaser_play_obj, 1, audiofilters_phaser_obj_play); diff --git a/shared-bindings/audiofreeverb/Freeverb.c b/shared-bindings/audiofreeverb/Freeverb.c index 62c9237a0d271..12eb7ef70ab79 100644 --- a/shared-bindings/audiofreeverb/Freeverb.c +++ b/shared-bindings/audiofreeverb/Freeverb.c @@ -196,11 +196,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_playing_obj, audiofreeverb_ MP_PROPERTY_GETTER(audiofreeverb_freeverb_playing_obj, (mp_obj_t)&audiofreeverb_freeverb_get_playing_obj); -//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Freeverb: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| The sample must match the encoding settings given in the constructor.""" +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Freeverb""" //| ... //| static mp_obj_t audiofreeverb_freeverb_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -218,7 +222,7 @@ static mp_obj_t audiofreeverb_freeverb_obj_play(size_t n_args, const mp_obj_t *p mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiofreeverb_freeverb_play(self, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiofreeverb_freeverb_play_obj, 1, audiofreeverb_freeverb_obj_play); diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c index dda6d06bd500c..516d079cd2a09 100644 --- a/shared-bindings/audiomixer/Mixer.c +++ b/shared-bindings/audiomixer/Mixer.c @@ -160,13 +160,17 @@ MP_PROPERTY_GETTER(audiomixer_mixer_voice_obj, //| def play( //| self, sample: circuitpython_typing.AudioSample, *, voice: int = 0, loop: bool = False -//| ) -> None: +//| ) -> Mixer: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| //| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`. //| -//| The sample must match the Mixer's encoding settings given in the constructor.""" +//| The sample must match the Mixer's encoding settings given in the constructor. +//| +//| :return: The mixer object itself. Can be used for chaining, ie: +//| ``audio.play(mixer.play(sample))``. +//| :rtype: Chorus""" //| ... //| static mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -189,7 +193,7 @@ static mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_arg mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiomixer_mixervoice_play(voice, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixer_play_obj, 1, audiomixer_mixer_obj_play); diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c index fc292d4ea2f68..128c214d447f8 100644 --- a/shared-bindings/audiomixer/MixerVoice.c +++ b/shared-bindings/audiomixer/MixerVoice.c @@ -114,6 +114,31 @@ MP_PROPERTY_GETSET(audiomixer_mixervoice_level_obj, (mp_obj_t)&audiomixer_mixervoice_get_level_obj, (mp_obj_t)&audiomixer_mixervoice_set_level_obj); +//| panning: synthio.BlockInput +//| """Defines the channel(s) in which the voice appears, as a floating point number between +//| -1 and 1. If your board does not support synthio, this property will only accept a float +//| value. This property is ignored if ``audiomixer.Mixer.channel_count=1``. +//| +//| -1 is left channel only, 0 is both channels, and 1 is right channel. For fractional values, +//| the note plays at full amplitude in one channel and partial amplitude in the other channel. +//| For instance -.5 plays at full amplitude in the left channel and 1/2 amplitude in the right +//| channel.""" +static mp_obj_t audiomixer_mixervoice_obj_get_panning(mp_obj_t self_in) { + return common_hal_audiomixer_mixervoice_get_panning(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_panning_obj, audiomixer_mixervoice_obj_get_panning); + +static mp_obj_t audiomixer_mixervoice_obj_set_panning(mp_obj_t self_in, mp_obj_t panning_in) { + audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiomixer_mixervoice_set_panning(self, panning_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiomixer_mixervoice_set_panning_obj, audiomixer_mixervoice_obj_set_panning); + +MP_PROPERTY_GETSET(audiomixer_mixervoice_panning_obj, + (mp_obj_t)&audiomixer_mixervoice_get_panning_obj, + (mp_obj_t)&audiomixer_mixervoice_set_panning_obj); + //| loop: bool //| """Get or set the loop status of the currently playing sample.""" static mp_obj_t audiomixer_mixervoice_obj_get_loop(mp_obj_t self_in) { @@ -158,6 +183,7 @@ static const mp_rom_map_elem_t audiomixer_mixervoice_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiomixer_mixervoice_playing_obj) }, { MP_ROM_QSTR(MP_QSTR_level), MP_ROM_PTR(&audiomixer_mixervoice_level_obj) }, + { MP_ROM_QSTR(MP_QSTR_panning), MP_ROM_PTR(&audiomixer_mixervoice_panning_obj) }, { MP_ROM_QSTR(MP_QSTR_loop), MP_ROM_PTR(&audiomixer_mixervoice_loop_obj) }, }; static MP_DEFINE_CONST_DICT(audiomixer_mixervoice_locals_dict, audiomixer_mixervoice_locals_dict_table); diff --git a/shared-bindings/audiomixer/MixerVoice.h b/shared-bindings/audiomixer/MixerVoice.h index fe350eb1a7592..d60820f7f5734 100644 --- a/shared-bindings/audiomixer/MixerVoice.h +++ b/shared-bindings/audiomixer/MixerVoice.h @@ -18,6 +18,8 @@ void common_hal_audiomixer_mixervoice_stop(audiomixer_mixervoice_obj_t *self); void common_hal_audiomixer_mixervoice_end(audiomixer_mixervoice_obj_t *self); mp_obj_t common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t *self); void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t *self, mp_obj_t gain); +mp_obj_t common_hal_audiomixer_mixervoice_get_panning(audiomixer_mixervoice_obj_t *self); +void common_hal_audiomixer_mixervoice_set_panning(audiomixer_mixervoice_obj_t *self, mp_obj_t value); bool common_hal_audiomixer_mixervoice_get_playing(audiomixer_mixervoice_obj_t *self); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 5f1d301b675be..4714c3ee0733a 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -368,14 +368,14 @@ static mp_obj_t busio_uart_obj_reset_input_buffer(mp_obj_t self_in) { return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_reset_input_buffer_obj, busio_uart_obj_reset_input_buffer); -//| class Parity: -//| """Enum-like class to define the parity used to verify correct data transfer.""" +//| class Parity: +//| """Enum-like class to define the parity used to verify correct data transfer.""" //| -//| ODD: int -//| """Total number of ones should be odd.""" +//| ODD: int +//| """Total number of ones should be odd.""" //| -//| EVEN: int -//| """Total number of ones should be even.""" +//| EVEN: int +//| """Total number of ones should be even.""" //| //| const mp_obj_type_t busio_uart_parity_type; diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index eddf3f66c4ec0..560fb66a67553 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -49,7 +49,7 @@ void displayio_tilegrid_validate_pixel_shader(mp_obj_t pixel_shader) { //| self, //| bitmap: Union[Bitmap, OnDiskBitmap], //| *, -//| pixel_shader: Union[ColorConverter, Palette], +//| pixel_shader: Union[ColorConverter, Palette, tilepalettemapper.TilePaletteMapper], //| width: int = 1, //| height: int = 1, //| tile_width: Optional[int] = None, @@ -68,7 +68,7 @@ void displayio_tilegrid_validate_pixel_shader(mp_obj_t pixel_shader) { //| tile_width and tile_height match the height of the bitmap by default. //| //| :param Bitmap,OnDiskBitmap bitmap: The bitmap storing one or more tiles. -//| :param ColorConverter,Palette pixel_shader: The pixel shader that produces colors from values +//| :param ColorConverter,Palette,tilepalettemapper.TilePaletteMapper pixel_shader: The pixel shader that produces colors from values //| :param int width: Width of the grid in tiles. //| :param int height: Height of the grid in tiles. //| :param int tile_width: Width of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions. @@ -330,7 +330,7 @@ static mp_obj_t displayio_tilegrid_obj_contains(mp_obj_t self_in, mp_obj_t touch } MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_contains_obj, displayio_tilegrid_obj_contains); -//| pixel_shader: Union[ColorConverter, Palette] +//| pixel_shader: Union[ColorConverter, Palette, tilepalettemapper.TilePaletteMapper] //| """The pixel shader of the tilegrid.""" static mp_obj_t displayio_tilegrid_obj_get_pixel_shader(mp_obj_t self_in) { displayio_tilegrid_t *self = native_tilegrid(self_in); diff --git a/shared-bindings/epaperdisplay/EPaperDisplay.c b/shared-bindings/epaperdisplay/EPaperDisplay.c index 9f261d599ada9..cd9c18e27d526 100644 --- a/shared-bindings/epaperdisplay/EPaperDisplay.c +++ b/shared-bindings/epaperdisplay/EPaperDisplay.c @@ -211,20 +211,43 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, } self->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - self, - display_bus, - start_bufinfo.buf, start_bufinfo.len, start_up_time, stop_bufinfo.buf, stop_bufinfo.len, - args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_ram_width].u_int, args[ARG_ram_height].u_int, - args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation, - args[ARG_set_column_window_command].u_int, args[ARG_set_row_window_command].u_int, - args[ARG_set_current_column_command].u_int, args[ARG_set_current_row_command].u_int, - args[ARG_write_black_ram_command].u_int, args[ARG_black_bits_inverted].u_bool, write_color_ram_command, - args[ARG_color_bits_inverted].u_bool, highlight_color, highlight_color2, refresh_buf, refresh_buf_len, refresh_time, - busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame, - args[ARG_always_toggle_chip_select].u_bool, args[ARG_grayscale].u_bool, args[ARG_advanced_color_epaper].u_bool, args[ARG_spectra6].u_bool, - two_byte_sequence_length, args[ARG_address_little_endian].u_bool - ); + epaperdisplay_construct_args_t construct_args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + construct_args.bus = display_bus; + construct_args.start_sequence = start_bufinfo.buf; + construct_args.start_sequence_len = start_bufinfo.len; + construct_args.start_up_time = start_up_time; + construct_args.stop_sequence = stop_bufinfo.buf; + construct_args.stop_sequence_len = stop_bufinfo.len; + construct_args.width = args[ARG_width].u_int; + construct_args.height = args[ARG_height].u_int; + construct_args.ram_width = args[ARG_ram_width].u_int; + construct_args.ram_height = args[ARG_ram_height].u_int; + construct_args.colstart = args[ARG_colstart].u_int; + construct_args.rowstart = args[ARG_rowstart].u_int; + construct_args.rotation = rotation; + construct_args.set_column_window_command = args[ARG_set_column_window_command].u_int; + construct_args.set_row_window_command = args[ARG_set_row_window_command].u_int; + construct_args.set_current_column_command = args[ARG_set_current_column_command].u_int; + construct_args.set_current_row_command = args[ARG_set_current_row_command].u_int; + construct_args.write_black_ram_command = args[ARG_write_black_ram_command].u_int; + construct_args.black_bits_inverted = args[ARG_black_bits_inverted].u_bool; + construct_args.write_color_ram_command = write_color_ram_command; + construct_args.color_bits_inverted = args[ARG_color_bits_inverted].u_bool; + construct_args.highlight_color = highlight_color; + construct_args.highlight_color2 = highlight_color2; + construct_args.refresh_sequence = refresh_buf; + construct_args.refresh_sequence_len = refresh_buf_len; + construct_args.refresh_time = refresh_time; + construct_args.busy_pin = busy_pin; + construct_args.busy_state = args[ARG_busy_state].u_bool; + construct_args.seconds_per_frame = seconds_per_frame; + construct_args.always_toggle_chip_select = args[ARG_always_toggle_chip_select].u_bool; + construct_args.grayscale = args[ARG_grayscale].u_bool; + construct_args.acep = args[ARG_advanced_color_epaper].u_bool; + construct_args.spectra6 = args[ARG_spectra6].u_bool; + construct_args.two_byte_sequence_length = two_byte_sequence_length; + construct_args.address_little_endian = args[ARG_address_little_endian].u_bool; + common_hal_epaperdisplay_epaperdisplay_construct(self, &construct_args); return self; } diff --git a/shared-bindings/epaperdisplay/EPaperDisplay.h b/shared-bindings/epaperdisplay/EPaperDisplay.h index afa90a514e2a5..83f0b0377fe6c 100644 --- a/shared-bindings/epaperdisplay/EPaperDisplay.h +++ b/shared-bindings/epaperdisplay/EPaperDisplay.h @@ -15,19 +15,84 @@ extern const mp_obj_type_t epaperdisplay_epaperdisplay_type; #define NO_COMMAND 0x100 +typedef struct { + mp_obj_t bus; + const uint8_t *start_sequence; + uint16_t start_sequence_len; + mp_float_t start_up_time; + const uint8_t *stop_sequence; + uint16_t stop_sequence_len; + uint16_t width; + uint16_t height; + uint16_t ram_width; + uint16_t ram_height; + int16_t colstart; + int16_t rowstart; + uint16_t rotation; + uint16_t set_column_window_command; + uint16_t set_row_window_command; + uint16_t set_current_column_command; + uint16_t set_current_row_command; + uint16_t write_black_ram_command; + bool black_bits_inverted; + uint16_t write_color_ram_command; + bool color_bits_inverted; + uint32_t highlight_color; + uint32_t highlight_color2; + const uint8_t *refresh_sequence; + uint16_t refresh_sequence_len; + mp_float_t refresh_time; + const mcu_pin_obj_t *busy_pin; + bool busy_state; + mp_float_t seconds_per_frame; + bool always_toggle_chip_select; + bool grayscale; + bool acep; + bool spectra6; + bool two_byte_sequence_length; + bool address_little_endian; +} epaperdisplay_construct_args_t; + +#define EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS { \ + .bus = mp_const_none, \ + .start_sequence = NULL, \ + .start_sequence_len = 0, \ + .start_up_time = 0.0, \ + .stop_sequence = NULL, \ + .stop_sequence_len = 0, \ + .width = 0, \ + .height = 0, \ + .ram_width = 0, \ + .ram_height = 0, \ + .colstart = 0, \ + .rowstart = 0, \ + .rotation = 0, \ + .set_column_window_command = NO_COMMAND, \ + .set_row_window_command = NO_COMMAND, \ + .set_current_column_command = NO_COMMAND, \ + .set_current_row_command = NO_COMMAND, \ + .write_black_ram_command = NO_COMMAND, \ + .black_bits_inverted = false, \ + .write_color_ram_command = NO_COMMAND, \ + .color_bits_inverted = false, \ + .highlight_color = 0x000000, \ + .highlight_color2 = 0x000000, \ + .refresh_sequence = NULL, \ + .refresh_sequence_len = 0, \ + .refresh_time = 0.0, \ + .busy_pin = NULL, \ + .busy_state = false, \ + .seconds_per_frame = 0.0, \ + .always_toggle_chip_select = false, \ + .grayscale = false, \ + .acep = false, \ + .spectra6 = false, \ + .two_byte_sequence_length = false, \ + .address_little_endian = false \ +} + void common_hal_epaperdisplay_epaperdisplay_construct(epaperdisplay_epaperdisplay_obj_t *self, - mp_obj_t bus, const uint8_t *start_sequence, uint16_t start_sequence_len, mp_float_t start_up_time, - const uint8_t *stop_sequence, uint16_t stop_sequence_len, - uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, - int16_t colstart, int16_t rowstart, uint16_t rotation, - uint16_t set_column_window_command, uint16_t set_row_window_command, - uint16_t set_current_column_command, uint16_t set_current_row_command, - uint16_t write_black_ram_command, bool black_bits_inverted, - uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint32_t highlight_color2, - const uint8_t *refresh_sequence, uint16_t refresh_sequence_len, mp_float_t refresh_time, - const mcu_pin_obj_t *busy_pin, bool busy_state, mp_float_t seconds_per_frame, - bool always_toggle_chip_select, bool grayscale, bool acep, bool spectra6, bool two_byte_sequence_length, - bool address_little_endian); + const epaperdisplay_construct_args_t *args); bool common_hal_epaperdisplay_epaperdisplay_refresh(epaperdisplay_epaperdisplay_obj_t *self); diff --git a/shared-bindings/keypad/EventQueue.h b/shared-bindings/keypad/EventQueue.h index 893165e3220f1..02c3414b0764c 100644 --- a/shared-bindings/keypad/EventQueue.h +++ b/shared-bindings/keypad/EventQueue.h @@ -11,7 +11,7 @@ extern const mp_obj_type_t keypad_eventqueue_type; -void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events); +void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events, bool use_gc_allocator); void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self); size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self); diff --git a/shared-bindings/keypad_demux/DemuxKeyMatrix.c b/shared-bindings/keypad_demux/DemuxKeyMatrix.c index d76a20aec9d01..f1b5ecae9ceb6 100644 --- a/shared-bindings/keypad_demux/DemuxKeyMatrix.c +++ b/shared-bindings/keypad_demux/DemuxKeyMatrix.c @@ -123,7 +123,8 @@ static mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type, column_pins_array[column] = pin; } - common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, args[ARG_transpose].u_bool, interval, max_events, debounce_threshold); + // Last arg is use_gc_allocator, true during VM use. + common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, args[ARG_transpose].u_bool, interval, max_events, debounce_threshold, true); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/keypad_demux/DemuxKeyMatrix.h b/shared-bindings/keypad_demux/DemuxKeyMatrix.h index 8bdaa597dc035..25d36283e90fc 100644 --- a/shared-bindings/keypad_demux/DemuxKeyMatrix.h +++ b/shared-bindings/keypad_demux/DemuxKeyMatrix.h @@ -11,7 +11,7 @@ extern const mp_obj_type_t keypad_demux_demuxkeymatrix_type; -void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], bool columns_to_anodes, bool transpose, mp_float_t interval, size_t max_events, uint8_t debounce_threshold); +void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], bool columns_to_anodes, bool transpose, mp_float_t interval, size_t max_events, uint8_t debounce_threshold, bool use_gc_allocator); void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_obj_t *self); diff --git a/shared-bindings/rotaryio/IncrementalEncoder.h b/shared-bindings/rotaryio/IncrementalEncoder.h index 1c60dd69a1937..b3ceb3eeb1513 100644 --- a/shared-bindings/rotaryio/IncrementalEncoder.h +++ b/shared-bindings/rotaryio/IncrementalEncoder.h @@ -13,11 +13,15 @@ extern const mp_obj_type_t rotaryio_incrementalencoder_type; extern void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b); + extern void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t *self); extern bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self); +extern void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self); + extern mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self); extern void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self, mp_int_t new_position); + extern mp_int_t common_hal_rotaryio_incrementalencoder_get_divisor(rotaryio_incrementalencoder_obj_t *self); extern void common_hal_rotaryio_incrementalencoder_set_divisor(rotaryio_incrementalencoder_obj_t *self, mp_int_t new_divisor); diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index ee0fb4ab53c3a..14ec16f3096c7 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -54,15 +54,11 @@ static mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t // get the mount point const char *mnt_str = mp_obj_str_get_str(args[ARG_mount_path].u_obj); - // Make sure we're given an object we can mount. - // TODO(tannewt): Make sure we have all the methods we need to operating it - // as a file system. + mp_obj_t vfs_obj = args[ARG_filesystem].u_obj; - mp_obj_t dest[2]; - mp_load_method_maybe(vfs_obj, MP_QSTR_mount, dest); - if (dest[0] == MP_OBJ_NULL) { - mp_raise_ValueError(MP_ERROR_TEXT("filesystem must provide mount method")); - } + + // Currently, the only supported filesystem is VfsFat. + mp_arg_validate_type(vfs_obj, &mp_fat_vfs_type, MP_QSTR_filesystem); common_hal_storage_mount(vfs_obj, mnt_str, args[ARG_readonly].u_bool); diff --git a/shared-bindings/synthio/MidiTrack.c b/shared-bindings/synthio/MidiTrack.c index 9add8f1745c83..db75a543c613d 100644 --- a/shared-bindings/synthio/MidiTrack.c +++ b/shared-bindings/synthio/MidiTrack.c @@ -115,6 +115,27 @@ static void check_for_deinit(synthio_miditrack_obj_t *self) { //| """32 bit value that tells how quickly samples are played in Hertz (cycles per second).""" //| +//| tempo: int +//| """Tempo of the streamed events, in MIDI ticks per second.""" +//| +static mp_obj_t synthio_miditrack_obj_get_tempo(mp_obj_t self_in) { + synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_int(common_hal_synthio_miditrack_get_tempo(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_get_tempo_obj, synthio_miditrack_obj_get_tempo); + +static mp_obj_t synthio_miditrack_obj_set_tempo(mp_obj_t self_in, mp_obj_t arg) { + synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_synthio_miditrack_set_tempo(self, mp_obj_get_int(arg)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_miditrack_set_tempo_obj, synthio_miditrack_obj_set_tempo); +MP_PROPERTY_GETSET(synthio_miditrack_tempo_obj, + (mp_obj_t)&synthio_miditrack_get_tempo_obj, + (mp_obj_t)&synthio_miditrack_set_tempo_obj); + //| error_location: Optional[int] //| """Offset, in bytes within the midi data, of a decoding error""" //| @@ -141,6 +162,7 @@ static const mp_rom_map_elem_t synthio_miditrack_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_error_location), MP_ROM_PTR(&synthio_miditrack_error_location_obj) }, + { MP_ROM_QSTR(MP_QSTR_tempo), MP_ROM_PTR(&synthio_miditrack_tempo_obj) }, AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(synthio_miditrack_locals_dict, synthio_miditrack_locals_dict_table); diff --git a/shared-bindings/synthio/MidiTrack.h b/shared-bindings/synthio/MidiTrack.h index 72b217e9613b1..cb154d3996b1a 100644 --- a/shared-bindings/synthio/MidiTrack.h +++ b/shared-bindings/synthio/MidiTrack.h @@ -15,3 +15,6 @@ void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self, const void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self); mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t *self); + +mp_int_t common_hal_synthio_miditrack_get_tempo(synthio_miditrack_obj_t *self); +void common_hal_synthio_miditrack_set_tempo(synthio_miditrack_obj_t *self, mp_int_t value); diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 504cd07d90111..8a591da368858 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -83,6 +83,16 @@ static mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, s } //| class struct_time: +//| tm_year: int +//| tm_mon: int +//| tm_mday: int +//| tm_hour: int +//| tm_min: int +//| tm_sec: int +//| tm_wday: int +//| tm_yday: int +//| tm_isdst: int +//| //| def __init__(self, time_tuple: Sequence[int]) -> None: //| """Structure used to capture a date and time. Can be constructed from a `struct_time`, `tuple`, `list`, or `namedtuple` with 9 elements. //| @@ -210,7 +220,7 @@ static mp_obj_t time_monotonic_ns(void) { } MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns); -//| def localtime(secs: int) -> struct_time: +//| def localtime(secs: Optional[int] = None) -> struct_time: //| """Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in //| local time. If secs is not provided or None, the current time as returned //| by time() is used. diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c index 7c9c354e4de10..a4a0e8680e531 100644 --- a/shared-bindings/usb_hid/Device.c +++ b/shared-bindings/usb_hid/Device.c @@ -98,7 +98,7 @@ static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args const uint16_t usage_page = usage_page_arg; const mp_int_t usage_arg = args[ARG_usage].u_int; - mp_arg_validate_int_range(usage_arg, 1, 0xFFFF, MP_QSTR_usage); + mp_arg_validate_int_range(usage_arg, 0, 0xFFFF, MP_QSTR_usage); const uint16_t usage = usage_arg; mp_obj_t report_ids = args[ARG_report_ids].u_obj; diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index a267dea11c1ff..9a7d445fd0473 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -99,7 +99,7 @@ MP_PROPERTY_GETSET(wifi_radio_enabled_obj, (mp_obj_t)&wifi_radio_get_enabled_obj, (mp_obj_t)&wifi_radio_set_enabled_obj); -//| hostname: Union[str | ReadableBuffer] +//| hostname: Union[str, ReadableBuffer] //| """Hostname for wifi interface. When the hostname is altered after interface started/connected //| the changes would only be reflected once the interface restarts/reconnects.""" static mp_obj_t wifi_radio_get_hostname(mp_obj_t self_in) { @@ -325,8 +325,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_station_obj, wifi_radio_stop_station); //| def start_ap( //| self, -//| ssid: Union[str | ReadableBuffer], -//| password: Union[str | ReadableBuffer] = b"", +//| ssid: Union[str, ReadableBuffer], +//| password: Union[str, ReadableBuffer] = b"", //| *, //| channel: int = 1, //| authmode: Iterable[AuthMode] = (), @@ -438,11 +438,11 @@ MP_PROPERTY_GETTER(wifi_radio_ap_active_obj, //| def connect( //| self, -//| ssid: Union[str | ReadableBuffer], -//| password: Union[str | ReadableBuffer] = b"", +//| ssid: Union[str, ReadableBuffer], +//| password: Union[str, ReadableBuffer] = b"", //| *, //| channel: int = 0, -//| bssid: Optional[Union[str | ReadableBuffer]] = None, +//| bssid: Optional[Union[str, ReadableBuffer]] = None, //| timeout: Optional[float] = None, //| ) -> None: //| """Connects to the given ssid and waits for an ip address. Reconnections are handled diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index bf80403137996..2ee683d75e1cd 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -196,12 +196,12 @@ void audiosample_convert_s16s_u8s(uint8_t *buffer_out, const int16_t *buffer_in, } } -void audiosample_must_match(audiosample_base_t *self, mp_obj_t other_in) { +void audiosample_must_match(audiosample_base_t *self, mp_obj_t other_in, bool allow_mono_to_stereo) { const audiosample_base_t *other = audiosample_check(other_in); if (other->sample_rate != self->sample_rate) { mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate); } - if (other->channel_count != self->channel_count) { + if ((!allow_mono_to_stereo || (allow_mono_to_stereo && self->channel_count != 2)) && other->channel_count != self->channel_count) { mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count); } if (other->bits_per_sample != self->bits_per_sample) { diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 875ac90ecc5c1..920fe752c3822 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -89,7 +89,7 @@ static inline void audiosample_get_buffer_structure_checked(mp_obj_t self_in, bo audiosample_get_buffer_structure(audiosample_check(self_in), single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing); } -void audiosample_must_match(audiosample_base_t *self, mp_obj_t other); +void audiosample_must_match(audiosample_base_t *self, mp_obj_t other, bool allow_mono_to_stereo); void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes); void audiosample_convert_u8s_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes); diff --git a/shared-module/audiodelays/Chorus.c b/shared-module/audiodelays/Chorus.c index 1609cc5f94684..9262c6b4de195 100644 --- a/shared-module/audiodelays/Chorus.c +++ b/shared-module/audiodelays/Chorus.c @@ -166,7 +166,7 @@ bool common_hal_audiodelays_chorus_get_playing(audiodelays_chorus_obj_t *self) { } void common_hal_audiodelays_chorus_play(audiodelays_chorus_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiodelays/Echo.c b/shared-module/audiodelays/Echo.c index 78764d9099a1c..0ca5fc8a7502e 100644 --- a/shared-module/audiodelays/Echo.c +++ b/shared-module/audiodelays/Echo.c @@ -204,7 +204,7 @@ bool common_hal_audiodelays_echo_get_playing(audiodelays_echo_obj_t *self) { } void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiodelays/MultiTapDelay.c b/shared-module/audiodelays/MultiTapDelay.c index 7b702ecf1154a..9c33a5eaee750 100644 --- a/shared-module/audiodelays/MultiTapDelay.c +++ b/shared-module/audiodelays/MultiTapDelay.c @@ -285,7 +285,7 @@ bool common_hal_audiodelays_multi_tap_delay_get_playing(audiodelays_multi_tap_de } void common_hal_audiodelays_multi_tap_delay_play(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index ac349da0dd50a..3b8c1a07c7b16 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -143,7 +143,7 @@ bool common_hal_audiodelays_pitch_shift_get_playing(audiodelays_pitch_shift_obj_ } void common_hal_audiodelays_pitch_shift_play(audiodelays_pitch_shift_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiofilters/Distortion.c b/shared-module/audiofilters/Distortion.c index ec5fe084e56d3..c4b6b7566ad0d 100644 --- a/shared-module/audiofilters/Distortion.c +++ b/shared-module/audiofilters/Distortion.c @@ -141,7 +141,7 @@ bool common_hal_audiofilters_distortion_get_playing(audiofilters_distortion_obj_ } void common_hal_audiofilters_distortion_play(audiofilters_distortion_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c index 19b567532eb8e..4cedc810abad6 100644 --- a/shared-module/audiofilters/Filter.c +++ b/shared-module/audiofilters/Filter.c @@ -143,7 +143,7 @@ bool common_hal_audiofilters_filter_get_playing(audiofilters_filter_obj_t *self) } void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiofilters/Phaser.c b/shared-module/audiofilters/Phaser.c index 81d9c0bea3083..01b938c3a0027 100644 --- a/shared-module/audiofilters/Phaser.c +++ b/shared-module/audiofilters/Phaser.c @@ -130,7 +130,7 @@ bool common_hal_audiofilters_phaser_get_playing(audiofilters_phaser_obj_t *self) } void common_hal_audiofilters_phaser_play(audiofilters_phaser_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiofreeverb/Freeverb.c b/shared-module/audiofreeverb/Freeverb.c index d910536013604..28779bdcc84b2 100644 --- a/shared-module/audiofreeverb/Freeverb.c +++ b/shared-module/audiofreeverb/Freeverb.c @@ -195,7 +195,7 @@ bool common_hal_audiofreeverb_freeverb_get_playing(audiofreeverb_freeverb_obj_t } void common_hal_audiofreeverb_freeverb_play(audiofreeverb_freeverb_obj_t *self, mp_obj_t sample, bool loop) { - audiosample_must_match(&self->base, sample); + audiosample_must_match(&self->base, sample, false); self->sample = sample; self->loop = loop; diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 2c727a5c0cdde..b27eafb71a98c 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -92,22 +92,23 @@ static inline uint32_t add16signed(uint32_t a, uint32_t b) { } __attribute__((always_inline)) -static inline uint32_t mult16signed(uint32_t val, int32_t mul) { +static inline uint32_t mult16signed(uint32_t val, int32_t mul[2]) { #if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) - mul <<= 16; + mul[0] <<= 16; + mul[1] <<= 16; int32_t hi, lo; enum { bits = 16 }; // saturate to 16 bits enum { shift = 15 }; // shift is done automatically - asm volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul), "r" (val)); - asm volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul), "r" (val)); + asm volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul[0]), "r" (val)); + asm volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul[1]), "r" (val)); asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); asm volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack return val; #else uint32_t result = 0; - float mod_mul = (float)mul / (float)((1 << 15) - 1); for (int8_t i = 0; i < 2; i++) { + float mod_mul = (float)mul[i] / (float)((1 << 15) - 1); int16_t ai = (val >> (sizeof(uint16_t) * 8 * i)); int32_t intermediate = (int32_t)(ai * mod_mul); if (intermediate > SHRT_MAX) { @@ -154,9 +155,32 @@ static inline uint32_t pack8(uint32_t val) { return ((val & 0xff000000) >> 16) | ((val & 0xff00) >> 8); } +static inline uint32_t copy16lsb(uint32_t val) { + val &= 0x0000ffff; + return val | (val << 16); +} + +static inline uint32_t copy16msb(uint32_t val) { + val &= 0xffff0000; + return val | (val >> 16); +} + +static inline uint32_t copy8lsb(uint32_t val) { + val &= 0x00ff; + return val | (val << 8); +} + +static inline uint32_t copy8msb(uint32_t val) { + val &= 0xff00; + return val | (val >> 8); +} + +#define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768) + static void mix_down_one_voice(audiomixer_mixer_obj_t *self, audiomixer_mixervoice_obj_t *voice, bool voices_active, uint32_t *word_buffer, uint32_t length) { + audiosample_base_t *sample = MP_OBJ_TO_PTR(voice->sample); while (length != 0) { if (voice->buffer_length == 0) { if (!voice->more_data) { @@ -179,75 +203,163 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, uint32_t *src = voice->remaining_buffer; #if CIRCUITPY_SYNTHIO - uint32_t n = MIN(MIN(voice->buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + uint32_t n; + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + n = MIN(MIN(voice->buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } else { + n = MIN(MIN(voice->buffer_length << 1, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } // Get the current level from the BlockInput. These may change at run time so you need to do bounds checking if required. shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); uint16_t level = (uint16_t)(synthio_block_slot_get_limited(&voice->level, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * (1 << 15)); + int16_t panning = synthio_block_slot_get_scaled(&voice->panning, -ALMOST_ONE, ALMOST_ONE); #else - uint32_t n = MIN(voice->buffer_length, length); + uint32_t n; + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + n = MIN(voice->buffer_length, length); + } else { + n = MIN(voice->buffer_length << 1, length); + } uint16_t level = voice->level; + int16_t panning = voice->panning; #endif + uint16_t left_panning_scaled = 32768, right_panning_scaled = 32768; + if (MP_LIKELY(self->base.channel_count == 2)) { + if (panning >= 0) { + right_panning_scaled = 32767 - panning; + } else { + left_panning_scaled = 32767 + panning; + } + } + + int32_t loudness[2] = { level, level }; + if (MP_LIKELY(self->base.channel_count == 2)) { + loudness[0] = (left_panning_scaled * loudness[0]) >> 15; + loudness[1] = (right_panning_scaled * loudness[1]) >> 15; + } + // First active voice gets copied over verbatim. if (!voices_active) { if (MP_LIKELY(self->base.bits_per_sample == 16)) { if (MP_LIKELY(self->base.samples_signed)) { - for (uint32_t i = 0; i < n; i++) { - uint32_t v = src[i]; - word_buffer[i] = mult16signed(v, level); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t v = src[i]; + word_buffer[i] = mult16signed(v, loudness); + } + } else { + for (uint32_t i = 0; i < n; i += 2) { + uint32_t v = src[i >> 1]; + word_buffer[i] = mult16signed(copy16lsb(v), loudness); + word_buffer[i + 1] = mult16signed(copy16msb(v), loudness); + } } } else { - for (uint32_t i = 0; i < n; i++) { - uint32_t v = src[i]; - v = tosigned16(v); - word_buffer[i] = mult16signed(v, level); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t v = src[i]; + v = tosigned16(v); + word_buffer[i] = mult16signed(v, loudness); + } + } else { + for (uint32_t i = 0; i + 1 < n; i += 2) { + uint32_t v = src[i >> 1]; + v = tosigned16(v); + word_buffer[i] = mult16signed(copy16lsb(v), loudness); + word_buffer[i + 1] = mult16signed(copy16msb(v), loudness); + } } } } else { uint16_t *hword_buffer = (uint16_t *)word_buffer; uint16_t *hsrc = (uint16_t *)src; - for (uint32_t i = 0; i < n * 2; i++) { - uint32_t word = unpack8(hsrc[i]); - if (MP_LIKELY(!self->base.samples_signed)) { - word = tosigned16(word); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n * 2; i++) { + uint32_t word = unpack8(hsrc[i]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + word = mult16signed(word, loudness); + hword_buffer[i] = pack8(word); + } + } else { + for (uint32_t i = 0; i + 1 < n * 2; i += 2) { + uint32_t word = unpack8(hsrc[i >> 1]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + hword_buffer[i] = pack8(mult16signed(copy16lsb(word), loudness)); + hword_buffer[i + 1] = pack8(mult16signed(copy16msb(word), loudness)); } - word = mult16signed(word, level); - hword_buffer[i] = pack8(word); } } } else { if (MP_LIKELY(self->base.bits_per_sample == 16)) { if (MP_LIKELY(self->base.samples_signed)) { - for (uint32_t i = 0; i < n; i++) { - uint32_t word = src[i]; - word_buffer[i] = add16signed(mult16signed(word, level), word_buffer[i]); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t word = src[i]; + word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]); + } + } else { + for (uint32_t i = 0; i + 1 < n; i += 2) { + uint32_t word = src[i >> 1]; + word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]); + word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]); + } } } else { - for (uint32_t i = 0; i < n; i++) { - uint32_t word = src[i]; - word = tosigned16(word); - word_buffer[i] = add16signed(mult16signed(word, level), word_buffer[i]); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t word = src[i]; + word = tosigned16(word); + word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]); + } + } else { + for (uint32_t i = 0; i + 1 < n; i += 2) { + uint32_t word = src[i >> 1]; + word = tosigned16(word); + word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]); + word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]); + } } } } else { uint16_t *hword_buffer = (uint16_t *)word_buffer; uint16_t *hsrc = (uint16_t *)src; - for (uint32_t i = 0; i < n * 2; i++) { - uint32_t word = unpack8(hsrc[i]); - if (MP_LIKELY(!self->base.samples_signed)) { - word = tosigned16(word); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n * 2; i++) { + uint32_t word = unpack8(hsrc[i]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + word = mult16signed(word, loudness); + word = add16signed(word, unpack8(hword_buffer[i])); + hword_buffer[i] = pack8(word); + } + } else { + for (uint32_t i = 0; i + 1 < n * 2; i += 2) { + uint32_t word = unpack8(hsrc[i >> 1]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + hword_buffer[i] = pack8(add16signed(mult16signed(copy16lsb(word), loudness), unpack8(hword_buffer[i]))); + hword_buffer[i + 1] = pack8(add16signed(mult16signed(copy16msb(word), loudness), unpack8(hword_buffer[i + 1]))); } - word = mult16signed(word, level); - word = add16signed(word, unpack8(hword_buffer[i])); - hword_buffer[i] = pack8(word); } } } length -= n; word_buffer += n; - voice->remaining_buffer += n; - voice->buffer_length -= n; + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + voice->remaining_buffer += n; + voice->buffer_length -= n; + } else { + voice->remaining_buffer += n >> 1; + voice->buffer_length -= n >> 1; + } } if (length && !voices_active) { diff --git a/shared-module/audiomixer/MixerVoice.c b/shared-module/audiomixer/MixerVoice.c index e0be869aa8e44..6c23a39215cbc 100644 --- a/shared-module/audiomixer/MixerVoice.c +++ b/shared-module/audiomixer/MixerVoice.c @@ -16,6 +16,7 @@ void common_hal_audiomixer_mixervoice_construct(audiomixer_mixervoice_obj_t *self) { self->sample = NULL; common_hal_audiomixer_mixervoice_set_level(self, mp_obj_new_float(1.0)); + common_hal_audiomixer_mixervoice_set_panning(self, mp_obj_new_float(0.0)); } void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t *self, audiomixer_mixer_obj_t *parent) { @@ -38,6 +39,22 @@ void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t *sel #endif } +mp_obj_t common_hal_audiomixer_mixervoice_get_panning(audiomixer_mixervoice_obj_t *self) { + #if CIRCUITPY_SYNTHIO + return self->panning.obj; + #else + return mp_obj_new_float((mp_float_t)self->panning / ((1 << 15) - 1)); + #endif +} + +void common_hal_audiomixer_mixervoice_set_panning(audiomixer_mixervoice_obj_t *self, mp_obj_t arg) { + #if CIRCUITPY_SYNTHIO + synthio_block_assign_slot(arg, &self->panning, MP_QSTR_panning); + #else + self->panning = (uint16_t)(mp_arg_validate_obj_float_range(arg, -1, 1, MP_QSTR_panning) * ((1 << 15) - 1)); + #endif +} + bool common_hal_audiomixer_mixervoice_get_loop(audiomixer_mixervoice_obj_t *self) { return self->loop; } @@ -47,7 +64,7 @@ void common_hal_audiomixer_mixervoice_set_loop(audiomixer_mixervoice_obj_t *self } void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp_obj_t sample_in, bool loop) { - audiosample_must_match(&self->parent->base, sample_in); + audiosample_must_match(&self->parent->base, sample_in, true); // cast is safe, checked by must_match audiosample_base_t *sample = MP_OBJ_TO_PTR(sample_in); self->sample = sample; diff --git a/shared-module/audiomixer/MixerVoice.h b/shared-module/audiomixer/MixerVoice.h index dd9095515459a..75e7d47faa33d 100644 --- a/shared-module/audiomixer/MixerVoice.h +++ b/shared-module/audiomixer/MixerVoice.h @@ -23,7 +23,9 @@ typedef struct { uint32_t buffer_length; #if CIRCUITPY_SYNTHIO synthio_block_slot_t level; + synthio_block_slot_t panning; #else uint16_t level; + int16_t panning; #endif } audiomixer_mixervoice_obj_t; diff --git a/shared-module/epaperdisplay/EPaperDisplay.c b/shared-module/epaperdisplay/EPaperDisplay.c index e1f0a07f467ee..556db6ae22002 100644 --- a/shared-module/epaperdisplay/EPaperDisplay.c +++ b/shared-module/epaperdisplay/EPaperDisplay.c @@ -26,82 +26,73 @@ #define DELAY 0x80 void common_hal_epaperdisplay_epaperdisplay_construct(epaperdisplay_epaperdisplay_obj_t *self, - mp_obj_t bus, const uint8_t *start_sequence, uint16_t start_sequence_len, mp_float_t start_up_time, - const uint8_t *stop_sequence, uint16_t stop_sequence_len, - uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, - int16_t colstart, int16_t rowstart, uint16_t rotation, - uint16_t set_column_window_command, uint16_t set_row_window_command, - uint16_t set_current_column_command, uint16_t set_current_row_command, - uint16_t write_black_ram_command, bool black_bits_inverted, - uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint32_t highlight_color2, - const uint8_t *refresh_sequence, uint16_t refresh_sequence_len, mp_float_t refresh_time, - const mcu_pin_obj_t *busy_pin, bool busy_state, mp_float_t seconds_per_frame, - bool chip_select, bool grayscale, bool acep, bool spectra6, bool two_byte_sequence_length, bool address_little_endian) { + const epaperdisplay_construct_args_t *args) { uint16_t color_depth = 1; bool core_grayscale = true; - if (highlight_color != 0x000000) { + if (args->highlight_color != 0x000000) { self->core.colorspace.tricolor = true; - self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(highlight_color); + self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(args->highlight_color); } else { self->core.colorspace.tricolor = false; } - if (highlight_color != 0x000000 && highlight_color2 != 0x000000) { + if (args->highlight_color != 0x000000 && args->highlight_color2 != 0x000000) { self->core.colorspace.tricolor = false; self->core.colorspace.fourcolor = true; - self->core.colorspace.fourcolor_hue = displayio_colorconverter_compute_hue(highlight_color2); + self->core.colorspace.fourcolor_hue = displayio_colorconverter_compute_hue(args->highlight_color2); } else { self->core.colorspace.fourcolor = false; } - self->acep = acep || spectra6; - self->core.colorspace.sixcolor = spectra6; - self->core.colorspace.sevencolor = acep; + self->acep = args->acep || args->spectra6; + self->core.colorspace.sixcolor = args->spectra6; + self->core.colorspace.sevencolor = args->acep; + bool grayscale = args->grayscale; if (self->acep) { color_depth = 4; // bits. 7 colors + clean grayscale = false; core_grayscale = false; } - if ((highlight_color != 0x000000 || highlight_color2 != 0x000000) && write_color_ram_command == NO_COMMAND) { + if ((args->highlight_color != 0x000000 || args->highlight_color2 != 0x000000) && args->write_color_ram_command == NO_COMMAND) { color_depth = 2; core_grayscale = false; grayscale = false; } - displayio_display_core_construct(&self->core, width, height, rotation, color_depth, core_grayscale, true, 1, true, true); - displayio_display_bus_construct(&self->bus, bus, ram_width, ram_height, - colstart, rowstart, - set_column_window_command, set_row_window_command, set_current_column_command, set_current_row_command, - false /* data_as_commands */, chip_select, - false /* SH1107_addressing */, address_little_endian); + displayio_display_core_construct(&self->core, args->width, args->height, args->rotation, color_depth, core_grayscale, true, 1, true, true); + displayio_display_bus_construct(&self->bus, args->bus, args->ram_width, args->ram_height, + args->colstart, args->rowstart, + args->set_column_window_command, args->set_row_window_command, args->set_current_column_command, args->set_current_row_command, + false /* data_as_commands */, args->always_toggle_chip_select, + false /* SH1107_addressing */, args->address_little_endian); - self->write_black_ram_command = write_black_ram_command; - self->black_bits_inverted = black_bits_inverted; - self->write_color_ram_command = write_color_ram_command; - self->color_bits_inverted = color_bits_inverted; - self->refresh_time = refresh_time * 1000; - self->busy_state = busy_state; + self->write_black_ram_command = args->write_black_ram_command; + self->black_bits_inverted = args->black_bits_inverted; + self->write_color_ram_command = args->write_color_ram_command; + self->color_bits_inverted = args->color_bits_inverted; + self->refresh_time = args->refresh_time * 1000; + self->busy_state = args->busy_state; self->refreshing = false; - self->milliseconds_per_frame = seconds_per_frame * 1000; - self->chip_select = chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED; + self->milliseconds_per_frame = args->seconds_per_frame * 1000; + self->chip_select = args->always_toggle_chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED; self->grayscale = grayscale; - self->start_sequence = start_sequence; - self->start_sequence_len = start_sequence_len; - self->start_up_time_ms = start_up_time * 1000; - self->stop_sequence = stop_sequence; - self->stop_sequence_len = stop_sequence_len; - self->refresh_sequence = refresh_sequence; - self->refresh_sequence_len = refresh_sequence_len; + self->start_sequence = args->start_sequence; + self->start_sequence_len = args->start_sequence_len; + self->start_up_time_ms = args->start_up_time * 1000; + self->stop_sequence = args->stop_sequence; + self->stop_sequence_len = args->stop_sequence_len; + self->refresh_sequence = args->refresh_sequence; + self->refresh_sequence_len = args->refresh_sequence_len; self->busy.base.type = &mp_type_NoneType; - self->two_byte_sequence_length = two_byte_sequence_length; - if (busy_pin != NULL) { + self->two_byte_sequence_length = args->two_byte_sequence_length; + if (args->busy_pin != NULL) { self->busy.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&self->busy, busy_pin); - common_hal_never_reset_pin(busy_pin); + common_hal_digitalio_digitalinout_construct(&self->busy, args->busy_pin); + common_hal_never_reset_pin(args->busy_pin); } // Clear the color memory if it isn't in use. - if (highlight_color == 0x00 && highlight_color2 == 0x00 && write_color_ram_command != NO_COMMAND) { + if (args->highlight_color == 0x00 && args->highlight_color2 == 0x00 && args->write_color_ram_command != NO_COMMAND) { // TODO: Clear } diff --git a/shared-module/keypad/EventQueue.c b/shared-module/keypad/EventQueue.c index e5b362a045ddf..3130d8b59a1d7 100644 --- a/shared-module/keypad/EventQueue.c +++ b/shared-module/keypad/EventQueue.c @@ -15,9 +15,14 @@ #define EVENT_SIZE_BYTES (sizeof(uint16_t) + sizeof(mp_obj_t)) -void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events) { +void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events, bool use_gc_allocator) { // Event queue is 16-bit values. - ringbuf_alloc(&self->encoded_events, max_events * EVENT_SIZE_BYTES); + const size_t size = max_events * EVENT_SIZE_BYTES; + if (use_gc_allocator) { + ringbuf_alloc(&self->encoded_events, size); + } else { + ringbuf_init(&self->encoded_events, port_malloc(size, false), size); + } self->overflowed = false; self->event_handler = NULL; } diff --git a/shared-module/keypad/KeyMatrix.c b/shared-module/keypad/KeyMatrix.c index 67a5546853552..28830f591b129 100644 --- a/shared-module/keypad/KeyMatrix.c +++ b/shared-module/keypad/KeyMatrix.c @@ -56,7 +56,7 @@ void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint self->columns_to_anodes = columns_to_anodes; self->funcs = &keymatrix_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, true); } void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self) { diff --git a/shared-module/keypad/Keys.c b/shared-module/keypad/Keys.c index 39d50f95e3238..80dcf36e163ad 100644 --- a/shared-module/keypad/Keys.c +++ b/shared-module/keypad/Keys.c @@ -41,7 +41,7 @@ void common_hal_keypad_keys_construct(keypad_keys_obj_t *self, mp_uint_t num_pin self->value_when_pressed = value_when_pressed; self->funcs = &keys_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, true); } diff --git a/shared-module/keypad/ShiftRegisterKeys.c b/shared-module/keypad/ShiftRegisterKeys.c index 97917434ff81b..aa0c14dd36b50 100644 --- a/shared-module/keypad/ShiftRegisterKeys.c +++ b/shared-module/keypad/ShiftRegisterKeys.c @@ -71,7 +71,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ self->value_when_pressed = value_when_pressed; self->funcs = &shiftregisterkeys_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, true); } void common_hal_keypad_shiftregisterkeys_deinit(keypad_shiftregisterkeys_obj_t *self) { diff --git a/shared-module/keypad/__init__.c b/shared-module/keypad/__init__.c index 3ffa0433174cf..f1d5d395df789 100644 --- a/shared-module/keypad/__init__.c +++ b/shared-module/keypad/__init__.c @@ -85,14 +85,20 @@ void keypad_deregister_scanner(keypad_scanner_obj_t *scanner) { supervisor_release_lock(&keypad_scanners_linked_list_lock); } -void keypad_construct_common(keypad_scanner_obj_t *self, mp_float_t interval, size_t max_events, uint8_t debounce_threshold) { +void keypad_construct_common(keypad_scanner_obj_t *self, mp_float_t interval, size_t max_events, uint8_t debounce_threshold, bool use_gc_allocator) { size_t key_count = common_hal_keypad_generic_get_key_count(self); - self->debounce_counter = (int8_t *)m_malloc_without_collect(sizeof(int8_t) * key_count); + self->debounce_counter = + use_gc_allocator + ? (int8_t *)m_malloc_without_collect(sizeof(int8_t) * key_count) + : (int8_t *)port_malloc_zero(sizeof(int8_t) * key_count, false); self->interval_ticks = (mp_uint_t)(interval * 1024); // interval * 1000 * (1024/1000) - keypad_eventqueue_obj_t *events = mp_obj_malloc(keypad_eventqueue_obj_t, &keypad_eventqueue_type); - common_hal_keypad_eventqueue_construct(events, max_events); + keypad_eventqueue_obj_t *events = + use_gc_allocator + ? mp_obj_malloc(keypad_eventqueue_obj_t, &keypad_eventqueue_type) + : mp_obj_port_malloc(keypad_eventqueue_obj_t, &keypad_eventqueue_type); + common_hal_keypad_eventqueue_construct(events, max_events, use_gc_allocator); self->events = events; self->debounce_threshold = debounce_threshold; diff --git a/shared-module/keypad/__init__.h b/shared-module/keypad/__init__.h index a7d21753f6625..66fea4878543b 100644 --- a/shared-module/keypad/__init__.h +++ b/shared-module/keypad/__init__.h @@ -39,7 +39,7 @@ void keypad_reset(void); void keypad_register_scanner(keypad_scanner_obj_t *scanner); void keypad_deregister_scanner(keypad_scanner_obj_t *scanner); -void keypad_construct_common(keypad_scanner_obj_t *scanner, mp_float_t interval, size_t max_events, uint8_t debounce_cycles); +void keypad_construct_common(keypad_scanner_obj_t *scanner, mp_float_t interval, size_t max_events, uint8_t debounce_cycles, bool use_gc_allocator); bool keypad_debounce(keypad_scanner_obj_t *self, mp_uint_t key_number, bool current); void keypad_never_reset(keypad_scanner_obj_t *self); diff --git a/shared-module/keypad_demux/DemuxKeyMatrix.c b/shared-module/keypad_demux/DemuxKeyMatrix.c index b90669d772fcd..329f7679d3f76 100644 --- a/shared-module/keypad_demux/DemuxKeyMatrix.c +++ b/shared-module/keypad_demux/DemuxKeyMatrix.c @@ -31,38 +31,45 @@ static mp_uint_t row_column_to_key_number(keypad_demux_demuxkeymatrix_obj_t *sel return row * common_hal_keypad_demux_demuxkeymatrix_get_column_count(self) + column; } -void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], bool columns_to_anodes, bool transpose, mp_float_t interval, size_t max_events, uint8_t debounce_threshold) { - +void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], bool columns_to_anodes, bool transpose, mp_float_t interval, size_t max_events, uint8_t debounce_threshold, bool use_gc_allocator) { // the multiplexed pins are outputs so we can set the address for the target row // the sense of the address pins themselves doesn't change with columns_to_anodes // but the value output on the selected row line will be !columns_to_anodes mp_obj_t row_addr_dios[num_row_addr_pins]; for (size_t row = 0; row < num_row_addr_pins; row++) { digitalio_digitalinout_obj_t *dio = - mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); + use_gc_allocator + ? mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type) + : mp_obj_port_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(dio, row_addr_pins[row]); common_hal_digitalio_digitalinout_switch_to_output(dio, false, DRIVE_MODE_PUSH_PULL); row_addr_dios[row] = dio; } - self->row_addr_digitalinouts = mp_obj_new_tuple(num_row_addr_pins, row_addr_dios); + self->row_addr_digitalinouts = + use_gc_allocator + ? mp_obj_new_tuple(num_row_addr_pins, row_addr_dios) + : mp_obj_new_port_tuple(num_row_addr_pins, row_addr_dios); // the column pins are always inputs, with default state based on columns_to_anodes mp_obj_t column_dios[num_column_pins]; for (size_t column = 0; column < num_column_pins; column++) { digitalio_digitalinout_obj_t *dio = - mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); - dio->base.type = &digitalio_digitalinout_type; + use_gc_allocator + ? mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type) + : mp_obj_port_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(dio, column_pins[column]); common_hal_digitalio_digitalinout_switch_to_input(dio, columns_to_anodes ? PULL_UP : PULL_DOWN); column_dios[column] = dio; } - self->column_digitalinouts = mp_obj_new_tuple(num_column_pins, column_dios); - + self->column_digitalinouts = + use_gc_allocator + ? mp_obj_new_tuple(num_column_pins, column_dios) + : mp_obj_new_port_tuple(num_column_pins, column_dios); self->columns_to_anodes = columns_to_anodes; self->transpose = transpose; self->funcs = &keymatrix_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, use_gc_allocator); } void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_obj_t *self) { diff --git a/shared-module/lvfontio/OnDiskFont.c b/shared-module/lvfontio/OnDiskFont.c index 0cf65301d2270..368bd381475b1 100644 --- a/shared-module/lvfontio/OnDiskFont.c +++ b/shared-module/lvfontio/OnDiskFont.c @@ -253,9 +253,10 @@ static bool load_font_header(lvfontio_ondiskfont_t *self, FIL *file, size_t *max *max_slots = advance_count[1] * 2 + advance_count[0]; } } + } else { + *max_slots = advance_count[0] + advance_count[1]; } - found_glyf = true; } diff --git a/shared-module/max3421e/Max3421E.c b/shared-module/max3421e/Max3421E.c index 4946e4e7d8dfa..3448cdd4c7596 100644 --- a/shared-module/max3421e/Max3421E.c +++ b/shared-module/max3421e/Max3421E.c @@ -83,7 +83,7 @@ void common_hal_max3421e_max3421e_deinit(max3421e_max3421e_obj_t *self) { // anyway. Don't run background tasks because this function is used by // tuh_task() which is run as a background task. #if CFG_TUSB_OS == OPT_OS_NONE -void osal_task_delay(uint32_t msec) { +void tusb_time_delay_ms_api(uint32_t msec) { uint32_t end_time = common_hal_time_monotonic_ms() + msec; while (common_hal_time_monotonic_ms() < end_time) { if (tuh_callback.prev != NULL) { diff --git a/shared-module/sdcardio/__init__.c b/shared-module/sdcardio/__init__.c index a49a1506712db..29c890c6870c1 100644 --- a/shared-module/sdcardio/__init__.c +++ b/shared-module/sdcardio/__init__.c @@ -123,5 +123,5 @@ void automount_sd_card(void) { sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); MP_STATE_VM(vfs_mount_table) = sdcard_vfs; _mounted = true; - #endif + #endif // DEFAULT_SD_CARD_DETECT } diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 9a2c8271222e0..dedcee1ff23f5 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -126,6 +126,11 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool rea // call the underlying object to do any mounting operation mp_vfs_proxy_call(vfs, MP_QSTR_mount, 2, (mp_obj_t *)&args); + fs_user_mount_t *vfs_fat = MP_OBJ_TO_PTR(vfs_obj); + // Filesystem is read-only to USB if writable by CircuitPython, and vice versa. + filesystem_set_writable_by_usb(vfs_fat, readonly); + filesystem_set_concurrent_write_protection(vfs_fat, true); + // Insert the vfs into the mount table by pushing it onto the front of the // mount table. mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); diff --git a/shared-module/synthio/MidiTrack.c b/shared-module/synthio/MidiTrack.c index 94430289bda10..1cccd440fad9e 100644 --- a/shared-module/synthio/MidiTrack.c +++ b/shared-module/synthio/MidiTrack.c @@ -116,6 +116,16 @@ mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t return self->error_location; } +mp_int_t common_hal_synthio_miditrack_get_tempo(synthio_miditrack_obj_t *self) { + return self->tempo; +} + +void common_hal_synthio_miditrack_set_tempo(synthio_miditrack_obj_t *self, mp_int_t value) { + mp_int_t val = mp_arg_validate_int_min(value, 1, MP_QSTR_tempo); + self->synth.span.dur = (uint32_t)self->synth.span.dur * self->tempo / val; + self->tempo = val; +} + void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self, bool single_channel_output, uint8_t channel) { synthio_synth_reset_buffer(&self->synth, single_channel_output, channel); diff --git a/shared-module/usb/core/Device.c b/shared-module/usb/core/Device.c index c9df0cf73805f..83def37de914e 100644 --- a/shared-module/usb/core/Device.c +++ b/shared-module/usb/core/Device.c @@ -1,12 +1,15 @@ // This file is part of the CircuitPython project: https://circuitpython.org // // SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2025 Sam Blenny // // SPDX-License-Identifier: MIT #include "shared-bindings/usb/core/Device.h" #include "tusb_config.h" +#include "supervisor/port.h" +#include "supervisor/port_heap.h" #include "lib/tinyusb/src/host/hcd.h" #include "lib/tinyusb/src/host/usbh.h" @@ -32,6 +35,28 @@ void tuh_umount_cb(uint8_t dev_addr) { static xfer_result_t _xfer_result; static size_t _actual_len; + +#if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE +// Helper to ensure buffer is DMA-capable for transfer operations +static uint8_t *_ensure_dma_buffer(usb_core_device_obj_t *self, const uint8_t *buffer, size_t len, bool for_write) { + if (port_buffer_is_dma_capable(buffer)) { + return (uint8_t *)buffer; // Already DMA-capable, use directly + } + + uint8_t *dma_buffer = port_malloc(len, true); // true = DMA capable + if (dma_buffer == NULL) { + return NULL; // Allocation failed + } + + // Copy data to DMA buffer if writing + if (for_write && buffer != NULL) { + memcpy(dma_buffer, buffer, len); + } + + return dma_buffer; +} + +#endif bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t device_address) { if (!tuh_inited()) { mp_raise_RuntimeError(MP_ERROR_TEXT("No usb host port initialized")); @@ -45,7 +70,7 @@ bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t d } self->device_address = device_address; self->first_langid = 0; - _xfer_result = 0xff; + _xfer_result = XFER_RESULT_INVALID; return true; } @@ -70,14 +95,18 @@ void common_hal_usb_core_device_deinit(usb_core_device_obj_t *self) { uint16_t common_hal_usb_core_device_get_idVendor(usb_core_device_obj_t *self) { uint16_t vid; uint16_t pid; - tuh_vid_pid_get(self->device_address, &vid, &pid); + if (!tuh_vid_pid_get(self->device_address, &vid, &pid)) { + mp_raise_usb_core_USBError(NULL); + } return vid; } uint16_t common_hal_usb_core_device_get_idProduct(usb_core_device_obj_t *self) { uint16_t vid; uint16_t pid; - tuh_vid_pid_get(self->device_address, &vid, &pid); + if (!tuh_vid_pid_get(self->device_address, &vid, &pid)) { + mp_raise_usb_core_USBError(NULL); + } return pid; } @@ -91,14 +120,109 @@ static void _transfer_done_cb(tuh_xfer_t *xfer) { static bool _wait_for_callback(void) { while (!mp_hal_is_interrupted() && - _xfer_result == 0xff) { + _xfer_result == XFER_RESULT_INVALID) { + // The background tasks include TinyUSB which will call the function + // we provided above. In other words, the callback isn't in an interrupt. + RUN_BACKGROUND_TASKS; + } + if (mp_hal_is_interrupted()) { + // Handle case of VM being interrupted by Ctrl-C or autoreload + return false; + } + // Handle callback result code from TinyUSB + xfer_result_t result = _xfer_result; + _xfer_result = XFER_RESULT_INVALID; + switch (result) { + case XFER_RESULT_SUCCESS: + return true; + case XFER_RESULT_FAILED: + mp_raise_usb_core_USBError(NULL); + break; + case XFER_RESULT_STALLED: + mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); + break; + case XFER_RESULT_TIMEOUT: + case XFER_RESULT_INVALID: + mp_raise_usb_core_USBTimeoutError(); + break; + } + return false; +} + +static void _prepare_for_transfer(void) { + // Prepare for transfer. Unless there is a timeout, these static globals will + // get modified by the _transfer_done_cb() callback when tinyusb finishes the + // transfer or encounters an error condition. + _xfer_result = XFER_RESULT_INVALID; + _actual_len = 0; +} + +static void _abort_transfer(tuh_xfer_t *xfer) { + bool aborted = tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr); + if (aborted) { + // If the transfer was aborted, then we can continue. + return; + } + uint32_t start_time = supervisor_ticks_ms32(); + // If not, we need to wait for it to finish, otherwise we may free memory out from under it. + // Limit the wait time to 10 milliseconds to avoid blocking indefinitely. + while (_xfer_result == XFER_RESULT_INVALID && (supervisor_ticks_ms32() - start_time < 10)) { + // The background tasks include TinyUSB which will call the function + // we provided above. In other words, the callback isn't in an interrupt. + RUN_BACKGROUND_TASKS; + } +} + +// Only frees the transfer buffer on error. +static size_t _handle_timed_transfer_callback(tuh_xfer_t *xfer, mp_int_t timeout, bool our_buffer) { + if (xfer == NULL) { + mp_raise_usb_core_USBError(NULL); + return 0; + } + uint32_t start_time = supervisor_ticks_ms32(); + while ((timeout == 0 || supervisor_ticks_ms32() - start_time < (uint32_t)timeout) && + !mp_hal_is_interrupted() && + _xfer_result == XFER_RESULT_INVALID) { // The background tasks include TinyUSB which will call the function // we provided above. In other words, the callback isn't in an interrupt. RUN_BACKGROUND_TASKS; } + if (mp_hal_is_interrupted()) { + // Handle case of VM being interrupted by Ctrl-C or autoreload + _abort_transfer(xfer); + return 0; + } + // Handle transfer result code from TinyUSB xfer_result_t result = _xfer_result; - _xfer_result = 0xff; - return result == XFER_RESULT_SUCCESS; + _xfer_result = XFER_RESULT_INVALID; + if (our_buffer && result != XFER_RESULT_SUCCESS && result != XFER_RESULT_INVALID) { + port_free(xfer->buffer); + } + switch (result) { + case XFER_RESULT_SUCCESS: + return _actual_len; + case XFER_RESULT_FAILED: + mp_raise_usb_core_USBError(NULL); + break; + case XFER_RESULT_STALLED: + mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); + break; + case XFER_RESULT_TIMEOUT: + // This timeout comes from TinyUSB, so assume that it has stopped the + // transfer (note: timeout logic may be unimplemented on TinyUSB side) + mp_raise_usb_core_USBTimeoutError(); + break; + case XFER_RESULT_INVALID: + // This timeout comes from CircuitPython, not TinyUSB, so tell TinyUSB + // to stop the transfer and then wait to free the buffer. + _abort_transfer(xfer); + if (our_buffer) { + port_free(xfer->buffer); + } + mp_raise_usb_core_USBTimeoutError(); + break; + } + return 0; } static mp_obj_t _get_string(const uint16_t *temp_buf) { @@ -115,41 +239,75 @@ static void _get_langid(usb_core_device_obj_t *self) { } // Two control bytes and one uint16_t language code. uint16_t temp_buf[2]; - if (!tuh_descriptor_get_string(self->device_address, 0, 0, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { - return; + _prepare_for_transfer(); + if (!tuh_descriptor_get_string(self->device_address, 0, 0, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + self->first_langid = temp_buf[1]; } - self->first_langid = temp_buf[1]; } mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *self) { uint16_t temp_buf[127]; - _get_langid(self); - if (!tuh_descriptor_get_serial_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { + tusb_desc_device_t descriptor; + // First, be sure not to ask TinyUSB for a non-existent string (avoid error) + if (!tuh_descriptor_get_device_local(self->device_address, &descriptor)) { return mp_const_none; } - return _get_string(temp_buf); + if (descriptor.iSerialNumber == 0) { + return mp_const_none; + } + // Device does provide this string, so continue + _get_langid(self); + _prepare_for_transfer(); + if (!tuh_descriptor_get_serial_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + return _get_string(temp_buf); + } + return mp_const_none; } mp_obj_t common_hal_usb_core_device_get_product(usb_core_device_obj_t *self) { uint16_t temp_buf[127]; - _get_langid(self); - if (!tuh_descriptor_get_product_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { + tusb_desc_device_t descriptor; + // First, be sure not to ask TinyUSB for a non-existent string (avoid error) + if (!tuh_descriptor_get_device_local(self->device_address, &descriptor)) { + return mp_const_none; + } + if (descriptor.iProduct == 0) { return mp_const_none; } - return _get_string(temp_buf); + // Device does provide this string, so continue + _get_langid(self); + _prepare_for_transfer(); + if (!tuh_descriptor_get_product_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + return _get_string(temp_buf); + } + return mp_const_none; } mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self) { uint16_t temp_buf[127]; - _get_langid(self); - if (!tuh_descriptor_get_manufacturer_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { + tusb_desc_device_t descriptor; + // First, be sure not to ask TinyUSB for a non-existent string (avoid error) + if (!tuh_descriptor_get_device_local(self->device_address, &descriptor)) { + return mp_const_none; + } + if (descriptor.iManufacturer == 0) { return mp_const_none; } - return _get_string(temp_buf); + // Device does provide this string, so continue + _get_langid(self); + _prepare_for_transfer(); + if (!tuh_descriptor_get_manufacturer_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + return _get_string(temp_buf); + } + return mp_const_none; } @@ -224,39 +382,18 @@ void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, m _wait_for_callback(); } -static size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout) { - _xfer_result = 0xff; +// Raises an exception on failure. Returns the number of bytes transferred (maybe zero) on success. +static size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout, bool our_buffer) { + _prepare_for_transfer(); xfer->complete_cb = _transfer_done_cb; if (!tuh_edpt_xfer(xfer)) { + if (our_buffer) { + port_free(xfer->buffer); + } mp_raise_usb_core_USBError(NULL); return 0; } - uint32_t start_time = supervisor_ticks_ms32(); - while ((timeout == 0 || supervisor_ticks_ms32() - start_time < (uint32_t)timeout) && - !mp_hal_is_interrupted() && - _xfer_result == 0xff) { - // The background tasks include TinyUSB which will call the function - // we provided above. In other words, the callback isn't in an interrupt. - RUN_BACKGROUND_TASKS; - } - if (mp_hal_is_interrupted()) { - tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr); - return 0; - } - xfer_result_t result = _xfer_result; - _xfer_result = 0xff; - if (result == XFER_RESULT_STALLED) { - mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); - } - if (result == 0xff) { - tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr); - mp_raise_usb_core_USBTimeoutError(); - } - if (result == XFER_RESULT_SUCCESS) { - return _actual_len; - } - - return 0; + return _handle_timed_transfer_callback(xfer, timeout, our_buffer); } static bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) { @@ -313,12 +450,30 @@ mp_int_t common_hal_usb_core_device_write(usb_core_device_obj_t *self, mp_int_t mp_raise_usb_core_USBError(NULL); return 0; } + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Ensure buffer is in DMA-capable memory + uint8_t *dma_buffer = _ensure_dma_buffer(self, buffer, len, true); // true = for write + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + return 0; + } + #else + uint8_t *dma_buffer = (uint8_t *)buffer; // All memory is DMA-capable + #endif + tuh_xfer_t xfer; xfer.daddr = self->device_address; xfer.ep_addr = endpoint; - xfer.buffer = (uint8_t *)buffer; + xfer.buffer = dma_buffer; xfer.buflen = len; - return _xfer(&xfer, timeout); + size_t result = _xfer(&xfer, timeout, dma_buffer != buffer); + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + if (dma_buffer != buffer) { + port_free(dma_buffer); + } + #endif + return result; } mp_int_t common_hal_usb_core_device_read(usb_core_device_obj_t *self, mp_int_t endpoint, uint8_t *buffer, mp_int_t len, mp_int_t timeout) { @@ -326,12 +481,34 @@ mp_int_t common_hal_usb_core_device_read(usb_core_device_obj_t *self, mp_int_t e mp_raise_usb_core_USBError(NULL); return 0; } + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Ensure buffer is in DMA-capable memory + uint8_t *dma_buffer = _ensure_dma_buffer(self, buffer, len, false); // false = for read + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + return 0; + } + #else + uint8_t *dma_buffer = buffer; // All memory is DMA-capable + #endif + tuh_xfer_t xfer; xfer.daddr = self->device_address; xfer.ep_addr = endpoint; - xfer.buffer = buffer; + xfer.buffer = dma_buffer; xfer.buflen = len; - return _xfer(&xfer, timeout); + mp_int_t result = _xfer(&xfer, timeout, dma_buffer != buffer); + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Copy data back to original buffer if needed + if (dma_buffer != buffer) { + memcpy(buffer, dma_buffer, result); + port_free(dma_buffer); + } + #endif + + return result; } mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self, @@ -340,6 +517,23 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self, uint8_t *buffer, mp_int_t len, mp_int_t timeout) { // Timeout is in ms. + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Determine if this is a write (host-to-device) or read (device-to-host) transfer + bool is_write = (bmRequestType & 0x80) == 0; // Bit 7: 0=host-to-device, 1=device-to-host + + // Ensure buffer is in DMA-capable memory + uint8_t *dma_buffer = NULL; + if (len > 0 && buffer != NULL) { + dma_buffer = _ensure_dma_buffer(self, buffer, len, is_write); + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + return 0; + } + } + #else + uint8_t *dma_buffer = buffer; // All memory is DMA-capable + #endif + tusb_control_request_t request = { .bmRequestType = bmRequestType, .bRequest = bRequest, @@ -351,42 +545,28 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self, .daddr = self->device_address, .ep_addr = 0, .setup = &request, - .buffer = buffer, + .buffer = dma_buffer, .complete_cb = _transfer_done_cb, }; - _xfer_result = 0xff; - + _prepare_for_transfer(); if (!tuh_control_xfer(&xfer)) { mp_raise_usb_core_USBError(NULL); return 0; } - uint32_t start_time = supervisor_ticks_ms32(); - while ((timeout == 0 || supervisor_ticks_ms32() - start_time < (uint32_t)timeout) && - !mp_hal_is_interrupted() && - _xfer_result == 0xff) { - // The background tasks include TinyUSB which will call the function - // we provided above. In other words, the callback isn't in an interrupt. - RUN_BACKGROUND_TASKS; - } - if (mp_hal_is_interrupted()) { - tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr); - return 0; - } - xfer_result_t result = _xfer_result; - _xfer_result = 0xff; - if (result == XFER_RESULT_STALLED) { - mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); - } - if (result == 0xff) { - tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr); - mp_raise_usb_core_USBTimeoutError(); - } - if (result == XFER_RESULT_SUCCESS) { - return len; + mp_int_t result = (mp_int_t)_handle_timed_transfer_callback(&xfer, timeout, dma_buffer != buffer); + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + if (dma_buffer != buffer) { + // Copy data back to original buffer if this was a read transfer + if (buffer != NULL && !is_write) { + memcpy(buffer, dma_buffer, result); + } + port_free(dma_buffer); } + #endif - return 0; + return result; } bool common_hal_usb_core_device_is_kernel_driver_active(usb_core_device_obj_t *self, mp_int_t interface) { diff --git a/supervisor/filesystem.h b/supervisor/filesystem.h index a0445b0510da9..30cd83d443815 100644 --- a/supervisor/filesystem.h +++ b/supervisor/filesystem.h @@ -21,6 +21,7 @@ void filesystem_set_internal_writable_by_usb(bool usb_writable); void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection); void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable); void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection); +void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection); // Whether user code can modify the filesystem. It doesn't depend on the state // of USB. Don't use this for a workflow. In workflows, grab the shared file diff --git a/supervisor/port.h b/supervisor/port.h index cc49538218fac..0bf8fd8d01350 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -9,6 +9,7 @@ #include #include +#include "py/obj.h" #include "supervisor/shared/safe_mode.h" // Provided by the linker; @@ -107,3 +108,10 @@ void port_gc_collect(void); // this function to sense the button. Ports that need to can override this // function to provide their own implementation. bool port_boot_button_pressed(void); + +// Allocating objects on the port heap, not the VM heap. +#define mp_obj_port_malloc(struct_type, obj_type) ((struct_type *)mp_obj_port_malloc_helper(sizeof(struct_type), obj_type)) +#define mp_obj_port_malloc_var(struct_type, var_field, var_type, var_num, obj_type) ((struct_type *)mp_obj_port_malloc_helper(offsetof(struct_type, var_field) + sizeof(var_type) * (var_num), obj_type)) + +void *mp_obj_port_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); +mp_obj_t mp_obj_new_port_tuple(size_t n, const mp_obj_t *items); diff --git a/supervisor/port_heap.h b/supervisor/port_heap.h index 07a3c884e241e..3e6b5a660fa79 100644 --- a/supervisor/port_heap.h +++ b/supervisor/port_heap.h @@ -21,9 +21,16 @@ void port_heap_init(void); void *port_malloc(size_t size, bool dma_capable); +void *port_malloc_zero(size_t size, bool dma_capable); void port_free(void *ptr); void *port_realloc(void *ptr, size_t size, bool dma_capable); +#if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE +// Check if a buffer pointer is in DMA-capable memory. DMA-capable memory is also accessible during +// flash operations. +bool port_buffer_is_dma_capable(const void *ptr); +#endif + size_t port_heap_get_largest_free_size(void); diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index 0df600e77fd2f..025c9ddbd6de3 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -148,8 +148,7 @@ bool filesystem_init(bool create_allowed, bool force_create) { res = f_mkdir(&circuitpy->fatfs, "/sd"); #if CIRCUITPY_FULL_BUILD MAKE_FILE_WITH_OPTIONAL_CONTENTS(&circuitpy->fatfs, "/sd/placeholder.txt", - "SD cards mounted at /sd will hide this file from Python." - " SD cards are not visible via USB CIRCUITPY.\n"); + "SD cards mounted at /sd will hide this file from Python.\n"); #endif #endif @@ -248,13 +247,15 @@ void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) { } bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) { - return (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0 || - (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0; + return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0); } bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) { - return (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0 || - (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0; + return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0); } void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) { @@ -269,6 +270,14 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu } } +void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection) { + if (ignore_write_protection) { + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; + } else { + vfs->blockdev.flags &= ~MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; + } +} + bool filesystem_present(void) { return _circuitpy_vfs.len > 0; } diff --git a/supervisor/shared/port.c b/supervisor/shared/port.c index 3b9f0c8718161..aabf003fb302d 100644 --- a/supervisor/shared/port.c +++ b/supervisor/shared/port.c @@ -43,6 +43,15 @@ MP_WEAK void *port_malloc(size_t size, bool dma_capable) { return block; } +// Ensure allocated memory is zero. +MP_WEAK void *port_malloc_zero(size_t size, bool dma_capable) { + void *ptr = port_malloc(size, dma_capable); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + MP_WEAK void port_free(void *ptr) { tlsf_free(heap, ptr); } @@ -80,3 +89,30 @@ MP_WEAK bool port_boot_button_pressed(void) { return false; #endif } + +// Ports may provide an implementation of this function if it is needed +MP_WEAK void port_gc_collect(void) { +} + +// Allocates an object in the port heap, not the VM heap, and also sets type, for mp_obj_malloc{,_var} macros. +MP_NOINLINE void *mp_obj_port_malloc_helper(size_t num_bytes, const mp_obj_type_t *type) { + mp_obj_base_t *base = (mp_obj_base_t *)port_malloc_zero(num_bytes, false); + base->type = type; + return base; +} + +// Creates a tuple on the port heap, not the VM heap. +// Implementation copied from py/objtuple.c. +mp_obj_t mp_obj_new_port_tuple(size_t n, const mp_obj_t *items) { + if (n == 0) { + return mp_const_empty_tuple; + } + mp_obj_tuple_t *o = mp_obj_port_malloc_var(mp_obj_tuple_t, items, mp_obj_t, n, &mp_type_tuple); + o->len = n; + if (items) { + for (size_t i = 0; i < n; i++) { + o->items[i] = items[i]; + } + } + return MP_OBJ_FROM_PTR(o); +} diff --git a/supervisor/shared/usb/usb_device.c b/supervisor/shared/usb/usb_device.c index ec08b8bf4d7e2..16ae137eddefb 100644 --- a/supervisor/shared/usb/usb_device.c +++ b/supervisor/shared/usb/usb_device.c @@ -166,6 +166,9 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ * @param wanted_char The wanted char (set previously) */ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { + // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB on ESP. + // So, we must notify the other task when a CTRL-C is received. + port_wake_main_task(); // Workaround for using shared/runtime/interrupt_char.c // Compare mp_interrupt_char with wanted_char and ignore if not matched if (mp_interrupt_char == wanted_char) { @@ -177,7 +180,14 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { if (usb_cdc_console_enabled() && mp_interrupt_char != -1 && itf == 0 && duration_ms > 0) { mp_sched_keyboard_interrupt(); + port_wake_main_task(); } } +void tud_cdc_rx_cb(uint8_t itf) { + (void)itf; + // Workaround for "press any key to enter REPL" response being delayed on espressif. + // Wake main task when any key is pressed. + port_wake_main_task(); +} #endif diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index 0b02faa5c18cb..febede876bbf5 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -45,6 +45,11 @@ static bool ejected[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = true}; static bool eject_once[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; static bool locked[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; +// Set to true if a write was in a file data or metadata area, +// as opposed to in the filesystem metadata area (e.g., dirty bit). +// Used to determine if an auto-reload is warranted. +static bool content_write[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; + #include "tusb.h" static const uint8_t usb_msc_descriptor_template[] = { @@ -132,7 +137,7 @@ static fs_user_mount_t *get_vfs(int lun) { if (lun == SAVES_LUN) { const char *path_under_mount; fs_user_mount_t *saves = filesystem_for_path("/saves", &path_under_mount); - if (saves != root && (saves->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0 && gc_nbytes(saves) == 0) { + if (saves != root && (saves->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0 && !gc_ptr_on_heap(saves)) { return saves; } } @@ -141,6 +146,7 @@ static fs_user_mount_t *get_vfs(int lun) { if (lun == SDCARD_LUN) { const char *path_under_mount; fs_user_mount_t *sdcard = filesystem_for_path("/sd", &path_under_mount); + // If "/sd" is on the root filesystem, nothing has been mounted there. if (sdcard != root && (sdcard->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0) { return sdcard; } else { @@ -243,7 +249,7 @@ bool tud_msc_is_writable_cb(uint8_t lun) { if (vfs == NULL) { return false; } - if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL || !filesystem_is_writable_by_usb(vfs)) { + if (!filesystem_is_writable_by_usb(vfs)) { return false; } // Lock the blockdev once we say we're writable. @@ -290,16 +296,19 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * if (vfs == NULL) { return -1; } + disk_write(vfs, buffer, lba, block_count); // Since by getting here we assume the mount is read-only to - // MicroPython let's update the cached FatFs sector if it's the one + // CircuitPython let's update the cached FatFs sector if it's the one // we just wrote. + if #if FF_MAX_SS != FF_MIN_SS - if (vfs->fatfs.ssize == MSC_FLASH_BLOCK_SIZE) { + (vfs->fatfs.ssize == MSC_FLASH_BLOCK_SIZE) #else // The compiler can optimize this away. - if (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE) { - #endif + (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE) + #endif + { if (lba == vfs->fatfs.winsect && lba > 0) { memcpy(vfs->fatfs.win, buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), @@ -307,17 +316,30 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * } } + // A write to an lba below fatbase is in the filesystem metadata (BPB) area or the "Reserved Region", + // and is probably setting or clearing the dirty bit. This should not trigger auto-reload. + // All other writes will trigger auto-reload. + if (lba >= vfs->fatfs.fatbase) { + content_write[lun] = true; + } + return block_count * MSC_FLASH_BLOCK_SIZE; } // Callback invoked when WRITE10 command is completed (status received and accepted by host). // used to flush any pending cache. void tud_msc_write10_complete_cb(uint8_t lun) { - (void)lun; - - // This write is complete; initiate an autoreload. autoreload_resume(AUTORELOAD_SUSPEND_USB); - autoreload_trigger(); + + // This write is complete; initiate an autoreload if this was a file data or metadata write, + // not just a dirty-bit write. + if (content_write[lun] && + // Fast path: lun == 0 is CIRCUITPY, which can always trigger auto-reload if enabled. + // Don't autoreload if this lun was mounted by the user: that will cause a VM stop and an unmount. + (lun == 0 || !gc_ptr_on_heap(get_vfs(lun)))) { + autoreload_trigger(); + content_write[lun] = false; + } } // Invoked when received SCSI_CMD_INQUIRY @@ -337,7 +359,7 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { return false; } - #if CIRCUITPY_SDCARDIO + #if CIRCUITPY_SDCARD_USB if (lun == SDCARD_LUN) { automount_sd_card(); } diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 0ecc6ea3acfe6..21bda334131c7 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -1,6 +1,5 @@ SRC_SUPERVISOR = \ main.c \ - lib/tlsf/tlsf.c \ supervisor/port.c \ supervisor/shared/background_callback.c \ supervisor/shared/board.c \ @@ -20,6 +19,10 @@ SRC_SUPERVISOR = \ supervisor/shared/translate/translate.c \ supervisor/shared/workflow.c \ +ifeq ($(CIRCUITPY_LIB_TLSF),1) +SRC_SUPERVISOR += lib/tlsf/tlsf.c +endif + # For tlsf CFLAGS += -D_DEBUG=0 diff --git a/tests/circuitpython/deque_subclass.py b/tests/circuitpython/deque_subclass.py new file mode 100644 index 0000000000000..5708407a9b630 --- /dev/null +++ b/tests/circuitpython/deque_subclass.py @@ -0,0 +1,40 @@ +try: + from collections import deque +except ImportError: + print("SKIP") + raise SystemExit + + +class DequeSubclass(deque): + def __init__(self, values, maxlen): + super().__init__(values, maxlen) + + def pop(self): + print("pop") + return super().pop() + + def popleft(self): + print("popleft") + return super().popleft() + + def append(self, value): + print("append") + return super().append(value) + + def appendleft(self, value): + print("appendleft") + return super().appendleft(value) + + def extend(self, value): + print("extend") + return super().extend(value) + + +d = DequeSubclass([1, 2, 3], 10) +print(d.append(4)) +print(d.appendleft(0)) +print(d.pop()) +print(d.popleft()) +d.extend([6, 7]) +# calling list() tests iteration. +print(list(d)) diff --git a/tools/board_stubs/circuitpython_setboard/__init__.py b/tools/board_stubs/circuitpython_setboard/__init__.py index 3a73beb3119df..69a405405b800 100644 --- a/tools/board_stubs/circuitpython_setboard/__init__.py +++ b/tools/board_stubs/circuitpython_setboard/__init__.py @@ -12,7 +12,12 @@ import shutil from collections import defaultdict from importlib import resources -from importlib.abc import Traversable + +try: + from importlib.resources.abc import Traversable +except ModuleNotFoundError: + # 3.10 and earlier. + from importlib.abc import Traversable def get_definitions_or_exit(board: str) -> Traversable: diff --git a/tools/ci_check_duplicate_usb_vid_pid.py b/tools/ci_check_duplicate_usb_vid_pid.py index 5361914af199b..38cce0f28be94 100644 --- a/tools/ci_check_duplicate_usb_vid_pid.py +++ b/tools/ci_check_duplicate_usb_vid_pid.py @@ -104,7 +104,7 @@ def check_vid_pid(files, clusterlist): """ usb_pattern = re.compile( - r"^CIRCUITPY_USB_DEVICE\s*=\s*0$|^IDF_TARGET = (esp32|esp32c2|esp32c3|esp32c6|esp32h2|esp32p4)$|^MCU_SERIES = MG24$", + r"^CIRCUITPY_USB_DEVICE\s*=\s*0$|^IDF_TARGET = (esp32|esp32c2|esp32c3|esp32c5|esp32c6|esp32c61|esp32h2|esp32p4)$|^MCU_SERIES = MG24$", flags=re.M, )