From 322f1269e054f7922caac804133c1ed4b6910ec3 Mon Sep 17 00:00:00 2001 From: Wellington Terumi Uemura Date: Fri, 25 Jun 2021 09:48:27 +0000 Subject: [PATCH 01/52] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1006 of 1006 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/pt_BR/ --- locale/pt_BR.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/pt_BR.po b/locale/pt_BR.po index df762a702a..3b95d85b9f 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-06-24 23:11+0000\n" +"PO-Revision-Date: 2021-06-25 18:00+0000\n" "Last-Translator: Wellington Terumi Uemura \n" "Language-Team: \n" "Language: pt_BR\n" @@ -896,7 +896,7 @@ msgstr "Pedaço de dados deve seguir o pedaço de cortes" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "" +msgstr "Os dados não são compatíveis com publicidade direcionada" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" @@ -1750,7 +1750,7 @@ msgstr "" #: shared-bindings/_bleio/Adapter.c msgid "Only connectable advertisements can be directed" -msgstr "" +msgstr "Somente anúncios conectáveis podem ser direcionados" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Only edge detection is available on this hardware" From 4e9bbee02f14349cb4c3b4847b1e901e47377fa9 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 25 Jun 2021 20:01:02 +0200 Subject: [PATCH 02/52] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/ --- locale/ID.po | 6 +++++- locale/cs.po | 6 +++++- locale/de_DE.po | 6 +++++- locale/el.po | 6 +++++- locale/en_GB.po | 6 +++++- locale/es.po | 6 +++++- locale/fil.po | 6 +++++- locale/fr.po | 6 +++++- locale/hi.po | 6 +++++- locale/it_IT.po | 6 +++++- locale/ja.po | 6 +++++- locale/ko.po | 6 +++++- locale/nl.po | 6 +++++- locale/pl.po | 6 +++++- locale/pt_BR.po | 6 +++++- locale/sv.po | 6 +++++- locale/zh_Latn_pinyin.po | 6 +++++- 17 files changed, 85 insertions(+), 17 deletions(-) diff --git a/locale/ID.po b/locale/ID.po index 0a209f3c08..7198339718 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -54,6 +54,10 @@ msgstr " File \"%q\", baris %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr "output:\n" @@ -2549,7 +2553,7 @@ msgstr "Argumen argsort harus berupa ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "argumen memiliki tipe yang salah" diff --git a/locale/cs.po b/locale/cs.po index a1b8031145..ebdd4f1264 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -50,6 +50,10 @@ msgstr " Soubor \"%q\", řádek %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " výstup:\n" @@ -2510,7 +2514,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 31097a7be1..97d76fb91e 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -53,6 +53,10 @@ msgstr " Datei \"%q\", Zeile %d" msgid " is of type %q\n" msgstr " ist vom Type %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " Ausgabe:\n" @@ -2555,7 +2559,7 @@ msgstr "Das Argument argsort muss ein ndarray sein" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "Argument hat falschen Typ" diff --git a/locale/el.po b/locale/el.po index 8f51d36529..ad6ab6f189 100644 --- a/locale/el.po +++ b/locale/el.po @@ -47,6 +47,10 @@ msgstr "" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr "" @@ -2507,7 +2511,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "" diff --git a/locale/en_GB.po b/locale/en_GB.po index 6f3ad2f15a..771de391af 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -55,6 +55,10 @@ msgstr " File \"%q\", line %d" msgid " is of type %q\n" msgstr " is of type %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " output:\n" @@ -2542,7 +2546,7 @@ msgstr "argsort argument must be an ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort is not implemented for flattened arrays" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "argument has wrong type" diff --git a/locale/es.po b/locale/es.po index 3e8697e393..1363b35df5 100644 --- a/locale/es.po +++ b/locale/es.po @@ -56,6 +56,10 @@ msgstr " Archivo \"%q\", línea %d" msgid " is of type %q\n" msgstr " es de tipo %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " salida:\n" @@ -2586,7 +2590,7 @@ msgstr "El argumento para argsort debe ser un ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "El argot no está implementado para arrays aplanados" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "el argumento tiene un tipo erroneo" diff --git a/locale/fil.po b/locale/fil.po index 700b8ec96c..e0d80d7b4b 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -46,6 +46,10 @@ msgstr " File \"%q\", line %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " output:\n" @@ -2535,7 +2539,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "may maling type ang argument" diff --git a/locale/fr.po b/locale/fr.po index 761aebe237..d579a9e2a4 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -56,6 +56,10 @@ msgstr " Fichier \"%q\", ligne %d" msgid " is of type %q\n" msgstr " est de type %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " sortie :\n" @@ -2588,7 +2592,7 @@ msgstr "Le paramêtre argsort doit être un ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort n'est pas mis en œuvre pour les matrices aplatis" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "l'argument est d'un mauvais type" diff --git a/locale/hi.po b/locale/hi.po index cbc07d270f..97823956e9 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -47,6 +47,10 @@ msgstr "" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr "" @@ -2507,7 +2511,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "" diff --git a/locale/it_IT.po b/locale/it_IT.po index 925124c3b0..03ae1d68ca 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -55,6 +55,10 @@ msgstr " File \"%q\", riga %d" msgid " is of type %q\n" msgstr " è di tipo %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " output:\n" @@ -2550,7 +2554,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "il tipo dell'argomento è errato" diff --git a/locale/ja.po b/locale/ja.po index ad58f1c5a3..d6cbde47c2 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -52,6 +52,10 @@ msgstr " ファイル \"%q\", 行 %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " 出力:\n" @@ -2522,7 +2526,7 @@ msgstr "argsortの引数はndarrayでなければなりません" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "" diff --git a/locale/ko.po b/locale/ko.po index 2b7c9b1a7a..0dfd9a596d 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -48,6 +48,10 @@ msgstr " 파일 \"%q\", 라인 %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " 산출:\n" @@ -2511,7 +2515,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "" diff --git a/locale/nl.po b/locale/nl.po index e766c090c5..c697cfbf4d 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -50,6 +50,10 @@ msgstr " Bestand \"%q\", regel %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " uitvoer:\n" @@ -2548,7 +2552,7 @@ msgstr "argsort argument moet een ndarray zijn" msgid "argsort is not implemented for flattened arrays" msgstr "argsort wordt niet geïmplementeerd voor vlakke arrays" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "argument heeft onjuist type" diff --git a/locale/pl.po b/locale/pl.po index 5f1aea6bf4..df71c704b0 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -52,6 +52,10 @@ msgstr " Plik \"%q\", linia %d" msgid " is of type %q\n" msgstr "" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " wyjście:\n" @@ -2524,7 +2528,7 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "argument ma zły typ" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 3b95d85b9f..4e3124c2c9 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -54,6 +54,10 @@ msgstr " Arquivo \"%q\", linha %d" msgid " is of type %q\n" msgstr " é do tipo %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " saída:\n" @@ -2591,7 +2595,7 @@ msgstr "O argumento argsort deve ser um ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort não é implementado para matrizes achatadas" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "argumento tem tipo errado" diff --git a/locale/sv.po b/locale/sv.po index 176c7f02be..0931d53800 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -54,6 +54,10 @@ msgstr " Fil \"%q\", rad %d" msgid " is of type %q\n" msgstr " är av typen %q\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " utdata:\n" @@ -2561,7 +2565,7 @@ msgstr "argumentet argsort måste vara en ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort är inte implementerad för tillplattade matriser" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "argumentet har fel typ" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index bb6fba4dd2..cb7745d4e8 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -55,6 +55,10 @@ msgstr " Wénjiàn \"%q\", dì %d xíng" msgid " is of type %q\n" msgstr " shì %q lèi xíng\n" +#: main.c +msgid " not found.\n" +msgstr "" + #: main.c msgid " output:\n" msgstr " shūchū:\n" @@ -2560,7 +2564,7 @@ msgstr "argsort cānshù bìxū shì ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "wèi wéi pīn hé shù zǔ shí xiàn argsort" -#: py/runtime.c +#: py/runtime.c shared-bindings/supervisor/__init__.c msgid "argument has wrong type" msgstr "cānshù lèixíng cuòwù" From 1987bead3179c65842bc52998eecb5a85d0df59e Mon Sep 17 00:00:00 2001 From: hexthat Date: Fri, 25 Jun 2021 18:14:16 +0000 Subject: [PATCH 03/52] Translated using Weblate (Chinese (Pinyin)) Currently translated at 100.0% (1007 of 1007 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/zh_Latn/ --- locale/zh_Latn_pinyin.po | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index cb7745d4e8..4f71db3fd3 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-06-23 17:15+0000\n" +"PO-Revision-Date: 2021-06-25 18:15+0000\n" "Last-Translator: hexthat \n" "Language-Team: Chinese Hanyu Pinyin\n" "Language: zh_Latn_pinyin\n" @@ -57,7 +57,7 @@ msgstr " shì %q lèi xíng\n" #: main.c msgid " not found.\n" -msgstr "" +msgstr " wèi zhǎo dào.\n" #: main.c msgid " output:\n" @@ -99,7 +99,7 @@ msgstr "%q suǒyǐn bìxū shì zhěngshù, ér bùshì %s" #: py/argcheck.c msgid "%q length must be %q" -msgstr "" +msgstr "%q cháng dù bì xū wéi %q" #: shared-bindings/vectorio/Polygon.c msgid "%q list must be a list" @@ -107,11 +107,11 @@ msgstr "%q lièbiǎo bìxū shì lièbiǎo" #: py/argcheck.c msgid "%q must <= %d" -msgstr "" +msgstr "%q bì xū <= %d" #: py/argcheck.c msgid "%q must be %d-%d" -msgstr "" +msgstr "%q bì xū wéi %d-%d" #: shared-bindings/usb_hid/Device.c msgid "%q must be 0-255" @@ -123,7 +123,7 @@ msgstr "%q bì xū wéi 1-255" #: py/argcheck.c msgid "%q must be >= %d" -msgstr "" +msgstr "%q bì xū >= %d" #: py/argcheck.c shared-bindings/memorymonitor/AllocationAlarm.c msgid "%q must be >= 0" @@ -143,7 +143,7 @@ msgstr "%q bì xū wéi wú huò zài 1 hé len(report_descriptor)-1 zhī jiān" #: py/argcheck.c msgid "%q must be a string" -msgstr "" +msgstr "%q bì xū shì yí gè zì fú chuàn" #: shared-module/vectorio/Polygon.c msgid "%q must be a tuple of length 2" @@ -155,12 +155,12 @@ msgstr "%q bì xū zài %d hé %d zhī jiān" #: py/argcheck.c msgid "%q must of type %q" -msgstr "" +msgstr "%q bì xū lèi xíng %q" #: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c #: shared-bindings/keypad/ShiftRegisterKeys.c msgid "%q must store bytes" -msgstr "" +msgstr "%q bì xū cún chǔ zì jié" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c @@ -889,7 +889,7 @@ msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "" +msgstr "bù zhī chí dìng xiàng guǎng gào de shù jù" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" @@ -1741,7 +1741,7 @@ msgstr "" #: shared-bindings/_bleio/Adapter.c msgid "Only connectable advertisements can be directed" -msgstr "" +msgstr "zhǐ yǒu kě lián jiē de guǎng gào cái néng bèi yǐn dǎo" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Only edge detection is available on this hardware" @@ -2641,7 +2641,7 @@ msgstr "èrjìnzhì bǎn qián bǎn %q wèi zhíxíng" #: extmod/modurandom.c msgid "bits must be 32 or less" -msgstr "" +msgstr "wèi bì xū shì 32 huò gèng shǎo" #: shared-bindings/busio/UART.c msgid "bits must be in range 5 to 9" @@ -3262,7 +3262,7 @@ msgstr "túxíng bìxū wèi 2048 zì jié" #: extmod/moduhashlib.c msgid "hash is final" -msgstr "" +msgstr "hā xī shì zuì zhōng de" #: extmod/moduheapq.c msgid "heap must be a list" From 11325bd338bbd92f74f0a9ef732c327678986a68 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 25 Jun 2021 20:15:49 +0200 Subject: [PATCH 04/52] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/ --- locale/ID.po | 4 ++++ locale/cs.po | 4 ++++ locale/de_DE.po | 4 ++++ locale/el.po | 4 ++++ locale/en_GB.po | 4 ++++ locale/es.po | 4 ++++ locale/fil.po | 4 ++++ locale/fr.po | 4 ++++ locale/hi.po | 4 ++++ locale/it_IT.po | 4 ++++ locale/ja.po | 4 ++++ locale/ko.po | 4 ++++ locale/nl.po | 4 ++++ locale/pl.po | 4 ++++ locale/pt_BR.po | 4 ++++ locale/sv.po | 4 ++++ locale/zh_Latn_pinyin.po | 4 ++++ 17 files changed, 68 insertions(+) diff --git a/locale/ID.po b/locale/ID.po index 7198339718..bb8428a3f2 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -2068,6 +2068,10 @@ msgstr "Kesalahan Init SPI" msgid "SPI Re-initialization error" msgstr "Kesalahan Inisialisasi ulang SPI" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/cs.po b/locale/cs.po index ebdd4f1264..ed87ef5768 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -2037,6 +2037,10 @@ msgstr "" msgid "SPI Re-initialization error" msgstr "" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 97d76fb91e..498f3bcd49 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -2066,6 +2066,10 @@ msgstr "SPI-Init-Fehler" msgid "SPI Re-initialization error" msgstr "SPI-Neuinitialisierungsfehler" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/el.po b/locale/el.po index ad6ab6f189..68052d303d 100644 --- a/locale/el.po +++ b/locale/el.po @@ -2034,6 +2034,10 @@ msgstr "" msgid "SPI Re-initialization error" msgstr "" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/en_GB.po b/locale/en_GB.po index 771de391af..b8e0e96034 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -2062,6 +2062,10 @@ msgstr "SPI init error" msgid "SPI Re-initialization error" msgstr "SPI reinitialisation error" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "SPI peripheral in use" diff --git a/locale/es.po b/locale/es.po index 1363b35df5..e184742e79 100644 --- a/locale/es.po +++ b/locale/es.po @@ -2090,6 +2090,10 @@ msgstr "Error de inicio de SPI" msgid "SPI Re-initialization error" msgstr "Error de reinicialización de SPI" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "Periférico SPI en uso" diff --git a/locale/fil.po b/locale/fil.po index e0d80d7b4b..da7b003bbc 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -2054,6 +2054,10 @@ msgstr "" msgid "SPI Re-initialization error" msgstr "" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/fr.po b/locale/fr.po index d579a9e2a4..c224337e01 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -2099,6 +2099,10 @@ msgstr "Erreur d'initialisation SPI" msgid "SPI Re-initialization error" msgstr "Erreur de réinitialisation SPI" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "Périphérique SPI utilisé" diff --git a/locale/hi.po b/locale/hi.po index 97823956e9..a6327c63d9 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -2034,6 +2034,10 @@ msgstr "" msgid "SPI Re-initialization error" msgstr "" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/it_IT.po b/locale/it_IT.po index 03ae1d68ca..28c4012afd 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -2073,6 +2073,10 @@ msgstr "" msgid "SPI Re-initialization error" msgstr "" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/ja.po b/locale/ja.po index d6cbde47c2..e3f25b8f9c 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -2048,6 +2048,10 @@ msgstr "SPI初期化エラー" msgid "SPI Re-initialization error" msgstr "SPI再初期化エラー" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/ko.po b/locale/ko.po index 0dfd9a596d..06ced23109 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -2037,6 +2037,10 @@ msgstr "" msgid "SPI Re-initialization error" msgstr "" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/nl.po b/locale/nl.po index c697cfbf4d..2561eeb710 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -2064,6 +2064,10 @@ msgstr "SPI Init Fout" msgid "SPI Re-initialization error" msgstr "SPI Herinitialisatie Fout" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/pl.po b/locale/pl.po index df71c704b0..6d736c6ce6 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -2045,6 +2045,10 @@ msgstr "Błąd inicjowania SPI" msgid "SPI Re-initialization error" msgstr "Błąd ponownej inicjalizacji SPI" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 4e3124c2c9..82a4cb62b6 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -2091,6 +2091,10 @@ msgstr "Houve um erro na inicialização SPI" msgid "SPI Re-initialization error" msgstr "Houve um erro na reinicialização SPI" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "O periférico SPI está em uso" diff --git a/locale/sv.po b/locale/sv.po index 0931d53800..76127123ff 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -2070,6 +2070,10 @@ msgstr "SPI Init-fel" msgid "SPI Re-initialization error" msgstr "SPI reinitialiseringsfel" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "SPI-enhet används redan" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 4f71db3fd3..9cbd84ebfd 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -2069,6 +2069,10 @@ msgstr "SPI chūshǐhuà cuòwù" msgid "SPI Re-initialization error" msgstr "SPI chóngxīn chūshǐhuà cuòwù" +#: ports/esp32s2/common-hal/busio/SPI.c +msgid "SPI configuration failed" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "SPI wài shè zhèng zài shǐ yòng zhōng" From 3177973843e429d019037a62a91d3f54e9bf6c5d Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 25 Jun 2021 14:58:32 -0700 Subject: [PATCH 05/52] Add BLE serial service --- locale/circuitpython.pot | 5 - main.c | 2 +- ports/nrf/background.c | 5 - ports/nrf/bluetooth/ble_drv.c | 2 +- ports/nrf/bluetooth/ble_uart.c | 191 --------- ports/nrf/bluetooth/ringbuffer.h | 99 ----- ports/nrf/common-hal/_bleio/Adapter.c | 2 +- ports/nrf/common-hal/_bleio/Characteristic.c | 5 +- .../common-hal/_bleio/CharacteristicBuffer.c | 32 +- ports/nrf/common-hal/_bleio/Connection.c | 4 +- ports/nrf/common-hal/_bleio/PacketBuffer.c | 17 + ports/nrf/common-hal/_bleio/Service.c | 16 +- ports/nrf/common-hal/_bleio/__init__.c | 2 +- ports/nrf/mpconfigport.mk | 3 + py/circuitpy_mpconfig.mk | 15 +- shared-bindings/_bleio/Characteristic.c | 18 +- shared-bindings/_bleio/Characteristic.h | 2 +- shared-bindings/_bleio/CharacteristicBuffer.h | 10 +- shared-bindings/_bleio/Service.h | 2 +- supervisor/shared/bluetooth/bluetooth.c | 232 +++++++++++ supervisor/shared/{ => bluetooth}/bluetooth.h | 4 - .../file_transfer.c} | 364 +++--------------- .../shared/bluetooth/file_transfer.h | 18 +- .../shared/bluetooth/file_transfer_protocol.h | 149 +++++++ supervisor/shared/bluetooth/serial.c | 153 ++++++++ supervisor/shared/bluetooth/serial.h | 39 ++ supervisor/shared/serial.c | 85 +++- supervisor/shared/tick.c | 5 - supervisor/supervisor.mk | 14 +- 29 files changed, 793 insertions(+), 702 deletions(-) delete mode 100644 ports/nrf/bluetooth/ble_uart.c delete mode 100644 ports/nrf/bluetooth/ringbuffer.h create mode 100644 supervisor/shared/bluetooth/bluetooth.c rename supervisor/shared/{ => bluetooth}/bluetooth.h (92%) rename supervisor/shared/{bluetooth.c => bluetooth/file_transfer.c} (66%) rename ports/nrf/bluetooth/ble_uart.h => supervisor/shared/bluetooth/file_transfer.h (73%) create mode 100644 supervisor/shared/bluetooth/file_transfer_protocol.h create mode 100644 supervisor/shared/bluetooth/serial.c create mode 100644 supervisor/shared/bluetooth/serial.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 0fc96f8b6e..e421eef8ea 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -147,11 +147,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/main.c b/main.c index dc2eaebb50..395b8c3057 100755 --- a/main.c +++ b/main.c @@ -71,7 +71,7 @@ #if CIRCUITPY_BLEIO #include "shared-bindings/_bleio/__init__.h" -#include "supervisor/shared/bluetooth.h" +#include "supervisor/shared/bluetooth/bluetooth.h" #endif #if CIRCUITPY_BOARD diff --git a/ports/nrf/background.c b/ports/nrf/background.c index 269bf6737f..f4d6b0f79f 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -41,11 +41,6 @@ #include "common-hal/audiopwmio/PWMAudioOut.h" #endif -#if CIRCUITPY_BLEIO -#include "supervisor/shared/bluetooth.h" -#include "common-hal/_bleio/bonding.h" -#endif - void port_start_background_task(void) { } void port_finish_background_task(void) { diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index 044acbebfc..29b2844736 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -38,7 +38,7 @@ #include "py/misc.h" #include "py/mpstate.h" -#include "supervisor/shared/bluetooth.h" +// #include "supervisor/shared/bluetooth.h" nrf_nvic_state_t nrf_nvic_state = { 0 }; diff --git a/ports/nrf/bluetooth/ble_uart.c b/ports/nrf/bluetooth/ble_uart.c deleted file mode 100644 index 6b1fed1ad5..0000000000 --- a/ports/nrf/bluetooth/ble_uart.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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 - -#include "ble.h" -#include "ble_uart.h" -#include "ringbuffer.h" -#include "py/mphal.h" -#include "py/runtime.h" -#include "lib/utils/interrupt_char.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Device.h" -#include "shared-bindings/_bleio/Service.h" -#include "shared-bindings/_bleio/UUID.h" - -#if CIRCUITPY_CONSOLE_BLE - -static const char default_name[] = "CP-REPL"; // max 8 chars or uuid won't fit in adv data -static const char NUS_UUID[] = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; - -#define NUS_RX_UUID 0x0002 -#define NUS_TX_UUID 0x0003 -#define BUFFER_SIZE 128 - -ringBuffer_typedef(uint8_t, ringbuffer_t); - -static bleio_device_obj_t m_device; -static bleio_service_obj_t *m_nus; -static bleio_characteristic_obj_t *m_tx_chara; -static bleio_characteristic_obj_t *m_rx_chara; - -static volatile bool m_cccd_enabled; - -static uint8_t m_rx_ring_buffer_data[BUFFER_SIZE]; -static ringbuffer_t m_rx_ring_buffer = { - .size = sizeof(m_rx_ring_buffer_data) + 1, - .elems = m_rx_ring_buffer_data, -}; - -STATIC void on_ble_evt(ble_evt_t *ble_evt, void *param) { - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_DISCONNECTED: { - mp_obj_t device_obj = MP_OBJ_FROM_PTR(&m_device); - mp_call_function_0(mp_load_attr(device_obj, qstr_from_str("start_advertising"))); - break; - } - - case BLE_GATTS_EVT_WRITE: { - ble_gatts_evt_write_t *write = &ble_evt->evt.gatts_evt.params.write; - - if (write->handle == m_tx_chara->cccd_handle) { - m_cccd_enabled = true; - } else if (write->handle == m_rx_chara->handle) { - for (size_t i = 0; i < write->len; ++i) { - #if MICROPY_KBD_EXCEPTION - if (write->data[i] == mp_interrupt_char) { - mp_sched_keyboard_interrupt(); - } else - #endif - { - bufferWrite(&m_rx_ring_buffer, write->data[i]); - } - } - } - } - } -} - -void ble_uart_init(void) { - mp_obj_t device_obj = MP_OBJ_FROM_PTR(&m_device); - m_device.base.type = &bleio_device_type; - m_device.service_list = mp_obj_new_list(0, NULL); - m_device.notif_handler = mp_const_none; - m_device.conn_handler = mp_const_none; - m_device.conn_handle = 0xFFFF; - m_device.is_peripheral = true; - m_device.name = mp_obj_new_str(default_name, strlen(default_name), false); - common_hal_bleio_adapter_get_address(&m_device.address); - - mp_obj_t nus_uuid_str = mp_obj_new_str(NUS_UUID, strlen(NUS_UUID), false); - mp_obj_t nus_uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &nus_uuid_str); - mp_obj_t nus_obj = bleio_service_type.make_new(&bleio_service_type, 1, 0, &nus_uuid_obj); - m_nus = MP_OBJ_TO_PTR(nus_obj); - mp_call_function_1(mp_load_attr(device_obj, qstr_from_str("add_service")), nus_obj); - - mp_obj_t tx_uuid_int = mp_obj_new_int(NUS_TX_UUID); - mp_obj_t tx_uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &tx_uuid_int); - mp_obj_t tx_obj = bleio_characteristic_type.make_new(&bleio_characteristic_type, 1, 0, &tx_uuid_obj); - m_tx_chara = MP_OBJ_TO_PTR(tx_obj); - m_tx_chara->uuid->type = UUID_TYPE_128BIT; - m_tx_chara->uuid->uuid_vs_idx = m_nus->uuid->uuid_vs_idx; - m_tx_chara->props.notify = true; - mp_call_function_1(mp_load_attr(nus_obj, qstr_from_str("add_characteristic")), tx_obj); - - mp_obj_t rx_uuid_int = mp_obj_new_int(NUS_RX_UUID); - mp_obj_t rx_uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &rx_uuid_int); - mp_obj_t rx_obj = bleio_characteristic_type.make_new(&bleio_characteristic_type, 1, 0, &rx_uuid_obj); - m_rx_chara = MP_OBJ_TO_PTR(rx_obj); - m_rx_chara->uuid->type = UUID_TYPE_128BIT; - m_rx_chara->uuid->uuid_vs_idx = m_nus->uuid->uuid_vs_idx; - m_rx_chara->props.write = true; - m_rx_chara->props.write_wo_resp = true; - mp_call_function_1(mp_load_attr(nus_obj, qstr_from_str("add_characteristic")), rx_obj); - - mp_call_function_0(mp_load_attr(device_obj, qstr_from_str("start_advertising"))); - - ble_drv_add_event_handler(on_ble_evt, &m_device); - - m_cccd_enabled = false; - - while (!m_cccd_enabled) { - RUN_BACKGROUND_TASKS; - } -} - -bool ble_uart_connected(void) { - return m_device.conn_handle != BLE_CONN_HANDLE_INVALID; -} - -char ble_uart_rx_chr(void) { - while (isBufferEmpty(&m_rx_ring_buffer)) { - RUN_BACKGROUND_TASKS; - } - - uint8_t byte; - bufferRead(&m_rx_ring_buffer, byte); - return (int)byte; -} - -bool ble_uart_stdin_any(void) { - return !isBufferEmpty(&m_rx_ring_buffer); -} - -void ble_uart_stdout_tx_str(const char *text) { - mp_hal_stdout_tx_strn(text, strlen(text)); -} - -int mp_hal_stdin_rx_chr(void) { - return ble_uart_rx_chr(); -} - -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - size_t send_len; - - while (len > 0) { - if (len >= BLE_GATT_ATT_MTU_DEFAULT - 3) { - send_len = (BLE_GATT_ATT_MTU_DEFAULT - 3); - } else { - send_len = len; - } - - mp_buffer_info_t bufinfo = { - .buf = (uint8_t *)str, - .len = send_len, - }; - - common_hal_bleio_characteristic_write_value(m_tx_chara, &bufinfo); - - len -= send_len; - str += send_len; - } -} - -#endif // CIRCUITPY_CONSOLE_BLE diff --git a/ports/nrf/bluetooth/ringbuffer.h b/ports/nrf/bluetooth/ringbuffer.h deleted file mode 100644 index baf2732931..0000000000 --- a/ports/nrf/bluetooth/ringbuffer.h +++ /dev/null @@ -1,99 +0,0 @@ -/* The MIT License (MIT) - * - * Copyright (c) 2013 Philip Thrasher - * - * 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. - * Philip Thrasher's Crazy Awesome Ring Buffer Macros! - * - * Below you will find some naughty macros for easy owning and manipulating - * generic ring buffers. Yes, they are slightly evil in readability, but they - * are really fast, and they work great. - * - * Example usage: - * - * #include - * - * // So we can use this in any method, this gives us a typedef - * // named 'intBuffer'. - * ringBuffer_typedef(int, intBuffer); - * - * int main() { - * // Declare vars. - * intBuffer myBuffer; - * - * bufferInit(myBuffer,1024,int); - * - * // We must have the pointer. All of the macros deal with the pointer. - * // (except for init.) - * intBuffer* myBuffer_ptr; - * myBuffer_ptr = &myBuffer; - * - * // Write two values. - * bufferWrite(myBuffer_ptr,37); - * bufferWrite(myBuffer_ptr,72); - * - * // Read a value into a local variable. - * int first; - * bufferRead(myBuffer_ptr,first); - * assert(first == 37); // true - * - * int second; - * bufferRead(myBuffer_ptr,second); - * assert(second == 72); // true - * - * return 0; - * } - * - */ - -#ifndef _ringbuffer_h -#define _ringbuffer_h - -#define ringBuffer_typedef(T, NAME) \ - typedef struct { \ - int size; \ - volatile int start; \ - volatile int end; \ - T *elems; \ - } NAME - -#define bufferInit(BUF, S, T) \ - BUF.size = S + 1; \ - BUF.start = 0; \ - BUF.end = 0; \ - BUF.elems = (T *)calloc(BUF.size, sizeof(T)) - - -#define bufferDestroy(BUF) free((BUF)->elems) -#define nextStartIndex(BUF) (((BUF)->start + 1) % (BUF)->size) -#define nextEndIndex(BUF) (((BUF)->end + 1) % (BUF)->size) -#define isBufferEmpty(BUF) ((BUF)->end == (BUF)->start) -#define isBufferFull(BUF) (nextEndIndex(BUF) == (BUF)->start) - -#define bufferWrite(BUF, ELEM) \ - (BUF)->elems[(BUF)->end] = ELEM; \ - (BUF)->end = ((BUF)->end + 1) % (BUF)->size; \ - if (isBufferEmpty(BUF)) { \ - (BUF)->start = nextStartIndex(BUF); \ - } - -#define bufferRead(BUF, ELEM) \ - ELEM = (BUF)->elems[(BUF)->start]; \ - (BUF)->start = nextStartIndex(BUF); - -#endif diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 3f8fbc3a97..bf92c7b3ba 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -40,7 +40,7 @@ #include "py/gc.h" #include "py/objstr.h" #include "py/runtime.h" -#include "supervisor/shared/bluetooth.h" +#include "supervisor/shared/bluetooth/bluetooth.h" #include "supervisor/shared/safe_mode.h" #include "supervisor/shared/tick.h" #include "supervisor/usb.h" diff --git a/ports/nrf/common-hal/_bleio/Characteristic.c b/ports/nrf/common-hal/_bleio/Characteristic.c index 621d400794..df86654c70 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.c +++ b/ports/nrf/common-hal/_bleio/Characteristic.c @@ -86,7 +86,8 @@ STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, - mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { + mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, + const char *user_description) { self->service = service; self->uuid = uuid; self->handle = BLE_GATT_HANDLE_INVALID; @@ -125,7 +126,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, if (service->is_remote) { self->handle = handle; } else { - common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo); + common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo, user_description); } } diff --git a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c index b17327da47..ca37f41c1a 100644 --- a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c @@ -80,20 +80,34 @@ STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { return true; } +void _common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + uint8_t *buffer, size_t buffer_size, + void *static_handler_entry) { + + self->characteristic = characteristic; + self->timeout_ms = timeout * 1000; + + self->ringbuf.buf = (uint8_t *)buffer; + self->ringbuf.size = buffer_size; + self->ringbuf.iget = 0; + self->ringbuf.iput = 0; + + if (static_handler_entry != NULL) { + ble_drv_add_event_handler_entry((ble_drv_evt_handler_entry_t *)static_handler_entry, characteristic_buffer_on_ble_evt, self); + } else { + ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self); + } +} + // Assumes that timeout and buffer_size have been validated before call. void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size) { - - self->characteristic = characteristic; - self->timeout_ms = timeout * 1000; - // This is a macro. - // true means long-lived, so it won't be moved. - ringbuf_alloc(&self->ringbuf, buffer_size, true); - - ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self); - + uint8_t *buffer = m_malloc(buffer_size, true); + _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, buffer, buffer_size, NULL); } uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) { diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c index 335f56c30c..0e7c6a3c54 100644 --- a/ports/nrf/common-hal/_bleio/Connection.c +++ b/ports/nrf/common-hal/_bleio/Connection.c @@ -311,6 +311,7 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { // Did an sd_ble_gatts_sys_attr_set() with the stored sys_attr values. // Indicate ATTR table change because we may have reloaded since the peer last // connected. + mp_printf(&mp_plat_print, "restore sys attrs\n"); sd_ble_gatts_service_changed(self->conn_handle, 0xC, 0xFFFF); } else { // No matching bonding found, so use fresh system attributes. @@ -533,7 +534,8 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio characteristic, m_char_discovery_service, gattc_char->handle_value, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values don't matter for gattc - mp_const_empty_bytes); + mp_const_empty_bytes, + NULL); mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list), MP_OBJ_FROM_PTR(characteristic)); diff --git a/ports/nrf/common-hal/_bleio/PacketBuffer.c b/ports/nrf/common-hal/_bleio/PacketBuffer.c index e721cfb53b..4a123a7c00 100644 --- a/ports/nrf/common-hal/_bleio/PacketBuffer.c +++ b/ports/nrf/common-hal/_bleio/PacketBuffer.c @@ -173,6 +173,23 @@ STATIC bool packet_buffer_on_ble_server_evt(ble_evt_t *ble_evt, void *param) { } break; } + case BLE_GAP_EVT_CONN_SEC_UPDATE: { // 0x1a + if (self->conn_handle != BLE_CONN_HANDLE_INVALID) { + break; + } + uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle; + // Check to see if the bond restored the HVX state. + uint16_t cccd; + ble_gatts_value_t value; + value.len = sizeof(uint16_t); + value.offset = 0; + value.p_value = (uint8_t *)&cccd; + sd_ble_gatts_value_get(conn_handle, self->characteristic->cccd_handle, &value); + if (cccd & BLE_GATT_HVX_NOTIFICATION) { + self->conn_handle = conn_handle; + } + break; + } case BLE_GAP_EVT_CONNECTED: break; case BLE_GAP_EVT_DISCONNECTED: diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c index 5302f25946..0c4ded2d1b 100644 --- a/ports/nrf/common-hal/_bleio/Service.c +++ b/ports/nrf/common-hal/_bleio/Service.c @@ -112,7 +112,8 @@ STATIC void _expand_range(uint16_t new_value, uint16_t *start, uint16_t *end) { void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, - mp_buffer_info_t *initial_value_bufinfo) { + mp_buffer_info_t *initial_value_bufinfo, + const char *user_description) { ble_gatts_char_md_t char_md = { .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0, .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0, @@ -142,6 +143,19 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, char_md.p_cccd_md = &cccd_md; } + ble_gatts_attr_md_t user_desc_md; + if (user_description != NULL && strlen(user_description) > 0) { + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_desc_md.read_perm); + // If the description is on the Python heap, then have the SD copy it. If not, assume it's + // static and will live for longer than the SD. + user_desc_md.vloc = gc_nbytes(user_description) > 0 ? BLE_GATTS_VLOC_STACK : BLE_GATTS_VLOC_USER; + char_md.p_user_desc_md = &user_desc_md; + char_md.p_char_user_desc = (const uint8_t *)user_description; + char_md.char_user_desc_max_size = strlen(user_description); + char_md.char_user_desc_size = strlen(user_description); + mp_printf(&mp_plat_print, "user description %s\n", user_description); + } + bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm); bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm); #if CIRCUITPY_VERBOSE_BLE diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index 3c919c9ffe..de1641eb9d 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -36,7 +36,7 @@ #include "shared-bindings/_bleio/Descriptor.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" -#include "supervisor/shared/bluetooth.h" +#include "supervisor/shared/bluetooth/bluetooth.h" #include "common-hal/_bleio/__init__.h" #include "common-hal/_bleio/bonding.h" diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk index 6bd63bcd72..87d79cb0e5 100644 --- a/ports/nrf/mpconfigport.mk +++ b/ports/nrf/mpconfigport.mk @@ -50,6 +50,9 @@ CIRCUITPY_ALARM ?= 1 # Turn on the BLE file service CIRCUITPY_BLE_FILE_SERVICE ?= 1 +# Turn on the BLE serial service +CIRCUITPY_SERIAL_BLE ?= 1 + CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE ?= 1 # nRF52840-specific diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index f4075f0d5a..0e2c577c69 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -136,9 +136,6 @@ CFLAGS += -DCIRCUITPY_DIGITALIO=$(CIRCUITPY_DIGITALIO) CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE ?= 0 CFLAGS += -DCIRCUITPY_COMPUTED_GOTO_SAVE_SPACE=$(CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE) -CIRCUITPY_CONSOLE_BLE ?= 0 -CFLAGS += -DCIRCUITPY_CONSOLE_BLE=$(CIRCUITPY_CONSOLE_BLE) - CIRCUITPY_CONSOLE_UART ?= 0 CFLAGS += -DCIRCUITPY_CONSOLE_UART=$(CIRCUITPY_CONSOLE_UART) @@ -255,15 +252,6 @@ CFLAGS += -DCIRCUITPY_RANDOM=$(CIRCUITPY_RANDOM) CIRCUITPY_RE ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_RE=$(CIRCUITPY_RE) -CIRCUITPY_REPL_BLE ?= 0 -CFLAGS += -DCIRCUITPY_REPL_BLE=$(CIRCUITPY_REPL_BLE) - -CIRCUITPY_REPL_UART ?= 0 -CFLAGS += -DCIRCUITPY_REPL_UART=$(CIRCUITPY_REPL_UART) - -CIRCUITPY_REPL_USB ?= 1 -CFLAGS += -DCIRCUITPY_REPL_USB=$(CIRCUITPY_REPL_USB) - # Should busio.I2C() check for pullups? # Some boards in combination with certain peripherals may not want this. CIRCUITPY_REQUIRE_I2C_PULLUPS ?= 1 @@ -299,6 +287,9 @@ CFLAGS += -DCIRCUITPY_SDCARDIO=$(CIRCUITPY_SDCARDIO) CIRCUITPY_SDIOIO ?= 0 CFLAGS += -DCIRCUITPY_SDIOIO=$(CIRCUITPY_SDIOIO) +CIRCUITPY_SERIAL_BLE ?= 0 +CFLAGS += -DCIRCUITPY_SERIAL_BLE=$(CIRCUITPY_SERIAL_BLE) + CIRCUITPY_SHARPDISPLAY ?= $(CIRCUITPY_FRAMEBUFFERIO) CFLAGS += -DCIRCUITPY_SHARPDISPLAY=$(CIRCUITPY_SHARPDISPLAY) diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 3c9e189d48..b6b6ee69d4 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -45,7 +45,11 @@ //| ... //| -//| def add_to_service(self, service: Service, uuid: UUID, *, properties: int = 0, read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, max_length: int = 20, fixed_length: bool = False, initial_value: Optional[ReadableBuffer] = None) -> Characteristic: +//| def add_to_service(self, service: Service, uuid: UUID, *, properties: int = 0, +//| read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, +//| max_length: int = 20, fixed_length: bool = False, +//| initial_value: Optional[ReadableBuffer] = None, +//| user_description: Optional[str] = None) -> Characteristic: //| """Create a new Characteristic object, and add it to this Service. //| //| :param Service service: The service that will provide this characteristic @@ -65,6 +69,7 @@ //| :param bool fixed_length: True if the characteristic value is of fixed length. //| :param ~_typing.ReadableBuffer initial_value: The initial value for this characteristic. If not given, will be //| filled with zeros. +//| :param str user_description: User friendly description of the characteristic //| //| :return: the new Characteristic.""" //| ... @@ -73,7 +78,7 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ // class is arg[0], which we can ignore. enum { ARG_service, ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm, - ARG_max_length, ARG_fixed_length, ARG_initial_value }; + ARG_max_length, ARG_fixed_length, ARG_initial_value, ARG_user_description }; static const mp_arg_t allowed_args[] = { { MP_QSTR_service, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -83,6 +88,7 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ { MP_QSTR_max_length, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 20} }, { MP_QSTR_fixed_length, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_initial_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_user_description, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -132,6 +138,11 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ mp_raise_ValueError(translate("initial_value length is wrong")); } + const char *user_description = NULL; + if (args[ARG_user_description].u_obj != mp_const_none) { + user_description = mp_obj_str_get_str(args[ARG_user_description].u_obj); + } + bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); characteristic->base.type = &bleio_characteristic_type; @@ -140,7 +151,8 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ common_hal_bleio_characteristic_construct( characteristic, MP_OBJ_TO_PTR(service_obj), 0, MP_OBJ_TO_PTR(uuid_obj), properties, read_perm, write_perm, - max_length, fixed_length, &initial_value_bufinfo); + max_length, fixed_length, &initial_value_bufinfo, + user_description); return MP_OBJ_FROM_PTR(characteristic); } diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h index 5807abf418..349dd5fdcf 100644 --- a/shared-bindings/_bleio/Characteristic.h +++ b/shared-bindings/_bleio/Characteristic.h @@ -44,7 +44,7 @@ extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characte extern size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t *self); extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len); extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor); -extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description); extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); diff --git a/shared-bindings/_bleio/CharacteristicBuffer.h b/shared-bindings/_bleio/CharacteristicBuffer.h index e82e96ca96..1fd9dd838c 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.h +++ b/shared-bindings/_bleio/CharacteristicBuffer.h @@ -31,7 +31,15 @@ extern const mp_obj_type_t bleio_characteristic_buffer_type; -extern void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size); +void _common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + uint8_t *buffer, size_t buffer_size, + void *static_handler_entry); +void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + size_t buffer_size); uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode); uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self); void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self); diff --git a/shared-bindings/_bleio/Service.h b/shared-bindings/_bleio/Service.h index b2a35793fb..eb1d29b57e 100644 --- a/shared-bindings/_bleio/Service.h +++ b/shared-bindings/_bleio/Service.h @@ -44,6 +44,6 @@ extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t * extern mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self); -extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo); +extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo, const char *user_description); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c new file mode 100644 index 0000000000..abfbecd8c8 --- /dev/null +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -0,0 +1,232 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "supervisor/shared/bluetooth/bluetooth.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#if defined(CIRCUITPY_BOOT_BUTTON) +#include "shared-bindings/digitalio/DigitalInOut.h" +#endif +#include "shared-bindings/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" +#include "shared-module/storage/__init__.h" + +#include "bluetooth/ble_drv.h" + +#include "common-hal/_bleio/__init__.h" + +#include "supervisor/shared/status_leds.h" +#include "supervisor/shared/tick.h" + +#include "py/mpstate.h" + +#if CIRCUITPY_BLE_FILE_SERVICE +#include "supervisor/shared/bluetooth/file_transfer.h" +#endif + +#if CIRCUITPY_SERIAL_BLE +#include "supervisor/shared/bluetooth/serial.h" +#endif + +// This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name. +const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags + 0x02, 0x0a, 0xd8, // 3-5 TX power level -40 + #if CIRCUITPY_BLE_FILE_SERVICE + 0x03, 0x02, 0xbb, 0xfe, // 6 - 9 Incomplete service list (File Transfer service) + #endif + 0x0e, 0xff, 0x22, 0x08, // 10 - 13 Adafruit Manufacturer Data + 0x0a, 0x04, 0x00, // 14 - 16 Creator ID / Creation ID + CIRCUITPY_CREATOR_ID & 0xff, // 17 - 20 Creator ID + (CIRCUITPY_CREATOR_ID >> 8) & 0xff, + (CIRCUITPY_CREATOR_ID >> 16) & 0xff, + (CIRCUITPY_CREATOR_ID >> 24) & 0xff, + CIRCUITPY_CREATION_ID & 0xff, // 21 - 24 Creation ID + (CIRCUITPY_CREATION_ID >> 8) & 0xff, + (CIRCUITPY_CREATION_ID >> 16) & 0xff, + (CIRCUITPY_CREATION_ID >> 24) & 0xff, + 0x05, 0x08, 0x43, 0x49, 0x52, 0x43 // 25 - 31 - Short name +}; +const uint8_t private_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags + 0x02, 0x0a, 0x00 // 3-5 TX power level 0 +}; +// This scan response advertises the full CIRCUITPYXXXX device name. +uint8_t circuitpython_scan_response_data[] = { + 0x0e, 0x09, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00, + #if CIRCUITPY_SERIAL_BLE + 0x06, 0x10, 0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x00, 0x00, 0x40, 0x6e, + #endif +}; + +bool boot_in_discovery_mode = false; +bool advertising = false; + +STATIC void supervisor_bluetooth_start_advertising(void) { + bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); + if (is_connected) { + return; + } + bool bonded = common_hal_bleio_adapter_is_bonded_to_central(&common_hal_bleio_adapter_obj); + #if CIRCUITPY_USB + // Don't advertise when we have USB instead of BLE. + if (!bonded && !boot_in_discovery_mode) { + // mp_printf(&mp_plat_print, "skipping advertising\n"); + return; + } + #endif + uint32_t timeout = 0; + float interval = 0.1f; + int tx_power = 0; + const uint8_t *adv = private_advertising_data; + size_t adv_len = sizeof(private_advertising_data); + const uint8_t *scan_response = NULL; + size_t scan_response_len = 0; + // Advertise with less power when doing so publicly to reduce who can hear us. This will make it + // harder for someone with bad intentions to pair from a distance. + if (!bonded) { + tx_power = -40; + adv = public_advertising_data; + adv_len = sizeof(public_advertising_data); + scan_response = circuitpython_scan_response_data; + scan_response_len = sizeof(circuitpython_scan_response_data); + } + uint32_t status = _common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj, + true, + bonded, // Advertise anonymously if we are bonded + timeout, + interval, + adv, + adv_len, + scan_response, + scan_response_len, + tx_power, + NULL); + // This may fail if we are already advertising. + advertising = status == NRF_SUCCESS; +} + +#define BLE_DISCOVERY_DATA_GUARD 0xbb0000bb +#define BLE_DISCOVERY_DATA_GUARD_MASK 0xff0000ff + +void supervisor_bluetooth_init(void) { + uint32_t reset_state = port_get_saved_word(); + uint32_t ble_mode = 0; + if ((reset_state & BLE_DISCOVERY_DATA_GUARD_MASK) == BLE_DISCOVERY_DATA_GUARD) { + ble_mode = (reset_state & ~BLE_DISCOVERY_DATA_GUARD_MASK) >> 8; + } + const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); + boot_in_discovery_mode = false; + if (reset_reason != RESET_REASON_POWER_ON && + reset_reason != RESET_REASON_RESET_PIN && + reset_reason != RESET_REASON_UNKNOWN && + reset_reason != RESET_REASON_SOFTWARE) { + return; + } + + if (ble_mode == 0) { + port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8)); + } + // Wait for a while to allow for reset. + + #ifdef CIRCUITPY_BOOT_BUTTON + digitalio_digitalinout_obj_t boot_button; + common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); + common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); + #endif + uint64_t start_ticks = supervisor_ticks_ms64(); + uint64_t diff = 0; + if (ble_mode != 0) { + #ifdef CIRCUITPY_STATUS_LED + new_status_color(0x0000ff); + #endif + common_hal_bleio_adapter_erase_bonding(&common_hal_bleio_adapter_obj); + boot_in_discovery_mode = true; + reset_state = 0x0; + } + while (diff < 1000) { + #ifdef CIRCUITPY_STATUS_LED + // Blink on for 100, off for 100, on for 100, off for 100 and on for 200 + bool led_on = ble_mode != 0 || (diff % 150) <= 75; + if (led_on) { + new_status_color(0x0000ff); + } else { + new_status_color(BLACK); + } + #endif + #ifdef CIRCUITPY_BOOT_BUTTON + if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) { + boot_in_discovery_mode = true; + break; + } + #endif + diff = supervisor_ticks_ms64() - start_ticks; + } + #if CIRCUITPY_STATUS_LED + new_status_color(BLACK); + status_led_deinit(); + #endif + port_set_saved_word(reset_state); +} + +STATIC bool was_connected; +void supervisor_bluetooth_background(void) { + bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); + if (was_connected && !is_connected) { + #if CIRCUITPY_BLE_FILE_SERVICE + supervisor_bluetooth_file_transfer_disconnected(); + #endif + } + was_connected = is_connected; + if (!is_connected) { + supervisor_bluetooth_start_advertising(); + return; + } + + #if CIRCUITPY_BLE_FILE_SERVICE + supervisor_bluetooth_file_transfer_background(); + #endif +} + +void supervisor_start_bluetooth(void) { + #if !CIRCUITPY_BLE_FILE_SERVICE && !CIRCUITPY_SERIAL_BLE + return; + #endif + + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); + + #if CIRCUITPY_BLE_FILE_SERVICE + supervisor_start_bluetooth_file_transfer(); + #endif + + #if CIRCUITPY_SERIAL_BLE + supervisor_start_bluetooth_serial(); + #endif + + // Kick off advertisments + supervisor_bluetooth_background(); +} diff --git a/supervisor/shared/bluetooth.h b/supervisor/shared/bluetooth/bluetooth.h similarity index 92% rename from supervisor/shared/bluetooth.h rename to supervisor/shared/bluetooth/bluetooth.h index 3784463af3..a8f3e8b159 100644 --- a/supervisor/shared/bluetooth.h +++ b/supervisor/shared/bluetooth/bluetooth.h @@ -29,12 +29,8 @@ #include -#include "shared-bindings/_bleio/Characteristic.h" - void supervisor_bluetooth_background(void); void supervisor_bluetooth_init(void); void supervisor_start_bluetooth(void); -extern bleio_characteristic_obj_t supervisor_ble_transfer_characteristic; - #endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth/file_transfer.c similarity index 66% rename from supervisor/shared/bluetooth.c rename to supervisor/shared/bluetooth/file_transfer.c index f89d8e3334..dcd3d36e78 100644 --- a/supervisor/shared/bluetooth.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -24,23 +24,8 @@ * THE SOFTWARE. */ -#if !CIRCUITPY_BLE_FILE_SERVICE - -void supervisor_bluetooth_init(void) { -} - -void supervisor_start_bluetooth(void) { -} - -void supervisor_bluetooth_background(void) { -} - -#else - #include -#include "supervisor/shared/bluetooth.h" - #include "extmod/vfs.h" #include "extmod/vfs_fat.h" @@ -50,11 +35,6 @@ void supervisor_bluetooth_background(void) { #include "shared-bindings/_bleio/PacketBuffer.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" -#if defined(CIRCUITPY_BOOT_BUTTON) -#include "shared-bindings/digitalio/DigitalInOut.h" -#endif -#include "shared-bindings/microcontroller/Processor.h" -#include "shared-bindings/microcontroller/ResetReason.h" #include "shared-module/storage/__init__.h" #include "bluetooth/ble_drv.h" @@ -62,169 +42,34 @@ void supervisor_bluetooth_background(void) { #include "common-hal/_bleio/__init__.h" #include "supervisor/shared/autoreload.h" -#include "supervisor/shared/status_leds.h" +#include "supervisor/shared/bluetooth/file_transfer_protocol.h" #include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include "py/mpstate.h" -bleio_service_obj_t supervisor_ble_service; -bleio_uuid_obj_t supervisor_ble_service_uuid; -bleio_characteristic_obj_t supervisor_ble_version_characteristic; -bleio_uuid_obj_t supervisor_ble_version_uuid; -bleio_characteristic_obj_t supervisor_ble_transfer_characteristic; -bleio_uuid_obj_t supervisor_ble_transfer_uuid; +STATIC bleio_service_obj_t supervisor_ble_service; +STATIC bleio_uuid_obj_t supervisor_ble_service_uuid; +STATIC bleio_characteristic_obj_t supervisor_ble_version_characteristic; +STATIC bleio_uuid_obj_t supervisor_ble_version_uuid; +STATIC bleio_characteristic_obj_t supervisor_ble_transfer_characteristic; +STATIC bleio_uuid_obj_t supervisor_ble_transfer_uuid; // This is the base UUID for the file transfer service. const uint8_t file_transfer_base_uuid[16] = {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0x00, 0x00, 0xaf, 0xad }; -// This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name. -const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags - 0x02, 0x0a, 0xd8, // 3-5 TX power level -40 - 0x03, 0x02, 0xbb, 0xfe, // 6 - 9 Incomplete service list (File Transfer service) - 0x0e, 0xff, 0x22, 0x08, // 10 - 13 Adafruit Manufacturer Data - 0x0a, 0x04, 0x00, // 14 - 16 Creator ID / Creation ID - CIRCUITPY_CREATOR_ID & 0xff, // 17 - 20 Creator ID - (CIRCUITPY_CREATOR_ID >> 8) & 0xff, - (CIRCUITPY_CREATOR_ID >> 16) & 0xff, - (CIRCUITPY_CREATOR_ID >> 24) & 0xff, - CIRCUITPY_CREATION_ID & 0xff, // 21 - 24 Creation ID - (CIRCUITPY_CREATION_ID >> 8) & 0xff, - (CIRCUITPY_CREATION_ID >> 16) & 0xff, - (CIRCUITPY_CREATION_ID >> 24) & 0xff, - 0x05, 0x08, 0x43, 0x49, 0x52, 0x43 // 25 - 31 - Short name -}; -const uint8_t private_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags - 0x02, 0x0a, 0x00 // 3-5 TX power level 0 -}; -// This scan response advertises the full CIRCUITPYXXXX device name. -uint8_t circuitpython_scan_response_data[15] = {0x0e, 0x09, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00}; -mp_obj_list_t service_list; -mp_obj_t service_list_items[1]; -mp_obj_list_t characteristic_list; -mp_obj_t characteristic_list_items[2]; + +STATIC mp_obj_list_t characteristic_list; +STATIC mp_obj_t characteristic_list_items[2]; // 2 * 10 ringbuf packets, 512 for a disk sector and 12 for the file transfer write header. #define PACKET_BUFFER_SIZE (2 * 10 + 512 + 12) // uint32_t so its aligned -uint32_t _buffer[PACKET_BUFFER_SIZE / 4 + 1]; -uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; -uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; -ble_drv_evt_handler_entry_t static_handler_entry; -bleio_packet_buffer_obj_t _transfer_packet_buffer; -bool boot_in_discovery_mode = false; -bool advertising = false; - -STATIC void supervisor_bluetooth_start_advertising(void) { - bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); - if (is_connected) { - return; - } - bool bonded = common_hal_bleio_adapter_is_bonded_to_central(&common_hal_bleio_adapter_obj); - #if CIRCUITPY_USB - // Don't advertise when we have USB instead of BLE. - if (!bonded && !boot_in_discovery_mode) { - // mp_printf(&mp_plat_print, "skipping advertising\n"); - return; - } - #endif - uint32_t timeout = 0; - float interval = 0.1f; - int tx_power = 0; - const uint8_t *adv = private_advertising_data; - size_t adv_len = sizeof(private_advertising_data); - const uint8_t *scan_response = NULL; - size_t scan_response_len = 0; - // Advertise with less power when doing so publicly to reduce who can hear us. This will make it - // harder for someone with bad intentions to pair from a distance. - if (!bonded) { - tx_power = -40; - adv = public_advertising_data; - adv_len = sizeof(public_advertising_data); - scan_response = circuitpython_scan_response_data; - scan_response_len = sizeof(circuitpython_scan_response_data); - } - uint32_t status = _common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj, - true, - bonded, // Advertise anonymously if we are bonded - timeout, - interval, - adv, - adv_len, - scan_response, - scan_response_len, - tx_power, - NULL); - // This may fail if we are already advertising. - advertising = status == NRF_SUCCESS; -} - -#define BLE_DISCOVERY_DATA_GUARD 0xbb0000bb -#define BLE_DISCOVERY_DATA_GUARD_MASK 0xff0000ff - -void supervisor_bluetooth_init(void) { - uint32_t reset_state = port_get_saved_word(); - uint32_t ble_mode = 0; - if ((reset_state & BLE_DISCOVERY_DATA_GUARD_MASK) == BLE_DISCOVERY_DATA_GUARD) { - ble_mode = (reset_state & ~BLE_DISCOVERY_DATA_GUARD_MASK) >> 8; - } - const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); - boot_in_discovery_mode = false; - if (reset_reason != RESET_REASON_POWER_ON && - reset_reason != RESET_REASON_RESET_PIN && - reset_reason != RESET_REASON_UNKNOWN && - reset_reason != RESET_REASON_SOFTWARE) { - return; - } - - // ble_mode = 1; - - if (ble_mode == 0) { - port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8)); - } - // Wait for a while to allow for reset. - - #ifdef CIRCUITPY_BOOT_BUTTON - digitalio_digitalinout_obj_t boot_button; - common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); - common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); - #endif - uint64_t start_ticks = supervisor_ticks_ms64(); - uint64_t diff = 0; - if (ble_mode != 0) { - #ifdef CIRCUITPY_STATUS_LED - new_status_color(0x0000ff); - #endif - common_hal_bleio_adapter_erase_bonding(&common_hal_bleio_adapter_obj); - boot_in_discovery_mode = true; - reset_state = 0x0; - } - while (diff < 1000) { - #ifdef CIRCUITPY_STATUS_LED - // Blink on for 100, off for 100, on for 100, off for 100 and on for 200 - bool led_on = ble_mode != 0 || (diff % 150) <= 75; - if (led_on) { - new_status_color(0x0000ff); - } else { - new_status_color(BLACK); - } - #endif - #ifdef CIRCUITPY_BOOT_BUTTON - if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) { - boot_in_discovery_mode = true; - break; - } - #endif - diff = supervisor_ticks_ms64() - start_ticks; - } - #if CIRCUITPY_STATUS_LED - new_status_color(BLACK); - status_led_deinit(); - #endif - port_set_saved_word(reset_state); -} - -void supervisor_start_bluetooth(void) { - common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); +STATIC uint32_t _buffer[PACKET_BUFFER_SIZE / 4 + 1]; +STATIC uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; +STATIC uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; +STATIC ble_drv_evt_handler_entry_t static_handler_entry; +STATIC bleio_packet_buffer_obj_t _transfer_packet_buffer; +void supervisor_start_bluetooth_file_transfer(void) { supervisor_ble_service_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&supervisor_ble_service_uuid, 0xfebb, NULL); @@ -249,7 +94,8 @@ void supervisor_start_bluetooth(void) { SECURITY_MODE_NO_ACCESS, 4, // max length true, // fixed length - NULL); // no initial value + NULL, // no initial value + NULL); // no description uint32_t version = 1; mp_buffer_info_t bufinfo; @@ -269,71 +115,24 @@ void supervisor_start_bluetooth(void) { SECURITY_MODE_ENC_NO_MITM, BLE_GATTS_VAR_ATTR_LEN_MAX, // max length false, // fixed length - NULL); // no initial value + NULL, // no initial valuen + NULL); _common_hal_bleio_packet_buffer_construct( &_transfer_packet_buffer, &supervisor_ble_transfer_characteristic, _buffer, PACKET_BUFFER_SIZE, _outgoing1, _outgoing2, BLE_GATTS_VAR_ATTR_LEN_MAX, &static_handler_entry); - - // Kick off advertisments - supervisor_bluetooth_background(); } #define COMMAND_SIZE 1024 #define ANY_COMMAND 0x00 #define THIS_COMMAND 0x01 -#define READ 0x10 -#define READ_DATA 0x11 -#define READ_PACING 0x12 -#define WRITE 0x20 -#define WRITE_PACING 0x21 -#define WRITE_DATA 0x22 -#define DELETE 0x30 -#define DELETE_STATUS 0x31 -#define MKDIR 0x40 -#define MKDIR_STATUS 0x41 -#define LISTDIR 0x50 -#define LISTDIR_ENTRY 0x51 - -#define STATUS_OK 0x01 -#define STATUS_ERROR 0x02 -#define STATUS_ERROR_NO_FILE 0x03 -#define STATUS_ERROR_PROTOCOL 0x04 // Used by read and write. -FIL active_file; - -struct read_command { - uint8_t command; - uint8_t reserved; - uint16_t path_length; - uint32_t chunk_offset; - uint32_t chunk_size; - uint8_t path[]; -}; - -struct read_data { - uint8_t command; - uint8_t status; - uint16_t reserved; - uint32_t chunk_offset; - uint32_t total_length; - uint32_t data_size; - uint8_t data[]; -}; - -struct read_pacing { - uint8_t command; - uint8_t status; - uint16_t reserved; - uint32_t chunk_offset; - uint32_t chunk_size; -}; - -uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) { +STATIC FIL active_file; +STATIC uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) { struct read_command *command = (struct read_command *)raw_buf; size_t header_size = 12; size_t response_size = 16; @@ -390,7 +189,7 @@ uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) { return READ_PACING; } -uint8_t _process_read_pacing(const uint8_t *command, size_t command_len) { +STATIC uint8_t _process_read_pacing(const uint8_t *command, size_t command_len) { size_t response_size = 4 * sizeof(uint32_t); uint32_t response[response_size / sizeof(uint32_t)]; uint8_t *response_bytes = (uint8_t *)response; @@ -429,35 +228,9 @@ uint8_t _process_read_pacing(const uint8_t *command, size_t command_len) { } // Used by write and write data to know when the write is complete. -size_t total_write_length; +STATIC size_t total_write_length; -struct write_command { - uint8_t command; - uint8_t reserved; - uint16_t path_length; - uint32_t offset; - uint32_t total_length; - uint8_t path[]; -}; - -struct write_data { - uint8_t command; - uint8_t status; - uint16_t reserved; - uint32_t offset; - uint32_t data_size; - uint8_t data[]; -}; - -struct write_pacing { - uint8_t command; - uint8_t status; - uint16_t reserved; - uint32_t offset; - uint32_t free_space; -}; - -uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { +STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { struct write_command *command = (struct write_command *)raw_buf; size_t header_size = 12; struct write_pacing response; @@ -508,7 +281,7 @@ uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { return WRITE_DATA; } -uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) { +STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) { struct write_data *command = (struct write_data *)raw_buf; size_t header_size = 12; struct write_pacing response; @@ -561,28 +334,16 @@ uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) { return WRITE_DATA; } -struct delete_command { - uint8_t command; - uint8_t reserved; - uint16_t path_length; - uint8_t path[]; -}; - -struct delete_response { - uint8_t command; - uint8_t status; -}; - -uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) { +STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) { const struct delete_command *command = (struct delete_command *)raw_buf; size_t header_size = 4; - struct delete_response response; + struct delete_status response; response.command = DELETE_STATUS; response.status = STATUS_OK; if (command->path_length > (COMMAND_SIZE - header_size - 1)) { // -1 for the null we'll write // TODO: throw away any more packets of path. response.status = STATUS_ERROR; - common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_response), NULL, 0); + common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0); return ANY_COMMAND; } // We need to receive another packet to have the full path. @@ -596,32 +357,20 @@ uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) { if (result != FR_OK) { response.status = STATUS_ERROR; } - common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_response), NULL, 0); + common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0); return ANY_COMMAND; } -struct mkdir_command { - uint8_t command; - uint8_t reserved; - uint16_t path_length; - uint8_t path[]; -}; - -struct mkdir_response { - uint8_t command; - uint8_t status; -}; - -uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) { +STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) { const struct mkdir_command *command = (struct mkdir_command *)raw_buf; size_t header_size = 4; - struct mkdir_response response; + struct mkdir_status response; response.command = MKDIR_STATUS; response.status = STATUS_OK; if (command->path_length > (COMMAND_SIZE - header_size - 1)) { // -1 for the null we'll write // TODO: throw away any more packets of path. response.status = STATUS_ERROR; - common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_response), NULL, 0); + common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0); return ANY_COMMAND; } // We need to receive another packet to have the full path. @@ -636,29 +385,11 @@ uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) { if (result != FR_OK) { response.status = STATUS_ERROR; } - common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_response), NULL, 0); + common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0); return ANY_COMMAND; } -struct listdir_command { - uint8_t command; - uint8_t reserved; - uint16_t path_length; - uint8_t path[]; -}; - -struct listdir_entry { - uint8_t command; - uint8_t status; - uint16_t path_length; - uint32_t entry_number; - uint32_t entry_count; - uint32_t flags; - uint32_t file_size; - uint8_t path[]; -}; - -uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) { +STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) { const struct listdir_command *command = (struct listdir_command *)raw_buf; struct listdir_entry *entry = (struct listdir_entry *)raw_buf; size_t header_size = 4; @@ -740,22 +471,10 @@ uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) { // Background state that must live across background calls. After the _process // helpers to force them to not use them. -uint8_t current_command[COMMAND_SIZE] __attribute__ ((aligned(4))); -volatile size_t current_offset; -uint8_t next_command; -bool was_connected; -void supervisor_bluetooth_background(void) { - bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); - if (was_connected && !is_connected) { - f_close(&active_file); - } - was_connected = is_connected; - if (!is_connected) { - next_command = 0; - supervisor_bluetooth_start_advertising(); - return; - } - +STATIC uint8_t current_command[COMMAND_SIZE] __attribute__ ((aligned(4))); +STATIC volatile size_t current_offset; +STATIC uint8_t next_command; +void supervisor_bluetooth_file_transfer_background(void) { mp_int_t size = 1; while (size > 0) { size = common_hal_bleio_packet_buffer_readinto(&_transfer_packet_buffer, current_command + current_offset, COMMAND_SIZE - current_offset); @@ -810,4 +529,7 @@ void supervisor_bluetooth_background(void) { } } -#endif // #else +void supervisor_bluetooth_file_transfer_disconnected(void) { + next_command = ANY_COMMAND; + f_close(&active_file); +} diff --git a/ports/nrf/bluetooth/ble_uart.h b/supervisor/shared/bluetooth/file_transfer.h similarity index 73% rename from ports/nrf/bluetooth/ble_uart.h rename to supervisor/shared/bluetooth/file_transfer.h index d86e6293ae..e27924e7fa 100644 --- a/ports/nrf/bluetooth/ble_uart.h +++ b/supervisor/shared/bluetooth/file_transfer.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,17 +24,13 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_UART_H -#define MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_UART_H +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_H #include -#include "ble_drv.h" +void supervisor_bluetooth_file_transfer_background(void); +void supervisor_start_bluetooth_file_transfer(void); +void supervisor_bluetooth_file_transfer_disconnected(void); -void ble_uart_init(void); -bool ble_uart_connected(void); -char ble_uart_rx_chr(void); -bool ble_uart_stdin_any(void); -void ble_uart_stdout_tx_str(const char *text); - -#endif // MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_UART_H +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_H diff --git a/supervisor/shared/bluetooth/file_transfer_protocol.h b/supervisor/shared/bluetooth/file_transfer_protocol.h new file mode 100644 index 0000000000..2c8fe1e5e7 --- /dev/null +++ b/supervisor/shared/bluetooth/file_transfer_protocol.h @@ -0,0 +1,149 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_PROTOCOL_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_PROTOCOL_H + +#include + +// See https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer +// for full protocol documentation and a Python client API. + +// 0x00 - 0x0f are never used by the protocol as a command +#define READ 0x10 +struct read_command { + uint8_t command; + uint8_t reserved; + uint16_t path_length; + uint32_t chunk_offset; + uint32_t chunk_size; + uint8_t path[]; +}; + +#define READ_DATA 0x11 +struct read_data { + uint8_t command; + uint8_t status; + uint16_t reserved; + uint32_t chunk_offset; + uint32_t total_length; + uint32_t data_size; + uint8_t data[]; +}; + +#define READ_PACING 0x12 +struct read_pacing { + uint8_t command; + uint8_t status; + uint16_t reserved; + uint32_t chunk_offset; + uint32_t chunk_size; +}; + +#define WRITE 0x20 +struct write_command { + uint8_t command; + uint8_t reserved; + uint16_t path_length; + uint32_t offset; + uint32_t total_length; + uint8_t path[]; +}; + +#define WRITE_PACING 0x21 +struct write_pacing { + uint8_t command; + uint8_t status; + uint16_t reserved; + uint32_t offset; + uint32_t free_space; +}; + +#define WRITE_DATA 0x22 +struct write_data { + uint8_t command; + uint8_t status; + uint16_t reserved; + uint32_t offset; + uint32_t data_size; + uint8_t data[]; +}; + +#define DELETE 0x30 +struct delete_command { + uint8_t command; + uint8_t reserved; + uint16_t path_length; + uint8_t path[]; +}; + +#define DELETE_STATUS 0x31 +struct delete_status { + uint8_t command; + uint8_t status; +}; + +#define MKDIR 0x40 +struct mkdir_command { + uint8_t command; + uint8_t reserved; + uint16_t path_length; + uint8_t path[]; +}; + +#define MKDIR_STATUS 0x41 +struct mkdir_status { + uint8_t command; + uint8_t status; +}; + +#define LISTDIR 0x50 +struct listdir_command { + uint8_t command; + uint8_t reserved; + uint16_t path_length; + uint8_t path[]; +}; + +#define LISTDIR_ENTRY 0x51 +struct listdir_entry { + uint8_t command; + uint8_t status; + uint16_t path_length; + uint32_t entry_number; + uint32_t entry_count; + uint32_t flags; + uint32_t file_size; + uint8_t path[]; +}; + +#define STATUS_OK 0x01 +#define STATUS_ERROR 0x02 +#define STATUS_ERROR_NO_FILE 0x03 +#define STATUS_ERROR_PROTOCOL 0x04 + + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_PROTOCOL_H diff --git a/supervisor/shared/bluetooth/serial.c b/supervisor/shared/bluetooth/serial.c new file mode 100644 index 0000000000..e1d26b89ce --- /dev/null +++ b/supervisor/shared/bluetooth/serial.c @@ -0,0 +1,153 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/CharacteristicBuffer.h" +#include "shared-bindings/_bleio/PacketBuffer.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" +#include "shared-module/storage/__init__.h" + +#include "common-hal/_bleio/__init__.h" + +#include "py/mpstate.h" + +STATIC bleio_service_obj_t supervisor_ble_serial_service; +STATIC bleio_uuid_obj_t supervisor_ble_serial_service_uuid; +STATIC bleio_characteristic_obj_t supervisor_ble_rx_characteristic; +STATIC bleio_uuid_obj_t supervisor_ble_rx_uuid; +STATIC bleio_characteristic_obj_t supervisor_ble_tx_characteristic; +STATIC bleio_uuid_obj_t supervisor_ble_tx_uuid; + +// This is the base UUID for the nordic uart service. +const uint8_t nordic_uart_base_uuid[16] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x00, 0x00, 0x40, 0x6e }; + +STATIC mp_obj_list_t characteristic_list; +STATIC mp_obj_t characteristic_list_items[2]; + +STATIC uint32_t _outgoing1[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; +STATIC uint32_t _outgoing2[BLE_GATTS_VAR_ATTR_LEN_MAX / 4]; +STATIC ble_drv_evt_handler_entry_t rx_static_handler_entry; +STATIC ble_drv_evt_handler_entry_t tx_static_handler_entry; +STATIC bleio_packet_buffer_obj_t _tx_packet_buffer; +STATIC uint32_t _incoming[64]; +STATIC bleio_characteristic_buffer_obj_t _rx_buffer; + +void supervisor_start_bluetooth_serial(void) { + supervisor_ble_serial_service_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_serial_service_uuid, 0x0001, nordic_uart_base_uuid); + + // We know we'll only be N characteristics so we can statically allocate it. + characteristic_list.base.type = &mp_type_list; + characteristic_list.alloc = sizeof(characteristic_list_items) / sizeof(characteristic_list_items[0]); + characteristic_list.len = 0; + characteristic_list.items = characteristic_list_items; + mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items)); + + _common_hal_bleio_service_construct(&supervisor_ble_serial_service, &supervisor_ble_serial_service_uuid, false /* is secondary */, &characteristic_list); + + // RX + supervisor_ble_rx_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_rx_uuid, 0x0002, nordic_uart_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_rx_characteristic, + &supervisor_ble_serial_service, + 0, // handle (for remote only) + &supervisor_ble_rx_uuid, + CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE, + SECURITY_MODE_NO_ACCESS, + SECURITY_MODE_ENC_NO_MITM, + BLE_GATTS_VAR_ATTR_LEN_MAX, // max length + false, // fixed length + NULL, // no initial value + "CircuitPython Serial"); + + // TX + supervisor_ble_tx_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_tx_uuid, 0x0003, nordic_uart_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_tx_characteristic, + &supervisor_ble_serial_service, + 0, // handle (for remote only) + &supervisor_ble_tx_uuid, + CHAR_PROP_NOTIFY, + SECURITY_MODE_ENC_NO_MITM, + SECURITY_MODE_NO_ACCESS, + BLE_GATTS_VAR_ATTR_LEN_MAX, // max length + false, // fixed length + NULL, // no initial value + "CircuitPython Serial"); + + // Use a PacketBuffer to transmit so that we glom characters to transmit + // together and save BLE overhead. + _common_hal_bleio_packet_buffer_construct( + &_tx_packet_buffer, &supervisor_ble_tx_characteristic, + NULL, 0, + _outgoing1, _outgoing2, BLE_GATTS_VAR_ATTR_LEN_MAX, + &tx_static_handler_entry); + + // Use a CharacteristicBuffer for rx so we can read a single character at a time. + _common_hal_bleio_characteristic_buffer_construct(&_rx_buffer, + &supervisor_ble_rx_characteristic, + 0.1f, + (uint8_t *)_incoming, sizeof(_incoming) * sizeof(uint32_t), + &rx_static_handler_entry); +} + +bool ble_serial_connected(void) { + return _tx_packet_buffer.conn_handle != BLE_CONN_HANDLE_INVALID; +} + +bool ble_serial_available(void) { + return !common_hal_bleio_characteristic_buffer_deinited(&_rx_buffer) && common_hal_bleio_characteristic_buffer_rx_characters_available(&_rx_buffer); +} + +char ble_serial_read_char(void) { + if (common_hal_bleio_characteristic_buffer_deinited(&_rx_buffer)) { + return -1; + } + uint8_t c; + common_hal_bleio_characteristic_buffer_read(&_rx_buffer, &c, 1, NULL); + return c; +} + +void ble_serial_write(const char *text, size_t len) { + if (common_hal_bleio_packet_buffer_deinited(&_tx_packet_buffer)) { + return; + } + size_t sent = 0; + while (sent < len) { + uint16_t packet_size = MIN(len, (size_t)common_hal_bleio_packet_buffer_get_outgoing_packet_length(&_tx_packet_buffer)); + mp_int_t written = common_hal_bleio_packet_buffer_write(&_tx_packet_buffer, (const uint8_t *)text + sent, packet_size, NULL, 0); + // Error, so we drop characters to transmit. + if (written < 0) { + break; + } + sent += written; + } +} diff --git a/supervisor/shared/bluetooth/serial.h b/supervisor/shared/bluetooth/serial.h new file mode 100644 index 0000000000..ac96a67f40 --- /dev/null +++ b/supervisor/shared/bluetooth/serial.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_SERIAL_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_SERIAL_H + +#include + +void supervisor_start_bluetooth_serial(void); + +bool ble_serial_connected(void); +bool ble_serial_available(void); +char ble_serial_read_char(void); +void ble_serial_write(const char *text, size_t len); + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_SERIAL_H diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c index f3a0d5a976..35feacb527 100644 --- a/supervisor/shared/serial.c +++ b/supervisor/shared/serial.c @@ -36,6 +36,10 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/usb_cdc/__init__.h" +#if CIRCUITPY_SERIAL_BLE +#include "supervisor/shared/bluetooth/serial.h" +#endif + #include "tusb.h" #ifdef NRF_DEBUG_PRINT @@ -93,11 +97,24 @@ bool serial_connected(void) { #if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX) return true; - #elif CIRCUITPY_USB_CDC - return usb_cdc_console_enabled() && tud_cdc_connected(); - #else - return tud_cdc_connected(); #endif + + #if CIRCUITPY_SERIAL_BLE + if (ble_serial_connected()) { + return true; + } + #endif + + #if CIRCUITPY_USB_CDC + if (usb_cdc_console_enabled() && tud_cdc_connected()) { + return true; + } + #else + if (tud_cdc_connected()) { + return true; + } + #endif + return false; } char serial_read(void) { @@ -117,7 +134,15 @@ char serial_read(void) { char text; common_hal_busio_uart_read(&debug_uart, (uint8_t *)&text, 1, &uart_errcode); return text; - #elif CIRCUITPY_USB_CDC + #endif + + #if CIRCUITPY_SERIAL_BLE + if (ble_serial_available() > 0) { + return ble_serial_read_char(); + } + #endif + + #if CIRCUITPY_USB_CDC if (!usb_cdc_console_enabled()) { return -1; } @@ -133,14 +158,29 @@ bool serial_bytes_available(void) { #endif #if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX) - return common_hal_busio_uart_rx_characters_available(&debug_uart) || (tud_cdc_available() > 0); - #elif CIRCUITPY_USB_CDC - if (!usb_cdc_console_enabled()) { - return 0; + if (common_hal_busio_uart_rx_characters_available(&debug_uart)) { + return true; } #endif - return tud_cdc_available() > 0; + + #if CIRCUITPY_SERIAL_BLE + if (ble_serial_available()) { + return true; + } + #endif + + #if CIRCUITPY_USB_CDC + if (usb_cdc_console_enabled() && tud_cdc_available() > 0) { + return true; + } + #else + if (tud_cdc_available() > 0) { + return true; + } + #endif + return false; } + void serial_write_substring(const char *text, uint32_t length) { if (length == 0) { return; @@ -156,6 +196,20 @@ void serial_write_substring(const char *text, uint32_t length) { } #endif + #if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX) + int uart_errcode; + + common_hal_busio_uart_write(&debug_uart, (const uint8_t *)text, length, &uart_errcode); + #endif + + #ifdef NRF_DEBUG_PRINT + _debug_print_substr(text, length); + #endif + + #if CIRCUITPY_SERIAL_BLE + ble_serial_write(text, length); + #endif + #if CIRCUITPY_USB_CDC if (!usb_cdc_console_enabled()) { return; @@ -171,17 +225,6 @@ void serial_write_substring(const char *text, uint32_t length) { } usb_background(); } - - #if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX) - int uart_errcode; - - common_hal_busio_uart_write(&debug_uart, (const uint8_t *)text, length, &uart_errcode); - #endif - - #ifdef NRF_DEBUG_PRINT - _debug_print_substr(text, length); - #endif - } void serial_write(const char *text) { diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 6a9a896467..05b728826e 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -36,11 +36,6 @@ #include "supervisor/shared/autoreload.h" #include "supervisor/shared/stack.h" -#if CIRCUITPY_BLEIO -#include "supervisor/shared/bluetooth.h" -#include "common-hal/_bleio/__init__.h" -#endif - #if CIRCUITPY_DISPLAYIO #include "shared-module/displayio/__init__.h" #endif diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index d1790d008a..0f53e1ebeb 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -28,12 +28,16 @@ SPI_FLASH_FILESYSTEM ?= 0 CFLAGS += -DSPI_FLASH_FILESYSTEM=$(SPI_FLASH_FILESYSTEM) ifeq ($(CIRCUITPY_BLEIO),1) - SRC_SUPERVISOR += supervisor/shared/bluetooth.c + SRC_SUPERVISOR += supervisor/shared/bluetooth/bluetooth.c + CIRCUITPY_CREATOR_ID ?= $(USB_VID) + CIRCUITPY_CREATION_ID ?= $(USB_PID) + CFLAGS += -DCIRCUITPY_CREATOR_ID=$(CIRCUITPY_CREATOR_ID) + CFLAGS += -DCIRCUITPY_CREATION_ID=$(CIRCUITPY_CREATION_ID) ifeq ($(CIRCUITPY_BLE_FILE_SERVICE),1) - CIRCUITPY_CREATOR_ID ?= $(USB_VID) - CIRCUITPY_CREATION_ID ?= $(USB_PID) - CFLAGS += -DCIRCUITPY_CREATOR_ID=$(CIRCUITPY_CREATOR_ID) - CFLAGS += -DCIRCUITPY_CREATION_ID=$(CIRCUITPY_CREATION_ID) + SRC_SUPERVISOR += supervisor/shared/bluetooth/file_transfer.c + endif + ifeq ($(CIRCUITPY_SERIAL_BLE),1) + SRC_SUPERVISOR += supervisor/shared/bluetooth/serial.c endif endif From b36858daa06cd3b3d361f6aee17b9d0c2d97b6cb Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 25 Jun 2021 16:40:23 -0700 Subject: [PATCH 06/52] Fix advertisement --- devices/ble_hci/common-hal/_bleio/Adapter.c | 9 +++-- .../common-hal/_bleio/Characteristic.c | 4 +-- devices/ble_hci/common-hal/_bleio/Service.c | 3 +- devices/ble_hci/common-hal/_bleio/__init__.c | 2 +- supervisor/shared/bluetooth/bluetooth.c | 33 +++++++++++-------- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index d9971b05a1..04231a4a76 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -118,7 +118,8 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) { SECURITY_MODE_NO_ACCESS, 248, // max length, from Bluetooth spec false, // not fixed length - &generic_name_bufinfo + &generic_name_bufinfo, + NULL ); uint16_t zero_16 = 0; @@ -140,7 +141,8 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) { SECURITY_MODE_NO_ACCESS, 2, // max length, from Bluetooth spec true, // fixed length - &zero_16_value + &zero_16_value, + NULL ); // Generic Attribute Service setup. @@ -176,7 +178,8 @@ STATIC void add_generic_services(bleio_adapter_obj_t *adapter) { SECURITY_MODE_NO_ACCESS, 4, // max length, from Bluetooth spec true, // fixed length - &zero_32_value + &zero_32_value, + NULL ); } diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index 940fdfc755..e2f9cad0ef 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -41,7 +41,7 @@ #define CCCD_INDICATE 0x2 -void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description) { self->service = service; self->uuid = uuid; self->decl_handle = BLE_GATT_HANDLE_INVALID; @@ -66,7 +66,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, if (service->is_remote) { self->handle = handle; } else { - common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo); + common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo, user_description); } } diff --git a/devices/ble_hci/common-hal/_bleio/Service.c b/devices/ble_hci/common-hal/_bleio/Service.c index 0bf00566f2..11b7efd523 100644 --- a/devices/ble_hci/common-hal/_bleio/Service.c +++ b/devices/ble_hci/common-hal/_bleio/Service.c @@ -84,7 +84,8 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, - mp_buffer_info_t *initial_value_bufinfo) { + mp_buffer_info_t *initial_value_bufinfo, + const char *user_description) { if (self->handle != common_hal_bleio_adapter_obj.last_added_service_handle) { mp_raise_bleio_BluetoothError( diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index 5b592de83a..4a439e8dd2 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -36,7 +36,7 @@ #include "shared-bindings/_bleio/Descriptor.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" -#include "supervisor/shared/bluetooth.h" +#include "supervisor/shared/bluetooth/bluetooth.h" // UUID shared by all cccd's. bleio_uuid_obj_t cccd_uuid; diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index abfbecd8c8..1a57075c6e 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -37,8 +37,6 @@ #include "shared-bindings/microcontroller/ResetReason.h" #include "shared-module/storage/__init__.h" -#include "bluetooth/ble_drv.h" - #include "common-hal/_bleio/__init__.h" #include "supervisor/shared/status_leds.h" @@ -48,10 +46,12 @@ #if CIRCUITPY_BLE_FILE_SERVICE #include "supervisor/shared/bluetooth/file_transfer.h" +#include "bluetooth/ble_drv.h" #endif #if CIRCUITPY_SERIAL_BLE #include "supervisor/shared/bluetooth/serial.h" +#include "bluetooth/ble_drv.h" #endif // This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name. @@ -75,11 +75,11 @@ const uint8_t public_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags const uint8_t private_advertising_data[] = { 0x02, 0x01, 0x06, // 0-2 Flags 0x02, 0x0a, 0x00 // 3-5 TX power level 0 }; -// This scan response advertises the full CIRCUITPYXXXX device name. +// This scan response advertises the full CIRCPYXXXX device name. uint8_t circuitpython_scan_response_data[] = { - 0x0e, 0x09, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x09, 0x43, 0x49, 0x52, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00, #if CIRCUITPY_SERIAL_BLE - 0x06, 0x10, 0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x00, 0x00, 0x40, 0x6e, + 0x11, 0x06, 0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e, #endif }; @@ -87,6 +87,9 @@ bool boot_in_discovery_mode = false; bool advertising = false; STATIC void supervisor_bluetooth_start_advertising(void) { + // #if !CIRCUITPY_BLE_FILE_SERVICE && !CIRCUITPY_SERIAL_BLE + // return; + // #else bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); if (is_connected) { return; @@ -95,7 +98,7 @@ STATIC void supervisor_bluetooth_start_advertising(void) { #if CIRCUITPY_USB // Don't advertise when we have USB instead of BLE. if (!bonded && !boot_in_discovery_mode) { - // mp_printf(&mp_plat_print, "skipping advertising\n"); + mp_printf(&mp_plat_print, "skipping advertising\n"); return; } #endif @@ -109,6 +112,7 @@ STATIC void supervisor_bluetooth_start_advertising(void) { // Advertise with less power when doing so publicly to reduce who can hear us. This will make it // harder for someone with bad intentions to pair from a distance. if (!bonded) { + mp_printf(&mp_plat_print, "public advertising\n"); tx_power = -40; adv = public_advertising_data; adv_len = sizeof(public_advertising_data); @@ -126,6 +130,7 @@ STATIC void supervisor_bluetooth_start_advertising(void) { scan_response_len, tx_power, NULL); + mp_printf(&mp_plat_print, "advert %d\n", status); // This may fail if we are already advertising. advertising = status == NRF_SUCCESS; } @@ -139,20 +144,22 @@ void supervisor_bluetooth_init(void) { if ((reset_state & BLE_DISCOVERY_DATA_GUARD_MASK) == BLE_DISCOVERY_DATA_GUARD) { ble_mode = (reset_state & ~BLE_DISCOVERY_DATA_GUARD_MASK) >> 8; } - const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); + // const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); boot_in_discovery_mode = false; - if (reset_reason != RESET_REASON_POWER_ON && - reset_reason != RESET_REASON_RESET_PIN && - reset_reason != RESET_REASON_UNKNOWN && - reset_reason != RESET_REASON_SOFTWARE) { - return; - } + // if (reset_reason != RESET_REASON_POWER_ON && + // reset_reason != RESET_REASON_RESET_PIN && + // reset_reason != RESET_REASON_UNKNOWN && + // reset_reason != RESET_REASON_SOFTWARE) { + // return; + // } if (ble_mode == 0) { port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8)); } // Wait for a while to allow for reset. + ble_mode = 1; + #ifdef CIRCUITPY_BOOT_BUTTON digitalio_digitalinout_obj_t boot_button; common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); From 3387edc424a7592ec97bfbc0083a44919e5ef1ca Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 25 Jun 2021 23:32:24 -0700 Subject: [PATCH 07/52] rm intersphinx_mapping to bus_device pkg --- conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/conf.py b/conf.py index 7acc981f3d..fb988499c3 100644 --- a/conf.py +++ b/conf.py @@ -414,7 +414,6 @@ texinfo_documents = [ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"cpython": ('https://docs.python.org/3/', None), - "bus_device": ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None), "register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None)} # Adapted from sphinxcontrib-redirects From dc02f97640dccc941ef43132cc14d2f62d169af1 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 25 Jun 2021 23:35:30 -0700 Subject: [PATCH 08/52] fix SPIDevice docs --- shared-bindings/adafruit_bus_device/SPIDevice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shared-bindings/adafruit_bus_device/SPIDevice.c b/shared-bindings/adafruit_bus_device/SPIDevice.c index 94901e4a15..a695a168ed 100644 --- a/shared-bindings/adafruit_bus_device/SPIDevice.c +++ b/shared-bindings/adafruit_bus_device/SPIDevice.c @@ -45,6 +45,7 @@ //| //| """ //| Represents a single SPI device and manages locking the bus and the device address. +//| //| :param ~busio.SPI spi: The SPI bus the device is on //| :param ~digitalio.DigitalInOut chip_select: The chip select pin object that implements the DigitalInOut API. //| :param int extra_clocks: The minimum number of clock cycles to cycle the bus after CS is high. (Used for SD cards.) From 02c70336ffbb858471fc2a2857f63fa8a9d89eef Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 25 Jun 2021 23:38:08 -0700 Subject: [PATCH 09/52] fix I2CDevice docs --- shared-bindings/adafruit_bus_device/I2CDevice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shared-bindings/adafruit_bus_device/I2CDevice.c b/shared-bindings/adafruit_bus_device/I2CDevice.c index ac760a490f..12c836396d 100644 --- a/shared-bindings/adafruit_bus_device/I2CDevice.c +++ b/shared-bindings/adafruit_bus_device/I2CDevice.c @@ -46,6 +46,7 @@ //| //| """Represents a single I2C device and manages locking the bus and the device //| address. +//| //| :param ~busio.I2C i2c: The I2C bus the device is on //| :param int device_address: The 7 bit device address //| :param bool probe: Probe for the device upon object creation, default is true @@ -114,6 +115,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_i2cdevice___exit_ //| If ``start`` or ``end`` is provided, then the buffer will be sliced //| as if ``buf[start:end]``. This will not cause an allocation like //| ``buf[start:end]`` will so it saves memory. +//| //| :param bytearray buf: buffer to write into //| :param int start: Index to start writing at //| :param int end: Index to write up to but not include; if None, use ``len(buf)``""" @@ -157,6 +159,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 2, //| If ``start`` or ``end`` is provided, then the buffer will be sliced //| as if ``buffer[start:end]``. This will not cause an allocation like //| ``buffer[start:end]`` will so it saves memory. +//| //| :param bytearray buf: buffer containing the bytes to write //| :param int start: Index to start writing from //| :param int end: Index to read up to but not include; if None, use ``len(buf)`` @@ -208,6 +211,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 2, adafruit_ //| will be sliced as if ``in_buffer[in_start:in_end]``. This will not //| cause an allocation like ``in_buffer[in_start:in_end]`` will so //| it saves memory. +//| //| :param bytearray out_buffer: buffer containing the bytes to write //| :param bytearray in_buffer: buffer containing the bytes to read into //| :param int out_start: Index to start writing from From 9ff9259d1ccda8179c6b3d28a949e01a2bd1ed21 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 26 Jun 2021 01:50:28 -0700 Subject: [PATCH 10/52] fix interlinking in busio docs --- shared-bindings/busio/I2C.c | 11 ++++++----- shared-bindings/busio/SPI.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index 56a6e1b8ae..d300956d0a 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -46,7 +46,7 @@ //| lines respectively. //| //| .. seealso:: Using this class directly requires careful lock management. -//| Instead, use :class:`~adafruit_bus_device.i2c_device.I2CDevice` to +//| Instead, use :class:`~adafruit_bus_device.I2CDevice` to //| manage locks. //| //| .. seealso:: Using this class to directly read registers requires manual @@ -56,7 +56,8 @@ //| :param ~microcontroller.Pin scl: The clock pin //| :param ~microcontroller.Pin sda: The data pin //| :param int frequency: The clock frequency in Hertz -//| :param int timeout: The maximum clock stretching timeut - (used only for bitbangio.I2C; ignored for busio.I2C) +//| :param int timeout: The maximum clock stretching timeut - (used only for +//| :class:`bitbangio.I2C`; ignored for :class:`busio.I2C`) //| //| .. note:: On the nRF52840, only one I2C object may be created, //| except on the Circuit Playground Bluefruit, which allows two, @@ -239,7 +240,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in //| to poll for the existence of a device. //| //| :param int address: 7-bit device address -//| :param ~_typing.ReadbleBuffer buffer: buffer containing the bytes to write +//| :param ~_typing.ReadableBuffer buffer: buffer containing the bytes to write //| :param int start: Index to start writing from //| :param int end: Index to read up to but not include. Defaults to ``len(buffer)``""" //| ... @@ -286,12 +287,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto); //| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and //| ``in_buffer`` can be the same buffer because they are used sequentially. //| -//| if ``start`` or ``end`` is provided, then the corresponding buffer will be sliced +//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced //| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]`` //| will so it saves memory. //| //| :param int address: 7-bit device address -//| :param ~_typing.ReadbleBuffer out_buffer: buffer containing the bytes to write +//| :param ~_typing.ReadableBuffer out_buffer: buffer containing the bytes to write //| :param ~_typing.WriteableBuffer in_buffer: buffer to write into //| :param int out_start: Index to start writing from //| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)`` diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 5a82ac0b41..31f3a9021e 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -65,7 +65,7 @@ //| peripherals. //| //| .. seealso:: Using this class directly requires careful lock management. -//| Instead, use :class:`~adafruit_bus_device.spi_device.SPIDevice` to +//| Instead, use :class:`~adafruit_bus_device.SPIDevice` to //| manage locks. //| //| .. seealso:: Using this class to directly read registers requires manual From f380a91e7caecc08b92b754f37d73be8c2d43ad0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 26 Jun 2021 20:00:31 -0500 Subject: [PATCH 11/52] objtuple: Move mp_obj_is_tuple_compatible to obj.h. Signed-off-by: Jeff Epler --- py/obj.h | 2 ++ py/objtuple.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/py/obj.h b/py/obj.h index 75caf459d4..da2ef08451 100644 --- a/py/obj.h +++ b/py/obj.h @@ -764,6 +764,8 @@ extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; #define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op)) #define mp_obj_is_dict_or_ordereddict(o) (mp_obj_is_obj(o) && ((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->make_new == mp_obj_dict_make_new) #define mp_obj_is_fun(o) (mp_obj_is_obj(o) && (((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) +// type check is done on getiter method to allow tuple, namedtuple, attrtuple +#define mp_obj_is_tuple_compatible(o) (mp_obj_get_type(o)->getiter == mp_obj_tuple_getiter) mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { diff --git a/py/objtuple.c b/py/objtuple.c index bb4f79997c..414cf65c3b 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -34,8 +34,6 @@ #include "supervisor/shared/translate.h" -// type check is done on getiter method to allow tuple, namedtuple, attrtuple -#define mp_obj_is_tuple_compatible(o) (mp_obj_get_type(o)->getiter == mp_obj_tuple_getiter) /******************************************************************************/ /* tuple */ From 33482e0831ca553970080fdb6ac8c85d55352956 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 26 Jun 2021 20:00:56 -0500 Subject: [PATCH 12/52] mp_obj_get_array: Work with namedtuple, attrtuple. Signed-off-by: Jeff Epler --- py/obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/obj.c b/py/obj.c index 9a81d65eca..d2483ed993 100644 --- a/py/obj.c +++ b/py/obj.c @@ -444,7 +444,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { // note: returned value in *items may point to the interior of a GC block void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) { - if (mp_obj_is_type(o, &mp_type_tuple)) { + if (mp_obj_is_tuple_compatible(o)) { mp_obj_tuple_get(o, len, items); } else if (mp_obj_is_type(o, &mp_type_list)) { mp_obj_list_get(o, len, items); From cac71a33fc62f05063417b61f6f2b0eea6e14437 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 26 Jun 2021 20:01:19 -0500 Subject: [PATCH 13/52] time: Allow constructing a struct_time from another struct_time Closes: #4917 --- shared-bindings/time/__init__.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 87a40f6fc1..5e40d2774a 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -83,12 +83,10 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp if (n_args != 1 || (kw_args != NULL && kw_args->used > 0)) { return namedtuple_make_new(type, n_args, args, kw_args); } - if (mp_obj_get_type(args[0])->getiter != mp_obj_tuple_getiter || ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(args[0]))->len != 9) { - mp_raise_TypeError(translate("time.struct_time() takes a 9-sequence")); - } - - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(args[0]); - return namedtuple_make_new(type, 9, tuple->items, NULL); + size_t len; + mp_obj_t *items; + mp_obj_get_array(args[0], &len, &items); + return namedtuple_make_new(type, len, items, NULL); } //| class struct_time: From 74be2d994e8e3a90623be80ec40062ba8a34b7af Mon Sep 17 00:00:00 2001 From: Alvaro Figueroa Date: Fri, 25 Jun 2021 22:20:48 +0000 Subject: [PATCH 14/52] Translated using Weblate (Spanish) Currently translated at 100.0% (1008 of 1008 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/es/ --- locale/es.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locale/es.po b/locale/es.po index e184742e79..13988a3e60 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-06-24 23:11+0000\n" +"PO-Revision-Date: 2021-06-27 12:33+0000\n" "Last-Translator: Alvaro Figueroa \n" "Language-Team: \n" "Language: es\n" @@ -58,7 +58,7 @@ msgstr " es de tipo %q\n" #: main.c msgid " not found.\n" -msgstr "" +msgstr " no encontrado.\n" #: main.c msgid " output:\n" @@ -897,7 +897,7 @@ msgstr "Trozo de datos debe seguir fmt chunk" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "" +msgstr "Datos sin capacidad de anuncio dirigido" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" @@ -1756,7 +1756,7 @@ msgstr "" #: shared-bindings/_bleio/Adapter.c msgid "Only connectable advertisements can be directed" -msgstr "" +msgstr "Solo se puede dirigir a los anuncios conectables" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Only edge detection is available on this hardware" @@ -2092,7 +2092,7 @@ msgstr "Error de reinicialización de SPI" #: ports/esp32s2/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "Configuración de SPI fallida" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" From 39c862f1f6639035a81b07277d5f81d7d6a7ea15 Mon Sep 17 00:00:00 2001 From: Jonny Bergdahl Date: Sat, 26 Jun 2021 12:12:34 +0000 Subject: [PATCH 15/52] Translated using Weblate (Swedish) Currently translated at 100.0% (1008 of 1008 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/sv/ --- locale/sv.po | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/locale/sv.po b/locale/sv.po index 76127123ff..a5e6241d1c 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-06-24 12:16+0000\n" +"PO-Revision-Date: 2021-06-27 12:33+0000\n" "Last-Translator: Jonny Bergdahl \n" "Language-Team: LANGUAGE \n" "Language: sv\n" @@ -56,7 +56,7 @@ msgstr " är av typen %q\n" #: main.c msgid " not found.\n" -msgstr "" +msgstr " hittades inte.\n" #: main.c msgid " output:\n" @@ -97,7 +97,7 @@ msgstr "Indexet %q måste vara ett heltal, inte %s" #: py/argcheck.c msgid "%q length must be %q" -msgstr "" +msgstr "längden på %q måste vara %q" #: shared-bindings/vectorio/Polygon.c msgid "%q list must be a list" @@ -105,11 +105,11 @@ msgstr "%q-listan måste vara en lista" #: py/argcheck.c msgid "%q must <= %d" -msgstr "" +msgstr "%q måste vara <=%d" #: py/argcheck.c msgid "%q must be %d-%d" -msgstr "" +msgstr "%q måste vara %d-%d" #: shared-bindings/usb_hid/Device.c msgid "%q must be 0-255" @@ -121,7 +121,7 @@ msgstr "%q måste vara 1-255" #: py/argcheck.c msgid "%q must be >= %d" -msgstr "" +msgstr "%q måste vara >= %d" #: py/argcheck.c shared-bindings/memorymonitor/AllocationAlarm.c msgid "%q must be >= 0" @@ -141,7 +141,7 @@ msgstr "%q måste vara None eller mellan 1 och len(report_descriptor)-1" #: py/argcheck.c msgid "%q must be a string" -msgstr "" +msgstr "%q måste vara en sträng" #: shared-module/vectorio/Polygon.c msgid "%q must be a tuple of length 2" @@ -153,12 +153,12 @@ msgstr "%q måste vara mellan %d och %d" #: py/argcheck.c msgid "%q must of type %q" -msgstr "" +msgstr "%q måste av typen %q" #: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c #: shared-bindings/keypad/ShiftRegisterKeys.c msgid "%q must store bytes" -msgstr "" +msgstr "%q måste lagra bytes" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c @@ -890,7 +890,7 @@ msgstr "Datasegmentet måste följa fmt-segmentet" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "" +msgstr "Data stöds inte med riktad annonsering" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" @@ -1738,7 +1738,7 @@ msgstr "" #: shared-bindings/_bleio/Adapter.c msgid "Only connectable advertisements can be directed" -msgstr "" +msgstr "Endast anslutningsbara annonseringar kan dirigeras" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Only edge detection is available on this hardware" @@ -2072,7 +2072,7 @@ msgstr "SPI reinitialiseringsfel" #: ports/esp32s2/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "SPI-konfigurationen misslyckades" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" From 259d5b9e7dbefff2d57ce77ce54ee8ba99096f17 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 28 Jun 2021 09:26:29 -0400 Subject: [PATCH 16/52] Fix displayio.Display __init__() signature documentation --- shared-bindings/displayio/Display.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c index 2825d5466a..e12e398802 100644 --- a/shared-bindings/displayio/Display.c +++ b/shared-bindings/displayio/Display.c @@ -54,7 +54,7 @@ //| Most people should not use this class directly. Use a specific display driver instead that will //| contain the initialization sequence at minimum.""" //| -//| def __init__(self, display_bus: _DisplayBus, init_sequence: ReadableBuffer, *, width: int, height: int, colstart: int = 0, rowstart: int = 0, rotation: int = 0, color_depth: int = 16, grayscale: bool = False, pixels_in_byte_share_row: bool = True, bytes_per_cell: int = 1, reverse_pixels_in_byte: bool = False, set_column_command: int = 0x2a, set_row_command: int = 0x2b, write_ram_command: int = 0x2c, set_vertical_scroll: int = 0, backlight_pin: Optional[microcontroller.Pin] = None, brightness_command: Optional[int] = None, brightness: float = 1.0, auto_brightness: bool = False, single_byte_bounds: bool = False, data_as_commands: bool = False, auto_refresh: bool = True, native_frames_per_second: int = 60) -> None: +//| def __init__(self, display_bus: _DisplayBus, init_sequence: ReadableBuffer, *, width: int, height: int, colstart: int = 0, rowstart: int = 0, rotation: int = 0, color_depth: int = 16, grayscale: bool = False, pixels_in_byte_share_row: bool = True, bytes_per_cell: int = 1, reverse_pixels_in_byte: bool = False, set_column_command: int = 0x2a, set_row_command: int = 0x2b, write_ram_command: int = 0x2c, set_vertical_scroll: int = 0, backlight_pin: Optional[microcontroller.Pin] = None, brightness_command: Optional[int] = None, brightness: float = 1.0, auto_brightness: bool = False, single_byte_bounds: bool = False, data_as_commands: bool = False, auto_refresh: bool = True, native_frames_per_second: int = 60, backlight_on_high: bool = True, SH1107_addressing: bool = False) -> None: //| r"""Create a Display object on the given display bus (`FourWire`, `ParallelBus` or `I2CDisplay`). //| //| The ``init_sequence`` is bitpacked to minimize the ram impact. Every command begins with a @@ -107,10 +107,11 @@ //| :param bool auto_brightness: If True, brightness is controlled via an ambient light sensor or other mechanism. //| :param bool single_byte_bounds: Display column and row commands use single bytes //| :param bool data_as_commands: Treat all init and boundary data as SPI commands. Certain displays require this. -//| :param bool SH1107_addressing: Special quirk for SH1107, use upper/lower column set and page set //| :param bool auto_refresh: Automatically refresh the screen //| :param int native_frames_per_second: Number of display refreshes per second that occur with the given init_sequence. -//| :param bool backlight_on_high: If True, pulling the backlight pin high turns the backlight on.""" +//| :param bool backlight_on_high: If True, pulling the backlight pin high turns the backlight on. +//| :param bool SH1107_addressing: Special quirk for SH1107, use upper/lower column set and page set +//| """ //| ... //| STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_args, From 2c2d541e7c35e17a57f2182d6c18d80a1430c2d4 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Mon, 28 Jun 2021 17:10:15 -0400 Subject: [PATCH 17/52] Adding pins to match silk and other RP2040 boards. --- ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c b/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c index 2e5890c1c4..bc57161ec5 100644 --- a/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c +++ b/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c @@ -15,13 +15,17 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_KEY12), MP_ROM_PTR(&pin_GPIO12) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER_SHUTDOWN), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_ENCODER_SWITCH), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_ENCODER_A), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_ROTA), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_ENCODER_B), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_ROTB), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO19) }, From 3dcd603e39a63248b84a823207c3200b7b23e623 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 28 Jun 2021 19:27:14 -0500 Subject: [PATCH 18/52] time: Fix and better document time.struct_time constructor INCOMPATIBLE CHANGE: struct_time(1,2,3,4,5,6,7,8,9) is now _rejected_ just as on standad Python. This incorrect constructor was added by me in #2327; I assumed without even checking that the `struct_time` constructor was also compatible with the `namedtuple` constructor, but it is not and has always been rejected by standard Python (checked 2.7 and 3.9) This commit restores the specific error message that we used for this purpose, which was removed in the previous commit either out of laziness or out of trying to reduce unneeded error strings. In this case, the alternate string is too misleading (it refers to arguments, not to sequence elements) so let's put the better message back. --- shared-bindings/time/__init__.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 5e40d2774a..a2eeee6cef 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -80,20 +80,21 @@ MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); #if MICROPY_PY_COLLECTIONS mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - if (n_args != 1 || (kw_args != NULL && kw_args->used > 0)) { - return namedtuple_make_new(type, n_args, args, kw_args); - } + mp_arg_check_num(n_args, kw_args, 1, 1, false); size_t len; mp_obj_t *items; mp_obj_get_array(args[0], &len, &items); + if (len != 9) { + mp_raise_TypeError(translate("time.struct_time() takes a 9-sequence")); + } return namedtuple_make_new(type, len, items, NULL); } //| class struct_time: -//| def __init__(self, time_tuple: Tuple[int, int, int, int, int, int, int, int, int]) -> None: -//| """Structure used to capture a date and time. Note that it takes a tuple! +//| def __init__(self, time_tuple: Sequence) -> None: +//| """Structure used to capture a date and time. Can be constructed from a `struct_time`, `tuple`, `list`, or `namedtuple` with 9 elements. //| -//| :param tuple time_tuple: Tuple of time info: ``(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)`` +//| :param Sequence time_tuple: Sequence of time info: ``(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)`` //| //| * ``tm_year``: the year, 2017 for example //| * ``tm_mon``: the month, range [1, 12] From e5d2b25b109f8b6dc4a88cca1dc645c7027505ab Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 28 Jun 2021 19:33:40 -0500 Subject: [PATCH 19/52] remove 'double-wide' characters not in the font I noticed the build printed things like ``` Font missing 3 characters ``` .. this is why. We can't make it an error, because Japanese has hundreds of characters not in the font. --- locale/zh_Latn_pinyin.po | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index bb6fba4dd2..3d754c82c8 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -535,7 +535,7 @@ msgstr "Bǐtè shízhōng hé dānzì xuǎnzé bìxū gòngxiǎng shízhōng dā #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "Bit depth must be from 1 to 6 inclusive, not %d" -msgstr "wèi shēn dù bì xū bāo hán 1 dào 6, ér bù shì %d" +msgstr "wèi shēn dù bì xū bāo hán 1 dào 6, ér bù shì %d" #: shared-bindings/audiobusio/PDMIn.c msgid "Bit depth must be multiple of 8." @@ -610,7 +610,7 @@ msgstr "Huǎnchōng qū bìxū zhìshǎo chángdù 1" #: shared-bindings/_bleio/PacketBuffer.c #, c-format msgid "Buffer too short by %d bytes" -msgstr "Huǎn chōng qū tài duǎn , àn %d zì jié" +msgstr "Huǎn chōng qū tài duǎn , àn %d zì jié" #: ports/atmel-samd/common-hal/displayio/ParallelBus.c #: ports/esp32s2/common-hal/displayio/ParallelBus.c @@ -2169,7 +2169,7 @@ msgid "" "Increase the stack size if you know how. If not:" msgstr "" "diàn lù dàn duī bèi sǔn huài, yīn wéi duī zhàn tài xiǎo.\n" -"rú guǒ nín zhī dào rú hé zēng jiā duī zhàn dà xiǎo. rú guǒ méi yǒu:" +"rú guǒ nín zhī dào rú hé zēng jiā duī zhàn dà xiǎo. rú guǒ méi yǒu:" #: supervisor/shared/safe_mode.c msgid "" @@ -2351,7 +2351,7 @@ msgstr "Wúfǎ xiě rù nvm." #: shared-bindings/alarm/SleepMemory.c msgid "Unable to write to sleep_memory." -msgstr "wú fǎ xiě rù sleep_memory。" +msgstr "wú fǎ xiě rù sleep_memory. #: ports/nrf/common-hal/_bleio/UUID.c msgid "Unexpected nrfx uuid type" @@ -3411,7 +3411,7 @@ msgstr "wúxiào de cānshù" #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid bits_per_pixel %d, must be, 1, 4, 8, 16, 24, or 32" -msgstr "wú xiào bits_per_pixel %d, bì xū shì, 1, 4, 8, 16, 24, huò 32" +msgstr "wú xiào bits_per_pixel %d, bì xū shì, 1, 4, 8, 16, 24, huò 32" #: shared-bindings/bitmaptools/__init__.c #, c-format @@ -3870,7 +3870,7 @@ msgstr "chāo gāo zhuǎnhuàn zhǎng zhěng shùzì shí" #: py/modstruct.c #, c-format msgid "pack expected %d items for packing (got %d)" -msgstr "bāo zhuāng yù qī de %d bāo zhuāng xiàng mù (dé dào %d)" +msgstr "bāo zhuāng yù qī de %d bāo zhuāng xiàng mù (dé dào %d)" #: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c msgid "palette must be 32 bytes long" @@ -4475,7 +4475,7 @@ msgid "zi must be of shape (n_section, 2)" msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" #~ msgid "Buffer too large and unable to allocate" -#~ msgstr "Huǎn chōng qū tài dà , wú fǎ fēn pèi" +#~ msgstr "Huǎn chōng qū tài dà , wú fǎ fēn pèi" #~ msgid "interp is defined for 1D arrays of equal length" #~ msgstr "interp shì wèi děng zhǎng de 1D shùzǔ dìngyì de" From fd681ca70a6c0e5d855f9476e095da62db07a19c Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Tue, 29 Jun 2021 08:11:16 +0530 Subject: [PATCH 20/52] minor fix for struct_time docs --- shared-bindings/time/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index a2eeee6cef..03f4fac0dc 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -91,7 +91,7 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp } //| class struct_time: -//| def __init__(self, time_tuple: Sequence) -> None: +//| def __init__(self, time_tuple: Sequence[int]) -> None: //| """Structure used to capture a date and time. Can be constructed from a `struct_time`, `tuple`, `list`, or `namedtuple` with 9 elements. //| //| :param Sequence time_tuple: Sequence of time info: ``(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)`` From 1a076d34c9d197c1e1420117f856a5d9aa2e8581 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 29 Jun 2021 00:47:54 +0200 Subject: [PATCH 21/52] PewPew M4: use keypad instead of gamepad Since the new keypad module is taking over gamepad functionality, I'm switching to it. If this works well, I will make the change for the remaining boards. --- frozen/circuitpython-stage | 2 +- ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/frozen/circuitpython-stage b/frozen/circuitpython-stage index 40d8a03b45..b014aa045d 160000 --- a/frozen/circuitpython-stage +++ b/frozen/circuitpython-stage @@ -1 +1 @@ -Subproject commit 40d8a03b4569d566faa62fcb0f798178118f2954 +Subproject commit b014aa045d9014b86a4ae583f452c6b8282a61b9 diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk index d500b81112..7990f91ccc 100644 --- a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk @@ -30,14 +30,17 @@ CIRCUIPTY_USB_CDC = 0 CIRCUITPY_USB_HID = 0 CIRCUITPY_USB_MIDI = 0 CIRCUITPY_VECTORIO = 0 +CIRCUITPY_GAMEPAD = 0 +CIRCUITPY_PWMIO = 0 CIRCUITPY_ANALOGIO = 1 CIRCUITPY_AUDIOMIXER = 1 CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_SYNTHIO = 1 CIRCUITPY_DISPLAYIO = 1 -CIRCUITPY_GAMEPAD = 1 CIRCUITPY_MATH = 1 CIRCUITPY_STAGE = 1 +CIRCUITPY_KEYPAD = 1 FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pewpew_m4 CIRCUITPY_DISPLAY_FONT = $(TOP)/ports/atmel-samd/boards/ugame10/brutalist-6.bdf From ae8ea915d7e643ce6d9332c2c569d64f2fc05d74 Mon Sep 17 00:00:00 2001 From: dmcomm <71192617+dmcomm@users.noreply.github.com> Date: Tue, 29 Jun 2021 13:38:12 +0100 Subject: [PATCH 22/52] Fix pulseio.PulseIn __len__() documentation --- shared-bindings/pulseio/PulseIn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c index ebc8d450e3..4672c1e060 100644 --- a/shared-bindings/pulseio/PulseIn.c +++ b/shared-bindings/pulseio/PulseIn.c @@ -237,7 +237,7 @@ const mp_obj_property_t pulseio_pulsein_paused_obj = { //| def __bool__(self) -> bool: ... //| //| def __len__(self) -> int: -//| """Returns the current pulse length +//| """Returns the number of pulse durations currently stored. //| //| This allows you to:: //| From e0c626af162e6854c3ede9f5cc80260d5a8d8840 Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Tue, 29 Jun 2021 19:59:44 +0530 Subject: [PATCH 23/52] fix bytes() and bytearray() input validation --- py/objarray.c | 3 +++ py/objstr.c | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/py/objarray.c b/py/objarray.c index 2d363392dd..220969ee20 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -195,6 +195,9 @@ STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, // no args: construct an empty bytearray return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0)); } else if (mp_obj_is_int(args[0])) { + if (n_args > 1) { + mp_raise_TypeError(MP_ERROR_TEXT("wrong number of arguments")); + } // 1 arg, an integer: construct a blank bytearray of that length mp_uint_t len = mp_obj_get_int(args[0]); mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len); diff --git a/py/objstr.c b/py/objstr.c index f95624960d..f29a954fb2 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -233,6 +233,10 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, cons return MP_OBJ_FROM_PTR(o); } + if (n_args > 1) { + goto wrong_args; + } + if (mp_obj_is_small_int(args[0])) { mp_int_t len = MP_OBJ_SMALL_INT_VALUE(args[0]); if (len < 0) { @@ -244,10 +248,6 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, cons return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } - if (n_args > 1) { - goto wrong_args; - } - // check if __bytes__ exists, and if so delegate to it mp_obj_t dest[2]; mp_load_method_maybe(args[0], MP_QSTR___bytes__, dest); From b8c4f7d6853ec2d9f5756d4ec95faa441bbdf23a Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 29 Jun 2021 17:30:51 +0200 Subject: [PATCH 24/52] MacroPad RP2040: Add initialization for the OLED display --- .../boards/adafruit_macropad_rp2040/board.c | 77 ++++++++++++++++++- .../boards/adafruit_macropad_rp2040/pins.c | 3 + 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c b/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c index 3fb4b21cbf..214662e331 100644 --- a/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c @@ -24,13 +24,86 @@ * THE SOFTWARE. */ -#include "supervisor/board.h" - +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/displayio/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/busio/SPI.h" #include "shared-bindings/microcontroller/Pin.h" #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" #include "supervisor/shared/board.h" +displayio_fourwire_obj_t board_display_obj; + +#define DELAY 0x80 + +uint8_t display_init_sequence[] = { + 0xae, 0, // sleep + 0xd5, 1, 0x80, // fOsc divide by 2 + 0xa8, 1, 0x3f, // multiplex 64 + 0xd3, 1, 0x00, // offset 0 + 0x40, 1, 0x00, // start line 0 + 0xad, 1, 0x8b, // dc/dc on + 0xa1, 0, // segment remap = 0 + 0xc8, 0, // scan incr + 0xda, 1, 0x12, // com pins + 0x81, 1, 0xff, // contrast 255 + 0xd9, 1, 0x1f, // pre/dis-charge 2DCLKs/2CLKs + 0xdb, 1, 0x20, // VCOM deslect 0.770 + 0x20, 1, 0x20, + 0x33, 0, // VPP 9V + 0xa6, 0, // not inverted + 0xa4, 0, // normal + 0xaf, 0, // on +}; + void board_init(void) { + busio_spi_obj_t *spi = &displays[0].fourwire_bus.inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO26, &pin_GPIO27, NULL); + common_hal_busio_spi_never_reset(spi); + + displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; + bus->base.type = &displayio_fourwire_type; + common_hal_displayio_fourwire_construct(bus, + spi, + &pin_GPIO24, // Command or data + &pin_GPIO22, // Chip select + &pin_GPIO23, // Reset + 1000000, // Baudrate + 0, // Polarity + 0); // Phase + + displayio_display_obj_t *display = &displays[0].display; + display->base.type = &displayio_display_type; + common_hal_displayio_display_construct(display, + bus, + 128, // Width + 64, // Height + 2, // column start + 0, // row start + 0, // rotation + 1, // Color depth + true, // grayscale + false, // pixels in byte share row. Only used with depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + 0, // Set column command + 0, // Set row command + 0, // Write memory command + 0xd3, // set vertical scroll command + display_init_sequence, + sizeof(display_init_sequence), + NULL, + 0x81, + 1.0f, // brightness + false, // auto_brightness + true, // single_byte_bounds + true, // data as commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + true); // SH1107_addressing } bool board_requests_safe_mode(void) { diff --git a/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c b/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c index bc57161ec5..17ff8d9a41 100644 --- a/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c +++ b/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c @@ -1,4 +1,5 @@ #include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_KEY1), MP_ROM_PTR(&pin_GPIO1) }, @@ -43,5 +44,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_i2c_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); From f2ef5863315a6e3916a1d6e730ac6bd13af82708 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 29 Jun 2021 11:54:15 -0700 Subject: [PATCH 25/52] clean up --- ports/nrf/bluetooth/ble_drv.c | 2 -- ports/nrf/common-hal/_bleio/Connection.c | 1 - ports/nrf/common-hal/_bleio/Service.c | 1 - supervisor/shared/bluetooth/bluetooth.c | 26 ++++++++++-------------- supervisor/shared/bluetooth/serial.h | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index 29b2844736..9596e45fbb 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -38,8 +38,6 @@ #include "py/misc.h" #include "py/mpstate.h" -// #include "supervisor/shared/bluetooth.h" - nrf_nvic_state_t nrf_nvic_state = { 0 }; // Flag indicating progress of internal flash operation. diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c index 0e7c6a3c54..b94ad09e6a 100644 --- a/ports/nrf/common-hal/_bleio/Connection.c +++ b/ports/nrf/common-hal/_bleio/Connection.c @@ -311,7 +311,6 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { // Did an sd_ble_gatts_sys_attr_set() with the stored sys_attr values. // Indicate ATTR table change because we may have reloaded since the peer last // connected. - mp_printf(&mp_plat_print, "restore sys attrs\n"); sd_ble_gatts_service_changed(self->conn_handle, 0xC, 0xFFFF); } else { // No matching bonding found, so use fresh system attributes. diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c index 0c4ded2d1b..4980b70fe1 100644 --- a/ports/nrf/common-hal/_bleio/Service.c +++ b/ports/nrf/common-hal/_bleio/Service.c @@ -153,7 +153,6 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, char_md.p_char_user_desc = (const uint8_t *)user_description; char_md.char_user_desc_max_size = strlen(user_description); char_md.char_user_desc_size = strlen(user_description); - mp_printf(&mp_plat_print, "user description %s\n", user_description); } bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm); diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index 1a57075c6e..df57bf691d 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -87,9 +87,9 @@ bool boot_in_discovery_mode = false; bool advertising = false; STATIC void supervisor_bluetooth_start_advertising(void) { - // #if !CIRCUITPY_BLE_FILE_SERVICE && !CIRCUITPY_SERIAL_BLE - // return; - // #else + #if !CIRCUITPY_BLE_FILE_SERVICE && !CIRCUITPY_SERIAL_BLE + return; + #else bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); if (is_connected) { return; @@ -98,7 +98,6 @@ STATIC void supervisor_bluetooth_start_advertising(void) { #if CIRCUITPY_USB // Don't advertise when we have USB instead of BLE. if (!bonded && !boot_in_discovery_mode) { - mp_printf(&mp_plat_print, "skipping advertising\n"); return; } #endif @@ -112,7 +111,6 @@ STATIC void supervisor_bluetooth_start_advertising(void) { // Advertise with less power when doing so publicly to reduce who can hear us. This will make it // harder for someone with bad intentions to pair from a distance. if (!bonded) { - mp_printf(&mp_plat_print, "public advertising\n"); tx_power = -40; adv = public_advertising_data; adv_len = sizeof(public_advertising_data); @@ -130,9 +128,9 @@ STATIC void supervisor_bluetooth_start_advertising(void) { scan_response_len, tx_power, NULL); - mp_printf(&mp_plat_print, "advert %d\n", status); // This may fail if we are already advertising. advertising = status == NRF_SUCCESS; + #endif } #define BLE_DISCOVERY_DATA_GUARD 0xbb0000bb @@ -144,22 +142,20 @@ void supervisor_bluetooth_init(void) { if ((reset_state & BLE_DISCOVERY_DATA_GUARD_MASK) == BLE_DISCOVERY_DATA_GUARD) { ble_mode = (reset_state & ~BLE_DISCOVERY_DATA_GUARD_MASK) >> 8; } - // const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); + const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); boot_in_discovery_mode = false; - // if (reset_reason != RESET_REASON_POWER_ON && - // reset_reason != RESET_REASON_RESET_PIN && - // reset_reason != RESET_REASON_UNKNOWN && - // reset_reason != RESET_REASON_SOFTWARE) { - // return; - // } + if (reset_reason != RESET_REASON_POWER_ON && + reset_reason != RESET_REASON_RESET_PIN && + reset_reason != RESET_REASON_UNKNOWN && + reset_reason != RESET_REASON_SOFTWARE) { + return; + } if (ble_mode == 0) { port_set_saved_word(BLE_DISCOVERY_DATA_GUARD | (0x01 << 8)); } // Wait for a while to allow for reset. - ble_mode = 1; - #ifdef CIRCUITPY_BOOT_BUTTON digitalio_digitalinout_obj_t boot_button; common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); diff --git a/supervisor/shared/bluetooth/serial.h b/supervisor/shared/bluetooth/serial.h index ac96a67f40..b5bbcccf10 100644 --- a/supervisor/shared/bluetooth/serial.h +++ b/supervisor/shared/bluetooth/serial.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 89678f79a7301f89d20d8cdb9be6204011da1156 Mon Sep 17 00:00:00 2001 From: ajs256 <67526318+ajs256@users.noreply.github.com> Date: Tue, 29 Jun 2021 21:32:32 -0700 Subject: [PATCH 26/52] Convert to using issue forms --- .github/ISSUE_TEMPLATE/bug_report.md | 54 --------------------------- .github/ISSUE_TEMPLATE/bug_report.yml | 54 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 54 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 65f61ebb5f..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: 'bug' -assignees: '' - ---- - - - -**Firmware** - - - -```python -Adafruit CircuitPython 6.2.0-beta.2 on 2021-03-01; Raspberry Pi Pico with rp2040 -``` - -**Code/REPL** - - - -```python -import busio, bitbangio -i2c = bitbangio.I2C(board.GP1, board.GP0) -``` - -**Behavior** - - - -```python -Traceback (most recent call last): - File "", line 1, in -TimeoutError: Clock stretch too long -``` - -**Description** - - - -- Error while using i2c... -- Only happens when... -- might be related to #4291... - -**Additional Info** - - diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..8e3ccf6440 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,54 @@ +name: Bug report +description: Report a bug in CircuitPython +labels: + - bug +body: + - type: markdown + attributes: + value: >- + ## Bug Report + Thanks! for testing out CircuitPython. Now that you have got a + problem... you can file a bug report for it. + - type: input + id: firmware + attributes: + label: CircuitPython version + description: >- + Include the version of CircuitPython you're running. You can see it in + the `boot_out.txt` file, as well as in the REPL. + placeholder: >- + Adafruit CircuitPython 6.2.0-beta.2 on 2021-03-01; Raspberry Pi Pico + with rp2040 + - type: textarea + id: code + attributes: + label: Code/REPL + placeholder: >- + import busio, bitbangio + i2c = bitbangio.I2C(board.GP1, board.GP0) + render: python + - type: textarea + id: behavior + attributes: + label: Behavior + description: What happens when you run the code above? Include any error messages. + placeholder: >- + Traceback (most recent call last): + File "", line 1, in + TimeoutError: Clock stretch too long + - type: textarea + id: description + attributes: + label: Description + description: Optionally, describe the bug in more detail. + placeholder: >- + - Error while using i2c... + - Only happens when... + - might be related to #4291... + - type: textarea + id: more-info + attributes: + label: Additional information + description: >- + Optionally, add any other information like hardware connection, scope + output etc. If you have already done some debugging, mention it here. \ No newline at end of file From d99d818bf85090b048baa8efee47383fcaf2bc41 Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Wed, 30 Jun 2021 15:42:22 +0530 Subject: [PATCH 27/52] update issue form and template --- .github/ISSUE_TEMPLATE/bug_report.yml | 47 ++++++++++++++--------- .github/ISSUE_TEMPLATE/config.yml | 4 +- .github/ISSUE_TEMPLATE/feature_request.md | 4 +- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 8e3ccf6440..7b6a53dbba 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,49 +1,57 @@ -name: Bug report -description: Report a bug in CircuitPython +name: 🐞 Bug Report +description: Create a bug report to help us improve labels: - bug body: - type: markdown attributes: value: >- - ## Bug Report - Thanks! for testing out CircuitPython. Now that you have got a - problem... you can file a bug report for it. - - type: input + Thanks! for testing out CircuitPython. Now that you have encountered a + bug... you can file a report for it. + - type: textarea id: firmware attributes: label: CircuitPython version description: >- Include the version of CircuitPython you're running. You can see it in - the `boot_out.txt` file, as well as in the REPL. - placeholder: >- - Adafruit CircuitPython 6.2.0-beta.2 on 2021-03-01; Raspberry Pi Pico - with rp2040 + the `boot_out.txt` file, as well as in the `REPL`. + placeholder: Adafruit CircuitPython 6.2.0 on 2021-03-01; Raspberry Pi Pico with rp2040 + render: python + validations: + required: true - type: textarea id: code attributes: label: Code/REPL - placeholder: >- - import busio, bitbangio + description: This is automatically rendered as Python, so no need for backticks. + placeholder: | + import busio, bitbangio i2c = bitbangio.I2C(board.GP1, board.GP0) render: python + validations: + required: true - type: textarea id: behavior attributes: label: Behavior - description: What happens when you run the code above? Include any error messages. - placeholder: >- - Traceback (most recent call last): + description: What happens when you run the code above? Include error messages (if any). + placeholder: | + ```python + Traceback (most recent call last): File "", line 1, in TimeoutError: Clock stretch too long + ``` + On-board led pulses red. + validations: + required: true - type: textarea id: description attributes: label: Description description: Optionally, describe the bug in more detail. - placeholder: >- - - Error while using i2c... - - Only happens when... + placeholder: | + - Error while using i2c... + - Only happens when... - might be related to #4291... - type: textarea id: more-info @@ -51,4 +59,5 @@ body: label: Additional information description: >- Optionally, add any other information like hardware connection, scope - output etc. If you have already done some debugging, mention it here. \ No newline at end of file + output etc. If you have already done some debugging, mention it here. + placeholder: Removing [this](url) line resolves the issue. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 73bf24af0c..2990e0d4b0 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ contact_links: - - name: Adafruit Forum + - name: 🔗 Adafruit Forum url: https://forums.adafruit.com/ about: Official Adafruit technical support forum. Good for getting help on getting a project working. - - name: Adafruit Discord + - name: 🔗 Adafruit Discord url: https://adafru.it/discord about: Unofficial chat with many helpful folks and normally prompt replies. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 4f65b84145..87349ee00c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,5 +1,5 @@ --- -name: Feature request +name: 🚀 Feature Request about: Suggest an idea for this project title: '' labels: 'enhancement' @@ -7,5 +7,5 @@ assignees: '' --- - From d83a21b9845d7fff14546c9d3950d2883e6a7fed Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 30 Jun 2021 10:27:46 -0500 Subject: [PATCH 28/52] ColorConverter: Add "BGR" color modes. The BGR565_SWAPPED mode is needed for OV2640 cameras. --- locale/circuitpython.pot | 5 ----- shared-bindings/displayio/__init__.c | 8 ++++++++ shared-bindings/displayio/__init__.h | 4 ++++ shared-module/displayio/ColorConverter.c | 22 ++++++++++++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 0fc96f8b6e..e421eef8ea 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -147,11 +147,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c index b39e72b946..dc4971de2a 100644 --- a/shared-bindings/displayio/__init__.c +++ b/shared-bindings/displayio/__init__.c @@ -70,6 +70,10 @@ MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565, DISPLAY MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB565_SWAPPED); MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555, DISPLAYIO_COLORSPACE_RGB555); MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565, DISPLAYIO_COLORSPACE_BGR565); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR565_SWAPPED, DISPLAYIO_COLORSPACE_BGR565_SWAPPED); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555, DISPLAYIO_COLORSPACE_BGR555); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, BGR555_SWAPPED, DISPLAYIO_COLORSPACE_BGR555_SWAPPED); //| class Colorspace: //| """The colorspace for a `ColorConverter` to operate in""" @@ -95,6 +99,10 @@ MAKE_ENUM_MAP(displayio_colorspace) { MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565_SWAPPED), MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555), MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555_SWAPPED), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR565_SWAPPED), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, BGR555_SWAPPED), }; STATIC MP_DEFINE_CONST_DICT(displayio_colorspace_locals_dict, displayio_colorspace_locals_table); diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h index 31af2ff2ba..938fcf3d98 100644 --- a/shared-bindings/displayio/__init__.h +++ b/shared-bindings/displayio/__init__.h @@ -46,6 +46,10 @@ typedef enum { DISPLAYIO_COLORSPACE_RGB555, DISPLAYIO_COLORSPACE_RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED, + DISPLAYIO_COLORSPACE_BGR565, + DISPLAYIO_COLORSPACE_BGR555, + DISPLAYIO_COLORSPACE_BGR565_SWAPPED, + DISPLAYIO_COLORSPACE_BGR555_SWAPPED, } displayio_colorspace_t; typedef bool (*display_bus_bus_reset)(mp_obj_t bus); diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index 6de7fe7883..4871ce81a0 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -176,6 +176,28 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d } break; + case DISPLAYIO_COLORSPACE_BGR565_SWAPPED: + pixel = __builtin_bswap16(pixel); + MP_FALLTHROUGH; + case DISPLAYIO_COLORSPACE_BGR565: { + uint32_t b8 = (pixel >> 11) << 3; + uint32_t g8 = ((pixel >> 5) << 2) & 0xff; + uint32_t r8 = (pixel << 3) & 0xff; + pixel = (r8 << 16) | (g8 << 8) | b8; + } + break; + + case DISPLAYIO_COLORSPACE_BGR555_SWAPPED: + pixel = __builtin_bswap16(pixel); + MP_FALLTHROUGH; + case DISPLAYIO_COLORSPACE_BGR555: { + uint32_t b8 = (pixel >> 10) << 3; + uint32_t g8 = ((pixel >> 5) << 3) & 0xff; + uint32_t r8 = (pixel << 3) & 0xff; + pixel = (r8 << 16) | (g8 << 8) | b8; + } + break; + case DISPLAYIO_COLORSPACE_RGB888: break; } From be206b7ba007f1e137ec63efb6b0408682e1f744 Mon Sep 17 00:00:00 2001 From: Wellington Terumi Uemura Date: Wed, 30 Jun 2021 06:57:23 +0000 Subject: [PATCH 29/52] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1008 of 1008 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/pt_BR/ --- locale/pt_BR.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 82a4cb62b6..fd3800d24c 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-06-25 18:00+0000\n" +"PO-Revision-Date: 2021-06-30 17:19+0000\n" "Last-Translator: Wellington Terumi Uemura \n" "Language-Team: \n" "Language: pt_BR\n" @@ -56,7 +56,7 @@ msgstr " é do tipo %q\n" #: main.c msgid " not found.\n" -msgstr "" +msgstr " não encontrado.\n" #: main.c msgid " output:\n" @@ -2093,7 +2093,7 @@ msgstr "Houve um erro na reinicialização SPI" #: ports/esp32s2/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "A configuração SPI falhou" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" From 0bd181c4d0707c771016354f4161ac61f45eae23 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 30 Jun 2021 19:19:33 +0200 Subject: [PATCH 30/52] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/ --- locale/ID.po | 5 ----- locale/cs.po | 5 ----- locale/de_DE.po | 5 ----- locale/el.po | 5 ----- locale/en_GB.po | 5 ----- locale/es.po | 8 +++----- locale/fil.po | 5 ----- locale/fr.po | 5 ----- locale/hi.po | 5 ----- locale/it_IT.po | 5 ----- locale/ja.po | 5 ----- locale/ko.po | 5 ----- locale/nl.po | 5 ----- locale/pl.po | 5 ----- locale/pt_BR.po | 8 +++----- locale/sv.po | 8 +++----- locale/zh_Latn_pinyin.po | 8 +++----- 17 files changed, 12 insertions(+), 85 deletions(-) diff --git a/locale/ID.po b/locale/ID.po index bb8428a3f2..b04a643c49 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -154,11 +154,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/cs.po b/locale/cs.po index ed87ef5768..0ea37f724f 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -150,11 +150,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/de_DE.po b/locale/de_DE.po index 498f3bcd49..e9c7aeaaea 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -155,11 +155,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/el.po b/locale/el.po index 68052d303d..f80452ea4a 100644 --- a/locale/el.po +++ b/locale/el.po @@ -147,11 +147,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/en_GB.po b/locale/en_GB.po index b8e0e96034..8df32c33a6 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -156,11 +156,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/es.po b/locale/es.po index 13988a3e60..00e787413d 100644 --- a/locale/es.po +++ b/locale/es.po @@ -158,11 +158,6 @@ msgstr "%q debe estar entre %d y %d" msgid "%q must of type %q" msgstr "%q debe ser de tipo %q" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "%q debe almacenar bytes" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" @@ -4516,6 +4511,9 @@ msgstr "zi debe ser de tipo flotante" msgid "zi must be of shape (n_section, 2)" msgstr "zi debe ser una forma (n_section,2)" +#~ msgid "%q must store bytes" +#~ msgstr "%q debe almacenar bytes" + #~ msgid "Buffer too large and unable to allocate" #~ msgstr "Buffer demasiado grande e incapaz de asignar" diff --git a/locale/fil.po b/locale/fil.po index da7b003bbc..094f344f92 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -147,11 +147,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/fr.po b/locale/fr.po index c224337e01..90e9c26484 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -158,11 +158,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/hi.po b/locale/hi.po index a6327c63d9..67f1c611fc 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -147,11 +147,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/it_IT.po b/locale/it_IT.po index 28c4012afd..bca6205810 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -157,11 +157,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/ja.po b/locale/ja.po index e3f25b8f9c..9ec4898cde 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -152,11 +152,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/ko.po b/locale/ko.po index 06ced23109..1e5abe7858 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -148,11 +148,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/nl.po b/locale/nl.po index 2561eeb710..cc305dbd4c 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -150,11 +150,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/pl.po b/locale/pl.po index 6d736c6ce6..c9335fd036 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -152,11 +152,6 @@ msgstr "" msgid "%q must of type %q" msgstr "" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index fd3800d24c..940e3e5e44 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -156,11 +156,6 @@ msgstr "%q deve estar entre %d e %d" msgid "%q must of type %q" msgstr "o %q deve ser do tipo %q" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "o %q deve armazenar bytes" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" @@ -4526,6 +4521,9 @@ msgstr "zi deve ser de um tipo float" msgid "zi must be of shape (n_section, 2)" msgstr "zi deve estar na forma (n_section, 2)" +#~ msgid "%q must store bytes" +#~ msgstr "o %q deve armazenar bytes" + #~ msgid "Buffer too large and unable to allocate" #~ msgstr "O buffer é muito grande e incapaz de alocar" diff --git a/locale/sv.po b/locale/sv.po index a5e6241d1c..d1018e2f6b 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -155,11 +155,6 @@ msgstr "%q måste vara mellan %d och %d" msgid "%q must of type %q" msgstr "%q måste av typen %q" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "%q måste lagra bytes" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" @@ -4485,6 +4480,9 @@ msgstr "zi måste vara av typ float" msgid "zi must be of shape (n_section, 2)" msgstr "zi måste vara i formen (n_section, 2)" +#~ msgid "%q must store bytes" +#~ msgstr "%q måste lagra bytes" + #~ msgid "Buffer too large and unable to allocate" #~ msgstr "Bufferten är för stor och kan inte allokeras" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 9cbd84ebfd..3018748aac 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -157,11 +157,6 @@ msgstr "%q bì xū zài %d hé %d zhī jiān" msgid "%q must of type %q" msgstr "%q bì xū lèi xíng %q" -#: shared-bindings/keypad/KeyMatrix.c shared-bindings/keypad/Keys.c -#: shared-bindings/keypad/ShiftRegisterKeys.c -msgid "%q must store bytes" -msgstr "%q bì xū cún chǔ zì jié" - #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: shared-bindings/canio/Match.c msgid "%q out of range" @@ -4482,6 +4477,9 @@ msgstr "zi bìxū wèi fú diǎn xíng" msgid "zi must be of shape (n_section, 2)" msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" +#~ msgid "%q must store bytes" +#~ msgstr "%q bì xū cún chǔ zì jié" + #~ msgid "Buffer too large and unable to allocate" #~ msgstr "Huǎn chōng qū tài dà , wú fǎ fēn pèi" From 4d953dcbddd23ac9528a781bafe51ac55432e82e Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 30 Jun 2021 22:54:03 -0400 Subject: [PATCH 31/52] Fix missing quote in locale/zh_Latn_pinyin.po Co-authored-by: microDev <70126934+microDev1@users.noreply.github.com> --- locale/zh_Latn_pinyin.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 3d754c82c8..81b815f2c1 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -2351,7 +2351,7 @@ msgstr "Wúfǎ xiě rù nvm." #: shared-bindings/alarm/SleepMemory.c msgid "Unable to write to sleep_memory." -msgstr "wú fǎ xiě rù sleep_memory. +msgstr "wú fǎ xiě rù sleep_memory." #: ports/nrf/common-hal/_bleio/UUID.c msgid "Unexpected nrfx uuid type" From 3940878695f2d7797fc1570d8b281ca9ffa454ff Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 1 Jul 2021 12:49:11 -0700 Subject: [PATCH 32/52] Shrink builds and handle 0-length writes --- ports/nrf/boards/pca10100/mpconfigboard.mk | 1 + ports/nrf/boards/simmel/mpconfigboard.mk | 2 ++ ports/nrf/common-hal/_bleio/__init__.c | 10 ++++----- ports/nrf/common-hal/busio/SPI.c | 2 +- ports/nrf/common-hal/busio/SPI.h | 2 +- supervisor/shared/bluetooth/file_transfer.c | 24 +++++++++++++++++++++ 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/ports/nrf/boards/pca10100/mpconfigboard.mk b/ports/nrf/boards/pca10100/mpconfigboard.mk index 3a7407861b..6381df74f4 100644 --- a/ports/nrf/boards/pca10100/mpconfigboard.mk +++ b/ports/nrf/boards/pca10100/mpconfigboard.mk @@ -27,6 +27,7 @@ CIRCUITPY_RE = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_SDCARDIO = 0 CIRCUITPY_ULAB = 0 +CIRCUITPY_USB_MIDI = 0 MICROPY_PY_ASYNC_AWAIT = 0 diff --git a/ports/nrf/boards/simmel/mpconfigboard.mk b/ports/nrf/boards/simmel/mpconfigboard.mk index 57f83fd3d2..4f6385260e 100644 --- a/ports/nrf/boards/simmel/mpconfigboard.mk +++ b/ports/nrf/boards/simmel/mpconfigboard.mk @@ -43,3 +43,5 @@ CIRCUITPY_WATCHDOG = 1 # Override optimization to keep binary small OPTIMIZATION_FLAGS = -Os +SUPEROPT_VM = 0 +SUPEROPT_GC = 0 diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index de1641eb9d..604f0be2e5 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -96,6 +96,8 @@ void check_sec_status(uint8_t sec_status) { // Turn off BLE on a reset or reload. void bleio_reset() { + // Set this explicitly to save data. + common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { return; } @@ -107,12 +109,8 @@ void bleio_reset() { } // The singleton _bleio.Adapter object, bound to _bleio.adapter -// It currently only has properties and no state -bleio_adapter_obj_t common_hal_bleio_adapter_obj = { - .base = { - .type = &bleio_adapter_type, - }, -}; +// It currently only has properties and no state. Inited by bleio_reset +bleio_adapter_obj_t common_hal_bleio_adapter_obj; void common_hal_bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLE_CONN_HANDLE_INVALID) { diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c index 309e1bce18..f606fe898f 100644 --- a/ports/nrf/common-hal/busio/SPI.c +++ b/ports/nrf/common-hal/busio/SPI.c @@ -51,7 +51,7 @@ #endif // These are in order from highest available frequency to lowest (32MHz first, then 8MHz). -STATIC spim_peripheral_t spim_peripherals[] = { +STATIC const spim_peripheral_t spim_peripherals[] = { #if NRFX_CHECK(NRFX_SPIM3_ENABLED) // SPIM3 exists only on nRF52840 and supports 32MHz max. All other SPIM's are only 8MHz max. // Allocate SPIM3 first. diff --git a/ports/nrf/common-hal/busio/SPI.h b/ports/nrf/common-hal/busio/SPI.h index 796ff59f93..91c65ee0df 100644 --- a/ports/nrf/common-hal/busio/SPI.h +++ b/ports/nrf/common-hal/busio/SPI.h @@ -38,7 +38,7 @@ typedef struct { typedef struct { mp_obj_base_t base; - spim_peripheral_t *spim_peripheral; + const spim_peripheral_t *spim_peripheral; bool has_lock; uint8_t clock_pin_number; uint8_t MOSI_pin_number; diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index dcd3d36e78..3bd306c5a7 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -275,9 +275,26 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { // Align the next chunk to a sector boundary. uint32_t offset = command->offset; size_t chunk_size = MIN(total_write_length - offset, 512 - (offset % 512)); + // Special case when truncating the file. (Deleting stuff off the end.) + if (chunk_size == 0) { + f_lseek(&active_file, offset); + f_truncate(&active_file); + f_close(&active_file); + #if CIRCUITPY_USB_MSC + usb_msc_unlock(); + #endif + } response.offset = offset; response.free_space = chunk_size; common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0); + if (chunk_size == 0) { + // Don't reload until everything is written out of the packet buffer. + common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer); + // Trigger an autoreload + autoreload_now(); + return ANY_COMMAND; + } + return WRITE_DATA; } @@ -474,7 +491,12 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) { STATIC uint8_t current_command[COMMAND_SIZE] __attribute__ ((aligned(4))); STATIC volatile size_t current_offset; STATIC uint8_t next_command; +STATIC bool running = false; void supervisor_bluetooth_file_transfer_background(void) { + if (running) { + return; + } + running = true; mp_int_t size = 1; while (size > 0) { size = common_hal_bleio_packet_buffer_readinto(&_transfer_packet_buffer, current_command + current_offset, COMMAND_SIZE - current_offset); @@ -527,9 +549,11 @@ void supervisor_bluetooth_file_transfer_background(void) { current_offset = 0; } } + running = false; } void supervisor_bluetooth_file_transfer_disconnected(void) { next_command = ANY_COMMAND; + current_offset = 0; f_close(&active_file); } From 33bbb8b1f48ba1263bddb103f49720201a139a91 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 30 Jun 2021 13:11:54 -0400 Subject: [PATCH 33/52] RP2040 PWMAudioOut: Release DMA channels after play has finished. --- ports/atmel-samd/audio_dma.c | 16 +++++----- ports/atmel-samd/audio_dma.h | 8 ++--- ports/raspberrypi/audio_dma.c | 32 +++++++++---------- ports/raspberrypi/audio_dma.h | 8 ++--- .../common-hal/audiobusio/I2SOut.h | 5 +-- .../common-hal/audiopwmio/PWMAudioOut.c | 8 ++--- ports/raspberrypi/common-hal/pwmio/PWMOut.c | 2 ++ shared-module/audiocore/RawSample.c | 10 +++--- shared-module/audiocore/RawSample.h | 6 ++-- shared-module/audiocore/WaveFile.c | 13 ++++---- shared-module/audiocore/WaveFile.h | 6 ++-- shared-module/audiocore/__init__.c | 12 +++---- shared-module/audiocore/__init__.h | 12 +++---- shared-module/audiomixer/Mixer.c | 10 +++--- shared-module/audiomixer/Mixer.h | 6 ++-- shared-module/audiomp3/MP3Decoder.c | 12 +++---- shared-module/audiomp3/MP3Decoder.h | 6 ++-- shared-module/synthio/MidiTrack.c | 6 ++-- shared-module/synthio/MidiTrack.h | 6 ++-- 19 files changed, 93 insertions(+), 91 deletions(-) diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index 7b1ca42c06..7f1260973d 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -131,7 +131,7 @@ void audio_dma_load_next_block(audio_dma_t *dma) { uint8_t *buffer; uint32_t buffer_length; audioio_get_buffer_result_t get_buffer_result = - audiosample_get_buffer(dma->sample, dma->single_channel, dma->audio_channel, + audiosample_get_buffer(dma->sample, dma->single_channel_output, dma->audio_channel, &buffer, &buffer_length); DmacDescriptor *descriptor = dma->second_descriptor; @@ -155,7 +155,7 @@ void audio_dma_load_next_block(audio_dma_t *dma) { descriptor->SRCADDR.reg = ((uint32_t)output_buffer) + output_buffer_length; if (get_buffer_result == GET_BUFFER_DONE) { if (dma->loop) { - audiosample_reset_buffer(dma->sample, dma->single_channel, dma->audio_channel); + audiosample_reset_buffer(dma->sample, dma->single_channel_output, dma->audio_channel); } else { descriptor->DESCADDR.reg = 0; } @@ -183,7 +183,7 @@ static void setup_audio_descriptor(DmacDescriptor *descriptor, uint8_t beat_size audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, mp_obj_t sample, bool loop, - bool single_channel, + bool single_channel_output, uint8_t audio_channel, bool output_signed, uint32_t output_register_address, @@ -195,7 +195,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, dma->sample = sample; dma->loop = loop; - dma->single_channel = single_channel; + dma->single_channel_output = single_channel_output; dma->audio_channel = audio_channel; dma->dma_channel = dma_channel; dma->signed_to_unsigned = false; @@ -203,12 +203,12 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, dma->second_descriptor = NULL; dma->spacing = 1; dma->first_descriptor_free = true; - audiosample_reset_buffer(sample, single_channel, audio_channel); + audiosample_reset_buffer(sample, single_channel_output, audio_channel); bool single_buffer; bool samples_signed; uint32_t max_buffer_length; - audiosample_get_buffer_structure(sample, single_channel, &single_buffer, &samples_signed, + audiosample_get_buffer_structure(sample, single_channel_output, &single_buffer, &samples_signed, &max_buffer_length, &dma->spacing); uint8_t output_spacing = dma->spacing; if (output_signed != samples_signed) { @@ -254,12 +254,12 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, } else { dma->beat_size = 1; dma->bytes_per_sample = 1; - if (single_channel) { + if (single_channel_output) { output_register_address += 1; } } // Transfer both channels at once. - if (!single_channel && audiosample_channel_count(sample) == 2) { + if (!single_channel_output && audiosample_channel_count(sample) == 2) { dma->beat_size *= 2; } diff --git a/ports/atmel-samd/audio_dma.h b/ports/atmel-samd/audio_dma.h index 4e7d193b1d..bc5beb3bf5 100644 --- a/ports/atmel-samd/audio_dma.h +++ b/ports/atmel-samd/audio_dma.h @@ -42,7 +42,7 @@ typedef struct { uint8_t beat_size; uint8_t spacing; bool loop; - bool single_channel; + bool single_channel_output; bool signed_to_unsigned; bool unsigned_to_signed; bool first_buffer_free; @@ -72,16 +72,16 @@ void dma_free_channel(uint8_t channel); // This sets everything up but doesn't start the timer. // Sample is the python object for the sample to play. // loop is true if we should loop the sample. -// single_channel is true if we only output a single channel. When false, all channels will be +// single_channel_output is true if we only output a single channel. When false, all channels will be // output. -// audio_channel is the index of the channel to dma. single_channel must be false in this case. +// audio_channel is the index of the channel to dma. single_channel_output must be false in this case. // output_signed is true if the dma'd data should be signed. False and it will be unsigned. // output_register_address is the address to copy data to. // dma_trigger_source is the DMA trigger source which cause another copy audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, mp_obj_t sample, bool loop, - bool single_channel, + bool single_channel_output, uint8_t audio_channel, bool output_signed, uint32_t output_register_address, diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c index 7044c44edf..91805e0a4d 100644 --- a/ports/raspberrypi/audio_dma.c +++ b/ports/raspberrypi/audio_dma.c @@ -129,7 +129,7 @@ void audio_dma_load_next_block(audio_dma_t *dma) { uint8_t *buffer; uint32_t buffer_length; get_buffer_result = audiosample_get_buffer(dma->sample, - dma->single_channel, dma->audio_channel, &buffer, &buffer_length); + dma->single_channel_output, dma->audio_channel, &buffer, &buffer_length); if (get_buffer_result == GET_BUFFER_ERROR) { audio_dma_stop(dma); @@ -148,7 +148,7 @@ void audio_dma_load_next_block(audio_dma_t *dma) { dma_channel_set_read_addr(dma_channel, output_buffer, false /* trigger */); if (get_buffer_result == GET_BUFFER_DONE) { if (dma->loop) { - audiosample_reset_buffer(dma->sample, dma->single_channel, dma->audio_channel); + audiosample_reset_buffer(dma->sample, dma->single_channel_output, dma->audio_channel); } else { // Set channel trigger to ourselves so we don't keep going. dma_channel_hw_t *c = &dma_hw->ch[dma_channel]; @@ -161,13 +161,13 @@ void audio_dma_load_next_block(audio_dma_t *dma) { audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, mp_obj_t sample, bool loop, - bool single_channel, + bool single_channel_output, uint8_t audio_channel, bool output_signed, uint8_t output_resolution, uint32_t output_register_address, uint8_t dma_trigger_source) { - // Use two DMA channels to because the DMA can't wrap to itself without the + // Use two DMA channels to play because the DMA can't wrap to itself without the // buffer being power of two aligned. dma->channel[0] = dma_claim_unused_channel(false); dma->channel[1] = dma_claim_unused_channel(false); @@ -180,7 +180,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, dma->sample = sample; dma->loop = loop; - dma->single_channel = single_channel; + dma->single_channel_output = single_channel_output; dma->audio_channel = audio_channel; dma->signed_to_unsigned = false; dma->unsigned_to_signed = false; @@ -189,12 +189,12 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, dma->first_channel_free = true; dma->output_resolution = output_resolution; dma->sample_resolution = audiosample_bits_per_sample(sample); - audiosample_reset_buffer(sample, single_channel, audio_channel); + audiosample_reset_buffer(sample, single_channel_output, audio_channel); bool single_buffer; bool samples_signed; uint32_t max_buffer_length; - audiosample_get_buffer_structure(sample, single_channel, &single_buffer, &samples_signed, + audiosample_get_buffer_structure(sample, single_channel_output, &single_buffer, &samples_signed, &max_buffer_length, &dma->sample_spacing); // Check to see if we have to scale the resolution up. @@ -227,10 +227,9 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, dma->output_size = 1; } // Transfer both channels at once. - if (!single_channel && audiosample_channel_count(sample) == 2) { + if (!single_channel_output && audiosample_channel_count(sample) == 2) { dma->output_size *= 2; } - enum dma_channel_transfer_size dma_size = DMA_SIZE_8; if (dma->output_size == 2) { dma_size = DMA_SIZE_16; @@ -324,20 +323,19 @@ void audio_dma_stop(audio_dma_t *dma) { // to hold the previous value. void audio_dma_pause(audio_dma_t *dma) { dma_hw->ch[dma->channel[0]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; - dma_hw->ch[dma->channel[1]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; + dma_hw->ch[dma->channel[1]].al1_ctrl &= ~DMA_CH1_CTRL_TRIG_EN_BITS; } void audio_dma_resume(audio_dma_t *dma) { // Always re-enable the non-busy channel first so it's ready to continue when the busy channel // finishes and chains to it. (An interrupt could make the time between enables long.) - size_t first = 0; - size_t second = 1; if (dma_channel_is_busy(dma->channel[0])) { - first = 1; - second = 0; + dma_hw->ch[dma->channel[1]].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS; + dma_hw->ch[dma->channel[0]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS; + } else { + dma_hw->ch[dma->channel[0]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS; + dma_hw->ch[dma->channel[1]].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS; } - dma_hw->ch[dma->channel[first]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS; - dma_hw->ch[dma->channel[second]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS; } bool audio_dma_get_paused(audio_dma_t *dma) { @@ -378,6 +376,8 @@ bool audio_dma_get_playing(audio_dma_t *dma) { // WARN(tannewt): DO NOT print from here, or anything it calls. Printing calls // background tasks such as this and causes a stack overflow. +// NOTE(dhalbert): I successfully printed from here while debugging. +// So it's possible, but be careful. STATIC void dma_callback_fun(void *arg) { audio_dma_t *dma = arg; if (dma == NULL) { diff --git a/ports/raspberrypi/audio_dma.h b/ports/raspberrypi/audio_dma.h index faececa8df..f84f6debeb 100644 --- a/ports/raspberrypi/audio_dma.h +++ b/ports/raspberrypi/audio_dma.h @@ -39,7 +39,7 @@ typedef struct { uint8_t output_size; uint8_t sample_spacing; bool loop; - bool single_channel; + bool single_channel_output; bool signed_to_unsigned; bool unsigned_to_signed; bool output_signed; @@ -66,16 +66,16 @@ void audio_dma_reset(void); // This sets everything up but doesn't start the timer. // Sample is the python object for the sample to play. // loop is true if we should loop the sample. -// single_channel is true if we only output a single channel. When false, all channels will be +// single_channel_output is true if we only output a single channel. When false, all channels will be // output. -// audio_channel is the index of the channel to dma. single_channel must be false in this case. +// audio_channel is the index of the channel to dma. single_channel_output must be false in this case. // output_signed is true if the dma'd data should be signed. False and it will be unsigned. // output_register_address is the address to copy data to. // dma_trigger_source is the DMA trigger source which cause another copy audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, mp_obj_t sample, bool loop, - bool single_channel, + bool single_channel_output, uint8_t audio_channel, bool output_signed, uint8_t output_resolution, diff --git a/ports/raspberrypi/common-hal/audiobusio/I2SOut.h b/ports/raspberrypi/common-hal/audiobusio/I2SOut.h index 851e86c8a9..52226ae49d 100644 --- a/ports/raspberrypi/common-hal/audiobusio/I2SOut.h +++ b/ports/raspberrypi/common-hal/audiobusio/I2SOut.h @@ -1,3 +1,4 @@ + /* * This file is part of the MicroPython project, http://micropython.org/ * @@ -36,10 +37,10 @@ // We don't bit pack because we'll only have two at most. Its better to save code size instead. typedef struct { mp_obj_base_t base; - bool left_justified; rp2pio_statemachine_obj_t state_machine; - bool playing; audio_dma_t dma; + bool left_justified; + bool playing; } audiobusio_i2sout_obj_t; void i2sout_reset(void); diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c index e191606577..bf9d04bb65 100644 --- a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c @@ -96,11 +96,6 @@ void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t *s mp_raise_RuntimeError(translate("All timers in use")); } - claim_pin(left_channel); - if (right_channel != NULL) { - claim_pin(right_channel); - } - audio_dma_init(&self->dma); self->pacing_timer = NUM_DMA_TIMERS; @@ -220,7 +215,10 @@ bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t if (!playing && self->pacing_timer < NUM_DMA_TIMERS) { dma_hw->timer[self->pacing_timer] = 0; self->pacing_timer = NUM_DMA_TIMERS; + + audio_dma_stop(&self->dma); } + return playing; } diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index 9695a8fdf7..5215f2b8df 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -163,6 +163,8 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, self->variable_frequency = variable_frequency; self->duty_cycle = duty; + claim_pin(pin); + if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) { return PWMOUT_INVALID_FREQUENCY; } diff --git a/shared-module/audiocore/RawSample.c b/shared-module/audiocore/RawSample.c index 1f1db0a509..e7d765e197 100644 --- a/shared-module/audiocore/RawSample.c +++ b/shared-module/audiocore/RawSample.c @@ -67,17 +67,17 @@ uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t * } void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel) { } audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { *buffer_length = self->len; - if (single_channel) { + if (single_channel_output) { *buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8); } else { *buffer = self->buffer; @@ -85,13 +85,13 @@ audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t return GET_BUFFER_DONE; } -void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel, +void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { *single_buffer = true; *samples_signed = self->samples_signed; *max_buffer_length = self->len; - if (single_channel) { + if (single_channel_output) { *spacing = self->channel_count; } else { *spacing = 1; diff --git a/shared-module/audiocore/RawSample.h b/shared-module/audiocore/RawSample.h index 8208b4c280..10d395b8a3 100644 --- a/shared-module/audiocore/RawSample.h +++ b/shared-module/audiocore/RawSample.h @@ -44,14 +44,14 @@ typedef struct { // These are not available from Python because it may be called in an interrupt. void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel); audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel, +void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiocore/WaveFile.c b/shared-module/audiocore/WaveFile.c index 4864004d52..6d42d27ddb 100644 --- a/shared-module/audiocore/WaveFile.c +++ b/shared-module/audiocore/WaveFile.c @@ -169,9 +169,9 @@ uint32_t audioio_wavefile_max_buffer_length(audioio_wavefile_obj_t *self) { } void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel) { - if (single_channel && channel == 1) { + if (single_channel_output && channel == 1) { return; } // We don't reset the buffer index in case we're looping and we have an odd number of buffer @@ -184,11 +184,11 @@ void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self, } audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { - if (!single_channel) { + if (!single_channel_output) { channel = 0; } @@ -265,13 +265,14 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t * return self->bytes_remaining == 0 ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA; } -void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel, +void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { *single_buffer = false; + // In WAV files, 8-bit samples are always unsigned, and larger samples are always signed. *samples_signed = self->bits_per_sample > 8; *max_buffer_length = 512; - if (single_channel) { + if (single_channel_output) { *spacing = self->channel_count; } else { *spacing = 1; diff --git a/shared-module/audiocore/WaveFile.h b/shared-module/audiocore/WaveFile.h index 80b2fd3a56..986359e16e 100644 --- a/shared-module/audiocore/WaveFile.h +++ b/shared-module/audiocore/WaveFile.h @@ -57,14 +57,14 @@ typedef struct { // These are not available from Python because it may be called in an interrupt. void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel); audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel, +void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index 605eac70b9..b85586851b 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -50,24 +50,24 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) { return proto->channel_count(MP_OBJ_TO_PTR(sample_obj)); } -void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) { +void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel) { const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, audio_channel); + proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, audio_channel); } audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, channel, buffer, buffer_length); + return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, channel, buffer, buffer_length); } -void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, +void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel, single_buffer, + proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing); } diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 69955a25f7..e57602519c 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -43,12 +43,12 @@ typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t); typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t); typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t); typedef void (*audiosample_reset_buffer_fun)(mp_obj_t, - bool single_channel, uint8_t audio_channel); + bool single_channel_output, uint8_t audio_channel); typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t, - bool single_channel, uint8_t channel, uint8_t **buffer, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); typedef void (*audiosample_get_buffer_structure_fun)(mp_obj_t, - bool single_channel, bool *single_buffer, + bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); @@ -65,12 +65,12 @@ typedef struct _audiosample_p_t { uint32_t audiosample_sample_rate(mp_obj_t sample_obj); uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); uint8_t audiosample_channel_count(mp_obj_t sample_obj); -void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel); +void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel); audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); -void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, +void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 20731933c4..d6569c66f0 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -94,7 +94,7 @@ bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self) { } void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel) { for (uint8_t i = 0; i < self->voice_count; i++) { common_hal_audiomixer_mixervoice_stop(self->voice[i]); @@ -280,11 +280,11 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, } audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { - if (!single_channel) { + if (!single_channel_output) { channel = 0; } @@ -351,13 +351,13 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t * return GET_BUFFER_MORE_DATA; } -void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel, +void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { *single_buffer = false; *samples_signed = self->samples_signed; *max_buffer_length = self->len; - if (single_channel) { + if (single_channel_output) { *spacing = self->channel_count; } else { *spacing = 1; diff --git a/shared-module/audiomixer/Mixer.h b/shared-module/audiomixer/Mixer.h index ceb04772ec..c9228d9f13 100644 --- a/shared-module/audiomixer/Mixer.h +++ b/shared-module/audiomixer/Mixer.h @@ -55,14 +55,14 @@ typedef struct { // These are not available from Python because it may be called in an interrupt. void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel); audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel, +void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c index 2b623233e0..27c69f735b 100644 --- a/shared-module/audiomp3/MP3Decoder.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -295,9 +295,9 @@ bool audiomp3_mp3file_samples_signed(audiomp3_mp3file_obj_t *self) { } void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel) { - if (single_channel && channel == 1) { + if (single_channel_output && channel == 1) { return; } // We don't reset the buffer index in case we're looping and we have an odd number of buffer @@ -314,14 +314,14 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self, } audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **bufptr, uint32_t *buffer_length) { if (!self->inbuf) { return GET_BUFFER_ERROR; } - if (!single_channel) { + if (!single_channel_output) { channel = 0; } @@ -363,13 +363,13 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t * return GET_BUFFER_MORE_DATA; } -void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel, +void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { *single_buffer = false; *samples_signed = true; *max_buffer_length = self->frame_buffer_size; - if (single_channel) { + if (single_channel_output) { *spacing = self->channel_count; } else { *spacing = 1; diff --git a/shared-module/audiomp3/MP3Decoder.h b/shared-module/audiomp3/MP3Decoder.h index c1e6178465..0f2256a417 100644 --- a/shared-module/audiomp3/MP3Decoder.h +++ b/shared-module/audiomp3/MP3Decoder.h @@ -58,14 +58,14 @@ typedef struct { // These are not available from Python because it may be called in an interrupt. void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel); audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel, +void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/synthio/MidiTrack.c b/shared-module/synthio/MidiTrack.c index 0827945ab5..b2693a0c59 100644 --- a/shared-module/synthio/MidiTrack.c +++ b/shared-module/synthio/MidiTrack.c @@ -165,7 +165,7 @@ uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t * } void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self, - bool single_channel, uint8_t channel) { + bool single_channel_output, uint8_t channel) { self->next_span = 0; } @@ -174,7 +174,7 @@ STATIC const uint16_t notes[] = {8372, 8870, 9397, 9956, 10548, 11175, 11840, 12544, 13290, 14080, 14917, 15804}; // 9th octave audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t *self, - bool single_channel, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { if (self->next_span >= self->total_spans) { *buffer_length = 0; @@ -202,7 +202,7 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t GET_BUFFER_DONE : GET_BUFFER_MORE_DATA; } -void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel, +void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { *single_buffer = true; diff --git a/shared-module/synthio/MidiTrack.h b/shared-module/synthio/MidiTrack.h index bd058daaee..0af174ebc1 100644 --- a/shared-module/synthio/MidiTrack.h +++ b/shared-module/synthio/MidiTrack.h @@ -49,16 +49,16 @@ typedef struct { // These are not available from Python because it may be called in an interrupt. void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel); audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t *self, - bool single_channel, + bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel, +void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output, bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); From d886e8041d57a7430dfa6989c65572ddf86dafed Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 1 Jul 2021 22:14:37 -0400 Subject: [PATCH 34/52] Turn off pwmio on meow meow for space reasons --- ports/atmel-samd/boards/meowmeow/mpconfigboard.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk index 55c6bb6de3..ff96231b84 100644 --- a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk +++ b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk @@ -6,6 +6,8 @@ USB_MANUFACTURER = "Electronic Cats" CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 +CIRCUITPY_PWMIO = 0 + INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 From a4bd4e916be663a4a4de30683ce54a55d2f2014a Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Fri, 2 Jul 2021 14:40:41 +0530 Subject: [PATCH 35/52] esp32s2 - fix spi_never_reset() --- ports/esp32s2/common-hal/busio/SPI.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/esp32s2/common-hal/busio/SPI.c b/ports/esp32s2/common-hal/busio/SPI.c index ce05b74b4e..fee533e755 100644 --- a/ports/esp32s2/common-hal/busio/SPI.c +++ b/ports/esp32s2/common-hal/busio/SPI.c @@ -118,8 +118,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { spi_never_reset[self->host_id] = true; common_hal_never_reset_pin(self->clock); - common_hal_never_reset_pin(self->MOSI); - common_hal_never_reset_pin(self->MISO); + if (self->MOSI != NULL) { + common_hal_never_reset_pin(self->MOSI); + } + if (self->MISO != NULL) { + common_hal_never_reset_pin(self->MISO); + } } bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { From 6bb44674a5400161c82cb9c42c7b7cb10704c207 Mon Sep 17 00:00:00 2001 From: Randall Bohn Date: Sat, 3 Jul 2021 04:34:55 -0600 Subject: [PATCH 36/52] Enable audiomixer for esp32s2. Allows playing sounds via Mixer on I2SOut. Tested on the feathers2. --- ports/esp32s2/mpconfigport.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index 5073d8812d..94758df8d4 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -21,6 +21,7 @@ CIRCUITPY_AUDIOBUSIO = 1 CIRCUITPY_AUDIOBUSIO_PDMIN = 0 CIRCUITPY_AUDIOBUSIO_I2SOUT = 1 CIRCUITPY_AUDIOIO = 0 +CIRCUITPY_AUDIOMIXER = 1 CIRCUITPY_CANIO = 1 CIRCUITPY_COUNTIO = 1 CIRCUITPY_DUALBANK = 1 From 2519b0647879dfad7017b0abb799385fb6efbbc0 Mon Sep 17 00:00:00 2001 From: Daniel Griswold Date: Tue, 6 Jul 2021 01:15:32 -0400 Subject: [PATCH 37/52] fix spi definition --- ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c b/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c index 17ff8d9a41..f5ff3618c9 100644 --- a/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c +++ b/ports/raspberrypi/boards/adafruit_macropad_rp2040/pins.c @@ -43,7 +43,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} }; From d660d229ab6f6f64736d3c68610af8156ad970fc Mon Sep 17 00:00:00 2001 From: hexthat Date: Mon, 5 Jul 2021 16:19:23 +0000 Subject: [PATCH 38/52] Translated using Weblate (Chinese (Pinyin)) Currently translated at 100.0% (1007 of 1007 strings) Translation: CircuitPython/main Translate-URL: https://hosted.weblate.org/projects/circuitpython/main/zh_Latn/ --- locale/zh_Latn_pinyin.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 74d6ab1fa8..e357c4eda5 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-06-25 18:15+0000\n" +"PO-Revision-Date: 2021-07-06 16:32+0000\n" "Last-Translator: hexthat \n" "Language-Team: Chinese Hanyu Pinyin\n" "Language: zh_Latn_pinyin\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.7.1-dev\n" +"X-Generator: Weblate 4.8-dev\n" #: main.c msgid "" @@ -2066,7 +2066,7 @@ msgstr "SPI chóngxīn chūshǐhuà cuòwù" #: ports/esp32s2/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "SPI pèi zhì shī bài" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" From b4e763613a732121e41e9489018f81aeb53cde0c Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Wed, 7 Jul 2021 15:13:26 +0530 Subject: [PATCH 39/52] delete ports/nrf/examples directory --- ports/nrf/examples/ubluepy_eddystone.py | 68 ------------------ ports/nrf/examples/ubluepy_scan.py | 42 ----------- ports/nrf/examples/ubluepy_temp.py | 94 ------------------------- 3 files changed, 204 deletions(-) delete mode 100644 ports/nrf/examples/ubluepy_eddystone.py delete mode 100644 ports/nrf/examples/ubluepy_scan.py delete mode 100644 ports/nrf/examples/ubluepy_temp.py diff --git a/ports/nrf/examples/ubluepy_eddystone.py b/ports/nrf/examples/ubluepy_eddystone.py deleted file mode 100644 index 96818d01c2..0000000000 --- a/ports/nrf/examples/ubluepy_eddystone.py +++ /dev/null @@ -1,68 +0,0 @@ -from ubluepy import Peripheral, constants - -BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE = const(0x02) -BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED = const(0x04) - -BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE = const( - BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED -) - -EDDYSTONE_FRAME_TYPE_URL = const(0x10) -EDDYSTONE_URL_PREFIX_HTTP_WWW = const(0x00) # "http://www". -EDDYSTONE_URL_SUFFIX_DOT_COM = const(0x01) # ".com" - - -def string_to_binarray(text): - b = bytearray([]) - for c in text: - b.append(ord(c)) - return b - - -def gen_ad_type_content(ad_type, data): - b = bytearray(1) - b.append(ad_type) - b.extend(data) - b[0] = len(b) - 1 - return b - - -def generate_eddystone_adv_packet(url): - # flags - disc_mode = bytearray([BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE]) - packet_flags = gen_ad_type_content(constants.ad_types.AD_TYPE_FLAGS, disc_mode) - - # 16-bit uuid - uuid = bytearray([0xAA, 0xFE]) - packet_uuid16 = gen_ad_type_content( - constants.ad_types.AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, uuid - ) - - # eddystone data - rssi = 0xEE # -18 dB, approx signal strength at 0m. - eddystone_data = bytearray([]) - eddystone_data.append(EDDYSTONE_FRAME_TYPE_URL) - eddystone_data.append(rssi) - eddystone_data.append(EDDYSTONE_URL_PREFIX_HTTP_WWW) - eddystone_data.extend(string_to_binarray(url)) - eddystone_data.append(EDDYSTONE_URL_SUFFIX_DOT_COM) - - # service data - service_data = uuid + eddystone_data - packet_service_data = gen_ad_type_content( - constants.ad_types.AD_TYPE_SERVICE_DATA, service_data - ) - - # generate advertisement packet - packet = bytearray([]) - packet.extend(packet_flags) - packet.extend(packet_uuid16) - packet.extend(packet_service_data) - - return packet - - -def start(): - adv_packet = generate_eddystone_adv_packet("micropython") - p = Peripheral() - p.advertise(data=adv_packet, connectable=False) diff --git a/ports/nrf/examples/ubluepy_scan.py b/ports/nrf/examples/ubluepy_scan.py deleted file mode 100644 index 37daa6c69b..0000000000 --- a/ports/nrf/examples/ubluepy_scan.py +++ /dev/null @@ -1,42 +0,0 @@ -from ubluepy import Scanner, constants - - -def bytes_to_str(bytes): - string = "" - for b in bytes: - string += chr(b) - return string - - -def get_device_names(scan_entries): - dev_names = [] - for e in scan_entries: - scan = e.getScanData() - if scan: - for s in scan: - if s[0] == constants.ad_types.AD_TYPE_COMPLETE_LOCAL_NAME: - dev_names.append((e, bytes_to_str(s[2]))) - return dev_names - - -def find_device_by_name(name): - s = Scanner() - scan_res = s.scan(100) - - device_names = get_device_names(scan_res) - for dev in device_names: - if name == dev[1]: - return dev[0] - - -# >>> res = find_device_by_name("micr") -# >>> if res: -# ... print("address:", res.addr()) -# ... print("address type:", res.addr_type()) -# ... print("rssi:", res.rssi()) -# ... -# ... -# ... -# address: c2:73:61:89:24:45 -# address type: 1 -# rssi: -26 diff --git a/ports/nrf/examples/ubluepy_temp.py b/ports/nrf/examples/ubluepy_temp.py deleted file mode 100644 index c70235c4a3..0000000000 --- a/ports/nrf/examples/ubluepy_temp.py +++ /dev/null @@ -1,94 +0,0 @@ -# This file is part of the MicroPython project, http://micropython.org/ -# -# The MIT License (MIT) -# -# SPDX-FileCopyrightText: Copyright (c) 2017 Glenn Ruben Bakke -# -# 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 - -from pyb import LED -from machine import RTC, Temp -from ubluepy import Service, Characteristic, UUID, Peripheral, constants - - -def event_handler(id, handle, data): - global rtc - global periph - global serv_env_sense - global notif_enabled - - if id == constants.EVT_GAP_CONNECTED: - # indicated 'connected' - LED(1).on() - - elif id == constants.EVT_GAP_DISCONNECTED: - # stop low power timer - rtc.stop() - # indicate 'disconnected' - LED(1).off() - # restart advertisement - periph.advertise(device_name="micr_temp", services=[serv_env_sense]) - - elif id == constants.EVT_GATTS_WRITE: - # write to this Characteristic is to CCCD - if int(data[0]) == 1: - notif_enabled = True - # start low power timer - rtc.start() - else: - notif_enabled = False - # stop low power timer - rtc.stop() - - -def send_temp(timer_id): - global notif_enabled - global char_temp - - if notif_enabled: - # measure chip temperature - temp = Temp.read() - temp = temp * 100 - char_temp.write(bytearray([temp & 0xFF, temp >> 8])) - - -# start off with LED(1) off -LED(1).off() - -# use RTC1 as RTC0 is used by bluetooth stack -# set up RTC callback every 5 second -rtc = RTC(1, period=5, mode=RTC.PERIODIC, callback=send_temp) - -notif_enabled = False - -uuid_env_sense = UUID("0x181A") # Environmental Sensing service -uuid_temp = UUID("0x2A6E") # Temperature characteristic - -serv_env_sense = Service(uuid_env_sense) - -temp_props = Characteristic.PROP_NOTIFY | Characteristic.PROP_READ -temp_attrs = Characteristic.ATTR_CCCD -char_temp = Characteristic(uuid_temp, props=temp_props, attrs=temp_attrs) - -serv_env_sense.addCharacteristic(char_temp) - -periph = Peripheral() -periph.addService(serv_env_sense) -periph.setConnectionHandler(event_handler) -periph.advertise(device_name="micr_temp", services=[serv_env_sense]) From 2e068d0384b74220cd78628f1b1ad543dc9b2911 Mon Sep 17 00:00:00 2001 From: James Carr <70200140+lesamouraipourpre@users.noreply.github.com> Date: Wed, 7 Jul 2021 22:30:30 +0100 Subject: [PATCH 40/52] Minor docs fix in TileGrid.c --- shared-bindings/displayio/TileGrid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 42e9810b54..a0c5e3d816 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -56,7 +56,7 @@ //| tile_width and tile_height match the height of the bitmap by default. //| //| :param Bitmap bitmap: The bitmap storing one or more tiles. -//| :param ColorConverter or Palette pixel_shader: The pixel shader that produces colors from values +//| :param ColorConverter,Palette pixel_shader: The pixel shader that produces colors from values //| :param int width: Width of the grid in tiles. //| :param int height: Height of the grid in tiles. //| :param int tile_width: Width of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions. From bd6826496cfb7e5fdcf48591c463f89243d5d0fb Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 8 Jul 2021 08:14:37 -0400 Subject: [PATCH 41/52] Fix various RP2040 audio dma things: (see detailed commit message) 1. Check for correct error values from dma_claim_unused_channel. 2. Introduce a .stereo flag for simplicity. 3. Clarify PWM carrier frequency choice. 4. Start introducing quiescent audio value. Still need to ramp up/down. 5. Redo audio stop logic a bit. 6. Fix (unrelated) displayio dependency things. There is still an interference problem between other DMA users and audio. Still debugging this. --- ports/raspberrypi/audio_dma.c | 17 +++-- .../common-hal/audiobusio/I2SOut.c | 7 ++ .../common-hal/audiopwmio/PWMAudioOut.c | 74 ++++++++++++------- .../common-hal/audiopwmio/PWMAudioOut.h | 1 + ports/raspberrypi/mpconfigport.mk | 4 +- 5 files changed, 68 insertions(+), 35 deletions(-) diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c index 91805e0a4d..52b1c84b91 100644 --- a/ports/raspberrypi/audio_dma.c +++ b/ports/raspberrypi/audio_dma.c @@ -169,15 +169,20 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, uint8_t dma_trigger_source) { // Use two DMA channels to play because the DMA can't wrap to itself without the // buffer being power of two aligned. - dma->channel[0] = dma_claim_unused_channel(false); - dma->channel[1] = dma_claim_unused_channel(false); - if (dma->channel[0] == NUM_DMA_CHANNELS || dma->channel[1] == NUM_DMA_CHANNELS) { - if (dma->channel[0] < NUM_DMA_CHANNELS) { - dma_channel_unclaim(dma->channel[0]); - } + int dma_channel_0_maybe = dma_claim_unused_channel(false); + if (dma_channel_0_maybe < 0) { return AUDIO_DMA_DMA_BUSY; } + int dma_channel_1_maybe = dma_claim_unused_channel(false); + if (dma_channel_1_maybe < 0) { + dma_channel_unclaim((uint)dma_channel_0_maybe); + return AUDIO_DMA_DMA_BUSY; + } + + dma->channel[0] = (uint8_t)dma_channel_0_maybe; + dma->channel[1] = (uint8_t)dma_channel_1_maybe; + dma->sample = sample; dma->loop = loop; dma->single_channel_output = single_channel_output; diff --git a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c index 0ad44c2527..0958de6883 100644 --- a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c +++ b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c @@ -145,7 +145,13 @@ void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t *self) { return; } + if (common_hal_audiobusio_i2sout_get_playing(self)) { + common_hal_audiobusio_i2sout_stop(self); + } + common_hal_rp2pio_statemachine_deinit(&self->state_machine); + + audio_dma_deinit(&self->dma); } void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, @@ -153,6 +159,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, if (common_hal_audiobusio_i2sout_get_playing(self)) { common_hal_audiobusio_i2sout_stop(self); } + uint8_t bits_per_sample = audiosample_bits_per_sample(sample); // Make sure we transmit a minimum of 16 bits. // TODO: Maybe we need an intermediate object to upsample instead. This is diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c index bf9d04bb65..3a8a7ef226 100644 --- a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c @@ -46,6 +46,12 @@ #define NUM_DMA_TIMERS 4 +// The PWM clock frequency is base_clock_rate / PWM_TOP, typically 125_000_000 / PWM_TOP. +// We pick BITS_PER_SAMPLE so we get a clock frequency that is above what would cause aliasing. +#define BITS_PER_SAMPLE 10 +#define SAMPLE_BITS_TO_DISCARD (16 - BITS_PER_SAMPLE) +#define PWM_TOP ((1 << BITS_PER_SAMPLE) - 1) + void audiopwmout_reset() { for (size_t i = 0; i < NUM_DMA_TIMERS; i++) { dma_hw->timer[i] = 0; @@ -55,7 +61,10 @@ void audiopwmout_reset() { // Caller validates that pins are free. void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t *self, const mcu_pin_obj_t *left_channel, const mcu_pin_obj_t *right_channel, uint16_t quiescent_value) { - if (left_channel != NULL && right_channel != NULL) { + + self->stereo = right_channel != NULL; + + if (self->stereo) { if (pwm_gpio_to_slice_num(left_channel->number) != pwm_gpio_to_slice_num(right_channel->number)) { mp_raise_ValueError(translate("Pins must share PWM slice")); } @@ -72,22 +81,20 @@ void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t *s // we want. ;-) We mark ourselves variable only if we're a mono output to // prevent other PWM use on the other channel. If stereo, we say fixed // frequency so we can allocate with ourselves. - bool mono = right_channel == NULL; - // We don't actually know our frequency yet so just pick one that shouldn't - // match anyone else. (We'll only know the frequency once we play something - // back.) - uint32_t frequency = 12500; + // We don't actually know our frequency yet. It is set when + // pwmio_pwmout_set_top() is called. This value is unimportant; it just needs to be valid. + const uint32_t frequency = 12000000; // Make sure the PWMOut's are "deinited" by default. self->left_pwm.pin = NULL; self->right_pwm.pin = NULL; - pwmout_result_t result = common_hal_pwmio_pwmout_construct(&self->left_pwm, - left_channel, 0, frequency, mono); + pwmout_result_t result = + common_hal_pwmio_pwmout_construct(&self->left_pwm, left_channel, 0, frequency, !self->stereo); if (result == PWMOUT_OK && right_channel != NULL) { - result = common_hal_pwmio_pwmout_construct(&self->right_pwm, - right_channel, 0, frequency, false); + result = + common_hal_pwmio_pwmout_construct(&self->right_pwm, right_channel, 0, frequency, false); if (result != PWMOUT_OK) { common_hal_pwmio_pwmout_deinit(&self->left_pwm); } @@ -96,10 +103,16 @@ void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t *s mp_raise_RuntimeError(translate("All timers in use")); } + self->quiescent_value = quiescent_value >> SAMPLE_BITS_TO_DISCARD; + common_hal_pwmio_pwmout_set_duty_cycle(&self->left_pwm, self->quiescent_value); + pwmio_pwmout_set_top(&self->left_pwm, PWM_TOP); + if (self->stereo) { + common_hal_pwmio_pwmout_set_duty_cycle(&self->right_pwm, self->quiescent_value); + pwmio_pwmout_set_top(&self->right_pwm, PWM_TOP); + } + audio_dma_init(&self->dma); self->pacing_timer = NUM_DMA_TIMERS; - - self->quiescent_value = quiescent_value; } bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t *self) { @@ -110,6 +123,7 @@ void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t *self if (common_hal_audiopwmio_pwmaudioout_deinited(self)) { return; } + if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) { common_hal_audiopwmio_pwmaudioout_stop(self); } @@ -139,13 +153,11 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, mp_raise_RuntimeError(translate("No DMA pacing timer found")); } uint32_t tx_register = (uint32_t)&pwm_hw->slice[self->left_pwm.slice].cc; - if (common_hal_pwmio_pwmout_deinited(&self->right_pwm)) { - // Shift the destination if we are outputting to the second PWM channel. + if (self->stereo) { + // Shift the destination if we are outputting to both PWM channels. tx_register += self->left_pwm.channel * sizeof(uint16_t); } - pwmio_pwmout_set_top(&self->left_pwm, 1023); - audio_dma_result result = audio_dma_setup_playback( &self->dma, sample, @@ -153,15 +165,16 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, false, // single channel 0, // audio channel false, // output signed - 10, - (uint32_t)tx_register, // output register + BITS_PER_SAMPLE, + (uint32_t)tx_register, // output register: PWM cc register 0x3b + pacing_timer); // data request line if (result == AUDIO_DMA_DMA_BUSY) { - // common_hal_audiobusio_i2sout_stop(self); + common_hal_audiopwmio_pwmaudioout_stop(self); mp_raise_RuntimeError(translate("No DMA channel found")); - } else if (result == AUDIO_DMA_MEMORY_ERROR) { - // common_hal_audiobusio_i2sout_stop(self); + } + if (result == AUDIO_DMA_MEMORY_ERROR) { + common_hal_audiopwmio_pwmaudioout_stop(self); mp_raise_RuntimeError(translate("Unable to allocate buffers for signed conversion")); } @@ -177,6 +190,7 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, // are 16-bit. uint32_t sample_rate = audiosample_sample_rate(sample); + uint32_t system_clock = common_hal_mcu_processor_get_frequency(); uint32_t best_numerator = 0; uint32_t best_denominator = 0; @@ -204,19 +218,25 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, } void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t *self) { - dma_hw->timer[self->pacing_timer] = 0; - self->pacing_timer = NUM_DMA_TIMERS; + if (self->pacing_timer < NUM_DMA_TIMERS) { + dma_hw->timer[self->pacing_timer] = 0; + self->pacing_timer = NUM_DMA_TIMERS; + } audio_dma_stop(&self->dma); + + // Set to quiescent level. + pwm_hw->slice[self->left_pwm.slice].cc = self->quiescent_value; + if (self->stereo) { + pwm_hw->slice[self->right_pwm.slice].cc = self->quiescent_value; + } } bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t *self) { bool playing = audio_dma_get_playing(&self->dma); - if (!playing && self->pacing_timer < NUM_DMA_TIMERS) { - dma_hw->timer[self->pacing_timer] = 0; - self->pacing_timer = NUM_DMA_TIMERS; - audio_dma_stop(&self->dma); + if (!playing && self->pacing_timer < NUM_DMA_TIMERS) { + common_hal_audiopwmio_pwmaudioout_stop(self); } return playing; diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h index 2b43b8354d..e9f0f68d06 100644 --- a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h +++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.h @@ -38,6 +38,7 @@ typedef struct { audio_dma_t dma; uint16_t quiescent_value; uint8_t pacing_timer; + bool stereo; // if false, only using left_pwm. } audiopwmio_pwmaudioout_obj_t; void audiopwmout_reset(void); diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index cdb8769bfc..bc8a26de7b 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -21,13 +21,13 @@ CIRCUITPY_ALARM ?= 1 CIRCUITPY_RP2PIO ?= 1 CIRCUITPY_NEOPIXEL_WRITE ?= $(CIRCUITPY_RP2PIO) -CIRCUITPY_FRAMEBUFFERIO ?= 1 +CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_FULL_BUILD ?= 1 CIRCUITPY_AUDIOMP3 ?= 1 CIRCUITPY_BITOPS ?= 1 CIRCUITPY_IMAGECAPTURE ?= 1 CIRCUITPY_PWMIO ?= 1 -CIRCUITPY_RGBMATRIX ?= 1 +CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_ROTARYIO ?= 1 CIRCUITPY_ROTARYIO_SOFTENCODER = 1 From ab52a92704fc7ecb52deb7fcb82337f0abca306f Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 8 Jul 2021 13:42:24 -0400 Subject: [PATCH 42/52] Disallow ctrl-C interrupts of RP2040 SPI and PIO --- ports/raspberrypi/common-hal/busio/SPI.c | 13 ++----------- .../common-hal/rp2pio/StateMachine.c | 17 +---------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/ports/raspberrypi/common-hal/busio/SPI.c b/ports/raspberrypi/common-hal/busio/SPI.c index 23030cbd0d..ab295c4ff1 100644 --- a/ports/raspberrypi/common-hal/busio/SPI.c +++ b/ports/raspberrypi/common-hal/busio/SPI.c @@ -212,15 +212,6 @@ static bool _transfer(busio_spi_obj_t *self, while (dma_channel_is_busy(chan_rx) || dma_channel_is_busy(chan_tx)) { // TODO: We should idle here until we get a DMA interrupt or something else. RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - if (dma_channel_is_busy(chan_rx)) { - dma_channel_abort(chan_rx); - } - if (dma_channel_is_busy(chan_tx)) { - dma_channel_abort(chan_tx); - } - break; - } } } @@ -233,7 +224,7 @@ static bool _transfer(busio_spi_obj_t *self, dma_channel_unclaim(chan_tx); } - if (!use_dma && !mp_hal_is_interrupted()) { + if (!use_dma) { // Use software for small transfers, or if couldn't claim two DMA channels // Never have more transfers in flight than will fit into the RX FIFO, // else FIFO will overflow if this code is heavily interrupted. @@ -241,7 +232,7 @@ static bool _transfer(busio_spi_obj_t *self, size_t rx_remaining = len; size_t tx_remaining = len; - while (!mp_hal_is_interrupted() && (rx_remaining || tx_remaining)) { + while (rx_remaining || tx_remaining) { if (tx_remaining && spi_is_writable(self->peripheral) && rx_remaining - tx_remaining < fifo_depth) { spi_get_hw(self->peripheral)->dr = (uint32_t)*data_out; // Increment only if the buffer is the transfer length. It's 1 otherwise. diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index ab70a27fcd..887ea8e644 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -654,15 +654,6 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, (tx && dma_channel_is_busy(chan_tx))) { // TODO: We should idle here until we get a DMA interrupt or something else. RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - if (rx && dma_channel_is_busy(chan_rx)) { - dma_channel_abort(chan_rx); - } - if (tx && dma_channel_is_busy(chan_tx)) { - dma_channel_abort(chan_tx); - } - break; - } } // Clear the stall bit so we can detect when the state machine is done transmitting. self->pio->fdebug = stall_mask; @@ -677,7 +668,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, dma_channel_unclaim(chan_tx); } - if (!use_dma && !mp_hal_is_interrupted()) { + if (!use_dma) { // Use software for small transfers, or if couldn't claim two DMA channels size_t rx_remaining = in_len / in_stride_in_bytes; size_t tx_remaining = out_len / out_stride_in_bytes; @@ -706,9 +697,6 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, --rx_remaining; } RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - break; - } } // Clear the stall bit so we can detect when the state machine is done transmitting. self->pio->fdebug = stall_mask; @@ -719,9 +707,6 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, while (!pio_sm_is_tx_fifo_empty(self->pio, self->state_machine) || (self->wait_for_txstall && (self->pio->fdebug & stall_mask) == 0)) { RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - break; - } } } return true; From 4046b0fb0a7ea7789101d773a973aad0d9ee8151 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 8 Jul 2021 14:09:21 -0500 Subject: [PATCH 43/52] Issue #4945 - handle multiple PulseIns --- ports/raspberrypi/common-hal/pulseio/PulseIn.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ports/raspberrypi/common-hal/pulseio/PulseIn.c b/ports/raspberrypi/common-hal/pulseio/PulseIn.c index 520526c661..bd53801b2f 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseIn.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseIn.c @@ -36,8 +36,6 @@ #include "bindings/rp2pio/StateMachine.h" #include "common-hal/pulseio/PulseIn.h" -pulseio_pulsein_obj_t *save_self; - #define NO_PIN 0xff #define MAX_PULSE 65535 #define MIN_PULSE 10 @@ -62,7 +60,6 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, self->idle_state = idle_state; self->start = 0; self->len = 0; - save_self = self; bool ok = rp2pio_statemachine_construct(&self->state_machine, pulsein_program, sizeof(pulsein_program) / sizeof(pulsein_program[0]), @@ -88,7 +85,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, buf_index = 0; pio_sm_set_in_pins(self->state_machine.pio,self->state_machine.state_machine,pin->number); - common_hal_rp2pio_statemachine_set_interrupt_handler(&(self->state_machine),&common_hal_pulseio_pulsein_interrupt,NULL,PIO_IRQ0_INTE_SM0_RXNEMPTY_BITS); + common_hal_rp2pio_statemachine_set_interrupt_handler(&(self->state_machine),&common_hal_pulseio_pulsein_interrupt,self,PIO_IRQ0_INTE_SM0_RXNEMPTY_BITS); // exec a set pindirs to 0 for input pio_sm_exec(self->state_machine.pio,self->state_machine.state_machine,0xe080); @@ -124,9 +121,8 @@ void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t *self) { result = 0; buf_index = 0; } -void common_hal_pulseio_pulsein_interrupt() { +void common_hal_pulseio_pulsein_interrupt(pulseio_pulsein_obj_t *self) { - pulseio_pulsein_obj_t *self = save_self; uint32_t rxfifo = 0; rxfifo = pio_sm_get_blocking(self->state_machine.pio, self->state_machine.state_machine); From 289575a81115310bbc570c1737e662bf7833e3f1 Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Thu, 8 Jul 2021 15:55:13 -0400 Subject: [PATCH 44/52] Adding rainbow module. --- py/circuitpy_defns.mk | 4 +++ py/circuitpy_mpconfig.h | 8 +++++ py/circuitpy_mpconfig.mk | 3 ++ shared-bindings/_pixelbuf/PixelBuf.c | 2 -- shared-bindings/_pixelbuf/__init__.c | 31 ---------------- shared-bindings/_pixelbuf/__init__.h | 4 --- shared-bindings/rainbow/__init__.c | 54 ++++++++++++++++++++++++++++ shared-bindings/rainbow/__init__.h | 33 +++++++++++++++++ shared-module/rainbow/__init__.c | 42 ++++++++++++++++++++++ 9 files changed, 144 insertions(+), 37 deletions(-) create mode 100644 shared-bindings/rainbow/__init__.c create mode 100644 shared-bindings/rainbow/__init__.h create mode 100644 shared-module/rainbow/__init__.c diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 9756329ac5..c42e2c38f8 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -229,6 +229,9 @@ endif ifeq ($(CIRCUITPY_PIXELBUF),1) SRC_PATTERNS += _pixelbuf/% endif +ifeq ($(CIRCUITPY_RAINBOW),1) +SRC_PATTERNS += rainbow/% +endif ifeq ($(CIRCUITPY_RGBMATRIX),1) SRC_PATTERNS += rgbmatrix/% endif @@ -533,6 +536,7 @@ SRC_SHARED_MODULE_ALL = \ network/__init__.c \ msgpack/__init__.c \ os/__init__.c \ + rainbow/__init__.c \ random/__init__.c \ rgbmatrix/RGBMatrix.c \ rgbmatrix/__init__.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index fdb78d885c..67feef436f 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -644,6 +644,13 @@ extern const struct _mp_obj_module_t pwmio_module; #define PWMIO_MODULE #endif +#if CIRCUITPY_RAINBOW +extern const struct _mp_obj_module_t rainbow_module; +#define RAINBOW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rainbow), (mp_obj_t)&rainbow_module }, +#else +#define RAINBOW_MODULE +#endif + #if CIRCUITPY_RANDOM extern const struct _mp_obj_module_t random_module; #define RANDOM_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, @@ -918,6 +925,7 @@ extern const struct _mp_obj_module_t msgpack_module; PS2IO_MODULE \ PULSEIO_MODULE \ PWMIO_MODULE \ + RAINBOW_MODULE \ RANDOM_MODULE \ RE_MODULE \ RGBMATRIX_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 0e2c577c69..d601d7df41 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -246,6 +246,9 @@ CFLAGS += -DCIRCUITPY_PULSEIO=$(CIRCUITPY_PULSEIO) CIRCUITPY_PWMIO ?= 1 CFLAGS += -DCIRCUITPY_PWMIO=$(CIRCUITPY_PWMIO) +CIRCUITPY_RAINBOW ?= 1 +CFLAGS += -DCIRCUITPY_RAINBOW=$(CIRCUITPY_RAINBOW) + CIRCUITPY_RANDOM ?= 1 CFLAGS += -DCIRCUITPY_RANDOM=$(CIRCUITPY_RANDOM) diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index 88c92f8f6c..55055c30c6 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -44,8 +44,6 @@ #include "extmod/ulab/code/ndarray.h" #endif -extern const int32_t colorwheel(float pos); - static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t *parsed); //| class PixelBuf: diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index 564e2051b7..a996479ecd 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -41,40 +41,9 @@ //| Byteorders are configured with strings, such as "RGB" or "RGBD".""" // TODO: Pull in docs from pypixelbuf. -//| def colorwheel(n: float) -> int: -//| """C implementation of the common wheel() function found in many examples. -//| Returns the colorwheel RGB value as an integer value for n (usable in :py:class:`PixelBuf`, neopixel, and dotstar).""" -//| ... -//| -//| def wheel(n: float) -> int: -//| """Use of wheel() is deprecated. Please use colorwheel().""" -//| - -STATIC mp_obj_t pixelbuf_colorwheel(mp_obj_t n) { - return MP_OBJ_NEW_SMALL_INT(colorwheel(mp_obj_is_small_int(n) ? MP_OBJ_SMALL_INT_VALUE(n) : mp_obj_get_float(n))); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_colorwheel_obj, pixelbuf_colorwheel); - -const int32_t colorwheel(float pos) { - if (pos > 255) { - pos = pos - ((uint32_t)(pos / 256) * 256); - } - if (pos < 85) { - return (uint8_t)(255 - (pos * 3)) << 16 | (uint8_t)(pos * 3) << 8; - } else if (pos < 170) { - pos -= 85; - return (uint8_t)(255 - (pos * 3)) << 8 | (uint8_t)(pos * 3); - } else { - pos -= 170; - return (uint8_t)(pos * 3) << 16 | (uint8_t)(255 - (pos * 3)); - } -} - STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pixelbuf) }, { MP_ROM_QSTR(MP_QSTR_PixelBuf), MP_ROM_PTR(&pixelbuf_pixelbuf_type) }, - { MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_PTR(&pixelbuf_colorwheel_obj) }, - { MP_ROM_QSTR(MP_QSTR_colorwheel), MP_ROM_PTR(&pixelbuf_colorwheel_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pixelbuf_module_globals, pixelbuf_module_globals_table); diff --git a/shared-bindings/_pixelbuf/__init__.h b/shared-bindings/_pixelbuf/__init__.h index dea3ca7ef8..28f95c6686 100644 --- a/shared-bindings/_pixelbuf/__init__.h +++ b/shared-bindings/_pixelbuf/__init__.h @@ -27,8 +27,4 @@ #ifndef CP_SHARED_BINDINGS_PIXELBUF_INIT_H #define CP_SHARED_BINDINGS_PIXELBUF_INIT_H -#include "common-hal/digitalio/DigitalInOut.h" - -const int32_t colorwheel(float pos); - #endif // CP_SHARED_BINDINGS_PIXELBUF_INIT_H diff --git a/shared-bindings/rainbow/__init__.c b/shared-bindings/rainbow/__init__.c new file mode 100644 index 0000000000..26c9f2d905 --- /dev/null +++ b/shared-bindings/rainbow/__init__.c @@ -0,0 +1,54 @@ +/* + * This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Kattni Rembor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/rainbow/__init__.h" +#include "py/mpconfig.h" +#include "py/obj.h" +//| """`rainbow` module. +//| +//| Provides the `colorwheel()` function.""" +//| +//| def colorwheel(n: float) -> int: +//| """C implementation of the common colorwheel() function found in many examples. +//| Returns the colorwheel RGB value as an integer value for n (usable in neopixel and dotstar).""" +//| ... +//| +STATIC mp_obj_t rainbow_colorwheel(mp_obj_t n) { + return MP_OBJ_NEW_SMALL_INT(colorwheel(mp_obj_is_small_int(n) ? MP_OBJ_SMALL_INT_VALUE(n) : mp_obj_get_float(n))); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(rainbow_colorwheel_obj, rainbow_colorwheel); + +STATIC const mp_rom_map_elem_t rainbow_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rainbow) }, + { MP_ROM_QSTR(MP_QSTR_colorwheel), MP_ROM_PTR(&rainbow_colorwheel_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rainbow_module_globals, rainbow_module_globals_table); + +const mp_obj_module_t rainbow_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&rainbow_module_globals, +}; diff --git a/shared-bindings/rainbow/__init__.h b/shared-bindings/rainbow/__init__.h new file mode 100644 index 0000000000..5e1f3f2acb --- /dev/null +++ b/shared-bindings/rainbow/__init__.h @@ -0,0 +1,33 @@ +/* + * This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Kattni Rembor + * + * 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 CP_SHARED_BINDINGS_RAINBOW_INIT_H +#define CP_SHARED_BINDINGS_RAINBOW_INIT_H +#include + +const int32_t colorwheel(float pos); + +#endif // CP_SHARED_BINDINGS_RAINBOW_INIT_H diff --git a/shared-module/rainbow/__init__.c b/shared-module/rainbow/__init__.c new file mode 100644 index 0000000000..a371992fe3 --- /dev/null +++ b/shared-module/rainbow/__init__.c @@ -0,0 +1,42 @@ +/* + * This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Kattni Rembor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/rainbow/__init__.h" + +const int32_t colorwheel(float pos) { + if (pos > 255) { + pos = pos - ((uint32_t)(pos / 256) * 256); + } + if (pos < 85) { + return (uint8_t)(255 - (pos * 3)) << 16 | (uint8_t)(pos * 3) << 8; + } else if (pos < 170) { + pos -= 85; + return (uint8_t)(255 - (pos * 3)) << 8 | (uint8_t)(pos * 3); + } else { + pos -= 170; + return (uint8_t)(pos * 3) << 16 | (uint8_t)(255 - (pos * 3)); + } +} From 92fa1055efe5315276cad7b89f484a6e65cc7810 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Thu, 8 Jul 2021 22:19:54 +0200 Subject: [PATCH 45/52] Allow changing size of the filesystem on samd21 per board As the CircuitPython grows, it may at some point no longer be possible to squeeze it on some of the flash-less SAMD21 boards, so it would be good to have the option of shrinking the filesystem size on per-board basis. This change allows to define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE inside the board's mpconfigborard.h file. --- ports/atmel-samd/mpconfigport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 20f5e2bed0..686bdcd294 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -92,11 +92,13 @@ #ifdef SAMD21 +#ifndef CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE #if INTERNAL_FLASH_FILESYSTEM #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (64 * 1024) #else #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0) #endif +#endif #ifndef CIRCUITPY_INTERNAL_NVM_SIZE #define CIRCUITPY_INTERNAL_NVM_SIZE (256) From 825a706135f3de49ae6a6c3bd785da5f8201b68f Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Thu, 8 Jul 2021 17:31:10 -0400 Subject: [PATCH 46/52] Turn off MIDI on one build, fix name. --- ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk | 2 ++ shared-bindings/_pixelbuf/PixelBuf.c | 2 +- shared-bindings/_pixelbuf/PixelBuf.h | 2 +- shared-bindings/_pixelbuf/__init__.c | 2 +- shared-bindings/_pixelbuf/__init__.h | 2 +- shared-module/_pixelbuf/PixelBuf.c | 2 +- shared-module/_pixelbuf/PixelBuf.h | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk b/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk index 7317dfbf1b..0d63829c7f 100644 --- a/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk +++ b/ports/atmel-samd/boards/escornabot_makech/mpconfigboard.mk @@ -9,3 +9,5 @@ CHIP_FAMILY = samd21 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 + +CIRCUITPY_USB_MIDI = 0 diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index 55055c30c6..13905c3c29 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Roy Hooper + * Copyright (c) 2018 Rose Hooper * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/shared-bindings/_pixelbuf/PixelBuf.h b/shared-bindings/_pixelbuf/PixelBuf.h index 3f2b328391..644f6cd64b 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.h +++ b/shared-bindings/_pixelbuf/PixelBuf.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Roy Hooper + * Copyright (c) 2018 Rose Hooper * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index a996479ecd..9d0cf8c63e 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Roy Hooper + * Copyright (c) 2018 Rose Hooper * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/shared-bindings/_pixelbuf/__init__.h b/shared-bindings/_pixelbuf/__init__.h index 28f95c6686..9a84bc68a7 100644 --- a/shared-bindings/_pixelbuf/__init__.h +++ b/shared-bindings/_pixelbuf/__init__.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Roy Hooper + * Copyright (c) 2018 Rose Hooper * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index 161b85b062..63cc409c71 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Roy Hooper + * Copyright (c) 2018 Rose Hooper * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h index 13139dcc19..b526254f29 100644 --- a/shared-module/_pixelbuf/PixelBuf.h +++ b/shared-module/_pixelbuf/PixelBuf.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Roy Hooper + * Copyright (c) 2018 Rose Hooper * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 99abd03b7a4b77ba0cb4e8b1e03db016a7c008a8 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Jul 2021 11:23:55 -0500 Subject: [PATCH 47/52] makeqstrdata: use an extremely accurate dictionary heuristic Try to accurately measure the costs of including a word in the dictionary vs the gains from using it in messages. This saves about 160 bytes on trinket_m0 ja, the fullest translation for that board. Other translations on the same board all have savings, ranging from 24 to 228 bytes. ``` Translation Before After Savings ja 1164 1324 160 de_DE 1260 1396 136 fr 1424 1652 228 zh_Latn_pinyin 1448 1520 72 pt_BR 1584 1736 152 pl 1592 1640 48 es 1724 1816 92 ko 1724 1816 92 fil 1764 1800 36 it_IT 1896 2040 144 nl 1956 2136 180 ID 2072 2180 108 cs 2124 2148 24 sv 2340 2448 108 en_x_pirate 2644 2740 96 en_GB 2652 2752 100 el 2656 2768 112 en_US 2656 2768 112 hi 2656 2768 112 ``` --- py/makeqstrdata.py | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 02f0bea7eb..dc004d2df3 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -9,6 +9,7 @@ supervisor/shared/translate.h from __future__ import print_function +import bisect import re import sys @@ -330,6 +331,7 @@ def compute_huffman_coding(translations, compression_filename): end_unused = min(ord_c, end_unused) max_words = end_unused - 0x80 + bits_per_codepoint = 16 if max_ord > 255 else 8 values_type = "uint16_t" if max_ord > 255 else "uint8_t" max_words_len = 160 if max_ord > 255 else 255 @@ -344,6 +346,31 @@ def compute_huffman_coding(translations, compression_filename): # again, neither will "there" or "wither", since they have "the" # as substrings. extractor = TextSplitter(words) + counter = collections.Counter() + for t in texts: + for atom in extractor.iter(t): + counter[atom] += 1 + cb = huffman.codebook(counter.items()) + lengths = sorted(dict((v, len(cb[k])) for k, v in counter.items()).items()) + + def bit_length(s): + return sum(len(cb[c]) for c in s) + + def est_len(occ): + idx = bisect.bisect_left(lengths, (occ, 0)) + return lengths[idx][1] + 1 + + # The cost of adding a dictionary word is just its storage size + # while its savings is the difference between the original + # huffman bit-length of the string and the estimated bit-length + # of the dictionary word, times the number of times the word appears. + # + # The difference between the two is the net savings, in bits. + def est_net_savings(s, occ): + savings = occ * (bit_length(s) - est_len(occ)) + cost = len(s) * bits_per_codepoint + return savings - cost + counter = collections.Counter() for t in texts: for (found, word) in extractor.iter_words(t): @@ -351,12 +378,16 @@ def compute_huffman_coding(translations, compression_filename): for substr in iter_substrings(word, minlen=3, maxlen=9): counter[substr] += 1 - # Score the candidates we found. This is an empirical formula only, - # chosen for its effectiveness. + # Score the candidates we found. This is a semi-empirical formula that + # attempts to model the number of bits saved as closely as possible. + # + # It attempts to compute the codeword lengths of the original word + # to the codeword length the dictionary entry would get, times + # the number of occurrences, less the ovehead of the entries in the + # words[] array. + scores = sorted( - ((s, (len(s) - 1) ** (occ + 4)) for (s, occ) in counter.items() if occ > 4), - key=lambda x: x[1], - reverse=True, + ((s, -est_net_savings(s, occ)) for (s, occ) in counter.items()), key=lambda x: x[1] ) # Pick the one with the highest score. From 8836198ff1d03254f8630703e0c8c941c0f733b7 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 3 Feb 2021 17:18:47 -0600 Subject: [PATCH 48/52] TextSplitter: don't mutate 'words' I was puzzled by why the dictionary words were sorted by length. It was because TextSplitter sorted its parameter, instead of a copy. This doesn't affect encoding size, but does affect the encoding NUMBER of the found words. We'll deliberately restore sorting by length next, for other reasons, but not by spooky action. --- py/makeqstrdata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index dc004d2df3..bbd298e931 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -280,7 +280,7 @@ def translate(translation_file, i18ns): class TextSplitter: def __init__(self, words): - words.sort(key=lambda x: len(x), reverse=True) + words = sorted(words, key=lambda x: len(x), reverse=True) self.words = set(words) if words: pat = "|".join(re.escape(w) for w in words) + "|." From 52e75c645d614379fd7ea404cb00b40e9fc30b59 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Jul 2021 14:16:14 -0500 Subject: [PATCH 49/52] makeqstrdata: Don't include strings that are a net loss! --- py/makeqstrdata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index bbd298e931..9073fc5667 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -390,8 +390,8 @@ def compute_huffman_coding(translations, compression_filename): ((s, -est_net_savings(s, occ)) for (s, occ) in counter.items()), key=lambda x: x[1] ) - # Pick the one with the highest score. - if not scores: + # Pick the one with the highest score. The score must be negative. + if not scores or scores[0][-1] >= 0: break word = scores[0][0] From 25e799e51a7448abb4ca78e85a7e1bec333ab784 Mon Sep 17 00:00:00 2001 From: DavePutz Date: Fri, 9 Jul 2021 20:49:59 -0500 Subject: [PATCH 50/52] Add LED and GP25 for Cytron Maker Pi Pico --- ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c b/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c index 5229642670..869cad17d3 100644 --- a/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c +++ b/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c @@ -40,6 +40,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_GPIO22) }, { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, From fd4a7fce91ea26b2b1014e509a7bfc5c3402aaa0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 10 Jul 2021 19:11:47 -0500 Subject: [PATCH 51/52] add tool to parse out firmware sizes for comparison --- tools/fwsizes.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tools/fwsizes.py diff --git a/tools/fwsizes.py b/tools/fwsizes.py new file mode 100644 index 0000000000..64d1af8b00 --- /dev/null +++ b/tools/fwsizes.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# Run this from within an unzipped directory of build logs from github +# to get a CSV file full of firmware sizes. Super useful to compare sizes +# from various builds. +# Taken from https://github.com/adafruit/circuitpython/pull/4564#issuecomment-816655101 +import os, re + +for fn in os.listdir(): + if os.path.isfile(fn) and ("build-arm " in fn or "build-riscv " in fn): + board = re.split("[()]", fn)[1] + if board in ( + "spresense", + "teensy40", + "teensy41", + "feather_m7_1011", + "feather_mimxrt1011", + "feather_mimxrt1062", + "imxrt1010_evk", + "imxrt1020_evk", + "imxrt1060_evk", + "metro_m7_1011", + ): + continue + with open(fn, "r") as f: + head = "Build " + board + " for " + lines = iter(f) + for line in lines: + if head in line: + tr = line.split(head)[1].split()[0] + assert "make: Entering directory" in next(lines) + assert "Use make V=1, make V=2" in next(lines) + while re.search( + r"\{\}|QSTR updated|FREEZE|\{'sku':|hex\tfilename|boot2.elf|Including User C Module from|Font missing|section `.bss' type changed to PROGBITS", + next(lines), + ): + pass + free = next(lines).split("bytes used, ")[1].split()[0] + print(board + "," + tr + "," + free) From 0b8b16f6ac6d18fdbe1f61bd53428befa00879d8 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 11 Jul 2021 08:57:27 -0500 Subject: [PATCH 52/52] increase comment on accuracy of the net savings estimate function Thanks to tyomitch for suggesting the comment could be more accurate. --- py/makeqstrdata.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 9073fc5667..d2a10d29db 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -361,11 +361,26 @@ def compute_huffman_coding(translations, compression_filename): return lengths[idx][1] + 1 # The cost of adding a dictionary word is just its storage size - # while its savings is the difference between the original + # while its savings is close to the difference between the original # huffman bit-length of the string and the estimated bit-length # of the dictionary word, times the number of times the word appears. # - # The difference between the two is the net savings, in bits. + # The savings is not strictly accurate because including a word into + # the Huffman tree bumps up the encoding lengths of all words in the + # same subtree. In the extreme case when the new word is so frequent + # that it gets a one-bit encoding, all other words will cost an extra + # bit each. + # + # Another source of inaccuracy is that compressed strings end up + # on byte boundaries, not bit boundaries, so saving 1 bit somewhere + # might not save a byte. + # + # In fact, when this change was first made, some translations (luckily, + # ones on boards not at all close to full) wasted up to 40 bytes, + # while the most constrained boards typically gained 100 bytes or + # more. + # + # The difference between the two is the estimated net savings, in bits. def est_net_savings(s, occ): savings = occ * (bit_length(s) - est_len(occ)) cost = len(s) * bits_per_codepoint