Merge branch 'main' into fastpixelmap

# Conflicts:
#	shared-module/adafruit_pixelbuf/PixelBuf.c
This commit is contained in:
foamyguy 2022-11-21 20:25:58 -06:00
commit 19f1119994
107 changed files with 3234 additions and 353 deletions

View File

@ -125,20 +125,30 @@ jobs:
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static-raspbian s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-raspbian-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-amd64-linux-${{ env.CP_VERSION }} --no-progress --region us-east-1
[ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/mpy-cross.static.exe s3://adafruit-circuit-python/bin/mpy-cross/mpy-cross.static-x64-windows-${{ env.CP_VERSION }}.exe --no-progress --region us-east-1
- name: "Get changes"
- name: Get last commit with checks
id: get-last-commit-with-checks
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@v2
id: filter
working-directory: tools
env:
REPO: ${{ github.repository }}
PULL: ${{ github.event.number }}
GITHUB_TOKEN: ${{ github.token }}
EXCLUDE_COMMIT: ${{ github.event.after }}
run: python3 -u ci_changes_per_commit.py
- name: Get changes
id: get-changes
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@v34
with:
list-files: json
filters: |
changed:
- '**'
- name: "Set matrix"
json: true
sha: ${{ steps.get-last-commit-with-checks.outputs.commit && github.event.after }}
base_sha: ${{ steps.get-last-commit-with-checks.outputs.commit }}
- name: Set matrix
id: set-matrix
working-directory: tools
env:
CHANGED_FILES: ${{ steps.filter.outputs.changed_files }}
CHANGED_FILES: ${{ steps.get-changes.outputs.all_changed_and_modified_files }}
LAST_FAILED_JOBS: ${{ steps.get-last-commit-with-checks.outputs.checkruns }}
run: python3 -u ci_set_matrix.py

6
.gitmodules vendored
View File

@ -319,3 +319,9 @@
[submodule "lib/mbedtls"]
path = lib/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
[submodule "frozen/Adafruit_CircuitPython_UC8151D"]
path = frozen/Adafruit_CircuitPython_UC8151D
url = https://github.com/adafruit/Adafruit_CircuitPython_UC8151D
[submodule "frozen/Adafruit_CircuitPython_SSD1680"]
path = frozen/Adafruit_CircuitPython_SSD1680
url = https://github.com/adafruit/Adafruit_CircuitPython_SSD1680

@ -1 +1 @@
Subproject commit 57de23c1fb434ba99aaafe1d00bd77d5cdf5d66b
Subproject commit 25a825e41c26cfcee018b762416741d0d63aeabf

@ -1 +1 @@
Subproject commit 18eaddb96aa6599901ef2ff0e140e89a2de8c5d0
Subproject commit 5b4703428fc299ac268d08350c885122b2af1e75

@ -1 +1 @@
Subproject commit a5d56f3e4866c8dbb343e03500355a42c46e557a
Subproject commit 317f4bdb799afa59b164def4ea0610f57db9922e

@ -0,0 +1 @@
Subproject commit 168624262c18f5ee80ec392c0844d6a4c6548760

@ -0,0 +1 @@
Subproject commit 565fed515138f962c4bcce0ee756d32e708a151a

@ -1 +1 @@
Subproject commit d0a07e14adcd71a7c22bcceb16c55aadb5e0d104
Subproject commit cc93ff18c3a20b25396cb2babaee8ed33bb79528

View File

@ -3730,10 +3730,20 @@ msgid "offset out of bounds"
msgstr "modul tidak ditemukan"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3707,10 +3707,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3716,10 +3716,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -6,14 +6,14 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2022-11-04 15:05+0000\n"
"PO-Revision-Date: 2022-11-09 19:20+0000\n"
"Last-Translator: Ettore Atalan <atalanttore@googlemail.com>\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.14.2-dev\n"
"X-Generator: Weblate 4.15-dev\n"
#: main.c
msgid ""
@ -38,7 +38,7 @@ msgid ""
"https://github.com/adafruit/circuitpython/issues\n"
msgstr ""
"\n"
"Bitte melden Sie ein Problem mit dem Inhalt Ihres CIRCUITPY-Laufwerks unter\n"
"Bitte melde ein Problem mit dem Inhalt Ihres CIRCUITPY-Laufwerks unter\n"
"https://github.com/adafruit/circuitpython/issues\n"
#: py/obj.c
@ -555,8 +555,8 @@ msgid ""
"Auto-reload is on. Simply save files over USB to run them or enter REPL to "
"disable.\n"
msgstr ""
"Automatisches Neuladen ist aktiv. Speichere Dateien über USB um sie "
"auszuführen oder verbinde dich mit der REPL zum Deaktivieren.\n"
"Automatisches Neuladen ist aktiviert. Speichere Dateien einfach über USB, um "
"sie auszuführen, oder gib REPL ein, um sie zu deaktivieren.\n"
#: ports/espressif/common-hal/canio/CAN.c
msgid "Baudrate not supported by peripheral"
@ -820,8 +820,8 @@ msgid ""
"Connection has been disconnected and can no longer be used. Create a new "
"connection."
msgstr ""
"Die Verbindung wurde getrennt und kann nicht mehr verwendet werden. "
"Erstellen Sie eine neue Verbindung."
"Die Verbindung wurde getrennt und kann nicht mehr verwendet werden. Erstelle "
"eine neue Verbindung."
#: py/persistentcode.c
msgid "Corrupt .mpy file"
@ -857,7 +857,7 @@ msgstr "DAC-Kanal-Initialisierungsfehler"
#: ports/stm/common-hal/analogio/AnalogOut.c
msgid "DAC Device Init Error"
msgstr "DAC Device Initialisierungs-Fehler"
msgstr "DAC-Gerät-Initialisierungsfehler"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "DAC already in use"
@ -1082,7 +1082,7 @@ msgstr "Die Funktion erwartet, dass der 'lock'-Befehl zuvor ausgeführt wurde"
#: ports/cxd56/common-hal/gnss/GNSS.c
msgid "GNSS init"
msgstr "GNSS Initialisierung"
msgstr "GNSS-Initialisierung"
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
msgid "Generic Failure"
@ -1105,7 +1105,7 @@ msgstr "Hald-Duplex SPI is tnicht implementiert"
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/canio/CAN.c
#: ports/stm/common-hal/sdioio/SDCard.c
msgid "Hardware busy, try alternative pins"
msgstr "Hardware beschäftigt, versuchen Sie alternative Pins"
msgstr "Hardware beschäftigt, versuche alternative Pins"
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
msgid "Hardware in use, try alternative pins"
@ -1117,7 +1117,7 @@ msgstr "Lese/Schreibe-operation an geschlossener Datei"
#: ports/stm/common-hal/busio/I2C.c
msgid "I2C init error"
msgstr "I2C Initialisierungsfehler"
msgstr "I2C-Initialisierungsfehler"
#: ports/raspberrypi/common-hal/busio/I2C.c
#: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c
@ -1142,8 +1142,8 @@ msgid ""
"Incompatible .mpy file. Please update all .mpy files. See http://adafru.it/"
"mpy-update for more info."
msgstr ""
"Inkompatible mpy-Datei. Bitte aktualisieren Sie alle mpy-Dateien. Siehe "
"http://adafru.it/mpy-update für weitere Informationen."
"Inkompatible .mpy-Datei. Bitte aktualisiere alle .mpy-Dateien. Siehe http://"
"adafru.it/mpy-update für weitere Informationen."
#: shared-bindings/_pew/PewPew.c
msgid "Incorrect buffer size"
@ -1779,8 +1779,8 @@ msgid ""
"constructor"
msgstr ""
"Pinbelegung verwendet %d Bytes pro Element, was mehr als die idealen %d "
"Bytes verbraucht. Wenn dies nicht vermieden werden kann, übergeben Sie "
"allow_inefficient = True an den Konstruktor"
"Bytes verbraucht. Wenn dies nicht vermieden werden kann, übergib "
"allow_inefficient=True an den Konstruktor"
#: ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c
msgid "Pins must be sequential"
@ -1919,7 +1919,7 @@ msgstr "SD-Card CSD-Format nicht unterstützt"
#: ports/cxd56/common-hal/sdioio/SDCard.c
msgid "SDCard init"
msgstr "SDCard Initialisierung"
msgstr "SDCard-Initialisierung"
#: ports/stm/common-hal/sdioio/SDCard.c
#, c-format
@ -1937,7 +1937,7 @@ msgstr "SPI-Konfiguration fehlgeschlagen"
#: ports/stm/common-hal/busio/SPI.c
msgid "SPI init error"
msgstr "SPI Initialisierungsfehler"
msgstr "SPI-Initialisierungsfehler"
#: ports/raspberrypi/common-hal/busio/SPI.c
msgid "SPI peripheral in use"
@ -1954,7 +1954,7 @@ msgstr "Maßstabs-Abmeßungen müssen durch 3 teilbar sein"
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Scannen Sie bereits in Bearbeitung. Stoppen Sie mit stop_scan."
msgstr "Scannen bereits in Bearbeitung. Stoppe mit stop_scan."
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@ -1996,7 +1996,7 @@ msgstr "Quell- und Zielbuffer müssen gleich lang sein"
#: shared-bindings/paralleldisplay/ParallelBus.c
msgid "Specify exactly one of data0 or data_pins"
msgstr "Geben Sie genau einen von data0 oder data_pins an"
msgstr "Gib genau einen von data0 oder data_pins an"
#: extmod/modure.c
msgid "Splitting with sub-captures"
@ -2012,11 +2012,11 @@ msgstr "Stereo rechts muss sich auf PWM-Kanal B befinden"
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
msgid "Supply at least one UART pin"
msgstr "Geben Sie mindestens einen UART-Pin an"
msgstr "Gib mindestens einen UART-Pin an"
#: shared-bindings/alarm/time/TimeAlarm.c
msgid "Supply one of monotonic_time or epoch_time"
msgstr "Geben Sie entweder monotonic_time oder epoch_time an"
msgstr "Gib entweder monotonic_time oder epoch_time an"
#: shared-bindings/gnss/GNSS.c
msgid "System entry must be gnss.SatelliteSystem"
@ -2036,7 +2036,7 @@ msgid ""
"Increase the stack size if you know how. If not:"
msgstr ""
"Der Heap von CircuitPython wurde beschädigt, weil der Stack zu klein war.\n"
"Vergrößern Sie den Stack, wenn Sie wissen, wie. Wenn nicht:"
"Vergrößere den Stack, wenn du weißt, wie. Wenn nicht:"
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "The SW38 button was pressed at start up.\n"
@ -2052,7 +2052,7 @@ msgid ""
"exit safe mode."
msgstr ""
"Das Modul `microcontroller` wurde zum Booten in den abgesicherten Modus "
"verwendet. Drücken Sie Reset, um den abgesicherten Modus zu verlassen."
"verwendet. Drücke Reset, um den abgesicherten Modus zu verlassen."
#: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h
msgid "The central button was pressed at start up.\n"
@ -2072,10 +2072,9 @@ msgid ""
"enough power for the whole circuit and press reset (after ejecting "
"CIRCUITPY)."
msgstr ""
"Der Mikrocontroller hatte einen Stromausfall. Vergewissern Sie sich, dass "
"die\n"
"Stromversorgung genügend Strom für die gesamte Schaltung liefert und drücken "
"Sie Reset (nach dem Auswerfen von CIRCUITPY)."
"Der Mikrocontroller hatte einen Stromausfall. Vergewisser dich, dass die\n"
"Stromversorgung genügend Strom für die gesamte Schaltung liefert und\n"
"drücke Reset (nach dem Auswerfen von CIRCUITPY)."
#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
@ -2133,6 +2132,8 @@ msgstr ""
#: supervisor/shared/safe_mode.c
msgid "To exit, please reset the board without requesting safe mode."
msgstr ""
"Zum Beenden setze bitte das Board zurück, ohne den abgesicherten Modus "
"aufzurufen."
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Too many channels in sample"
@ -2176,11 +2177,11 @@ msgstr "UART wird de-initialisiert"
#: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c
#: ports/espressif/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
msgid "UART init"
msgstr "UART Initialisierung"
msgstr "UART-Initialisierung"
#: ports/stm/common-hal/busio/UART.c
msgid "UART re-init"
msgstr "UART wird wieder Initialisiert"
msgstr "UART wird erneut Initialisiert"
#: ports/stm/common-hal/busio/UART.c
msgid "UART write"
@ -2432,7 +2433,7 @@ msgstr "Schreiben nicht unterstüzt für diese Charakteristik"
#: supervisor/shared/safe_mode.c
msgid "You are in safe mode because:\n"
msgstr "Du bist im abgesicherten Modus weil:\n"
msgstr "Du befindest dich im abgesicherten Modus, weil:\n"
#: supervisor/shared/safe_mode.c
msgid ""
@ -2521,7 +2522,7 @@ msgstr "Versuch (arg)min/(arg)max einer leeren Sequenz zu holen"
#: extmod/ulab/code/numpy/numerical.c
msgid "attempt to get argmin/argmax of an empty sequence"
msgstr "Sie haben versucht argmin/argmax einer leeren Sequenz zu erhalten"
msgstr "Versuch, argmin/argmax einer leeren Sequenz zu ermitteln"
#: py/objstr.c
msgid "attributes not supported yet"
@ -3449,8 +3450,8 @@ msgstr ""
#: py/argcheck.c
msgid "keyword argument(s) not yet implemented - use normal args instead"
msgstr ""
"Schlüsselwort-Argument(e) noch nicht implementiert - verwenden Sie "
"stattdessen normale Argumente"
"Schlüsselwort-Argument(e) noch nicht implementiert - verwende stattdessen "
"normale Argumente"
#: py/bc.c
msgid "keywords must be strings"
@ -3794,10 +3795,20 @@ msgid "offset out of bounds"
msgstr "offset außerhalb der Grenzen"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "nur eine bit_depth=16 wird unterstützt"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "nur eine sample_rate=16000 wird unterstützt"
@ -4091,8 +4102,7 @@ msgstr "String Indizes müssen Integer sein, nicht %q"
#: py/stream.c
msgid "string not supported; use bytes or bytearray"
msgstr ""
"Zeichenfolgen werden nicht unterstützt; Verwenden Sie bytes oder bytearray"
msgstr "Zeichenfolgen werden nicht unterstützt; verwende bytes oder bytearray"
#: extmod/moductypes.c
msgid "struct: can't index"
@ -4147,7 +4157,7 @@ msgstr "Zeitlimit beim warten auf v2 Karte"
#: ports/stm/common-hal/pwmio/PWMOut.c
msgid "timer re-init"
msgstr "Timer wird neu initialisiert"
msgstr "Timer wird erneut initialisiert"
#: shared-bindings/time/__init__.c
msgid "timestamp out of range for platform time_t"

View File

@ -3725,10 +3725,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3735,10 +3735,20 @@ msgid "offset out of bounds"
msgstr "offset out of bounds"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "only bit_depth=16 is supported"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "only sample_rate=16000 is supported"

View File

@ -3782,10 +3782,20 @@ msgid "offset out of bounds"
msgstr "offset fuera de límites"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "solo se admite bit_depth=16"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "solo se admite sample_rate=16000"

View File

@ -3734,10 +3734,20 @@ msgid "offset out of bounds"
msgstr "wala sa sakop ang address"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2022-08-29 18:20+0000\n"
"Last-Translator: Maxime Leroy <lisacintosh@gmail.com>\n"
"PO-Revision-Date: 2022-11-09 19:20+0000\n"
"Last-Translator: Deleted User <noreply+52049@weblate.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.14.1-dev\n"
"X-Generator: Weblate 4.15-dev\n"
#: main.c
msgid ""
@ -73,7 +73,7 @@ msgstr "%%c nécessite un chiffre entier 'int' ou un caractère 'char'"
#: main.c
#, c-format
msgid "%02X"
msgstr ""
msgstr "%02X"
#: shared-bindings/rgbmatrix/RGBMatrix.c
#, c-format
@ -173,7 +173,7 @@ msgstr "%q doit être >= %d"
#: shared-bindings/analogbufio/BufferedIn.c
#: shared-bindings/audiocore/RawSample.c
msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'"
msgstr ""
msgstr "%q doit être a bytearray ou array de type 'h', 'H', 'b', ou 'B'"
#: py/argcheck.c
msgid "%q must be a string"
@ -602,7 +602,7 @@ msgstr "RX et TX requis pour le contrôle de flux"
#: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
#: ports/atmel-samd/boards/meowmeow/mpconfigboard.h
msgid "Both buttons were pressed at start up.\n"
msgstr ""
msgstr "Les deux boutons étaient pressés au démarrage.\n"
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
msgid "Both pins must support hardware interrupts"
@ -672,7 +672,7 @@ msgstr "La broche %d du bus est déjà utilisée"
#: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h
#: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h
msgid "Button A was pressed at start up.\n"
msgstr ""
msgstr "Le bouton A était pressé au démarrage.\n"
#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
@ -967,7 +967,7 @@ msgstr "Attendu un %q"
#: ports/raspberrypi/bindings/cyw43/__init__.c
msgid "Expected a %q or %q"
msgstr ""
msgstr "Attendu un %q ou %q"
#: shared-bindings/alarm/__init__.c
msgid "Expected an %q"
@ -1054,16 +1054,16 @@ msgstr "Filtres trop complexe"
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is duplicate"
msgstr ""
msgstr "Le logiciel est identique"
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is invalid"
msgstr ""
msgstr "Logiciel invalide"
#: ports/espressif/common-hal/coproc/Coproc.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is too big"
msgstr ""
msgstr "Logiciel trop volumineux"
#: shared-bindings/bitmaptools/__init__.c
msgid "For L8 colorspace, input bitmap must have 8 bits per pixel"
@ -1597,11 +1597,11 @@ msgstr "Aucun minuteur disponible"
#: supervisor/shared/safe_mode.c
msgid "Nordic system firmware failure assertion."
msgstr "Assertion échouée du logiciel systême Nordic."
msgstr "Assertion échouée du logiciel système Nordic."
#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Nordic system firmware out of memory"
msgstr "Logiciel systême Nordic hors de mémoire"
msgstr "Logiciel système Nordic n'a plus de mémoire"
#: shared-bindings/ipaddress/IPv4Address.c shared-bindings/ipaddress/__init__.c
msgid "Not a valid IP string"
@ -1693,7 +1693,7 @@ msgstr ""
#: ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c
#: ports/espressif/common-hal/alarm/touch/TouchAlarm.c
msgid "Only one %q can be set in deep sleep."
msgstr ""
msgstr "Une seul %q autorisée en sommeil profond."
#: ports/espressif/common-hal/i2ctarget/I2CTarget.c
#: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c
@ -1729,7 +1729,7 @@ msgstr "Timeout de l'opération"
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
msgid "Out of memory"
msgstr "Hors de mémoire"
msgstr "Mémoire insuffisante"
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
@ -2058,7 +2058,7 @@ msgstr "Délais de lecture de température dépassée"
#: supervisor/shared/safe_mode.c
msgid "The BOOT button was pressed at start up.\n"
msgstr ""
msgstr "Le bouton BOOT était pressé au démarrage.\n"
#: supervisor/shared/safe_mode.c
msgid ""
@ -2070,11 +2070,11 @@ msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "The SW38 button was pressed at start up.\n"
msgstr ""
msgstr "Le bouton SW38 était pressé au démarrage.\n"
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "The VOLUME button was pressed at start up.\n"
msgstr ""
msgstr "Le bouton VOLUME était pressé au démarrage.\n"
#: supervisor/shared/safe_mode.c
msgid ""
@ -2086,11 +2086,11 @@ msgstr ""
#: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h
msgid "The central button was pressed at start up.\n"
msgstr ""
msgstr "Le bouton central était pressé au démarrage.\n"
#: ports/nrf/boards/aramcon2_badge/mpconfigboard.h
msgid "The left button was pressed at start up.\n"
msgstr ""
msgstr "Le bouton gauche était pressé au démarrage.\n"
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30"
@ -2160,7 +2160,7 @@ msgstr "Le délai est trop long : le délai maximal est de %d secondes"
#: supervisor/shared/safe_mode.c
msgid "To exit, please reset the board without requesting safe mode."
msgstr ""
msgstr "Pour le quitter, redémarrez sans demander le mode sans-échec."
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Too many channels in sample"
@ -2215,8 +2215,9 @@ msgid "UART write"
msgstr "Écriture UART"
#: main.c
#, fuzzy
msgid "UID:"
msgstr ""
msgstr "UID:"
#: shared-module/usb_hid/Device.c
msgid "USB busy"
@ -2284,7 +2285,7 @@ msgstr "Impossible de lancer la requête mDNS"
#: shared-bindings/coproc/CoprocMemory.c
msgid "Unable to write"
msgstr ""
msgstr "Écriture impossible"
#: shared-bindings/nvm/ByteArray.c
msgid "Unable to write to nvm."
@ -2336,22 +2337,22 @@ msgstr "Erreur de sécurité inconnue : 0x%04x"
#: ports/espressif/common-hal/_bleio/__init__.c
#, c-format
msgid "Unknown system firmware error at %s:%d: %d"
msgstr "Erreur du firmware système inconnue à %s:%d : %d"
msgstr "Erreur du logiciel système inconnue à %s:%d : %d"
#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Unknown system firmware error: %04x"
msgstr "Faute inconnue du logiciel systême : %04x"
msgstr "Faute inconnue du logiciel système : %04x"
#: ports/espressif/common-hal/_bleio/__init__.c
#, c-format
msgid "Unknown system firmware error: %d"
msgstr "Erreur du firmware système inconnue : %d"
msgstr "Erreur du logiciel système inconnue : %d"
#: ports/raspberrypi/common-hal/wifi/__init__.c
#, c-format
msgid "Unkown error code %d"
msgstr ""
msgstr "Erreur inconnue %d"
#: shared-bindings/adafruit_pixelbuf/PixelBuf.c
#, c-format
@ -2508,7 +2509,7 @@ msgstr "Le paramêtre argsort doit être un ndarray"
#: extmod/ulab/code/numpy/numerical.c
msgid "argsort is not implemented for flattened arrays"
msgstr "argsort n'est pas mis en œuvre pour les matrices aplatis"
msgstr "argsort n'est pas implémenté pour les matrices aplaties"
#: py/runtime.c shared-bindings/supervisor/__init__.c
msgid "argument has wrong type"
@ -3039,6 +3040,8 @@ msgid ""
"esp32_camera.Camera requires reserved PSRAM to be configured. See the "
"documentation for instructions."
msgstr ""
"esp32_camera.Camera nécessite la configuration de PSRAM réservée. Se référer "
"à la documentation."
#: py/runtime.c
msgid "exceptions must derive from BaseException"
@ -3822,10 +3825,20 @@ msgid "offset out of bounds"
msgstr "décalage hors limites"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "seul bit_depth = 16 est pris en charge"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "seul sample_rate = 16000 est pris en charge"
@ -4293,7 +4306,7 @@ msgstr "type '%q' inconnu"
#: py/objstr.c
#, c-format
msgid "unmatched '%c' in format"
msgstr ""
msgstr "'%c' sans correspondance dans le format"
#: py/objtype.c py/runtime.c
msgid "unreadable attribute"
@ -4374,7 +4387,7 @@ msgstr "wifi nest pas activé"
#: ports/raspberrypi/common-hal/wifi/Monitor.c
msgid "wifi.Monitor not available"
msgstr ""
msgstr "wifi.Monitor non disponible"
#: shared-bindings/_bleio/Adapter.c
msgid "window must be <= interval"

View File

@ -3698,10 +3698,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3745,10 +3745,20 @@ msgid "offset out of bounds"
msgstr "indirizzo fuori limite"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3717,10 +3717,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "bit_depth=16のみ対応しています"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3702,10 +3702,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -3735,10 +3735,20 @@ msgid "offset out of bounds"
msgstr "offset buiten bereik"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "alleen bit_depth=16 wordt ondersteund"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "alleen sample_rate=16000 wordt ondersteund"

View File

@ -3710,10 +3710,20 @@ msgid "offset out of bounds"
msgstr "offset poza zakresem"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "obsługiwane jest tylko bit_depth=16"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "obsługiwane jest tylko sample_rate=16000"

View File

@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2022-11-02 09:33+0000\n"
"PO-Revision-Date: 2022-11-11 18:49+0000\n"
"Last-Translator: Wellington Terumi Uemura <wellingtonuemura@gmail.com>\n"
"Language-Team: \n"
"Language: pt_BR\n"
@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.14.2-dev\n"
"X-Generator: Weblate 4.15-dev\n"
#: main.c
msgid ""
@ -3798,10 +3798,20 @@ msgid "offset out of bounds"
msgstr "desvio fora dos limites"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "apenas bit_depth = 16 é compatível"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr "Apenas o mono é compatível"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr "apenas oversample=64 é compatível"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "apenas sample_rate = 16000 é compatível"
@ -4271,7 +4281,7 @@ msgstr "tipo desconhecido '%q'"
#: py/objstr.c
#, c-format
msgid "unmatched '%c' in format"
msgstr ""
msgstr "'%c' sem correspondência no formato"
#: py/objtype.c py/runtime.c
msgid "unreadable attribute"

View File

@ -3747,10 +3747,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2022-10-31 13:02+0000\n"
"PO-Revision-Date: 2022-11-11 18:49+0000\n"
"Last-Translator: Jonny Bergdahl <jonny@bergdahl.it>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: sv\n"
@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.14.2-dev\n"
"X-Generator: Weblate 4.15-dev\n"
#: main.c
msgid ""
@ -3763,10 +3763,20 @@ msgid "offset out of bounds"
msgstr "offset utanför gränserna"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "bara bit_depth=16 stöds"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr "endast mono stöds"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr "endast oversample=64 stöds"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "enbart sample_rate=16000 stöds"
@ -4232,7 +4242,7 @@ msgstr "okänd typ '%q'"
#: py/objstr.c
#, c-format
msgid "unmatched '%c' in format"
msgstr ""
msgstr "Omatchad '%c' i format"
#: py/objtype.c py/runtime.c
msgid "unreadable attribute"

View File

@ -3718,10 +3718,20 @@ msgid "offset out of bounds"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr ""
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr ""
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr ""

View File

@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: circuitpython-cn\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2022-08-20 14:09+0000\n"
"PO-Revision-Date: 2022-11-19 18:48+0000\n"
"Last-Translator: hexthat <hexthat@gmail.com>\n"
"Language-Team: Chinese Hanyu Pinyin\n"
"Language: zh_Latn_pinyin\n"
@ -15,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.14-dev\n"
"X-Generator: Weblate 4.15-dev\n"
#: main.c
msgid ""
@ -72,7 +72,7 @@ msgstr "%%c xūyào zhěngshù huòzhě zìfú"
#: main.c
#, c-format
msgid "%02X"
msgstr ""
msgstr "%02X"
#: shared-bindings/rgbmatrix/RGBMatrix.c
#, c-format
@ -127,7 +127,7 @@ msgstr "%q chūshǐhuà shībài"
#: shared-bindings/dualbank/__init__.c
msgid "%q is %q"
msgstr ""
msgstr "%q shì %q"
#: py/argcheck.c
msgid "%q length must be %d"
@ -173,6 +173,7 @@ msgstr "%q bìxū >= %d"
#: shared-bindings/audiocore/RawSample.c
msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'"
msgstr ""
"%q bì xū shì zì jié shù zǔ huò lèi xíng wéi 'h', 'H', 'b', huò 'B' de shù zǔ"
#: py/argcheck.c
msgid "%q must be a string"
@ -597,7 +598,7 @@ msgstr "RX hé TX dōu xū yào liúliàng kòngzhì"
#: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
#: ports/atmel-samd/boards/meowmeow/mpconfigboard.h
msgid "Both buttons were pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià le liǎng gè àn niǔ.\n"
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
msgid "Both pins must support hardware interrupts"
@ -667,7 +668,7 @@ msgstr "Zǒngxiàn yǐnjiǎo %d yǐjīng zài shǐyòng zhōng"
#: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h
#: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h
msgid "Button A was pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià àn niǔ A.\n"
#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
@ -741,11 +742,11 @@ msgstr "Wúfǎ huòqǔ wēndù"
#: shared-bindings/_bleio/Adapter.c
msgid "Cannot have scan responses for extended, connectable advertisements."
msgstr "Nín wúfǎ sǎomiáo kuòzhǎn de, kě liánjiē de guǎnggào."
msgstr "Quē fá duì tuī guǎng, kě lián jiē guǎng gào de dá fù."
#: ports/espressif/common-hal/alarm/pin/PinAlarm.c
msgid "Cannot pull on input-only pin."
msgstr "wú fǎ lā dòng jǐn shū rù yǐn jiǎo."
msgstr "wúfǎ lādòng jǐn shūrù yǐnjiǎo."
#: shared-bindings/audiobusio/PDMIn.c
msgid "Cannot record to a file"
@ -753,7 +754,7 @@ msgstr "Wúfǎ jìlù dào wénjiàn"
#: shared-module/storage/__init__.c
msgid "Cannot remount '/' when visible via USB."
msgstr "tōng guò USB kě jiàn shí wú fǎ chóng xīn ān zhuāng '/'."
msgstr "tōngguò USB kějiàn shí wúfǎ chóngxīn ānzhuāng '/'."
#: ports/atmel-samd/common-hal/microcontroller/__init__.c
#: ports/cxd56/common-hal/microcontroller/__init__.c
@ -772,31 +773,31 @@ msgstr "Dāng fāngxiàng wéi shūrù shí, bùnéng shèzhì zhí."
#: ports/espressif/common-hal/busio/UART.c
#: ports/mimxrt10xx/common-hal/busio/UART.c
msgid "Cannot specify RTS or CTS in RS485 mode"
msgstr "wú fǎ zài RS485 mó shì xià zhǐ dìng RTS huò CTS"
msgstr "wúfǎ zài RS485 móshì xià zhǐdìng RTS huò CTS"
#: py/objslice.c
msgid "Cannot subclass slice"
msgstr "bùnéng zi lèi huà qiēpiàn"
msgstr "bùnéng zǐlèihuà qiēpiàn"
#: shared-module/bitbangio/SPI.c
msgid "Cannot transfer without MOSI and MISO pins"
msgstr "méiyǒu MOSI hé MISO yǐn jiǎo wúfǎ chuánshū"
msgstr "méiyǒu MOSI hé MISO yǐnjiǎo, wúfǎ chuánshū"
#: shared-bindings/pwmio/PWMOut.c
msgid "Cannot vary frequency on a timer that is already in use"
msgstr "Wúfǎ gēnggǎi yǐ zài shǐyòng de jìshí qì shàng de pínlǜ"
msgstr "Wúfǎ zài shǐyòng zhōng de jìshí qì shàng gēnggǎi pínlǜ"
#: ports/nrf/common-hal/alarm/pin/PinAlarm.c
msgid "Cannot wake on pin edge, only level"
msgstr "wúfǎ zài yǐn jiǎo biānyuán huànxǐng, zhǐ néng diàn píng"
msgstr "wúfǎ shǐyòng biānyuán huànxǐng, zhǐnéng shǐyòng diànpíng"
#: ports/espressif/common-hal/alarm/pin/PinAlarm.c
msgid "Cannot wake on pin edge. Only level."
msgstr "wú fǎ zài yǐn jiǎo biān yuán huàn xǐng. jǐn jí bié."
msgstr "wúfǎ shǐyòng biānyuán huànxǐng. zhǐnéng shǐyòng diànpíng."
#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Wèi tígōng zìfú huǎncún xiě rù"
msgstr "Wèi tígōng zìfú huǎncún xiěrù"
#: supervisor/shared/safe_mode.c
msgid "CircuitPython core code crashed hard. Whoops!\n"
@ -808,11 +809,11 @@ msgstr "CircuitPython wúfǎ fēnpèi duī."
#: shared-module/bitbangio/I2C.c
msgid "Clock stretch too long"
msgstr "Shízhōng shēnzhǎn tài zhǎng"
msgstr "shízhōng yánzhǎn guòcháng"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Clock unit in use"
msgstr "Shǐyòng shízhōng dānwèi"
msgstr "shízhōng dānyuán zhèngzài shǐyòng zhōng"
#: shared-bindings/_bleio/Connection.c
msgid ""
@ -830,7 +831,7 @@ msgstr "wúfǎ jiǎnsuǒ shízhōng"
#: shared-bindings/_bleio/Adapter.c
msgid "Could not set address"
msgstr "wú fǎ shè zhì dì zhǐ"
msgstr "wúfǎ shèzhì dìzhǐ"
#: shared-bindings/pwmio/PWMOut.c
msgid "Could not start PWM"
@ -842,11 +843,11 @@ msgstr "Wúfǎ qǐdòng zhōngduàn,RX máng"
#: shared-module/audiomp3/MP3Decoder.c
msgid "Couldn't allocate decoder"
msgstr "Zhǎo bù dào jiěmǎ qì"
msgstr "wúfǎ fēnpèi jiěmǎ qì"
#: supervisor/shared/safe_mode.c
msgid "Crash into the HardFault_Handler."
msgstr "Zhuìhuǐ. Shūrù HardFault_Handler."
msgstr "gu4zhang4, jin4ru4 HardFault_Handler."
#: ports/stm/common-hal/analogio/AnalogOut.c
msgid "DAC Channel Init Error"
@ -858,12 +859,12 @@ msgstr "DAC shèbèi chūshǐhuà cuòwù"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "DAC already in use"
msgstr "Fā yuán huì yǐjīng shǐyòng"
msgstr "DAC zhèngzài bèi shǐyòng"
#: ports/atmel-samd/common-hal/paralleldisplay/ParallelBus.c
#: ports/nrf/common-hal/paralleldisplay/ParallelBus.c
msgid "Data 0 pin must be byte aligned"
msgstr "Shùjù 0 de yǐn jiǎo bìxū shì zì jié duìqí"
msgstr "shù jù 0 yǐn jiǎo bì xū shì zì jié duì qí de"
#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
@ -872,7 +873,7 @@ msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài"
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Data not supported with directed advertising"
msgstr "bù zhī chí dìng xiàng guǎng gào de shù jù"
msgstr "wèi xiàng guǎng gào tí gòng zhī zhù de shù jù"
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/nrf/common-hal/_bleio/Adapter.c
@ -946,15 +947,15 @@ msgstr "cuò wù: bǎng dìng shī bài"
#: shared-bindings/coproc/__init__.c shared-bindings/microcontroller/Pin.c
#: shared-bindings/neopixel_write/__init__.c
msgid "Expected a %q"
msgstr "Yùqí %q"
msgstr "Yù qí %q"
#: ports/raspberrypi/bindings/cyw43/__init__.c
msgid "Expected a %q or %q"
msgstr ""
msgstr "yù qī wéi %q huò %q"
#: shared-bindings/alarm/__init__.c
msgid "Expected an %q"
msgstr ""
msgstr "yù qī wéi %q"
#: ports/espressif/common-hal/_bleio/Adapter.c
#: ports/nrf/common-hal/_bleio/Adapter.c
@ -1036,16 +1037,16 @@ msgstr "guò lǜ qì tài fù zá"
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is duplicate"
msgstr ""
msgstr "gù jiàn chóng fù"
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is invalid"
msgstr ""
msgstr "gù jiàn wú xiào"
#: ports/espressif/common-hal/coproc/Coproc.c
#: ports/espressif/common-hal/dualbank/__init__.c
msgid "Firmware is too big"
msgstr ""
msgstr "gù jiàn tài dà"
#: shared-bindings/bitmaptools/__init__.c
msgid "For L8 colorspace, input bitmap must have 8 bits per pixel"
@ -1663,7 +1664,7 @@ msgstr ""
#: ports/espressif/common-hal/alarm/coproc/CoprocAlarm.c
#: ports/espressif/common-hal/alarm/touch/TouchAlarm.c
msgid "Only one %q can be set in deep sleep."
msgstr ""
msgstr "zài shēn dù shuì mián zhōng zhǐ néng shè zhì yí gè %q."
#: ports/espressif/common-hal/i2ctarget/I2CTarget.c
#: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c
@ -2024,7 +2025,7 @@ msgstr "Wēndù dòu qǔ chāoshí"
#: supervisor/shared/safe_mode.c
msgid "The BOOT button was pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià le yǐn dǎo àn niǔ.\n"
#: supervisor/shared/safe_mode.c
msgid ""
@ -2036,11 +2037,11 @@ msgstr ""
#: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h
msgid "The SW38 button was pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià le SW38 àn niǔ .\n"
#: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h
msgid "The VOLUME button was pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià yīn liàng àn niǔ.\n"
#: supervisor/shared/safe_mode.c
msgid ""
@ -2052,11 +2053,11 @@ msgstr ""
#: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h
msgid "The central button was pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià zhōng yāng àn niǔ.\n"
#: ports/nrf/boards/aramcon2_badge/mpconfigboard.h
msgid "The left button was pressed at start up.\n"
msgstr ""
msgstr "qǐ dòng shí àn xià zuǒ àn niǔ.\n"
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30"
@ -2125,6 +2126,8 @@ msgstr "Chāoshí shíjiān tài zhǎng: Zuìdà chāoshí shíjiān wèi%d miǎ
#: supervisor/shared/safe_mode.c
msgid "To exit, please reset the board without requesting safe mode."
msgstr ""
"yào tuì chū, qǐng zài bù qǐng qiú ān quán mó shì de qíng kuàng xià chóng zhì "
"zhǔ bǎn."
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Too many channels in sample"
@ -2180,7 +2183,7 @@ msgstr "UART xiě rù"
#: main.c
msgid "UID:"
msgstr ""
msgstr "UID:"
#: shared-module/usb_hid/Device.c
msgid "USB busy"
@ -2245,7 +2248,7 @@ msgstr "wú fǎ qǐ dòng mDNS chá xún"
#: shared-bindings/coproc/CoprocMemory.c
msgid "Unable to write"
msgstr ""
msgstr "wú fǎ xiě rù"
#: shared-bindings/nvm/ByteArray.c
msgid "Unable to write to nvm."
@ -2312,7 +2315,7 @@ msgstr "wèi zhī de xì tǒng gù jiàn cuò wù: %d"
#: ports/raspberrypi/common-hal/wifi/__init__.c
#, c-format
msgid "Unkown error code %d"
msgstr ""
msgstr "wèi zhī cuò wù dài %d"
#: shared-bindings/adafruit_pixelbuf/PixelBuf.c
#, c-format
@ -2989,6 +2992,8 @@ msgid ""
"esp32_camera.Camera requires reserved PSRAM to be configured. See the "
"documentation for instructions."
msgstr ""
"esp32_camera. shè xiàng jī xū yào pèi zhì yù liú de PSRAM. yǒu guān shuō "
"míng, qǐng cān yuè wén dàng."
#: py/runtime.c
msgid "exceptions must derive from BaseException"
@ -3763,10 +3768,20 @@ msgid "offset out of bounds"
msgstr "piānlí biānjiè"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only bit_depth=16 is supported"
msgstr "Jǐn zhīchí wèi shēndù = 16"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only mono is supported"
msgstr "jǐn zhī chí dān shēng dào"
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only oversample=64 is supported"
msgstr "jǐn zhī chí guò cǎi yàng =64"
#: ports/nrf/common-hal/audiobusio/PDMIn.c
#: ports/stm/common-hal/audiobusio/PDMIn.c
msgid "only sample_rate=16000 is supported"
msgstr "Jǐn zhīchí cǎiyàng lǜ = 16000"
@ -4234,7 +4249,7 @@ msgstr "wèizhī lèixíng '%q'"
#: py/objstr.c
#, c-format
msgid "unmatched '%c' in format"
msgstr ""
msgstr "gé shì bù pǐ pèi de '%c'"
#: py/objtype.c py/runtime.c
msgid "unreadable attribute"
@ -4315,7 +4330,7 @@ msgstr "wèi qǐ yòng WIFI"
#: ports/raspberrypi/common-hal/wifi/Monitor.c
msgid "wifi.Monitor not available"
msgstr ""
msgstr "wú xiàn wǎng luò xiǎn shì qì bù kě yòng"
#: shared-bindings/_bleio/Adapter.c
msgid "window must be <= interval"

View File

@ -644,6 +644,10 @@ void port_disable_tick(void) {
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_PER2;
#endif
#ifdef SAMD21
if (_tick_event_channel == EVSYS_SYNCH_NUM) {
return;
}
if (_tick_event_channel >= 8) {
uint8_t value = 1 << (_tick_event_channel - 8);
EVSYS->INTENCLR.reg = EVSYS_INTENSET_EVDp8(value);
@ -651,6 +655,7 @@ void port_disable_tick(void) {
uint8_t value = 1 << _tick_event_channel;
EVSYS->INTENCLR.reg = EVSYS_INTENSET_EVD(value);
}
disable_event_channel(_tick_event_channel);
_tick_event_channel = EVSYS_SYNCH_NUM;
#endif
}

View File

@ -1,5 +1,5 @@
# idf.py menuconfig
sdkconfig*
/sdkconfig*
# lock files for examples and components
dependencies.lock

View File

@ -30,7 +30,9 @@
#define MICROPY_HW_MCU_NAME "ESP32-C3"
// Status LED
#define MICROPY_HW_LED_STATUS (&pin_GPIO19)
#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO3)
#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO4)
#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO5)
// Default bus pins
#define DEFAULT_UART_BUS_RX (&pin_GPIO20)

View File

@ -30,7 +30,9 @@
#define MICROPY_HW_MCU_NAME "ESP32-C3FN4"
// Status LED
#define MICROPY_HW_LED_STATUS (&pin_GPIO19)
#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO3)
#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO4)
#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO5)
// Default bus pins
#define DEFAULT_UART_BUS_RX (&pin_GPIO20)

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,43 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Micropython setup
#define MICROPY_HW_BOARD_NAME "CRCibernetica IdeaBoard"
#define MICROPY_HW_MCU_NAME "ESP32"
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO21}}
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO23, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}}
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View File

