diff options
52 files changed, 1462 insertions, 165 deletions
diff --git a/.travis.yml b/.travis.yml index 5f27bb256..4863b9542 100755 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ git: # that SDK is shortest and add it there. In the case of major re-organizations, # just try to make the builds "about equal in run time" env: - - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="trinket_m0_haxpress circuitplayground_express mini_sam_m4 grandcentral_m4_express capablerobot_usbhub pygamer pca10056 pca10059 feather_nrf52840_express makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini electronut_labs_papyr electronut_labs_blip" TRAVIS_SDK=arm:nrf + - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="trinket_m0_haxpress circuitplayground_express mini_sam_m4 grandcentral_m4_express capablerobot_usbhub pygamer pca10056 pca10059 feather_nrf52840_express metro_nrf52840_express makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini electronut_labs_papyr electronut_labs_blip" TRAVIS_SDK=arm:nrf - TRAVIS_BOARDS="metro_m0_express metro_m4_express metro_m4_airlift_lite pirkey_m0 trellis_m4_express trinket_m0 sparkfun_lumidrive sparkfun_redboard_turbo bast_pro_mini_m0 datum_distance pyruler" TRAVIS_SDK=arm - TRAVIS_BOARDS="cp32-m4 feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow sam32 uchip escornabot_makech pygamer_advance datum_imu snekboard" TRAVIS_SDK=arm - TRAVIS_BOARDS="feather_m0_supersized feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300 arduino_mkrzero pewpew10 kicksat-sprite ugame10 robohatmm1_m0 robohatmm1_m4 datum_light" TRAVIS_SDK=arm @@ -88,7 +88,7 @@ before_script: # Check if there's any board missing in TRAVIS_BOARDS - cd tools && python3 -u travis_new_boards_check.py - cd .. - + # report some good version numbers to the build - gcc --version - (! var_search "${TRAVIS_SDK-}" arm || arm-none-eabi-gcc --version) diff --git a/locale/ID.po b/locale/ID.po index bd12a5c94..e8fdf3595 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -255,6 +255,7 @@ msgstr "Semua timer untuk pin ini sedang digunakan" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -329,6 +330,11 @@ msgstr "" msgid "Buffer incorrect size. Should be %d bytes." msgstr "" +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "" @@ -951,6 +957,7 @@ msgid "Not connected" msgstr "Tidak dapat menyambungkan ke AP" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "" @@ -1080,6 +1087,7 @@ msgid "Sample rate must be positive" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d" @@ -1168,7 +1176,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2445,10 +2457,6 @@ msgstr "sintaksis error pada pendeskripsi uctypes" msgid "threshold must be in the range 0-65536" msgstr "" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 1b135822f..a2e66cc5d 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -253,6 +253,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -325,6 +326,11 @@ msgstr "" msgid "Buffer incorrect size. Should be %d bytes." msgstr "" +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "" @@ -935,6 +941,7 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "" @@ -1060,6 +1067,7 @@ msgid "Sample rate must be positive" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -1145,7 +1153,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2409,10 +2421,6 @@ msgstr "" msgid "threshold must be in the range 0-65536" msgstr "" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 7ad69e1dd..3037a5369 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: Pascal Deneaux\n" "Language-Team: Sebastian Plamauer, Pascal Deneaux\n" @@ -255,6 +255,7 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -329,6 +330,11 @@ msgstr "Die Helligkeit ist nicht einstellbar" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Der Puffergröße ist inkorrekt. Sie sollte %d bytes haben." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Der Puffer muss eine Mindestenslänge von 1 haben" @@ -948,6 +954,7 @@ msgid "Not connected" msgstr "Nicht verbunden" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "Spielt nicht" @@ -1077,6 +1084,7 @@ msgid "Sample rate must be positive" msgstr "Abtastrate muss positiv sein" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Abtastrate zu hoch. Wert muss unter %d liegen" @@ -1174,7 +1182,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2461,10 +2473,6 @@ msgstr "Syntaxfehler in uctypes Deskriptor" msgid "threshold must be in the range 0-65536" msgstr "threshold muss im Intervall 0-65536 liegen" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/en_US.po b/locale/en_US.po index 49699283c..6d15af4dd 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: \n" @@ -253,6 +253,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -325,6 +326,11 @@ msgstr "" msgid "Buffer incorrect size. Should be %d bytes." msgstr "" +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "" @@ -935,6 +941,7 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "" @@ -1060,6 +1067,7 @@ msgid "Sample rate must be positive" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -1145,7 +1153,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2409,10 +2421,6 @@ msgstr "" msgid "threshold must be in the range 0-65536" msgstr "" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po index 885abe681..57bb45380 100644 --- a/locale/en_x_pirate.po +++ b/locale/en_x_pirate.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: @sommersoft, @MrCertainly\n" @@ -255,6 +255,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -329,6 +330,11 @@ msgstr "" msgid "Buffer incorrect size. Should be %d bytes." msgstr "" +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "" @@ -939,6 +945,7 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "" @@ -1064,6 +1071,7 @@ msgid "Sample rate must be positive" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -1149,7 +1157,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2413,10 +2425,6 @@ msgstr "" msgid "threshold must be in the range 0-65536" msgstr "" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/es.po b/locale/es.po index 772570a31..a3ffe5799 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-07-31 16:30-0500\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n" "Last-Translator: \n" "Language-Team: \n" @@ -257,6 +257,7 @@ msgstr "Todos los timers para este pin están siendo utilizados" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -333,6 +334,11 @@ msgstr "El brillo no se puede ajustar" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Tamaño de buffer incorrecto. Debe ser de %d bytes." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Buffer debe ser de longitud 1 como minimo" @@ -950,6 +956,7 @@ msgid "Not connected" msgstr "No conectado" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "No reproduciendo" @@ -1088,6 +1095,7 @@ msgid "Sample rate must be positive" msgstr "Sample rate debe ser positivo" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d" @@ -1185,8 +1193,12 @@ msgid "Tile height must exactly divide bitmap height" msgstr "La altura del Tile debe dividir exacto la altura del bitmap" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" -msgstr "Los índices de Tile deben ser 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" +msgstr "" #: shared-bindings/displayio/TileGrid.c msgid "Tile width must exactly divide bitmap width" @@ -2476,10 +2488,6 @@ msgstr "error de sintaxis en el descriptor uctypes" msgid "threshold must be in the range 0-65536" msgstr "limite debe ser en el rango 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "el indice del tile fuera de limite" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() toma un sequencio 9" @@ -2836,6 +2844,9 @@ msgstr "paso cero" #~ msgid "STA required" #~ msgstr "STA requerido" +#~ msgid "Tile indices must be 0 - 255" +#~ msgstr "Los índices de Tile deben ser 0 - 255" + #~ msgid "UART(%d) does not exist" #~ msgstr "UART(%d) no existe" @@ -2937,6 +2948,9 @@ msgstr "paso cero" #~ msgid "services includes an object that is not a Service" #~ msgstr "services incluye un objeto que no es servicio" +#~ msgid "tile index out of bounds" +#~ msgstr "el indice del tile fuera de limite" + #~ msgid "too many arguments" #~ msgstr "muchos argumentos" diff --git a/locale/fil.po b/locale/fil.po index 8e4dbd9fd..f83429882 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-07-31 16:30-0500\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy <me@timothygarcia.ca>\n" "Language-Team: fil\n" @@ -257,6 +257,7 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -331,6 +332,11 @@ msgstr "" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Mali ang size ng buffer. Dapat %d bytes." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Buffer dapat ay hindi baba sa 1 na haba" @@ -960,6 +966,7 @@ msgid "Not connected" msgstr "Hindi maka connect sa AP" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "Hindi playing" @@ -1093,6 +1100,7 @@ msgid "Sample rate must be positive" msgstr "Sample rate ay dapat positibo" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Sample rate ay masyadong mataas. Ito ay dapat hindi hiigit sa %d" @@ -1188,7 +1196,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2486,10 +2498,6 @@ msgstr "may pagkakamali sa sintaks sa uctypes descriptor" msgid "threshold must be in the range 0-65536" msgstr "ang threshold ay dapat sa range 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() kumukuha ng 9-sequence" diff --git a/locale/fr.po b/locale/fr.po index 5bb51b622..07355526f 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-07-31 16:30-0500\n" "PO-Revision-Date: 2019-04-14 20:05+0100\n" "Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n" "Language-Team: fr\n" @@ -260,6 +260,7 @@ msgstr "Tous les timers pour cette broche sont utilisés" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -336,6 +337,11 @@ msgstr "Luminosité non-ajustable" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Tampon de taille incorrect. Devrait être de %d octets." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Le tampon doit être de longueur au moins 1" @@ -969,6 +975,7 @@ msgid "Not connected" msgstr "Non connecté" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "Ne joue pas" @@ -1110,6 +1117,7 @@ msgid "Sample rate must be positive" msgstr "Le taux d'échantillonage doit être positif" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Taux d'échantillonage trop élevé. Doit être inf. à %d" @@ -1209,8 +1217,12 @@ msgid "Tile height must exactly divide bitmap height" msgstr "La hauteur de la tuile doit diviser exactement la hauteur de l'image" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" -msgstr "Les indices des tuiles doivent être compris entre 0 et 255 " +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" +msgstr "" #: shared-bindings/displayio/TileGrid.c msgid "Tile width must exactly divide bitmap width" @@ -2528,10 +2540,6 @@ msgstr "erreur de syntaxe dans le descripteur d'uctypes" msgid "threshold must be in the range 0-65536" msgstr "le seuil doit être dans la gamme 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "indice de tuile hors limites" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() prend une séquence de longueur 9" @@ -2887,6 +2895,9 @@ msgstr "'step' nul" #~ msgid "STA required" #~ msgstr "'STA' requis" +#~ msgid "Tile indices must be 0 - 255" +#~ msgstr "Les indices des tuiles doivent être compris entre 0 et 255 " + #~ msgid "UART(%d) does not exist" #~ msgstr "UART(%d) n'existe pas" @@ -2983,6 +2994,9 @@ msgstr "'step' nul" #~ msgid "services includes an object that is not a Service" #~ msgstr "'services' inclut un object qui n'est pas un 'Service'" +#~ msgid "tile index out of bounds" +#~ msgstr "indice de tuile hors limites" + #~ msgid "too many arguments" #~ msgstr "trop d'arguments" diff --git a/locale/it_IT.po b/locale/it_IT.po index 2f8cfdc1e..4360cd221 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-07-31 16:30-0500\n" "PO-Revision-Date: 2018-10-02 16:27+0200\n" "Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n" "Language-Team: \n" @@ -256,6 +256,7 @@ msgstr "Tutti i timer per questo pin sono in uso" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -331,6 +332,11 @@ msgstr "Illiminazione non è regolabile" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Buffer di lunghezza non valida. Dovrebbe essere di %d bytes." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Il buffer deve essere lungo almeno 1" @@ -959,6 +965,7 @@ msgid "Not connected" msgstr "Impossible connettersi all'AP" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "In pausa" @@ -1098,6 +1105,7 @@ msgid "Sample rate must be positive" msgstr "STA deve essere attiva" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -1187,7 +1195,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2484,10 +2496,6 @@ msgstr "errore di sintassi nel descrittore uctypes" msgid "threshold must be in the range 0-65536" msgstr "la soglia deve essere nell'intervallo 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/pl.po b/locale/pl.po index 83e408a3d..0a38aa914 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski <circuitpython@sheep.art.pl>\n" "Language-Team: pl\n" @@ -254,6 +254,7 @@ msgstr "Wszystkie timery tej nóżki w użyciu" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -328,6 +329,11 @@ msgstr "Jasność nie jest regulowana" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Zła wielkość bufora. Powinno być %d bajtów." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Bufor musi mieć długość 1 lub więcej" @@ -945,6 +951,7 @@ msgid "Not connected" msgstr "Nie podłączono" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "Nic nie jest odtwarzane" @@ -1070,6 +1077,7 @@ msgid "Sample rate must be positive" msgstr "Częstotliwość próbkowania musi być dodatnia" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Zbyt wysoka częstotliwość próbkowania. Musi być mniejsza niż %d" @@ -1165,8 +1173,12 @@ msgid "Tile height must exactly divide bitmap height" msgstr "Wysokość bitmapy musi być wielokrotnością wysokości kafelka" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" -msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" +msgstr "" #: shared-bindings/displayio/TileGrid.c msgid "Tile width must exactly divide bitmap width" @@ -2436,10 +2448,6 @@ msgstr "błąd składni w deskryptorze uctypes" msgid "threshold must be in the range 0-65536" msgstr "threshold musi być w zakresie 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "indeks kafelka poza zakresem" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() wymaga 9-elementowej sekwencji" @@ -2694,6 +2702,9 @@ msgstr "zerowy krok" #~ msgid "Must be a Group subclass." #~ msgstr "Musi dziedziczyć z Group." +#~ msgid "Tile indices must be 0 - 255" +#~ msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie" + #~ msgid "UUID integer value not in range 0 to 0xffff" #~ msgstr "Wartość UUID poza zakresem 0 do 0xffff" @@ -2702,3 +2713,6 @@ msgstr "zerowy krok" #~ msgid "services includes an object that is not a Service" #~ msgstr "obiekt typu innego niż Service w services" + +#~ msgid "tile index out of bounds" +#~ msgstr "indeks kafelka poza zakresem" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index d3a8fe50a..defeb3e44 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-07-31 16:30-0500\n" "PO-Revision-Date: 2018-10-02 21:14-0000\n" "Last-Translator: \n" "Language-Team: \n" @@ -256,6 +256,7 @@ msgstr "Todos os temporizadores para este pino estão em uso" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -328,6 +329,11 @@ msgstr "" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Buffer de tamanho incorreto. Deve ser %d bytes." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "" @@ -951,6 +957,7 @@ msgid "Not connected" msgstr "Não é possível conectar-se ao AP" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "" @@ -1080,6 +1087,7 @@ msgid "Sample rate must be positive" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Taxa de amostragem muito alta. Deve ser menor que %d" @@ -1165,7 +1173,11 @@ msgid "Tile height must exactly divide bitmap height" msgstr "" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" msgstr "" #: shared-bindings/displayio/TileGrid.c @@ -2437,10 +2449,6 @@ msgstr "" msgid "threshold must be in the range 0-65536" msgstr "Limite deve estar no alcance de 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 055dd5461..c0537202c 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-25 22:48-0700\n" +"POT-Creation-Date: 2019-08-05 17:52-0700\n" "PO-Revision-Date: 2019-04-13 10:10-0700\n" "Last-Translator: hexthat\n" "Language-Team: Chinese Hanyu Pinyin\n" @@ -255,6 +255,7 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/pulseio/PulseOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c #: shared-module/_pew/PewPew.c msgid "All timers in use" @@ -329,6 +330,11 @@ msgstr "Liàngdù wúfǎ tiáozhěng" msgid "Buffer incorrect size. Should be %d bytes." msgstr "Huǎnchōng qū dàxiǎo bù zhèngquè. Yīnggāi shì %d zì jié." +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c +#, c-format +msgid "Buffer length %d too big. It must be less than %d" +msgstr "" + #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" msgstr "Huǎnchōng qū bìxū zhìshǎo chángdù 1" @@ -945,6 +951,7 @@ msgid "Not connected" msgstr "Wèi liánjiē" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" msgstr "Wèi bòfàng" @@ -1075,6 +1082,7 @@ msgid "Sample rate must be positive" msgstr "Cǎiyàng lǜ bìxū wèi zhèng shù" #: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "Cǎiyàng lǜ tài gāo. Tā bìxū xiǎoyú %d" @@ -1128,8 +1136,9 @@ msgstr "" msgid "" "The `microcontroller` module was used to boot into safe mode. Press reset to " "exit safe mode.\n" -msgstr "“Wēi kòngzhì qì” mókuài yòng yú qǐdòng ānquán móshì. Àn chóng zhì kě " -"tuìchū ānquán móshì.\n" +msgstr "" +"“Wēi kòngzhì qì” mókuài yòng yú qǐdòng ānquán móshì. Àn chóng zhì kě tuìchū " +"ānquán móshì.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -1171,8 +1180,12 @@ msgid "Tile height must exactly divide bitmap height" msgstr "Píng pū gāodù bìxū huàfēn wèi tú gāodù" #: shared-bindings/displayio/TileGrid.c -msgid "Tile indices must be 0 - 255" -msgstr "Píng pū zhǐshù bìxū wèi 0 - 255" +msgid "Tile index out of bounds" +msgstr "" + +#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +msgid "Tile value out of bounds" +msgstr "" #: shared-bindings/displayio/TileGrid.c msgid "Tile width must exactly divide bitmap width" @@ -2449,10 +2462,6 @@ msgstr "uctypes miáoshù fú zhōng de yǔfǎ cuòwù" msgid "threshold must be in the range 0-65536" msgstr "yùzhí bìxū zài fànwéi 0-65536" -#: shared-bindings/displayio/TileGrid.c -msgid "tile index out of bounds" -msgstr "kuài suǒyǐn chāochū fànwéi" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() xūyào 9 xùliè" @@ -2719,6 +2728,9 @@ msgstr "líng bù" #~ msgid "Only bit maps of 8 bit color or less are supported" #~ msgstr "Jǐn zhīchí 8 wèi yánsè huò xiǎoyú" +#~ msgid "Tile indices must be 0 - 255" +#~ msgstr "Píng pū zhǐshù bìxū wèi 0 - 255" + #~ msgid "UUID integer value not in range 0 to 0xffff" #~ msgstr "UUID zhěngshù zhí bùzài fànwéi 0 zhì 0xffff" @@ -2734,6 +2746,9 @@ msgstr "líng bù" #~ msgid "services includes an object that is not a Service" #~ msgstr "fúwù bāokuò yīgè bùshì fúwù de wùjiàn" +#~ msgid "tile index out of bounds" +#~ msgstr "kuài suǒyǐn chāochū fànwéi" + #~ msgid "too many arguments" #~ msgstr "tài duō cānshù" diff --git a/ports/nrf/background.c b/ports/nrf/background.c index 9c4f3ab27..453bc96df 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -33,6 +33,10 @@ #include "shared-module/displayio/__init__.h" #endif +#if CIRCUITPY_AUDIOPWMIO +#include "common-hal/audiopwmio/PWMAudioOut.h" +#endif + static bool running_background_tasks = false; void background_tasks_reset(void) { @@ -47,6 +51,9 @@ void run_background_tasks(void) { running_background_tasks = true; filesystem_background(); usb_background(); +#if CIRCUITPY_AUDIOPWMIO + audiopwmout_background(); +#endif #if CIRCUITPY_DISPLAYIO displayio_refresh_displays(); diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index e1f43e3c9..70ccffc3f 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -27,8 +27,6 @@ #include "nrfx/hal/nrf_gpio.h" -#define FEATHER52840 - #define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "Feather52840Express" diff --git a/ports/nrf/boards/metro_nrf52840_express/board.c b/ports/nrf/boards/metro_nrf52840_express/board.c new file mode 100644 index 000000000..4421970ee --- /dev/null +++ b/ports/nrf/boards/metro_nrf52840_express/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h new file mode 100644 index 000000000..520eef90d --- /dev/null +++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h @@ -0,0 +1,73 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "nrfx/hal/nrf_gpio.h" + +#define MICROPY_HW_BOARD_NAME "Adafruit Metro nRF52840 Express" +#define MICROPY_HW_MCU_NAME "nRF52840" +#define MICROPY_PY_SYS_PLATFORM "Metro52840Express" + +#define FLASH_SIZE (0x100000) +#define FLASH_PAGE_SIZE (4096) + +#define MICROPY_HW_NEOPIXEL (&pin_P0_13) + +#define MICROPY_HW_LED_STATUS (&pin_P1_13) + +#if QSPI_FLASH_FILESYSTEM +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20) +#endif + +#if SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_17 +#define SPI_FLASH_MISO_PIN &pin_P0_23 +#define SPI_FLASH_SCK_PIN &pin_P0_19 +#define SPI_FLASH_CS_PIN &pin_P0_20 +#endif + +#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 + +#define CIRCUITPY_INTERNAL_NVM_SIZE (4096) + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_P0_16) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_15) + +#define DEFAULT_SPI_BUS_SCK (&pin_P0_07) +#define DEFAULT_SPI_BUS_MOSI (&pin_P1_08) +#define DEFAULT_SPI_BUS_MISO (&pin_P0_11) + +#define DEFAULT_UART_BUS_RX (&pin_P0_24) +#define DEFAULT_UART_BUS_TX (&pin_P0_25) diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk new file mode 100644 index 000000000..4c1c93c10 --- /dev/null +++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk @@ -0,0 +1,26 @@ +USB_VID = 0x239A +USB_PID = 0x8040 +USB_PRODUCT = "Metro nRF52840 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +MCU_CHIP = nrf52840 +SD ?= s140 +SOFTDEV_VERSION ?= 6.1.0 + +BOOT_SETTING_ADDR = 0xFF000 + +ifeq ($(SD),) + LD_FILE = boards/nrf52840_1M_256k.ld +else + LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld + CIRCUITPY_BLEIO = 1 +endif + +NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q16C" diff --git a/ports/nrf/boards/metro_nrf52840_express/pins.c b/ports/nrf/boards/metro_nrf52840_express/pins.c new file mode 100644 index 000000000..452e31202 --- /dev/null +++ b/ports/nrf/boards/metro_nrf52840_express/pins.c @@ -0,0 +1,56 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) }, + + { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_31) }, + + { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P1_02) }, + + { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) }, + + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_24) }, + + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_25) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P1_14) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P1_09) }, + { MP_ROM_QSTR(MP_QSTR_D13),MP_ROM_PTR(&pin_P0_14) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_16) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_P0_13) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_11) }, + + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_13) }, + { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P1_13) }, + + { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P1_15) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/nrf/boards/particle_argon/mpconfigboard.h b/ports/nrf/boards/particle_argon/mpconfigboard.h index 0ee785c31..a4ecb2bb4 100644 --- a/ports/nrf/boards/particle_argon/mpconfigboard.h +++ b/ports/nrf/boards/particle_argon/mpconfigboard.h @@ -27,8 +27,6 @@ #include "nrfx/hal/nrf_gpio.h" -#define FEATHER52840 - #define MICROPY_HW_BOARD_NAME "Particle Argon" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "Particle Argon" diff --git a/ports/nrf/boards/particle_boron/mpconfigboard.h b/ports/nrf/boards/particle_boron/mpconfigboard.h index b814fc694..5e817311f 100644 --- a/ports/nrf/boards/particle_boron/mpconfigboard.h +++ b/ports/nrf/boards/particle_boron/mpconfigboard.h @@ -27,8 +27,6 @@ #include "nrfx/hal/nrf_gpio.h" -#define FEATHER52840 - #define MICROPY_HW_BOARD_NAME "Particle Boron" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "Particle Boron" diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h index c8da66736..6c8cc7cef 100644 --- a/ports/nrf/boards/particle_xenon/mpconfigboard.h +++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h @@ -27,8 +27,6 @@ #include "nrfx/hal/nrf_gpio.h" -#define FEATHER52840 - #define MICROPY_HW_BOARD_NAME "Particle Xenon" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "Particle Xenon" diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c new file mode 100644 index 000000000..0321b751c --- /dev/null +++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c @@ -0,0 +1,316 @@ +/* + * 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 <stdint.h> +#include <string.h> + +#include "extmod/vfs_fat.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "common-hal/audiopwmio/PWMAudioOut.h" +#include "common-hal/pulseio/PWMOut.h" +#include "shared-bindings/audiopwmio/PWMAudioOut.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/shared/translate.h" + +// TODO: This should be the same size as PWMOut.c:pwms[], but there's no trivial way to accomplish that +STATIC audiopwmio_pwmaudioout_obj_t* active_audio[4]; + +#define F_TARGET (62500) +#define F_PWM (16000000) +// return the REFRESH value, store the TOP value in an out-parameter +// Tested for key values (worst relative error = 0.224% = 3.84 cents) +// 8000: top = 250 refresh = 7 [ 8000.0] +// 22050: top = 242 refresh = 2 [22038.5] +// 24000: top = 222 refresh = 2 [24024.0] +// 44100: top = 181 refresh = 1 [44198.8] +// 48000: top = 167 refresh = 1 [47904.1] +STATIC uint32_t calculate_pwm_parameters(uint32_t sample_rate, uint32_t *top_out) { + // the desired frequency is the closest integer multiple of sample_rate not less than F_TARGET + uint32_t desired_frequency = (F_TARGET + sample_rate - 1) / sample_rate * sample_rate; + // The top value is the PWM frequency divided by the desired frequency (round to nearest) + uint32_t top = (F_PWM + desired_frequency/2) / desired_frequency; + // The actual frequency is the PWM frequency divided by the top value (round to nearest) + uint32_t actual_frequency = (F_PWM + top/2) / top; + // The multiplier is the actual frequency divided by the sample rate (round to nearest) + uint32_t multiplier = (actual_frequency + sample_rate/2) / sample_rate; + *top_out = top; + return multiplier - 1; +} + +STATIC void activate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) { + for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) { + if(!active_audio[i]) { + active_audio[i] = self; + break; + } + } +} +STATIC void deactivate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) { + for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) { + if(active_audio[i] == self) + active_audio[i] = NULL; + } +} + +void audiopwmout_reset() { + for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) + active_audio[i] = NULL; +} + +STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) { + self->pwm->EVENTS_SEQSTARTED[1-buf] = 0; + uint16_t *dev_buffer = self->buffers[buf]; + uint8_t *buffer; + uint32_t buffer_length; + audioio_get_buffer_result_t get_buffer_result = + audiosample_get_buffer(self->sample, false, 0, + &buffer, &buffer_length); + if (get_buffer_result == GET_BUFFER_ERROR) { + common_hal_audiopwmio_pwmaudioout_stop(self); + return; + } + uint32_t num_samples = buffer_length / self->bytes_per_sample / self->spacing; + + if(self->bytes_per_sample == 1) { + uint8_t offset = self->signed_to_unsigned ? 0x80 : 0; + uint16_t scale = self->scale; + for(uint32_t i=0; i<buffer_length/self->spacing; i++) { + uint8_t rawval = (*buffer++ + offset); + uint16_t val = (uint16_t)(((uint32_t)rawval * (uint32_t)scale) >> 8); + *dev_buffer++ = val; + if(self->spacing == 1) + *dev_buffer++ = val; + } + } else { + uint16_t offset = self->signed_to_unsigned ? 0x8000 : 0; + uint16_t scale = self->scale; + uint16_t *buffer16 = (uint16_t*)buffer; + for(uint32_t i=0; i<buffer_length/2/self->spacing; i++) { + uint16_t rawval = (*buffer16++ + offset); + uint16_t val = (uint16_t)((rawval * (uint32_t)scale) >> 16); + *dev_buffer++ = val; + if(self->spacing == 1) + *dev_buffer++ = val; + } + } + self->pwm->SEQ[buf].PTR = (intptr_t)self->buffers[buf]; + self->pwm->SEQ[buf].CNT = num_samples*2; + + if (self->loop && get_buffer_result == GET_BUFFER_DONE) { + audiosample_reset_buffer(self->sample, false, 0); + } else if(get_buffer_result == GET_BUFFER_DONE) { + self->pwm->SHORTS = NRF_PWM_SHORT_SEQEND0_STOP_MASK | NRF_PWM_SHORT_SEQEND1_STOP_MASK; + self->stopping = true; + } +} + +STATIC void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) { + if(!common_hal_audiopwmio_pwmaudioout_get_playing(self)) + return; + if(self->stopping) { + bool stopped = + (self->pwm->EVENTS_SEQEND[0] || !self->pwm->EVENTS_SEQSTARTED[0]) && + (self->pwm->EVENTS_SEQEND[1] || !self->pwm->EVENTS_SEQSTARTED[1]); + if(stopped) + self->pwm->TASKS_STOP = 1; + } else if(!self->paused && !self->single_buffer) { + if(self->pwm->EVENTS_SEQSTARTED[0]) fill_buffers(self, 1); + if(self->pwm->EVENTS_SEQSTARTED[1]) fill_buffers(self, 0); + } +} + +void audiopwmout_background() { + for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) { + if(!active_audio[i]) continue; + audiopwmout_background_obj(active_audio[i]); + } +} + +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) { + assert_pin_free(left_channel); + assert_pin_free(right_channel); + self->pwm = pwmout_allocate(256, PWM_PRESCALER_PRESCALER_DIV_1, true, NULL, NULL); + if(!self->pwm) { + mp_raise_RuntimeError(translate("All timers in use")); + } + + self->pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1; + // two uint16_t values per sample when Grouped + // n.b. SEQ[#].CNT "counts" are 2 per sample (left and right channels) + self->pwm->DECODER = PWM_DECODER_LOAD_Grouped; + + // we use channels 0 and 2 because these are GROUPED; it lets us save half + // the space for sample data (no additional optimization is possible for + // single channel) + self->pwm->PSEL.OUT[0] = self->left_channel_number = left_channel->number; + claim_pin(left_channel); + + if(right_channel) + { + self->pwm->PSEL.OUT[2] = self->right_channel_number = right_channel->number; + claim_pin(right_channel); + } + + self->quiescent_value = quiescent_value >> 8; + + self->pwm->ENABLE = 1; + // TODO: Ramp from 0 to quiescent value +} + +bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self) { + return !self->pwm; +} + +void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self) { + if (common_hal_audiopwmio_pwmaudioout_deinited(self)) { + return; + } + // TODO: ramp the pwm down from quiescent value to 0 + self->pwm->ENABLE = 0; + + if(self->left_channel_number) + reset_pin_number(self->left_channel_number); + if(self->right_channel_number) + reset_pin_number(self->right_channel_number); + + pwmout_free_channel(self->pwm, 0); + pwmout_free_channel(self->pwm, 2); + + self->pwm = NULL; + + m_free(self->buffers[0]); + self->buffers[0] = NULL; + + m_free(self->buffers[1]); + self->buffers[1] = NULL; +} + +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); + } + self->sample = sample; + self->loop = loop; + + uint32_t sample_rate = audiosample_sample_rate(sample); + uint32_t max_sample_rate = 62500; + if (sample_rate > max_sample_rate) { + mp_raise_ValueError_varg(translate("Sample rate too high. It must be less than %d"), max_sample_rate); + } + self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; + + uint32_t max_buffer_length; + audiosample_get_buffer_structure(sample, /* single channel */ false, + &self->single_buffer, &self->signed_to_unsigned, &max_buffer_length, + &self->spacing); + if(max_buffer_length > UINT16_MAX) { + mp_raise_ValueError_varg(translate("Buffer length %d too big. It must be less than %d"), max_buffer_length, UINT16_MAX); + } + self->buffer_length = (uint16_t)max_buffer_length; + self->buffers[0] = m_malloc(self->buffer_length * 2 * sizeof(uint16_t), false); + if(!self->single_buffer) + self->buffers[1] = m_malloc(self->buffer_length * 2 * sizeof(uint16_t), false); + + + uint32_t top; + self->pwm->SEQ[0].REFRESH = self->pwm->SEQ[1].REFRESH = calculate_pwm_parameters(sample_rate, &top); + self->scale = top-1; + self->pwm->COUNTERTOP = top; + + self->pwm->LOOP = 1; + audiosample_reset_buffer(self->sample, false, 0); + activate_audiopwmout_obj(self); + fill_buffers(self, 0); + self->pwm->SEQ[1].PTR = self->pwm->SEQ[0].PTR; + self->pwm->SEQ[1].CNT = self->pwm->SEQ[0].CNT; + self->pwm->EVENTS_SEQSTARTED[0] = 0; + self->pwm->EVENTS_SEQSTARTED[1] = 0; + self->pwm->EVENTS_STOPPED = 0; + self->pwm->SHORTS = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK; + self->pwm->TASKS_SEQSTART[0] = 1; + self->playing = true; + self->stopping = false; + self->paused = false; +} + +void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self) { + deactivate_audiopwmout_obj(self); + self->pwm->TASKS_STOP = 1; + self->stopping = false; + self->paused = false; + + m_free(self->buffers[0]); + self->buffers[0] = NULL; + + m_free(self->buffers[1]); + self->buffers[1] = NULL; +} + +bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self) { + if(!self->paused && self->pwm->EVENTS_STOPPED) { + self->playing = false; + self->pwm->EVENTS_STOPPED = 0; + } + return self->playing; +} + +/* pause/resume present difficulties for the NRF PWM audio module. + * + * A PWM sequence can be stopped in its tracks by sending a TASKS_STOP event, + * but there's no way to pick up the sequence where it was stopped; you could + * start at the start of one of the two sequences, but especially for "single buffer" + * sample, this seems undesirable. + * + * Or, you can stop at the end of a sequence so that you don't duplicate anything + * when restarting, but again this is unsatisfactory for a "single buffer" sample. + * + * For now, I've taken the coward's way and left these methods unimplemented. + * Perhaps the way forward is to divide even "single buffer" samples into tasks of + * only a few ms long, so that they can be stopped/restarted quickly enough that it + * feels instant. (This also saves on memory, for long in-memory "single buffer" + * samples, since we have to locally take a resampled copy!) + */ +void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self) { + self->paused = true; + self->pwm->SHORTS = NRF_PWM_SHORT_SEQEND1_STOP_MASK; +} + +void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self) { + self->paused = false; + self->pwm->SHORTS = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK; + if (self->pwm->EVENTS_STOPPED) { + self->pwm->EVENTS_STOPPED = 0; + self->pwm->TASKS_SEQSTART[0] = 1; + } +} + +bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self) { + return self->paused; +} diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h new file mode 100644 index 000000000..8deff5d34 --- /dev/null +++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h @@ -0,0 +1,59 @@ +/* + * 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_NRF_COMMON_HAL_AUDIOPWM_AUDIOOUT_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOPWM_AUDIOOUT_H + +#include "common-hal/microcontroller/Pin.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t *sample; + NRF_PWM_Type *pwm; + uint16_t *buffers[2]; + + uint16_t buffer_length; + uint16_t quiescent_value; + uint16_t scale; + + uint8_t left_channel_number; + uint8_t right_channel_number; + uint8_t spacing; + uint8_t bytes_per_sample; + + bool playing; + bool stopping; + bool paused; + bool loop; + bool signed_to_unsigned; + bool single_buffer; +} audiopwmio_pwmaudioout_obj_t; + +void audiopwmout_reset(void); + +void audiopwmout_background(void); + +#endif diff --git a/ports/nrf/common-hal/audiopwmio/__init__.c b/ports/nrf/common-hal/audiopwmio/__init__.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/nrf/common-hal/audiopwmio/__init__.c diff --git a/ports/nrf/common-hal/pulseio/PWMOut.c b/ports/nrf/common-hal/pulseio/PWMOut.c index 5233c9adc..b827470d3 100644 --- a/ports/nrf/common-hal/pulseio/PWMOut.c +++ b/ports/nrf/common-hal/pulseio/PWMOut.c @@ -57,6 +57,12 @@ STATIC uint16_t pwm_seq[MP_ARRAY_SIZE(pwms)][CHANNELS_PER_PWM]; static uint8_t never_reset_pwm[MP_ARRAY_SIZE(pwms)]; +STATIC int pwm_idx(NRF_PWM_Type *pwm) { + for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) + if(pwms[i] == pwm) return i; + return -1; +} + void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) { for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) { NRF_PWM_Type* pwm = pwms[i]; @@ -133,29 +139,11 @@ bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t * return false; } -pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, - const mcu_pin_obj_t* pin, - uint16_t duty, - uint32_t frequency, - bool variable_frequency) { - - // We don't use the nrfx driver here because we want to dynamically allocate channels - // as needed in an already-enabled PWM. - - uint16_t countertop; - nrf_pwm_clk_t base_clock; - if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) { - return PWMOUT_INVALID_FREQUENCY; - } - - self->pwm = NULL; - self->channel = CHANNELS_PER_PWM; // out-of-range value. - bool pwm_already_in_use; - NRF_PWM_Type* pwm; - size_t pwm_index = 0; - for (; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) { - pwm = pwms[pwm_index]; - pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk; +NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock, + bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out) { + for (size_t pwm_index = 0; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) { + NRF_PWM_Type *pwm = pwms[pwm_index]; + bool pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk; if (pwm_already_in_use) { if (variable_frequency) { // Variable frequency requires exclusive use of a PWM, so try the next one. @@ -168,28 +156,65 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) { if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) { // Channel is free. - self->pwm = pwm; - self->channel = chan; - break; + if(channel_out) + *channel_out = chan; + if(pwm_already_in_use_out) + *pwm_already_in_use_out = pwm_already_in_use; + return pwm; } } - // Did we find a channel? If not, loop and check the next pwm. - if (self->pwm != NULL) { - break; - } } } else { // PWM not yet in use, so we can start to use it. Use channel 0. - self->pwm = pwm; - self->channel = 0; - break; + if(channel_out) + *channel_out = 0; + if(pwm_already_in_use_out) + *pwm_already_in_use_out = pwm_already_in_use; + return pwm; } } + return NULL; +} + +void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel) { + // Disconnect pin from channel. + pwm->PSEL.OUT[channel] = 0xFFFFFFFF; + + for(int i=0; i < CHANNELS_PER_PWM; i++) { + if (pwm->PSEL.OUT[i] != 0xFFFFFFFF) { + // Some channel is still being used, so don't disable. + return; + } + } + + nrf_pwm_disable(pwm); +} + +pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, + const mcu_pin_obj_t* pin, + uint16_t duty, + uint32_t frequency, + bool variable_frequency) { + + // We don't use the nrfx driver here because we want to dynamically allocate channels + // as needed in an already-enabled PWM. + + uint16_t countertop; + nrf_pwm_clk_t base_clock; + if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) { + return PWMOUT_INVALID_FREQUENCY; + } + + int8_t channel; + bool pwm_already_in_use; + self->pwm = pwmout_allocate(countertop, base_clock, variable_frequency, + &channel, &pwm_already_in_use); if (self->pwm == NULL) { return PWMOUT_ALL_TIMERS_IN_USE; } + self->channel = channel; self->pin_number = pin->number; claim_pin(pin); @@ -200,17 +225,17 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, nrf_gpio_cfg_output(self->pin_number); // disable before mapping pin channel - nrf_pwm_disable(pwm); + nrf_pwm_disable(self->pwm); if (!pwm_already_in_use) { - reset_single_pwmout(pwm_index); - nrf_pwm_configure(pwm, base_clock, NRF_PWM_MODE_UP, countertop); + reset_single_pwmout(pwm_idx(self->pwm)); + nrf_pwm_configure(self->pwm, base_clock, NRF_PWM_MODE_UP, countertop); } // Connect channel to pin, without disturbing other channels. - pwm->PSEL.OUT[self->channel] = pin->number; + self->pwm->PSEL.OUT[self->channel] = pin->number; - nrf_pwm_enable(pwm); + nrf_pwm_enable(self->pwm); common_hal_pulseio_pwmout_set_duty_cycle(self, duty); return PWMOUT_OK; @@ -230,17 +255,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { NRF_PWM_Type* pwm = self->pwm; self->pwm = NULL; - // Disconnect pin from channel. - pwm->PSEL.OUT[self->channel] = 0xFFFFFFFF; - - for(int i=0; i < CHANNELS_PER_PWM; i++) { - if (self->pwm->PSEL.OUT[i] != 0xFFFFFFFF) { - // Some channel is still being used, so don't disable. - return; - } - } - - nrf_pwm_disable(pwm); + pwmout_free_channel(pwm, self->channel); } void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { diff --git a/ports/nrf/common-hal/pulseio/PWMOut.h b/ports/nrf/common-hal/pulseio/PWMOut.h index a4e58dc1a..b6798cb68 100644 --- a/ports/nrf/common-hal/pulseio/PWMOut.h +++ b/ports/nrf/common-hal/pulseio/PWMOut.h @@ -41,5 +41,8 @@ typedef struct { } pulseio_pwmout_obj_t; void pwmout_reset(void); +NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock, + bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out); +void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel); #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk index 83166708a..57879bbaa 100644 --- a/ports/nrf/mpconfigport.mk +++ b/ports/nrf/mpconfigport.mk @@ -10,8 +10,10 @@ USB_SERIAL_NUMBER_LENGTH = 16 # All nRF ports have longints. LONGINT_IMPL = MPZ -# No DAC, so no regular audio. +# Audio via PWM +CIRCUITPY_AUDIOCORE = 1 CIRCUITPY_AUDIOIO = 0 +CIRCUITPY_AUDIOPWMIO = 1 # No I2S yet. CIRCUITPY_AUDIOBUSIO = 0 diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index 8fbf75498..03f787624 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -50,6 +50,10 @@ #include "shared-bindings/rtc/__init__.h" +#ifdef CIRCUITPY_AUDIOPWMIO +#include "common-hal/audiopwmio/PWMAudioOut.h" +#endif + static void power_warning_handler(void) { reset_into_safe_mode(BROWNOUT); } @@ -94,6 +98,10 @@ void reset_port(void) { spi_reset(); uart_reset(); +#ifdef CIRCUITPY_AUDIOPWMIO + audiopwmout_reset(); +#endif + #if CIRCUITPY_PULSEIO pwmout_reset(); pulseout_reset(); diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 5e5ebeaa8..d4733e338 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -108,6 +108,9 @@ endif ifeq ($(CIRCUITPY_AUDIOIO),1) SRC_PATTERNS += audioio/% endif +ifeq ($(CIRCUITPY_AUDIOPWMIO),1) +SRC_PATTERNS += audiopwmio/% +endif ifeq ($(CIRCUITPY_AUDIOCORE),1) SRC_PATTERNS += audiocore/% endif @@ -223,6 +226,8 @@ $(filter $(SRC_PATTERNS), \ audiobusio/__init__.c \ audiobusio/I2SOut.c \ audiobusio/PDMIn.c \ + audiopwmio/__init__.c \ + audiopwmio/PWMAudioOut.c \ audioio/__init__.c \ audioio/AudioOut.c \ bleio/__init__.c \ @@ -301,6 +306,7 @@ $(filter $(SRC_PATTERNS), \ _stage/Layer.c \ _stage/Text.c \ _stage/__init__.c \ + audiopwmio/__init__.c \ audioio/__init__.c \ audiocore/__init__.c \ audiocore/Mixer.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 3440eb052..d88d6538e 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -244,6 +244,13 @@ extern const struct _mp_obj_module_t audioio_module; #define AUDIOIO_MODULE #endif +#if CIRCUITPY_AUDIOPWMIO +#define AUDIOPWMIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiopwmio), (mp_obj_t)&audiopwmio_module }, +extern const struct _mp_obj_module_t audiopwmio_module; +#else +#define AUDIOPWMIO_MODULE +#endif + #if CIRCUITPY_BITBANGIO #define BITBANGIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, extern const struct _mp_obj_module_t bitbangio_module; @@ -573,6 +580,7 @@ extern const struct _mp_obj_module_t ustack_module; AUDIOBUSIO_MODULE \ AUDIOCORE_MODULE \ AUDIOIO_MODULE \ + AUDIOPWMIO_MODULE \ BITBANGIO_MODULE \ BLEIO_MODULE \ BOARD_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 772a1c3e1..a408cd7ac 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -74,9 +74,18 @@ CIRCUITPY_AUDIOIO = $(CIRCUITPY_FULL_BUILD) endif CFLAGS += -DCIRCUITPY_AUDIOIO=$(CIRCUITPY_AUDIOIO) +ifndef CIRCUITPY_AUDIOPWMIO +CIRCUITPY_AUDIOPWMIO = 0 +endif +CFLAGS += -DCIRCUITPY_AUDIOPWMIO=$(CIRCUITPY_AUDIOPWMIO) + ifndef CIRCUITPY_AUDIOCORE +ifeq ($(CIRCUITPY_AUDIOPWMIO),1) +CIRCUITPY_AUDIOCORE = $(CIRCUITPY_AUDIOPWMIO) +else CIRCUITPY_AUDIOCORE = $(CIRCUITPY_AUDIOIO) endif +endif CFLAGS += -DCIRCUITPY_AUDIOCORE=$(CIRCUITPY_AUDIOCORE) ifndef CIRCUITPY_BITBANGIO diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 980f11392..9bce9c760 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -56,7 +56,7 @@ //| using `UDA1334 Breakout <https://www.adafruit.com/product/3678>`_:: //| //| import audiobusio -//| import audioio +//| import audiocore //| import board //| import array //| import time @@ -68,7 +68,7 @@ //| for i in range(length): //| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15) //| -//| sine_wave = audiobusio.RawSample(sine_wave, sample_rate=8000) +//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000) //| i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9) //| i2s.play(sine_wave, loop=True) //| time.sleep(1) @@ -78,12 +78,13 @@ //| //| import board //| import audioio +//| import audiocore //| import audiobusio //| import digitalio //| //| //| f = open("cplay-5.1-16bit-16khz.wav", "rb") -//| wav = audioio.WaveFile(f) +//| wav = audiocore.WaveFile(f) //| //| a = audiobusio.I2SOut(board.D1, board.D0, board.D9) //| @@ -163,7 +164,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_i2sout___exit___obj, 4, 4, //| Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| Sample must be an `audioio.WaveFile` or `audioio.RawSample`. +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`. //| //| The sample itself should consist of 8 bit or 16 bit samples. //| diff --git a/shared-bindings/audiocore/Mixer.c b/shared-bindings/audiocore/Mixer.c index b2f0a3fda..9ab720434 100644 --- a/shared-bindings/audiocore/Mixer.c +++ b/shared-bindings/audiocore/Mixer.c @@ -36,7 +36,7 @@ #include "shared-bindings/util.h" #include "supervisor/shared/translate.h" -//| .. currentmodule:: audioio +//| .. currentmodule:: audiocore //| //| :class:`Mixer` -- Mixes one or more audio samples together //| =========================================================== @@ -54,15 +54,16 @@ //| //| import board //| import audioio +//| import audiocore //| import digitalio //| //| # Required for CircuitPlayground Express //| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) //| speaker_enable.switch_to_output(value=True) //| -//| music = audioio.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb")) -//| drum = audioio.WaveFile(open("drum.wav", "rb")) -//| mixer = audioio.Mixer(voice_count=2, sample_rate=16000, channel_count=1, bits_per_sample=16, samples_signed=True) +//| music = audiocore.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb")) +//| drum = audiocore.WaveFile(open("drum.wav", "rb")) +//| mixer = audiocore.Mixer(voice_count=2, sample_rate=16000, channel_count=1, bits_per_sample=16, samples_signed=True) //| a = audioio.AudioOut(board.A0) //| //| print("playing") @@ -151,7 +152,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_mixer___exit___obj, 4, 4, aud //| Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| Sample must be an `audioio.WaveFile`, `audioio.Mixer` or `audioio.RawSample`. +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`. //| //| The sample must match the Mixer's encoding settings given in the constructor. //| diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c index 912b48bfb..07f8c683f 100644 --- a/shared-bindings/audiocore/RawSample.c +++ b/shared-bindings/audiocore/RawSample.c @@ -35,7 +35,7 @@ #include "shared-bindings/audiocore/RawSample.h" #include "supervisor/shared/translate.h" -//| .. currentmodule:: audioio +//| .. currentmodule:: audiocore //| //| :class:`RawSample` -- A raw audio sample buffer //| ======================================================== @@ -55,6 +55,7 @@ //| //| Simple 8ksps 440 Hz sin wave:: //| +//| import audiocore //| import audioio //| import board //| import array @@ -68,7 +69,7 @@ //| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15)) //| //| dac = audioio.AudioOut(board.SPEAKER) -//| sine_wave = audioio.RawSample(sine_wave) +//| sine_wave = audiocore.RawSample(sine_wave) //| dac.play(sine_wave, loop=True) //| time.sleep(1) //| dac.stop() diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 4c1993b7c..edb190d3a 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -33,7 +33,7 @@ #include "shared-bindings/util.h" #include "supervisor/shared/translate.h" -//| .. currentmodule:: audioio +//| .. currentmodule:: audiocore //| //| :class:`WaveFile` -- Load a wave file for audio playback //| ======================================================== @@ -50,6 +50,7 @@ //| Playing a wave file from flash:: //| //| import board +//| import audiocore //| import audioio //| import digitalio //| @@ -58,7 +59,7 @@ //| speaker_enable.switch_to_output(value=True) //| //| data = open("cplay-5.1-16bit-16khz.wav", "rb") -//| wav = audioio.WaveFile(data) +//| wav = audiocore.WaveFile(data) //| a = audioio.AudioOut(board.A0) //| //| print("playing") diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index 79df66f7d..af2fce48e 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -55,6 +55,7 @@ //| //| Simple 8ksps 440 Hz sin wave:: //| +//| import audiocore //| import audioio //| import board //| import array @@ -68,7 +69,7 @@ //| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15) //| //| dac = audioio.AudioOut(board.SPEAKER) -//| sine_wave = audioio.RawSample(sine_wave, sample_rate=8000) +//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000) //| dac.play(sine_wave, loop=True) //| time.sleep(1) //| dac.stop() @@ -84,7 +85,7 @@ //| speaker_enable.switch_to_output(value=True) //| //| data = open("cplay-5.1-16bit-16khz.wav", "rb") -//| wav = audioio.WaveFile(data) +//| wav = audiocore.WaveFile(data) //| a = audioio.AudioOut(board.A0) //| //| print("playing") @@ -162,7 +163,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_audioout___exit___obj, 4, 4, //| Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| -//| Sample must be an `audioio.WaveFile` or `audioio.RawSample`. +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`. //| //| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output //| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c new file mode 100644 index 000000000..92543d112 --- /dev/null +++ b/shared-bindings/audiopwmio/PWMAudioOut.c @@ -0,0 +1,294 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdint.h> + +#include "lib/utils/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/audiopwmio/PWMAudioOut.h" +#include "shared-bindings/audiocore/RawSample.h" +#include "shared-bindings/util.h" +#include "supervisor/shared/translate.h" + +//| .. currentmodule:: audiopwmio +//| +//| :class:`PWMAudioOut` -- Output an analog audio signal +//| ======================================================== +//| +//| AudioOut can be used to output an analog audio signal on a given pin. +//| +//| .. class:: PWMAudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000) +//| +//| Create a PWMAudioOut object associated with the given pin(s). This allows you to +//| play audio signals out on the given pin(s). In contrast to mod:`audioio`, +//| the pin(s) specified are digital pins, and are driven with a device-dependent PWM +//| signal. +//| +//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to +//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to +//| :param int quiescent_value: The output value when no signal is present. Samples should start +//| and end with this value to prevent audible popping. +//| +//| Simple 8ksps 440 Hz sin wave:: +//| +//| import audiocore +//| import audiopwmio +//| import board +//| import array +//| import time +//| import math +//| +//| # Generate one period of sine wav. +//| length = 8000 // 440 +//| sine_wave = array.array("H", [0] * length) +//| for i in range(length): +//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15) +//| +//| dac = audiopwmio.PWMAudioOut(board.SPEAKER) +//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000) +//| dac.play(sine_wave, loop=True) +//| time.sleep(1) +//| dac.stop() +//| +//| Playing a wave file from flash:: +//| +//| import board +//| import audiocore +//| import audiopwmio +//| import digitalio +//| +//| # Required for CircuitPlayground Express +//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) +//| speaker_enable.switch_to_output(value=True) +//| +//| data = open("cplay-5.1-16bit-16khz.wav", "rb") +//| wav = audiocore.WaveFile(data) +//| a = audiopwmio.PWMAudioOut(board.SPEAKER) +//| +//| print("playing") +//| a.play(wav) +//| while a.playing: +//| pass +//| print("stopped") +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_left_channel, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_right_channel, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = mp_const_none} }, + { MP_QSTR_quiescent_value, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x8000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t left_channel_obj = args[ARG_left_channel].u_obj; + assert_pin(left_channel_obj, false); + const mcu_pin_obj_t *left_channel_pin = MP_OBJ_TO_PTR(left_channel_obj); + + mp_obj_t right_channel_obj = args[ARG_right_channel].u_obj; + const mcu_pin_obj_t *right_channel_pin = NULL; + if (right_channel_obj != mp_const_none) { + assert_pin(right_channel_obj, false); + right_channel_pin = MP_OBJ_TO_PTR(right_channel_obj); + } + + // create AudioOut object from the given pin + audiopwmio_pwmaudioout_obj_t *self = m_new_obj(audiopwmio_pwmaudioout_obj_t); + self->base.type = &audiopwmio_pwmaudioout_type; + common_hal_audiopwmio_pwmaudioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: deinit() +//| +//| Deinitialises the PWMAudioOut and releases any hardware resources for reuse. +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_deinit(mp_obj_t self_in) { + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiopwmio_pwmaudioout_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_deinit_obj, audiopwmio_pwmaudioout_deinit); + +STATIC void check_for_deinit(audiopwmio_pwmaudioout_obj_t *self) { + if (common_hal_audiopwmio_pwmaudioout_deinited(self)) { + raise_deinited_error(); + } +} +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +// Provided by context manager helper. + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info. +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_audiopwmio_pwmaudioout_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiopwmio_pwmaudioout___exit___obj, 4, 4, audiopwmio_pwmaudioout_obj___exit__); + + +//| .. method:: play(sample, *, loop=False) +//| +//| Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`. +//| +//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output +//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit +//| DAC that ignores the lowest 6 bits when playing 16 bit samples. +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiopwmio_pwmaudioout_play(self, sample, args[ARG_loop].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiopwmio_pwmaudioout_play_obj, 1, audiopwmio_pwmaudioout_obj_play); + +//| .. method:: stop() +//| +//| Stops playback and resets to the start of the sample. +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj_stop(mp_obj_t self_in) { + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_audiopwmio_pwmaudioout_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_stop_obj, audiopwmio_pwmaudioout_obj_stop); + +//| .. attribute:: playing +//| +//| True when an audio sample is being output even if `paused`. (read-only) +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_playing(mp_obj_t self_in) { + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiopwmio_pwmaudioout_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_get_playing_obj, audiopwmio_pwmaudioout_obj_get_playing); + +const mp_obj_property_t audiopwmio_pwmaudioout_playing_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audiopwmio_pwmaudioout_get_playing_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. method:: pause() +//| +//| Stops playback temporarily while remembering the position. Use `resume` to resume playback. +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj_pause(mp_obj_t self_in) { + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (!common_hal_audiopwmio_pwmaudioout_get_playing(self)) { + mp_raise_RuntimeError(translate("Not playing")); + } + common_hal_audiopwmio_pwmaudioout_pause(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_pause_obj, audiopwmio_pwmaudioout_obj_pause); + +//| .. method:: resume() +//| +//| Resumes sample playback after :py:func:`pause`. +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj_resume(mp_obj_t self_in) { + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (common_hal_audiopwmio_pwmaudioout_get_paused(self)) { + common_hal_audiopwmio_pwmaudioout_resume(self); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_resume_obj, audiopwmio_pwmaudioout_obj_resume); + +//| .. attribute:: paused +//| +//| True when playback is paused. (read-only) +//| +STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_paused(mp_obj_t self_in) { + audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiopwmio_pwmaudioout_get_paused(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_get_paused_obj, audiopwmio_pwmaudioout_obj_get_paused); + +const mp_obj_property_t audiopwmio_pwmaudioout_paused_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audiopwmio_pwmaudioout_get_paused_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t audiopwmio_pwmaudioout_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiopwmio_pwmaudioout_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiopwmio_pwmaudioout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiopwmio_pwmaudioout_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiopwmio_pwmaudioout_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&audiopwmio_pwmaudioout_pause_obj) }, + { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&audiopwmio_pwmaudioout_resume_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiopwmio_pwmaudioout_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&audiopwmio_pwmaudioout_paused_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(audiopwmio_pwmaudioout_locals_dict, audiopwmio_pwmaudioout_locals_dict_table); + +const mp_obj_type_t audiopwmio_pwmaudioout_type = { + { &mp_type_type }, + .name = MP_QSTR_PWMAudioOut, + .make_new = audiopwmio_pwmaudioout_make_new, + .locals_dict = (mp_obj_dict_t*)&audiopwmio_pwmaudioout_locals_dict, +}; diff --git a/shared-bindings/audiopwmio/PWMAudioOut.h b/shared-bindings/audiopwmio/PWMAudioOut.h new file mode 100644 index 000000000..22afc70d3 --- /dev/null +++ b/shared-bindings/audiopwmio/PWMAudioOut.h @@ -0,0 +1,49 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H + +#include "common-hal/audiopwmio/PWMAudioOut.h" +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/audiocore/RawSample.h" + +extern const mp_obj_type_t audiopwmio_pwmaudioout_type; + +// left_channel will always be non-NULL but right_channel may be for mono output. +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 default_value); + +void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self); +bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self); +void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop); +void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self); +bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self); +void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self); +void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self); +bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H diff --git a/shared-bindings/audiopwmio/__init__.c b/shared-bindings/audiopwmio/__init__.c new file mode 100644 index 000000000..8a2b202b3 --- /dev/null +++ b/shared-bindings/audiopwmio/__init__.c @@ -0,0 +1,71 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdint.h> + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/audiopwmio/__init__.h" +#include "shared-bindings/audiopwmio/PWMAudioOut.h" + +//| :mod:`audiopwmio` --- Support for audio input and output +//| ======================================================== +//| +//| .. module:: audiopwmio +//| :synopsis: Support for audio output via digital PWM +//| :platform: NRF52 +//| +//| The `audiopwmio` module contains classes to provide access to audio IO. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| PWMAudioOut +//| +//| All classes change hardware state and should be deinitialized when they +//| are no longer needed if the program continues after use. To do so, either +//| call :py:meth:`!deinit` or use a context manager. See +//| :ref:`lifetime-and-contextmanagers` for more info. +//| +//| Since CircuitPython 5, `Mixer`, `RawSample` and `WaveFile` are moved +//| to :mod:`audiocore`. +//| + +STATIC const mp_rom_map_elem_t audiopwmio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiopwmio) }, + { MP_ROM_QSTR(MP_QSTR_PWMAudioOut), MP_ROM_PTR(&audiopwmio_pwmaudioout_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(audiopwmio_module_globals, audiopwmio_module_globals_table); + +const mp_obj_module_t audiopwmio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&audiopwmio_module_globals, +}; diff --git a/shared-bindings/audiopwmio/__init__.h b/shared-bindings/audiopwmio/__init__.h new file mode 100644 index 000000000..e4b7067d1 --- /dev/null +++ b/shared-bindings/audiopwmio/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H + +#include "py/obj.h" + +// Nothing now. + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 6ba4914a0..53fbb51c8 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -131,7 +131,8 @@ STATIC mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_ displayio_tilegrid_t *self = m_new_obj(displayio_tilegrid_t); self->base.type = &displayio_tilegrid_type; - common_hal_displayio_tilegrid_construct(self, native, bitmap_width / tile_width, + common_hal_displayio_tilegrid_construct(self, native, + bitmap_width / tile_width, bitmap_height / tile_height, pixel_shader, args[ARG_width].u_int, args[ARG_height].u_int, tile_width, tile_height, x, y, args[ARG_default_tile].u_int); return MP_OBJ_FROM_PTR(self); @@ -346,7 +347,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v } if (x >= common_hal_displayio_tilegrid_get_width(self) || y >= common_hal_displayio_tilegrid_get_height(self)) { - mp_raise_IndexError(translate("tile index out of bounds")); + mp_raise_IndexError(translate("Tile index out of bounds")); } if (value_obj == MP_OBJ_SENTINEL) { @@ -357,7 +358,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v } else { mp_int_t value = mp_obj_get_int(value_obj); if (value < 0 || value > 255) { - mp_raise_ValueError(translate("Tile indices must be 0 - 255")); + mp_raise_ValueError(translate("Tile value out of bounds")); } common_hal_displayio_tilegrid_set_tile(self, x, y, value); } diff --git a/shared-bindings/displayio/TileGrid.h b/shared-bindings/displayio/TileGrid.h index 1f9995a94..8227abfd3 100644 --- a/shared-bindings/displayio/TileGrid.h +++ b/shared-bindings/displayio/TileGrid.h @@ -32,7 +32,8 @@ extern const mp_obj_type_t displayio_tilegrid_type; void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap, - uint16_t bitmap_width_in_tiles, mp_obj_t pixel_shader, uint16_t width, uint16_t height, + uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles, + mp_obj_t pixel_shader, uint16_t width, uint16_t height, uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile); mp_int_t common_hal_displayio_tilegrid_get_x(displayio_tilegrid_t *self); diff --git a/shared-module/audiocore/WaveFile.h b/shared-module/audiocore/WaveFile.h index 97dd6a46f..3eecbf15c 100644 --- a/shared-module/audiocore/WaveFile.h +++ b/shared-module/audiocore/WaveFile.h @@ -27,6 +27,7 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_WAVEFILE_H #define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_WAVEFILE_H +#include "extmod/vfs_fat.h" #include "py/obj.h" #include "shared-module/audiocore/__init__.h" diff --git a/shared-module/audiopwmio/__init__.c b/shared-module/audiopwmio/__init__.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/shared-module/audiopwmio/__init__.c diff --git a/shared-module/audiopwmio/__init__.h b/shared-module/audiopwmio/__init__.h new file mode 100644 index 000000000..964e4aafe --- /dev/null +++ b/shared-module/audiopwmio/__init__.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H +#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H + +#include "shared-module/audiocore/__init__.h" + +#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index f8dc24c15..59971d25c 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -63,6 +63,11 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi } self->x_mask = (1 << self->x_shift) - 1; // Used as a modulus on the x value self->bitmask = (1 << bits_per_value) - 1; + + self->dirty_area.x1 = 0; + self->dirty_area.x2 = width; + self->dirty_area.y1 = 0; + self->dirty_area.y2 = height; } uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self) { @@ -104,6 +109,26 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, if (self->read_only) { mp_raise_RuntimeError(translate("Read-only object")); } + // Update the dirty area. + if (self->dirty_area.x1 == self->dirty_area.x2) { + self->dirty_area.x1 = x; + self->dirty_area.x2 = x + 1; + self->dirty_area.y1 = y; + self->dirty_area.y2 = y + 1; + } else { + if (x < self->dirty_area.x1) { + self->dirty_area.x1 = x; + } else if (x >= self->dirty_area.x2) { + self->dirty_area.x2 = x + 1; + } + if (y < self->dirty_area.y1) { + self->dirty_area.y1 = y; + } else if (y >= self->dirty_area.y2) { + self->dirty_area.y2 = y + 1; + } + } + + // Update our data int32_t row_start = y * self->stride; uint32_t bytes_per_value = self->bits_per_value / 8; if (bytes_per_value < 1) { @@ -124,3 +149,16 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, } } } + +displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail) { + if (self->dirty_area.x1 == self->dirty_area.x2) { + return tail; + } + self->dirty_area.next = tail; + return &self->dirty_area; +} + +void displayio_bitmap_finish_refresh(displayio_bitmap_t *self) { + self->dirty_area.x1 = 0; + self->dirty_area.x2 = 0; +} diff --git a/shared-module/displayio/Bitmap.h b/shared-module/displayio/Bitmap.h index 48ca9e2cf..f4bd7ce4d 100644 --- a/shared-module/displayio/Bitmap.h +++ b/shared-module/displayio/Bitmap.h @@ -31,6 +31,7 @@ #include <stdint.h> #include "py/obj.h" +#include "shared-module/displayio/area.h" typedef struct { mp_obj_base_t base; @@ -41,8 +42,12 @@ typedef struct { uint8_t bits_per_value; uint8_t x_shift; size_t x_mask; + displayio_area_t dirty_area; uint16_t bitmask; bool read_only; } displayio_bitmap_t; +void displayio_bitmap_finish_refresh(displayio_bitmap_t *self); +displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail); + #endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index fee2ae978..6144f8f99 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -26,6 +26,7 @@ #include "shared-bindings/displayio/TileGrid.h" +#include "py/runtime.h" #include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/OnDiskBitmap.h" @@ -33,7 +34,7 @@ #include "shared-bindings/displayio/Shape.h" void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap, - uint16_t bitmap_width_in_tiles, + uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles, mp_obj_t pixel_shader, uint16_t width, uint16_t height, uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) { uint32_t total_tiles = width * height; @@ -54,6 +55,7 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_ self->inline_tiles = false; } self->bitmap_width_in_tiles = bitmap_width_in_tiles; + self->tiles_in_bitmap = bitmap_width_in_tiles * bitmap_height_in_tiles; self->width_in_tiles = width; self->height_in_tiles = height; self->x = x; @@ -204,6 +206,9 @@ uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint1 } void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index) { + if (tile_index >= self->tiles_in_bitmap) { + mp_raise_ValueError(translate("Tile value out of bounds")); + } uint8_t* tiles = self->tiles; if (self->inline_tiles) { tiles = (uint8_t*) &self->tiles; @@ -462,6 +467,14 @@ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) { } else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) { displayio_colorconverter_finish_refresh(self->pixel_shader); } + if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) { + displayio_bitmap_finish_refresh(self->bitmap); + } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) { + // TODO: Support shape changes. + } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) { + // OnDiskBitmap changes will trigger a complete reload so no need to + // track changes. + } // TODO(tannewt): We could double buffer changes to position and move them over here. // That way they won't change during a refresh and tear. } @@ -478,8 +491,21 @@ displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *sel return &self->current_area; } - // We must recheck if our sources require a refresh because needs_refresh may or may not have - // been called. + // If we have an in-memory bitmap, then check it for modifications. + if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) { + displayio_area_t* refresh_area = displayio_bitmap_get_refresh_areas(self->bitmap, tail); + if (refresh_area != tail) { + // Special case a TileGrid that shows a full bitmap and use its + // dirty area. Copy it to ours so we can transform it. + if (self->tiles_in_bitmap == 1) { + displayio_area_copy(refresh_area, &self->dirty_area); + self->partial_change = true; + } else { + self->full_change = true; + } + } + } + self->full_change = self->full_change || (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) && displayio_palette_needs_refresh(self->pixel_shader)) || diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h index fb6033e9c..222aaed19 100644 --- a/shared-module/displayio/TileGrid.h +++ b/shared-module/displayio/TileGrid.h @@ -42,7 +42,8 @@ typedef struct { int16_t y; uint16_t pixel_width; uint16_t pixel_height; - uint16_t bitmap_width_in_tiles; + uint16_t bitmap_width_in_tiles;; + uint8_t tiles_in_bitmap; uint16_t width_in_tiles; uint16_t height_in_tiles; uint16_t tile_width; diff --git a/supervisor/shared/display.h b/supervisor/shared/display.h index d5faa7777..2a2ccf46d 100644 --- a/supervisor/shared/display.h +++ b/supervisor/shared/display.h @@ -35,11 +35,10 @@ // These are autogenerated resources. // This is fixed so it doesn't need to be in RAM. -extern const displayio_bitmap_t supervisor_terminal_font_bitmap; - extern const fontio_builtinfont_t supervisor_terminal_font; // These will change so they must live in RAM. +extern displayio_bitmap_t supervisor_terminal_font_bitmap; extern displayio_tilegrid_t supervisor_terminal_text_grid; extern terminalio_terminal_obj_t supervisor_terminal; diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py index a731cbd9c..0f6b9014b 100644 --- a/tools/gen_display_resources.py +++ b/tools/gen_display_resources.py @@ -129,6 +129,7 @@ displayio_tilegrid_t supervisor_terminal_text_grid = {{ .pixel_width = {1}, .pixel_height = {2}, .bitmap_width_in_tiles = {0}, + .tiles_in_bitmap = {0}, .width_in_tiles = 1, .height_in_tiles = 1, .tile_width = {1}, @@ -157,7 +158,7 @@ c_file.write("""\ """) c_file.write("""\ -const displayio_bitmap_t supervisor_terminal_font_bitmap = {{ +displayio_bitmap_t supervisor_terminal_font_bitmap = {{ .base = {{.type = &displayio_bitmap_type }}, .width = {}, .height = {}, |
