summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--.github/workflows/build.yml1
-rw-r--r--docs/design_guide.rst18
m---------frozen/pew-pewpew-standalone-10.x0
-rw-r--r--locale/ID.po19
-rw-r--r--locale/circuitpython.pot19
-rw-r--r--locale/cs.po19
-rw-r--r--locale/de_DE.po19
-rw-r--r--locale/el.po19
-rw-r--r--locale/es.po19
-rw-r--r--locale/fil.po19
-rw-r--r--locale/fr.po19
-rw-r--r--locale/hi.po19
-rw-r--r--locale/it_IT.po19
-rw-r--r--locale/ja.po19
-rw-r--r--locale/ko.po19
-rw-r--r--locale/nl.po19
-rw-r--r--locale/pl.po27
-rw-r--r--locale/pt_BR.po21
-rw-r--r--locale/sv.po23
-rw-r--r--locale/zh_Latn_pinyin.po19
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Pin.c2
-rw-r--r--ports/raspberrypi/Makefile1
-rw-r--r--ports/raspberrypi/audio_dma.c383
-rw-r--r--ports/raspberrypi/audio_dma.h91
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/board.c44
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h14
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk9
-rw-r--r--ports/raspberrypi/boards/qtpy_rp2040/pins.c49
-rw-r--r--ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c235
-rw-r--r--ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h47
-rw-r--r--ports/raspberrypi/common-hal/audiopwmio/__init__.c0
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.c56
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.h4
-rw-r--r--ports/raspberrypi/mpconfigport.h3
-rw-r--r--ports/raspberrypi/mpconfigport.mk11
-rw-r--r--ports/raspberrypi/supervisor/port.c5
-rw-r--r--py/builtinevex.c9
-rw-r--r--shared-bindings/adafruit_bus_device/SPIDevice.c21
-rw-r--r--shared-bindings/adafruit_bus_device/SPIDevice.h1
-rw-r--r--shared-module/adafruit_bus_device/SPIDevice.c4
-rw-r--r--tests/manual/audiocore/jeplayer-splash-16000-16bit-mono-signed.wavbin0 -> 130448 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-16000-16bit-stereo-signed.wavbin0 -> 260852 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-16000-24bit-mono-signed.wavbin0 -> 195650 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-16000-24bit-stereo-signed.wavbin0 -> 391256 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-16000-8bit-mono-unsigned.wavbin0 -> 65246 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-16000-8bit-stereo-unsigned.wavbin0 -> 130448 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-16bit-mono-signed.wavbin0 -> 359468 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-16bit-stereo-signed.wavbin0 -> 718892 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-24bit-mono-signed.wavbin0 -> 539180 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-24bit-stereo-signed.wavbin0 -> 1078316 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-8bit-mono-unsigned.wavbin0 -> 179756 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-8bit-stereo-unsigned.wavbin0 -> 359468 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-44100-stereo.mp3bin0 -> 65200 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-8000-16bit-mono-signed.wavbin0 -> 65246 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-8000-16bit-stereo-signed.wavbin0 -> 130448 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-8000-24bit-mono-signed.wavbin0 -> 97848 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-8000-24bit-stereo-signed.wavbin0 -> 195650 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-8000-8bit-mono-unsigned.wavbin0 -> 32646 bytes
-rw-r--r--tests/manual/audiocore/jeplayer-splash-8000-8bit-stereo-unsigned.wavbin0 -> 65246 bytes
-rw-r--r--tests/manual/audiopwmio/single_buffer_loop.py65
-rw-r--r--tests/manual/audiopwmio/wavefile_pause_resume.py39
-rw-r--r--tests/manual/audiopwmio/wavefile_playback.py36
63 files changed, 1431 insertions, 55 deletions
diff --git a/.gitattributes b/.gitattributes
index 5ebde95f0..c077807ab 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -18,6 +18,7 @@
*.deb binary
*.zip binary
*.pdf binary
+*.wav binary
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index adba66314..69dcaf46d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -296,6 +296,7 @@ jobs:
- "pyruler"
- "qtpy_m0"
- "qtpy_m0_haxpress"
+ - "qtpy_rp2040"
- "raspberry_pi_pico"
- "raytac_mdbt50q-db-40"
- "robohatmm1_m4"
diff --git a/docs/design_guide.rst b/docs/design_guide.rst
index 7a8c76b50..331757034 100644
--- a/docs/design_guide.rst
+++ b/docs/design_guide.rst
@@ -165,6 +165,24 @@ use what.
Here is more info on properties from
`Python <https://docs.python.org/3/library/functions.html#property>`_.
+Exceptions and asserts
+--------------------------------------------------------------------------------
+
+Raise an appropriate `Exception <https://docs.python.org/3/library/exceptions.html#bltin-exceptions>`_,
+along with a useful message, whenever a critical test or other condition fails.
+
+Example::
+
+ if not 0 <= pin <= 7:
+ raise ValueError("Pin number must be 0-7.")
+
+If memory is constrained and a more compact method is needed, use `assert`
+instead.
+
+Example::
+
+ assert 0 <= pin <= 7, "Pin number must be 0-7."
+
Design for compatibility with CPython
--------------------------------------------------------------------------------
diff --git a/frozen/pew-pewpew-standalone-10.x b/frozen/pew-pewpew-standalone-10.x
-Subproject a14da2e1ced1010a0da65f758199ff08eedd0bd
+Subproject 88b8be84b5dce7660f58c02a63263f1d2ff0709
diff --git a/locale/ID.po b/locale/ID.po
index d2d1cc9ad..5d6ff8e06 100644
--- a/locale/ID.po
+++ b/locale/ID.po
@@ -368,6 +368,7 @@ msgstr "Semua timer untuk pin ini sedang digunakan"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Semua timer sedang digunakan"
@@ -1467,9 +1468,14 @@ msgstr "Tidak ada DAC (Digital Analog Converter) di dalam chip"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "tidak ada channel DMA ditemukan"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1756,6 +1762,10 @@ msgstr ""
"ideal. Jika ini tidak dapat dihindari, berikan allow_inefficient=True ke "
"konstruktor"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Tambahkan module apapun pada filesystem\n"
@@ -1996,6 +2006,14 @@ msgstr "Memisahkan dengan menggunakan sub-captures"
msgid "Stack size must be at least 256"
msgstr "Ukuran stack minimal harus 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Aliran tidak menemukan metode readinto() atau write()."
@@ -2167,6 +2185,7 @@ msgstr "Nilai UUID bukan str, int atau byte buffer"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Tidak dapat mengalokasikan buffer untuk signed conversion"
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 035941ff5..e936dd1f8 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -363,6 +363,7 @@ msgstr ""
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr ""
@@ -1446,9 +1447,14 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1724,6 +1730,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr ""
@@ -1963,6 +1973,14 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr ""
@@ -2126,6 +2144,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
diff --git a/locale/cs.po b/locale/cs.po
index b71c491c3..fe95f9da1 100644
--- a/locale/cs.po
+++ b/locale/cs.po
@@ -366,6 +366,7 @@ msgstr ""
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr ""
@@ -1449,9 +1450,14 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1727,6 +1733,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr ""
@@ -1966,6 +1976,14 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr ""
@@ -2129,6 +2147,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index caaa28ced..88d0f2fa0 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -368,6 +368,7 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Alle timer werden benutzt"
@@ -1469,9 +1470,14 @@ msgstr "Kein DAC im Chip vorhanden"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Kein DMA Kanal gefunden"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1756,6 +1762,10 @@ msgstr ""
"Bytes verbraucht. Wenn dies nicht vermieden werden kann, übergeben Sie "
"allow_inefficient = True an den Konstruktor"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "und alle Module im Dateisystem \n"
@@ -1995,6 +2005,14 @@ msgstr "Splitting mit sub-captures"
msgid "Stack size must be at least 256"
msgstr "Die Stackgröße sollte mindestens 256 sein"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Stream fehlt readinto() oder write() Methode."
@@ -2172,6 +2190,7 @@ msgstr "Der UUID-Wert ist kein str-, int- oder Byte-Puffer"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Konnte keine Buffer für Vorzeichenumwandlung allozieren"
diff --git a/locale/el.po b/locale/el.po
index bf03a5d82..675d53fbe 100644
--- a/locale/el.po
+++ b/locale/el.po
@@ -363,6 +363,7 @@ msgstr ""
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr ""
@@ -1446,9 +1447,14 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1724,6 +1730,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr ""
@@ -1963,6 +1973,14 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr ""
@@ -2126,6 +2144,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index fbde0ce37..789c04103 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -374,6 +374,7 @@ msgstr "Todos los timers para este pin están siendo utilizados"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Todos los timers en uso"
@@ -1470,9 +1471,14 @@ msgstr "El chip no tiene DAC"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "No se encontró el canal DMA"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1759,6 +1765,10 @@ msgstr ""
"ideales. Si esto no se puede evitar, pase allow_inefficient=True al "
"constructor"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Además de cualquier módulo en el sistema de archivos\n"
@@ -2002,6 +2012,14 @@ msgstr "Dividiendo con sub-capturas"
msgid "Stack size must be at least 256"
msgstr "El tamaño de la pila debe ser de al menos 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "A Stream le falta el método readinto() o write()."
@@ -2179,6 +2197,7 @@ msgstr "UUID valor no es un str, int o byte buffer"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "No se pudieron asignar buffers para la conversión con signo"
diff --git a/locale/fil.po b/locale/fil.po
index b030bd5c8..a27b0f8e3 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -366,6 +366,7 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Lahat ng timer ginagamit"
@@ -1461,9 +1462,14 @@ msgstr "Walang DAC sa chip"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Walang DMA channel na mahanap"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1743,6 +1749,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Kasama ang kung ano pang modules na sa filesystem\n"
@@ -1983,6 +1993,14 @@ msgstr "Binibiyak gamit ang sub-captures"
msgid "Stack size must be at least 256"
msgstr "Ang laki ng stack ay dapat na hindi bababa sa 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Stream kulang ng readinto() o write() method."
@@ -2146,6 +2164,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Hindi ma-allocate ang buffers para sa naka-sign na conversion"
diff --git a/locale/fr.po b/locale/fr.po
index ed7c12486..36cfb70b1 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -374,6 +374,7 @@ msgstr "Tous les minuteurs pour cette broche sont utilisés"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Tous les minuteurs sont utilisés"
@@ -1483,9 +1484,14 @@ msgstr "Pas de DAC sur la puce"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Aucun canal DMA trouvé"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1774,6 +1780,10 @@ msgstr ""
"octets idéal. Si cela ne peut pas être évité, transmettez allow_inefficient "
"= True au constructeur"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Ainsi que tout autres modules présents sur le système de fichiers\n"
@@ -2020,6 +2030,14 @@ msgstr "Fractionnement avec des sous-captures"
msgid "Stack size must be at least 256"
msgstr "La pile doit être au moins de 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Il manque une méthode readinto() ou write() au flux."
@@ -2198,6 +2216,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Impossible d'allouer des tampons pour une conversion signée"
diff --git a/locale/hi.po b/locale/hi.po
index fa57c47e5..4e5c9dc3b 100644
--- a/locale/hi.po
+++ b/locale/hi.po
@@ -363,6 +363,7 @@ msgstr ""
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr ""
@@ -1446,9 +1447,14 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1724,6 +1730,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr ""
@@ -1963,6 +1973,14 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr ""
@@ -2126,6 +2144,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 561f9fb08..d85f17b05 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -365,6 +365,7 @@ msgstr "Tutti i timer per questo pin sono in uso"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Tutti i timer utilizzati"
@@ -1465,9 +1466,14 @@ msgstr "Nessun DAC sul chip"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Nessun canale DMA trovato"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1752,6 +1758,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
#, fuzzy
msgid "Plus any modules on the filesystem\n"
@@ -1995,6 +2005,14 @@ msgstr "Suddivisione con sotto-catture"
msgid "Stack size must be at least 256"
msgstr "La dimensione dello stack deve essere almeno 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Metodi mancanti readinto() o write() allo stream."
@@ -2158,6 +2176,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Ipossibilitato ad allocare buffer per la conversione con segno"
diff --git a/locale/ja.po b/locale/ja.po
index c58264a7d..b7915197f 100644
--- a/locale/ja.po
+++ b/locale/ja.po
@@ -368,6 +368,7 @@ msgstr "このピン用の全てのタイマが使用中"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "全てのタイマーが使用中"
@@ -1459,9 +1460,14 @@ msgstr "チップにDACがありません"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "DMAチャネルが見つかりません"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1740,6 +1746,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr ""
@@ -1979,6 +1989,14 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr "スタックサイズは少なくとも256以上でなければなりません"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "ストリームにreadinto()またはwrite()メソッドがありません"
@@ -2149,6 +2167,7 @@ msgstr "UUIDの値がstr, int, bufferのいずれでもありません"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
diff --git a/locale/ko.po b/locale/ko.po
index ff1217f1c..86c1d4610 100644
--- a/locale/ko.po
+++ b/locale/ko.po
@@ -364,6 +364,7 @@ msgstr "핀의 모든 타이머가 사용 중입니다"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "모든 타이머가 사용 중입니다"
@@ -1449,9 +1450,14 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1727,6 +1733,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr ""
@@ -1966,6 +1976,14 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr ""
@@ -2130,6 +2148,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
diff --git a/locale/nl.po b/locale/nl.po
index 451241ba5..3fcb527b6 100644
--- a/locale/nl.po
+++ b/locale/nl.po
@@ -366,6 +366,7 @@ msgstr "Alle timers voor deze pin zijn in gebruik"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Alle timers zijn in gebruik"
@@ -1460,9 +1461,14 @@ msgstr "Geen DAC op de chip"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Geen DMA kanaal gevonden"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1750,6 +1756,10 @@ msgstr ""
"gebruikt. Als dit niet kan worden vermeden, geef dan het argument "
"allow_inefficient=True aan de constructor"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "En iedere module in het bestandssysteem\n"
@@ -1995,6 +2005,14 @@ msgstr "Splitting met sub-captures"
msgid "Stack size must be at least 256"
msgstr "Stack grootte moet op zijn minst 256 zijn"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Stream mist readinto() of write() methode."
@@ -2168,6 +2186,7 @@ msgstr "UUID waarde is geen str, int, of byte buffer"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Niet in staat buffers voor gesigneerde conversie te alloceren"
diff --git a/locale/pl.po b/locale/pl.po
index a3f0b2621..7251f8773 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-01-27 01:31+0000\n"
+"PO-Revision-Date: 2021-02-10 21:50+0000\n"
"Last-Translator: Maciej Stankiewicz <tawezik@gmail.com>\n"
"Language-Team: pl\n"
"Language: pl\n"
@@ -368,6 +368,7 @@ msgstr "Wszystkie timery tej nóżki w użyciu"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Wszystkie timery w użyciu"
@@ -1460,9 +1461,14 @@ msgstr "Brak DAC"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Nie znaleziono kanału DMA"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1738,6 +1744,10 @@ msgid ""
"constructor"
msgstr ""
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Oraz moduły w systemie plików\n"
@@ -1977,6 +1987,14 @@ msgstr "Podział z podgrupami"
msgid "Stack size must be at least 256"
msgstr "Stos musi mieć co najmniej 256 bajtów"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Strumień nie ma metod readinto() lub write()."
@@ -2140,6 +2158,7 @@ msgstr "UUID nie jest typu str, int lub bytes"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Nie udała się alokacja buforów do konwersji ze znakiem"
@@ -4107,7 +4126,7 @@ msgstr ""
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
-msgstr ""
+msgstr "szerokość musi być większa niż zero"
#: ports/esp32s2/common-hal/wifi/Radio.c
msgid "wifi is not enabled"
@@ -4127,7 +4146,7 @@ msgstr ""
#: extmod/ulab/code/vector/vectorise.c
msgid "wrong input type"
-msgstr ""
+msgstr "nieprawidłowy typ wejścia"
#: extmod/ulab/code/ulab_create.c py/objstr.c
msgid "wrong number of arguments"
@@ -4143,7 +4162,7 @@ msgstr "zły typ operandu"
#: extmod/ulab/code/vector/vectorise.c
msgid "wrong output type"
-msgstr ""
+msgstr "nieprawidłowy typ wyjścia"
#: shared-module/displayio/Shape.c
msgid "x value out of bounds"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 04fbb64cc..f81698453 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-02-09 14:03+0000\n"
+"PO-Revision-Date: 2021-02-12 03:20+0000\n"
"Last-Translator: Wellington Terumi Uemura <wellingtonuemura@gmail.com>\n"
"Language-Team: \n"
"Language: pt_BR\n"
@@ -376,6 +376,7 @@ msgstr "Todos os temporizadores para este pino estão em uso"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Todos os temporizadores em uso"
@@ -1478,9 +1479,14 @@ msgstr "Nenhum DAC no chip"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Nenhum canal DMA foi encontrado"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr "Nenhum temporizador DMA foi encontrado"
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1770,6 +1776,10 @@ msgstr ""
"ideal. Caso isso não possa ser evitado, passe allow_inefficient=True ao "
"construtor"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr "Os pinos devem compartilhar a fatia do PWM"
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Além de quaisquer módulos no sistema de arquivos\n"
@@ -2019,6 +2029,14 @@ msgstr "Divisão com sub-capturas"
msgid "Stack size must be at least 256"
msgstr "O tamanho da pilha deve ser pelo menos 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr "O estéreo à esquerda deve estar no canal PWM A"
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr "O estéreo à direita deve estar no canal PWM B"
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Transmita o método ausente readinto() ou write()."
@@ -2196,6 +2214,7 @@ msgstr "O valor UUID não é um buffer str, int ou byte"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Não é possível alocar buffers para conversão assinada"
diff --git a/locale/sv.po b/locale/sv.po
index e9eb91b05..91dd4d4fb 100644
--- a/locale/sv.po
+++ b/locale/sv.po
@@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
-"PO-Revision-Date: 2021-02-05 19:47+0000\n"
+"PO-Revision-Date: 2021-02-15 00:33+0000\n"
"Last-Translator: Jonny Bergdahl <jonny@bergdahl.it>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: sv\n"
@@ -371,6 +371,7 @@ msgstr "Alla timers för denna pinne är i bruk"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Alla timers används"
@@ -1466,9 +1467,14 @@ msgstr "Ingen DAC på chipet"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Ingen DMA-kanal hittades"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr "Ingen DMA pacing timer hittades"
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1754,6 +1760,10 @@ msgstr ""
"%d byte. Om detta inte kan undvikas, skicka allow_inefficient=True till "
"konstruktorn"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr "Pinnar måste dela PWM-segment"
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Plus eventuella moduler i filsystemet\n"
@@ -1999,6 +2009,14 @@ msgstr "Splitting med sub-captures"
msgid "Stack size must be at least 256"
msgstr "Stackstorleken måste vara minst 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr "Vänster stereokanal måste använda PWM kanal A"
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr "Höger stereokanal måste använda PWM kanal B"
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Stream saknar readinto() eller write() metod."
@@ -2172,6 +2190,7 @@ msgstr "UUID-värdet är inte str, int eller byte-buffert"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Det går inte att allokera buffert för signerad konvertering"
@@ -3687,7 +3706,7 @@ msgstr "pop från tom %q"
#: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c
msgid "port must be >= 0"
-msgstr ""
+msgstr "port måste vara >= 0"
#: py/objint_mpz.c
msgid "pow() 3rd argument cannot be 0"
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index f4b549777..91cd796a8 100644
--- a/locale/zh_Latn_pinyin.po
+++ b/locale/zh_Latn_pinyin.po
@@ -373,6 +373,7 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng"
#: ports/esp32s2/common-hal/pulseio/PulseOut.c
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
msgid "All timers in use"
msgstr "Suǒyǒu jìshí qì shǐyòng"
@@ -1465,9 +1466,14 @@ msgstr "Méiyǒu DAC zài xīnpiàn shàng de"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr "Wèi zhǎodào DMA píndào"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "No DMA pacing timer found"
+msgstr ""
+
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
@@ -1752,6 +1758,10 @@ msgstr ""
"duōzì jié. Rúguǒ wúfǎ bìmiǎn, qǐng jiāng allow_inefficient = True chuándì "
"gěigòuzào hánshù"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Pins must share PWM slice"
+msgstr ""
+
#: py/builtinhelp.c
msgid "Plus any modules on the filesystem\n"
msgstr "Zài wénjiàn xìtǒng shàng tiānjiā rènhé mókuài\n"
@@ -1994,6 +2004,14 @@ msgstr "Yǔ zi bǔhuò fēnliè"
msgid "Stack size must be at least 256"
msgstr "Duīzhàn dàxiǎo bìxū zhìshǎo 256"
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo left must be on PWM channel A"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
+msgid "Stereo right must be on PWM channel B"
+msgstr ""
+
#: shared-bindings/multiterminal/__init__.c
msgid "Stream missing readinto() or write() method."
msgstr "Liú quēshǎo readinto() huò write() fāngfǎ."
@@ -2166,6 +2184,7 @@ msgstr "UUID zhí bùshì str,int huò zì jié huǎnchōng qū"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Unable to allocate buffers for signed conversion"
msgstr "Wúfǎ fēnpèi huǎnchōng qū yòng yú qiānmíng zhuǎnhuàn"
diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c
index fca89ce8e..ff6d0ed35 100644
--- a/ports/esp32s2/common-hal/microcontroller/Pin.c
+++ b/ports/esp32s2/common-hal/microcontroller/Pin.c
@@ -134,7 +134,7 @@ bool pin_number_is_free(gpio_num_t pin_number) {
uint8_t offset = pin_number / 32;
uint32_t mask = 1 << (pin_number % 32);
- return (never_reset_pins[offset] & mask) == 0 && (in_use[offset] & mask) == 0;
+ return (in_use[offset] & mask) == 0;
}
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile
index e1169ce7d..7ce5606f8 100644
--- a/ports/raspberrypi/Makefile
+++ b/ports/raspberrypi/Makefile
@@ -196,6 +196,7 @@ SRC_C += \
bindings/rp2pio/__init__.c \
common-hal/rp2pio/StateMachine.c \
common-hal/rp2pio/__init__.c \
+ audio_dma.c \
background.c \
peripherals/pins.c \
fatfs_port.c \
diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c
new file mode 100644
index 000000000..96317984d
--- /dev/null
+++ b/ports/raspberrypi/audio_dma.c
@@ -0,0 +1,383 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "audio_dma.h"
+
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/audiocore/WaveFile.h"
+#include "supervisor/background_callback.h"
+
+#include "py/mpstate.h"
+#include "py/runtime.h"
+
+#include "src/rp2_common/hardware_irq/include/hardware/irq.h"
+
+#if CIRCUITPY_AUDIOPWMIO || CIRCUITPY_AUDIOBUSIO
+
+#define AUDIO_DMA_CHANNEL_COUNT NUM_DMA_CHANNELS
+
+void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer_length,
+ uint8_t** output_buffer, uint32_t* output_buffer_length) {
+ if (dma->first_buffer_free) {
+ *output_buffer = dma->first_buffer;
+ } else {
+ *output_buffer = dma->second_buffer;
+ }
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ if (dma->signed_to_unsigned ||
+ dma->unsigned_to_signed ||
+ dma->sample_spacing > 1 ||
+ (dma->sample_resolution != dma->output_resolution)) {
+ *output_buffer_length = buffer_length / dma->sample_spacing;
+ uint32_t out_i = 0;
+ if (dma->sample_resolution <= 8 && dma->output_resolution > 8) {
+ size_t shift = dma->output_resolution - dma->sample_resolution;
+
+ for (uint32_t i = 0; i < buffer_length; i += dma->sample_spacing) {
+ if (dma->signed_to_unsigned) {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t) ((int8_t*) buffer)[i] + 0x80) << shift;
+ } else if (dma->unsigned_to_signed) {
+ ((int16_t*) *output_buffer)[out_i] = ((int16_t) ((uint8_t*) buffer)[i] - 0x80) << shift;
+ } else {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t) ((uint8_t*) buffer)[i]) << shift;
+ }
+ out_i += 1;
+ }
+ } else if (dma->sample_resolution <= 8 && dma->output_resolution <= 8) {
+ for (uint32_t i = 0; i < buffer_length; i += dma->sample_spacing) {
+ if (dma->signed_to_unsigned) {
+ ((uint8_t*) *output_buffer)[out_i] = ((int8_t*) buffer)[i] + 0x80;
+ } else if (dma->unsigned_to_signed) {
+ ((int8_t*) *output_buffer)[out_i] = ((uint8_t*) buffer)[i] - 0x80;
+ } else {
+ ((uint8_t*) *output_buffer)[out_i] = ((uint8_t*) buffer)[i];
+ }
+ out_i += 1;
+ }
+ } else if (dma->sample_resolution > 8 && dma->output_resolution > 8) {
+ size_t shift = 16 - dma->output_resolution;
+ for (uint32_t i = 0; i < buffer_length / 2; i += dma->sample_spacing) {
+ if (dma->signed_to_unsigned) {
+ ((uint16_t*) *output_buffer)[out_i] = ((int16_t*) buffer)[i] + 0x8000;
+ } else if (dma->unsigned_to_signed) {
+ ((int16_t*) *output_buffer)[out_i] = ((uint16_t*) buffer)[i] - 0x8000;
+ } else {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t*) buffer)[i];
+ }
+ if (dma->output_resolution < 16) {
+ if (dma->output_signed) {
+ ((int16_t*) *output_buffer)[out_i] = ((int16_t*) *output_buffer)[out_i] >> shift;
+ } else {
+ ((uint16_t*) *output_buffer)[out_i] = ((uint16_t*) *output_buffer)[out_i] >> shift;
+ }
+ }
+ out_i += 1;
+ }
+ }
+ } else {
+ *output_buffer = buffer;
+ *output_buffer_length = buffer_length;
+ }
+ #pragma GCC diagnostic pop
+ dma->first_buffer_free = !dma->first_buffer_free;
+}
+
+void audio_dma_load_next_block(audio_dma_t* dma) {
+ uint8_t dma_channel = dma->channel[1];
+ if (dma->first_channel_free) {
+ dma_channel = dma->channel[0];
+ }
+ dma->first_channel_free = !dma->first_channel_free;
+
+ uint8_t* output_buffer;
+ uint32_t output_buffer_length;
+ audioio_get_buffer_result_t get_buffer_result;
+ uint8_t* buffer;
+ uint32_t buffer_length;
+ get_buffer_result = audiosample_get_buffer(dma->sample,
+ dma->single_channel, dma->audio_channel, &buffer, &buffer_length);
+
+ if (get_buffer_result == GET_BUFFER_ERROR) {
+ audio_dma_stop(dma);
+ return;
+ }
+
+ audio_dma_convert_signed(dma, buffer, buffer_length, &output_buffer, &output_buffer_length);
+
+ // If we don't have an output buffer, save the pointer to first_buffer for use in the single
+ // buffer special case.
+ if (dma->first_buffer == NULL) {
+ dma->first_buffer = output_buffer;
+ }
+
+ dma_channel_set_trans_count(dma_channel, output_buffer_length / dma->output_size, false /* trigger */);
+ dma_channel_set_read_addr(dma_channel, output_buffer, false /* trigger */);
+ if (get_buffer_result == GET_BUFFER_DONE) {
+ if (dma->loop) {
+ audiosample_reset_buffer(dma->sample, dma->single_channel, dma->audio_channel);
+ } else {
+ // Set channel trigger to ourselves so we don't keep going.
+ dma_channel_hw_t* c = &dma_hw->ch[dma_channel];
+ c->al1_ctrl = (c->al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (dma_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB);
+ }
+ }
+}
+
+// Playback should be shutdown before calling this.
+audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
+ mp_obj_t sample,
+ bool loop,
+ bool single_channel,
+ uint8_t audio_channel,
+ bool output_signed,
+ uint8_t output_resolution,
+ uint32_t output_register_address,
+ uint8_t dma_trigger_source) {
+ // Use two DMA channels to because the DMA can't wrap to itself without the
+ // buffer being power of two aligned.
+ dma->channel[0] = dma_claim_unused_channel(false);
+ dma->channel[1] = dma_claim_unused_channel(false);
+ if (dma->channel[0] == NUM_DMA_CHANNELS || dma->channel[1] == NUM_DMA_CHANNELS) {
+ if (dma->channel[0] < NUM_DMA_CHANNELS) {
+ dma_channel_unclaim(dma->channel[0]);
+ }
+ return AUDIO_DMA_DMA_BUSY;
+ }
+
+ dma->sample = sample;
+ dma->loop = loop;
+ dma->single_channel = single_channel;
+ dma->audio_channel = audio_channel;
+ dma->signed_to_unsigned = false;
+ dma->unsigned_to_signed = false;
+ dma->output_signed = output_signed;
+ dma->sample_spacing = 1;
+ dma->first_channel_free = true;
+ dma->output_resolution = output_resolution;
+ dma->sample_resolution = audiosample_bits_per_sample(sample);
+ audiosample_reset_buffer(sample, single_channel, audio_channel);
+
+ bool single_buffer;
+ bool samples_signed;
+ uint32_t max_buffer_length;
+ audiosample_get_buffer_structure(sample, single_channel, &single_buffer, &samples_signed,
+ &max_buffer_length, &dma->sample_spacing);
+
+ // Check to see if we have to scale the resolution up.
+ if (dma->sample_resolution <= 8 && dma->output_resolution > 8) {
+ max_buffer_length *= 2;
+ }
+ if (output_signed != samples_signed ||
+ dma->sample_spacing > 1 ||
+ (dma->sample_resolution != dma->output_resolution)) {
+ max_buffer_length /= dma->sample_spacing;
+ dma->first_buffer = (uint8_t*) m_realloc(dma->first_buffer, max_buffer_length);
+ if (dma->first_buffer == NULL) {
+ return AUDIO_DMA_MEMORY_ERROR;
+ }
+
+ dma->first_buffer_free = true;
+ if (!single_buffer) {
+ dma->second_buffer = (uint8_t*) m_realloc(dma->second_buffer, max_buffer_length);
+ if (dma->second_buffer == NULL) {
+ return AUDIO_DMA_MEMORY_ERROR;
+ }
+ }
+ dma->signed_to_unsigned = !output_signed && samples_signed;
+ dma->unsigned_to_signed = output_signed && !samples_signed;
+ }
+
+ if (output_resolution > 8) {
+ dma->output_size = 2;
+ } else {
+ dma->output_size = 1;
+ }
+ // Transfer both channels at once.
+ if (!single_channel && audiosample_channel_count(sample) == 2) {
+ dma->output_size *= 2;
+ }
+
+ enum dma_channel_transfer_size dma_size = DMA_SIZE_8;
+ if (dma->output_size == 2) {
+ dma_size = DMA_SIZE_16;
+ } else if (dma->output_size == 4) {
+ dma_size = DMA_SIZE_32;
+ }
+
+ for (size_t i = 0; i < 2; i++) {
+ dma_channel_config c = dma_channel_get_default_config(dma->channel[i]);
+ channel_config_set_transfer_data_size(&c, dma_size);
+ channel_config_set_dreq(&c, dma_trigger_source);
+ channel_config_set_read_increment(&c, true);
+ channel_config_set_write_increment(&c, false);
+ // Chain to the other channel by default.
+ channel_config_set_chain_to(&c, dma->channel[(i + 1) % 2]);
+ dma_channel_set_config(dma->channel[i], &c, false /* trigger */);
+ dma_channel_set_write_addr(dma->channel[i], (void*) output_register_address, false /* trigger */);
+ }
+
+ // We keep the audio_dma_t for internal use and the sample as a root pointer because it
+ // contains the audiodma structure.
+ MP_STATE_PORT(playing_audio)[dma->channel[0]] = dma;
+ MP_STATE_PORT(playing_audio)[dma->channel[1]] = dma;
+
+ // Load the first two blocks up front.
+ audio_dma_load_next_block(dma);
+ if (!single_buffer) {
+ audio_dma_load_next_block(dma);
+ }
+
+ // Special case the DMA for a single buffer. It's commonly used for a single wave length of sound
+ // and may be short. Therefore, we use DMA chaining to loop quickly without involving interrupts.
+ // On the RP2040 we chain by having a second DMA writing to the config registers of the first.
+ // Read and write addresses change with DMA so we need to reset the read address back to the
+ // start of the sample.
+ if (single_buffer) {
+ dma_channel_config c = dma_channel_get_default_config(dma->channel[1]);
+ channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
+ channel_config_set_dreq(&c, 0x3f); // dma as fast as possible
+ channel_config_set_read_increment(&c, false);
+ channel_config_set_write_increment(&c, false);
+ channel_config_set_chain_to(&c, dma->channel[1]); // Chain to ourselves so we stop.
+ dma_channel_configure(dma->channel[1], &c,
+ &dma_hw->ch[dma->channel[0]].al3_read_addr_trig, // write address
+ &dma->first_buffer, // read address
+ 1, // transaction count
+ false); // trigger
+ } else {
+ // Enable our DMA channels on DMA0 to the CPU. This will wake us up when
+ // we're WFI.
+ dma_hw->inte0 |= (1 << dma->channel[0]) | (1 << dma->channel[1]);
+ irq_set_mask_enabled(1 << DMA_IRQ_0, true);
+ }
+
+ dma_channel_start(dma->channel[0]);
+
+ return AUDIO_DMA_OK;
+}
+
+void audio_dma_stop(audio_dma_t* dma) {
+ // Disable our interrupts.
+ dma_hw->inte0 &= ~((1 << dma->channel[0]) | (1 << dma->channel[1]));
+ irq_set_mask_enabled(1 << DMA_IRQ_0, false);
+
+ // Run any remaining audio tasks because we remove ourselves from
+ // playing_audio.
+ RUN_BACKGROUND_TASKS;
+
+ for (size_t i = 0; i < 2; i++) {
+ size_t channel = dma->channel[i];
+
+ if (dma_channel_is_busy(channel)) {
+ dma_channel_abort(channel);
+ }
+ dma_channel_unclaim(channel);
+ MP_STATE_PORT(playing_audio)[channel] = NULL;
+ dma->channel[i] = NUM_DMA_CHANNELS;
+ }
+
+ // Hold onto our buffers.
+}
+
+// To pause we simply stop the DMA. It is the responsibility of the output peripheral
+// to hold the previous value.
+void audio_dma_pause(audio_dma_t* dma) {
+ dma_hw->ch[dma->channel[0]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS;
+ dma_hw->ch[dma->channel[1]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS;
+}
+
+void audio_dma_resume(audio_dma_t* dma) {
+ // Always re-enable the non-busy channel first so it's ready to continue when the busy channel
+ // finishes and chains to it. (An interrupt could make the time between enables long.)
+ size_t first = 0;
+ size_t second = 1;
+ if (dma_channel_is_busy(dma->channel[0])) {
+ first = 1;
+ second = 0;
+ }
+ dma_hw->ch[dma->channel[first]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS;
+ dma_hw->ch[dma->channel[second]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS;
+}
+
+bool audio_dma_get_paused(audio_dma_t* dma) {
+ if (dma->channel[0] >= AUDIO_DMA_CHANNEL_COUNT) {
+ return false;
+ }
+ uint32_t control = dma_hw->ch[dma->channel[0]].ctrl_trig;
+
+ return (control & DMA_CH0_CTRL_TRIG_EN_BITS) == 0;
+}
+
+void audio_dma_init(audio_dma_t* dma) {
+ dma->first_buffer = NULL;
+ dma->second_buffer = NULL;
+}
+
+void audio_dma_deinit(audio_dma_t* dma) {
+ m_free(dma->first_buffer);
+ dma->first_buffer = NULL;
+
+ m_free(dma->second_buffer);
+ dma->second_buffer = NULL;
+}
+
+bool audio_dma_get_playing(audio_dma_t* dma) {
+ if (dma->channel[0] == NUM_DMA_CHANNELS) {
+ return false;
+ }
+ if (!dma_channel_is_busy(dma->channel[0]) &&
+ !dma_channel_is_busy(dma->channel[1])) {
+ audio_dma_stop(dma);
+ return false;
+ }
+
+ return true;
+}
+
+// WARN(tannewt): DO NOT print from here, or anything it calls. Printing calls
+// background tasks such as this and causes a stack overflow.
+STATIC void dma_callback_fun(void *arg) {
+ audio_dma_t* dma = arg;
+ if (dma == NULL) {
+ return;
+ }
+
+ audio_dma_load_next_block(dma);
+}
+
+void isr_dma_0(void) {
+ for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) {
+ uint32_t mask = 1 << i;
+ if ((dma_hw->intr & mask) != 0 && MP_STATE_PORT(playing_audio)[i] != NULL) {
+ audio_dma_t* dma = MP_STATE_PORT(playing_audio)[i];
+ background_callback_add(&dma->callback, dma_callback_fun, (void*)dma);
+ dma_hw->ints0 = mask;
+ }
+ }
+}
+
+#endif
diff --git a/ports/raspberrypi/audio_dma.h b/ports/raspberrypi/audio_dma.h
new file mode 100644
index 000000000..1f739ff73
--- /dev/null
+++ b/ports/raspberrypi/audio_dma.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H
+#define MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H
+
+#include "py/obj.h"
+#include "supervisor/background_callback.h"
+
+#include "src/rp2_common/hardware_dma/include/hardware/dma.h"
+
+typedef struct {
+ mp_obj_t sample;
+ uint8_t channel[2];
+ uint8_t audio_channel;
+ uint8_t output_size;
+ uint8_t sample_spacing;
+ bool loop;
+ bool single_channel;
+ bool signed_to_unsigned;
+ bool unsigned_to_signed;
+ bool output_signed;
+ bool first_channel_free;
+ bool first_buffer_free;
+ uint8_t output_resolution; // in bits
+ uint8_t sample_resolution; // in bits
+ uint8_t* first_buffer;
+ uint8_t* second_buffer;
+ background_callback_t callback;
+} audio_dma_t;
+
+typedef enum {
+ AUDIO_DMA_OK,
+ AUDIO_DMA_DMA_BUSY,
+ AUDIO_DMA_MEMORY_ERROR,
+} audio_dma_result;
+
+
+void audio_dma_init(audio_dma_t* dma);
+void audio_dma_deinit(audio_dma_t* dma);
+void audio_dma_reset(void);
+
+// This sets everything up but doesn't start the timer.
+// Sample is the python object for the sample to play.
+// loop is true if we should loop the sample.
+// single_channel is true if we only output a single channel. When false, all channels will be
+// output.
+// audio_channel is the index of the channel to dma. single_channel must be false in this case.
+// output_signed is true if the dma'd data should be signed. False and it will be unsigned.
+// output_register_address is the address to copy data to.
+// dma_trigger_source is the DMA trigger source which cause another copy
+audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
+ mp_obj_t sample,
+ bool loop,
+ bool single_channel,
+ uint8_t audio_channel,
+ bool output_signed,
+ uint8_t output_resolution,
+ uint32_t output_register_address,
+ uint8_t dma_trigger_source);
+
+void audio_dma_stop(audio_dma_t* dma);
+bool audio_dma_get_playing(audio_dma_t* dma);
+void audio_dma_pause(audio_dma_t* dma);
+void audio_dma_resume(audio_dma_t* dma);
+bool audio_dma_get_paused(audio_dma_t* dma);
+
+#endif // MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/board.c b/ports/raspberrypi/boards/qtpy_rp2040/board.c
new file mode 100644
index 000000000..332145ab8
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/board.c
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "supervisor/board.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
+
+void board_init(void) {
+ common_hal_never_reset_pin(&pin_GPIO11);
+ gpio_init(11);
+ gpio_set_dir(11, GPIO_OUT);
+ gpio_put(11, true);
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h
new file mode 100644
index 000000000..26abe8a83
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.h
@@ -0,0 +1,14 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit QTPy RP2040"
+#define MICROPY_HW_MCU_NAME "rp2040"
+
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO12)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_GPIO25)
+#define DEFAULT_I2C_BUS_SDA (&pin_GPIO24)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6)
+#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3)
+#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4)
+
+// #define DEFAULT_UART_BUS_RX (&pin_PA11)
+// #define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk
new file mode 100644
index 000000000..5e454e312
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/mpconfigboard.mk
@@ -0,0 +1,9 @@
+USB_VID = 0x239A
+USB_PID = 0x80F8
+USB_PRODUCT = "QT Py RP2040"
+USB_MANUFACTURER = "Adafruit"
+
+CHIP_VARIANT = RP2040
+CHIP_FAMILY = rp2
+
+INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/raspberrypi/boards/qtpy_rp2040/pins.c b/ports/raspberrypi/boards/qtpy_rp2040/pins.c
new file mode 100644
index 000000000..e0ebd0032
--- /dev/null
+++ b/ports/raspberrypi/boards/qtpy_rp2040/pins.c
@@ -0,0 +1,49 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO29) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO29) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO28) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO28) },
+
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO27) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO27) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO26) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO27) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO24) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO24) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO25) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO25) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO20) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO20) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO9) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO6) },
+
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO4) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO4) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO3) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO12) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO11) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_GPIO22) },
+ { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO23) },
+
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ // { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
new file mode 100644
index 000000000..57605a1fb
--- /dev/null
+++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
@@ -0,0 +1,235 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "extmod/vfs_fat.h"
+#include "py/gc.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "shared-bindings/pwmio/PWMOut.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Processor.h"
+#include "supervisor/shared/tick.h"
+#include "supervisor/shared/translate.h"
+
+#include "src/rp2040/hardware_structs/include/hardware/structs/dma.h"
+#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
+
+#define NUM_DMA_TIMERS 4
+
+void audiopwmout_reset() {
+ for (size_t i = 0; i < NUM_DMA_TIMERS; i++) {
+ dma_hw->timer[i] = 0;
+ }
+}
+
+// Caller validates that pins are free.
+void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t quiescent_value) {
+ if (left_channel != NULL && right_channel != NULL) {
+ if (pwm_gpio_to_slice_num(left_channel->number) != pwm_gpio_to_slice_num(right_channel->number)) {
+ mp_raise_ValueError(translate("Pins must share PWM slice"));
+ }
+ if (pwm_gpio_to_channel(left_channel->number) != 0) {
+ mp_raise_ValueError(translate("Stereo left must be on PWM channel A"));
+ }
+ if (pwm_gpio_to_channel(right_channel->number) != 1) {
+ mp_raise_ValueError(translate("Stereo right must be on PWM channel B"));
+ }
+ }
+
+ // Typically pwmout doesn't let us change frequency with two objects on the
+ // same PWM slice. However, we have private access to it so we can do what
+ // we want. ;-) We mark ourselves variable only if we're a mono output to
+ // prevent other PWM use on the other channel. If stereo, we say fixed
+ // frequency so we can allocate with ourselves.
+ bool mono = right_channel == NULL;
+
+ // We don't actually know our frequency yet so just pick one that shouldn't
+ // match anyone else. (We'll only know the frequency once we play something
+ // back.)
+ uint32_t frequency = 12500;
+
+ // Make sure the PWMOut's are "deinited" by default.
+ self->left_pwm.pin = NULL;
+ self->right_pwm.pin = NULL;
+
+ pwmout_result_t result = common_hal_pwmio_pwmout_construct(&self->left_pwm,
+ left_channel, 0, frequency, mono);
+ if (result == PWMOUT_OK && right_channel != NULL) {
+ result = common_hal_pwmio_pwmout_construct(&self->right_pwm,
+ right_channel, 0, frequency, false);
+ if (result != PWMOUT_OK) {
+ common_hal_pwmio_pwmout_deinit(&self->left_pwm);
+ }
+ }
+ if (result != PWMOUT_OK) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+
+ claim_pin(left_channel);
+ if (right_channel != NULL) {
+ claim_pin(right_channel);
+ }
+
+ audio_dma_init(&self->dma);
+
+ self->quiescent_value = quiescent_value;
+}
+
+bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self) {
+ return common_hal_pwmio_pwmout_deinited(&self->left_pwm);
+}
+
+void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self) {
+ if (common_hal_audiopwmio_pwmaudioout_deinited(self)) {
+ return;
+ }
+ if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ }
+
+ // TODO: ramp the pwm down from quiescent value to 0
+ common_hal_pwmio_pwmout_deinit(&self->left_pwm);
+ common_hal_pwmio_pwmout_deinit(&self->right_pwm);
+
+ audio_dma_deinit(&self->dma);
+}
+
+void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop) {
+ if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ }
+
+ // TODO: Share pacing timers based on frequency.
+ size_t pacing_timer = NUM_DMA_TIMERS;
+ for (size_t i = 0; i < NUM_DMA_TIMERS; i++) {
+ if (dma_hw->timer[i] == 0) {
+ pacing_timer = i;
+ }
+ break;
+ }
+ if (pacing_timer == NUM_DMA_TIMERS) {
+ mp_raise_RuntimeError(translate("No DMA pacing timer found"));
+ }
+ uint32_t tx_register = (uint32_t) &pwm_hw->slice[self->left_pwm.slice].cc;
+ if (common_hal_pwmio_pwmout_deinited(&self->right_pwm)) {
+ // Shift the destination if we are outputting to the second PWM channel.
+ tx_register += self->left_pwm.channel * sizeof(uint16_t);
+ }
+
+ pwmio_pwmout_set_top(&self->left_pwm, 1023);
+
+ audio_dma_result result = audio_dma_setup_playback(
+ &self->dma,
+ sample,
+ loop,
+ false, // single channel
+ 0, // audio channel
+ false, // output signed
+ 10,
+ (uint32_t) tx_register, // output register
+ 0x3b + pacing_timer); // data request line
+
+ if (result == AUDIO_DMA_DMA_BUSY) {
+ // common_hal_audiobusio_i2sout_stop(self);
+ mp_raise_RuntimeError(translate("No DMA channel found"));
+ } else if (result == AUDIO_DMA_MEMORY_ERROR) {
+ // common_hal_audiobusio_i2sout_stop(self);
+ mp_raise_RuntimeError(translate("Unable to allocate buffers for signed conversion"));
+ }
+
+ // OK! We got all of the resources we need and dma is ready.
+ self->pacing_timer = pacing_timer;
+
+ // Playback with two independent clocks. One is the sample rate which
+ // determines when we push a new sample to the PWM slice. The second is the
+ // PWM frequency itself.
+
+ // Determine the DMA divisor. The RP2040 has four pacing timers we can use
+ // to trigger the DMA. Each has a 16 bit fractional divisor system clock * X / Y where X and Y
+ // are 16-bit.
+
+ uint32_t sample_rate = audiosample_sample_rate(sample);
+ uint32_t system_clock = common_hal_mcu_processor_get_frequency();
+ uint32_t best_numerator = 0;
+ uint32_t best_denominator = 0;
+ uint32_t best_error = system_clock;
+
+ for (uint32_t denominator = 0xffff; denominator > 0; denominator--) {
+ uint32_t numerator = (denominator * sample_rate) / system_clock;
+ uint32_t remainder = (denominator * sample_rate) % system_clock;
+ if (remainder > (system_clock / 2)) {
+ numerator += 1;
+ remainder = system_clock - remainder;
+ }
+ if (remainder < best_error) {
+ best_denominator = denominator;
+ best_numerator = numerator;
+ best_error = remainder;
+ // Stop early if we can't do better.
+ if (remainder == 0) {
+ break;
+ }
+ }
+ }
+
+ dma_hw->timer[pacing_timer] = best_numerator << 16 | best_denominator;
+}
+
+void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self) {
+ dma_hw->timer[self->pacing_timer] = 0;
+ self->pacing_timer = NUM_DMA_TIMERS;
+
+ audio_dma_stop(&self->dma);
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self) {
+ bool playing = audio_dma_get_playing(&self->dma);
+ if (!playing && self->pacing_timer < NUM_DMA_TIMERS) {
+ dma_hw->timer[self->pacing_timer] = 0;
+ self->pacing_timer = NUM_DMA_TIMERS;
+ }
+ return playing;
+}
+
+void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self) {
+ audio_dma_pause(&self->dma);
+}
+
+void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self) {
+ audio_dma_resume(&self->dma);
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self) {
+ return audio_dma_get_paused(&self->dma);
+}
diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h
new file mode 100644
index 000000000..2b43b8354
--- /dev/null
+++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_AUDIOPWMIO_PWMAUDIOOUT_H
+#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_AUDIOPWMIO_PWMAUDIOOUT_H
+
+#include "common-hal/pwmio/PWMOut.h"
+
+#include "audio_dma.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ pwmio_pwmout_obj_t left_pwm;
+ pwmio_pwmout_obj_t right_pwm;
+ audio_dma_t dma;
+ uint16_t quiescent_value;
+ uint8_t pacing_timer;
+} audiopwmio_pwmaudioout_obj_t;
+
+void audiopwmout_reset(void);
+
+void audiopwmout_background(void);
+
+#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_AUDIOPWMIO_PWMAUDIOOUT_H
diff --git a/ports/raspberrypi/common-hal/audiopwmio/__init__.c b/ports/raspberrypi/common-hal/audiopwmio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/raspberrypi/common-hal/audiopwmio/__init__.c
diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c
index 3d8979a03..00b461880 100644
--- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c
+++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c
@@ -39,12 +39,24 @@
#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
uint32_t target_slice_frequencies[NUM_PWM_SLICES];
-uint32_t slice_fixed_frequency;
+uint32_t slice_variable_frequency;
#define CHANNELS_PER_SLICE 2
static uint32_t channel_use;
static uint32_t never_reset_channel;
+// Per the RP2040 datasheet:
+//
+// "A CC value of 0 will produce a 0% output, i.e. the output signal
+// is always low. A CC value of TOP + 1 (i.e. equal to the period, in
+// non-phase-correct mode) will produce a 100% output. For example, if
+// TOP is programmed to 254, the counter will have a period of 255
+// cycles, and CC values in the range of 0 to 255 inclusive will
+// produce duty cycles in the range 0% to 100% inclusive."
+//
+// So 65534 should be the maximum top value, and we'll set CC to be TOP+1 as appropriate.
+#define MAX_TOP 65534
+
static uint32_t _mask(uint8_t slice, uint8_t channel) {
return 1 << (slice * CHANNELS_PER_SLICE + channel);
}
@@ -76,7 +88,7 @@ void pwmout_reset(void) {
}
pwm_set_enabled(slice, false);
target_slice_frequencies[slice] = 0;
- slice_fixed_frequency &= ~(1 << slice);
+ slice_variable_frequency &= ~(1 << slice);
}
}
@@ -108,7 +120,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
// If the other user wants a variable frequency then we can't share either.
- if ((slice_fixed_frequency & (1 << slice)) != 0) {
+ if ((slice_variable_frequency & (1 << slice)) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
// If we're both fixed frequency but we don't match target frequencies then we can't share.
@@ -118,9 +130,10 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
}
self->slice = slice;
self->channel = channel;
+
channel_use |= channel_use_mask;
if (variable_frequency) {
- slice_fixed_frequency |= 1 << slice;
+ slice_variable_frequency |= 1 << slice;
}
if (target_slice_frequencies[slice] != frequency) {
@@ -153,7 +166,7 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (self->slice * CHANNELS_PER_SLICE + self->channel);
if ((channel_use & slice_mask) == 0) {
target_slice_frequencies[self->slice] = 0;
- slice_fixed_frequency &= ~(1 << self->slice);
+ slice_variable_frequency &= ~(1 << self->slice);
pwm_set_enabled(self->slice, false);
}
@@ -163,14 +176,30 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t* self, uint16_t duty) {
self->duty_cycle = duty;
- uint16_t actual_duty = duty * self->top / ((1 << 16) - 1);
- pwm_set_chan_level(self->slice, self->channel, actual_duty);
+ // Do arithmetic in 32 bits to prevent overflow.
+ uint16_t compare_count;
+ if (duty == 65535) {
+ // Ensure that 100% duty cycle is 100% full on and not rounded down,
+ // but do MIN() to keep value in range, just in case.
+ compare_count = MIN(UINT16_MAX, (uint32_t) self->top + 1);
+ } else {
+ compare_count= ((uint32_t) duty * self->top + MAX_TOP / 2) / MAX_TOP;
+ }
+ // compare_count is the CC register value, which should be TOP+1 for 100% duty cycle.
+ pwm_set_chan_level(self->slice, self->channel, compare_count);
}
uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t* self) {
return self->duty_cycle;
}
+void pwmio_pwmout_set_top(pwmio_pwmout_obj_t* self, uint16_t top) {
+ self->actual_frequency = common_hal_mcu_processor_get_frequency() / top;
+ self->top = top;
+ pwm_set_clkdiv_int_frac(self->slice, 1, 0);
+ pwm_set_wrap(self->slice, self->top);
+}
+
void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t frequency) {
if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) {
mp_raise_ValueError(translate("Invalid PWM frequency"));
@@ -179,7 +208,7 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t fr
target_slice_frequencies[self->slice] = frequency;
// For low frequencies use the divider to give us full resolution duty_cycle.
- if (frequency < (common_hal_mcu_processor_get_frequency() / (1 << 16))) {
+ if (frequency <= (common_hal_mcu_processor_get_frequency() / (1 << 16))) {
// Compute the divisor. It's an 8 bit integer and 4 bit fraction. Therefore,
// we compute everything * 16 for the fractional part.
// This is 1 << 12 because 4 bits are the * 16.
@@ -193,16 +222,17 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t fr
if (div16 >= (1 << 12)) {
div16 = (1 << 12) - 1;
}
- self->actual_frequency = frequency16 / div16;
- self->top = 1 << 16;
+ self->actual_frequency = (frequency16 + (div16 / 2)) / div16;
+ self->top = MAX_TOP;
pwm_set_clkdiv_int_frac(self->slice, div16 / 16, div16 % 16);
- pwm_set_wrap(self->slice, self->top - 1);
+ pwm_set_wrap(self->slice, self->top);
} else {
uint32_t top = common_hal_mcu_processor_get_frequency() / frequency;
self->actual_frequency = common_hal_mcu_processor_get_frequency() / top;
- self->top = top;
+ self->top = MIN(MAX_TOP, top);
pwm_set_clkdiv_int_frac(self->slice, 1, 0);
- pwm_set_wrap(self->slice, self->top - 1);
+ // Set TOP register. For 100% duty cycle, CC must be set to TOP+1.
+ pwm_set_wrap(self->slice, self->top);
}
common_hal_pwmio_pwmout_set_duty_cycle(self, self->duty_cycle);
}
diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.h b/ports/raspberrypi/common-hal/pwmio/PWMOut.h
index 50f84777b..0070e188b 100644
--- a/ports/raspberrypi/common-hal/pwmio/PWMOut.h
+++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.h
@@ -39,9 +39,11 @@ typedef struct {
bool variable_frequency;
uint16_t duty_cycle;
uint32_t actual_frequency;
- uint32_t top;
+ uint16_t top;
} pwmio_pwmout_obj_t;
void pwmout_reset(void);
+// Private API for AudioPWMOut.
+void pwmio_pwmout_set_top(pwmio_pwmout_obj_t* self, uint16_t top);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h
index 77d1ff080..e0d98579d 100644
--- a/ports/raspberrypi/mpconfigport.h
+++ b/ports/raspberrypi/mpconfigport.h
@@ -27,6 +27,8 @@
#ifndef __INCLUDED_MPCONFIGPORT_H
#define __INCLUDED_MPCONFIGPORT_H
+#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
+
#define MICROPY_PY_SYS_PLATFORM "RP2040"
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
@@ -41,6 +43,7 @@
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
+ mp_obj_t playing_audio[NUM_DMA_CHANNELS]; \
CIRCUITPY_COMMON_ROOT_POINTERS;
#endif // __INCLUDED_MPCONFIGPORT_H
diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk
index 8681e2994..dac7231da 100644
--- a/ports/raspberrypi/mpconfigport.mk
+++ b/ports/raspberrypi/mpconfigport.mk
@@ -27,8 +27,6 @@ CIRCUITPY_FULL_BUILD = 1
CIRCUITPY_PWMIO = 1
# Things that need to be implemented.
-CIRCUITPY_AUDIOBUSIO = 0 # Use PIO interally for I2S
-CIRCUITPY_AUDIOMP3 = 0
CIRCUITPY_COUNTIO = 0 # Use PWM interally
CIRCUITPY_FREQUENCYIO = 0 # Use PWM interally
CIRCUITPY_I2CPERIPHERAL = 0
@@ -37,8 +35,15 @@ CIRCUITPY_PULSEIO = 0 # Use PIO interally
CIRCUITPY_ROTARYIO = 0 # Use PIO interally
CIRCUITPY_WATCHDOG = 1
-# Things that are unsupported by the hardware.
+# Audio via PWM
CIRCUITPY_AUDIOIO = 0
+CIRCUITPY_AUDIOBUSIO ?= 0 # add this later
+CIRCUITPY_AUDIOCORE ?= 1
+CIRCUITPY_AUDIOPWMIO ?= 1
+
+# These libraries require Cortex M4+ for fancy math instructions.
+CIRCUITPY_AUDIOMIXER ?= 0
+CIRCUITPY_AUDIOMP3 ?= 0
INTERNAL_LIBM = 1
diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c
index 7c503514a..36d2e8275 100644
--- a/ports/raspberrypi/supervisor/port.c
+++ b/ports/raspberrypi/supervisor/port.c
@@ -32,6 +32,7 @@
#include "bindings/rp2pio/StateMachine.h"
#include "genhdr/mpversion.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
#include "shared-bindings/busio/I2C.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/microcontroller/__init__.h"
@@ -108,6 +109,10 @@ void reset_port(void) {
rtc_reset();
#endif
+ #if CIRCUITPY_AUDIOPWMIO
+ audiopwmout_reset();
+ #endif
+
reset_all_pins();
}
diff --git a/py/builtinevex.c b/py/builtinevex.c
index ade12d39d..cff57c413 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -132,17 +132,18 @@ STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_i
}
#endif
- size_t str_len;
- const char *str = mp_obj_str_get_data(args[0], &str_len);
+ // Extract the source code.
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
// create the lexer
// MP_PARSE_SINGLE_INPUT is used to indicate a file input
mp_lexer_t *lex;
if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) {
- lex = mp_lexer_new_from_file(str);
+ lex = mp_lexer_new_from_file(bufinfo.buf);
parse_input_kind = MP_PARSE_FILE_INPUT;
} else {
- lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
+ lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, bufinfo.buf, bufinfo.len, 0);
}
return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);
diff --git a/shared-bindings/adafruit_bus_device/SPIDevice.c b/shared-bindings/adafruit_bus_device/SPIDevice.c
index e37f88368..74fa28e4d 100644
--- a/shared-bindings/adafruit_bus_device/SPIDevice.c
+++ b/shared-bindings/adafruit_bus_device/SPIDevice.c
@@ -34,7 +34,6 @@
#include "lib/utils/buffer_helper.h"
#include "lib/utils/context_manager_helpers.h"
-#include "py/objproperty.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
@@ -123,29 +122,9 @@ STATIC mp_obj_t adafruit_bus_device_spidevice_obj___exit__(size_t n_args, const
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_spidevice___exit___obj, 4, 4, adafruit_bus_device_spidevice_obj___exit__);
-//| spi: busio.SPI
-//| """The underlying SPI bus. Useful for weird uses like clocking an SD card without chip select.
-//|
-//| You shouldn't normally need this."""
-//|
-STATIC mp_obj_t adafruit_bus_device_spidevice_obj_get_spi(mp_obj_t self_in) {
- adafruit_bus_device_spidevice_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return common_hal_adafruit_bus_device_spidevice_get_spi(self);
-}
-MP_DEFINE_CONST_FUN_OBJ_1(adafruit_bus_device_spidevice_get_spi_obj, adafruit_bus_device_spidevice_obj_get_spi);
-
-const mp_obj_property_t adafruit_bus_device_spidevice_spi_obj = {
- .base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&adafruit_bus_device_spidevice_get_spi_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj},
-};
-
STATIC const mp_rom_map_elem_t adafruit_bus_device_spidevice_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&adafruit_bus_device_spidevice___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&adafruit_bus_device_spidevice___exit___obj) },
-
- { MP_ROM_QSTR(MP_QSTR_spi), MP_ROM_PTR(&adafruit_bus_device_spidevice_spi_obj) },
};
STATIC MP_DEFINE_CONST_DICT(adafruit_bus_device_spidevice_locals_dict, adafruit_bus_device_spidevice_locals_dict_table);
diff --git a/shared-bindings/adafruit_bus_device/SPIDevice.h b/shared-bindings/adafruit_bus_device/SPIDevice.h
index baa9ec464..997e22a6b 100644
--- a/shared-bindings/adafruit_bus_device/SPIDevice.h
+++ b/shared-bindings/adafruit_bus_device/SPIDevice.h
@@ -46,6 +46,5 @@ extern void common_hal_adafruit_bus_device_spidevice_construct(adafruit_bus_devi
uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t extra_clocks);
extern mp_obj_t common_hal_adafruit_bus_device_spidevice_enter(adafruit_bus_device_spidevice_obj_t *self);
extern void common_hal_adafruit_bus_device_spidevice_exit(adafruit_bus_device_spidevice_obj_t *self);
-extern mp_obj_t common_hal_adafruit_bus_device_spidevice_get_spi(adafruit_bus_device_spidevice_obj_t *self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSDEVICE_SPIDEVICE_H
diff --git a/shared-module/adafruit_bus_device/SPIDevice.c b/shared-module/adafruit_bus_device/SPIDevice.c
index 5c1a69b12..65649026a 100644
--- a/shared-module/adafruit_bus_device/SPIDevice.c
+++ b/shared-module/adafruit_bus_device/SPIDevice.c
@@ -84,7 +84,3 @@ void common_hal_adafruit_bus_device_spidevice_exit(adafruit_bus_device_spidevice
common_hal_busio_spi_unlock(self->spi);
}
-
-mp_obj_t common_hal_adafruit_bus_device_spidevice_get_spi(adafruit_bus_device_spidevice_obj_t *self) {
- return self->spi;
-}
diff --git a/tests/manual/audiocore/jeplayer-splash-16000-16bit-mono-signed.wav b/tests/manual/audiocore/jeplayer-splash-16000-16bit-mono-signed.wav
new file mode 100644
index 000000000..cd3da395b
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-16000-16bit-mono-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-16000-16bit-stereo-signed.wav b/tests/manual/audiocore/jeplayer-splash-16000-16bit-stereo-signed.wav
new file mode 100644
index 000000000..c1036475b
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-16000-16bit-stereo-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-16000-24bit-mono-signed.wav b/tests/manual/audiocore/jeplayer-splash-16000-24bit-mono-signed.wav
new file mode 100644
index 000000000..6aa6afc7a
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-16000-24bit-mono-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-16000-24bit-stereo-signed.wav b/tests/manual/audiocore/jeplayer-splash-16000-24bit-stereo-signed.wav
new file mode 100644
index 000000000..c175aaf61
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-16000-24bit-stereo-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-16000-8bit-mono-unsigned.wav b/tests/manual/audiocore/jeplayer-splash-16000-8bit-mono-unsigned.wav
new file mode 100644
index 000000000..ccf63b9c1
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-16000-8bit-mono-unsigned.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-16000-8bit-stereo-unsigned.wav b/tests/manual/audiocore/jeplayer-splash-16000-8bit-stereo-unsigned.wav
new file mode 100644
index 000000000..63aaa5b29
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-16000-8bit-stereo-unsigned.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-16bit-mono-signed.wav b/tests/manual/audiocore/jeplayer-splash-44100-16bit-mono-signed.wav
new file mode 100644
index 000000000..147b14b16
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-16bit-mono-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-16bit-stereo-signed.wav b/tests/manual/audiocore/jeplayer-splash-44100-16bit-stereo-signed.wav
new file mode 100644
index 000000000..adfe84fb0
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-16bit-stereo-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-24bit-mono-signed.wav b/tests/manual/audiocore/jeplayer-splash-44100-24bit-mono-signed.wav
new file mode 100644
index 000000000..2c5337045
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-24bit-mono-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-24bit-stereo-signed.wav b/tests/manual/audiocore/jeplayer-splash-44100-24bit-stereo-signed.wav
new file mode 100644
index 000000000..a290c6c37
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-24bit-stereo-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-8bit-mono-unsigned.wav b/tests/manual/audiocore/jeplayer-splash-44100-8bit-mono-unsigned.wav
new file mode 100644
index 000000000..cd1c79280
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-8bit-mono-unsigned.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-8bit-stereo-unsigned.wav b/tests/manual/audiocore/jeplayer-splash-44100-8bit-stereo-unsigned.wav
new file mode 100644
index 000000000..12c48e258
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-8bit-stereo-unsigned.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-44100-stereo.mp3 b/tests/manual/audiocore/jeplayer-splash-44100-stereo.mp3
new file mode 100644
index 000000000..fd820e69a
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-44100-stereo.mp3
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-8000-16bit-mono-signed.wav b/tests/manual/audiocore/jeplayer-splash-8000-16bit-mono-signed.wav
new file mode 100644
index 000000000..a730c2b84
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-8000-16bit-mono-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-8000-16bit-stereo-signed.wav b/tests/manual/audiocore/jeplayer-splash-8000-16bit-stereo-signed.wav
new file mode 100644
index 000000000..5038ae8ae
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-8000-16bit-stereo-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-8000-24bit-mono-signed.wav b/tests/manual/audiocore/jeplayer-splash-8000-24bit-mono-signed.wav
new file mode 100644
index 000000000..ac25cddb3
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-8000-24bit-mono-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-8000-24bit-stereo-signed.wav b/tests/manual/audiocore/jeplayer-splash-8000-24bit-stereo-signed.wav
new file mode 100644
index 000000000..6fec67431
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-8000-24bit-stereo-signed.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-8000-8bit-mono-unsigned.wav b/tests/manual/audiocore/jeplayer-splash-8000-8bit-mono-unsigned.wav
new file mode 100644
index 000000000..d5e49b24b
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-8000-8bit-mono-unsigned.wav
Binary files differ
diff --git a/tests/manual/audiocore/jeplayer-splash-8000-8bit-stereo-unsigned.wav b/tests/manual/audiocore/jeplayer-splash-8000-8bit-stereo-unsigned.wav
new file mode 100644
index 000000000..3df7945aa
--- /dev/null
+++ b/tests/manual/audiocore/jeplayer-splash-8000-8bit-stereo-unsigned.wav
Binary files differ
diff --git a/tests/manual/audiopwmio/single_buffer_loop.py b/tests/manual/audiopwmio/single_buffer_loop.py
new file mode 100644
index 000000000..dfac475b5
--- /dev/null
+++ b/tests/manual/audiopwmio/single_buffer_loop.py
@@ -0,0 +1,65 @@
+import audiocore
+import audiopwmio
+import board
+import digitalio
+import array
+import time
+import math
+
+trigger = digitalio.DigitalInOut(board.D4)
+trigger.switch_to_output(True)
+
+# Generate one period of sine wav.
+length = 8000 // 440
+
+samples = []
+sample_names = [
+"unsigned 8 bit",
+"signed 8 bit",
+"unsigned 16 bit",
+"signed 16 bit"
+]
+
+
+# unsigned 8 bit
+u8 = array.array("B", [0] * length)
+for i in range(length):
+ u8[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 7) + 2 ** 7)
+
+samples.append(audiocore.RawSample(u8, sample_rate=4000))
+
+# signed 8 bit
+s8 = array.array("b", [0] * length)
+for i in range(length):
+ s8[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 7))
+
+samples.append(audiocore.RawSample(s8, sample_rate=16000))
+
+# unsigned 16 bit
+u16 = array.array("H", [0] * length)
+for i in range(length):
+ u16[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
+
+samples.append(audiocore.RawSample(u16, sample_rate=8000))
+
+
+# signed 16 bit
+s16 = array.array("h", [0] * length)
+for i in range(length):
+ s16[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
+
+samples.append(audiocore.RawSample(s16, sample_rate=8000))
+
+
+dac = audiopwmio.PWMAudioOut(board.D13)
+for sample, name in zip(samples, sample_names):
+ print(name)
+ trigger.value = False
+ dac.play(sample, loop=True)
+ time.sleep(1)
+ dac.stop()
+ time.sleep(0.1)
+ trigger.value = True
+ print()
+
+print("done")
diff --git a/tests/manual/audiopwmio/wavefile_pause_resume.py b/tests/manual/audiopwmio/wavefile_pause_resume.py
new file mode 100644
index 000000000..27912d321
--- /dev/null
+++ b/tests/manual/audiopwmio/wavefile_pause_resume.py
@@ -0,0 +1,39 @@
+import audiocore
+import audiopwmio
+import board
+import digitalio
+import time
+import math
+import os
+
+trigger = digitalio.DigitalInOut(board.D4)
+trigger.switch_to_output(True)
+
+sample_prefix = "jeplayer-splash"
+
+samples = []
+for fn in os.listdir("/"):
+ if fn.startswith(sample_prefix):
+ samples.append(fn)
+
+dac = audiopwmio.PWMAudioOut(left_channel=board.D12, right_channel=board.D13)
+for filename in samples:
+ print("playing", filename)
+ with open(filename, "rb") as sample_file:
+ try:
+ sample = audiocore.WaveFile(sample_file)
+ except OSError as e:
+ print(e)
+ continue
+ trigger.value = False
+ dac.play(sample)
+ while dac.playing:
+ time.sleep(0.1)
+ dac.pause()
+ time.sleep(0.1)
+ dac.resume()
+ trigger.value = True
+ time.sleep(0.1)
+ print()
+
+print("done")
diff --git a/tests/manual/audiopwmio/wavefile_playback.py b/tests/manual/audiopwmio/wavefile_playback.py
new file mode 100644
index 000000000..0adbf2b19
--- /dev/null
+++ b/tests/manual/audiopwmio/wavefile_playback.py
@@ -0,0 +1,36 @@
+import audiocore
+import audiopwmio
+import board
+import digitalio
+import time
+import math
+import os
+
+trigger = digitalio.DigitalInOut(board.D4)
+trigger.switch_to_output(True)
+
+sample_prefix = "jeplayer-splash"
+
+samples = []
+for fn in os.listdir("/"):
+ if fn.startswith(sample_prefix):
+ samples.append(fn)
+
+dac = audiopwmio.PWMAudioOut(left_channel=board.D12, right_channel=board.D13)
+for filename in samples:
+ print("playing", filename)
+ with open(filename, "rb") as sample_file:
+ try:
+ sample = audiocore.WaveFile(sample_file)
+ except OSError as e:
+ print(e)
+ continue
+ trigger.value = False
+ dac.play(sample)
+ while dac.playing:
+ time.sleep(1)
+ trigger.value = True
+ time.sleep(0.1)
+ print()
+
+print("done")