@ -0,0 +1,9 @@
CIRCUITPY_CREATOR_ID = 0x0000303A
CIRCUITPY_CREATION_ID = 0x00320002
IDF_TARGET = esp32
CIRCUITPY_ESP_FLASH_MODE = dio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 16MB
CIRCUITPY_ESP32_CAMERA = 0

View File

@ -0,0 +1,52 @@
#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_NEOPIXEL), 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_RX), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_MISO), 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_SDA), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO23) },
{ 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_IO32), MP_ROM_PTR(&pin_GPIO32) },
{ MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,20 @@
CONFIG_ESP32_ECO3_CACHE_LOCK_FIX=y
CONFIG_ESP32_SPIRAM_SUPPORT=n
# Uncomment (remove ###) to send ESP_LOG output to TX/RX pins
### #
### # ESP System Settings
### #
### CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
### # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
### CONFIG_ESP_CONSOLE_UART_CUSTOM=y
### CONFIG_ESP_CONSOLE_NONE is not set
### CONFIG_ESP_CONSOLE_UART=y
### CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y
### # CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1 is not set
### CONFIG_ESP_CONSOLE_UART_NUM=0
### CONFIG_ESP_CONSOLE_UART_TX_GPIO=17
### CONFIG_ESP_CONSOLE_UART_RX_GPIO=16
### CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
### # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set
### # end of ESP System Settings

View File

@ -0,0 +1,61 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/displayio/FourWire.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/board.h"
#include "components/log/include/esp_log.h"
#define DELAY 0x80
void board_init(void) {
// USB
common_hal_never_reset_pin(&pin_GPIO19);
common_hal_never_reset_pin(&pin_GPIO20);
// Debug UART
#ifdef DEBUG
common_hal_never_reset_pin(&pin_GPIO43);
common_hal_never_reset_pin(&pin_GPIO44);
#endif /* DEBUG */
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// Micropython setup
#define MICROPY_HW_BOARD_NAME "Maker badge by Czech maker"
#define MICROPY_HW_MCU_NAME "ESP32S2"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO18)
#define MICROPY_HW_NEOPIXEL_COUNT (4)
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
#define AUTORESET_DELAY_MS 500
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35)
#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37)
#define DEFAULT_UART_BUS_RX (&pin_GPIO44)
#define DEFAULT_UART_BUS_TX (&pin_GPIO43)
// USB is always used internally so skip the pin objects for it.
#define IGNORE_PIN_GPIO18 1
#define IGNORE_PIN_GPIO19 1
#define DOUBLE_TAP_PIN (&pin_GPIO38)

View File

@ -0,0 +1,20 @@
USB_VID = 0x239A
USB_PID = 0x2030
USB_PRODUCT = "Maker badge"
USB_MANUFACTURER = "Czech maker"
CIRCUITPY_ESP32_CAMERA = 0
CIRCUITPY_ESP_FLASH_MODE=dio
CIRCUITPY_ESP_FLASH_FREQ=40m
CIRCUITPY_ESP_FLASH_SIZE=4MB
IDF_TARGET = esp32s2
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_UC8151D
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SSD1680

View File

@ -0,0 +1,86 @@
#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_D0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_CAP5), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_CAP4), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_CAP3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_CAP2), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_CAP1), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER_INVERTED), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_D33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_D34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_GPIO37) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) },
{ MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_GPIO38) },
{ MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_D40), MP_ROM_PTR(&pin_GPIO40) },
{ MP_ROM_QSTR(MP_QSTR_D41), MP_ROM_PTR(&pin_GPIO41) },
{ MP_ROM_QSTR(MP_QSTR_D42), MP_ROM_PTR(&pin_GPIO42) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,6 @@
CONFIG_ESP32S2_SPIRAM_SUPPORT=n
# LWIP
#
CONFIG_LWIP_LOCAL_HOSTNAME="Maker_badge"
# end of LWIP

View File

@ -49,8 +49,9 @@ static void uart_event_task(void *param) {
while (true) {
if (xQueueReceive(self->event_queue, &event, portMAX_DELAY)) {
switch (event.type) {
case UART_BREAK:
case UART_PATTERN_DET:
// When the console uart receives CTRL+C, wake the main task and schedule a keyboard interrupt
// When the console uart receives CTRL+C or BREAK, wake the main task and schedule a keyboard interrupt
if (self->is_console) {
port_wake_main_task();
if (mp_interrupt_char == CHAR_CTRL_C) {

View File

@ -40,13 +40,13 @@
#include "soc/efuse_reg.h"
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S3)
#if !defined(CONFIG_IDF_TARGET_ESP32)
#include "driver/temp_sensor.h"
#endif
float common_hal_mcu_processor_get_temperature(void) {
float tsens_out;
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32)
#if defined(CONFIG_IDF_TARGET_ESP32)
mp_raise_NotImplementedError(NULL);
#else
temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); // DEFAULT: range:-10℃ ~ 80℃, error < 1℃.

View File

@ -166,7 +166,20 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) {
void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) {
never_reset_tim[self->tim_handle.timer_num] = false;
never_reset_chan[self->chan_handle.channel] = false;
// Search if any other channel is using the timer and is never reset.
// Otherwise, we clear never_reset for the timer as well.
bool other_never_reset = false;
for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++) {
if (i != self->chan_handle.channel &&
reserved_channels[i] == self->tim_handle.timer_num &&
never_reset_chan[i]) {
other_never_reset = true;
break;
}
}
if (!other_never_reset) {
never_reset_chan[self->chan_handle.channel] = false;
}
}
bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t *self) {
@ -182,11 +195,13 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
ledc_stop(LEDC_LOW_SPEED_MODE, self->chan_handle.channel, 0);
}
reserved_channels[self->chan_handle.channel] = INDEX_EMPTY;
never_reset_chan[self->chan_handle.channel] = false;
// Search if any other channel is using the timer
bool taken = false;
for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++) {
if (reserved_channels[i] == self->tim_handle.timer_num) {
taken = true;
break;
}
}
// Variable frequency means there's only one channel on the timer
@ -195,6 +210,7 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
reserved_timer_freq[self->tim_handle.timer_num] = 0;
// if timer isn't varfreq this will be off aleady
varfreq_timers[self->tim_handle.timer_num] = false;
never_reset_tim[self->tim_handle.timer_num] = false;
}
common_hal_reset_pin(self->pin);
self->deinited = true;

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,45 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Glenn Ruben Bakke
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "nrfx/hal/nrf_gpio.h"
#define MICROPY_HW_BOARD_NAME "PillBug"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_HW_LED_STATUS (&pin_P0_20)
#define BOARD_HAS_CRYSTAL 1
#define DEFAULT_I2C_BUS_SCL (&pin_P0_13)
#define DEFAULT_I2C_BUS_SDA (&pin_P0_15)
#define DEFAULT_SPI_BUS_SCK (&pin_P1_08)
#define DEFAULT_SPI_BUS_MOSI (&pin_P0_11)
#define DEFAULT_SPI_BUS_MISO (&pin_P0_26)
#define DEFAULT_UART_BUS_RX (&pin_P0_08)
#define DEFAULT_UART_BUS_TX (&pin_P0_06)

View File

@ -0,0 +1,8 @@
USB_VID = 0x16D0
USB_PID = 0x10ED
USB_PRODUCT = "PillBug"
USB_MANUFACTURER = "Mechwild"
MCU_CHIP = nrf52840
INTERNAL_FLASH_FILESYSTEM = 1

View File

@ -0,0 +1,64 @@
#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_P0_02), MP_ROM_PTR(&pin_P0_02) },
{ MP_ROM_QSTR(MP_QSTR_P0_04), MP_ROM_PTR(&pin_P0_04) },
{ MP_ROM_QSTR(MP_QSTR_P0_06), MP_ROM_PTR(&pin_P0_06) },
{ MP_ROM_QSTR(MP_QSTR_P0_08), MP_ROM_PTR(&pin_P0_08) },
{ MP_ROM_QSTR(MP_QSTR_P0_09), MP_ROM_PTR(&pin_P0_09) },
{ MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) },
{ MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) },
{ MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) },
{ MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) },
{ MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) },
{ MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) },
{ MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) },
{ MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) },
{ MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) },
{ MP_ROM_QSTR(MP_QSTR_P0_26), MP_ROM_PTR(&pin_P0_26) },
{ MP_ROM_QSTR(MP_QSTR_P0_29), MP_ROM_PTR(&pin_P0_29) },
{ MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) },
{ MP_ROM_QSTR(MP_QSTR_P1_00), MP_ROM_PTR(&pin_P1_00) },
{ MP_ROM_QSTR(MP_QSTR_P1_01), MP_ROM_PTR(&pin_P1_01) },
{ MP_ROM_QSTR(MP_QSTR_P1_02), MP_ROM_PTR(&pin_P1_02) },
{ MP_ROM_QSTR(MP_QSTR_P1_04), MP_ROM_PTR(&pin_P1_04) },
{ MP_ROM_QSTR(MP_QSTR_P1_06), MP_ROM_PTR(&pin_P1_06) },
{ MP_ROM_QSTR(MP_QSTR_P1_07), MP_ROM_PTR(&pin_P1_07) },
{ MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) },
{ MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) },
{ MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) },
{ MP_ROM_QSTR(MP_QSTR_AIN0), MP_ROM_PTR(&pin_P0_02) },
{ MP_ROM_QSTR(MP_QSTR_AIN2), MP_ROM_PTR(&pin_P0_03) },
{ MP_ROM_QSTR(MP_QSTR_AIN5), MP_ROM_PTR(&pin_P0_29) },
{ MP_ROM_QSTR(MP_QSTR_AIN7), MP_ROM_PTR(&pin_P0_31) },
{ MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) },
{ MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_P0_04) }, // Read battery voltage divider
{ MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_P0_04) },
{ MP_ROM_QSTR(MP_QSTR_VCC_OFF), MP_ROM_PTR(&pin_P1_07) }, // External VCC by MOSFET
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_P0_20) }, // Blue LED, HIGH sets to on
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_08) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_06) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_13) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_15) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P1_13) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_10) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P1_11) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -120,13 +120,14 @@ SRC_LWIP :=
endif
INC += \
-I. \
-Ilwip_inc \
-I. \
-Ilwip_inc \
-I../.. \
-I../lib/mp-readline \
-I../shared/timeutils \
-Iboards/$(BOARD) \
-Iboards/ \
-isystem ./../../lib/cmsis/inc \
-isystem sdk/ \
-isystem sdk/src/common/pico_base/include/ \
-isystem sdk/src/common/pico_binary_info/include/ \

View File

@ -123,6 +123,14 @@ const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj) {
return MP_OBJ_TO_PTR(obj);
}
const mcu_pin_obj_t *validate_obj_is_free_pin_or_gpio29(mp_obj_t obj) {
const mcu_pin_obj_t *pin = validate_obj_is_pin(obj);
if (obj != &pin_GPIO29) {
assert_pin_free(pin);
}
return pin;
}
const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj) {
const mcu_pin_obj_t *pin = validate_obj_is_pin_including_cyw43(obj);
assert_pin_free(pin);

View File

@ -32,6 +32,7 @@
extern const mp_obj_type_t cyw43_pin_type;
const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj);
const mcu_pin_obj_t *validate_obj_is_free_pin_or_gpio29(mp_obj_t obj);
const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj);
#define CONSTANT_CYW43_PM_VALUE(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \

View File

@ -45,6 +45,10 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Fabian Affolter <fabian@affolter-engineering.ch>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,2 @@
#define MICROPY_HW_BOARD_NAME "WeAct Studio Pico 16MB"
#define MICROPY_HW_MCU_NAME "rp2040"

View File

@ -0,0 +1,11 @@
USB_VID = 0x239A
USB_PID = 0x102E
USB_PRODUCT = "Pico"
USB_MANUFACTURER = "WeAct Studio"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ"
CIRCUITPY__EVE = 1

View File

@ -0,0 +1 @@
// Put board-specific pico-sdk definitions here. This file must exist.

View File

@ -0,0 +1,53 @@
#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_GP0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -234,6 +234,9 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
// Reset uses the watchdog. Use scratch registers to store wake reason
watchdog_hw->scratch[RP_WKUP_SCRATCH_REG] = _get_wakeup_cause();
// Just before reset, enable the pinalarm interrupt.
alarm_pin_pinalarm_entering_deep_sleep();
reset_cpu();
}

View File

@ -38,7 +38,7 @@
STATIC bool woke_up;
STATIC uint64_t alarm_triggered_pins; // 36 actual pins
STATIC uint64_t alarm_reserved_pins; // 36 actual pins
STATIC bool _pinalarm_set = false;
STATIC bool _not_yet_deep_sleeping = false;
#define GPIO_IRQ_ALL_EVENTS 0x15u
@ -46,12 +46,21 @@ STATIC void gpio_callback(uint gpio, uint32_t events) {
alarm_triggered_pins |= (1 << gpio);
woke_up = true;
// does this need to be called, to prevent IRQ from constantly going off?
gpio_acknowledge_irq(gpio, events);
// gpio_acknowledge_irq(gpio, events) is called automatically, before this callback is called.
// Disable IRQ automatically
gpio_set_irq_enabled(gpio, events, false);
gpio_set_dormant_irq_enabled(gpio, events, false);
if (_not_yet_deep_sleeping) {
// Event went off prematurely, before we went to sleep, so set it again.
gpio_set_irq_enabled(gpio, events, false);
} else {
// Went off during sleep.
// Disable IRQ automatically.
gpio_set_irq_enabled(gpio, events, false);
gpio_set_dormant_irq_enabled(gpio, events, false);
}
}
void alarm_pin_pinalarm_entering_deep_sleep() {
_not_yet_deep_sleeping = false;
}
void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) {
@ -156,11 +165,7 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
gpio_set_dormant_irq_enabled((uint)alarm->pin->number, event, true);
}
_pinalarm_set = true;
_not_yet_deep_sleeping = true;
}
}
}
bool alarm_pin_pinalarm_is_set(void) {
return _pinalarm_set;
}

View File

@ -46,4 +46,4 @@ void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_light_reset(void);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
bool alarm_pin_pinalarm_woke_this_cycle(void);
bool alarm_pin_pinalarm_is_set(void);
void alarm_pin_pinalarm_entering_deep_sleep(void);

View File

@ -26,6 +26,7 @@
#include "common-hal/analogio/AnalogIn.h"
#include "shared-bindings/analogio/AnalogIn.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "py/runtime.h"
#include "supervisor/shared/translate/translate.h"
@ -35,16 +36,31 @@
#define ADC_FIRST_PIN_NUMBER 26
#define ADC_PIN_COUNT 4
// Voltage monitor is special on Pico W, because this pin is shared between the
// voltage monitor function and the wifi function. Special handling is required
// to read the analog voltage.
#if CIRCUITPY_CYW43
#include "bindings/cyw43/__init__.h"
#define SPECIAL_PIN(pin) (pin->number == 29)
const mcu_pin_obj_t *common_hal_analogio_analogin_validate_pin(mp_obj_t obj) {
return validate_obj_is_free_pin_or_gpio29(obj);
}
#else
#define SPECIAL_PIN(pin) false
#endif
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, const mcu_pin_obj_t *pin) {
if (pin->number < ADC_FIRST_PIN_NUMBER || pin->number > ADC_FIRST_PIN_NUMBER + ADC_PIN_COUNT) {
raise_ValueError_invalid_pin();
}
adc_init();
if (!SPECIAL_PIN(pin)) {
adc_gpio_init(pin->number);
claim_pin(pin);
}
adc_gpio_init(pin->number);
claim_pin(pin);
self->pin = pin;
}
@ -57,14 +73,30 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
return;
}
reset_pin_number(self->pin->number);
if (!SPECIAL_PIN(self->pin)) {
reset_pin_number(self->pin->number);
}
self->pin = NULL;
}
uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
uint16_t value = adc_read();
uint16_t value;
if (SPECIAL_PIN(self->pin)) {
common_hal_mcu_disable_interrupts();
uint32_t old_pad = padsbank0_hw->io[self->pin->number];
uint32_t old_ctrl = iobank0_hw->io[self->pin->number].ctrl;
adc_gpio_init(self->pin->number);
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
common_hal_mcu_delay_us(100);
value = adc_read();
gpio_init(self->pin->number);
padsbank0_hw->io[self->pin->number] = old_pad;
iobank0_hw->io[self->pin->number].ctrl = old_ctrl;
common_hal_mcu_enable_interrupts();
} else {
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
value = adc_read();
}
// Stretch 12-bit ADC reading to 16-bit range
return (value << 4) | (value >> 8);
}

View File

@ -151,6 +151,15 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
spi_set_format(self->peripheral, bits, polarity, phase, SPI_MSB_FIRST);
// Workaround to start with clock line high if polarity=1. The hw SPI peripheral does not do this
// automatically. See https://github.com/raspberrypi/pico-sdk/issues/868 and
// https://forums.raspberrypi.com/viewtopic.php?t=336142
// TODO: scheduled to be be fixed in pico-sdk 1.5.0.
if (polarity) {
hw_clear_bits(&spi_get_hw(self->peripheral)->cr1, SPI_SSPCR1_SSE_BITS); // disable the SPI
hw_set_bits(&spi_get_hw(self->peripheral)->cr1, SPI_SSPCR1_SSE_BITS); // re-enable the SPI
}
self->polarity = polarity;
self->phase = phase;
self->bits = bits;

View File

@ -41,6 +41,10 @@
#include "pico/cyw43_arch.h"
#include "bindings/cyw43/__init__.h"
#define IS_CYW(self) ((self)->pin->base.type == &cyw43_pin_type)
const mcu_pin_obj_t *common_hal_digitalio_validate_pin(mp_obj_t obj) {
return validate_obj_is_free_pin_including_cyw43(obj);
}
#endif
digitalinout_result_t common_hal_digitalio_digitalinout_construct(

View File

@ -46,15 +46,12 @@
#include "components/mdns/include/mdns.h"
#endif
#include "lwip/sys.h"
#include "lwip/dns.h"
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip_src/ping.h"
#ifndef PING_ID
#define PING_ID 0xAFAF
#endif
#define MAC_ADDRESS_LENGTH 6
#define NETIF_STA (&cyw43_state.netif[CYW43_ITF_STA])
@ -295,6 +292,7 @@ void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv
}
volatile bool ping_received;
uint32_t ping_time;
static u8_t
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) {
@ -303,6 +301,7 @@ ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
if ((p->tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
pbuf_remove_header(p, PBUF_IP_HLEN) == 0) {
iecho = (struct icmp_echo_hdr *)p->payload;
if ((iecho->id == PING_ID) && (iecho->seqno == lwip_htons(ping_seq_num))) {
@ -322,6 +321,7 @@ ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
}
mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) {
ping_time = sys_now();
ip_addr_t ping_addr;
ipaddress_ipaddress_to_lwip(ip_address, &ping_addr);

View File

@ -12,6 +12,14 @@
#define PING_USE_SOCKETS LWIP_SOCKET
#endif
#ifndef PING_ID
#define PING_ID 0xAFAF
#endif
#ifndef PING_DEBUG
#define PING_DEBUG LWIP_DBG_ON
#endif
void ping_init(const ip_addr_t *ping_addr);
void ping_prepare_echo(struct icmp_echo_hdr *iecho, u16_t len);

View File

@ -72,6 +72,9 @@
#include "supervisor/serial.h"
#include "tusb.h"
#include <cmsis_compiler.h>
extern volatile bool mp_msc_enabled;
STATIC void _tick_callback(uint alarm_num);
@ -241,38 +244,48 @@ uint32_t port_get_saved_word(void) {
return __scratch_x_start__;
}
static volatile bool ticks_enabled;
uint64_t port_get_raw_ticks(uint8_t *subticks) {
uint64_t microseconds = time_us_64();
return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977;
}
STATIC void _tick_callback(uint alarm_num) {
supervisor_tick();
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
if (ticks_enabled) {
supervisor_tick();
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
}
}
// Enable 1/1024 second tick.
void port_enable_tick(void) {
ticks_enabled = true;
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
}
// Disable 1/1024 second tick.
void port_disable_tick(void) {
// hardware_alarm_cancel(0);
// One additional _tick_callback may occur, but it will just return
// whenever !ticks_enabled. Cancel is not called just in case
// it could nuke a timeout set by port_interrupt_after_ticks.
ticks_enabled = false;
}
// This is called by sleep, we ignore it when our ticks are enabled because
// they'll wake us up earlier. If we don't, we'll mess up ticks by overwriting
// the next RTC wake up time.
void port_interrupt_after_ticks(uint32_t ticks) {
if (!ticks_enabled) {
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), ticks * 977));
}
}
void port_idle_until_interrupt(void) {
common_hal_mcu_disable_interrupts();
if (!background_callback_pending()) {
// TODO: Does not work when board is power-cycled.
// asm volatile ("dsb 0xF" ::: "memory");
// __wfi();
if (!background_callback_pending() && !tud_task_event_ready()) {
__DSB();
__WFI();
}
common_hal_mcu_enable_interrupts();
}

View File

@ -234,6 +234,17 @@ SRC_C += \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/periph.c \
packages/$(MCU_PACKAGE).c
ifneq ($(CIRCUITPY_AUDIOBUSIO_PDMIN),0)
SRC_C += \
common-hal/audiobusio/MEMS_Audio.c \
common-hal/audiobusio/MEMS_Audio_ll_stm32l4.c \
common-hal/audiobusio/OpenPDMFilter.c
SRC_STM32 += \
$(HAL_DIR)/Src/stm32$(MCU_SERIES_LOWER)xx_hal_sai.c
endif
ifneq ($(CIRCUITPY_USB),0)
SRC_C += lib/tinyusb/src/portable/st/synopsys/dcd_synopsys.c
endif

View File

@ -15,61 +15,42 @@ LD_DEFAULT = boards/STM32L4R5_default.ld
LD_BOOT = boards/STM32L4R5_boot.ld
UF2_OFFSET = 0x8010000
UF2_BOOTLOADER ?= 1
CIRCUITPY_BUILD_EXTENSIONS = bin,uf2
# Turn all of the below off while trying to get the thing to run
# These modules are implemented in ports/<port>/common-hal:
# Typically the first module to create
CIRCUITPY_MICROCONTROLLER = 1
CIRCUITPY_ALARM = 1
# Typically the second module to create
CIRCUITPY_DIGITALIO = 1
# Other modules:
CIRCUITPY_OS = 1
CIRCUITPY_STORAGE = 1
CIRCUITPY_USB_MSC = 1
CIRCUITPY_UDB_CDC = 1
CIRCUITPY_USB_VENDOR = 1
CIRCUITPY_NVM = 0
CIRCUITPY_ANALOGIO = 1
CIRCUITPY_AUDIOBUSIO = 1
CIRCUITPY_AUDIOBUSIO_I2SOUT = 0
CIRCUITPY_AUDIOBUSIO_PDMIN = 1
CIRCUITPY_AUDIOPWMIO = 1
CIRCUITPY_BITBANGIO = 1
CIRCUITPY_BLEIO = 0
CIRCUITPY_BLEIO_HCI = 0
CIRCUITPY_BUSDEVICE = 0
CIRCUITPY_BUSIO = 1
CIRCUITPY_CANIO = 0
CIRCUITPY_DIGITALIO = 1
CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_ENABLE_MPY_NATIVE = 1
CIRCUITPY_I2CTARGET = 0
CIRCUITPY_KEYPAD = 1
CIRCUITPY_MICROCONTROLLER = 1
CIRCUITPY_NEOPIXEL_WRITE = 0
CIRCUITPY_NVM = 0
CIRCUITPY_OS = 1
CIRCUITPY_PIXELBUF = 0
CIRCUITPY_PULSEIO = 1
CIRCUITPY_PWMIO = 1
CIRCUITPY_AUDIOPWMIO = 1
CIRCUITPY_CANIO = 0
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_I2CTARGET = 0
# Requires SPI, PulseIO (stub ok):
CIRCUITPY_DISPLAYIO = 0
# These modules are implemented in shared-module/ - they can be included in
# any port once their prerequisites in common-hal are complete.
# Requires DigitalIO:
CIRCUITPY_BITBANGIO = 1
# Requires neopixel_write or SPI (dotstar)
CIRCUITPY_PIXELBUF = 0
# Requires OS
CIRCUITPY_RANDOM = 1
# Requires Microcontroller
CIRCUITPY_TOUCHIO = 1
# Requires USB
CIRCUITPY_USB_HID = 0
CIRCUITPY_USB_MIDI = 0
# Does nothing without I2C
CIRCUITPY_REQUIRE_I2C_PULLUPS = 0
# No requirements, but takes extra flash
CIRCUITPY_ULAB = 1
# requires SPI
CIRCUITPY_SDCARDIO = 0
CIRCUITPY_BLEIO_HCI = 0
CIRCUITPY_BLEIO = 0
CIRCUITPY_BUSDEVICE = 0
CIRCUITPY_KEYPAD = 1
CIRCUITPY_RGBMATRIX = 0
CIRCUITPY_RTC = 1
CIRCUITPY_BUILD_EXTENSIONS = bin,uf2
CIRCUITPY_SDCARDIO = 0
CIRCUITPY_STORAGE = 1
CIRCUITPY_TOUCHIO = 1
CIRCUITPY_UDB_CDC = 1
CIRCUITPY_ULAB = 1
CIRCUITPY_USB_HID = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_USB_MSC = 1
CIRCUITPY_USB_VENDOR = 1

View File

@ -129,5 +129,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_PA03) },
{ MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_PC03) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -0,0 +1 @@
// Although IS2Out is not enabled on the STM32L4 family, this file is still required for the build to pass

View File

@ -0,0 +1 @@
// Although IS2Out is not enabled on the STM32L4 family, this file is still required for the build to pass

View File

@ -0,0 +1,96 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* 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 <assert.h>
#include <stm32l4xx_hal.h>
#include "MEMS_Audio.h"
#include "MEMS_Audio_ll.h"
static void default_pcm_data_available(MemsAudio *audio, pcm_sample_t *pcmSamples, size_t pcmLength) {
}
/**
* @brief Initializes the MemsAudio instance. Only one instance can be initialized and used at a given time.
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_init(MemsAudio *audio) {
if (!audio->pcm_data_available) {
audio->pcm_data_available = default_pcm_data_available;
}
return mems_audio_ll_init(audio);
}
/**
* @brief Uninitializes the MemsAudio instance.
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_uninit(MemsAudio *audio) {
return mems_audio_ll_uninit(audio);
}
/**
* @brief Asynchronously records audio.
*
* @param audio
* @param pdmBuffer
* @param pdmBufferLength
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_record(MemsAudio *audio) {
return mems_audio_ll_record(audio);
}
/**
* @brief Pause recording audio.
*/
mems_audio_err_t mems_audio_pause(MemsAudio *audio) {
return mems_audio_ll_pause(audio);
}
/**
* @brief Resume recording audio.
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_resume(MemsAudio *audio) {
return mems_audio_ll_resume(audio);
}
/**
* @brief Stop recording audio and
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_stop(MemsAudio *audio) {
return mems_audio_ll_stop(audio);
}

View File

@ -0,0 +1,156 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _MEMS_AUDIO_H_
#define _MEMS_AUDIO_H_
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief How many milliseconds of audio can fit in the audio buffer(s).
* Interrupts for recieved data fire at half this duration / twice the frequency.
*/
#ifndef MEMS_AUDIO_MS_BUFFER
#define MEMS_AUDIO_MS_BUFFER (1)
#endif
/**
* @brief The number of bits per sample of the PCM output
*/
#define PCM_OUT_RESOLUTION 16
/**
* @brief The output frequency of PCM samples in Hz.
*/
#define PCM_OUT_SAMPLING_FREQUENCY 16000
/**
* @brief type for describing error conditions.
*/
typedef int32_t mems_audio_err_t;
/**
* @brief The datatype that holds an output PCM sample.
*/
typedef int16_t pcm_sample_t;
_Static_assert(PCM_OUT_RESOLUTION==16, "Output PCM resolution must be 16-bits");
typedef enum {
MEMS_AUDIO_OK = 0,
MEMS_AUDIO_ERROR_ALREADY_INITIALIZED = -1,
MEMS_AUDIO_ERROR_NOT_INITIALIZED = -2
} mems_audio_err_enum_t;
#define IS_MEMS_AUDIO_ERROR(e) (e)
#define CHECK_MEMS_AUDIO_ERROR(e) { if (IS_MEMS_AUDIO_ERROR(e)) return e; }
#define CHECK_MEMS_AUDIO_INITIALIZED(x) { if (!x) return MEMS_AUDIO_ERROR_NOT_INITIALIZED; }
typedef struct MemsAudio_t MemsAudio;
/**
* @brief Callback informing that PCM samples are available for processing.
*/
typedef void (*pcm_data_available_t)(MemsAudio* audio, pcm_sample_t* pcmSamples, size_t pcmLength);
/**
* @brief MemsAudio manages the filter, buffers and callbacks used to capture PDM audio samples and convert to PCM.
*
*/
typedef struct MemsAudio_t {
/**
* @brief The buffer to store PCM audio samples
*/
volatile pcm_sample_t* volatile pcmOutputBuffer;
/**
* @brief The length of the PCM buffer. SHould be at least MEMS_AUDIO_PCM_BUFFER_LENGTH
*/
volatile size_t pcmOutputBufferLength;
/**
* @brief Optional callback for when PCM data is available.
*/
pcm_data_available_t pcm_data_available;
void* audioImpl;
void* userData;
} MemsAudio;
mems_audio_err_t mems_audio_init(MemsAudio* audio);
/**
* @brief Uninitializes the MemsAudio instance.
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_uninit(MemsAudio* audio);
/**
* @brief Asynchronously records audio.
*
* @param audio
* @param pdmBuffer
* @param pdmBufferLength
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_record(MemsAudio* audio);
/**
* @brief Pause recording audio.
*/
mems_audio_err_t mems_audio_pause(MemsAudio* audio);
/**
* @brief Resume recording audio.
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_resume(MemsAudio* audio);
/**
* @brief Stop recording audio and
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_stop(MemsAudio* audio);
#ifdef __cplusplus
}
#endif
#endif // _MEMS_AUDIO_H_

View File

@ -0,0 +1,75 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _MEMS_AUDIO_LL_H_
#define _MEMS_AUDIO_LL_H_
#include "MEMS_Audio.h"
#ifdef __cplusplus
extern "C" {
#endif
mems_audio_err_t mems_audio_ll_init(MemsAudio *audio);
mems_audio_err_t mems_audio_ll_uninit(MemsAudio *audio);
/**
* @brief Asynchronously records audio.
*
* @param audio
* @param pdmBuffer
* @param pdmBufferLength
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_ll_record(MemsAudio *audio);
/**
* @brief Pause recording audio.
*/
mems_audio_err_t mems_audio_ll_pause(MemsAudio *audio);
/**
* @brief Resume recording audio.
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_ll_resume(MemsAudio *audio);
/**
* @brief Stop recording audio and
*
* @param audio
* @return mems_audio_err_t
*/
mems_audio_err_t mems_audio_ll_stop(MemsAudio *audio);
#ifdef __cplusplus
}
#endif
#endif // _MEMS_AUDIO_LL_H_

View File

@ -0,0 +1,386 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* 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 <stm32l4xx_hal.h>
#include "MEMS_Audio_ll_stm32l4.h"
#include "MEMS_Audio.h"
/**
* @brief The implementation is a singleton.
*
*/
MemsAudio_STM32L4SAIPDM* volatile audioImpl;
static mems_audio_err_t MX_DMA_Init(void);
static mems_audio_err_t MX_DMA_Uninit(void);
static mems_audio_err_t MX_SAI1_Init(void);
#define CHECK_HAL_ERROR(x, e) \
{ \
if ((x) != HAL_OK) \
return e; \
}
/**
* @brief Checks the HAL return code and returns from a void function on error. The
* error is saved to lastError.
*/
#define CHECK_HAL_ERROR_VOID(x, e) \
{ \
if ((x) != HAL_OK) { \
audioImpl->lastError = e; \
return; \
} \
}
#define CHECK_MEMS_AUDIO_ERROR_LAST() \
{ \
if (audioImpl->lastError != MEMS_AUDIO_OK) \
return audioImpl->lastError; \
}
static bool default_pdm_data_available(MemsAudio_STM32L4SAIPDM* audio, pdm_sample_t* pdmSamples, size_t count)
{
return true;
}
int filter_pdm(MemsAudio_STM32L4SAIPDM* impl, pdm_sample_t* input, pcm_sample_t* output)
{
if (impl->filter.Decimation==64) {
Open_PDM_Filter_64(input, output, 1, &impl->filter);
}
else {
Open_PDM_Filter_128(input, output, 1, &impl->filter);
}
return impl->filter.nSamples;
}
static void mems_audio_init_filter(MemsAudio_STM32L4SAIPDM *impl)
{
TPDMFilter_InitStruct* filter = &impl->filter;
filter->Fs = PCM_OUT_SAMPLING_FREQUENCY;
filter->nSamples = MEMS_AUDIO_PCM_BUFFER_LENGTH;
filter->LP_HZ = PCM_OUT_SAMPLING_FREQUENCY / 2; // The Nyquist frequency
filter->HP_HZ = 10; // high pass to remove DC offset
filter->In_MicChannels = 1;
filter->Out_MicChannels = 1;
filter->Decimation = PDM_IN_DECIMATION_FACTOR;
Open_PDM_Filter_Init(filter);
}
volatile unsigned ignore_dma_count;
/**
* @brief Converts PDM samples
*
* @param pdmBuffer The buffer holding the PDM samples
* @param pdmBufferLength The number of samples available
*/
void pdm2pcm(uint8_t *pdmBuffer, size_t pdmBufferLength)
{
MemsAudio_STM32L4SAIPDM *impl = audioImpl;
if (impl)
{
bool convert = impl->discard_dma || impl->pdm_data_available(impl, pdmBuffer, pdmBufferLength);
if (convert)
{
MemsAudio* audio = impl->audio;
filter_pdm(impl, pdmBuffer, (pcm_sample_t*)audio->pcmOutputBuffer);
if (!impl->discard_dma)
audio->pcm_data_available(audio, (pcm_sample_t*)audio->pcmOutputBuffer, impl->filter.nSamples);
else
impl->discard_dma--;
}
}
}
/**
* @brief Initialize the PDM interface ready to begin capture.
* @retval
*/
mems_audio_err_t mems_audio_ll_init(MemsAudio *audio)
{
mems_audio_init_filter(audioImpl);
if (!audioImpl->pdm_data_available) {
audioImpl->pdm_data_available = &default_pdm_data_available;
}
CHECK_MEMS_AUDIO_ERROR(MX_DMA_Init());
CHECK_MEMS_AUDIO_ERROR(MX_SAI1_Init());
return MEMS_AUDIO_OK;
}
mems_audio_err_t uninit(void) {
if (audioImpl) {
MemsAudio_STM32L4SAIPDM* impl = audioImpl;
audioImpl = NULL;
mems_audio_ll_stop(impl->audio);
CHECK_HAL_ERROR(HAL_SAI_DeInit(&impl->hSAI_BlockA1), MEMS_AUDIO_ERROR_SAI_DEINIT);
CHECK_MEMS_AUDIO_ERROR(MX_DMA_Uninit());
}
return MEMS_AUDIO_OK;
}
/**
* @brief Uninitialize low level PDM capture
*/
mems_audio_err_t mems_audio_ll_uninit(MemsAudio *audio)
{
if (audioImpl->audio == audio) {
uninit();
}
return MEMS_AUDIO_OK;
}
mems_audio_err_t mems_audio_ll_record(MemsAudio *audio)
{
audioImpl->discard_dma = (100/MEMS_AUDIO_MS_BUFFER)+1;
CHECK_HAL_ERROR(HAL_SAI_Receive_DMA(&audioImpl->hSAI_BlockA1, audioImpl->pdmBuffer, audioImpl->pdmBufferLength),
MEMS_AUDIO_ERROR_DMA_START);
return MEMS_AUDIO_OK;
}
mems_audio_err_t mems_audio_ll_stop(MemsAudio *audio)
{
CHECK_HAL_ERROR(HAL_SAI_DMAStop(&audioImpl->hSAI_BlockA1), MEMS_AUDIO_ERROR_DMA_STOP);
return MEMS_AUDIO_OK;
}
mems_audio_err_t mems_audio_ll_pause(MemsAudio *audio)
{
CHECK_HAL_ERROR(HAL_SAI_DMAPause(&audioImpl->hSAI_BlockA1), MEMS_AUDIO_ERROR_DMA_PAUSE);
return MEMS_AUDIO_OK;
}
mems_audio_err_t mems_audio_ll_resume(MemsAudio *audio)
{
CHECK_HAL_ERROR(HAL_SAI_DMAResume(&audioImpl->hSAI_BlockA1), MEMS_AUDIO_ERROR_DMA_RESUME);
return MEMS_AUDIO_OK;
}
/**
* @brief SAI1 Initialization Function
* @param None
* @retval None
*/
static mems_audio_err_t MX_SAI1_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
SAI_HandleTypeDef hSAI_BlockA1 = {0};
MemsAudio_STM32L4SAIPDM* impl = audioImpl;
CHECK_MEMS_AUDIO_INITIALIZED(impl);
hSAI_BlockA1.Instance = SAI1_Block_A;
hSAI_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;
hSAI_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
/* The PDM interface provides 8 1-bit samples at a time */
hSAI_BlockA1.Init.DataSize = SAI_DATASIZE_8;
hSAI_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;
hSAI_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
hSAI_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS; /* asynchronous - not chained to other SAI blocks */
hSAI_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; /* Not driving the primary SAI clock */
hSAI_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_DISABLE;
hSAI_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
hSAI_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_FULL;
hSAI_BlockA1.Init.MonoStereoMode = SAI_MONOMODE; /* PDM is intrinsicly stereo, sampling on */
hSAI_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hSAI_BlockA1.Init.PdmInit.Activation = ENABLE; /* Enable PDM interface in the SAI */
hSAI_BlockA1.Init.PdmInit.MicPairsNbr = 1; /* 1 pair - 2 mics */
hSAI_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
hSAI_BlockA1.FrameInit.FrameLength = 16;
hSAI_BlockA1.FrameInit.ActiveFrameLength = 1;
hSAI_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME; /* FS is not really used */
hSAI_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
hSAI_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
hSAI_BlockA1.SlotInit.FirstBitOffset = 0;
hSAI_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hSAI_BlockA1.SlotInit.SlotNumber = 2;
hSAI_BlockA1.SlotInit.SlotActive = 0x0001;
impl->hSAI_BlockA1 = hSAI_BlockA1;
CHECK_HAL_ERROR(HAL_SAI_Init(&impl->hSAI_BlockA1), MEMS_AUDIO_ERROR_SAI_INIT);
CHECK_MEMS_AUDIO_ERROR_LAST();
return MEMS_AUDIO_OK;
}
#define MEMS_AUDIO_DMA_IRQn DMA1_Channel6_IRQn
#define MEMS_AUDIO_DMA_CHANNEL DMA1_Channel6
#define MEMS_AUDIO_DMA_PRIORITY 6
#define DMA_HANDLER DMA1_Channel6_IRQHandler
void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/* SAI1 */
MemsAudio_STM32L4SAIPDM* impl = audioImpl;
if (hsai->Instance == SAI1_Block_A && impl)
{
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_MSI;
PeriphClkInit.PLLSAI1.PLLSAI1M = MEMS_AUDIO_CLOCK_PLLM;
PeriphClkInit.PLLSAI1.PLLSAI1N = MEMS_AUDIO_CLOCK_PLLN;
PeriphClkInit.PLLSAI1.PLLSAI1P = MEMS_AUDIO_CLOCK_PLLP;
PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
CHECK_HAL_ERROR_VOID(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit), MEMS_AUDIO_ERROR_SAI_CLOCK);
if (impl->SAI1_client == 0)
{
__HAL_RCC_SAI1_CLK_ENABLE();
}
impl->SAI1_client++;
/**SAI1_A_Block_A GPIO Configuration
PC3 ------> SAI1_D1
PA3 ------> SAI1_CK1
*/
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_SAI1;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF3_SAI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral DMA init*/
DMA_HandleTypeDef hdma_sai1_a = {0};
hdma_sai1_a.Instance = MEMS_AUDIO_DMA_CHANNEL;
hdma_sai1_a.Init.Request = DMA_REQUEST_SAI1_A;
hdma_sai1_a.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;
hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_sai1_a.Init.Mode = DMA_CIRCULAR;
hdma_sai1_a.Init.Priority = DMA_PRIORITY_HIGH;
impl->hdma_sai1_a = hdma_sai1_a;
CHECK_HAL_ERROR_VOID(HAL_DMA_Init(&impl->hdma_sai1_a), MEMS_AUDIO_ERROR_SAI_DMA_INIT);
/* Several peripheral DMA handle pointers point to the same DMA handle.
Be aware that there is only one channel to perform all the requested DMAs. */
__HAL_LINKDMA(hsai, hdmarx, impl->hdma_sai1_a);
__HAL_LINKDMA(hsai, hdmatx, impl->hdma_sai1_a);
}
}
void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
{
/* SAI1 */
MemsAudio_STM32L4SAIPDM* impl = audioImpl;
if (hsai->Instance == SAI1_Block_A && impl)
{
impl->SAI1_client--;
if (impl->SAI1_client == 0)
{
/* Peripheral clock disable */
__HAL_RCC_SAI1_CLK_DISABLE();
}
/**SAI1_A_Block_A GPIO Configuration
PC3 ------> SAI1_D1
PA3 ------> SAI1_CK1
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3);
/* SAI1 DMA Deinit */
HAL_DMA_DeInit(hsai->hdmarx);
HAL_DMA_DeInit(hsai->hdmatx);
}
}
/**
* @brief Initialize the DMA peripheral
*
*/
static mems_audio_err_t MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(MEMS_AUDIO_DMA_IRQn, MEMS_AUDIO_DMA_PRIORITY, 0);
HAL_NVIC_EnableIRQ(MEMS_AUDIO_DMA_IRQn);
return MEMS_AUDIO_OK;
}
static mems_audio_err_t MX_DMA_Uninit(void)
{
HAL_NVIC_DisableIRQ(MEMS_AUDIO_DMA_IRQn);
return MEMS_AUDIO_OK;
}
/**
* @brief Global handler for the DMA interrupt. Forwards to the HAL for further processing.
*
*/
void DMA_HANDLER(void)
{
HAL_DMA_IRQHandler(&audioImpl->hdma_sai1_a);
}
/**
* @brief Converts PDM samples in the upper half of the PDM buffer.
*
* @param hSai
*/
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hSai)
{
(void)hSai;
pdm2pcm(audioImpl->pdmBuffer, audioImpl->pdmBufferLength>>1);
}
/**
* @brief Converts PDM samples in the upper half of the PDM buffer.
*
* @param hSai
*/
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hSai)
{
(void)hSai;
pdm2pcm(audioImpl->pdmBuffer+(audioImpl->pdmBufferLength>>1), audioImpl->pdmBufferLength>>1);
}
mems_audio_err_t mems_audio_init_stm32l4_sai_pdm(MemsAudio* audio, MemsAudio_STM32L4SAIPDM* impl)
{
uninit();
audioImpl = impl;
impl->audio = audio;
return mems_audio_init(audio);
}

View File

@ -0,0 +1,209 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _MEMS_AUDIO_LL_STM32L4_H_
#define _MEMS_AUDIO_LL_STM32L4_H_
#include <stdbool.h>
#include <assert.h>
#include <stm32l4xx_hal.h>
#include "OpenPDMFilter.h"
#include "MEMS_Audio.h"
#include "MEMS_Audio_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief The SAI PDM interface captures 8 bits from the PDM signal.
*/
typedef uint8_t pdm_sample_t;
/**
* @brief The PDM sample frequency in kHz. (Bit samples per millisecond.)
*/
#define PDM_IN_FREQUENCY_KHZ 1024
#define PDM_IN_FREQUENCY (PDM_IN_FREQUENCY_KHZ * 1000)
/**
* @brief The number of channels of audio captured
*/
#define PDM_IN_CHANNELS 1
/**
* @brief The decimation of the PDM bit stream to produce PCM samples at the desired output rate.
*/
#define PDM_IN_DECIMATION_FACTOR 64
/**
* @brief The number of pdm samples captured per millisecond from the PDM interface.
*/
#define MEMS_AUDIO_PDM_SAMPLES_PER_MS ((PDM_IN_FREQUENCY_KHZ / (sizeof(pdm_sample_t) * 8)) * PDM_IN_CHANNELS)
/**
* @brief The size of the buffer used to hold PDM samples prior to conversion to PCM.
* Each half of the buffer generates an interrupt.
*/
#define MEMS_AUDIO_PDM_BUFFER_LENGTH (MEMS_AUDIO_PDM_SAMPLES_PER_MS * MEMS_AUDIO_MS_BUFFER * 2)
/**
* @brief The length of the PCM buffer required to hold converted samples.
*/
#define MEMS_AUDIO_PCM_BUFFER_LENGTH (PCM_OUT_SAMPLING_FREQUENCY * MEMS_AUDIO_MS_BUFFER / 1000)
/**
* Presently the internal PDM parameters and output PCM parameters are fixed for the values given here.
*/
/**
* @brief 128 point decimation did not work with the OpenPDMFilter and just produced PCM output
* approaching a square wave.
*/
_Static_assert(PDM_IN_DECIMATION_FACTOR == 64 || PDM_IN_DECIMATION_FACTOR == 128, "A decomation factor of 64 or 128 is supported at present.");
/**
* @brief The PDM bitstream frequency divided by the decimation factor should be the same as the desired output PCM frequency.
*/
_Static_assert(PDM_IN_FREQUENCY / PDM_IN_DECIMATION_FACTOR == PCM_OUT_SAMPLING_FREQUENCY, "PDM output frequency should equal the input frequency divided by the decimation factor.");
//
// SAI PDM interface clock configuration
//
#define MEMS_AUDIO_MSI_FREQUENCY (48 * 1000 * 1000)
#define MEMS_AUDIO_CLOCK_PLLM (15)
#define MEMS_AUDIO_CLOCK_PLLN (16)
#define MEMS_AUDIO_CLOCK_PLLP (RCC_PLLP_DIV25)
/**
* @brief The SAI PDM clock should be twice the desired PDM bitstream frequency
*/
_Static_assert((MEMS_AUDIO_MSI_FREQUENCY / MEMS_AUDIO_CLOCK_PLLM * MEMS_AUDIO_CLOCK_PLLN / MEMS_AUDIO_CLOCK_PLLP) == (PDM_IN_FREQUENCY_KHZ * 1000 * 2), "PDM clock should be twice the PDM sample frequency.");
typedef struct MemsAudio_STM32L4SAIPDM_t MemsAudio_STM32L4SAIPDM;
/**
* @brief Callback informing that PDM samples are available for processing.
* @param audio The MemsAudio instance
* @return `false` to skip conversion of PDM to PCM. `true` to convert the PDM samples to PCM.
*/
typedef bool (*pdm_data_available_t)(MemsAudio_STM32L4SAIPDM *audio, pdm_sample_t *pdmSamples, size_t pdmLength);
/**
* @brief Implementation details for the STM32 SAI PDM implementation.
*
*/
/**
* @brief Audio capture from a MEMS microphone on the STM32L4 using the SAI PDM interface.
*/
typedef struct MemsAudio_STM32L4SAIPDM_t {
MemsAudio *audio;
/**
* @brief The last error that happened in a void function (e.g. HAL callback)
*/
mems_audio_err_t lastError;
/**
* @brief The buffer to store PDM audio samples
*/
pdm_sample_t *pdmBuffer;
/**
* @brief The length of the PDM buffer. Should be at least MEMS_AUDIO_PDM_BUFFER_LENGTH
*/
size_t pdmBufferLength;
/**
* @brief Optional callback for when PDM data is available.
*/
pdm_data_available_t pdm_data_available;
/**
* @brief A cound of the number of PDM clients in use.
*/
uint32_t SAI1_client;
/**
* @brief The SAI peripheral handle being used for SAI A subclock 1.
*/
SAI_HandleTypeDef hSAI_BlockA1;
/**
* @brief The DMA handle to transfer SAI data from the peripheral to memory.
*/
DMA_HandleTypeDef hdma_sai1_a;
/**
* @brief An instance of the PDM filter that performs decimation, and high and low pass filtering.
* Unlike the DFSDM peripheral, the SAI PDM interface doesn't perform these operations in hardware.
*/
TPDMFilter_InitStruct filter;
/**
* @brief The number of DMA transfers to ignore after starting recording.
*/
volatile uint16_t discard_dma;
} MemsAudio_STM32L4SAIPDM;
/**
* @brief Creates a MemsAudio instance that retrieves PDM samples from SAI A block 1 via the PDM interface,
* decimates and filters these in software to produce the PCM output stream.
*
* @param audio
* @param implementation
* @return meems_audio_error_t
*/
mems_audio_err_t mems_audio_init_stm32l4_sai_pdm(MemsAudio *audio, MemsAudio_STM32L4SAIPDM *implementation);
/**
* @brief Implementation-specific error codes.
*
*/
typedef enum mems_audio_err_stm32l4_t {
MEMS_AUDIO_ERROR_SAI_DMA_INIT = 1,
MEMS_AUDIO_ERROR_SAI_CLOCK = 2,
MEMS_AUDIO_ERROR_SAI_INIT = 3,
MEMS_AUDIO_ERROR_SAI_DEINIT = 4,
MEMS_AUDIO_ERROR_DMA_START = 5,
MEMS_AUDIO_ERROR_DMA_STOP = 6,
MEMS_AUDIO_ERROR_DMA_PAUSE = 7,
MEMS_AUDIO_ERROR_DMA_RESUME = 8
} mems_audio_err_stm32l4_t;
#ifdef __cplusplus
}
#endif
#endif // _MEMS_AUDIO_LL_STM32L4_H_

View File

@ -0,0 +1,302 @@
/**
*******************************************************************************
* @file OpenPDMFilter.c
* @author CL
* @version V1.0.0
* @date 9-September-2015
* @brief Open PDM audio software decoding Library.
* This Library is used to decode and reconstruct the audio signal
* produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx).
*******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2018 STMicroelectronics</center></h2>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "OpenPDMFilter.h"
/* Functions -----------------------------------------------------------------*/
#ifdef USE_LUT
int32_t filter_table_mono_64(lut_t lut, uint8_t *data, uint8_t sincn) {
return (int32_t)
lut[data[0]][0][sincn] +
lut[data[1]][1][sincn] +
lut[data[2]][2][sincn] +
lut[data[3]][3][sincn] +
lut[data[4]][4][sincn] +
lut[data[5]][5][sincn] +
lut[data[6]][6][sincn] +
lut[data[7]][7][sincn];
}
int32_t filter_table_stereo_64(lut_t lut, uint8_t *data, uint8_t sincn) {
return (int32_t)
lut[data[0]][0][sincn] +
lut[data[2]][1][sincn] +
lut[data[4]][2][sincn] +
lut[data[6]][3][sincn] +
lut[data[8]][4][sincn] +
lut[data[10]][5][sincn] +
lut[data[12]][6][sincn] +
lut[data[14]][7][sincn];
}
#if DECIMATION_MAX == 128
int32_t filter_table_mono_128(lut_t lut, uint8_t *data, uint8_t sincn) {
return (int32_t)
lut[data[0]][0][sincn] +
lut[data[1]][1][sincn] +
lut[data[2]][2][sincn] +
lut[data[3]][3][sincn] +
lut[data[4]][4][sincn] +
lut[data[5]][5][sincn] +
lut[data[6]][6][sincn] +
lut[data[7]][7][sincn] +
lut[data[8]][8][sincn] +
lut[data[9]][9][sincn] +
lut[data[10]][10][sincn] +
lut[data[11]][11][sincn] +
lut[data[12]][12][sincn] +
lut[data[13]][13][sincn] +
lut[data[14]][14][sincn] +
lut[data[15]][15][sincn];
}
int32_t filter_table_stereo_128(lut_t lut, uint8_t *data, uint8_t sincn) {
return (int32_t)
lut[data[0]][0][sincn] +
lut[data[2]][1][sincn] +
lut[data[4]][2][sincn] +
lut[data[6]][3][sincn] +
lut[data[8]][4][sincn] +
lut[data[10]][5][sincn] +
lut[data[12]][6][sincn] +
lut[data[14]][7][sincn] +
lut[data[16]][8][sincn] +
lut[data[18]][9][sincn] +
lut[data[20]][10][sincn] +
lut[data[22]][11][sincn] +
lut[data[24]][12][sincn] +
lut[data[26]][13][sincn] +
lut[data[28]][14][sincn] +
lut[data[30]][15][sincn];
}
#endif
int32_t (*filter_tables_64[2])(lut_t lut, uint8_t *data, uint8_t sincn) = {filter_table_mono_64, filter_table_stereo_64};
#if DECIMATION_MAX == 128
int32_t (*filter_tables_128[2])(lut_t lut, uint8_t *data, uint8_t sincn) = {filter_table_mono_128, filter_table_stereo_128};
#endif
#else
int32_t filter_table(uint8_t *data, uint8_t sincn, TPDMFilter_InitStruct *param) {
uint8_t c, i;
uint16_t data_index = 0;
uint32_t *coef_p = &param->coef[sincn][0];
int32_t F = 0;
uint8_t decimation = param->Decimation;
uint8_t channels = param->In_MicChannels;
for (i = 0; i < decimation; i += 8) {
c = data[data_index];
F += ((c >> 7)) * coef_p[i ] +
((c >> 6) & 0x01) * coef_p[i + 1] +
((c >> 5) & 0x01) * coef_p[i + 2] +
((c >> 4) & 0x01) * coef_p[i + 3] +
((c >> 3) & 0x01) * coef_p[i + 4] +
((c >> 2) & 0x01) * coef_p[i + 5] +
((c >> 1) & 0x01) * coef_p[i + 6] +
((c) & 0x01) * coef_p[i + 7];
data_index += channels;
}
return F;
}
#endif
void convolve(uint32_t Signal[] /* SignalLen */, unsigned short SignalLen,
uint32_t Kernel[] /* KernelLen */, unsigned short KernelLen,
uint32_t Result[] /* SignalLen + KernelLen - 1 */) {
uint16_t n;
for (n = 0; n < SignalLen + KernelLen - 1; n++)
{
unsigned short kmin, kmax, k;
Result[n] = 0;
kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0;
kmax = (n < SignalLen - 1) ? n : SignalLen - 1;
for (k = kmin; k <= kmax; k++) {
Result[n] += Signal[k] * Kernel[n - k];
}
}
}
void Open_PDM_Filter_Init(TPDMFilter_InitStruct *Param) {
uint16_t i, j;
int64_t sum = 0;
uint8_t decimation = Param->Decimation;
for (i = 0; i < SINCN; i++) {
Param->Coef[i] = 0;
Param->bit[i] = 0;
}
for (i = 0; i < decimation; i++) {
Param->sinc1[i] = 1;
}
Param->OldOut = Param->OldIn = Param->OldZ = 0;
Param->LP_ALFA = (Param->LP_HZ != 0 ? (uint16_t)((float)Param->LP_HZ * 256 / (Param->LP_HZ + Param->Fs / (2 * 3.14159))) : 0);
Param->HP_ALFA = (Param->HP_HZ != 0 ? (uint16_t)((float)Param->Fs * 256 / (2 * 3.14159 * Param->HP_HZ + Param->Fs)) : 0);
Param->FilterLen = decimation * SINCN;
Param->sinc[0] = 0;
Param->sinc[decimation * SINCN - 1] = 0;
convolve(Param->sinc1, decimation, Param->sinc1, decimation, Param->sinc2);
convolve(Param->sinc2, (decimation << 1) - 1, Param->sinc1, decimation, &Param->sinc[1]);
for (j = 0; j < SINCN; j++) {
for (i = 0; i < decimation; i++) {
Param->coef[j][i] = Param->sinc[j * decimation + i];
sum += Param->sinc[j * decimation + i];
}
}
Param->sub_const = sum >> 1;
uint32_t div_const = Param->sub_const * Param->MaxVolume / 32768 / FILTER_GAIN;
Param->div_const = (div_const == 0 ? 1 : div_const);
#ifdef USE_LUT
/* Look-Up Table. */
uint16_t c, d, s;
for (s = 0; s < SINCN; s++)
{
uint32_t *coef_p = &Param->coef[s][0];
for (c = 0; c < 256; c++) {
for (d = 0; d < decimation / 8; d++) {
Param->lut[c][d][s] = ((c >> 7)) * coef_p[d * 8 ] +
((c >> 6) & 0x01) * coef_p[d * 8 + 1] +
((c >> 5) & 0x01) * coef_p[d * 8 + 2] +
((c >> 4) & 0x01) * coef_p[d * 8 + 3] +
((c >> 3) & 0x01) * coef_p[d * 8 + 4] +
((c >> 2) & 0x01) * coef_p[d * 8 + 5] +
((c >> 1) & 0x01) * coef_p[d * 8 + 6] +
((c) & 0x01) * coef_p[d * 8 + 7];
}
}
}
#endif
}
int Open_PDM_Filter_64(uint8_t *data, int16_t *dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) {
uint8_t i, data_out_index;
uint8_t channels = Param->In_MicChannels;
uint8_t data_inc = ((DECIMATION_MAX >> 4) * channels);
int64_t Z, Z0, Z1, Z2;
int64_t OldOut, OldIn, OldZ;
OldOut = Param->OldOut;
OldIn = Param->OldIn;
OldZ = Param->OldZ;
#ifdef USE_LUT
uint8_t j = channels - 1;
#endif
for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) {
#ifdef USE_LUT
Z0 = filter_tables_64[j](Param->lut, data, 0);
Z1 = filter_tables_64[j](Param->lut, data, 1);
Z2 = filter_tables_64[j](Param->lut, data, 2);
#else
Z0 = filter_table(data, 0, Param);
Z1 = filter_table(data, 1, Param);
Z2 = filter_table(data, 2, Param);
#endif
Z = Param->Coef[1] + Z2 - Param->sub_const;
Param->Coef[1] = Param->Coef[0] + Z1;
Param->Coef[0] = Z0;
OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8;
OldIn = Z;
OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8;
Z = OldZ * volume;
Z = RoundDiv(Z, (Param->div_const));
Z = SaturaLH(Z, -32700, 32700);
dataOut[data_out_index] = Z;
data += data_inc;
}
Param->OldOut = OldOut;
Param->OldIn = OldIn;
Param->OldZ = OldZ;
return data_out_index;
}
#if DECIMATION_MAX == 128
int Open_PDM_Filter_128(uint8_t *data, int16_t *dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) {
uint8_t i, data_out_index;
uint8_t channels = Param->In_MicChannels;
uint8_t data_inc = ((DECIMATION_MAX >> 3) * channels);
int64_t Z, Z0, Z1, Z2;
int64_t OldOut, OldIn, OldZ;
OldOut = Param->OldOut;
OldIn = Param->OldIn;
OldZ = Param->OldZ;
#ifdef USE_LUT
uint8_t j = channels - 1;
#endif
for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) {
#ifdef USE_LUT
Z0 = filter_tables_128[j](Param->lut, data, 0);
Z1 = filter_tables_128[j](Param->lut, data, 1);
Z2 = filter_tables_128[j](Param->lut, data, 2);
#else
Z0 = filter_table(data, 0, Param);
Z1 = filter_table(data, 1, Param);
Z2 = filter_table(data, 2, Param);
#endif
Z = Param->Coef[1] + Z2 - Param->sub_const;
Param->Coef[1] = Param->Coef[0] + Z1;
Param->Coef[0] = Z0;
OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8;
OldIn = Z;
OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8;
Z = OldZ * volume;
Z = RoundDiv(Z, (Param->div_const));
Z = SaturaLH(Z, -32700, 32700);
dataOut[data_out_index] = Z;
data += data_inc;
}
Param->OldOut = OldOut;
Param->OldIn = OldIn;
Param->OldZ = OldZ;
return data_out_index;
}
#endif

View File

@ -0,0 +1,112 @@
/**
*******************************************************************************
* @file OpenPDMFilter.h
* @author CL
* @version V1.0.0
* @date 9-September-2015
* @brief Header file for Open PDM audio software decoding Library.
* This Library is used to decode and reconstruct the audio signal
* produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx).
*******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2018 STMicroelectronics</center></h2>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __OPENPDMFILTER_H
#define __OPENPDMFILTER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/* Definitions ---------------------------------------------------------------*/
/*
* Enable to use a Look-Up Table to improve performances while using more FLASH
* and RAM memory.
* Note: Without Look-Up Table up to stereo@16KHz configuration is supported.
*/
#define USE_LUT
#define SINCN 3
#define DECIMATION_MAX 128 // can be 128 but this didn't work for me
#define FILTER_GAIN 16
#define HTONS(A) ((((uint16_t)(A) & 0xff00) >> 8) | \
(((uint16_t)(A) & 0x00ff) << 8))
#define RoundDiv(a, b) (((a) > 0) ? (((a) + (b) / 2) / (b)) : (((a) - (b) / 2) / (b)))
#define SaturaLH(N, L, H) (((N) < (L)) ? (L) : (((N) > (H)) ? (H) : (N)))
/* Types ---------------------------------------------------------------------*/
typedef int32_t lut_t[256][DECIMATION_MAX / 8][SINCN];
typedef struct
{
/* Public */
uint16_t LP_HZ;
uint16_t HP_HZ;
uint16_t Fs;
unsigned int nSamples;
uint8_t In_MicChannels;
uint8_t Out_MicChannels;
uint8_t Decimation;
uint8_t MaxVolume;
/* Private */
uint32_t Coef[SINCN];
uint16_t FilterLen;
int64_t OldOut, OldIn, OldZ;
uint16_t LP_ALFA;
uint16_t HP_ALFA;
uint16_t bit[5];
uint16_t byte;
uint32_t div_const;
int64_t sub_const;
uint32_t sinc[DECIMATION_MAX * SINCN];
uint32_t sinc1[DECIMATION_MAX];
uint32_t sinc2[DECIMATION_MAX * 2];
uint32_t coef[SINCN][DECIMATION_MAX];
#ifdef USE_LUT
lut_t lut;
#endif
} TPDMFilter_InitStruct;
/* Exported functions ------------------------------------------------------- */
void Open_PDM_Filter_Init(TPDMFilter_InitStruct *init_struct);
int Open_PDM_Filter_64(uint8_t *data, int16_t *data_out, uint16_t mic_gain, TPDMFilter_InitStruct *init_struct);
#if DECIMATION_MAX == 128
int Open_PDM_Filter_128(uint8_t *data, int16_t *data_out, uint16_t mic_gain, TPDMFilter_InitStruct *init_struct);
#endif
#ifdef __cplusplus
}
#endif
#endif // __OPENPDMFILTER_H
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,199 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdint.h>
#include "common-hal/audiobusio/PDMIn.h"
#include "shared-bindings/audiobusio/PDMIn.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "py/runtime.h"
#include "supervisor/memory.h"
#include "MEMS_Audio_ll_stm32l4.h"
MemsAudio memsAudio;
MemsAudio_STM32L4SAIPDM memsAudioImpl;
pdm_sample_t pdmBuffer[MEMS_AUDIO_PDM_BUFFER_LENGTH];
audiobusio_pdmin_obj_t *instance;
static bool pdm_data_available(MemsAudio_STM32L4SAIPDM *impl, uint8_t *pdmBuffer, size_t pdmBufferLength);
// Caller validates that pins are free.
void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
const mcu_pin_obj_t *clock_pin,
const mcu_pin_obj_t *data_pin,
uint32_t sample_rate,
uint8_t bit_depth,
bool mono,
uint8_t oversample) {
self->sample_rate = sample_rate;
self->mono = mono;
self->oversample = oversample;
self->recording_complete = true;
if (!mono) {
mp_raise_ValueError(translate("only mono is supported"));
}
if (sample_rate != 16000) {
mp_raise_ValueError(translate("only sample_rate=16000 is supported"));
}
if (bit_depth != 16) {
mp_raise_ValueError(translate("only bit_depth=16 is supported"));
}
if (oversample != 64) {
mp_raise_ValueError(translate("only oversample=64 is supported"));
}
// wait for the previous instance to finish.
if (instance) {
common_hal_audiobusio_pdmin_deinit(instance);
}
instance = self;
memset(&memsAudio, 0, sizeof(memsAudio));
memset(&memsAudioImpl, 0, sizeof(memsAudioImpl));
common_hal_mcu_pin_claim(clock_pin);
self->clock_pin = clock_pin;
common_hal_mcu_pin_claim(data_pin);
self->data_pin = data_pin;
self->audio = &memsAudio;
self->audio_impl = &memsAudioImpl;
self->audio_impl->pdmBuffer = pdmBuffer;
self->audio_impl->pdmBufferLength = sizeof(pdmBuffer) / sizeof(pdmBuffer[0]);
self->audio_impl->pdm_data_available = pdm_data_available;
mems_audio_init_stm32l4_sai_pdm(self->audio, self->audio_impl);
mems_audio_record(self->audio);
mems_audio_pause(self->audio);
}
bool common_hal_audiobusio_pdmin_deinited(audiobusio_pdmin_obj_t *self) {
return self->clock_pin == NULL;
}
void wait_dma_complete(audiobusio_pdmin_obj_t *self) {
while (!self->recording_complete) {
MICROPY_VM_HOOK_LOOP;
}
}
void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t *self) {
if (instance != self) {
return;
}
instance = NULL;
if (self->audio) {
wait_dma_complete(self);
mems_audio_stop(self->audio);
mems_audio_uninit(self->audio);
self->audio = NULL;
self->audio_impl = NULL;
}
if (self->data_pin) {
common_hal_reset_pin(self->data_pin);
self->data_pin = NULL;
}
if (self->clock_pin) {
common_hal_reset_pin(self->clock_pin);
self->clock_pin = NULL;
}
}
uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t *self) {
return 16;
}
uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t *self) {
return 16000;
}
static bool pdm_data_available(MemsAudio_STM32L4SAIPDM *impl, uint8_t *pdmBuffer, size_t pdmBufferLength) {
// update the filter with the correct number of samples
audiobusio_pdmin_obj_t *pdmIn = (audiobusio_pdmin_obj_t *)(impl->audio->userData);
MemsAudio *audio = impl->audio;
uint32_t pcmSamplesAvailable = pdmBufferLength * 8 / PDM_IN_DECIMATION_FACTOR;
if (pcmSamplesAvailable > audio->pcmOutputBufferLength) {
pcmSamplesAvailable = audio->pcmOutputBufferLength;
}
// ensure the filter doesn't try to produce more samples than available
pdmIn->audio_impl->filter.nSamples = pcmSamplesAvailable;
return pcmSamplesAvailable > 0;
}
static void pcm_data_available(MemsAudio *audio, int16_t *pcmBuffer, size_t pcmBufferLength) {
// data is already in the output buffer
audiobusio_pdmin_obj_t *pdmIn = (audiobusio_pdmin_obj_t *)(audio->userData);
// if DMA copies more data than will fit into the output buffer, crop the length to what will fit
if (audio->pcmOutputBufferLength < pcmBufferLength) {
pcmBufferLength = audio->pcmOutputBufferLength;
}
audio->pcmOutputBuffer += pcmBufferLength;
audio->pcmOutputBufferLength -= pcmBufferLength;
if (audio->pcmOutputBufferLength == 0) {
pdmIn->recording_complete = true;
mems_audio_pause(audio);
}
}
uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self,
uint16_t *output_buffer, uint32_t output_buffer_length) {
MemsAudio *audio = self->audio;
wait_dma_complete(self);
audio->pcmOutputBuffer = (int16_t *)output_buffer;
audio->pcmOutputBufferLength = output_buffer_length;
audio->pcm_data_available = pcm_data_available;
audio->userData = self; /// reference back to the PDMIn instance
self->recording_complete = false;
mems_audio_err_t err = mems_audio_resume(audio);
if (!IS_MEMS_AUDIO_ERROR(err)) {
wait_dma_complete(self);
}
mems_audio_pause(audio);
int samples_output = (int)(output_buffer_length) - audio->pcmOutputBufferLength;
// convert from signed to unsigned (min-point moves from 0 to 32k)
for (int i = 0; i < samples_output; i++) {
output_buffer[i] += 0x8000;
}
return samples_output;
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Matthew McGowan for Blues Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM_COMMON_HAL_AUDIOBUSIO_AUDIOOUT_H
#define MICROPY_INCLUDED_STM_COMMON_HAL_AUDIOBUSIO_AUDIOOUT_H
#include <stdint.h>
#include "py/obj.h"
#include "peripherals/pins.h"
#include "supervisor/memory.h"
typedef struct MemsAudio_t MemsAudio;
typedef struct MemsAudio_STM32L4SAIPDM_t MemsAudio_STM32L4SAIPDM;
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *clock_pin;
const mcu_pin_obj_t *data_pin;
uint32_t sample_rate;
uint8_t bit_depth;
bool mono;
uint8_t oversample;
supervisor_allocation *audio_allocation;
MemsAudio *audio;
MemsAudio_STM32L4SAIPDM *audio_impl;
/**
* @brief Flag to indicate from the ISR that recording is complete.
*/
volatile bool recording_complete;
} audiobusio_pdmin_obj_t;
#endif

View File

@ -106,7 +106,8 @@ void pulsein_reset(void) {
memset(callback_obj_ref, 0, sizeof(callback_obj_ref));
HAL_TIM_Base_DeInit(&tim_handle);
tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance));
// tim_clock_disable() takes a bitmask of timers.
tim_clock_disable(1 << stm_peripherals_timer_get_index(tim_handle.Instance));
memset(&tim_handle, 0, sizeof(tim_handle));
refcount = 0;
}

View File

@ -36,23 +36,24 @@
#include "timers.h"
#define ALL_CLOCKS 0xFFFF
STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
// Bitmask of channels taken.
STATIC uint8_t tim_channels_taken[TIM_BANK_ARRAY_LEN];
// Initial frequency timer is set to.
STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN];
STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN];
STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) {
// duty cycle is duty/0xFFFF fraction x (number of pulses per period)
return (duty * period) / ((1 << 16) - 1);
return (duty * period) / 0xffff;
}
STATIC bool timer_get_optimal_divisors(uint32_t *period, uint32_t *prescaler,
uint32_t frequency, uint32_t source_freq) {
// Find the largest possible period supported by this frequency
for (int i = 0; i < (1 << 16); i++) {
*prescaler = 0;
for (uint32_t i = 1; i <= 0xffff; i++) {
*period = source_freq / (i * frequency);
if (*period < (1 << 16) && *period >= 2) {
if (*period <= 0xffff && *period >= 2) {
*prescaler = i;
break;
}
@ -62,13 +63,10 @@ STATIC bool timer_get_optimal_divisors(uint32_t *period, uint32_t *prescaler,
}
void pwmout_reset(void) {
uint16_t never_reset_mask = 0x00;
for (int i = 0; i < TIM_BANK_ARRAY_LEN; i++) {
if (!never_reset_tim[i]) {
reserved_tim[i] = 0x00;
tim_frequencies[i] = 0x00;
} else {
never_reset_mask |= 1 << i;
tim_channels_taken[i] = 0x00;
tim_frequencies[i] = 0;
}
}
}
@ -78,73 +76,69 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
uint16_t duty,
uint32_t frequency,
bool variable_frequency) {
TIM_TypeDef *TIMx;
uint8_t tim_num = MP_ARRAY_SIZE(mcu_tim_pin_list);
bool tim_taken_internal = false;
bool tim_chan_taken = false;
bool tim_taken_f_mismatch = false;
bool var_freq_mismatch = false;
// Default error is no timer at all on pin.
pwmout_result_t last_failure = PWMOUT_INVALID_PIN;
bool first_time_setup = true;
for (uint i = 0; i < tim_num; i++) {
const mcu_tim_pin_obj_t *l_tim = &mcu_tim_pin_list[i];
uint8_t l_tim_index = l_tim->tim_index;
uint8_t l_tim_channel = l_tim->channel_index;
uint8_t tim_index;
uint8_t tim_channel_index;
self->tim = NULL;
for (uint i = 0; i < MP_ARRAY_SIZE(mcu_tim_pin_list); i++) {
const mcu_tim_pin_obj_t *tim = &mcu_tim_pin_list[i];
tim_index = tim->tim_index;
tim_channel_index = tim->channel_index;
// if pin is same
if (l_tim->pin == pin) {
if (tim->pin == pin) {
// check if the timer has a channel active, or is reserved by main timer system
if (l_tim_index < TIM_BANK_ARRAY_LEN && reserved_tim[l_tim_index] != 0) {
if (tim_index < TIM_BANK_ARRAY_LEN && tim_channels_taken[tim_index] != 0) {
// Timer has already been reserved by an internal module
if (stm_peripherals_timer_is_reserved(mcu_tim_banks[l_tim_index])) {
tim_taken_internal = true;
if (stm_peripherals_timer_is_reserved(mcu_tim_banks[tim_index])) {
last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
continue; // keep looking
}
// is it the same channel? (or all channels reserved by a var-freq)
if (reserved_tim[l_tim_index] & 1 << (l_tim_channel)) {
tim_chan_taken = true;
if (tim_channels_taken[tim_index] & (1 << tim_channel_index)) {
last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
continue; // keep looking, might be another viable option
}
// If the frequencies are the same it's ok
if (tim_frequencies[l_tim_index] != frequency) {
tim_taken_f_mismatch = true;
if (tim_frequencies[tim_index] != frequency) {
last_failure = PWMOUT_INVALID_FREQUENCY_ON_PIN;
continue; // keep looking
}
// you can't put a variable frequency on a partially reserved timer
if (variable_frequency) {
var_freq_mismatch = true;
last_failure = PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE;
continue; // keep looking
}
first_time_setup = false; // skip setting up the timer
}
// No problems taken, so set it up
self->tim = l_tim;
self->tim = tim;
break;
}
}
TIM_TypeDef *TIMx;
// handle valid/invalid timer instance
if (self->tim != NULL) {
// create instance
TIMx = mcu_tim_banks[self->tim->tim_index];
TIMx = mcu_tim_banks[tim_index];
// reserve timer/channel
if (variable_frequency) {
reserved_tim[self->tim->tim_index] = 0x0F;
// Take all the channels.
tim_channels_taken[tim_index] = 0x0F;
} else {
reserved_tim[self->tim->tim_index] |= 1 << self->tim->channel_index;
tim_channels_taken[tim_index] |= 1 << tim_channel_index;
}
tim_frequencies[self->tim->tim_index] = frequency;
tim_frequencies[tim_index] = frequency;
stm_peripherals_timer_reserve(TIMx);
} else { // no match found
if (tim_chan_taken || tim_taken_internal) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
} else if (tim_taken_f_mismatch) {
return PWMOUT_INVALID_FREQUENCY_ON_PIN;
} else if (var_freq_mismatch) {
return PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE;
} else {
return PWMOUT_INVALID_PIN;
}
} else {
// no match found
return last_failure;
}
uint32_t prescaler = 0; // prescaler is 15 bit
@ -163,10 +157,10 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
self->pin = pin;
tim_clock_enable(1 << (self->tim->tim_index));
tim_clock_enable(1 << tim_index);
// translate channel into handle value
self->channel = 4 * self->tim->channel_index;
// translate channel into handle value: TIM_CHANNEL_1, _2, _3, _4.
self->channel = 4 * tim_channel_index;
// Timer init
self->handle.Instance = TIMx;
@ -175,6 +169,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
self->handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
self->handle.Init.CounterMode = TIM_COUNTERMODE_UP;
self->handle.Init.RepetitionCounter = 0;
self->handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
// only run init if this is the first instance of this timer
if (first_time_setup) {
@ -232,15 +227,15 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
}
// var freq shuts down entire timer, others just their channel
if (self->variable_frequency) {
reserved_tim[self->tim->tim_index] = 0x00;
tim_channels_taken[self->tim->tim_index] = 0x00;
} else {
reserved_tim[self->tim->tim_index] &= ~(1 << self->tim->channel_index);
tim_channels_taken[self->tim->tim_index] &= ~(1 << self->tim->channel_index);
HAL_TIM_PWM_Stop(&self->handle, self->channel);
}
common_hal_reset_pin(self->pin);
// if reserved timer has no active channels, we can disable it
if (reserved_tim[self->tim->tim_index] == 0) {
if (tim_channels_taken[self->tim->tim_index] == 0) {
tim_frequencies[self->tim->tim_index] = 0x00;
stm_peripherals_timer_free(self->handle.Instance);
}

View File

@ -39,12 +39,12 @@ typedef struct {
TIM_HandleTypeDef handle;
TIM_OC_InitTypeDef chan_handle;
const mcu_tim_pin_obj_t *tim;
uint8_t channel : 7;
bool variable_frequency : 1;
uint16_t duty_cycle;
uint32_t frequency;
uint32_t period;
const mcu_pin_obj_t *pin;
uint16_t duty_cycle;
uint8_t channel;
bool variable_frequency;
} pwmio_pwmout_obj_t;
void pwmout_reset(void);

View File

@ -150,26 +150,65 @@ static size_t irq_map[] = {
};
// Get the frequency (in Hz) of the source clock for the given timer.
// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set.
// If the APB prescaler is 1, then the timer clock is equal to its respective
// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its
// respective APB clock. See DM00031020 Rev 4, page 115.
//
// From STM ref manual: DM00031020 Rev 19, section 7.2, page 217:
//
// The timer clock frequencies for STM32F405xx/07xx and STM32F415xx/17xx are
// automatically set by hardware. There are two cases:
// 1. If the APB prescaler is 1, the timer clock frequencies are set to the same frequency as
// that of the APB domain to which the timers are connected.
// 2. Otherwise, they are set to twice (×2) the frequency of the APB domain to which the
// timers are connected.
// From STM ref manual: DM00031020 Rev 19, section 6.2, page 153:
//
// The timer clock frequencies for STM32F42xxx and STM32F43xxx are automatically set by
// hardware. There are two cases depending on the value of TIMPRE bit in RCC_CFGR [sic - should be RCC_DKCFGR]
// register:
// * If TIMPRE bit in RCC_DKCFGR register is reset:
// If the APB prescaler is configured to a division factor of 1, the timer clock frequencies
// (TIMxCLK) are set to PCLKx. Otherwise, the timer clock frequencies are twice the
// frequency of the APB domain to which the timers are connected: TIMxCLK = 2xPCLKx.
// * If TIMPRE bit in RCC_DKCFGR register is set:
// If the APB prescaler is configured to a division factor of 1, 2 or 4, the timer clock
// frequencies (TIMxCLK) are set to HCLK. Otherwise, the timer clock frequencies is four
// times the frequency of the APB domain to which the timers are connected: TIMxCLK = 4xPCLKx.
uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef *timer) {
size_t tim_id = stm_peripherals_timer_get_index(timer);
// The timer index starts at 0, but the timer numbers start at TIM1.
size_t tim_id = stm_peripherals_timer_get_index(timer) + 1;
uint32_t source, clk_div;
if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
// TIM{1,8,9,10,11} are on APB2
source = HAL_RCC_GetPCLK2Freq();
clk_div = RCC->CFGR & RCC_CFGR_PPRE2;
// 0b0xx means not divided; 0b100 is divide by 2; 0b101 by 4; 0b110 by 8; 0b111 by 16.
clk_div = (RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos;
} else {
// TIM{2,3,4,5,6,7,12,13,14} are on APB1
source = HAL_RCC_GetPCLK1Freq();
clk_div = RCC->CFGR & RCC_CFGR_PPRE1;
// 0b0xx means not divided; 0b100 is divide by 2; 0b101 by 4; 0b110 by 8; 0b111 by 16.
clk_div = (RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos;
}
if (clk_div != 0) {
// APB prescaler for this timer is > 1
// Only some STM32's have TIMPRE.
#if defined(RCC_CFGR_TIMPRE)
uint32_t timpre = RCC->DCKCFGR & RCC_CFGR_TIMPRE;
if (timpre == 0) {
if (clk_div >= 0b100) {
source *= 2;
}
} else {
if (clk_div > 0b101) {
source *= 4;
} else {
source = HAL_RCC_GetHCLKFreq();
}
}
#else
if (clk_div >= 0b100) {
source *= 2;
}
#endif
return source;
}
@ -271,6 +310,7 @@ bool stm_peripherals_timer_is_reserved(TIM_TypeDef *instance) {
return stm_timer_reserved[tim_idx];
}
// Note this returns a timer index starting at zero, corresponding to TIM1.
size_t stm_peripherals_timer_get_index(TIM_TypeDef *instance) {
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
if (instance == mcu_tim_banks[i]) {

View File

@ -32,6 +32,13 @@
extern const mp_obj_type_t pixelbuf_pixelbuf_type;
typedef union {
struct {
uint8_t r, g, b, w;
};
uint32_t rgbw;
} color_u;
void common_hal_adafruit_pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size_t n,
pixelbuf_byteorder_details_t *byteorder, mp_float_t brightness, bool auto_write, uint8_t *header,
size_t header_len, uint8_t *trailer, size_t trailer_len);

View File

@ -36,6 +36,10 @@
#include "shared-bindings/analogio/AnalogIn.h"
#include "shared-bindings/util.h"
MP_WEAK const mcu_pin_obj_t *common_hal_analogio_analogin_validate_pin(mp_obj_t obj) {
return validate_obj_is_free_pin(obj);
}
//| class AnalogIn:
//| """Read analog voltage levels
//|
@ -60,8 +64,7 @@ STATIC mp_obj_t analogio_analogin_make_new(const mp_obj_type_t *type,
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// 1st argument is the pin
const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
const mcu_pin_obj_t *pin = common_hal_analogio_analogin_validate_pin(args[0]);
analogio_analogin_obj_t *self = m_new_obj(analogio_analogin_obj_t);
self->base.type = &analogio_analogin_type;
common_hal_analogio_analogin_construct(self, pin);

View File

@ -32,6 +32,7 @@
extern const mp_obj_type_t analogio_analogin_type;
const mcu_pin_obj_t *common_hal_analogio_analogin_validate_pin(mp_obj_t obj);
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, const mcu_pin_obj_t *pin);
void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self);
bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self);

View File

@ -66,6 +66,10 @@ STATIC void check_result(digitalinout_result_t result) {
}
}
MP_WEAK const mcu_pin_obj_t *common_hal_digitalio_validate_pin(mp_obj_t obj) {
return validate_obj_is_free_pin(obj);
}
//| class DigitalInOut:
//| """Digital input and output
//|
@ -87,14 +91,7 @@ STATIC mp_obj_t digitalio_digitalinout_make_new(const mp_obj_type_t *type,
digitalio_digitalinout_obj_t *self = m_new_obj(digitalio_digitalinout_obj_t);
self->base.type = &digitalio_digitalinout_type;
#if CIRCUITPY_CYW43
// The GPIO pin attached to the CYW43 co-processor can only be used for
// DigitalInOut, not for other purposes like PWM. That's why this check
// is here, and it's not rolled into validate_obj_is_free_pin.
const mcu_pin_obj_t *pin = validate_obj_is_free_pin_including_cyw43(args[0]);
#else
const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
#endif
const mcu_pin_obj_t *pin = common_hal_digitalio_validate_pin(args[0]);
common_hal_digitalio_digitalinout_construct(self, pin);
return MP_OBJ_FROM_PTR(self);

View File

@ -55,6 +55,7 @@ typedef enum {
DIGITALINOUT_REG_TOGGLE,
} digitalinout_reg_op_t;
const mcu_pin_obj_t *common_hal_digitalio_validate_pin(mp_obj_t obj);
digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin);
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self);
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self);

View File

@ -159,7 +159,7 @@ STATIC mp_obj_t i2ctarget_i2c_target_request(size_t n_args, const mp_obj_t *pos_
bool forever = false;
uint64_t timeout_end = 0;
if (timeout_ms <= 0) {
if (timeout_ms == 0) {
forever = true;
} else if (timeout_ms > 0) {
timeout_end = common_hal_time_monotonic_ms() + timeout_ms;

View File

@ -109,6 +109,9 @@ MP_PROPERTY_GETSET(vectorio_circle_color_index_obj,
//| y: int
//| """Y position of the center point of the circle in the parent."""
//|
//| hidden: bool
//| """Hide the circle or not."""
//|
//| location: Tuple[int, int]
//| """(X,Y) position of the center point of the circle in the parent."""
//|
@ -123,6 +126,7 @@ STATIC const mp_rom_map_elem_t vectorio_circle_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_radius), MP_ROM_PTR(&vectorio_circle_radius_obj) },
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&vectorio_vector_shape_y_obj) },
{ MP_ROM_QSTR(MP_QSTR_hidden), MP_ROM_PTR(&vectorio_vector_shape_hidden_obj) },
{ MP_ROM_QSTR(MP_QSTR_color_index), MP_ROM_PTR(&vectorio_circle_color_index_obj) },
{ MP_ROM_QSTR(MP_QSTR_location), MP_ROM_PTR(&vectorio_vector_shape_location_obj) },
{ MP_ROM_QSTR(MP_QSTR_pixel_shader), MP_ROM_PTR(&vectorio_vector_shape_pixel_shader_obj) },

View File

@ -118,6 +118,9 @@ MP_PROPERTY_GETSET(vectorio_polygon_color_index_obj,
//| y: int
//| """Y position of the 0,0 origin in the points list."""
//|
//| hidden: bool
//| """Hide the polygon or not."""
//|
//| location: Tuple[int, int]
//| """(X,Y) position of the 0,0 origin in the points list."""
//|
@ -132,6 +135,7 @@ STATIC const mp_rom_map_elem_t vectorio_polygon_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_points), MP_ROM_PTR(&vectorio_polygon_points_obj) },
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&vectorio_vector_shape_y_obj) },
{ MP_ROM_QSTR(MP_QSTR_hidden), MP_ROM_PTR(&vectorio_vector_shape_hidden_obj) },
{ MP_ROM_QSTR(MP_QSTR_color_index), MP_ROM_PTR(&vectorio_polygon_color_index_obj) },
{ MP_ROM_QSTR(MP_QSTR_location), MP_ROM_PTR(&vectorio_vector_shape_location_obj) },
{ MP_ROM_QSTR(MP_QSTR_pixel_shader), MP_ROM_PTR(&vectorio_vector_shape_pixel_shader_obj) },

View File

@ -139,6 +139,9 @@ const mp_obj_property_t vectorio_rectangle_color_index_obj = {
//| y: int
//| """Y position of the top left corner of the rectangle in the parent."""
//|
//| hidden: bool
//| """Hide the rectangle or not."""
//|
//| location: Tuple[int, int]
//| """(X,Y) position of the top left corner of the rectangle in the parent."""
//|
@ -152,6 +155,7 @@ STATIC const mp_rom_map_elem_t vectorio_rectangle_locals_dict_table[] = {
// Properties
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&vectorio_vector_shape_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&vectorio_vector_shape_y_obj) },
{ MP_ROM_QSTR(MP_QSTR_hidden), MP_ROM_PTR(&vectorio_vector_shape_hidden_obj) },
{ MP_ROM_QSTR(MP_QSTR_color_index), MP_ROM_PTR(&vectorio_rectangle_color_index_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&vectorio_rectangle_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&vectorio_rectangle_height_obj) },

View File

@ -181,6 +181,33 @@ MP_PROPERTY_GETSET(vectorio_vector_shape_location_obj,
(mp_obj_t)&vectorio_vector_shape_set_location_obj);
// Stub checker does not approve of these shared properties.
// hidden: bool
// """Hide the shape or not."""
//
STATIC mp_obj_t vectorio_vector_shape_obj_get_hidden(mp_obj_t wrapper_shape) {
// Relies on the fact that only vector_shape impl gets matched with a VectorShape.
const vectorio_draw_protocol_t *draw_protocol = mp_proto_get(MP_QSTR_protocol_draw, wrapper_shape);
vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(draw_protocol->draw_get_protocol_self(wrapper_shape));
return mp_obj_new_bool(common_hal_vectorio_vector_shape_get_hidden(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(vectorio_vector_shape_get_hidden_obj, vectorio_vector_shape_obj_get_hidden);
STATIC mp_obj_t vectorio_vector_shape_obj_set_hidden(mp_obj_t wrapper_shape, mp_obj_t hidden_obj) {
// Relies on the fact that only vector_shape impl gets matched with a VectorShape.
const vectorio_draw_protocol_t *draw_protocol = mp_proto_get(MP_QSTR_protocol_draw, wrapper_shape);
vectorio_vector_shape_t *self = MP_OBJ_TO_PTR(draw_protocol->draw_get_protocol_self(wrapper_shape));
common_hal_vectorio_vector_shape_set_hidden(self, mp_obj_is_true(hidden_obj));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(vectorio_vector_shape_set_hidden_obj, vectorio_vector_shape_obj_set_hidden);
MP_PROPERTY_GETSET(vectorio_vector_shape_hidden_obj,
(mp_obj_t)&vectorio_vector_shape_get_hidden_obj,
(mp_obj_t)&vectorio_vector_shape_set_hidden_obj);
// pixel_shader: Union[ColorConverter, Palette]
// """The pixel shader of the shape."""
//

View File

@ -31,6 +31,9 @@ void common_hal_vectorio_vector_shape_set_location(vectorio_vector_shape_t *self
mp_int_t common_hal_vectorio_vector_shape_get_y(vectorio_vector_shape_t *self);
void common_hal_vectorio_vector_shape_set_y(vectorio_vector_shape_t *self, mp_int_t y);
mp_int_t common_hal_vectorio_vector_shape_get_hidden(vectorio_vector_shape_t *self);
void common_hal_vectorio_vector_shape_set_hidden(vectorio_vector_shape_t *self, bool hidden);
mp_obj_t common_hal_vectorio_vector_shape_get_pixel_shader(vectorio_vector_shape_t *self);
void common_hal_vectorio_vector_shape_set_pixel_shader(vectorio_vector_shape_t *self, mp_obj_t pixel_shader);
@ -40,6 +43,7 @@ void vectorio_vector_shape_update_transform(vectorio_vector_shape_t *self, displ
extern vectorio_draw_protocol_impl_t vectorio_vector_shape_draw_protocol_impl;
extern const mp_obj_property_getset_t vectorio_vector_shape_x_obj;
extern const mp_obj_property_getset_t vectorio_vector_shape_y_obj;
extern const mp_obj_property_getset_t vectorio_vector_shape_hidden_obj;
extern const mp_obj_property_getset_t vectorio_vector_shape_location_obj;
extern const mp_obj_property_getset_t vectorio_vector_shape_pixel_shader_obj;
extern const mp_obj_fun_builtin_fixed_t vectorio_vector_shape_contains_obj;

View File

@ -143,8 +143,10 @@ void common_hal_adafruit_pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_f
STATIC uint8_t _pixelbuf_get_as_uint8(mp_obj_t obj) {
if (mp_obj_is_small_int(obj)) {
return MP_OBJ_SMALL_INT_VALUE(obj);
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
} else if (mp_obj_is_int(obj)) {
return mp_obj_get_int_truncated(obj);
#endif
} else if (mp_obj_is_float(obj)) {
return (uint8_t)mp_obj_get_float(obj);
}
@ -152,55 +154,56 @@ STATIC uint8_t _pixelbuf_get_as_uint8(mp_obj_t obj) {
translate("can't convert %q to %q"), mp_obj_get_type_qstr(obj), MP_QSTR_int);
}
static void pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t *self, mp_obj_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *w) {
STATIC color_u _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t *self, mp_obj_t color) {
color_u result;
pixelbuf_byteorder_details_t *byteorder = &self->byteorder;
// w is shared between white in NeoPixels and brightness in dotstars (so that DotStars can have
// per-pixel brightness). Set the defaults here in case it isn't set below.
if (byteorder->is_dotstar) {
*w = 255;
result.w = 255;
} else {
*w = 0;
result.w = 0;
}
if (mp_obj_is_int(color) || mp_obj_is_float(color)) {
mp_int_t value = mp_obj_is_int(color) ? mp_obj_get_int_truncated(color) : (mp_int_t)mp_obj_get_float(color);
*r = value >> 16 & 0xff;
*g = (value >> 8) & 0xff;
*b = value & 0xff;
result.r = value >> 16 & 0xff;
result.g = (value >> 8) & 0xff;
result.b = value & 0xff;
} else {
mp_obj_t *items;
size_t len;
mp_obj_get_array(color, &len, &items);
mp_arg_validate_length_range(len, 3, 4, MP_QSTR_color);
*r = _pixelbuf_get_as_uint8(items[PIXEL_R]);
*g = _pixelbuf_get_as_uint8(items[PIXEL_G]);
*b = _pixelbuf_get_as_uint8(items[PIXEL_B]);
result.r = _pixelbuf_get_as_uint8(items[PIXEL_R]);
result.g = _pixelbuf_get_as_uint8(items[PIXEL_G]);
result.b = _pixelbuf_get_as_uint8(items[PIXEL_B]);
if (len > 3) {
if (mp_obj_is_float(items[PIXEL_W])) {
*w = 255 * mp_obj_get_float(items[PIXEL_W]);
result.w = 255 * mp_obj_get_float(items[PIXEL_W]);
} else {
*w = mp_obj_get_int_truncated(items[PIXEL_W]);
result.w = mp_obj_get_int_truncated(items[PIXEL_W]);
}
return;
return result;
}
}
// Int colors can't set white directly so convert to white when all components are equal.
// Also handles RGBW values assigned an RGB tuple.
if (!byteorder->is_dotstar && byteorder->bpp == 4 && byteorder->has_white && *r == *g && *r == *b) {
*w = *r;
*r = 0;
*g = 0;
*b = 0;
if (!byteorder->is_dotstar && byteorder->bpp == 4 && byteorder->has_white && result.r == result.g && result.r == result.b) {
result.w = result.r;
result.r = 0;
result.g = 0;
result.b = 0;
}
return result;
}
void common_hal_adafruit_pixelbuf_pixelbuf_parse_color(mp_obj_t self_in, mp_obj_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *w) {
pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in);
pixelbuf_parse_color(self, color, r, g, b, w);
}
static void pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t *self, size_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
STATIC void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t *self, size_t index, color_u rgbw) {
uint8_t r = rgbw.r;
uint8_t g = rgbw.g;
uint8_t b = rgbw.b;
uint8_t w = rgbw.w;
// DotStars don't have white, instead they have 5 bit brightness so pack it into w. Shift right
// by three to leave the top five bits.
if (self->bytes_per_pixel == 4 && self->byteorder.is_dotstar) {
@ -237,18 +240,10 @@ static void pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t *self, size_t index
scaled_buffer[rgbw_order->b] = (b * self->scaled_brightness) / 256;
}
}
void common_hal_adafruit_pixelbuf_pixelbuf_set_pixel_color(mp_obj_t self_in, size_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in);
pixelbuf_set_pixel_color(self, index, r, g, b, w);
}
STATIC void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t *self, size_t index, mp_obj_t value) {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t w;
common_hal_adafruit_pixelbuf_pixelbuf_parse_color(self, value, &r, &g, &b, &w);
common_hal_adafruit_pixelbuf_pixelbuf_set_pixel_color(self, index, r, g, b, w);
color_u rgbw = _pixelbuf_parse_color(self, value);
_pixelbuf_set_pixel_color(self, index, rgbw);
}
void common_hal_adafruit_pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t *values,
@ -327,14 +322,10 @@ void common_hal_adafruit_pixelbuf_pixelbuf_show(mp_obj_t self_in) {
void common_hal_adafruit_pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t fill_color) {
pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in);
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t w;
common_hal_adafruit_pixelbuf_pixelbuf_parse_color(self, fill_color, &r, &g, &b, &w);
color_u rgbw = _pixelbuf_parse_color(self, fill_color);
for (size_t i = 0; i < self->pixel_count; i++) {
common_hal_adafruit_pixelbuf_pixelbuf_set_pixel_color(self, i, r, g, b, w);
_pixelbuf_set_pixel_color(self, i, rgbw);
}
if (self->auto_write) {
common_hal_adafruit_pixelbuf_pixelbuf_show(self_in);

View File

@ -293,6 +293,16 @@ void common_hal_vectorio_vector_shape_set_location(vectorio_vector_shape_t *self
}
}
mp_int_t common_hal_vectorio_vector_shape_get_hidden(vectorio_vector_shape_t *self) {
VECTORIO_SHAPE_DEBUG("%p get_hidden\n", self);
return self->hidden;
}
void common_hal_vectorio_vector_shape_set_hidden(vectorio_vector_shape_t *self, bool hidden) {
VECTORIO_SHAPE_DEBUG("%p set_hidden %d\n", self, x);
self->hidden = hidden;
common_hal_vectorio_vector_shape_set_dirty(self);
}
mp_obj_t common_hal_vectorio_vector_shape_get_pixel_shader(vectorio_vector_shape_t *self) {
VECTORIO_SHAPE_DEBUG("%p get_pixel_shader\n", self);
@ -315,6 +325,11 @@ bool vectorio_vector_shape_fill_area(vectorio_vector_shape_t *self, const _displ
uint64_t start = common_hal_time_monotonic_ns();
uint64_t pixel_time = 0;
#endif
if (self->hidden) {
return false;
}
VECTORIO_SHAPE_DEBUG("%p fill_area: fill: {(%5d,%5d), (%5d,%5d)}",
self,
area->x1, area->y1, area->x2, area->y2

View File

@ -37,6 +37,7 @@ typedef struct {
displayio_area_t ephemeral_dirty_area;
displayio_area_t current_area;
bool current_area_dirty;
bool hidden;
} vectorio_vector_shape_t;
displayio_area_t *vectorio_vector_shape_get_refresh_areas(vectorio_vector_shape_t *self, displayio_area_t *tail);

Some files were not shown because too many files have changed in this diff Show More