summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.travis.yml30
m---------frozen/circuitpython-stage0
m---------lib/tinyusb0
-rw-r--r--locale/ID.po100
-rw-r--r--locale/circuitpython.pot98
-rw-r--r--locale/de_DE.po98
-rw-r--r--locale/en_US.po98
-rw-r--r--locale/en_x_pirate.po98
-rw-r--r--locale/es.po111
-rw-r--r--locale/fil.po98
-rw-r--r--locale/fr.po109
-rw-r--r--locale/it_IT.po104
-rw-r--r--locale/pl.po113
-rw-r--r--locale/pt_BR.po98
-rw-r--r--locale/zh_Latn_pinyin.po121
-rw-r--r--ports/atmel-samd/audio_dma.c30
-rw-r--r--ports/atmel-samd/audio_dma.h3
-rw-r--r--ports/atmel-samd/background.c2
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/board.c129
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h39
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk16
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/pins.c94
-rw-r--r--ports/atmel-samd/boards/snekboard/board.c38
-rw-r--r--ports/atmel-samd/boards/snekboard/mpconfigboard.h35
-rw-r--r--ports/atmel-samd/boards/snekboard/mpconfigboard.mk16
-rw-r--r--ports/atmel-samd/boards/snekboard/pins.c28
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/PDMIn.c8
-rw-r--r--ports/atmel-samd/common-hal/audioio/AudioOut.c8
-rw-r--r--ports/atmel-samd/common-hal/busio/UART.c8
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseOut.c4
-rw-r--r--ports/atmel-samd/common-hal/touchio/TouchIn.c4
-rw-r--r--ports/atmel-samd/mphalport.c4
-rwxr-xr-xports/nrf/Makefile3
-rw-r--r--ports/nrf/background.c7
-rw-r--r--ports/nrf/bluetooth/ble_uart.c8
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/board.c38
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h73
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk26
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/pins.c71
-rw-r--r--ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h2
-rw-r--r--ports/nrf/boards/make-pins.py208
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/board.c38
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h73
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk26
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/pins.c56
-rw-r--r--ports/nrf/boards/particle_argon/mpconfigboard.h2
-rw-r--r--ports/nrf/boards/particle_boron/mpconfigboard.h2
-rw-r--r--ports/nrf/boards/particle_xenon/mpconfigboard.h2
-rw-r--r--ports/nrf/common-hal/audiobusio/I2SOut.c70
-rw-r--r--ports/nrf/common-hal/audiobusio/I2SOut.h36
-rw-r--r--ports/nrf/common-hal/audiobusio/PDMIn.c130
-rw-r--r--ports/nrf/common-hal/audiobusio/PDMIn.h40
-rw-r--r--ports/nrf/common-hal/audiobusio/__init__.c0
-rw-r--r--ports/nrf/common-hal/audiopwmio/PWMAudioOut.c316
-rw-r--r--ports/nrf/common-hal/audiopwmio/PWMAudioOut.h59
-rw-r--r--ports/nrf/common-hal/audiopwmio/__init__.c0
-rw-r--r--ports/nrf/common-hal/bleio/Adapter.c41
-rw-r--r--ports/nrf/common-hal/bleio/Attribute.c60
-rw-r--r--ports/nrf/common-hal/bleio/Attribute.h32
-rw-r--r--ports/nrf/common-hal/bleio/Central.c346
-rw-r--r--ports/nrf/common-hal/bleio/Central.h5
-rw-r--r--ports/nrf/common-hal/bleio/Characteristic.c270
-rw-r--r--ports/nrf/common-hal/bleio/Characteristic.h10
-rw-r--r--ports/nrf/common-hal/bleio/CharacteristicBuffer.c4
-rw-r--r--ports/nrf/common-hal/bleio/Descriptor.c111
-rw-r--r--ports/nrf/common-hal/bleio/Descriptor.h11
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.c106
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.h15
-rw-r--r--ports/nrf/common-hal/bleio/Service.c101
-rw-r--r--ports/nrf/common-hal/bleio/Service.h2
-rw-r--r--ports/nrf/common-hal/bleio/__init__.c451
-rw-r--r--ports/nrf/common-hal/bleio/__init__.h8
-rw-r--r--ports/nrf/common-hal/busio/UART.c12
-rw-r--r--ports/nrf/common-hal/microcontroller/__init__.c9
-rw-r--r--ports/nrf/common-hal/neopixel_write/__init__.c4
-rw-r--r--ports/nrf/common-hal/pulseio/PWMOut.c113
-rw-r--r--ports/nrf/common-hal/pulseio/PWMOut.h3
-rw-r--r--ports/nrf/common-hal/pulseio/PulseOut.c4
-rw-r--r--ports/nrf/device/nrf52/startup_nrf52840.c2
-rw-r--r--ports/nrf/mpconfigport.mk8
-rw-r--r--ports/nrf/mphalport.c4
-rw-r--r--ports/nrf/nrfx_config.h1
-rw-r--r--ports/nrf/peripherals/nrf/timers.c2
-rw-r--r--ports/nrf/sd_mutex.c4
-rw-r--r--ports/nrf/supervisor/port.c8
-rw-r--r--py/circuitpy_defns.mk17
-rw-r--r--py/circuitpy_mpconfig.h21
-rw-r--r--py/circuitpy_mpconfig.mk9
-rw-r--r--py/makeqstrdata.py4
-rw-r--r--py/obj.h1
-rw-r--r--py/objlist.c5
-rw-r--r--py/objstr.c6
-rw-r--r--py/objstr.h3
-rw-r--r--py/objtuple.c3
-rw-r--r--shared-bindings/_stage/__init__.c18
-rw-r--r--shared-bindings/audiobusio/I2SOut.c9
-rw-r--r--shared-bindings/audiocore/Mixer.c2
-rw-r--r--shared-bindings/audiocore/RawSample.c5
-rw-r--r--shared-bindings/audiocore/WaveFile.c28
-rw-r--r--shared-bindings/audiocore/WaveFile.h2
-rw-r--r--shared-bindings/audioio/AudioOut.c7
-rw-r--r--shared-bindings/audiopwmio/PWMAudioOut.c294
-rw-r--r--shared-bindings/audiopwmio/PWMAudioOut.h49
-rw-r--r--shared-bindings/audiopwmio/__init__.c71
-rw-r--r--shared-bindings/audiopwmio/__init__.h34
-rw-r--r--shared-bindings/bleio/Adapter.c36
-rw-r--r--shared-bindings/bleio/Adapter.h3
-rw-r--r--shared-bindings/bleio/Address.c47
-rw-r--r--shared-bindings/bleio/Attribute.c94
-rw-r--r--shared-bindings/bleio/Attribute.h38
-rw-r--r--shared-bindings/bleio/Central.c98
-rw-r--r--shared-bindings/bleio/Central.h5
-rw-r--r--shared-bindings/bleio/Characteristic.c265
-rw-r--r--shared-bindings/bleio/Characteristic.h4
-rw-r--r--shared-bindings/bleio/Descriptor.c145
-rw-r--r--shared-bindings/bleio/Descriptor.h27
-rw-r--r--shared-bindings/bleio/Peripheral.c102
-rw-r--r--shared-bindings/bleio/Peripheral.h5
-rw-r--r--shared-bindings/bleio/Service.c25
-rw-r--r--shared-bindings/bleio/Service.h1
-rw-r--r--shared-bindings/bleio/__init__.c38
-rw-r--r--shared-bindings/bleio/__init__.h16
-rw-r--r--shared-bindings/displayio/FourWire.c4
-rw-r--r--shared-bindings/displayio/I2CDisplay.c4
-rw-r--r--shared-bindings/displayio/ParallelBus.c4
-rw-r--r--shared-bindings/displayio/TileGrid.c7
-rw-r--r--shared-bindings/displayio/TileGrid.h3
-rw-r--r--shared-bindings/i2cslave/I2CSlave.c6
-rw-r--r--shared-bindings/time/__init__.c35
-rw-r--r--shared-module/_stage/__init__.c37
-rw-r--r--shared-module/_stage/__init__.h2
-rw-r--r--shared-module/audiocore/WaveFile.c33
-rw-r--r--shared-module/audiocore/WaveFile.h1
-rw-r--r--shared-module/audiopwmio/__init__.c0
-rw-r--r--shared-module/audiopwmio/__init__.h (renamed from shared-module/bleio/__init__.h)14
-rw-r--r--shared-module/bleio/Attribute.c46
-rw-r--r--shared-module/bleio/Attribute.h41
-rw-r--r--shared-module/bleio/Characteristic.h21
-rw-r--r--shared-module/board/__init__.c29
-rw-r--r--shared-module/displayio/Bitmap.c38
-rw-r--r--shared-module/displayio/Bitmap.h5
-rw-r--r--shared-module/displayio/Display.c25
-rw-r--r--shared-module/displayio/TileGrid.c32
-rw-r--r--shared-module/displayio/TileGrid.h3
-rw-r--r--shared-module/displayio/__init__.c6
-rw-r--r--shared-module/terminalio/Terminal.c6
-rw-r--r--shared-module/usb_hid/Device.c6
-rw-r--r--supervisor/shared/display.h3
-rw-r--r--supervisor/shared/usb/usb.c5
-rw-r--r--tools/check_translations.py4
-rw-r--r--tools/gen_display_resources.py3
151 files changed, 5090 insertions, 1645 deletions
diff --git a/.travis.yml b/.travis.yml
index 44369ddfe..9a058aa64 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,20 +12,32 @@ git:
# pip packages, and so forth. By gathering activities together in optimal
# ways, the "run time" and "total time" of the travis jobs can be minimized.
#
-# Since at the time of writing Travis generally starts 5 or 6 jobs, the
-# builds have been organized into 5 groups of *approximately* equal durations.
-# Additionally, the jobs that need extra SDKs are also organized together.
+# Builds are organized so some will complete quickly, and others are of
+# approximately equal size. Try not to freeze out other Travis users.
+#
+# Board names are in alphabetical order for easy finding, but grouped by
+# Adafruit/modified-Adafruit and Other. Ideally they'd be separated into
+# separate jobs, but there are too many.
#
# When adding new boards, take a look on the travis CI page
# https://travis-ci.org/adafruit/circuitpython to which build that installs
# that SDK is shortest and add it there. In the case of major re-organizations,
# just try to make the builds "about equal in run time"
env:
- - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="trinket_m0_haxpress circuitplayground_express mini_sam_m4 grandcentral_m4_express capablerobot_usbhub pygamer pca10056 pca10059 feather_nrf52840_express makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini electronut_labs_papyr electronut_labs_blip" TRAVIS_SDK=arm:nrf
- - TRAVIS_BOARDS="metro_m0_express metro_m4_express metro_m4_airlift_lite pirkey_m0 trellis_m4_express trinket_m0 sparkfun_lumidrive sparkfun_redboard_turbo bast_pro_mini_m0 datum_distance pyruler" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="cp32-m4 feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow sam32 uchip escornabot_makech pygamer_advance datum_imu" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="feather_m0_supersized feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300 arduino_mkrzero pewpew10 kicksat-sprite ugame10 robohatmm1_m0 robohatmm1_m4 datum_light" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="datalore_ip_m4 circuitplayground_express_crickit feather_m0_adalogger feather_m0_basic feather_m0_express catwan_usbstick pyportal sparkfun_samd21_mini sparkfun_samd21_dev pybadge pybadge_airlift datum_weather" TRAVIS_SDK=arm
+ # Non-board tasks
+ - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS=""
+ # Adafruit and Nordic nRF boards
+ - TRAVIS_BOARDS="circuitplayground_bluefruit feather_nrf52840_express metro_nrf52840_express pca10056 pca10059" TRAVIS_SDK=arm
+ # Other nRF boards
+ - TRAVIS_BOARDS="electronut_labs_blip electronut_labs_papyr makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_argon particle_boron particle_xenon sparkfun_nrf52840_mini" TRAVIS_SDK=arm
+ # Adafruit and modified Adafruit SAMD21 (M0) + Other SAMD21 (M0)
+ - TRAVIS_BOARDS="circuitplayground_express circuitplayground_express_crickit feather_m0_adalogger feather_m0_basic feather_m0_express feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m0_supersized feather_radiofruit_zigbee gemma_m0 hallowing_m0_express " TRAVIS_SDK=arm
+ - TRAVIS_BOARDS="itsybitsy_m0_express metro_m0_express pirkey_m0 pyruler trinket_m0 trinket_m0_haxpress arduino_mkr1300 arduino_mkrzero arduino_zero bast_pro_mini_m0 catwan_usbstick datum_distance datum_imu datum_weather" TRAVIS_SDK=arm
+ - TRAVIS_BOARDS="escornabot_makech meowmeow pewpew10 robohatmm1_m0 snekboard sparkfun_lumidrive sparkfun_redboard_turbo sparkfun_samd21_dev sparkfun_samd21_mini uchip ugame10" TRAVIS_SDK=arm
+ # Adafruit SAMD51 (M4) + Other SAMD51
+ - TRAVIS_BOARDS="feather_m4_express grandcentral_m4_express itsybitsy_m4_express metro_m4_airlift_lite metro_m4_express pybadge pybadge_airlift pygamer pygamer_advance" TRAVIS_SDK=arm
+ - TRAVIS_BOARDS="pyportal pyportal_titano trellis_m4_express capablerobot_usbhub cp32-m4 datalore_ip_m4 datum_light kicksat-sprite mini_sam_m4 robohatmm1_m4 sam32" TRAVIS_SDK=arm
+
addons:
artifacts:
@@ -88,7 +100,7 @@ before_script:
# Check if there's any board missing in TRAVIS_BOARDS
- cd tools && python3 -u travis_new_boards_check.py
- cd ..
-
+
# report some good version numbers to the build
- gcc --version
- (! var_search "${TRAVIS_SDK-}" arm || arm-none-eabi-gcc --version)
diff --git a/frozen/circuitpython-stage b/frozen/circuitpython-stage
-Subproject 6d1ae72916cf240ea86185c45f844d59f56d8ec
+Subproject 0d2d660e886de8a1b96778c865c7fa48df5f4ea
diff --git a/lib/tinyusb b/lib/tinyusb
-Subproject 1ee9ef4f2b7c6acfab6c398a4f57ca22036958f
+Subproject 96d96a94b887bc1b648a175c28b377dba76a906
diff --git a/locale/ID.po b/locale/ID.po
index bd12a5c94..a4ca0124d 100644
--- a/locale/ID.po
+++ b/locale/ID.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -255,6 +255,7 @@ msgstr "Semua timer untuk pin ini sedang digunakan"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -329,6 +330,11 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -358,7 +364,7 @@ msgid "Can not use dotstar with %s"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -427,6 +433,10 @@ msgstr ""
msgid "Characteristic already in use by another Service."
msgstr ""
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -502,6 +512,10 @@ msgstr ""
msgid "Data too large for advertisement packet"
msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr ""
@@ -596,7 +610,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Gagal untuk menemukan layanan, status: 0x%08lX"
@@ -616,17 +630,22 @@ msgstr "Gagal untuk mendapatkan status softdevice, error: 0x%08lX"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Gagal untuk membaca nilai atribut, status: 0x%08lX"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX"
@@ -656,6 +675,11 @@ msgstr "Gagal untuk memulai advertisement, status: 0x%08lX"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -671,12 +695,12 @@ msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Gagal untuk menulis nilai atribut, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX"
@@ -822,10 +846,18 @@ msgstr "Pin-pin tidak valid"
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr ""
@@ -944,13 +976,15 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Tidak dapat menyambungkan ke AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -1080,6 +1114,7 @@ msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d"
@@ -1099,7 +1134,7 @@ msgid "Slices not supported"
msgstr ""
#: ports/nrf/common-hal/bleio/Adapter.c
-#, c-format
+#, fuzzy, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l"
@@ -1168,7 +1203,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1277,6 +1316,19 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1376,10 +1428,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "mode compile buruk"
@@ -1697,6 +1745,10 @@ msgstr ""
msgid "default 'except' must be last"
msgstr "'except' standar harus terakhir"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2036,6 +2088,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2135,8 +2193,8 @@ msgstr ""
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2222,6 +2280,14 @@ msgstr "panjang data string memiliki keganjilan (odd-length)"
msgid "offset out of bounds"
msgstr "modul tidak ditemukan"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2445,10 +2511,6 @@ msgstr "sintaksis error pada pendeskripsi uctypes"
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 1b135822f..d0a5646e0 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -253,6 +253,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -325,6 +326,11 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -353,7 +359,7 @@ msgid "Can not use dotstar with %s"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -417,6 +423,10 @@ msgstr ""
msgid "Characteristic already in use by another Service."
msgstr ""
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -491,6 +501,10 @@ msgstr ""
msgid "Data too large for advertisement packet"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr ""
@@ -584,7 +598,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
msgid "Failed to discover services"
msgstr ""
@@ -601,17 +615,22 @@ msgstr ""
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr ""
@@ -641,6 +660,11 @@ msgstr ""
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -656,12 +680,12 @@ msgstr ""
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr ""
@@ -807,10 +831,18 @@ msgstr ""
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr ""
@@ -929,12 +961,14 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr ""
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -1060,6 +1094,7 @@ msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1145,7 +1180,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1253,6 +1292,19 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1343,10 +1395,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1663,6 +1711,10 @@ msgstr ""
msgid "default 'except' must be last"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2002,6 +2054,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2100,8 +2158,8 @@ msgstr ""
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2186,6 +2244,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2409,10 +2475,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 7ad69e1dd..6c932572d 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Pascal Deneaux\n"
"Language-Team: Sebastian Plamauer, Pascal Deneaux\n"
@@ -255,6 +255,7 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -329,6 +330,11 @@ msgstr "Die Helligkeit ist nicht einstellbar"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Der Puffergröße ist inkorrekt. Sie sollte %d bytes haben."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Der Puffer muss eine Mindestenslänge von 1 haben"
@@ -357,7 +363,7 @@ msgid "Can not use dotstar with %s"
msgstr "Kann dotstar nicht mit %s verwenden"
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -421,6 +427,10 @@ msgstr "Characteristic UUID stimmt nicht mit der Service-UUID überein"
msgid "Characteristic already in use by another Service."
msgstr "Characteristic wird bereits von einem anderen Dienst verwendet."
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Schreiben von CharacteristicBuffer ist nicht vorgesehen"
@@ -495,6 +505,10 @@ msgstr ""
msgid "Data too large for advertisement packet"
msgstr "Zu vielen Daten für das advertisement packet"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr "Die Zielkapazität ist kleiner als destination_length."
@@ -588,7 +602,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
msgid "Failed to discover services"
msgstr "Es konnten keine Dienste gefunden werden"
@@ -605,17 +619,22 @@ msgstr "Fehler beim Abrufen des Softdevice-Status"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Kann CCCD value nicht lesen. Status: 0x%04x"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "gatts value konnte nicht gelesen werden. Status: 0x%04x"
@@ -645,6 +664,11 @@ msgstr "Kann advertisement nicht starten. Status: 0x%04x"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -660,12 +684,12 @@ msgstr "Kann advertisement nicht stoppen. Status: 0x%04x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Kann den Attributwert nicht schreiben. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "gatts value konnte nicht geschrieben werden. Status: 0x%04x"
@@ -813,10 +837,18 @@ msgstr "Ungültige Pins"
msgid "Invalid polarity"
msgstr "Ungültige Polarität"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Ungültiger Ausführungsmodus"
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr "Ungültige Anzahl von Stimmen"
@@ -942,12 +974,14 @@ msgstr "Kein Speicherplatz auf Gerät"
msgid "No such file/directory"
msgstr "Keine solche Datei/Verzeichnis"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr "Nicht verbunden"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Spielt nicht"
@@ -1077,6 +1111,7 @@ msgid "Sample rate must be positive"
msgstr "Abtastrate muss positiv sein"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Abtastrate zu hoch. Wert muss unter %d liegen"
@@ -1174,7 +1209,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1284,6 +1323,19 @@ msgstr "Nicht unterstützte Operation"
msgid "Unsupported pull value."
msgstr "Nicht unterstützter Pull-Wert"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Viper-Funktionen unterstützen derzeit nicht mehr als 4 Argumente"
@@ -1383,10 +1435,6 @@ msgstr "Array/Bytes auf der rechten Seite erforderlich"
msgid "attributes not supported yet"
msgstr "Attribute werden noch nicht unterstützt"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1703,6 +1751,10 @@ msgstr ""
msgid "default 'except' must be last"
msgstr "Die Standart-Ausnahmebehandlung muss als letztes sein"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2049,6 +2101,12 @@ msgstr "map buffer zu klein"
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "maximale Rekursionstiefe überschritten"
@@ -2147,8 +2205,8 @@ msgstr ""
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2233,6 +2291,14 @@ msgstr "String mit ungerader Länge"
msgid "offset out of bounds"
msgstr "offset außerhalb der Grenzen"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2461,10 +2527,6 @@ msgstr "Syntaxfehler in uctypes Deskriptor"
msgid "threshold must be in the range 0-65536"
msgstr "threshold muss im Intervall 0-65536 liegen"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
diff --git a/locale/en_US.po b/locale/en_US.po
index 49699283c..46e719637 100644
--- a/locale/en_US.po
+++ b/locale/en_US.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -253,6 +253,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -325,6 +326,11 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -353,7 +359,7 @@ msgid "Can not use dotstar with %s"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -417,6 +423,10 @@ msgstr ""
msgid "Characteristic already in use by another Service."
msgstr ""
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -491,6 +501,10 @@ msgstr ""
msgid "Data too large for advertisement packet"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr ""
@@ -584,7 +598,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
msgid "Failed to discover services"
msgstr ""
@@ -601,17 +615,22 @@ msgstr ""
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr ""
@@ -641,6 +660,11 @@ msgstr ""
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -656,12 +680,12 @@ msgstr ""
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr ""
@@ -807,10 +831,18 @@ msgstr ""
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr ""
@@ -929,12 +961,14 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr ""
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -1060,6 +1094,7 @@ msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1145,7 +1180,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1253,6 +1292,19 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1343,10 +1395,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1663,6 +1711,10 @@ msgstr ""
msgid "default 'except' must be last"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2002,6 +2054,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2100,8 +2158,8 @@ msgstr ""
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2186,6 +2244,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2409,10 +2475,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po
index 885abe681..55b907023 100644
--- a/locale/en_x_pirate.po
+++ b/locale/en_x_pirate.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: @sommersoft, @MrCertainly\n"
@@ -255,6 +255,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -329,6 +330,11 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -357,7 +363,7 @@ msgid "Can not use dotstar with %s"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -421,6 +427,10 @@ msgstr ""
msgid "Characteristic already in use by another Service."
msgstr ""
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -495,6 +505,10 @@ msgstr ""
msgid "Data too large for advertisement packet"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr ""
@@ -588,7 +602,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
msgid "Failed to discover services"
msgstr ""
@@ -605,17 +619,22 @@ msgstr ""
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr ""
@@ -645,6 +664,11 @@ msgstr ""
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -660,12 +684,12 @@ msgstr ""
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr ""
@@ -811,10 +835,18 @@ msgstr ""
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr ""
@@ -933,12 +965,14 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr ""
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -1064,6 +1098,7 @@ msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1149,7 +1184,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1257,6 +1296,19 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1347,10 +1399,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1667,6 +1715,10 @@ msgstr ""
msgid "default 'except' must be last"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2006,6 +2058,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2104,8 +2162,8 @@ msgstr ""
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2190,6 +2248,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2413,10 +2479,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index 772570a31..62d9da9d6 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -257,6 +257,7 @@ msgstr "Todos los timers para este pin están siendo utilizados"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -333,6 +334,11 @@ msgstr "El brillo no se puede ajustar"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Tamaño de buffer incorrecto. Debe ser de %d bytes."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Buffer debe ser de longitud 1 como minimo"
@@ -361,7 +367,7 @@ msgid "Can not use dotstar with %s"
msgstr "No se puede usar dotstar con %s"
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -425,6 +431,10 @@ msgstr "Características UUID no concide con el Service UUID"
msgid "Characteristic already in use by another Service."
msgstr "Características ya esta en uso por otro Serivice"
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "CharateristicBuffer escritura no proporcionada"
@@ -499,6 +509,10 @@ msgstr "Trozo de datos debe seguir fmt chunk"
msgid "Data too large for advertisement packet"
msgstr "Data es muy grande para el paquete de advertisement."
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr "Capacidad de destino es mas pequeña que destination_length."
@@ -592,7 +606,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "No se puede iniciar el escaneo. err: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "No se puede descubrir servicios"
@@ -610,17 +624,22 @@ msgstr "No se puede obtener el estado del softdevice"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Error al notificar o indicar el valor del atributo, err 0x%04x"
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "No se puede leer el valor del atributo. err 0x%02x"
#: ports/nrf/common-hal/bleio/Characteristic.c
-#, c-format
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, fuzzy, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Error al leer valor del atributo, err 0x%04"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "No se puede escribir el valor del atributo. status: 0x%02x"
@@ -650,6 +669,11 @@ msgstr "No se puede inicar el anuncio. err: 0x%04x"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -665,12 +689,12 @@ msgstr "No se puede detener el anuncio. err: 0x%04x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "No se puede escribir el valor del atributo. err: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "No se puede escribir el valor del atributo. err: 0x%04x"
@@ -818,10 +842,18 @@ msgstr "pines inválidos"
msgid "Invalid polarity"
msgstr "Polaridad inválida"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Modo de ejecución inválido."
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr "Cuenta de voces inválida"
@@ -944,12 +976,14 @@ msgstr "No queda espacio en el dispositivo"
msgid "No such file/directory"
msgstr "No existe el archivo/directorio"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr "No conectado"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "No reproduciendo"
@@ -1088,6 +1122,7 @@ msgid "Sample rate must be positive"
msgstr "Sample rate debe ser positivo"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d"
@@ -1185,8 +1220,12 @@ msgid "Tile height must exactly divide bitmap height"
msgstr "La altura del Tile debe dividir exacto la altura del bitmap"
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Los índices de Tile deben ser 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1294,6 +1333,19 @@ msgstr "Operación no soportada"
msgid "Unsupported pull value."
msgstr "valor pull no soportado."
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "funciones Viper actualmente no soportan más de 4 argumentos."
@@ -1392,10 +1444,6 @@ msgstr "array/bytes requeridos en el lado derecho"
msgid "attributes not supported yet"
msgstr "atributos aún no soportados"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "mal GATT role"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "modo de compilación erroneo"
@@ -1717,6 +1765,10 @@ msgstr "números decimales no soportados"
msgid "default 'except' must be last"
msgstr "'except' por defecto deberia estar de último"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2061,6 +2113,12 @@ msgstr "map buffer muy pequeño"
msgid "math domain error"
msgstr "error de dominio matemático"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "profundidad máxima de recursión excedida"
@@ -2159,8 +2217,8 @@ msgstr "no hay tal atributo"
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2249,6 +2307,14 @@ msgstr "string de longitud impar"
msgid "offset out of bounds"
msgstr "address fuera de límites"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2476,10 +2542,6 @@ msgstr "error de sintaxis en el descriptor uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "limite debe ser en el rango 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "el indice del tile fuera de limite"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() toma un sequencio 9"
@@ -2836,6 +2898,9 @@ msgstr "paso cero"
#~ msgid "STA required"
#~ msgstr "STA requerido"
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Los índices de Tile deben ser 0 - 255"
+
#~ msgid "UART(%d) does not exist"
#~ msgstr "UART(%d) no existe"
@@ -2855,6 +2920,9 @@ msgstr "paso cero"
#~ msgstr ""
#~ "Usa esptool para borrar la flash y vuelve a cargar Python en su lugar"
+#~ msgid "bad GATT role"
+#~ msgstr "mal GATT role"
+
#~ msgid "buffer too long"
#~ msgstr "buffer demasiado largo"
@@ -2937,6 +3005,9 @@ msgstr "paso cero"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "services incluye un objeto que no es servicio"
+#~ msgid "tile index out of bounds"
+#~ msgstr "el indice del tile fuera de limite"
+
#~ msgid "too many arguments"
#~ msgstr "muchos argumentos"
diff --git a/locale/fil.po b/locale/fil.po
index 8e4dbd9fd..f585372d2 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-12-20 22:15-0800\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n"
@@ -257,6 +257,7 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -331,6 +332,11 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Mali ang size ng buffer. Dapat %d bytes."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Buffer dapat ay hindi baba sa 1 na haba"
@@ -360,7 +366,7 @@ msgid "Can not use dotstar with %s"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -425,6 +431,10 @@ msgstr ""
msgid "Characteristic already in use by another Service."
msgstr ""
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -502,6 +512,10 @@ msgstr "Dapat sunurin ng Data chunk ang fmt chunk"
msgid "Data too large for advertisement packet"
msgstr "Hindi makasya ang data sa loob ng advertisement packet"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr ""
@@ -599,7 +613,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Nabigo sa pagdiscover ng services, status: 0x%08lX"
@@ -619,17 +633,22 @@ msgstr "Nabigo sa pagkuha ng softdevice state, error: 0x%08lX"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Hindi mabasa ang value ng attribute, status: 0x%08lX"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Hindi maisulat ang gatts value, status: 0x%08lX"
@@ -659,6 +678,11 @@ msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -674,12 +698,12 @@ msgstr "Hindi mahinto ang advertisement, status: 0x%08lX"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Hindi maisulat ang attribute value, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Hindi maisulat ang gatts value, status: 0x%08lX"
@@ -827,10 +851,18 @@ msgstr "Mali ang pins"
msgid "Invalid polarity"
msgstr "Mali ang polarity"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Mali ang run mode."
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr "Maling bilang ng voice"
@@ -953,13 +985,15 @@ msgstr ""
msgid "No such file/directory"
msgstr "Walang file/directory"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Hindi maka connect sa AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Hindi playing"
@@ -1093,6 +1127,7 @@ msgid "Sample rate must be positive"
msgstr "Sample rate ay dapat positibo"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Sample rate ay masyadong mataas. Ito ay dapat hindi hiigit sa %d"
@@ -1188,7 +1223,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1298,6 +1337,19 @@ msgstr "Hindi sinusuportahang operasyon"
msgid "Unsupported pull value."
msgstr "Hindi suportado ang pull value."
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1396,10 +1448,6 @@ msgstr "array/bytes kinakailangan sa kanang bahagi"
msgid "attributes not supported yet"
msgstr "attributes hindi sinusuportahan"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "masamang mode ng compile"
@@ -1723,6 +1771,10 @@ msgstr "decimal numbers hindi sinusuportahan"
msgid "default 'except' must be last"
msgstr "default 'except' ay dapat sa huli"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2072,6 +2124,12 @@ msgstr "masyadong maliit ang buffer map"
msgid "math domain error"
msgstr "may pagkakamali sa math domain"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "lumagpas ang maximum recursion depth"
@@ -2171,8 +2229,8 @@ msgstr "walang ganoon na attribute"
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2258,6 +2316,14 @@ msgstr "odd-length string"
msgid "offset out of bounds"
msgstr "wala sa sakop ang address"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2486,10 +2552,6 @@ msgstr "may pagkakamali sa sintaks sa uctypes descriptor"
msgid "threshold must be in the range 0-65536"
msgstr "ang threshold ay dapat sa range 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() kumukuha ng 9-sequence"
diff --git a/locale/fr.po b/locale/fr.po
index 5bb51b622..5308d1be0 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2019-04-14 20:05+0100\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -260,6 +260,7 @@ msgstr "Tous les timers pour cette broche sont utilisés"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -336,6 +337,11 @@ msgstr "Luminosité non-ajustable"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Tampon de taille incorrect. Devrait être de %d octets."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Le tampon doit être de longueur au moins 1"
@@ -365,7 +371,7 @@ msgid "Can not use dotstar with %s"
msgstr "Impossible d'utiliser 'dotstar' avec %s"
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -431,6 +437,10 @@ msgstr "L'UUID de 'Characteristic' ne correspond pas à l'UUID du Service"
msgid "Characteristic already in use by another Service."
msgstr "'Characteristic' déjà en utilisation par un autre service"
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Ecriture sur 'CharacteristicBuffer' non fournie"
@@ -507,6 +517,10 @@ msgstr "Un bloc de données doit suivre un bloc de format"
msgid "Data too large for advertisement packet"
msgstr "Données trop volumineuses pour un paquet de diffusion"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr "La capacité de destination est plus petite que 'destination_length'."
@@ -603,7 +617,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Impossible de poursuivre le scan, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Echec de la découverte de services"
@@ -624,17 +638,22 @@ msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
"Impossible de notifier ou d'indiquer la valeur de l'attribut, err 0x%04x"
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Impossible de lire la valeur 'CCCD', err 0x%04x"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Impossible de lire la valeur de l'attribut, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Impossible de lire la valeur de 'gatts', err 0x%04x"
@@ -664,6 +683,11 @@ msgstr "Impossible de commencer à diffuser, err 0x%04x"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -679,12 +703,12 @@ msgstr "Echec de l'arrêt de diffusion, err 0x%04x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Impossible d'écrire la valeur de l'attribut, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Impossible d'écrire la valeur de 'gatts', err 0x%04x"
@@ -835,10 +859,18 @@ msgstr "Broches invalides"
msgid "Invalid polarity"
msgstr "Polarité invalide"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Mode de lancement invalide."
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
#, fuzzy
msgid "Invalid voice count"
@@ -962,13 +994,15 @@ msgstr "Il n'y a plus d'espace libre sur le périphérique"
msgid "No such file/directory"
msgstr "Fichier/dossier introuvable"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Non connecté"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Ne joue pas"
@@ -1110,6 +1144,7 @@ msgid "Sample rate must be positive"
msgstr "Le taux d'échantillonage doit être positif"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Taux d'échantillonage trop élevé. Doit être inf. à %d"
@@ -1209,8 +1244,12 @@ msgid "Tile height must exactly divide bitmap height"
msgstr "La hauteur de la tuile doit diviser exactement la hauteur de l'image"
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Les indices des tuiles doivent être compris entre 0 et 255 "
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1323,6 +1362,19 @@ msgstr "Opération non supportée"
msgid "Unsupported pull value."
msgstr "Valeur de tirage 'pull' non supportée."
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1421,10 +1473,6 @@ msgstr "tableau/octets requis à droite"
msgid "attributes not supported yet"
msgstr "attribut pas encore supporté"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "mauvais rôle GATT"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "mauvais mode de compilation"
@@ -1759,6 +1807,10 @@ msgstr "nombres décimaux non supportés"
msgid "default 'except' must be last"
msgstr "l''except' par défaut doit être en dernier"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2105,6 +2157,12 @@ msgstr "tampon trop petit"
msgid "math domain error"
msgstr "erreur de domaine math"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "profondeur maximale de récursivité dépassée"
@@ -2205,8 +2263,8 @@ msgstr "pas de tel attribut"
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2294,6 +2352,14 @@ msgstr "chaîne de longueur impaire"
msgid "offset out of bounds"
msgstr "adresse hors limites"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2528,10 +2594,6 @@ msgstr "erreur de syntaxe dans le descripteur d'uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "le seuil doit être dans la gamme 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "indice de tuile hors limites"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() prend une séquence de longueur 9"
@@ -2887,6 +2949,9 @@ msgstr "'step' nul"
#~ msgid "STA required"
#~ msgstr "'STA' requis"
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Les indices des tuiles doivent être compris entre 0 et 255 "
+
#~ msgid "UART(%d) does not exist"
#~ msgstr "UART(%d) n'existe pas"
@@ -2906,6 +2971,9 @@ msgstr "'step' nul"
#~ msgstr ""
#~ "Utilisez 'esptool' pour effacer la flash et recharger Python à la place"
+#~ msgid "bad GATT role"
+#~ msgstr "mauvais rôle GATT"
+
#~ msgid "buffer too long"
#~ msgstr "tampon trop long"
@@ -2983,6 +3051,9 @@ msgstr "'step' nul"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "'services' inclut un object qui n'est pas un 'Service'"
+#~ msgid "tile index out of bounds"
+#~ msgstr "indice de tuile hors limites"
+
#~ msgid "too many arguments"
#~ msgstr "trop d'arguments"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 2f8cfdc1e..8ab16aefb 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -112,7 +112,7 @@ msgid "'%s' expects {r0, r1, ...}"
msgstr "'%s' aspetta un registro"
#: py/emitinlinextensa.c
-#, c-format
+#, fuzzy, c-format
msgid "'%s' integer %d is not within range %d..%d"
msgstr "intero '%s' non è nell'intervallo %d..%d"
@@ -256,6 +256,7 @@ msgstr "Tutti i timer per questo pin sono in uso"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -331,6 +332,11 @@ msgstr "Illiminazione non è regolabile"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Buffer di lunghezza non valida. Dovrebbe essere di %d bytes."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Il buffer deve essere lungo almeno 1"
@@ -360,7 +366,7 @@ msgid "Can not use dotstar with %s"
msgstr "dotstar non può essere usato con %s"
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -426,6 +432,10 @@ msgstr "caratteristico UUID non assomiglia servizio UUID"
msgid "Characteristic already in use by another Service."
msgstr "caratteristico già usato da un altro servizio"
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "CharacteristicBuffer scritura non dato"
@@ -503,6 +513,10 @@ msgstr ""
msgid "Data too large for advertisement packet"
msgstr "Impossibile inserire dati nel pacchetto di advertisement."
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr "La capacità di destinazione è più piccola di destination_length."
@@ -599,7 +613,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Impossible iniziare la scansione. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
@@ -618,17 +632,22 @@ msgstr "Impossibile fermare advertisement. status: 0x%02x"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Notificamento o indicazione di attribute value fallito, err 0x%04x"
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Tentative leggere attribute value fallito, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
@@ -658,6 +677,11 @@ msgstr "Impossibile avviare advertisement. status: 0x%02x"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -673,12 +697,12 @@ msgstr "Impossibile fermare advertisement. status: 0x%02x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
@@ -828,10 +852,18 @@ msgstr "Pin non validi"
msgid "Invalid polarity"
msgstr "Polarità non valida"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Modalità di esecuzione non valida."
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
#, fuzzy
msgid "Invalid voice count"
@@ -952,13 +984,15 @@ msgstr "Non che spazio sul dispositivo"
msgid "No such file/directory"
msgstr "Nessun file/directory esistente"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Impossible connettersi all'AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "In pausa"
@@ -1098,6 +1132,7 @@ msgid "Sample rate must be positive"
msgstr "STA deve essere attiva"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1187,7 +1222,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1297,6 +1336,19 @@ msgstr "Operazione non supportata"
msgid "Unsupported pull value."
msgstr "Valore di pull non supportato."
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Le funzioni Viper non supportano più di 4 argomenti al momento"
@@ -1390,10 +1442,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr "attributi non ancora supportati"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1514,7 +1562,7 @@ msgid "can't assign to expression"
msgstr "impossibile assegnare all'espressione"
#: py/obj.c
-#, c-format
+#, fuzzy, c-format
msgid "can't convert %s to complex"
msgstr "non è possibile convertire a complex"
@@ -1716,6 +1764,10 @@ msgstr "numeri decimali non supportati"
msgid "default 'except' must be last"
msgstr "'except' predefinito deve essere ultimo"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2065,6 +2117,12 @@ msgstr "map buffer troppo piccolo"
msgid "math domain error"
msgstr "errore di dominio matematico"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "profondità massima di ricorsione superata"
@@ -2165,8 +2223,8 @@ msgstr "attributo inesistente"
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2254,6 +2312,14 @@ msgstr "stringa di lunghezza dispari"
msgid "offset out of bounds"
msgstr "indirizzo fuori limite"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2484,10 +2550,6 @@ msgstr "errore di sintassi nel descrittore uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "la soglia deve essere nell'intervallo 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2579,7 +2641,7 @@ msgid "unindent does not match any outer indentation level"
msgstr ""
#: py/objstr.c
-#, c-format
+#, fuzzy, c-format
msgid "unknown conversion specifier %c"
msgstr "specificatore di conversione %s sconosciuto"
diff --git a/locale/pl.po b/locale/pl.po
index 83e408a3d..8b1600200 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2019-03-19 18:37-0700\n"
"Last-Translator: Radomir Dopieralski <circuitpython@sheep.art.pl>\n"
"Language-Team: pl\n"
@@ -254,6 +254,7 @@ msgstr "Wszystkie timery tej nóżki w użyciu"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -328,6 +329,11 @@ msgstr "Jasność nie jest regulowana"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Zła wielkość bufora. Powinno być %d bajtów."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Bufor musi mieć długość 1 lub więcej"
@@ -356,7 +362,7 @@ msgid "Can not use dotstar with %s"
msgstr "Nie można używać dotstar z %s"
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -420,6 +426,10 @@ msgstr "UUID charakterystyki inny niż UUID serwisu"
msgid "Characteristic already in use by another Service."
msgstr "Charakterystyka w użyciu w innym serwisie"
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Pisanie do CharacteristicBuffer niewspierane"
@@ -494,6 +504,10 @@ msgstr "Fragment danych musi następować po fragmencie fmt"
msgid "Data too large for advertisement packet"
msgstr "Zbyt dużo danych pakietu rozgłoszeniowego"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr "Pojemność celu mniejsza od destination_length."
@@ -545,12 +559,12 @@ msgid "Failed sending command."
msgstr ""
#: ports/nrf/sd_mutex.c
-#, c-format
+#, fuzzy, c-format
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Nie udało się uzyskać blokady, błąd 0x$04x"
#: ports/nrf/common-hal/bleio/Service.c
-#, c-format
+#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Nie udało się dodać charakterystyki, błąd 0x$04x"
@@ -587,7 +601,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
msgid "Failed to discover services"
msgstr "Nie udało się odkryć serwisów"
@@ -604,17 +618,22 @@ msgstr "Nie udało się odczytać stanu softdevice"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Nie udało się powiadomić o wartości atrybutu, błąd 0x%04x"
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Nie udało się odczytać CCCD, błąd 0x%04x"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Nie udało się odczytać wartości atrybutu, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Nie udało się odczytać gatts, błąd 0x%04x"
@@ -644,6 +663,11 @@ msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -659,12 +683,12 @@ msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Nie udało się zapisać atrybutu, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Nie udało się zapisać gatts, błąd 0x%04x"
@@ -812,10 +836,18 @@ msgstr "Złe nóżki"
msgid "Invalid polarity"
msgstr "Zła polaryzacja"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Zły tryb uruchomienia"
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr "Zła liczba głosów"
@@ -939,12 +971,14 @@ msgstr "Brak miejsca"
msgid "No such file/directory"
msgstr "Brak pliku/katalogu"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr "Nie podłączono"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Nic nie jest odtwarzane"
@@ -1070,6 +1104,7 @@ msgid "Sample rate must be positive"
msgstr "Częstotliwość próbkowania musi być dodatnia"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Zbyt wysoka częstotliwość próbkowania. Musi być mniejsza niż %d"
@@ -1165,8 +1200,12 @@ msgid "Tile height must exactly divide bitmap height"
msgstr "Wysokość bitmapy musi być wielokrotnością wysokości kafelka"
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1273,6 +1312,19 @@ msgstr "Zła operacja"
msgid "Unsupported pull value."
msgstr "Zła wartość podciągnięcia."
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Funkcje Viper nie obsługują obecnie więcej niż 4 argumentów"
@@ -1367,10 +1419,6 @@ msgstr "tablica/bytes wymagane po prawej stronie"
msgid "attributes not supported yet"
msgstr "atrybuty nie są jeszcze obsługiwane"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "zła rola GATT"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "zły tryb kompilacji"
@@ -1687,6 +1735,10 @@ msgstr "liczby dziesiętne nieobsługiwane"
msgid "default 'except' must be last"
msgstr "domyślny 'except' musi być ostatni"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2027,6 +2079,12 @@ msgstr "bufor mapy zbyt mały"
msgid "math domain error"
msgstr "błąd domeny"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "przekroczono dozwoloną głębokość rekurencji"
@@ -2125,8 +2183,8 @@ msgstr "nie ma takiego atrybutu"
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2211,6 +2269,14 @@ msgstr "łańcuch o nieparzystej długości"
msgid "offset out of bounds"
msgstr "offset poza zakresem"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2436,10 +2502,6 @@ msgstr "błąd składni w deskryptorze uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "threshold musi być w zakresie 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "indeks kafelka poza zakresem"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() wymaga 9-elementowej sekwencji"
@@ -2694,11 +2756,20 @@ msgstr "zerowy krok"
#~ msgid "Must be a Group subclass."
#~ msgstr "Musi dziedziczyć z Group."
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie"
+
#~ msgid "UUID integer value not in range 0 to 0xffff"
#~ msgstr "Wartość UUID poza zakresem 0 do 0xffff"
+#~ msgid "bad GATT role"
+#~ msgstr "zła rola GATT"
+
#~ msgid "interval not in range 0.0020 to 10.24"
#~ msgstr "przedział poza zakresem 0.0020 do 10.24"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "obiekt typu innego niż Service w services"
+
+#~ msgid "tile index out of bounds"
+#~ msgstr "indeks kafelka poza zakresem"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index d3a8fe50a..0191a0d78 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2018-10-02 21:14-0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -256,6 +256,7 @@ msgstr "Todos os temporizadores para este pino estão em uso"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -328,6 +329,11 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Buffer de tamanho incorreto. Deve ser %d bytes."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -357,7 +363,7 @@ msgid "Can not use dotstar with %s"
msgstr ""
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -422,6 +428,10 @@ msgstr ""
msgid "Characteristic already in use by another Service."
msgstr ""
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -498,6 +508,10 @@ msgstr "Pedaço de dados deve seguir o pedaço de cortes"
msgid "Data too large for advertisement packet"
msgstr "Não é possível ajustar dados no pacote de anúncios."
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr ""
@@ -594,7 +608,7 @@ msgstr ""
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Não é possível iniciar o anúncio. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Não pode parar propaganda. status: 0x%02x"
@@ -613,17 +627,22 @@ msgstr "Não pode parar propaganda. status: 0x%02x"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Não é possível ler o valor do atributo. status: 0x%02x"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
@@ -653,6 +672,11 @@ msgstr "Não é possível iniciar o anúncio. status: 0x%02x"
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -668,12 +692,12 @@ msgstr "Não pode parar propaganda. status: 0x%02x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
@@ -821,10 +845,18 @@ msgstr "Pinos inválidos"
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
#, fuzzy
msgid "Invalid voice count"
@@ -944,13 +976,15 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Não é possível conectar-se ao AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -1080,6 +1114,7 @@ msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Taxa de amostragem muito alta. Deve ser menor que %d"
@@ -1165,7 +1200,11 @@ msgid "Tile height must exactly divide bitmap height"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1274,6 +1313,19 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
@@ -1364,10 +1416,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr "atributos ainda não suportados"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1687,6 +1735,10 @@ msgstr ""
msgid "default 'except' must be last"
msgstr ""
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2027,6 +2079,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2126,8 +2184,8 @@ msgstr ""
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2212,6 +2270,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2437,10 +2503,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr "Limite deve estar no alcance de 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index 055dd5461..15b57d281 100644
--- a/locale/zh_Latn_pinyin.po
+++ b/locale/zh_Latn_pinyin.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: circuitpython-cn\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-25 22:48-0700\n"
+"POT-Creation-Date: 2019-08-19 10:22-0400\n"
"PO-Revision-Date: 2019-04-13 10:10-0700\n"
"Last-Translator: hexthat\n"
"Language-Team: Chinese Hanyu Pinyin\n"
@@ -255,6 +255,7 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -329,6 +330,11 @@ msgstr "Liàngdù wúfǎ tiáozhěng"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Huǎnchōng qū dàxiǎo bù zhèngquè. Yīnggāi shì %d zì jié."
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Huǎnchōng qū bìxū zhìshǎo chángdù 1"
@@ -357,8 +363,8 @@ msgid "Can not use dotstar with %s"
msgstr "Wúfǎ yǔ dotstar yīqǐ shǐyòng %s"
#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
-msgstr "Wúfǎ wéi běndì tèzhēng shèzhì CCCD"
+msgid "Can't set CCCD on local Characteristic"
+msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
msgid "Cannot delete values"
@@ -421,6 +427,10 @@ msgstr "Zìfú UUID bù fúhé fúwù UUID"
msgid "Characteristic already in use by another Service."
msgstr "Qítā fúwù bùmén yǐ shǐyòng de gōngnéng."
+#: shared-bindings/bleio/Service.c
+msgid "Characteristic is already attached to a Service"
+msgstr ""
+
#: shared-bindings/bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Wèi tígōng zìfú huǎncún xiě rù"
@@ -495,6 +505,10 @@ msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài"
msgid "Data too large for advertisement packet"
msgstr "Guǎnggào bāo de shùjù tài dà"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Descriptor is already attached to a Characteristic"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid "Destination capacity is smaller than destination_length."
msgstr "Mùbiāo róngliàng xiǎoyú mùdì de_chángdù."
@@ -588,7 +602,7 @@ msgstr "Liánjiē shībài: Chāoshí"
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Jìxù sǎomiáo shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/bleio/__init__.c
msgid "Failed to discover services"
msgstr "Fāxiàn fúwù shībài"
@@ -605,17 +619,22 @@ msgstr "Wúfǎ huòdé ruǎnjiàn shèbèi zhuàngtài"
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Wúfǎ tōngzhī huò xiǎnshì shǔxìng zhí, err 0x%04x"
+#: ports/nrf/common-hal/bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Dòu qǔ CCCD zhí, err 0x%04x shībài"
#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Dòu qǔ shǔxìng zhí shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Wúfǎ dòu qǔ gatts zhí, err 0x%04x"
@@ -645,6 +664,11 @@ msgstr "Qǐdòng guǎnggào shībài, err 0x%04x"
msgid "Failed to start connecting, error 0x%04x"
msgstr "Wúfǎ kāishǐ liánjiē, cuòwù 0x%04x"
+#: ports/nrf/common-hal/bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
@@ -660,12 +684,12 @@ msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x"
msgid "Failed to write CCCD, err 0x%04x"
msgstr "Wúfǎ xiě rù CCCD, cuòwù 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Xiě rù shǔxìng zhí shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Xiě rù gatts zhí,err 0x%04x shībài"
@@ -813,10 +837,18 @@ msgstr "Wúxiào de yǐn jiǎo"
msgid "Invalid polarity"
msgstr "Wúxiào liǎng jí zhí"
+#: shared-bindings/bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Wúxiào de yùnxíng móshì."
+#: shared-module/bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
#: shared-bindings/audiocore/Mixer.c
msgid "Invalid voice count"
msgstr "Wúxiào de yǔyīn jìshù"
@@ -939,12 +971,14 @@ msgstr "Shèbèi shàng méiyǒu kònggé"
msgid "No such file/directory"
msgstr "Méiyǒu cǐ lèi wénjiàn/mùlù"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c
#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/bleio/Peripheral.c
msgid "Not connected"
msgstr "Wèi liánjiē"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Wèi bòfàng"
@@ -1075,6 +1109,7 @@ msgid "Sample rate must be positive"
msgstr "Cǎiyàng lǜ bìxū wèi zhèng shù"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Cǎiyàng lǜ tài gāo. Tā bìxū xiǎoyú %d"
@@ -1128,8 +1163,9 @@ msgstr ""
msgid ""
"The `microcontroller` module was used to boot into safe mode. Press reset to "
"exit safe mode.\n"
-msgstr "“Wēi kòngzhì qì” mókuài yòng yú qǐdòng ānquán móshì. Àn chóng zhì kě "
-"tuìchū ānquán móshì.\n"
+msgstr ""
+"“Wēi kòngzhì qì” mókuài yòng yú qǐdòng ānquán móshì. Àn chóng zhì kě tuìchū "
+"ānquán móshì.\n"
#: supervisor/shared/safe_mode.c
msgid ""
@@ -1171,8 +1207,12 @@ msgid "Tile height must exactly divide bitmap height"
msgstr "Píng pū gāodù bìxū huàfēn wèi tú gāodù"
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Píng pū zhǐshù bìxū wèi 0 - 255"
+msgid "Tile index out of bounds"
+msgstr ""
+
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1279,6 +1319,19 @@ msgstr "Bù zhīchí de cāozuò"
msgid "Unsupported pull value."
msgstr "Bù zhīchí de lādòng zhí."
+#: ports/nrf/common-hal/bleio/Characteristic.c
+msgid "Value length required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Viper hánshù mùqián bù zhīchí chāoguò 4 gè cānshù"
@@ -1376,10 +1429,6 @@ msgstr "yòu cè xūyào shùzǔ/zì jié"
msgid "attributes not supported yet"
msgstr "shǔxìng shàngwèi zhīchí"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "zǒng xiédìng de bùliáng juésè"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "biānyì móshì cuòwù"
@@ -1698,6 +1747,10 @@ msgstr "bù zhīchí xiǎoshù shù"
msgid "default 'except' must be last"
msgstr "mòrèn 'except' bìxū shì zuìhòu yīgè"
+#: shared-bindings/bleio/Characteristic.c
+msgid "descriptors includes an object that is not a Descriptors"
+msgstr ""
+
#: shared-bindings/audiobusio/PDMIn.c
msgid ""
"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
@@ -2039,6 +2092,12 @@ msgstr "dìtú huǎnchōng qū tài xiǎo"
msgid "math domain error"
msgstr "shùxué yù cuòwù"
+#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "chāochū zuìdà dìguī shēndù"
@@ -2138,8 +2197,8 @@ msgstr "méiyǒu cǐ shǔxìng"
msgid "non-Service found in services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2224,6 +2283,14 @@ msgstr "jīshù zìfú chuàn"
msgid "offset out of bounds"
msgstr "piānlí biānjiè"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2449,10 +2516,6 @@ msgstr "uctypes miáoshù fú zhōng de yǔfǎ cuòwù"
msgid "threshold must be in the range 0-65536"
msgstr "yùzhí bìxū zài fànwéi 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "kuài suǒyǐn chāochū fànwéi"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() xūyào 9 xùliè"
@@ -2548,7 +2611,7 @@ msgid "unknown conversion specifier %c"
msgstr "wèizhī de zhuǎnhuàn biāozhù %c"
#: py/objstr.c
-#, c-format
+#, fuzzy, c-format
msgid "unknown format code '%c' for object of type '%s'"
msgstr "lèixíng '%s' duìxiàng wèizhī de géshì dàimǎ '%c'"
@@ -2665,6 +2728,9 @@ msgstr "líng bù"
#~ msgid "Can't connect in Peripheral mode"
#~ msgstr "Wúfǎ zài biānyuán móshì zhōng liánjiē"
+#~ msgid "Can't set CCCD for local Characteristic"
+#~ msgstr "Wúfǎ wéi běndì tèzhēng shèzhì CCCD"
+
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Guǎnggào bāo de shùjù tài dà"
@@ -2719,9 +2785,15 @@ msgstr "líng bù"
#~ msgid "Only bit maps of 8 bit color or less are supported"
#~ msgstr "Jǐn zhīchí 8 wèi yánsè huò xiǎoyú"
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Píng pū zhǐshù bìxū wèi 0 - 255"
+
#~ msgid "UUID integer value not in range 0 to 0xffff"
#~ msgstr "UUID zhěngshù zhí bùzài fànwéi 0 zhì 0xffff"
+#~ msgid "bad GATT role"
+#~ msgstr "zǒng xiédìng de bùliáng juésè"
+
#~ msgid "expected a DigitalInOut"
#~ msgstr "qídài de DigitalInOut"
@@ -2734,6 +2806,9 @@ msgstr "líng bù"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "fúwù bāokuò yīgè bùshì fúwù de wùjiàn"
+#~ msgid "tile index out of bounds"
+#~ msgstr "kuài suǒyǐn chāochū fànwéi"
+
#~ msgid "too many arguments"
#~ msgstr "tài duō cānshù"
diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c
index 6b5eeddcc..481a420cb 100644
--- a/ports/atmel-samd/audio_dma.c
+++ b/ports/atmel-samd/audio_dma.c
@@ -35,6 +35,8 @@
#include "py/mpstate.h"
#include "py/runtime.h"
+#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
+
static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];
// This cannot be in audio_dma_state because it's volatile.
@@ -50,6 +52,18 @@ uint8_t find_free_audio_dma_channel(void) {
return channel;
}
+void audio_dma_disable_channel(uint8_t channel) {
+ if (channel >= AUDIO_DMA_CHANNEL_COUNT)
+ return;
+ dma_disable_channel(channel);
+}
+
+void audio_dma_enable_channel(uint8_t channel) {
+ if (channel >= AUDIO_DMA_CHANNEL_COUNT)
+ return;
+ dma_enable_channel(channel);
+}
+
void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer_length,
uint8_t** output_buffer, uint32_t* output_buffer_length,
uint8_t* output_spacing) {
@@ -252,16 +266,19 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
}
dma_configure(dma_channel, dma_trigger_source, true);
- dma_enable_channel(dma_channel);
+ audio_dma_enable_channel(dma_channel);
return AUDIO_DMA_OK;
}
void audio_dma_stop(audio_dma_t* dma) {
- dma_disable_channel(dma->dma_channel);
- disable_event_channel(dma->event_channel);
- MP_STATE_PORT(playing_audio)[dma->dma_channel] = NULL;
-
+ uint8_t channel = dma->dma_channel;
+ if (channel < AUDIO_DMA_CHANNEL_COUNT) {
+ audio_dma_disable_channel(channel);
+ disable_event_channel(dma->event_channel);
+ MP_STATE_PORT(playing_audio)[channel] = NULL;
+ audio_dma_state[channel] = NULL;
+ }
dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT;
}
@@ -290,7 +307,7 @@ void audio_dma_reset(void) {
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
audio_dma_state[i] = NULL;
audio_dma_pending[i] = false;
- dma_disable_channel(i);
+ audio_dma_disable_channel(i);
dma_descriptor(i)->BTCTRL.bit.VALID = false;
MP_STATE_PORT(playing_audio)[i] = NULL;
}
@@ -333,3 +350,4 @@ void audio_dma_background(void) {
audio_dma_pending[i] = false;
}
}
+#endif
diff --git a/ports/atmel-samd/audio_dma.h b/ports/atmel-samd/audio_dma.h
index 53173c277..9d923c5ce 100644
--- a/ports/atmel-samd/audio_dma.h
+++ b/ports/atmel-samd/audio_dma.h
@@ -83,6 +83,9 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
bool output_signed,
uint32_t output_register_address,
uint8_t dma_trigger_source);
+
+void audio_dma_disable_channel(uint8_t channel);
+void audio_dma_enable_channel(uint8_t channel);
void audio_dma_stop(audio_dma_t* dma);
bool audio_dma_get_playing(audio_dma_t* dma);
void audio_dma_pause(audio_dma_t* dma);
diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c
index 4e88d34e7..694238070 100644
--- a/ports/atmel-samd/background.c
+++ b/ports/atmel-samd/background.c
@@ -56,7 +56,7 @@ void run_background_tasks(void) {
assert_heap_ok();
running_background_tasks = true;
- #if (defined(SAMD21) && defined(PIN_PA02)) || defined(SAMD51)
+ #if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
audio_dma_background();
#endif
#if CIRCUITPY_DISPLAYIO
diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c
new file mode 100644
index 000000000..0ed1010a1
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/board.c
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#include "boards/board.h"
+#include "mpconfigboard.h"
+#include "hal/include/hal_gpio.h"
+
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+
+#include "tick.h"
+
+#define DELAY 0x80
+
+uint8_t display_init_sequence[] = {
+ 0x01, DELAY, 100/5, // Soft reset, then delay 10 ms
+ 0xB9, 3, 0xFF, 0x83, 0x57, // Extension command set
+ 0xFF, DELAY, 500/5,
+ 0xB3, 4, 0x80, 0x00, 0x06, 0x06, // 0x80 enables SDO pin (0x00 disables)
+ 0xB6, 2, 0x01, 0x25, // -1.52V
+ 0xB0, 1, 0x68, // Normal mode 70Hz, Idle mode 55 Hz
+ 0xCC, 1, 0x05,
+ 0xB1, 6,
+ 0x00, // Not deep standby
+ 0x15, // BT
+ 0x1C, // VSPR
+ 0x1C, // VSNR
+ 0x83, // AP
+ 0xAA, // FS
+ 0xC0, 6,
+ 0x50, // OPON normal
+ 0x50, // OPON idle
+ 0x01, // STBA
+ 0x3C, // STBA
+ 0x1E, // STBA
+ 0x08, // GEN
+ 0xB4, 7,
+ 0x02, // NW 0x02
+ 0x40, // RTN
+ 0x00, // DIV
+ 0x2A, // DUM
+ 0x2A, // DUM
+ 0x0D, // GDON
+ 0x78, // GDOFF
+ 0xE0, 34,
+ 0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b,
+ 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x02, 0x0A,
+ 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A,
+ 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01,
+ 0x3a, 1, 0x55,
+ 0x36, 1, 0x00,
+ 0x11, DELAY, 150/5, // Exit Sleep, then delay 150 ms
+ 0x29, DELAY, 50/5
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, &pin_PA14);
+ 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_PB05, // TFT_DC Command or data
+ &pin_PB06, // TFT_CS Chip select
+ &pin_PA00, // TFT_RST Reset
+ 24000000);
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 480, // Width
+ 320, // Height
+ 0, // column start
+ 0, // row start
+ 270, // rotation
+ 16, // Color depth
+ false, // grayscale
+ false, // pixels_in_byte_share_row (unused for depths > 8)
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 0x37, // Set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_PB31, // Backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false); // data_as_commands
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h
new file mode 100644
index 000000000..91c118810
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h
@@ -0,0 +1,39 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit PyPortal Titano"
+#define MICROPY_HW_MCU_NAME "samd51j20"
+
+#define CIRCUITPY_MCU_FAMILY samd51
+
+
+#define MICROPY_HW_LED_STATUS (&pin_PA27)
+
+#define MICROPY_HW_NEOPIXEL (&pin_PB22)
+
+// These are pins not to reset.
+// QSPI Data pins
+#define MICROPY_PORT_A ( PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 )
+// QSPI CS, and QSPI SCK
+#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11 | PORT_PB22 )
+#define MICROPY_PORT_C ( 0 )
+#define MICROPY_PORT_D (0)
+
+#define AUTORESET_DELAY_MS 500
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code
+#define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA13)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA12)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA14)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB13)
+#define DEFAULT_UART_BUS_TX (&pin_PB12)
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
new file mode 100644
index 000000000..0ca438311
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
@@ -0,0 +1,16 @@
+LD_FILE = boards/samd51x20-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x8054
+USB_PRODUCT = "PyPortal Titano"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+CHIP_VARIANT = SAMD51J20A
+CHIP_FAMILY = samd51
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 2
+EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
+LONGINT_IMPL = MPZ
+
+# No touch on SAMD51 yet
+CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/pyportal_titano/pins.c b/ports/atmel-samd/boards/pyportal_titano/pins.c
new file mode 100644
index 000000000..6bc0a504a
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/pins.c
@@ -0,0 +1,94 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "boards/board.h"
+#include "shared-module/displayio/__init__.h"
+
+// This mapping only includes functional names because pins broken
+// out on connectors are labeled with their MCU name available from
+// microcontroller.pin.
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AUDIO_OUT), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, // analog out/in
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA27) },
+
+ // Light sensor
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA07) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA07) },
+
+ // STEMMA connectors
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) },
+
+ // Indicator LED
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB23) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PB23) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_PB22) },
+
+ // LCD pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_PA00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RD), MP_ROM_PTR(&pin_PB04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RS), MP_ROM_PTR(&pin_PB05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB06) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_TE), MP_ROM_PTR(&pin_PB07) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_WR), MP_ROM_PTR(&pin_PB09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_PB31) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA0), MP_ROM_PTR(&pin_PA16) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA1), MP_ROM_PTR(&pin_PA17) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA2), MP_ROM_PTR(&pin_PA18) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA3), MP_ROM_PTR(&pin_PA19) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA4), MP_ROM_PTR(&pin_PA20) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA5), MP_ROM_PTR(&pin_PA21) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA6), MP_ROM_PTR(&pin_PA22) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA7), MP_ROM_PTR(&pin_PA23) },
+
+ // Touch pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_YD), MP_ROM_PTR(&pin_PB00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_XL), MP_ROM_PTR(&pin_PB01) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_YU), MP_ROM_PTR(&pin_PA06) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_XR), MP_ROM_PTR(&pin_PB08) },
+
+ // ESP control
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_PB14) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_GPIO0), MP_ROM_PTR(&pin_PB15) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_PB16) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_PB17) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RTS), MP_ROM_PTR(&pin_PA15) },
+
+ // UART
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB12) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB13) },
+
+ // SPI
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI),MP_ROM_PTR(&pin_PA12) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCK),MP_ROM_PTR(&pin_PA13) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MISO),MP_ROM_PTR(&pin_PA14) },
+
+ // I2C
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SDA),MP_ROM_PTR(&pin_PB02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCL),MP_ROM_PTR(&pin_PB03) },
+
+ // SD Card
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS),MP_ROM_PTR(&pin_PB30) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CARD_DETECT),MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+
+ // TFT control pins
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(&pin_PB31)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_PA12)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_PA13)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MISO), MP_ROM_PTR(&pin_PA14)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_PA00)},
+ {MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB06)},
+ {MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB05)},
+
+ { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/snekboard/board.c b/ports/atmel-samd/boards/snekboard/board.c
new file mode 100644
index 000000000..c8e20206a
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void)
+{
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.h b/ports/atmel-samd/boards/snekboard/mpconfigboard.h
new file mode 100644
index 000000000..a349143d9
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.h
@@ -0,0 +1,35 @@
+#define MICROPY_HW_BOARD_NAME "keithp.com snekboard"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA02)
+
+#define MICROPY_HW_NEOPIXEL (&pin_PB11)
+
+#define SPI_FLASH_MOSI_PIN &pin_PB22
+#define SPI_FLASH_MISO_PIN &pin_PB03
+#define SPI_FLASH_SCK_PIN &pin_PB23
+#define SPI_FLASH_CS_PIN &pin_PA27
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (PORT_PB11)
+#define MICROPY_PORT_B ( 0 )
+#define MICROPY_PORT_C ( 0 )
+
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code.
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 0
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA08) /* ANALOG 5 */
+#define DEFAULT_I2C_BUS_SDA (&pin_PA09) /* ANALOG 6 */
+
+#define DEFAULT_UART_BUS_RX (&pin_PB08) /* ANALOG 1 */
+#define DEFAULT_UART_BUS_TX (&pin_PB09) /* ANALOG 2 */
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
new file mode 100644
index 000000000..9892ade8f
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
@@ -0,0 +1,16 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x804E
+USB_PRODUCT = "snekboard"
+USB_MANUFACTURER = "keithp.com"
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "W25Q16JV_IQ"
+LONGINT_IMPL = MPZ
+
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/snekboard/pins.c b/ports/atmel-samd/boards/snekboard/pins.c
new file mode 100644
index 000000000..48bdc672e
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/pins.c
@@ -0,0 +1,28 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_POWER1), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_DIR1), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_POWER2), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_DIR2), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_POWER3), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_DIR3), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_POWER4), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_DIR4), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB11) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
index 8b308b60b..76010a684 100644
--- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
+++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@@ -385,7 +385,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
init_event_channel_interrupt(event_channel, CORE_GCLK, EVSYS_ID_GEN_DMAC_CH_0 + dma_channel);
// Turn on serializer now to get it in sync with DMA.
i2s_set_serializer_enable(self->serializer, true);
- dma_enable_channel(dma_channel);
+ audio_dma_enable_channel(dma_channel);
// Record
uint32_t buffers_processed = 0;
@@ -408,9 +408,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
// If wait_counts exceeds the max count, buffer has probably stopped filling;
// DMA may have missed an I2S trigger event.
while (!event_interrupt_active(event_channel) && ++wait_counts < MAX_WAIT_COUNTS) {
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
// The mic is running all the time, so we don't need to wait the usual 10msec or 100msec
@@ -466,7 +464,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
}
disable_event_channel(event_channel);
- dma_disable_channel(dma_channel);
+ audio_dma_disable_channel(dma_channel);
// Turn off serializer, but leave clock on, to avoid mic startup delay.
i2s_set_serializer_enable(self->serializer, false);
diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c
index a75abd324..90f1aa41f 100644
--- a/ports/atmel-samd/common-hal/audioio/AudioOut.c
+++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c
@@ -69,9 +69,7 @@ static void ramp_value(uint16_t start, uint16_t end) {
DAC->DATA.reg = value;
DAC->DATABUF.reg = value;
common_hal_mcu_delay_us(50);
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
}
#endif
@@ -94,9 +92,7 @@ static void ramp_value(uint16_t start, uint16_t end) {
DAC->DATABUF[1].reg = value;
common_hal_mcu_delay_us(50);
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
}
#endif
diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c
index f04594842..2505e894a 100644
--- a/ports/atmel-samd/common-hal/busio/UART.c
+++ b/ports/atmel-samd/common-hal/busio/UART.c
@@ -291,13 +291,11 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
// Reset the timeout on every character read.
start_ticks = ticks_ms;
}
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
+ RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
break;
}
-#endif
// If we are zero timeout, make sure we don't loop again (in the event
// we read in under 1ms)
if (self->timeout_ms == 0) {
@@ -339,9 +337,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
done = true;
break;
}
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
if (!done) {
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
index 528a5c808..8b8bc6dc6 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
@@ -198,9 +198,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
while(pulse_index < length) {
// Do other things while we wait. The interrupts will handle sending the
// signal.
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP;
diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c
index 9fb3a2ea1..71886089c 100644
--- a/ports/atmel-samd/common-hal/touchio/TouchIn.c
+++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c
@@ -51,9 +51,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
while (!adafruit_ptc_is_conversion_finished(PTC)) {
// wait
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
return adafruit_ptc_get_conversion_result(PTC);
diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c
index 5c34a576a..957bf6073 100644
--- a/ports/atmel-samd/mphalport.c
+++ b/ports/atmel-samd/mphalport.c
@@ -53,9 +53,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t duration = 0;
while (duration < delay) {
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
// Check to see if we've been CTRL-Ced by autoreload or the user.
if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) ||
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index 9da2c498d..fad127514 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -95,8 +95,7 @@ ifeq ($(DEBUG), 1)
CFLAGS += -fno-inline -fno-ipa-sra
else
CFLAGS += -Os -DNDEBUG
- # TODO: Test with -flto
- ### CFLAGS += -flto
+ CFLAGS += -flto -flto-partition=none
endif
diff --git a/ports/nrf/background.c b/ports/nrf/background.c
index 9c4f3ab27..453bc96df 100644
--- a/ports/nrf/background.c
+++ b/ports/nrf/background.c
@@ -33,6 +33,10 @@
#include "shared-module/displayio/__init__.h"
#endif
+#if CIRCUITPY_AUDIOPWMIO
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#endif
+
static bool running_background_tasks = false;
void background_tasks_reset(void) {
@@ -47,6 +51,9 @@ void run_background_tasks(void) {
running_background_tasks = true;
filesystem_background();
usb_background();
+#if CIRCUITPY_AUDIOPWMIO
+ audiopwmout_background();
+#endif
#if CIRCUITPY_DISPLAYIO
displayio_refresh_displays();
diff --git a/ports/nrf/bluetooth/ble_uart.c b/ports/nrf/bluetooth/ble_uart.c
index 91d10cff1..d83cf3980 100644
--- a/ports/nrf/bluetooth/ble_uart.c
+++ b/ports/nrf/bluetooth/ble_uart.c
@@ -138,9 +138,7 @@ void ble_uart_init(void) {
m_cccd_enabled = false;
while (!m_cccd_enabled) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
}
@@ -150,9 +148,7 @@ bool ble_uart_connected(void) {
char ble_uart_rx_chr(void) {
while (isBufferEmpty(&m_rx_ring_buffer)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
uint8_t byte;
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/board.c b/ports/nrf/boards/circuitplayground_bluefruit/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
new file mode 100644
index 000000000..04c7e8d60
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "Adafruit Circuit Playground Bluefruit"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+#define MICROPY_PY_SYS_PLATFORM "CircuitPlaygroundBluefruit"
+
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (4096)
+
+#define MICROPY_HW_NEOPIXEL (&pin_P0_13)
+
+#define MICROPY_HW_LED_STATUS (&pin_P1_14)
+
+#if QSPI_FLASH_FILESYSTEM
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 21)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 23)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 00)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 22)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 15)
+#endif
+
+#if SPI_FLASH_FILESYSTEM
+#define SPI_FLASH_MOSI_PIN &pin_P0_21
+#define SPI_FLASH_MISO_PIN &pin_P0_23
+#define SPI_FLASH_SCK_PIN &pin_P0_19
+#define SPI_FLASH_CS_PIN &pin_P0_15
+#endif
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_04)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_05)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_05)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P1_03)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_29)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_30)
+#define DEFAULT_UART_BUS_TX (&pin_P0_14)
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
new file mode 100644
index 000000000..dbb32629c
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
@@ -0,0 +1,26 @@
+USB_VID = 0x239A
+USB_PID = 0x8046
+USB_PRODUCT = "Circuit Playground Bluefruit"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+MCU_CHIP = nrf52840
+SD ?= s140
+SOFTDEV_VERSION ?= 6.1.0
+
+BOOT_SETTING_ADDR = 0xFF000
+
+ifeq ($(SD),)
+ LD_FILE = boards/nrf52840_1M_256k.ld
+else
+ LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld
+ CIRCUITPY_BLEIO = 1
+endif
+
+NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/pins.c b/ports/nrf/boards/circuitplayground_bluefruit/pins.c
new file mode 100644
index 000000000..556651679
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/pins.c
@@ -0,0 +1,71 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_P0_26) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_05) },
+
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_29) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_03) },
+
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_04) },
+
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_05) },
+
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_30) },
+
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_P0_28) },
+
+ { MP_ROM_QSTR(MP_QSTR_TEMPERATURE), MP_ROM_PTR(&pin_P0_31) },
+ { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_P1_02) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P1_02) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_P1_15) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_SLIDE_SWITCH), MP_ROM_PTR(&pin_P1_06) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P1_06) },
+
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_14) },
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_P0_17) },
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_P0_16) },
+
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_P1_13) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SDA), MP_ROM_PTR(&pin_P1_10) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SCL), MP_ROM_PTR(&pin_P1_12) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_P1_04) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h
index e1f43e3c9..70ccffc3f 100644
--- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h
+++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Feather52840Express"
diff --git a/ports/nrf/boards/make-pins.py b/ports/nrf/boards/make-pins.py
deleted file mode 100644
index d1cfd5b70..000000000
--- a/ports/nrf/boards/make-pins.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/env python
-"""Creates the pin file for the nRF5."""
-
-from __future__ import print_function
-
-import argparse
-import sys
-import csv
-
-
-def parse_port_pin(name_str):
- """Parses a string and returns a (port-num, pin-num) tuple."""
- if len(name_str) < 4:
- raise ValueError("Expecting pin name to be at least 5 charcters.")
- if name_str[0] != 'P':
- raise ValueError("Expecting pin name to start with P")
- if name_str[1] not in ('0', '1'):
- raise ValueError("Expecting pin port to be in 0 or 1")
- port = ord(name_str[1]) - ord('0')
- pin_str = name_str[3:]
- if not pin_str.isdigit():
- raise ValueError("Expecting numeric pin number.")
- return (port, int(pin_str))
-
-
-class Pin(object):
- """Holds the information associated with a pin."""
-
- def __init__(self, port, pin):
- self.port = port
- self.pin = pin
- self.adc_channel = '0'
- self.board_pin = False
-
- def cpu_pin_name(self):
- return 'P{:d}_{:02d}'.format(self.port, self.pin)
-
- def is_board_pin(self):
- return self.board_pin
-
- def set_is_board_pin(self):
- self.board_pin = True
-
- def parse_adc(self, adc_str):
- if (adc_str[:3] != 'AIN'):
- return
- self.adc_channel = 'SAADC_CH_PSELP_PSELP_AnalogInput%d' % int(adc_str[3])
-
- def print(self):
- print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s});'.format(
- self.cpu_pin_name(), self.cpu_pin_name(),
- self.port, self.pin, self.adc_channel))
-
- def print_header(self, hdr_file):
- hdr_file.write('extern const pin_obj_t pin_{:s};\n'.
- format(self.cpu_pin_name()))
-
-
-class NamedPin(object):
-
- def __init__(self, name, pin):
- self._name = name
- self._pin = pin
-
- def pin(self):
- return self._pin
-
- def name(self):
- return self._name
-
-
-class Pins(object):
-
- def __init__(self):
- self.cpu_pins = [] # list of NamedPin objects
- self.board_pins = [] # list of NamedPin objects
-
- def find_pin(self, port_num, pin_num):
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.port == port_num and pin.pin == pin_num:
- return pin
-
- def parse_af_file(self, filename):
- with open(filename, 'r') as csvfile:
- rows = csv.reader(csvfile)
- for row in rows:
- try:
- (port_num, pin_num) = parse_port_pin(row[0])
- except:
- continue
- pin = Pin(port_num, pin_num)
- if len(row) > 1:
- pin.parse_adc(row[1])
- self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin))
-
- def parse_board_file(self, filename):
- with open(filename, 'r') as csvfile:
- rows = csv.reader(csvfile)
- for row in rows:
- try:
- (port_num, pin_num) = parse_port_pin(row[1])
- except:
- continue
- pin = self.find_pin(port_num, pin_num)
- if pin:
- pin.set_is_board_pin()
- self.board_pins.append(NamedPin(row[0], pin))
-
- def print_named(self, label, named_pins):
- print('')
- print('STATIC const mp_rom_map_elem_t {:s}_table[] = {{'.format(label))
- for named_pin in named_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},'.format(named_pin.name(), pin.cpu_pin_name()))
- print('};')
- print('MP_DEFINE_CONST_DICT({:s}, {:s}_table);'.format(label, label))
-
- def print(self):
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- pin.print()
- self.print_named('mcu_pin_globals', self.cpu_pins)
- self.print_named('board_module_globals', self.board_pins)
-
- def print_header(self, hdr_filename):
- with open(hdr_filename, 'wt') as hdr_file:
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- pin.print_header(hdr_file)
-
- def print_qstr(self, qstr_filename):
- with open(qstr_filename, 'wt') as qstr_file:
- qstr_set = set([])
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- qstr_set |= set([named_pin.name()])
- for named_pin in self.board_pins:
- qstr_set |= set([named_pin.name()])
- for qstr in sorted(qstr_set):
- print('Q({})'.format(qstr), file=qstr_file)
-
-
-def main():
- parser = argparse.ArgumentParser(
- prog="make-pins.py",
- usage="%(prog)s [options] [command]",
- description="Generate board specific pin file"
- )
- parser.add_argument(
- "-a", "--af",
- dest="af_filename",
- help="Specifies the alternate function file for the chip",
- default="nrf_af.csv"
- )
- parser.add_argument(
- "-b", "--board",
- dest="board_filename",
- help="Specifies the board file",
- )
- parser.add_argument(
- "-p", "--prefix",
- dest="prefix_filename",
- help="Specifies beginning portion of generated pins file",
- default="nrf52_prefix.c"
- )
- parser.add_argument(
- "-q", "--qstr",
- dest="qstr_filename",
- help="Specifies name of generated qstr header file",
- default="build/pins_qstr.h"
- )
- parser.add_argument(
- "-r", "--hdr",
- dest="hdr_filename",
- help="Specifies name of generated pin header file",
- default="build/pins.h"
- )
- args = parser.parse_args(sys.argv[1:])
-
- pins = Pins()
-
- print('// This file was automatically generated by make-pins.py')
- print('//')
- if args.af_filename:
- print('// --af {:s}'.format(args.af_filename))
- pins.parse_af_file(args.af_filename)
-
- if args.board_filename:
- print('// --board {:s}'.format(args.board_filename))
- pins.parse_board_file(args.board_filename)
-
- if args.prefix_filename:
- print('// --prefix {:s}'.format(args.prefix_filename))
- print('')
- with open(args.prefix_filename, 'r') as prefix_file:
- print(prefix_file.read())
- pins.print()
- pins.print_header(args.hdr_filename)
- pins.print_qstr(args.qstr_filename)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ports/nrf/boards/metro_nrf52840_express/board.c b/ports/nrf/boards/metro_nrf52840_express/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h
new file mode 100644
index 000000000..520eef90d
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "Adafruit Metro nRF52840 Express"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+#define MICROPY_PY_SYS_PLATFORM "Metro52840Express"
+
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (4096)
+
+#define MICROPY_HW_NEOPIXEL (&pin_P0_13)
+
+#define MICROPY_HW_LED_STATUS (&pin_P1_13)
+
+#if QSPI_FLASH_FILESYSTEM
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 23)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20)
+#endif
+
+#if SPI_FLASH_FILESYSTEM
+#define SPI_FLASH_MOSI_PIN &pin_P0_17
+#define SPI_FLASH_MISO_PIN &pin_P0_23
+#define SPI_FLASH_SCK_PIN &pin_P0_19
+#define SPI_FLASH_CS_PIN &pin_P0_20
+#endif
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_16)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_15)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_07)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P1_08)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_11)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_24)
+#define DEFAULT_UART_BUS_TX (&pin_P0_25)
diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
new file mode 100644
index 000000000..4c1c93c10
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
@@ -0,0 +1,26 @@
+USB_VID = 0x239A
+USB_PID = 0x8040
+USB_PRODUCT = "Metro nRF52840 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+MCU_CHIP = nrf52840
+SD ?= s140
+SOFTDEV_VERSION ?= 6.1.0
+
+BOOT_SETTING_ADDR = 0xFF000
+
+ifeq ($(SD),)
+ LD_FILE = boards/nrf52840_1M_256k.ld
+else
+ LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld
+ CIRCUITPY_BLEIO = 1
+endif
+
+NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/metro_nrf52840_express/pins.c b/ports/nrf/boards/metro_nrf52840_express/pins.c
new file mode 100644
index 000000000..452e31202
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/pins.c
@@ -0,0 +1,56 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) },
+
+ { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P1_02) },
+
+ { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_24) },
+
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_25) },
+
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P1_10) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P1_04) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P1_11) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_12) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P1_14) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P1_09) },
+ { MP_ROM_QSTR(MP_QSTR_D13),MP_ROM_PTR(&pin_P0_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_16) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_P0_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P1_08) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_11) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_13) },
+ { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P1_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P1_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/particle_argon/mpconfigboard.h b/ports/nrf/boards/particle_argon/mpconfigboard.h
index 0ee785c31..a4ecb2bb4 100644
--- a/ports/nrf/boards/particle_argon/mpconfigboard.h
+++ b/ports/nrf/boards/particle_argon/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Particle Argon"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Particle Argon"
diff --git a/ports/nrf/boards/particle_boron/mpconfigboard.h b/ports/nrf/boards/particle_boron/mpconfigboard.h
index b814fc694..5e817311f 100644
--- a/ports/nrf/boards/particle_boron/mpconfigboard.h
+++ b/ports/nrf/boards/particle_boron/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Particle Boron"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Particle Boron"
diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h
index c8da66736..6c8cc7cef 100644
--- a/ports/nrf/boards/particle_xenon/mpconfigboard.h
+++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Particle Xenon"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Particle Xenon"
diff --git a/ports/nrf/common-hal/audiobusio/I2SOut.c b/ports/nrf/common-hal/audiobusio/I2SOut.c
new file mode 100644
index 000000000..8be1fb2f8
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/I2SOut.c
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/audiobusio/I2SOut.h"
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t* self,
+ const mcu_pin_obj_t* bit_clock, const mcu_pin_obj_t* word_select,
+ const mcu_pin_obj_t* data, bool left_justified) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self,
+ mp_obj_t sample, bool loop) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
+
+bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) {
+ mp_raise_NotImplementedError(NULL);
+}
diff --git a/ports/nrf/common-hal/audiobusio/I2SOut.h b/ports/nrf/common-hal/audiobusio/I2SOut.h
new file mode 100644
index 000000000..01c944e72
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/I2SOut.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} audiobusio_i2sout_obj_t;
+
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
diff --git a/ports/nrf/common-hal/audiobusio/PDMIn.c b/ports/nrf/common-hal/audiobusio/PDMIn.c
new file mode 100644
index 000000000..a7f9c9d74
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/PDMIn.c
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/audiobusio/PDMIn.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+#include "py/runtime.h"
+
+__attribute__((used))
+NRF_PDM_Type *nrf_pdm = NRF_PDM;
+
+static uint32_t dummy_buffer[4];
+
+void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
+ const mcu_pin_obj_t* clock_pin,
+ const mcu_pin_obj_t* data_pin,
+ uint32_t sample_rate,
+ uint8_t bit_depth,
+ bool mono,
+ uint8_t oversample) {
+ assert_pin_free(clock_pin);
+ assert_pin_free(data_pin);
+ claim_pin(clock_pin);
+ claim_pin(data_pin);
+
+ self->mono = mono;
+ self->clock_pin_number = clock_pin->number;
+ self->data_pin_number = data_pin->number;
+
+ if (sample_rate != 16000) {
+ mp_raise_ValueError(translate("only sample_rate=16000 is supported"));
+ }
+ if (bit_depth != 16) {
+ mp_raise_ValueError(translate("only bit_depth=16 is supported"));
+ }
+ nrf_pdm->PSEL.CLK = self->clock_pin_number;
+ nrf_pdm->PSEL.DIN = self->data_pin_number;
+ nrf_pdm->PDMCLKCTRL = PDM_PDMCLKCTRL_FREQ_Default; // For Ratio64
+ nrf_pdm->RATIO = PDM_RATIO_RATIO_Ratio64;
+ nrf_pdm->GAINL = PDM_GAINL_GAINL_DefaultGain;
+ nrf_pdm->GAINR = PDM_GAINR_GAINR_DefaultGain;
+ nrf_pdm->ENABLE = 1;
+
+ nrf_pdm->SAMPLE.PTR = (uintptr_t)&dummy_buffer;
+ nrf_pdm->SAMPLE.MAXCNT = 1;
+ nrf_pdm->TASKS_START = 1;
+}
+
+bool common_hal_audiobusio_pdmin_deinited(audiobusio_pdmin_obj_t* self) {
+ return !self->clock_pin_number;
+}
+
+void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) {
+ nrf_pdm->ENABLE = 0;
+
+ reset_pin_number(self->clock_pin_number);
+ self->clock_pin_number = 0;
+ reset_pin_number(self->data_pin_number);
+ self->data_pin_number = 0;
+}
+
+uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t* self) {
+ return 16;
+}
+
+uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t* self) {
+ return 16000;
+}
+
+uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self,
+ uint16_t* output_buffer, uint32_t output_buffer_length) {
+ // Note: Adafruit's module has SELECT pulled to GND, which makes the DATA
+ // valid when the CLK is low, therefore it must be sampled on the rising edge.
+ if (self->mono) {
+ nrf_pdm->MODE = PDM_MODE_OPERATION_Stereo | PDM_MODE_EDGE_LeftRising;
+ } else {
+ nrf_pdm->MODE = PDM_MODE_OPERATION_Mono | PDM_MODE_EDGE_LeftRising;
+ }
+
+ // step 1. Redirect to real buffer
+ nrf_pdm->SAMPLE.PTR = (uintptr_t)output_buffer;
+ nrf_pdm->SAMPLE.MAXCNT = output_buffer_length;
+
+ // a delay is the safest simple way to ensure that the above requested sample has started
+ mp_hal_delay_us(200);
+ nrf_pdm->EVENTS_END = 0;
+
+ // step 2. Registers are double buffered, so pre-redirect back to dummy buffer
+ nrf_pdm->SAMPLE.PTR = (uintptr_t)&dummy_buffer;
+ nrf_pdm->SAMPLE.MAXCNT = 1;
+
+ // Step 3. wait for PDM to end
+ while (!nrf_pdm->EVENTS_END) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+
+ // Step 4. They want unsigned
+ for (uint32_t i=0; i<output_buffer_length; i++) {
+ output_buffer[i] += 32768;
+ }
+
+ if (self->mono) {
+ return (output_buffer_length / 2) * 2;
+ } else {
+ return (output_buffer_length / 4) * 4;
+ }
+}
diff --git a/ports/nrf/common-hal/audiobusio/PDMIn.h b/ports/nrf/common-hal/audiobusio/PDMIn.h
new file mode 100644
index 000000000..d921e42ff
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/PDMIn.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_AUDIOOUT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_AUDIOOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t clock_pin_number, data_pin_number;
+ bool mono;
+} audiobusio_pdmin_obj_t;
+
+#endif
diff --git a/ports/nrf/common-hal/audiobusio/__init__.c b/ports/nrf/common-hal/audiobusio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/__init__.c
diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
new file mode 100644
index 000000000..0321b751c
--- /dev/null
+++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
@@ -0,0 +1,316 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "extmod/vfs_fat.h"
+#include "py/gc.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#include "common-hal/pulseio/PWMOut.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "supervisor/shared/translate.h"
+
+// TODO: This should be the same size as PWMOut.c:pwms[], but there's no trivial way to accomplish that
+STATIC audiopwmio_pwmaudioout_obj_t* active_audio[4];
+
+#define F_TARGET (62500)
+#define F_PWM (16000000)
+// return the REFRESH value, store the TOP value in an out-parameter
+// Tested for key values (worst relative error = 0.224% = 3.84 cents)
+// 8000: top = 250 refresh = 7 [ 8000.0]
+// 22050: top = 242 refresh = 2 [22038.5]
+// 24000: top = 222 refresh = 2 [24024.0]
+// 44100: top = 181 refresh = 1 [44198.8]
+// 48000: top = 167 refresh = 1 [47904.1]
+STATIC uint32_t calculate_pwm_parameters(uint32_t sample_rate, uint32_t *top_out) {
+ // the desired frequency is the closest integer multiple of sample_rate not less than F_TARGET
+ uint32_t desired_frequency = (F_TARGET + sample_rate - 1) / sample_rate * sample_rate;
+ // The top value is the PWM frequency divided by the desired frequency (round to nearest)
+ uint32_t top = (F_PWM + desired_frequency/2) / desired_frequency;
+ // The actual frequency is the PWM frequency divided by the top value (round to nearest)
+ uint32_t actual_frequency = (F_PWM + top/2) / top;
+ // The multiplier is the actual frequency divided by the sample rate (round to nearest)
+ uint32_t multiplier = (actual_frequency + sample_rate/2) / sample_rate;
+ *top_out = top;
+ return multiplier - 1;
+}
+
+STATIC void activate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
+ if(!active_audio[i]) {
+ active_audio[i] = self;
+ break;
+ }
+ }
+}
+STATIC void deactivate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
+ if(active_audio[i] == self)
+ active_audio[i] = NULL;
+ }
+}
+
+void audiopwmout_reset() {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++)
+ active_audio[i] = NULL;
+}
+
+STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) {
+ self->pwm->EVENTS_SEQSTARTED[1-buf] = 0;
+ uint16_t *dev_buffer = self->buffers[buf];
+ uint8_t *buffer;
+ uint32_t buffer_length;
+ audioio_get_buffer_result_t get_buffer_result =
+ audiosample_get_buffer(self->sample, false, 0,
+ &buffer, &buffer_length);
+ if (get_buffer_result == GET_BUFFER_ERROR) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ return;
+ }
+ uint32_t num_samples = buffer_length / self->bytes_per_sample / self->spacing;
+
+ if(self->bytes_per_sample == 1) {
+ uint8_t offset = self->signed_to_unsigned ? 0x80 : 0;
+ uint16_t scale = self->scale;
+ for(uint32_t i=0; i<buffer_length/self->spacing; i++) {
+ uint8_t rawval = (*buffer++ + offset);
+ uint16_t val = (uint16_t)(((uint32_t)rawval * (uint32_t)scale) >> 8);
+ *dev_buffer++ = val;
+ if(self->spacing == 1)
+ *dev_buffer++ = val;
+ }
+ } else {
+ uint16_t offset = self->signed_to_unsigned ? 0x8000 : 0;
+ uint16_t scale = self->scale;
+ uint16_t *buffer16 = (uint16_t*)buffer;
+ for(uint32_t i=0; i<buffer_length/2/self->spacing; i++) {
+ uint16_t rawval = (*buffer16++ + offset);
+ uint16_t val = (uint16_t)((rawval * (uint32_t)scale) >> 16);
+ *dev_buffer++ = val;
+ if(self->spacing == 1)
+ *dev_buffer++ = val;
+ }
+ }
+ self->pwm->SEQ[buf].PTR = (intptr_t)self->buffers[buf];
+ self->pwm->SEQ[buf].CNT = num_samples*2;
+
+ if (self->loop && get_buffer_result == GET_BUFFER_DONE) {
+ audiosample_reset_buffer(self->sample, false, 0);
+ } else if(get_buffer_result == GET_BUFFER_DONE) {
+ self->pwm->SHORTS = NRF_PWM_SHORT_SEQEND0_STOP_MASK | NRF_PWM_SHORT_SEQEND1_STOP_MASK;
+ self->stopping = true;
+ }
+}
+
+STATIC void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) {
+ if(!common_hal_audiopwmio_pwmaudioout_get_playing(self))
+ return;
+ if(self->stopping) {
+ bool stopped =
+ (self->pwm->EVENTS_SEQEND[0] || !self->pwm->EVENTS_SEQSTARTED[0]) &&
+ (self->pwm->EVENTS_SEQEND[1] || !self->pwm->EVENTS_SEQSTARTED[1]);
+ if(stopped)
+ self->pwm->TASKS_STOP = 1;
+ } else if(!self->paused && !self->single_buffer) {
+ if(self->pwm->EVENTS_SEQSTARTED[0]) fill_buffers(self, 1);
+ if(self->pwm->EVENTS_SEQSTARTED[1]) fill_buffers(self, 0);
+ }
+}
+
+void audiopwmout_background() {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
+ if(!active_audio[i]) continue;
+ audiopwmout_background_obj(active_audio[i]);
+ }
+}
+
+void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t quiescent_value) {
+ assert_pin_free(left_channel);
+ assert_pin_free(right_channel);
+ self->pwm = pwmout_allocate(256, PWM_PRESCALER_PRESCALER_DIV_1, true, NULL, NULL);
+ if(!self->pwm) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+
+ self->pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1;
+ // two uint16_t values per sample when Grouped
+ // n.b. SEQ[#].CNT "counts" are 2 per sample (left and right channels)
+ self->pwm->DECODER = PWM_DECODER_LOAD_Grouped;
+
+ // we use channels 0 and 2 because these are GROUPED; it lets us save half
+ // the space for sample data (no additional optimization is possible for
+ // single channel)
+ self->pwm->PSEL.OUT[0] = self->left_channel_number = left_channel->number;
+ claim_pin(left_channel);
+
+ if(right_channel)
+ {
+ self->pwm->PSEL.OUT[2] = self->right_channel_number = right_channel->number;
+ claim_pin(right_channel);
+ }
+
+ self->quiescent_value = quiescent_value >> 8;
+
+ self->pwm->ENABLE = 1;
+ // TODO: Ramp from 0 to quiescent value
+}
+
+bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self) {
+ return !self->pwm;
+}
+
+void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self) {
+ if (common_hal_audiopwmio_pwmaudioout_deinited(self)) {
+ return;
+ }
+ // TODO: ramp the pwm down from quiescent value to 0
+ self->pwm->ENABLE = 0;
+
+ if(self->left_channel_number)
+ reset_pin_number(self->left_channel_number);
+ if(self->right_channel_number)
+ reset_pin_number(self->right_channel_number);
+
+ pwmout_free_channel(self->pwm, 0);
+ pwmout_free_channel(self->pwm, 2);
+
+ self->pwm = NULL;
+
+ m_free(self->buffers[0]);
+ self->buffers[0] = NULL;
+
+ m_free(self->buffers[1]);
+ self->buffers[1] = NULL;
+}
+
+void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop) {
+ if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ }
+ self->sample = sample;
+ self->loop = loop;
+
+ uint32_t sample_rate = audiosample_sample_rate(sample);
+ uint32_t max_sample_rate = 62500;
+ if (sample_rate > max_sample_rate) {
+ mp_raise_ValueError_varg(translate("Sample rate too high. It must be less than %d"), max_sample_rate);
+ }
+ self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
+
+ uint32_t max_buffer_length;
+ audiosample_get_buffer_structure(sample, /* single channel */ false,
+ &self->single_buffer, &self->signed_to_unsigned, &max_buffer_length,
+ &self->spacing);
+ if(max_buffer_length > UINT16_MAX) {
+ mp_raise_ValueError_varg(translate("Buffer length %d too big. It must be less than %d"), max_buffer_length, UINT16_MAX);
+ }
+ self->buffer_length = (uint16_t)max_buffer_length;
+ self->buffers[0] = m_malloc(self->buffer_length * 2 * sizeof(uint16_t), false);
+ if(!self->single_buffer)
+ self->buffers[1] = m_malloc(self->buffer_length * 2 * sizeof(uint16_t), false);
+
+
+ uint32_t top;
+ self->pwm->SEQ[0].REFRESH = self->pwm->SEQ[1].REFRESH = calculate_pwm_parameters(sample_rate, &top);
+ self->scale = top-1;
+ self->pwm->COUNTERTOP = top;
+
+ self->pwm->LOOP = 1;
+ audiosample_reset_buffer(self->sample, false, 0);
+ activate_audiopwmout_obj(self);
+ fill_buffers(self, 0);
+ self->pwm->SEQ[1].PTR = self->pwm->SEQ[0].PTR;
+ self->pwm->SEQ[1].CNT = self->pwm->SEQ[0].CNT;
+ self->pwm->EVENTS_SEQSTARTED[0] = 0;
+ self->pwm->EVENTS_SEQSTARTED[1] = 0;
+ self->pwm->EVENTS_STOPPED = 0;
+ self->pwm->SHORTS = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+ self->pwm->TASKS_SEQSTART[0] = 1;
+ self->playing = true;
+ self->stopping = false;
+ self->paused = false;
+}
+
+void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self) {
+ deactivate_audiopwmout_obj(self);
+ self->pwm->TASKS_STOP = 1;
+ self->stopping = false;
+ self->paused = false;
+
+ m_free(self->buffers[0]);
+ self->buffers[0] = NULL;
+
+ m_free(self->buffers[1]);
+ self->buffers[1] = NULL;
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self) {
+ if(!self->paused && self->pwm->EVENTS_STOPPED) {
+ self->playing = false;
+ self->pwm->EVENTS_STOPPED = 0;
+ }
+ return self->playing;
+}
+
+/* pause/resume present difficulties for the NRF PWM audio module.
+ *
+ * A PWM sequence can be stopped in its tracks by sending a TASKS_STOP event,
+ * but there's no way to pick up the sequence where it was stopped; you could
+ * start at the start of one of the two sequences, but especially for "single buffer"
+ * sample, this seems undesirable.
+ *
+ * Or, you can stop at the end of a sequence so that you don't duplicate anything
+ * when restarting, but again this is unsatisfactory for a "single buffer" sample.
+ *
+ * For now, I've taken the coward's way and left these methods unimplemented.
+ * Perhaps the way forward is to divide even "single buffer" samples into tasks of
+ * only a few ms long, so that they can be stopped/restarted quickly enough that it
+ * feels instant. (This also saves on memory, for long in-memory "single buffer"
+ * samples, since we have to locally take a resampled copy!)
+ */
+void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self) {
+ self->paused = true;
+ self->pwm->SHORTS = NRF_PWM_SHORT_SEQEND1_STOP_MASK;
+}
+
+void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self) {
+ self->paused = false;
+ self->pwm->SHORTS = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+ if (self->pwm->EVENTS_STOPPED) {
+ self->pwm->EVENTS_STOPPED = 0;
+ self->pwm->TASKS_SEQSTART[0] = 1;
+ }
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self) {
+ return self->paused;
+}
diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
new file mode 100644
index 000000000..8deff5d34
--- /dev/null
+++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOPWM_AUDIOOUT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOPWM_AUDIOOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t *sample;
+ NRF_PWM_Type *pwm;
+ uint16_t *buffers[2];
+
+ uint16_t buffer_length;
+ uint16_t quiescent_value;
+ uint16_t scale;
+
+ uint8_t left_channel_number;
+ uint8_t right_channel_number;
+ uint8_t spacing;
+ uint8_t bytes_per_sample;
+
+ bool playing;
+ bool stopping;
+ bool paused;
+ bool loop;
+ bool signed_to_unsigned;
+ bool single_buffer;
+} audiopwmio_pwmaudioout_obj_t;
+
+void audiopwmout_reset(void);
+
+void audiopwmout_background(void);
+
+#endif
diff --git a/ports/nrf/common-hal/audiopwmio/__init__.c b/ports/nrf/common-hal/audiopwmio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/nrf/common-hal/audiopwmio/__init__.c
diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/bleio/Adapter.c
index 9d0912930..936dfcb9b 100644
--- a/ports/nrf/common-hal/bleio/Adapter.c
+++ b/ports/nrf/common-hal/bleio/Adapter.c
@@ -34,10 +34,11 @@
#include "nrfx_power.h"
#include "nrf_nvic.h"
#include "nrf_sdm.h"
+#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-
#include "supervisor/usb.h"
+#include "shared-bindings/bleio/Adapter.h"
+#include "shared-bindings/bleio/Address.h"
STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) {
mp_raise_msg_varg(&mp_type_AssertionError,
@@ -132,20 +133,42 @@ bool common_hal_bleio_adapter_get_enabled(void) {
return is_enabled;
}
-void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) {
- ble_gap_addr_t local_address;
+void get_address(ble_gap_addr_t *address) {
uint32_t err_code;
common_hal_bleio_adapter_set_enabled(true);
- err_code = sd_ble_gap_addr_get(&local_address);
+ err_code = sd_ble_gap_addr_get(address);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg(translate("Failed to get local address"));
}
+}
+
+bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) {
+ common_hal_bleio_adapter_set_enabled(true);
+
+ ble_gap_addr_t local_address;
+ get_address(&local_address);
+
+ bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
+ address->base.type = &bleio_address_type;
+
+ common_hal_bleio_address_construct(address, local_address.addr, local_address.addr_type);
+ return address;
+}
+
+mp_obj_t common_hal_bleio_adapter_get_default_name(void) {
+ common_hal_bleio_adapter_set_enabled(true);
+
+ ble_gap_addr_t local_address;
+ get_address(&local_address);
+
+ char name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 };
- address->type = local_address.addr_type;
+ name[sizeof(name) - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf];
+ name[sizeof(name) - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf];
+ name[sizeof(name) - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf];
+ name[sizeof(name) - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf];
- mp_buffer_info_t buf_info;
- mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
- memcpy(address->bytes, buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
+ return mp_obj_new_str(name, sizeof(name));
}
diff --git a/ports/nrf/common-hal/bleio/Attribute.c b/ports/nrf/common-hal/bleio/Attribute.c
new file mode 100644
index 000000000..fd1e7538d
--- /dev/null
+++ b/ports/nrf/common-hal/bleio/Attribute.c
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/bleio/Attribute.h"
+
+// Convert a bleio security mode to a ble_gap_conn_sec_mode_t setting.
+void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) {
+ switch (security_mode) {
+ case SECURITY_MODE_NO_ACCESS:
+ BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm);
+ break;
+
+ case SECURITY_MODE_OPEN:
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm);
+ break;
+
+ case SECURITY_MODE_ENC_NO_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm);
+ break;
+
+ case SECURITY_MODE_ENC_WITH_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm);
+ break;
+
+ case SECURITY_MODE_LESC_ENC_WITH_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm);
+ break;
+
+ case SECURITY_MODE_SIGNED_NO_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm);
+ break;
+
+ case SECURITY_MODE_SIGNED_WITH_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm);
+ break;
+ }
+}
diff --git a/ports/nrf/common-hal/bleio/Attribute.h b/ports/nrf/common-hal/bleio/Attribute.h
new file mode 100644
index 000000000..44c2fdfa1
--- /dev/null
+++ b/ports/nrf/common-hal/bleio/Attribute.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H
+
+// Nothing yet.
+
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H
diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c
index d90737411..3c5d97784 100644
--- a/ports/nrf/common-hal/bleio/Central.c
+++ b/ports/nrf/common-hal/bleio/Central.c
@@ -34,217 +34,9 @@
#include "nrf_soc.h"
#include "py/objstr.h"
#include "py/runtime.h"
+#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Characteristic.h"
#include "shared-bindings/bleio/Central.h"
-#include "shared-bindings/bleio/Descriptor.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
-
-static bleio_service_obj_t *m_char_discovery_service;
-static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
-
-static volatile bool m_discovery_in_process;
-static volatile bool m_discovery_successful;
-
-// service_uuid may be NULL, to discover all services.
-STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_handle, ble_uuid_t *service_uuid) {
- m_discovery_successful = false;
- m_discovery_in_process = true;
-
- uint32_t err_code = sd_ble_gattc_primary_services_discover(self->conn_handle, start_handle, service_uuid);
-
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg(translate("Failed to discover services"));
- }
-
- // Wait for a discovery event.
- while (m_discovery_in_process) {
- MICROPY_VM_HOOK_LOOP;
- }
- return m_discovery_successful;
-}
-
-STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_service_obj_t *service, uint16_t start_handle) {
- m_char_discovery_service = service;
-
- ble_gattc_handle_range_t handle_range;
- handle_range.start_handle = start_handle;
- handle_range.end_handle = service->end_handle;
-
- m_discovery_successful = false;
- m_discovery_in_process = true;
-
- uint32_t err_code = sd_ble_gattc_characteristics_discover(self->conn_handle, &handle_range);
- if (err_code != NRF_SUCCESS) {
- return false;
- }
-
- // Wait for a discovery event.
- while (m_discovery_in_process) {
- MICROPY_VM_HOOK_LOOP;
- }
- return m_discovery_successful;
-}
-
-STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) {
- m_desc_discovery_characteristic = characteristic;
-
- ble_gattc_handle_range_t handle_range;
- handle_range.start_handle = start_handle;
- handle_range.end_handle = end_handle;
-
- m_discovery_successful = false;
- m_discovery_in_process = true;
-
- uint32_t err_code = sd_ble_gattc_descriptors_discover(self->conn_handle, &handle_range);
- if (err_code != NRF_SUCCESS) {
- return false;
- }
-
- // Wait for a discovery event.
- while (m_discovery_in_process) {
- MICROPY_VM_HOOK_LOOP;
- }
- return m_discovery_successful;
-}
-
-STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_central_obj_t *central) {
- for (size_t i = 0; i < response->count; ++i) {
- ble_gattc_service_t *gattc_service = &response->services[i];
-
- bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
- service->base.type = &bleio_service_type;
-
- // Initialize several fields at once.
- common_hal_bleio_service_construct(service, NULL, mp_obj_new_list(0, NULL), false);
-
- service->device = MP_OBJ_FROM_PTR(central);
- service->start_handle = gattc_service->handle_range.start_handle;
- service->end_handle = gattc_service->handle_range.end_handle;
- service->handle = gattc_service->handle_range.start_handle;
-
- if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
- // Known service UUID.
- bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
- uuid->base.type = &bleio_uuid_type;
- bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
- service->uuid = uuid;
- service->device = MP_OBJ_FROM_PTR(central);
- } else {
- // The discovery response contained a 128-bit UUID that has not yet been registered with the
- // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
- // For now, just set the UUID to NULL.
- service->uuid = NULL;
- }
-
- mp_obj_list_append(central->service_list, service);
- }
-
- if (response->count > 0) {
- m_discovery_successful = true;
- }
- m_discovery_in_process = false;
-}
-
-STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_central_obj_t *central) {
- for (size_t i = 0; i < response->count; ++i) {
- ble_gattc_char_t *gattc_char = &response->chars[i];
-
- bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
- characteristic->base.type = &bleio_characteristic_type;
-
- characteristic->descriptor_list = mp_obj_new_list(0, NULL);
-
- bleio_uuid_obj_t *uuid = NULL;
-
- if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
- // Known characteristic UUID.
- uuid = m_new_obj(bleio_uuid_obj_t);
- uuid->base.type = &bleio_uuid_type;
- bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
- } else {
- // The discovery response contained a 128-bit UUID that has not yet been registered with the
- // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
- // For now, just leave the UUID as NULL.
- }
-
- bleio_characteristic_properties_t props;
-
- props.broadcast = gattc_char->char_props.broadcast;
- props.indicate = gattc_char->char_props.indicate;
- props.notify = gattc_char->char_props.notify;
- props.read = gattc_char->char_props.read;
- props.write = gattc_char->char_props.write;
- props.write_no_response = gattc_char->char_props.write_wo_resp;
-
- // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
- common_hal_bleio_characteristic_construct(characteristic, uuid, props, mp_obj_new_list(0, NULL));
- characteristic->handle = gattc_char->handle_value;
- characteristic->service = m_char_discovery_service;
-
- mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
- }
-
- if (response->count > 0) {
- m_discovery_successful = true;
- }
- m_discovery_in_process = false;
-}
-
-STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_central_obj_t *central) {
- for (size_t i = 0; i < response->count; ++i) {
- ble_gattc_desc_t *gattc_desc = &response->descs[i];
-
- // Remember handles for certain well-known descriptors.
- switch (gattc_desc->uuid.uuid) {
- case DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION:
- m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle;
- break;
-
- case DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION:
- m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle;
- break;
-
- case DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION:
- m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle;
- break;
-
- default:
- // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors,
- // so ignore those.
- // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors
- break;
- }
-
- bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
- descriptor->base.type = &bleio_descriptor_type;
-
- bleio_uuid_obj_t *uuid = NULL;
-
- if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
- // Known descriptor UUID.
- uuid = m_new_obj(bleio_uuid_obj_t);
- uuid->base.type = &bleio_uuid_type;
- bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid);
- } else {
- // The discovery response contained a 128-bit UUID that has not yet been registered with the
- // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
- // For now, just leave the UUID as NULL.
- }
-
- common_hal_bleio_descriptor_construct(descriptor, uuid);
- descriptor->handle = gattc_desc->handle;
- descriptor->characteristic = m_desc_discovery_characteristic;
-
- mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
- }
-
- if (response->count > 0) {
- m_discovery_successful = true;
- }
- m_discovery_in_process = false;
-}
STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
bleio_central_obj_t *central = (bleio_central_obj_t*)central_in;
@@ -262,20 +54,6 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
case BLE_GAP_EVT_DISCONNECTED:
central->conn_handle = BLE_CONN_HANDLE_INVALID;
- m_discovery_successful = false;
- m_discovery_in_process = false;
- break;
-
- case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
- on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, central);
- break;
-
- case BLE_GATTC_EVT_CHAR_DISC_RSP:
- on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, central);
- break;
-
- case BLE_GATTC_EVT_DESC_DISC_RSP:
- on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, central);
break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
@@ -288,7 +66,6 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
sd_ble_gap_conn_param_update(central->conn_handle, &request->conn_params);
break;
}
-
default:
// For debugging.
// mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
@@ -299,12 +76,11 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
void common_hal_bleio_central_construct(bleio_central_obj_t *self) {
common_hal_bleio_adapter_set_enabled(true);
- self->service_list = mp_obj_new_list(0, NULL);
- self->gatt_role = GATT_ROLE_CLIENT;
+ self->remote_services_list = mp_obj_new_list(0, NULL);
self->conn_handle = BLE_CONN_HANDLE_INVALID;
}
-void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids) {
+void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) {
common_hal_bleio_adapter_set_enabled(true);
ble_drv_add_event_handler(central_on_ble_evt, self);
@@ -339,115 +115,12 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
}
while (self->waiting_to_connect) {
- MICROPY_VM_HOOK_LOOP;
+ RUN_BACKGROUND_TASKS;
}
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
mp_raise_OSError_msg(translate("Failed to connect: timeout"));
}
-
- // Connection successful.
- // Now discover services on the remote peripheral.
-
- if (service_uuids == mp_const_none) {
-
- // List of service UUID's not given, so discover all available services.
-
- uint16_t next_service_start_handle = BLE_GATT_HANDLE_START;
-
- while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) {
- // discover_next_services() appends to service_list.
-
- // Get the most recently discovered service, and then ask for services
- // whose handles start after the last attribute handle inside that service.
- const bleio_service_obj_t *service =
- MP_OBJ_TO_PTR(self->service_list->items[self->service_list->len - 1]);
- next_service_start_handle = service->end_handle + 1;
- }
- } else {
- mp_obj_iter_buf_t iter_buf;
- mp_obj_t iterable = mp_getiter(service_uuids, &iter_buf);
- mp_obj_t uuid_obj;
- while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
- if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
- mp_raise_ValueError(translate("non-UUID found in service_uuids"));
- }
- bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
-
- ble_uuid_t nrf_uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid);
-
- // Service might or might not be discovered; that's ok. Caller has to check
- // Central.remote_services to find out.
- // We only need to call this once for each service to discover.
- discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid);
- }
- }
-
-
- for (size_t service_idx = 0; service_idx < self->service_list->len; ++service_idx) {
- bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->service_list->items[service_idx]);
-
- // Skip the service if it had an unknown (unregistered) UUID.
- if (service->uuid == NULL) {
- continue;
- }
-
- uint16_t next_char_start_handle = service->start_handle;
-
- // Stop when we go past the end of the range of handles for this service or
- // discovery call returns nothing.
- // discover_next_characteristics() appends to the characteristic_list.
- while (next_char_start_handle <= service->end_handle &&
- discover_next_characteristics(self, service, next_char_start_handle)) {
-
-
- // Get the most recently discovered characteristic, and then ask for characteristics
- // whose handles start after the last attribute handle inside that characteristic.
- const bleio_characteristic_obj_t *characteristic =
- MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]);
- next_char_start_handle = characteristic->handle + 1;
- }
-
- // Got characteristics for this service. Now discover descriptors for each characteristic.
- size_t char_list_len = service->characteristic_list->len;
- for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) {
- bleio_characteristic_obj_t *characteristic =
- MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]);
- const bool last_characteristic = char_idx == char_list_len - 1;
- bleio_characteristic_obj_t *next_characteristic = last_characteristic
- ? NULL
- : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]);
-
- // Skip the characteristic if it had an unknown (unregistered) UUID.
- if (characteristic->uuid == NULL) {
- continue;
- }
-
- uint16_t next_desc_start_handle = characteristic->handle + 1;
-
- // Don't run past the end of this service or the beginning of the next characteristic.
- uint16_t next_desc_end_handle = next_characteristic == NULL
- ? service->end_handle
- : next_characteristic->handle - 1;
-
- // Stop when we go past the end of the range of handles for this service or
- // discovery call returns nothing.
- // discover_next_descriptors() appends to the descriptor_list.
- while (next_desc_start_handle <= service->end_handle &&
- next_desc_start_handle < next_desc_end_handle &&
- discover_next_descriptors(self, characteristic,
- next_desc_start_handle, next_desc_end_handle)) {
-
- // Get the most recently discovered descriptor, and then ask for descriptors
- // whose handles start after that descriptor's handle.
- const bleio_descriptor_obj_t *descriptor =
- MP_OBJ_TO_PTR(characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]);
- next_desc_start_handle = descriptor->handle + 1;
- }
- }
-
- }
}
void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) {
@@ -458,6 +131,15 @@ bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) {
return self->conn_handle != BLE_CONN_HANDLE_INVALID;
}
+mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist) {
+ common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist);
+ // Convert to a tuple and then clear the list so the callee will take ownership.
+ mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_services_list->len,
+ self->remote_services_list->items);
+ mp_obj_list_clear(self->remote_services_list);
+ return services_tuple;
+}
+
mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) {
- return self->service_list;
+ return self->remote_services_list;
}
diff --git a/ports/nrf/common-hal/bleio/Central.h b/ports/nrf/common-hal/bleio/Central.h
index ac1670088..b7a9050b8 100644
--- a/ports/nrf/common-hal/bleio/Central.h
+++ b/ports/nrf/common-hal/bleio/Central.h
@@ -31,15 +31,14 @@
#include <stdbool.h>
#include "py/objlist.h"
-#include "shared-module/bleio/__init__.h"
#include "shared-module/bleio/Address.h"
typedef struct {
mp_obj_base_t base;
- gatt_role_t gatt_role;
volatile bool waiting_to_connect;
volatile uint16_t conn_handle;
- mp_obj_list_t *service_list;
+ // Services discovered after connecting to a remote peripheral.
+ mp_obj_list_t *remote_services_list;
} bleio_central_obj_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H
diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c
index 17417a5e6..45e8d2495 100644
--- a/ports/nrf/common-hal/bleio/Characteristic.c
+++ b/ports/nrf/common-hal/bleio/Characteristic.c
@@ -25,29 +25,23 @@
* THE SOFTWARE.
*/
-#include <string.h>
-#include <stdio.h>
-
-#include "ble_drv.h"
-#include "ble_gatts.h"
-#include "nrf_soc.h"
-
#include "py/runtime.h"
-#include "common-hal/bleio/__init__.h"
-#include "common-hal/bleio/Characteristic.h"
-STATIC volatile bleio_characteristic_obj_t *m_read_characteristic;
+#include "shared-bindings/bleio/__init__.h"
+#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Descriptor.h"
+#include "shared-bindings/bleio/Service.h"
-STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
+static volatile bleio_characteristic_obj_t *m_read_characteristic;
+
+STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) {
uint16_t cccd;
ble_gatts_value_t value = {
.p_value = (uint8_t*) &cccd,
.len = 2,
};
- const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->cccd_handle, &value);
-
+ const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value);
if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
// CCCD is not set, so say that neither Notify nor Indicate is enabled.
@@ -59,64 +53,39 @@ STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
return cccd;
}
-STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) {
- // This might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
- // we can still read and write the local value.
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
-
- mp_buffer_info_t bufinfo;
- ble_gatts_value_t gatts_value = {
- .p_value = NULL,
- .len = 0,
- };
-
- // Read once to find out what size buffer we need, then read again to fill buffer.
-
- uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
- if (err_code == NRF_SUCCESS) {
- characteristic->value_data = mp_obj_new_bytearray_of_zeros(gatts_value.len);
- mp_get_buffer_raise(characteristic->value_data, &bufinfo, MP_BUFFER_WRITE);
- gatts_value.p_value = bufinfo.buf;
-
- // Read again, with the correct size of buffer.
- err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
- }
-
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code);
- }
-}
-
+STATIC void characteristic_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
+ switch (ble_evt->header.evt_id) {
-STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
- // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
- // we can still read and write the local value.
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
+ // More events may be handled later, so keep this as a switch.
- ble_gatts_value_t gatts_value = {
- .p_value = bufinfo->buf,
- .len = bufinfo->len,
- };
+ case BLE_GATTC_EVT_READ_RSP: {
+ ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
+ if (m_read_characteristic) {
+ m_read_characteristic->value = mp_obj_new_bytearray(response->len, response->data);
+ }
+ // Indicate to busy-wait loop that we've read the attribute value.
+ m_read_characteristic = NULL;
+ break;
+ }
- const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code);
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
}
}
-STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
+STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
uint16_t hvx_len = bufinfo->len;
ble_gatts_hvx_params_t hvx_params = {
- .handle = characteristic->handle,
+ .handle = handle,
.type = hvx_type,
.offset = 0,
.p_len = &hvx_len,
.p_data = bufinfo->buf,
};
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
-
while (1) {
const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
if (err_code == NRF_SUCCESS) {
@@ -125,156 +94,128 @@ STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp
// TX buffer is full
// We could wait for an event indicating the write is complete, but just retrying is easier.
if (err_code == NRF_ERROR_RESOURCES) {
- MICROPY_VM_HOOK_LOOP;
+ RUN_BACKGROUND_TASKS;
continue;
}
// Some real error has occurred.
mp_raise_OSError_msg_varg(translate("Failed to notify or indicate attribute value, err 0x%04x"), err_code);
}
-
-}
-
-STATIC void check_connected(uint16_t conn_handle) {
- if (conn_handle == BLE_CONN_HANDLE_INVALID) {
- mp_raise_OSError_msg(translate("Not connected"));
- }
}
-STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) {
+STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic) {
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- check_connected(conn_handle);
+ common_hal_bleio_check_connected(conn_handle);
+ // Set to NULL in event loop after event.
m_read_characteristic = characteristic;
+ ble_drv_add_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic);
+
const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
}
while (m_read_characteristic != NULL) {
- MICROPY_VM_HOOK_LOOP;
- }
-}
-
-STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- check_connected(conn_handle);
-
- ble_gattc_write_params_t write_params = {
- .write_op = characteristic->props.write_no_response ? BLE_GATT_OP_WRITE_CMD : BLE_GATT_OP_WRITE_REQ,
- .handle = characteristic->handle,
- .p_value = bufinfo->buf,
- .len = bufinfo->len,
- };
-
- while (1) {
- uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
- if (err_code == NRF_SUCCESS) {
- break;
- }
-
- // Write with response will return NRF_ERROR_BUSY if the response has not been received.
- // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
- if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
- // We could wait for an event indicating the write is complete, but just retrying is easier.
- MICROPY_VM_HOOK_LOOP;
- continue;
- }
-
- // Some real error occurred.
- mp_raise_OSError_msg_varg(translate("Failed to write attribute value, err 0x%04x"), err_code);
+ RUN_BACKGROUND_TASKS;
}
+ ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic);
}
-STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) {
- switch (ble_evt->header.evt_id) {
-
- // More events may be handled later, so keep this as a switch.
-
- case BLE_GATTC_EVT_READ_RSP: {
- ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
- m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data);
- // Indicate to busy-wait loop that we've read the characteristic.
- m_read_characteristic = NULL;
- break;
- }
-
- // For debugging.
- default:
- // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
- break;
- }
-
-}
-
-void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list) {
- self->service = mp_const_none;
+void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, 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_obj_list_t *descriptor_list) {
+ self->service = MP_OBJ_NULL;
self->uuid = uuid;
- self->value_data = mp_const_none;
+ self->value = mp_const_empty_bytes;
+ self->handle = BLE_GATT_HANDLE_INVALID;
self->props = props;
+ self->read_perm = read_perm;
+ self->write_perm = write_perm;
self->descriptor_list = descriptor_list;
- self->handle = BLE_GATT_HANDLE_INVALID;
- ble_drv_add_event_handler(characteristic_on_ble_evt, self);
+ const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
+ if (max_length < 0 || max_length > max_length_max) {
+ mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
+ max_length_max, fixed_length ? "True" : "False");
+ }
+ self->max_length = max_length;
+ self->fixed_length = fixed_length;
+
+ for (size_t descriptor_idx = 0; descriptor_idx < descriptor_list->len; ++descriptor_idx) {
+ bleio_descriptor_obj_t *descriptor =
+ MP_OBJ_TO_PTR(descriptor_list->items[descriptor_idx]);
+ descriptor->characteristic = self;
+ }
}
mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) {
return self->descriptor_list;
}
+bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) {
+ return self->service;
+}
+
mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
- switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
- case GATT_ROLE_CLIENT:
- gattc_read(self);
- break;
-
- case GATT_ROLE_SERVER:
- gatts_read(self);
- break;
-
- default:
- mp_raise_RuntimeError(translate("bad GATT role"));
- break;
+ // Do GATT operations only if this characteristic has been added to a registered service.
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+ if (common_hal_bleio_service_get_is_remote(self->service)) {
+ // self->value is set by evt handler.
+ characteristic_gattc_read(self);
+ } else {
+ self->value = common_hal_bleio_gatts_read(self->handle, conn_handle);
+ }
}
- return self->value_data;
+ return self->value;
}
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
- bool sent = false;
- uint16_t cccd = 0;
+ // Do GATT operations only if this characteristic has been added to a registered service.
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+
+ if (common_hal_bleio_service_get_is_remote(self->service)) {
+ // Last argument is true if write-no-reponse desired.
+ common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo,
+ (self->props & CHAR_PROP_WRITE_NO_RESPONSE));
+ } else {
+ if (self->fixed_length && bufinfo->len != self->max_length) {
+ mp_raise_ValueError(translate("Value length required fixed length"));
+ }
+ if (bufinfo->len > self->max_length) {
+ mp_raise_ValueError(translate("Value length > max_length"));
+ }
+
+ bool sent = false;
+ uint16_t cccd = 0;
- switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
- case GATT_ROLE_SERVER:
- if (self->props.notify || self->props.indicate) {
- cccd = get_cccd(self);
+ const bool notify = self->props & CHAR_PROP_NOTIFY;
+ const bool indicate = self->props & CHAR_PROP_INDICATE;
+ if (notify | indicate) {
+ cccd = characteristic_get_cccd(self->cccd_handle, conn_handle);
}
+
// It's possible that both notify and indicate are set.
- if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
- gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION);
+ if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
+ characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION);
sent = true;
}
- if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
- gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION);
+ if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
+ characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION);
sent = true;
}
+
if (!sent) {
- gatts_write(self, bufinfo);
+ common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo);
}
- break;
-
- case GATT_ROLE_CLIENT:
- gattc_write(self, bufinfo);
- break;
-
- default:
- mp_raise_RuntimeError(translate("bad GATT role"));
- break;
+ }
}
-}
+ self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
+}
bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) {
return self->uuid;
@@ -289,18 +230,17 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
mp_raise_ValueError(translate("No CCCD for this Characteristic"));
}
- if (common_hal_bleio_device_get_gatt_role(self->service->device) != GATT_ROLE_CLIENT) {
- mp_raise_ValueError(translate("Can't set CCCD for local Characteristic"));
+ if (!common_hal_bleio_service_get_is_remote(self->service)) {
+ mp_raise_ValueError(translate("Can't set CCCD on local Characteristic"));
}
+ const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+ common_hal_bleio_check_connected(conn_handle);
+
uint16_t cccd_value =
(notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
(indicate ? BLE_GATT_HVX_INDICATION : 0);
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
- check_connected(conn_handle);
-
-
ble_gattc_write_params_t write_params = {
.write_op = BLE_GATT_OP_WRITE_REQ,
.handle = self->cccd_handle,
@@ -318,7 +258,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
// Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
// We could wait for an event indicating the write is complete, but just retrying is easier.
- MICROPY_VM_HOOK_LOOP;
+ RUN_BACKGROUND_TASKS;
continue;
}
diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/bleio/Characteristic.h
index 7cb227596..fb6a4c6ce 100644
--- a/ports/nrf/common-hal/bleio/Characteristic.h
+++ b/ports/nrf/common-hal/bleio/Characteristic.h
@@ -28,17 +28,23 @@
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
+#include "shared-bindings/bleio/Attribute.h"
+#include "shared-module/bleio/Characteristic.h"
#include "common-hal/bleio/Service.h"
#include "common-hal/bleio/UUID.h"
-#include "shared-module/bleio/Characteristic.h"
typedef struct {
mp_obj_base_t base;
+ // Will be MP_OBJ_NULL before being assigned to a Service.
bleio_service_obj_t *service;
bleio_uuid_obj_t *uuid;
- volatile mp_obj_t value_data;
+ mp_obj_t value;
+ uint16_t max_length;
+ bool fixed_length;
uint16_t handle;
bleio_characteristic_properties_t props;
+ bleio_attribute_security_mode_t read_perm;
+ bleio_attribute_security_mode_t write_perm;
mp_obj_list_t *descriptor_list;
uint16_t user_desc_handle;
uint16_t cccd_handle;
diff --git a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
index 59eaaf02b..64ab5e8a7 100644
--- a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
+++ b/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
@@ -37,7 +37,7 @@
#include "tick.h"
-#include "common-hal/bleio/__init__.h"
+#include "shared-bindings/bleio/__init__.h"
#include "common-hal/bleio/CharacteristicBuffer.h"
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
@@ -99,7 +99,7 @@ int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
- MICROPY_VM_HOOK_LOOP;
+ RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
return 0;
diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c
index 005af6eaa..2a2019277 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.c
+++ b/ports/nrf/common-hal/bleio/Descriptor.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
@@ -26,17 +26,116 @@
* THE SOFTWARE.
*/
-#include "common-hal/bleio/Descriptor.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/bleio/__init__.h"
+#include "shared-bindings/bleio/Descriptor.h"
+#include "shared-bindings/bleio/Service.h"
#include "shared-bindings/bleio/UUID.h"
-void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) {
+static volatile bleio_descriptor_obj_t *m_read_descriptor;
+
+void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length) {
+ self->characteristic = MP_OBJ_NULL;
self->uuid = uuid;
-}
+ self->value = mp_const_empty_bytes;
+ self->handle = BLE_GATT_HANDLE_INVALID;
+ self->read_perm = read_perm;
+ self->write_perm = write_perm;
-mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) {
- return self->handle;
+ const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
+ if (max_length < 0 || max_length > max_length_max) {
+ mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
+ max_length_max, fixed_length ? "True" : "False");
+ }
+ self->max_length = max_length;
+ self->fixed_length = fixed_length;
}
bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
return self->uuid;
}
+
+bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) {
+ return self->characteristic;
+}
+
+STATIC void descriptor_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
+ switch (ble_evt->header.evt_id) {
+
+ // More events may be handled later, so keep this as a switch.
+
+ case BLE_GATTC_EVT_READ_RSP: {
+ ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
+ if (m_read_descriptor) {
+ m_read_descriptor->value = mp_obj_new_bytearray(response->len, response->data);
+ }
+ // Indicate to busy-wait loop that we've read the attribute value.
+ m_read_descriptor = NULL;
+ break;
+ }
+
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled descriptor event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
+ }
+}
+
+STATIC void descriptor_gattc_read(bleio_descriptor_obj_t *descriptor) {
+ const uint16_t conn_handle =
+ common_hal_bleio_device_get_conn_handle(descriptor->characteristic->service->device);
+ common_hal_bleio_check_connected(conn_handle);
+
+ // Set to NULL in event loop after event.
+ m_read_descriptor = descriptor;
+
+ ble_drv_add_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor);
+
+ const uint32_t err_code = sd_ble_gattc_read(conn_handle, descriptor->handle, 0);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
+ }
+
+ while (m_read_descriptor != NULL) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+
+ ble_drv_remove_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor);
+}
+
+mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self) {
+ // Do GATT operations only if this descriptor has been registered
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
+ descriptor_gattc_read(self);
+ } else {
+ self->value = common_hal_bleio_gatts_read(
+ self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device));
+ }
+ }
+
+ return self->value;
+}
+
+void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) {
+ // Do GATT operations only if this descriptor has been registered.
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device);
+ if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
+ // false means WRITE_REQ, not write-no-response
+ common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false);
+ } else {
+ if (self->fixed_length && bufinfo->len != self->max_length) {
+ mp_raise_ValueError(translate("Value length != required fixed length"));
+ }
+ if (bufinfo->len > self->max_length) {
+ mp_raise_ValueError(translate("Value length > max_length"));
+ }
+
+ common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo);
+ }
+ }
+
+ self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
+}
diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h
index b7af6a42f..6db4d7be3 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.h
+++ b/ports/nrf/common-hal/bleio/Descriptor.h
@@ -30,14 +30,21 @@
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
#include "py/obj.h"
-#include "common-hal/bleio/Characteristic.h"
+
+#include "shared-bindings/bleio/Characteristic.h"
#include "common-hal/bleio/UUID.h"
typedef struct {
mp_obj_base_t base;
- uint16_t handle;
+ // Will be MP_OBJ_NULL before being assigned to a Characteristic.
bleio_characteristic_obj_t *characteristic;
bleio_uuid_obj_t *uuid;
+ mp_obj_t value;
+ uint16_t max_length;
+ bool fixed_length;
+ uint16_t handle;
+ bleio_attribute_security_mode_t read_perm;
+ bleio_attribute_security_mode_t write_perm;
} bleio_descriptor_obj_t;
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c
index 608bd1342..ed35516fc 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.c
+++ b/ports/nrf/common-hal/bleio/Peripheral.c
@@ -36,12 +36,12 @@
#include "py/objlist.h"
#include "py/objstr.h"
#include "py/runtime.h"
+#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Adapter.h"
#include "shared-bindings/bleio/Characteristic.h"
#include "shared-bindings/bleio/Peripheral.h"
#include "shared-bindings/bleio/Service.h"
#include "shared-bindings/bleio/UUID.h"
-#include "common-hal/bleio/Service.h"
#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS)
@@ -52,6 +52,19 @@
#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
+static const ble_gap_sec_params_t pairing_sec_params = {
+ .bond = 0, // TODO: add bonding
+ .mitm = 0,
+ .lesc = 0,
+ .keypress = 0,
+ .oob = 0,
+ .io_caps = BLE_GAP_IO_CAPS_NONE,
+ .min_key_size = 7,
+ .max_key_size = 16,
+ .kdist_own = { .enc = 1, .id = 1},
+ .kdist_peer = { .enc = 1, .id = 1},
+};
+
STATIC void check_data_fit(size_t data_len) {
if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
mp_raise_ValueError(translate("Data too large for advertisement packet"));
@@ -61,6 +74,9 @@ STATIC void check_data_fit(size_t data_len) {
STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in;
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Peripheral event: 0x%04x\n", ble_evt->header.evt_id);
+
switch (ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED: {
// Central has connected.
@@ -89,10 +105,6 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
// Someday may handle timeouts or limit reached.
break;
- case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
- sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
- break;
-
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
ble_gap_evt_conn_param_update_request_t *request =
&ble_evt->evt.gap_evt.params.conn_param_update_request;
@@ -113,6 +125,47 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
break;
+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+ sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, &pairing_sec_params, NULL);
+ break;
+
+ case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
+ // TODO for LESC pairing:
+ // sd_ble_gap_lesc_dhkey_reply(...);
+ break;
+
+ case BLE_GAP_EVT_AUTH_STATUS: {
+ // Pairing process completed
+ ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status;
+ if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) {
+ // mp_printf(&mp_plat_print, "Pairing succeeded, status: 0x%04x\n", status->auth_status);
+ self->pair_status = PAIR_PAIRED;
+ } else {
+ // mp_printf(&mp_plat_print, "Pairing failed, status: 0x%04x\n", status->auth_status);
+ self->pair_status = PAIR_NOT_PAIRED;
+ }
+ break;
+ }
+
+ case BLE_GAP_EVT_CONN_SEC_UPDATE: {
+ ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec;
+ if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) {
+ // Security setup did not succeed:
+ // mode 0, level 0 means no access
+ // mode 1, level 1 means open link
+ // mode >=1 and/or level >=1 means encryption is set up
+ self->pair_status = PAIR_NOT_PAIRED;
+ } else {
+ // TODO: see Bluefruit lib
+ // if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) {
+ // sd_ble_gatts_sys_attr_set(_conn_hdl, NULL, 0, 0);
+ // }
+ self->pair_status = PAIR_PAIRED;
+ }
+ break;
+ }
+
+
default:
// For debugging.
// mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id);
@@ -120,20 +173,22 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
}
}
-void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name) {
+void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *services_list, mp_obj_t name) {
common_hal_bleio_adapter_set_enabled(true);
- self->service_list = service_list;
+ self->services_list = services_list;
+ // Used only for discovery when acting as a client.
+ self->remote_services_list = mp_obj_new_list(0, NULL);
self->name = name;
- self->gatt_role = GATT_ROLE_SERVER;
self->conn_handle = BLE_CONN_HANDLE_INVALID;
self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
+ self->pair_status = PAIR_NOT_PAIRED;
// Add all the services.
- for (size_t service_idx = 0; service_idx < service_list->len; ++service_idx) {
- bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[service_idx]);
+ for (size_t service_idx = 0; service_idx < services_list->len; ++service_idx) {
+ bleio_service_obj_t *service = MP_OBJ_TO_PTR(services_list->items[service_idx]);
service->device = MP_OBJ_FROM_PTR(self);
@@ -156,8 +211,8 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_
}
-mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self) {
- return self->service_list;
+mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) {
+ return self->services_list;
}
bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) {
@@ -247,3 +302,30 @@ void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self)
void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) {
sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
}
+
+mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist) {
+ common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist);
+ // Convert to a tuple and then clear the list so the callee will take ownership.
+ mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_services_list->len,
+ self->remote_services_list->items);
+ mp_obj_list_clear(self->remote_services_list);
+ return services_tuple;
+}
+
+void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *self) {
+ self->pair_status = PAIR_WAITING;
+
+ uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to start pairing, error 0x%04x"), err_code);
+ }
+
+ while (self->pair_status == PAIR_WAITING) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+
+ if (self->pair_status == PAIR_NOT_PAIRED) {
+ mp_raise_OSError_msg(translate("Failed to pair"));
+ }
+}
diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h
index 2a1251715..e75a1641a 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.h
+++ b/ports/nrf/common-hal/bleio/Peripheral.h
@@ -35,22 +35,29 @@
#include "py/obj.h"
#include "py/objlist.h"
-#include "shared-module/bleio/__init__.h"
#include "shared-module/bleio/Address.h"
+typedef enum {
+ PAIR_NOT_PAIRED,
+ PAIR_WAITING,
+ PAIR_PAIRED,
+} pair_status_t;
+
typedef struct {
mp_obj_base_t base;
mp_obj_t name;
- gatt_role_t gatt_role;
volatile uint16_t conn_handle;
- mp_obj_list_t *service_list;
+ // Services provided by this peripheral.
+ mp_obj_list_t *services_list;
+ // Remote services discovered when this peripheral is acting as a client.
+ mp_obj_list_t *remote_services_list;
// The advertising data and scan response buffers are held by us, not by the SD, so we must
// maintain them and not change it. If we need to change the contents during advertising,
// there are tricks to get the SD to notice (see DevZone - TBS).
uint8_t* advertising_data;
uint8_t* scan_response_data;
uint8_t adv_handle;
-
+ pair_status_t pair_status;
} bleio_peripheral_obj_t;
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H
diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c
index b6fcde827..a7a3a6db0 100644
--- a/ports/nrf/common-hal/bleio/Service.c
+++ b/ports/nrf/common-hal/bleio/Service.c
@@ -29,8 +29,8 @@
#include "ble.h"
#include "py/runtime.h"
#include "common-hal/bleio/__init__.h"
-#include "common-hal/bleio/Characteristic.h"
#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Descriptor.h"
#include "shared-bindings/bleio/Service.h"
#include "shared-bindings/bleio/Adapter.h"
@@ -39,6 +39,7 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob
self->handle = 0xFFFF;
self->uuid = uuid;
self->characteristic_list = characteristic_list;
+ self->is_remote = false;
self->is_secondary = is_secondary;
for (size_t characteristic_idx = 0; characteristic_idx < characteristic_list->len; ++characteristic_idx) {
@@ -46,7 +47,6 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob
MP_OBJ_TO_PTR(characteristic_list->items[characteristic_idx]);
characteristic->service = self;
}
-
}
bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
@@ -57,6 +57,10 @@ mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_ob
return self->characteristic_list;
}
+bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
+ return self->is_remote;
+}
+
bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
return self->is_secondary;
}
@@ -68,13 +72,17 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self)
bleio_characteristic_obj_t *characteristic =
MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]);
+ if (characteristic->handle != BLE_GATT_HANDLE_INVALID) {
+ mp_raise_ValueError(translate("Characteristic already in use by another Service."));
+ }
+
ble_gatts_char_md_t char_md = {
- .char_props.broadcast = characteristic->props.broadcast,
- .char_props.read = characteristic->props.read,
- .char_props.write_wo_resp = characteristic->props.write_no_response,
- .char_props.write = characteristic->props.write,
- .char_props.notify = characteristic->props.notify,
- .char_props.indicate = characteristic->props.indicate,
+ .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0,
+ .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0,
+ .char_props.write_wo_resp = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0,
+ .char_props.write = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0,
+ .char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0,
+ .char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0,
};
ble_gatts_attr_md_t cccd_md = {
@@ -88,39 +96,74 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self)
char_md.p_cccd_md = &cccd_md;
}
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &uuid);
+ ble_uuid_t char_uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid);
- ble_gatts_attr_md_t attr_md = {
+ ble_gatts_attr_md_t char_attr_md = {
.vloc = BLE_GATTS_VLOC_STACK,
- .vlen = 1,
+ .vlen = !characteristic->fixed_length,
};
- BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
- BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&char_attr_md.read_perm);
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&char_attr_md.write_perm);
+
+ mp_buffer_info_t char_value_bufinfo;
+ mp_get_buffer_raise(characteristic->value, &char_value_bufinfo, MP_BUFFER_READ);
- ble_gatts_attr_t attr_char_value = {
- .p_uuid = &uuid,
- .p_attr_md = &attr_md,
- .init_len = sizeof(uint8_t),
- .max_len = GATT_MAX_DATA_LENGTH,
+ ble_gatts_attr_t char_attr = {
+ .p_uuid = &char_uuid,
+ .p_attr_md = &char_attr_md,
+ .init_len = char_value_bufinfo.len,
+ .p_value = char_value_bufinfo.buf,
+ .init_offs = 0,
+ .max_len = characteristic->max_length,
};
- ble_gatts_char_handles_t handles;
+ ble_gatts_char_handles_t char_handles;
uint32_t err_code;
- err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &attr_char_value, &handles);
+ err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code);
}
- if (characteristic->handle != BLE_GATT_HANDLE_INVALID) {
- mp_raise_ValueError(translate("Characteristic already in use by another Service."));
- }
+ characteristic->user_desc_handle = char_handles.user_desc_handle;
+ characteristic->cccd_handle = char_handles.cccd_handle;
+ characteristic->sccd_handle = char_handles.sccd_handle;
+ characteristic->handle = char_handles.value_handle;
- characteristic->user_desc_handle = handles.user_desc_handle;
- characteristic->cccd_handle = handles.cccd_handle;
- characteristic->sccd_handle = handles.sccd_handle;
- characteristic->handle = handles.value_handle;
- }
+ // Add the descriptors for this characteristic.
+ for (size_t descriptor_idx = 0; descriptor_idx < characteristic->descriptor_list->len; ++descriptor_idx) {
+ bleio_descriptor_obj_t *descriptor =
+ MP_OBJ_TO_PTR(characteristic->descriptor_list->items[descriptor_idx]);
+
+ ble_uuid_t desc_uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
+
+ ble_gatts_attr_md_t desc_attr_md = {
+ // Data passed is not in a permanent location and should be copied.
+ .vloc = BLE_GATTS_VLOC_STACK,
+ .vlen = !descriptor->fixed_length,
+ };
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.read_perm);
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.write_perm);
+
+ mp_buffer_info_t desc_value_bufinfo;
+ mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
+
+ ble_gatts_attr_t desc_attr = {
+ .p_uuid = &desc_uuid,
+ .p_attr_md = &desc_attr_md,
+ .init_len = desc_value_bufinfo.len,
+ .p_value = desc_value_bufinfo.buf,
+ .init_offs = 0,
+ .max_len = descriptor->max_length,
+ };
+
+ err_code = sd_ble_gatts_descriptor_add(characteristic->handle, &desc_attr, &descriptor->handle);
+
+ } // loop over descriptors
+
+ } // loop over characteristics
}
diff --git a/ports/nrf/common-hal/bleio/Service.h b/ports/nrf/common-hal/bleio/Service.h
index 583593fb8..03ac2bca8 100644
--- a/ports/nrf/common-hal/bleio/Service.h
+++ b/ports/nrf/common-hal/bleio/Service.h
@@ -35,6 +35,8 @@ typedef struct {
mp_obj_base_t base;
// Handle for this service.
uint16_t handle;
+ // True if created during discovery.
+ bool is_remote;
bool is_secondary;
bleio_uuid_obj_t *uuid;
// May be a Peripheral, Central, etc.
diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c
index 2dba5780c..2e26ac07d 100644
--- a/ports/nrf/common-hal/bleio/__init__.c
+++ b/ports/nrf/common-hal/bleio/__init__.c
@@ -26,12 +26,24 @@
* THE SOFTWARE.
*/
+#include "py/runtime.h"
#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Adapter.h"
#include "shared-bindings/bleio/Central.h"
+#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Descriptor.h"
#include "shared-bindings/bleio/Peripheral.h"
+#include "shared-bindings/bleio/Service.h"
+#include "shared-bindings/bleio/UUID.h"
+
#include "common-hal/bleio/__init__.h"
+static volatile bool m_discovery_in_process;
+static volatile bool m_discovery_successful;
+
+static bleio_service_obj_t *m_char_discovery_service;
+static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
+
// Turn off BLE on a reset or reload.
void bleio_reset() {
if (common_hal_bleio_adapter_get_enabled()) {
@@ -47,13 +59,9 @@ const super_adapter_obj_t common_hal_bleio_adapter_obj = {
},
};
-gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) {
- if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
- return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
- } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
- return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
- } else {
- return GATT_ROLE_NONE;
+void common_hal_bleio_check_connected(uint16_t conn_handle) {
+ if (conn_handle == BLE_CONN_HANDLE_INVALID) {
+ mp_raise_OSError_msg(translate("Not connected"));
}
}
@@ -63,6 +71,433 @@ uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) {
} else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
} else {
- return 0;
+ return BLE_CONN_HANDLE_INVALID;
+ }
+}
+
+mp_obj_list_t *common_hal_bleio_device_get_remote_services_list(mp_obj_t device) {
+ if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
+ return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->remote_services_list;
+ } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
+ return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->remote_services_list;
+ } else {
+ return NULL;
+ }
+}
+
+// service_uuid may be NULL, to discover all services.
+STATIC bool discover_next_services(mp_obj_t device, uint16_t start_handle, ble_uuid_t *service_uuid) {
+ m_discovery_successful = false;
+ m_discovery_in_process = true;
+
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device);
+ uint32_t err_code = sd_ble_gattc_primary_services_discover(conn_handle, start_handle, service_uuid);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg(translate("Failed to discover services"));
+ }
+
+ // Wait for a discovery event.
+ while (m_discovery_in_process) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+ return m_discovery_successful;
+}
+
+STATIC bool discover_next_characteristics(mp_obj_t device, bleio_service_obj_t *service, uint16_t start_handle) {
+ m_char_discovery_service = service;
+
+ ble_gattc_handle_range_t handle_range;
+ handle_range.start_handle = start_handle;
+ handle_range.end_handle = service->end_handle;
+
+ m_discovery_successful = false;
+ m_discovery_in_process = true;
+
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device);
+ uint32_t err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range);
+ if (err_code != NRF_SUCCESS) {
+ return false;
+ }
+
+ // Wait for a discovery event.
+ while (m_discovery_in_process) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+ return m_discovery_successful;
+}
+
+STATIC bool discover_next_descriptors(mp_obj_t device, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) {
+ m_desc_discovery_characteristic = characteristic;
+
+ ble_gattc_handle_range_t handle_range;
+ handle_range.start_handle = start_handle;
+ handle_range.end_handle = end_handle;
+
+ m_discovery_successful = false;
+ m_discovery_in_process = true;
+
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device);
+ uint32_t err_code = sd_ble_gattc_descriptors_discover(conn_handle, &handle_range);
+ if (err_code != NRF_SUCCESS) {
+ return false;
}
+
+ // Wait for a discovery event.
+ while (m_discovery_in_process) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+ return m_discovery_successful;
+}
+
+STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, mp_obj_t device) {
+ for (size_t i = 0; i < response->count; ++i) {
+ ble_gattc_service_t *gattc_service = &response->services[i];
+
+ bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
+ service->base.type = &bleio_service_type;
+
+ // Initialize several fields at once.
+ common_hal_bleio_service_construct(service, NULL, mp_obj_new_list(0, NULL), false);
+
+ service->device = device;
+ service->is_remote = true;
+ service->start_handle = gattc_service->handle_range.start_handle;
+ service->end_handle = gattc_service->handle_range.end_handle;
+ service->handle = gattc_service->handle_range.start_handle;
+
+ if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
+ // Known service UUID.
+ bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
+ uuid->base.type = &bleio_uuid_type;
+ bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
+ service->uuid = uuid;
+ } else {
+ // The discovery response contained a 128-bit UUID that has not yet been registered with the
+ // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
+ // For now, just set the UUID to NULL.
+ service->uuid = NULL;
+ }
+
+ mp_obj_list_append(common_hal_bleio_device_get_remote_services_list(device), service);
+ }
+
+ if (response->count > 0) {
+ m_discovery_successful = true;
+ }
+ m_discovery_in_process = false;
+}
+
+STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_obj_t device) {
+ for (size_t i = 0; i < response->count; ++i) {
+ ble_gattc_char_t *gattc_char = &response->chars[i];
+
+ bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
+ characteristic->base.type = &bleio_characteristic_type;
+
+ bleio_uuid_obj_t *uuid = NULL;
+
+ if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
+ // Known characteristic UUID.
+ uuid = m_new_obj(bleio_uuid_obj_t);
+ uuid->base.type = &bleio_uuid_type;
+ bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
+ } else {
+ // The discovery response contained a 128-bit UUID that has not yet been registered with the
+ // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
+ // For now, just leave the UUID as NULL.
+ }
+
+ bleio_characteristic_properties_t props =
+ (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) |
+ (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) |
+ (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) |
+ (gattc_char->char_props.read ? CHAR_PROP_READ : 0) |
+ (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) |
+ (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0);
+
+ // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
+ common_hal_bleio_characteristic_construct(
+ characteristic, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
+ GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
+ mp_obj_new_list(0, NULL));
+ characteristic->handle = gattc_char->handle_value;
+ characteristic->service = m_char_discovery_service;
+
+ mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
+ }
+
+ if (response->count > 0) {
+ m_discovery_successful = true;
+ }
+ m_discovery_in_process = false;
+}
+
+STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_obj_t device) {
+ for (size_t i = 0; i < response->count; ++i) {
+ ble_gattc_desc_t *gattc_desc = &response->descs[i];
+
+ // Remember handles for certain well-known descriptors.
+ switch (gattc_desc->uuid.uuid) {
+ case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG:
+ m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle;
+ break;
+
+ case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG:
+ m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle;
+ break;
+
+ case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC:
+ m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle;
+ break;
+
+ default:
+ // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors,
+ // so ignore those.
+ // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors
+ break;
+ }
+
+ bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
+ descriptor->base.type = &bleio_descriptor_type;
+
+ bleio_uuid_obj_t *uuid = NULL;
+
+ if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
+ // Known descriptor UUID.
+ uuid = m_new_obj(bleio_uuid_obj_t);
+ uuid->base.type = &bleio_uuid_type;
+ bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid);
+ } else {
+ // The discovery response contained a 128-bit UUID that has not yet been registered with the
+ // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
+ // For now, just leave the UUID as NULL.
+ }
+
+ common_hal_bleio_descriptor_construct(descriptor, uuid, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
+ GATT_MAX_DATA_LENGTH, false);
+ descriptor->handle = gattc_desc->handle;
+ descriptor->characteristic = m_desc_discovery_characteristic;
+
+ mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
+ }
+
+ if (response->count > 0) {
+ m_discovery_successful = true;
+ }
+ m_discovery_in_process = false;
+}
+
+STATIC void discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t device) {
+ switch (ble_evt->header.evt_id) {
+ case BLE_GAP_EVT_DISCONNECTED:
+ m_discovery_successful = false;
+ m_discovery_in_process = false;
+ break;
+
+ case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
+ on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device);
+ break;
+
+ case BLE_GATTC_EVT_CHAR_DISC_RSP:
+ on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device);
+ break;
+
+ case BLE_GATTC_EVT_DESC_DISC_RSP:
+ on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, device);
+ break;
+
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
+ }
+}
+
+
+void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) {
+ mp_obj_list_t *remote_services_list = common_hal_bleio_device_get_remote_services_list(device);
+
+ ble_drv_add_event_handler(discovery_on_ble_evt, device);
+
+ // Start over with an empty list.
+ mp_obj_list_clear(MP_OBJ_FROM_PTR(common_hal_bleio_device_get_remote_services_list(device)));
+
+ if (service_uuids_whitelist == mp_const_none) {
+ // List of service UUID's not given, so discover all available services.
+
+ uint16_t next_service_start_handle = BLE_GATT_HANDLE_START;
+
+ while (discover_next_services(device, next_service_start_handle, MP_OBJ_NULL)) {
+ // discover_next_services() appends to remote_services_list.
+
+ // Get the most recently discovered service, and then ask for services
+ // whose handles start after the last attribute handle inside that service.
+ const bleio_service_obj_t *service =
+ MP_OBJ_TO_PTR(remote_services_list->items[remote_services_list->len - 1]);
+ next_service_start_handle = service->end_handle + 1;
+ }
+ } else {
+ mp_obj_iter_buf_t iter_buf;
+ mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf);
+ mp_obj_t uuid_obj;
+ while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
+ if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
+ mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist"));
+ }
+ bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
+
+ ble_uuid_t nrf_uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid);
+
+ // Service might or might not be discovered; that's ok. Caller has to check
+ // Central.remote_services to find out.
+ // We only need to call this once for each service to discover.
+ discover_next_services(device, BLE_GATT_HANDLE_START, &nrf_uuid);
+ }
+ }
+
+
+ for (size_t service_idx = 0; service_idx < remote_services_list->len; ++service_idx) {
+ bleio_service_obj_t *service = MP_OBJ_TO_PTR(remote_services_list->items[service_idx]);
+
+ // Skip the service if it had an unknown (unregistered) UUID.
+ if (service->uuid == NULL) {
+ continue;
+ }
+
+ uint16_t next_char_start_handle = service->start_handle;
+
+ // Stop when we go past the end of the range of handles for this service or
+ // discovery call returns nothing.
+ // discover_next_characteristics() appends to the characteristic_list.
+ while (next_char_start_handle <= service->end_handle &&
+ discover_next_characteristics(device, service, next_char_start_handle)) {
+
+
+ // Get the most recently discovered characteristic, and then ask for characteristics
+ // whose handles start after the last attribute handle inside that characteristic.
+ const bleio_characteristic_obj_t *characteristic =
+ MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]);
+ next_char_start_handle = characteristic->handle + 1;
+ }
+
+ // Got characteristics for this service. Now discover descriptors for each characteristic.
+ size_t char_list_len = service->characteristic_list->len;
+ for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) {
+ bleio_characteristic_obj_t *characteristic =
+ MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]);
+ const bool last_characteristic = char_idx == char_list_len - 1;
+ bleio_characteristic_obj_t *next_characteristic = last_characteristic
+ ? NULL
+ : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]);
+
+ // Skip the characteristic if it had an unknown (unregistered) UUID.
+ if (characteristic->uuid == NULL) {
+ continue;
+ }
+
+ uint16_t next_desc_start_handle = characteristic->handle + 1;
+
+ // Don't run past the end of this service or the beginning of the next characteristic.
+ uint16_t next_desc_end_handle = next_characteristic == NULL
+ ? service->end_handle
+ : next_characteristic->handle - 1;
+
+ // Stop when we go past the end of the range of handles for this service or
+ // discovery call returns nothing.
+ // discover_next_descriptors() appends to the descriptor_list.
+ while (next_desc_start_handle <= service->end_handle &&
+ next_desc_start_handle < next_desc_end_handle &&
+ discover_next_descriptors(device, characteristic,
+ next_desc_start_handle, next_desc_end_handle)) {
+
+ // Get the most recently discovered descriptor, and then ask for descriptors
+ // whose handles start after that descriptor's handle.
+ const bleio_descriptor_obj_t *descriptor =
+ MP_OBJ_TO_PTR(characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]);
+ next_desc_start_handle = descriptor->handle + 1;
+ }
+ }
+ }
+
+ // This event handler is no longer needed.
+ ble_drv_remove_event_handler(discovery_on_ble_evt, device);
+
+}
+
+// GATTS read of a Characteristic or Descriptor.
+mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle) {
+ // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
+ // we can still read and write the local value.
+
+ mp_buffer_info_t bufinfo;
+ ble_gatts_value_t gatts_value = {
+ .p_value = NULL,
+ .len = 0,
+ };
+
+ // Read once to find out what size buffer we need, then read again to fill buffer.
+
+ mp_obj_t value = mp_const_none;
+ uint32_t err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value);
+ if (err_code == NRF_SUCCESS) {
+ value = mp_obj_new_bytearray_of_zeros(gatts_value.len);
+ mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_WRITE);
+ gatts_value.p_value = bufinfo.buf;
+
+ // Read again, with the correct size of buffer.
+ err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value);
+ }
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code);
+ }
+
+ return value;
+}
+
+void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) {
+ // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
+ // we can still read and write the local value.
+
+ ble_gatts_value_t gatts_value = {
+ .p_value = bufinfo->buf,
+ .len = bufinfo->len,
+ };
+
+ const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, handle, &gatts_value);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code);
+ }
+}
+
+void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) {
+ common_hal_bleio_check_connected(conn_handle);
+
+ ble_gattc_write_params_t write_params = {
+ .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ,
+ .handle = handle,
+ .p_value = bufinfo->buf,
+ .len = bufinfo->len,
+ };
+
+ while (1) {
+ uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
+ }
+
+ // Write with response will return NRF_ERROR_BUSY if the response has not been received.
+ // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
+ if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ MICROPY_VM_HOOK_LOOP;
+ continue;
+ }
+
+ // Some real error occurred.
+ mp_raise_OSError_msg_varg(translate("Failed to write attribute value, err 0x%04x"), err_code);
+ }
+
}
diff --git a/ports/nrf/common-hal/bleio/__init__.h b/ports/nrf/common-hal/bleio/__init__.h
index 0c46b631f..c0bba3799 100644
--- a/ports/nrf/common-hal/bleio/__init__.h
+++ b/ports/nrf/common-hal/bleio/__init__.h
@@ -27,16 +27,10 @@
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
-#include "shared-bindings/bleio/__init__.h"
-#include "shared-bindings/bleio/Adapter.h"
-
-#include "shared-module/bleio/__init__.h"
+void bleio_reset(void);
// We assume variable length data.
// 20 bytes max (23 - 3).
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
-gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device);
-uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
-
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c
index b9e9e5538..54a66ddbe 100644
--- a/ports/nrf/common-hal/busio/UART.c
+++ b/ports/nrf/common-hal/busio/UART.c
@@ -235,13 +235,11 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
+ RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
return 0;
}
-#endif
}
// prevent conflict with uart irq
@@ -271,9 +269,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data,
// Wait for on-going transfer to complete
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
// Time up
@@ -295,9 +291,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data,
(*errcode) = 0;
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
if ( !nrfx_is_in_ram(data) ) {
diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c
index ab7b5d5d6..a6b1c4ba3 100644
--- a/ports/nrf/common-hal/microcontroller/__init__.c
+++ b/ports/nrf/common-hal/microcontroller/__init__.c
@@ -37,6 +37,7 @@
#include "shared-bindings/microcontroller/Processor.h"
#include "supervisor/filesystem.h"
+#include "supervisor/shared/safe_mode.h"
#include "nrfx_glue.h"
// This routine should work even when interrupts are disabled. Used by OneWire
@@ -52,7 +53,13 @@ void common_hal_mcu_enable_interrupts() {
}
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
- // TODO: see atmel-samd for functionality
+ enum { DFU_MAGIC_UF2_RESET = 0x57 };
+ if(runmode == RUNMODE_BOOTLOADER)
+ NRF_POWER->GPREGRET = DFU_MAGIC_UF2_RESET;
+ else
+ NRF_POWER->GPREGRET = 0;
+ if(runmode == RUNMODE_SAFE_MODE)
+ safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
}
void common_hal_mcu_reset(void) {
diff --git a/ports/nrf/common-hal/neopixel_write/__init__.c b/ports/nrf/common-hal/neopixel_write/__init__.c
index 78e0038e8..3b67778a6 100644
--- a/ports/nrf/common-hal/neopixel_write/__init__.c
+++ b/ports/nrf/common-hal/neopixel_write/__init__.c
@@ -200,9 +200,7 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
// But we have to wait for the flag to be set.
while ( !nrf_pwm_event_check(pwm, NRF_PWM_EVENT_SEQEND0) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
// Before leave we clear the flag for the event.
diff --git a/ports/nrf/common-hal/pulseio/PWMOut.c b/ports/nrf/common-hal/pulseio/PWMOut.c
index 5233c9adc..b827470d3 100644
--- a/ports/nrf/common-hal/pulseio/PWMOut.c
+++ b/ports/nrf/common-hal/pulseio/PWMOut.c
@@ -57,6 +57,12 @@ STATIC uint16_t pwm_seq[MP_ARRAY_SIZE(pwms)][CHANNELS_PER_PWM];
static uint8_t never_reset_pwm[MP_ARRAY_SIZE(pwms)];
+STATIC int pwm_idx(NRF_PWM_Type *pwm) {
+ for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++)
+ if(pwms[i] == pwm) return i;
+ return -1;
+}
+
void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) {
for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) {
NRF_PWM_Type* pwm = pwms[i];
@@ -133,29 +139,11 @@ bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t *
return false;
}
-pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
- const mcu_pin_obj_t* pin,
- uint16_t duty,
- uint32_t frequency,
- bool variable_frequency) {
-
- // We don't use the nrfx driver here because we want to dynamically allocate channels
- // as needed in an already-enabled PWM.
-
- uint16_t countertop;
- nrf_pwm_clk_t base_clock;
- if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) {
- return PWMOUT_INVALID_FREQUENCY;
- }
-
- self->pwm = NULL;
- self->channel = CHANNELS_PER_PWM; // out-of-range value.
- bool pwm_already_in_use;
- NRF_PWM_Type* pwm;
- size_t pwm_index = 0;
- for (; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
- pwm = pwms[pwm_index];
- pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
+NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
+ bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out) {
+ for (size_t pwm_index = 0; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
+ NRF_PWM_Type *pwm = pwms[pwm_index];
+ bool pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
if (pwm_already_in_use) {
if (variable_frequency) {
// Variable frequency requires exclusive use of a PWM, so try the next one.
@@ -168,28 +156,65 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) {
if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) {
// Channel is free.
- self->pwm = pwm;
- self->channel = chan;
- break;
+ if(channel_out)
+ *channel_out = chan;
+ if(pwm_already_in_use_out)
+ *pwm_already_in_use_out = pwm_already_in_use;
+ return pwm;
}
}
- // Did we find a channel? If not, loop and check the next pwm.
- if (self->pwm != NULL) {
- break;
- }
}
} else {
// PWM not yet in use, so we can start to use it. Use channel 0.
- self->pwm = pwm;
- self->channel = 0;
- break;
+ if(channel_out)
+ *channel_out = 0;
+ if(pwm_already_in_use_out)
+ *pwm_already_in_use_out = pwm_already_in_use;
+ return pwm;
}
}
+ return NULL;
+}
+
+void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel) {
+ // Disconnect pin from channel.
+ pwm->PSEL.OUT[channel] = 0xFFFFFFFF;
+
+ for(int i=0; i < CHANNELS_PER_PWM; i++) {
+ if (pwm->PSEL.OUT[i] != 0xFFFFFFFF) {
+ // Some channel is still being used, so don't disable.
+ return;
+ }
+ }
+
+ nrf_pwm_disable(pwm);
+}
+
+pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
+ const mcu_pin_obj_t* pin,
+ uint16_t duty,
+ uint32_t frequency,
+ bool variable_frequency) {
+
+ // We don't use the nrfx driver here because we want to dynamically allocate channels
+ // as needed in an already-enabled PWM.
+
+ uint16_t countertop;
+ nrf_pwm_clk_t base_clock;
+ if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) {
+ return PWMOUT_INVALID_FREQUENCY;
+ }
+
+ int8_t channel;
+ bool pwm_already_in_use;
+ self->pwm = pwmout_allocate(countertop, base_clock, variable_frequency,
+ &channel, &pwm_already_in_use);
if (self->pwm == NULL) {
return PWMOUT_ALL_TIMERS_IN_USE;
}
+ self->channel = channel;
self->pin_number = pin->number;
claim_pin(pin);
@@ -200,17 +225,17 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
nrf_gpio_cfg_output(self->pin_number);
// disable before mapping pin channel
- nrf_pwm_disable(pwm);
+ nrf_pwm_disable(self->pwm);
if (!pwm_already_in_use) {
- reset_single_pwmout(pwm_index);
- nrf_pwm_configure(pwm, base_clock, NRF_PWM_MODE_UP, countertop);
+ reset_single_pwmout(pwm_idx(self->pwm));
+ nrf_pwm_configure(self->pwm, base_clock, NRF_PWM_MODE_UP, countertop);
}
// Connect channel to pin, without disturbing other channels.
- pwm->PSEL.OUT[self->channel] = pin->number;
+ self->pwm->PSEL.OUT[self->channel] = pin->number;
- nrf_pwm_enable(pwm);
+ nrf_pwm_enable(self->pwm);
common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
return PWMOUT_OK;
@@ -230,17 +255,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
NRF_PWM_Type* pwm = self->pwm;
self->pwm = NULL;
- // Disconnect pin from channel.
- pwm->PSEL.OUT[self->channel] = 0xFFFFFFFF;
-
- for(int i=0; i < CHANNELS_PER_PWM; i++) {
- if (self->pwm->PSEL.OUT[i] != 0xFFFFFFFF) {
- // Some channel is still being used, so don't disable.
- return;
- }
- }
-
- nrf_pwm_disable(pwm);
+ pwmout_free_channel(pwm, self->channel);
}
void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) {
diff --git a/ports/nrf/common-hal/pulseio/PWMOut.h b/ports/nrf/common-hal/pulseio/PWMOut.h
index a4e58dc1a..b6798cb68 100644
--- a/ports/nrf/common-hal/pulseio/PWMOut.h
+++ b/ports/nrf/common-hal/pulseio/PWMOut.h
@@ -41,5 +41,8 @@ typedef struct {
} pulseio_pwmout_obj_t;
void pwmout_reset(void);
+NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
+ bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out);
+void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H
diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c
index be5deca9f..d0433247a 100644
--- a/ports/nrf/common-hal/pulseio/PulseOut.c
+++ b/ports/nrf/common-hal/pulseio/PulseOut.c
@@ -155,9 +155,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
while(pulse_array_index < length) {
// Do other things while we wait. The interrupts will handle sending the
// signal.
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
nrfx_timer_disable(timer);
diff --git a/ports/nrf/device/nrf52/startup_nrf52840.c b/ports/nrf/device/nrf52/startup_nrf52840.c
index 30634a1b5..8e1c36012 100644
--- a/ports/nrf/device/nrf52/startup_nrf52840.c
+++ b/ports/nrf/device/nrf52/startup_nrf52840.c
@@ -116,7 +116,7 @@ void CRYPTOCELL_IRQHandler (void) __attribute__ ((weak, alias("Default_Han
void SPIM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
void PWM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
-const func __Vectors[] __attribute__ ((section(".isr_vector"))) = {
+const func __Vectors[] __attribute__ ((used, section(".isr_vector"))) = {
(func)&_estack,
Reset_Handler,
NMI_Handler,
diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk
index 83166708a..55920b3f4 100644
--- a/ports/nrf/mpconfigport.mk
+++ b/ports/nrf/mpconfigport.mk
@@ -10,11 +10,11 @@ USB_SERIAL_NUMBER_LENGTH = 16
# All nRF ports have longints.
LONGINT_IMPL = MPZ
-# No DAC, so no regular audio.
+# Audio via PWM
+CIRCUITPY_AUDIOCORE = 1
CIRCUITPY_AUDIOIO = 0
-
-# No I2S yet.
-CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_AUDIOPWMIO = 1
+CIRCUITPY_AUDIOBUSIO = 1
# No I2CSlave implementation
CIRCUITPY_I2CSLAVE = 0
diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c
index 7d9463d0b..bcd9fb114 100644
--- a/ports/nrf/mphalport.c
+++ b/ports/nrf/mphalport.c
@@ -39,9 +39,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t duration = 0;
while (duration < delay) {
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
// Check to see if we've been CTRL-Ced by autoreload or the user.
if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) ||
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h
index a2b48065d..8fa6721e2 100644
--- a/ports/nrf/nrfx_config.h
+++ b/ports/nrf/nrfx_config.h
@@ -78,6 +78,7 @@
// TIMERS
#define NRFX_TIMER_ENABLED 1
// Don't enable TIMER0: it's used by the SoftDevice.
+#define NRFX_TIMER0_ENABLED 0
#define NRFX_TIMER1_ENABLED 1
#define NRFX_TIMER2_ENABLED 1
diff --git a/ports/nrf/peripherals/nrf/timers.c b/ports/nrf/peripherals/nrf/timers.c
index 7f7a003d3..88f3dd468 100644
--- a/ports/nrf/peripherals/nrf/timers.c
+++ b/ports/nrf/peripherals/nrf/timers.c
@@ -36,7 +36,7 @@
STATIC nrfx_timer_t nrfx_timers[] = {
#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
- // Note that TIMER0 is reserved for use by the SoftDevice, so it should not usually be enabled.
+ #error NRFX_TIMER0_ENABLED should not be on: TIMER0 is used by the SoftDevice
NRFX_TIMER_INSTANCE(0),
#endif
#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
diff --git a/ports/nrf/sd_mutex.c b/ports/nrf/sd_mutex.c
index 7682ffa62..b3162e6af 100644
--- a/ports/nrf/sd_mutex.c
+++ b/ports/nrf/sd_mutex.c
@@ -37,9 +37,7 @@ void sd_mutex_acquire_check(nrf_mutex_t* p_mutex) {
void sd_mutex_acquire_wait(nrf_mutex_t* p_mutex) {
while (sd_mutex_acquire(p_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
}
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index 8fbf75498..03f787624 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -50,6 +50,10 @@
#include "shared-bindings/rtc/__init__.h"
+#ifdef CIRCUITPY_AUDIOPWMIO
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#endif
+
static void power_warning_handler(void) {
reset_into_safe_mode(BROWNOUT);
}
@@ -94,6 +98,10 @@ void reset_port(void) {
spi_reset();
uart_reset();
+#ifdef CIRCUITPY_AUDIOPWMIO
+ audiopwmout_reset();
+#endif
+
#if CIRCUITPY_PULSEIO
pwmout_reset();
pulseout_reset();
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 16a2474f3..fa005ef73 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -108,6 +108,9 @@ endif
ifeq ($(CIRCUITPY_AUDIOIO),1)
SRC_PATTERNS += audioio/%
endif
+ifeq ($(CIRCUITPY_AUDIOPWMIO),1)
+SRC_PATTERNS += audiopwmio/%
+endif
ifeq ($(CIRCUITPY_AUDIOCORE),1)
SRC_PATTERNS += audiocore/%
endif
@@ -223,10 +226,13 @@ $(filter $(SRC_PATTERNS), \
audiobusio/__init__.c \
audiobusio/I2SOut.c \
audiobusio/PDMIn.c \
+ audiopwmio/__init__.c \
+ audiopwmio/PWMAudioOut.c \
audioio/__init__.c \
audioio/AudioOut.c \
bleio/__init__.c \
bleio/Adapter.c \
+ bleio/Attribute.c \
bleio/Central.c \
bleio/Characteristic.c \
bleio/CharacteristicBuffer.c \
@@ -276,6 +282,9 @@ $(filter $(SRC_PATTERNS), \
# All possible sources are listed here, and are filtered by SRC_PATTERNS.
SRC_BINDINGS_ENUMS = \
$(filter $(SRC_PATTERNS), \
+ bleio/Address.c \
+ bleio/Attribute.c \
+ bleio/ScanEntry.c \
digitalio/Direction.c \
digitalio/DriveMode.c \
digitalio/Pull.c \
@@ -289,12 +298,6 @@ SRC_BINDINGS_ENUMS += \
help.c \
util.c
-SRC_BINDINGS_ENUMS += \
-$(filter $(SRC_PATTERNS), \
- bleio/Address.c \
- bleio/ScanEntry.c \
-)
-
# All possible sources are listed here, and are filtered by SRC_PATTERNS.
SRC_SHARED_MODULE = \
$(filter $(SRC_PATTERNS), \
@@ -303,6 +306,7 @@ $(filter $(SRC_PATTERNS), \
_stage/Layer.c \
_stage/Text.c \
_stage/__init__.c \
+ audiopwmio/__init__.c \
audioio/__init__.c \
audiocore/__init__.c \
audiocore/Mixer.c \
@@ -315,6 +319,7 @@ $(filter $(SRC_PATTERNS), \
bitbangio/__init__.c \
board/__init__.c \
bleio/Address.c \
+ bleio/Attribute.c \
bleio/ScanEntry.c \
busio/OneWire.c \
displayio/Bitmap.c \
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index 3440eb052..393b7600c 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -244,6 +244,13 @@ extern const struct _mp_obj_module_t audioio_module;
#define AUDIOIO_MODULE
#endif
+#if CIRCUITPY_AUDIOPWMIO
+#define AUDIOPWMIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiopwmio), (mp_obj_t)&audiopwmio_module },
+extern const struct _mp_obj_module_t audiopwmio_module;
+#else
+#define AUDIOPWMIO_MODULE
+#endif
+
#if CIRCUITPY_BITBANGIO
#define BITBANGIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module },
extern const struct _mp_obj_module_t bitbangio_module;
@@ -266,13 +273,7 @@ extern const struct _mp_obj_module_t board_module;
#define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI))
#define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX))
-#if BOARD_I2C
-#define BOARD_I2C_ROOT_POINTER mp_obj_t shared_i2c_bus;
-#else
-#define BOARD_I2C_ROOT_POINTER
-#endif
-
-// SPI is always allocated off the heap.
+// I2C and SPI are always allocated off the heap.
#if BOARD_UART
#define BOARD_UART_ROOT_POINTER mp_obj_t shared_uart_bus;
@@ -282,7 +283,6 @@ extern const struct _mp_obj_module_t board_module;
#else
#define BOARD_MODULE
-#define BOARD_I2C_ROOT_POINTER
#define BOARD_UART_ROOT_POINTER
#endif
@@ -573,6 +573,7 @@ extern const struct _mp_obj_module_t ustack_module;
AUDIOBUSIO_MODULE \
AUDIOCORE_MODULE \
AUDIOIO_MODULE \
+ AUDIOPWMIO_MODULE \
BITBANGIO_MODULE \
BLEIO_MODULE \
BOARD_MODULE \
@@ -595,8 +596,8 @@ extern const struct _mp_obj_module_t ustack_module;
WIZNET_MODULE \
PEW_MODULE \
PIXELBUF_MODULE \
- PULSEIO_MODULE \
PS2IO_MODULE \
+ PULSEIO_MODULE \
RANDOM_MODULE \
RE_MODULE \
ROTARYIO_MODULE \
@@ -639,12 +640,12 @@ extern const struct _mp_obj_module_t ustack_module;
GAMEPAD_ROOT_POINTERS \
mp_obj_t pew_singleton; \
mp_obj_t terminal_tilegrid_tiles; \
- BOARD_I2C_ROOT_POINTER \
BOARD_UART_ROOT_POINTER \
FLASH_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \
void run_background_tasks(void);
+#define RUN_BACKGROUND_TASKS (run_background_tasks())
// TODO: Used in wiznet5k driver, but may not be needed in the long run.
#define MICROPY_THREAD_YIELD()
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index 772a1c3e1..a408cd7ac 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -74,9 +74,18 @@ CIRCUITPY_AUDIOIO = $(CIRCUITPY_FULL_BUILD)
endif
CFLAGS += -DCIRCUITPY_AUDIOIO=$(CIRCUITPY_AUDIOIO)
+ifndef CIRCUITPY_AUDIOPWMIO
+CIRCUITPY_AUDIOPWMIO = 0
+endif
+CFLAGS += -DCIRCUITPY_AUDIOPWMIO=$(CIRCUITPY_AUDIOPWMIO)
+
ifndef CIRCUITPY_AUDIOCORE
+ifeq ($(CIRCUITPY_AUDIOPWMIO),1)
+CIRCUITPY_AUDIOCORE = $(CIRCUITPY_AUDIOPWMIO)
+else
CIRCUITPY_AUDIOCORE = $(CIRCUITPY_AUDIOIO)
endif
+endif
CFLAGS += -DCIRCUITPY_AUDIOCORE=$(CIRCUITPY_AUDIOCORE)
ifndef CIRCUITPY_BITBANGIO
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 5b5ec1c37..8e3835d86 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -180,7 +180,7 @@ def compress(encoding_table, decompressed):
if not isinstance(decompressed, bytes):
raise TypeError()
values, lengths = encoding_table
- enc = bytearray(len(decompressed))
+ enc = bytearray(len(decompressed) * 2)
#print(decompressed)
#print(lengths)
current_bit = 7
@@ -227,6 +227,8 @@ def compress(encoding_table, decompressed):
current_bit -= 1
if current_bit != 7:
current_byte += 1
+ if current_byte > len(decompressed):
+ print("Note: compression increased length", repr(decompressed.decode('utf-8')), len(decompressed), current_byte, file=sys.stderr)
return enc[:current_byte]
def qstr_escape(qst):
diff --git a/py/obj.h b/py/obj.h
index 6eead377d..c719c2945 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -668,6 +668,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed);
mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items);
mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items);
+mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable);
mp_obj_t mp_obj_new_dict(size_t n_args);
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
diff --git a/py/objlist.c b/py/objlist.c
index 558c4c611..ea38e64e5 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -68,6 +68,11 @@ STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
return list;
}
+mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable) {
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+ return list_extend_from_iter(list, iterable);
+}
+
STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
(void)type_in;
mp_arg_check_num(n_args, kw_args, 0, 1, false);
diff --git a/py/objstr.c b/py/objstr.c
index ebd11d5cc..afe11f00f 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -41,6 +41,12 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
+const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'};
+
+const char nibble_to_hex_lower[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'};
+
/******************************************************************************/
/* str */
diff --git a/py/objstr.h b/py/objstr.h
index 0efe62a80..61a11d0bd 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -77,6 +77,9 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s
mp_obj_t index, bool is_slice);
const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction);
+const char nibble_to_hex_upper[16];
+const char nibble_to_hex_lower[16];
+
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj);
diff --git a/py/objtuple.c b/py/objtuple.c
index 474f81c1a..ed13cdcef 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -251,7 +251,8 @@ mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) {
}
void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {
- assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
+ // type check is done on getiter method to allow tuple, namedtuple, attrtuple
+ mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter);
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
*len = self->len;
*items = &self->items[0];
diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c
index 9f3f89462..6096f6b6d 100644
--- a/shared-bindings/_stage/__init__.c
+++ b/shared-bindings/_stage/__init__.c
@@ -50,7 +50,7 @@
//| Layer
//| Text
//|
-//| .. function:: render(x0, y0, x1, y1, layers, buffer, display)
+//| .. function:: render(x0, y0, x1, y1, layers, buffer, display[, scale])
//|
//| Render and send to the display a fragment of the screen.
//|
@@ -61,6 +61,7 @@
//| :param list layers: A list of the :py:class:`~_stage.Layer` objects.
//| :param bytearray buffer: A buffer to use for rendering.
//| :param ~displayio.Display display: The display to use.
+//| :param int scale: How many times should the image be scaled up.
//|
//| There are also no sanity checks, outside of the basic overflow
//| checking. The caller is responsible for making the passed parameters
@@ -89,11 +90,13 @@ STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) {
mp_raise_TypeError(translate("argument num/types mismatch"));
}
displayio_display_obj_t *display = MP_OBJ_TO_PTR(native_display);
+ uint8_t scale = 1;
+ if (n_args >= 8) {
+ scale = mp_obj_get_int(args[7]);
+ }
while (!displayio_display_begin_transaction(display)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
}
displayio_area_t area;
area.x1 = x0;
@@ -101,12 +104,15 @@ STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) {
area.x2 = x1;
area.y2 = y1;
displayio_display_set_region_to_update(display, &area);
- render_stage(x0, y0, x1, y1, layers, layers_size, buffer, buffer_size, display);
+
+ display->send(display->bus, true, &display->write_ram_command, 1);
+ render_stage(x0, y0, x1, y1, layers, layers_size, buffer, buffer_size,
+ display, scale);
displayio_display_end_transaction(display);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 7, stage_render);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 8, stage_render);
STATIC const mp_rom_map_elem_t stage_module_globals_table[] = {
diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c
index 980f11392..9bce9c760 100644
--- a/shared-bindings/audiobusio/I2SOut.c
+++ b/shared-bindings/audiobusio/I2SOut.c
@@ -56,7 +56,7 @@
//| using `UDA1334 Breakout <https://www.adafruit.com/product/3678>`_::
//|
//| import audiobusio
-//| import audioio
+//| import audiocore
//| import board
//| import array
//| import time
@@ -68,7 +68,7 @@
//| for i in range(length):
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
//|
-//| sine_wave = audiobusio.RawSample(sine_wave, sample_rate=8000)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
//| i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9)
//| i2s.play(sine_wave, loop=True)
//| time.sleep(1)
@@ -78,12 +78,13 @@
//|
//| import board
//| import audioio
+//| import audiocore
//| import audiobusio
//| import digitalio
//|
//|
//| f = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audioio.WaveFile(f)
+//| wav = audiocore.WaveFile(f)
//|
//| a = audiobusio.I2SOut(board.D1, board.D0, board.D9)
//|
@@ -163,7 +164,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_i2sout___exit___obj, 4, 4,
//| Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audioio.WaveFile` or `audioio.RawSample`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`.
//|
//| The sample itself should consist of 8 bit or 16 bit samples.
//|
diff --git a/shared-bindings/audiocore/Mixer.c b/shared-bindings/audiocore/Mixer.c
index 66babdd08..035c47cb0 100644
--- a/shared-bindings/audiocore/Mixer.c
+++ b/shared-bindings/audiocore/Mixer.c
@@ -38,7 +38,7 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
+//| .. currentmodule:: audiocore
//|
//| :class:`Mixer` -- Mixes one or more audio samples together
//| ===========================================================
diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c
index 912b48bfb..07f8c683f 100644
--- a/shared-bindings/audiocore/RawSample.c
+++ b/shared-bindings/audiocore/RawSample.c
@@ -35,7 +35,7 @@
#include "shared-bindings/audiocore/RawSample.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
+//| .. currentmodule:: audiocore
//|
//| :class:`RawSample` -- A raw audio sample buffer
//| ========================================================
@@ -55,6 +55,7 @@
//|
//| Simple 8ksps 440 Hz sin wave::
//|
+//| import audiocore
//| import audioio
//| import board
//| import array
@@ -68,7 +69,7 @@
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15))
//|
//| dac = audioio.AudioOut(board.SPEAKER)
-//| sine_wave = audioio.RawSample(sine_wave)
+//| sine_wave = audiocore.RawSample(sine_wave)
//| dac.play(sine_wave, loop=True)
//| time.sleep(1)
//| dac.stop()
diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c
index 4c1993b7c..1b3a94ff3 100644
--- a/shared-bindings/audiocore/WaveFile.c
+++ b/shared-bindings/audiocore/WaveFile.c
@@ -33,23 +33,27 @@
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
+//| .. currentmodule:: audiocore
//|
//| :class:`WaveFile` -- Load a wave file for audio playback
//| ========================================================
//|
//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
-//| be 8 bit unsigned or 16 bit signed.
+//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
+//| an internal buffer.
//|
-//| .. class:: WaveFile(file)
+//| .. class:: WaveFile(file[, buffer])
//|
//| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
//| :param typing.BinaryIO file: Already opened wave file
+//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally.
+//|
//|
//| Playing a wave file from flash::
//|
//| import board
+//| import audiocore
//| import audioio
//| import digitalio
//|
@@ -58,7 +62,7 @@
//| speaker_enable.switch_to_output(value=True)
//|
//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audioio.WaveFile(data)
+//| wav = audiocore.WaveFile(data)
//| a = audioio.AudioOut(board.A0)
//|
//| print("playing")
@@ -68,15 +72,23 @@
//| print("stopped")
//|
STATIC mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- mp_arg_check_num(n_args, kw_args, 1, 1, false);
+ mp_arg_check_num(n_args, kw_args, 1, 2, false);
audioio_wavefile_obj_t *self = m_new_obj(audioio_wavefile_obj_t);
self->base.type = &audioio_wavefile_type;
- if (MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) {
- common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]));
- } else {
+ if (!MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) {
mp_raise_TypeError(translate("file must be a file opened in byte mode"));
}
+ uint8_t *buffer = NULL;
+ size_t buffer_size = 0;
+ if (n_args >= 2) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
+ buffer = bufinfo.buf;
+ buffer_size = bufinfo.len;
+ }
+ common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]),
+ buffer, buffer_size);
return MP_OBJ_FROM_PTR(self);
}
diff --git a/shared-bindings/audiocore/WaveFile.h b/shared-bindings/audiocore/WaveFile.h
index d2572318b..f4a172319 100644
--- a/shared-bindings/audiocore/WaveFile.h
+++ b/shared-bindings/audiocore/WaveFile.h
@@ -35,7 +35,7 @@
extern const mp_obj_type_t audioio_wavefile_type;
void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
- pyb_file_obj_t* file);
+ pyb_file_obj_t* file, uint8_t *buffer, size_t buffer_size);
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self);
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self);
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index 79df66f7d..af2fce48e 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -55,6 +55,7 @@
//|
//| Simple 8ksps 440 Hz sin wave::
//|
+//| import audiocore
//| import audioio
//| import board
//| import array
@@ -68,7 +69,7 @@
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
//|
//| dac = audioio.AudioOut(board.SPEAKER)
-//| sine_wave = audioio.RawSample(sine_wave, sample_rate=8000)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
//| dac.play(sine_wave, loop=True)
//| time.sleep(1)
//| dac.stop()
@@ -84,7 +85,7 @@
//| speaker_enable.switch_to_output(value=True)
//|
//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audioio.WaveFile(data)
+//| wav = audiocore.WaveFile(data)
//| a = audioio.AudioOut(board.A0)
//|
//| print("playing")
@@ -162,7 +163,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_audioout___exit___obj, 4, 4,
//| Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audioio.WaveFile` or `audioio.RawSample`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`.
//|
//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output
//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit
diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c
new file mode 100644
index 000000000..92543d112
--- /dev/null
+++ b/shared-bindings/audiopwmio/PWMAudioOut.c
@@ -0,0 +1,294 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: audiopwmio
+//|
+//| :class:`PWMAudioOut` -- Output an analog audio signal
+//| ========================================================
+//|
+//| AudioOut can be used to output an analog audio signal on a given pin.
+//|
+//| .. class:: PWMAudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000)
+//|
+//| Create a PWMAudioOut object associated with the given pin(s). This allows you to
+//| play audio signals out on the given pin(s). In contrast to mod:`audioio`,
+//| the pin(s) specified are digital pins, and are driven with a device-dependent PWM
+//| signal.
+//|
+//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
+//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
+//| :param int quiescent_value: The output value when no signal is present. Samples should start
+//| and end with this value to prevent audible popping.
+//|
+//| Simple 8ksps 440 Hz sin wave::
+//|
+//| import audiocore
+//| import audiopwmio
+//| import board
+//| import array
+//| import time
+//| import math
+//|
+//| # Generate one period of sine wav.
+//| length = 8000 // 440
+//| sine_wave = array.array("H", [0] * length)
+//| for i in range(length):
+//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
+//|
+//| dac = audiopwmio.PWMAudioOut(board.SPEAKER)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
+//| dac.play(sine_wave, loop=True)
+//| time.sleep(1)
+//| dac.stop()
+//|
+//| Playing a wave file from flash::
+//|
+//| import board
+//| import audiocore
+//| import audiopwmio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audiocore.WaveFile(data)
+//| a = audiopwmio.PWMAudioOut(board.SPEAKER)
+//|
+//| print("playing")
+//| a.play(wav)
+//| while a.playing:
+//| pass
+//| print("stopped")
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_left_channel, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_right_channel, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = mp_const_none} },
+ { MP_QSTR_quiescent_value, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x8000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t left_channel_obj = args[ARG_left_channel].u_obj;
+ assert_pin(left_channel_obj, false);
+ const mcu_pin_obj_t *left_channel_pin = MP_OBJ_TO_PTR(left_channel_obj);
+
+ mp_obj_t right_channel_obj = args[ARG_right_channel].u_obj;
+ const mcu_pin_obj_t *right_channel_pin = NULL;
+ if (right_channel_obj != mp_const_none) {
+ assert_pin(right_channel_obj, false);
+ right_channel_pin = MP_OBJ_TO_PTR(right_channel_obj);
+ }
+
+ // create AudioOut object from the given pin
+ audiopwmio_pwmaudioout_obj_t *self = m_new_obj(audiopwmio_pwmaudioout_obj_t);
+ self->base.type = &audiopwmio_pwmaudioout_type;
+ common_hal_audiopwmio_pwmaudioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the PWMAudioOut and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_deinit(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_audiopwmio_pwmaudioout_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_deinit_obj, audiopwmio_pwmaudioout_deinit);
+
+STATIC void check_for_deinit(audiopwmio_pwmaudioout_obj_t *self) {
+ if (common_hal_audiopwmio_pwmaudioout_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+//| .. method:: __enter__()
+//|
+//| No-op used by Context Managers.
+//|
+// Provided by context manager helper.
+
+//| .. method:: __exit__()
+//|
+//| Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_audiopwmio_pwmaudioout_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiopwmio_pwmaudioout___exit___obj, 4, 4, audiopwmio_pwmaudioout_obj___exit__);
+
+
+//| .. method:: play(sample, *, loop=False)
+//|
+//| Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
+//|
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiocore.Mixer`.
+//|
+//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output
+//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit
+//| DAC that ignores the lowest 6 bits when playing 16 bit samples.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sample, ARG_loop };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ check_for_deinit(self);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t sample = args[ARG_sample].u_obj;
+ common_hal_audiopwmio_pwmaudioout_play(self, sample, args[ARG_loop].u_bool);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audiopwmio_pwmaudioout_play_obj, 1, audiopwmio_pwmaudioout_obj_play);
+
+//| .. method:: stop()
+//|
+//| Stops playback and resets to the start of the sample.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_stop(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_stop_obj, audiopwmio_pwmaudioout_obj_stop);
+
+//| .. attribute:: playing
+//|
+//| True when an audio sample is being output even if `paused`. (read-only)
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_playing(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_bool(common_hal_audiopwmio_pwmaudioout_get_playing(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_get_playing_obj, audiopwmio_pwmaudioout_obj_get_playing);
+
+const mp_obj_property_t audiopwmio_pwmaudioout_playing_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiopwmio_pwmaudioout_get_playing_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. method:: pause()
+//|
+//| Stops playback temporarily while remembering the position. Use `resume` to resume playback.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_pause(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ if (!common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ mp_raise_RuntimeError(translate("Not playing"));
+ }
+ common_hal_audiopwmio_pwmaudioout_pause(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_pause_obj, audiopwmio_pwmaudioout_obj_pause);
+
+//| .. method:: resume()
+//|
+//| Resumes sample playback after :py:func:`pause`.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_resume(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ if (common_hal_audiopwmio_pwmaudioout_get_paused(self)) {
+ common_hal_audiopwmio_pwmaudioout_resume(self);
+ }
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_resume_obj, audiopwmio_pwmaudioout_obj_resume);
+
+//| .. attribute:: paused
+//|
+//| True when playback is paused. (read-only)
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_paused(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_bool(common_hal_audiopwmio_pwmaudioout_get_paused(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_get_paused_obj, audiopwmio_pwmaudioout_obj_get_paused);
+
+const mp_obj_property_t audiopwmio_pwmaudioout_paused_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiopwmio_pwmaudioout_get_paused_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t audiopwmio_pwmaudioout_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiopwmio_pwmaudioout_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiopwmio_pwmaudioout___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiopwmio_pwmaudioout_play_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiopwmio_pwmaudioout_stop_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&audiopwmio_pwmaudioout_pause_obj) },
+ { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&audiopwmio_pwmaudioout_resume_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiopwmio_pwmaudioout_playing_obj) },
+ { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&audiopwmio_pwmaudioout_paused_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(audiopwmio_pwmaudioout_locals_dict, audiopwmio_pwmaudioout_locals_dict_table);
+
+const mp_obj_type_t audiopwmio_pwmaudioout_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PWMAudioOut,
+ .make_new = audiopwmio_pwmaudioout_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audiopwmio_pwmaudioout_locals_dict,
+};
diff --git a/shared-bindings/audiopwmio/PWMAudioOut.h b/shared-bindings/audiopwmio/PWMAudioOut.h
new file mode 100644
index 000000000..22afc70d3
--- /dev/null
+++ b/shared-bindings/audiopwmio/PWMAudioOut.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H
+
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/audiocore/RawSample.h"
+
+extern const mp_obj_type_t audiopwmio_pwmaudioout_type;
+
+// left_channel will always be non-NULL but right_channel may be for mono output.
+void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t default_value);
+
+void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self);
+bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self);
+void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop);
+void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self);
+bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self);
+void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self);
+void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self);
+bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H
diff --git a/shared-bindings/audiopwmio/__init__.c b/shared-bindings/audiopwmio/__init__.c
new file mode 100644
index 000000000..8a2b202b3
--- /dev/null
+++ b/shared-bindings/audiopwmio/__init__.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiopwmio/__init__.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+
+//| :mod:`audiopwmio` --- Support for audio input and output
+//| ========================================================
+//|
+//| .. module:: audiopwmio
+//| :synopsis: Support for audio output via digital PWM
+//| :platform: NRF52
+//|
+//| The `audiopwmio` module contains classes to provide access to audio IO.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| PWMAudioOut
+//|
+//| All classes change hardware state and should be deinitialized when they
+//| are no longer needed if the program continues after use. To do so, either
+//| call :py:meth:`!deinit` or use a context manager. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+//| Since CircuitPython 5, `Mixer`, `RawSample` and `WaveFile` are moved
+//| to :mod:`audiocore`.
+//|
+
+STATIC const mp_rom_map_elem_t audiopwmio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiopwmio) },
+ { MP_ROM_QSTR(MP_QSTR_PWMAudioOut), MP_ROM_PTR(&audiopwmio_pwmaudioout_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(audiopwmio_module_globals, audiopwmio_module_globals_table);
+
+const mp_obj_module_t audiopwmio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&audiopwmio_module_globals,
+};
diff --git a/shared-bindings/audiopwmio/__init__.h b/shared-bindings/audiopwmio/__init__.h
new file mode 100644
index 000000000..e4b7067d1
--- /dev/null
+++ b/shared-bindings/audiopwmio/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
diff --git a/shared-bindings/bleio/Adapter.c b/shared-bindings/bleio/Adapter.c
index 7b8df5103..2bb7f3465 100644
--- a/shared-bindings/bleio/Adapter.c
+++ b/shared-bindings/bleio/Adapter.c
@@ -53,12 +53,6 @@
//|
//| State of the BLE adapter.
//|
-
-//| .. attribute:: adapter.address
-//|
-//| MAC address of the BLE adapter. (read-only)
-//|
-
STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) {
return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled());
}
@@ -80,13 +74,13 @@ const mp_obj_property_t bleio_adapter_enabled_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: adapter.address
+//|
+//| MAC address of the BLE adapter. (read-only)
+//|
STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
- mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, mp_const_none);
- bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj);
-
- common_hal_bleio_adapter_get_address(address);
+ return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address());
- return obj;
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address);
@@ -97,9 +91,29 @@ const mp_obj_property_t bleio_adapter_address_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: adapter.default_name
+//|
+//| default_name of the BLE adapter. (read-only)
+//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
+//| to make it easy to distinguish multiple CircuitPython boards.
+//|
+STATIC mp_obj_t bleio_adapter_get_default_name(mp_obj_t self) {
+ return common_hal_bleio_adapter_get_default_name();
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_default_name_obj, bleio_adapter_get_default_name);
+
+const mp_obj_property_t bleio_adapter_default_name_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_adapter_get_default_name_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&bleio_adapter_enabled_obj) },
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_adapter_address_obj) },
+ { MP_ROM_QSTR(MP_QSTR_default_name), MP_ROM_PTR(&bleio_adapter_default_name_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table);
diff --git a/shared-bindings/bleio/Adapter.h b/shared-bindings/bleio/Adapter.h
index de9d1d6db..72382616c 100644
--- a/shared-bindings/bleio/Adapter.h
+++ b/shared-bindings/bleio/Adapter.h
@@ -34,6 +34,7 @@ const mp_obj_type_t bleio_adapter_type;
extern bool common_hal_bleio_adapter_get_enabled(void);
extern void common_hal_bleio_adapter_set_enabled(bool enabled);
-extern void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address);
+extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(void);
+extern mp_obj_t common_hal_bleio_adapter_get_default_name(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c
index 37f01042c..baeb6d7c0 100644
--- a/shared-bindings/bleio/Address.c
+++ b/shared-bindings/bleio/Address.c
@@ -83,7 +83,21 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
//| .. attribute:: address_bytes
//|
-//| The bytes that make up the device address (read-only)
+//| The bytes that make up the device address (read-only).
+//|
+//| Note that the ``bytes`` object returned is in little-endian order:
+//| The least significant byte is ``address_bytes[0]``. So the address will
+//| appear to be reversed if you print the raw ``bytes`` object. If you print
+//| or use `str()` on the :py:class:`~bleio.Attribute` object itself, the address will be printed
+//| in the expected order. For example:
+//|
+//| .. code-block:: pycon
+//|
+//| >>> import bleio
+//| >>> bleio.adapter.address
+//| <Address c8:1d:f5:ed:a8:35>
+//| >>> bleio.adapter.address.address_bytes
+//| b'5\xa8\xed\xf5\x1d\xc8'
//|
STATIC mp_obj_t bleio_address_get_address_bytes(mp_obj_t self_in) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -147,18 +161,13 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o
STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (kind == PRINT_STR) {
- mp_buffer_info_t buf_info;
- mp_obj_t address_bytes = common_hal_bleio_address_get_address_bytes(self);
- mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ);
-
- const uint8_t *buf = (uint8_t *) buf_info.buf;
- mp_printf(print,
- "%02x:%02x:%02x:%02x:%02x:%02x",
- buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
- } else {
- mp_printf(print, "<Address>");
- }
+ mp_buffer_info_t buf_info;
+ mp_obj_t address_bytes = common_hal_bleio_address_get_address_bytes(self);
+ mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ);
+
+ const uint8_t *buf = (uint8_t *) buf_info.buf;
+ mp_printf(print, "<Address %02x:%02x:%02x:%02x:%02x:%02x>",
+ buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
}
//| .. data:: PUBLIC
@@ -179,13 +188,13 @@ STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
//| A randomly generated address that changes on every connection.
//|
STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) },
- { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) },
+ { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) },
+ { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) },
// These match the BLE_GAP_ADDR_TYPES values used by the nRF library.
- { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_OBJ_NEW_SMALL_INT(0) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_OBJ_NEW_SMALL_INT(1) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(2) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(3) },
+ { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_INT(0) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_INT(1) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_INT(2) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_INT(3) },
};
diff --git a/shared-bindings/bleio/Attribute.c b/shared-bindings/bleio/Attribute.c
new file mode 100644
index 000000000..2cc9ef6d0
--- /dev/null
+++ b/shared-bindings/bleio/Attribute.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/UUID.h"
+
+//
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Attribute` -- BLE Attribute
+//| =========================================================
+//|
+//| Definitions associated with all BLE attributes: characteristics, descriptors, etc.
+//| :py:class:`~bleio.Attribute` is, notionally, a superclass of
+//| :py:class:`~Characteristic` and :py:class:`~Descriptor`,
+//| but is not defined as a Python superclass of those classes.
+//|
+//| .. class:: Attribute()
+//|
+//| You cannot create an instance of :py:class:`~bleio.Attribute`.
+//|
+
+STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = {
+
+//| .. data:: NO_ACCESS
+//|
+//| security mode: access not allowed
+//|
+//| .. data:: OPEN
+//|
+//| security_mode: no security (link is not encrypted)
+//|
+//| .. data:: ENCRYPT_NO_MITM
+//|
+//| security_mode: unauthenticated encryption, without man-in-the-middle protection
+//|
+//| .. data:: ENCRYPT_WITH_MITM
+//|
+//| security_mode: authenticated encryption, with man-in-the-middle protection
+//|
+//| .. data:: LESC_ENCRYPT_WITH_MITM
+//|
+//| security_mode: LESC encryption, with man-in-the-middle protection
+//|
+//| .. data:: SIGNED_NO_MITM
+//|
+//| security_mode: unauthenticated data signing, without man-in-the-middle protection
+//|
+//| .. data:: SIGNED_WITH_MITM
+//|
+//| security_mode: authenticated data signing, without man-in-the-middle protection
+//|
+ { MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SECURITY_MODE_NO_ACCESS) },
+ { MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SECURITY_MODE_OPEN) },
+ { MP_ROM_QSTR(MP_QSTR_ENCRYPT_NO_MITM), MP_ROM_INT(SECURITY_MODE_ENC_NO_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_ENCRYPT_WITH_MITM), MP_ROM_INT(SECURITY_MODE_ENC_WITH_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_LESC_ENCRYPT_WITH_MITM), MP_ROM_INT(SECURITY_MODE_LESC_ENC_WITH_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_SIGNED_NO_MITM), MP_ROM_INT(SECURITY_MODE_SIGNED_NO_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_SIGNED_WITH_MITM), MP_ROM_INT(SECURITY_MODE_SIGNED_WITH_MITM) },
+
+};
+STATIC MP_DEFINE_CONST_DICT(bleio_attribute_locals_dict, bleio_attribute_locals_dict_table);
+
+const mp_obj_type_t bleio_attribute_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Attribute,
+ .locals_dict = (mp_obj_dict_t*)&bleio_attribute_locals_dict,
+};
diff --git a/shared-bindings/bleio/Attribute.h b/shared-bindings/bleio/Attribute.h
new file mode 100644
index 000000000..06a6eb5a9
--- /dev/null
+++ b/shared-bindings/bleio/Attribute.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H
+
+#include "py/obj.h"
+
+#include "shared-module/bleio/Attribute.h"
+
+extern const mp_obj_type_t bleio_attribute_type;
+
+extern void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H
diff --git a/shared-bindings/bleio/Central.c b/shared-bindings/bleio/Central.c
index fc00bce5c..1fc455d8d 100644
--- a/shared-bindings/bleio/Central.c
+++ b/shared-bindings/bleio/Central.c
@@ -56,12 +56,16 @@
//|
//| my_entry = None
//| for entry in entries:
-//| if entry.name is not None and entry.name == 'MyPeripheral':
+//| if entry.name is not None and entry.name == 'InterestingPeripheral':
//| my_entry = entry
//| break
//|
-//| central = bleio.Central(my_entry.address)
-//| central.connect(10.0) # timeout after 10 seconds
+//| if not my_entry:
+//| raise Exception("'InterestingPeripheral' not found")
+//|
+//| central = bleio.Central()
+//| central.connect(my_entry.address, 10) # timeout after 10 seconds
+//| remote_services = central.discover_remote_services()
//|
//| .. class:: Central()
@@ -79,24 +83,11 @@ STATIC mp_obj_t bleio_central_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: connect(address, timeout, *, service_uuids=None)
-//| Attempts a connection to the remote peripheral. If the connection is successful,
-//| Do BLE discovery for the listed services, to find their handles and characteristics.
-//| The attribute `remote_services` will contain a list of all discovered services.
+//| .. method:: connect(address, timeout, *, service_uuids_whitelist=None)
+//| Attempts a connection to the remote peripheral.
//|
//| :param bleio.Address address: The address of the peripheral to connect to
//| :param float/int timeout: Try to connect for timeout seconds.
-//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services
-//| provided by the peripheral that you want to use.
-//| The peripheral may provide more services, but services not listed are ignored.
-//| If a service in service_uuids is not found during discovery, it will not
-//| appear in `remote_services`.
-//|
-//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
-//|
-//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
-//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
-//| service or characteristic to be discovered. (This restriction may be lifted in the future.)
//|
STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -105,7 +96,6 @@ STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_service_uuids_whitelist, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -119,7 +109,7 @@ STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args
mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
// common_hal_bleio_central_connect() will validate that services is an iterable or None.
- common_hal_bleio_central_connect(self, address, timeout, args[ARG_service_uuids_whitelist].u_obj);
+ common_hal_bleio_central_connect(self, address, timeout);
return mp_const_none;
}
@@ -139,6 +129,46 @@ STATIC mp_obj_t bleio_central_disconnect(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_disconnect);
+//| .. method:: discover_remote_services(service_uuids_whitelist=None)
+//| Do BLE discovery for all services or for the given service UUIDS,
+//| to find their handles and characteristics, and return the discovered services.
+//| `Peripheral.connected` must be True.
+//|
+//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services
+//| provided by the peripheral that you want to use.
+//| The peripheral may provide more services, but services not listed are ignored
+//| and will not be returned.
+//|
+//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
+//|
+//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
+//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
+//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered
+//| for use. (This restriction may be lifted in the future.)
+//|
+//| :return: A tuple of services provided by the remote peripheral.
+//|
+STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_service_uuids_whitelist };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ if (!common_hal_bleio_central_get_connected(self)) {
+ mp_raise_ValueError(translate("Not connected"));
+ }
+
+ return MP_OBJ_FROM_PTR(common_hal_bleio_central_discover_remote_services(
+ MP_OBJ_FROM_PTR(self),
+ args[ARG_service_uuids_whitelist].u_obj));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services);
+
//| .. attribute:: connected
//|
//| True if connected to a remove peripheral.
@@ -157,36 +187,14 @@ const mp_obj_property_t bleio_central_connected_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-
-//| .. attribute:: remote_services (read-only)
-//|
-//| A tuple of services provided by the remote peripheral.
-//| If the Central is not connected, an empty tuple will be returned.
-//|
-STATIC mp_obj_t bleio_central_get_remote_services(mp_obj_t self_in) {
- bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- // Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *service_list = common_hal_bleio_central_get_remote_services(self);
- return mp_obj_new_tuple(service_list->len, service_list->items);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_get_remote_services_obj, bleio_central_get_remote_services);
-
-const mp_obj_property_t bleio_central_remote_services_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_central_get_remote_services_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = {
// Methods
- { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_central_discover_remote_services_obj) },
// Properties
{ MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_remote_services), MP_ROM_PTR(&bleio_central_remote_services_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_central_locals_dict, bleio_central_locals_dict_table);
diff --git a/shared-bindings/bleio/Central.h b/shared-bindings/bleio/Central.h
index 0e84037f9..cbc437087 100644
--- a/shared-bindings/bleio/Central.h
+++ b/shared-bindings/bleio/Central.h
@@ -28,15 +28,16 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
+#include "py/objtuple.h"
#include "common-hal/bleio/Central.h"
#include "common-hal/bleio/Service.h"
extern const mp_obj_type_t bleio_central_type;
extern void common_hal_bleio_central_construct(bleio_central_obj_t *self);
-extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids);
+extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout);
extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self);
extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self);
-extern mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self);
+extern mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c
index 3bf0476ab..4894ad114 100644
--- a/shared-bindings/bleio/Characteristic.c
+++ b/shared-bindings/bleio/Characteristic.c
@@ -28,7 +28,9 @@
#include "py/objproperty.h"
#include "py/runtime.h"
+#include "shared-bindings/bleio/Attribute.h"
#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Descriptor.h"
#include "shared-bindings/bleio/UUID.h"
//| .. currentmodule:: bleio
@@ -40,30 +42,36 @@
//| and writing of the characteristic's value.
//|
//|
-//| .. class:: Characteristic(uuid, *, broadcast=False, indicate=False, notify=False, read=False, write=False, write_no_response=False)
+//| .. class:: Characteristic(uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, descriptors=None)
//|
//| Create a new Characteristic object identified by the specified UUID.
//|
//| :param bleio.UUID uuid: The uuid of the characteristic
-//| :param bool broadcast: Allowed in advertising packets
-//| :param bool indicate: Server will indicate to the client when the value is set and wait for a response
-//| :param bool notify: Server will notify the client when the value is set
-//| :param bool read: Clients may read this characteristic
-//| :param bool write: Clients may write this characteristic; a response will be sent back
-//| :param bool write_no_response: Clients may write this characteristic; no response will be sent back
+//| :param int properties: bitmask of these values bitwise-or'd together: `BROADCAST`, `INDICATE`,
+//| `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`
+//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which
+//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
+//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
+//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
+//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which
+//| security mode is required. Values allowed are the same as ``read_perm``.
+//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
+//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
+//| number of data bytes that fit in a single BLE 4.x ATT packet.
+//| :param bool fixed_length: True if the characteristic value is of fixed length.
+//| :param iterable descriptors: BLE descriptors for this characteristic.
//|
STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum {
- ARG_uuid, ARG_broadcast, ARG_indicate, ARG_notify, ARG_read, ARG_write, ARG_write_no_response,
- };
+ enum { ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm,
+ ARG_max_length, ARG_fixed_length, ARG_descriptors };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_broadcast, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_indicate, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_notify, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_read, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_write, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_write_no_response, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
+ { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
+ { 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_descriptors, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -76,129 +84,69 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t
}
bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
- bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t);
- self->base.type = &bleio_characteristic_type;
-
- bleio_characteristic_properties_t properties;
-
- properties.broadcast = args[ARG_broadcast].u_bool;
- properties.indicate = args[ARG_indicate].u_bool;
- properties.notify = args[ARG_notify].u_bool;
- properties.read = args[ARG_read].u_bool;
- properties.write = args[ARG_write].u_bool;
- properties.write_no_response = args[ARG_write_no_response].u_bool;
-
- // Initialize, with an empty descriptor list.
- common_hal_bleio_characteristic_construct(self, uuid, properties, mp_obj_new_list(0, NULL));
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-//| .. attribute:: broadcast
-//|
-//| A `bool` specifying if the characteristic allows broadcasting its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).broadcast);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast);
-
-const mp_obj_property_t bleio_characteristic_broadcast_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: indicate
-//|
-//| A `bool` specifying if the characteristic allows indicating its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).indicate);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate);
-
-
-const mp_obj_property_t bleio_characteristic_indicate_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: notify
-//|
-//| A `bool` specifying if the characteristic allows notifying its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ const bleio_characteristic_properties_t properties = args[ARG_properties].u_int;
+ if (properties & ~CHAR_PROP_ALL) {
+ mp_raise_ValueError(translate("Invalid properties"));
+ }
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).notify);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify);
+ const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(read_perm);
-const mp_obj_property_t bleio_characteristic_notify_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
+ const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(write_perm);
-//| .. attribute:: read
-//|
-//| A `bool` specifying if the characteristic allows reading its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_t descriptors = args[ARG_descriptors].u_obj;
+ if (descriptors == mp_const_none) {
+ descriptors = mp_const_empty_tuple;
+ }
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).read);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read);
+ bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t);
+ self->base.type = &bleio_characteristic_type;
-const mp_obj_property_t bleio_characteristic_read_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
+ // Copy the descriptors list and validate its items.
+ mp_obj_t desc_list_obj = mp_obj_new_list(0, NULL);
+ mp_obj_list_t *desc_list = MP_OBJ_TO_PTR(desc_list_obj);
+
+ // If descriptors is not an iterable, an exception will be thrown.
+ mp_obj_iter_buf_t iter_buf;
+ mp_obj_t descriptors_iter = mp_getiter(descriptors, &iter_buf);
+
+ mp_obj_t descriptor_obj;
+ while ((descriptor_obj = mp_iternext(descriptors_iter)) != MP_OBJ_STOP_ITERATION) {
+ if (!MP_OBJ_IS_TYPE(descriptor_obj, &bleio_descriptor_type)) {
+ mp_raise_ValueError(translate("descriptors includes an object that is not a Descriptors"));
+ }
+ bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(descriptor_obj);
+ if (common_hal_bleio_descriptor_get_characteristic(descriptor) != MP_OBJ_NULL) {
+ mp_raise_ValueError(translate("Descriptor is already attached to a Characteristic"));
+ }
+ mp_obj_list_append(desc_list_obj, descriptor_obj);
+ }
-//| .. attribute:: write
-//|
-//| A `bool` specifying if the characteristic allows writing to its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ // Range checking on max_length arg is done by the common_hal layer, because
+ // it may vary depending on underlying BLE implementation.
+ common_hal_bleio_characteristic_construct(self, uuid, properties,
+ read_perm, write_perm,
+ args[ARG_max_length].u_int, args[ARG_fixed_length].u_bool,
+ desc_list);
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).write);
+ return MP_OBJ_FROM_PTR(self);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write);
-const mp_obj_property_t bleio_characteristic_write_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: write_no_response
+//| .. attribute:: properties
//|
-//| A `bool` specifying if the characteristic allows writing to its value without response. (read-only)
+//| An int bitmask representing which properties are set.
//|
-STATIC mp_obj_t bleio_characteristic_get_write_no_response(mp_obj_t self_in) {
+STATIC mp_obj_t bleio_characteristic_get_properties(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).write_no_response);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_properties(self));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_no_response_obj, bleio_characteristic_get_write_no_response);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_properties_obj, bleio_characteristic_get_properties);
-const mp_obj_property_t bleio_characteristic_write_no_response_obj = {
+const mp_obj_property_t bleio_characteristic_properties_obj = {
.base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_write_no_response_obj,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_properties_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj },
};
@@ -225,9 +173,7 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = {
//| .. attribute:: value
//|
-//| The value of this characteristic. The value can be written to if the `write` property allows it.
-//| If the `read` property allows it, the value can be read. If the `notify` property is set, writing
-//| to the value will generate a BLE notification.
+//| The value of this characteristic.
//|
STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -274,6 +220,24 @@ const mp_obj_property_t bleio_characteristic_descriptors_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: service (read-only)
+//|
+//| The Service this Characteristic is a part of. None if not yet assigned to a Service.
+//|
+STATIC mp_obj_t bleio_characteristic_get_service(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_bleio_characteristic_get_service(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_service_obj, bleio_characteristic_get_service);
+
+const mp_obj_property_t bleio_characteristic_service_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_service_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
//| .. method:: set_cccd(*, notify=False, indicate=False)
//|
//| Set the remote characteristic's CCCD to enable or disable notification and indication.
@@ -301,16 +265,43 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_ch
STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&bleio_characteristic_broadcast_obj) },
- { MP_ROM_QSTR(MP_QSTR_descriptors), MP_ROM_PTR(&bleio_characteristic_descriptors_obj) },
- { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&bleio_characteristic_indicate_obj) },
- { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&bleio_characteristic_notify_obj) },
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&bleio_characteristic_read_obj) },
- { MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
- { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
- { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) },
- { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_obj) },
- { MP_ROM_QSTR(MP_QSTR_write_no_response), MP_ROM_PTR(&bleio_characteristic_write_no_response_obj) },
+ { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties) },
+ { MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) },
+
+ // Bitmask constants to represent properties
+//| .. data:: BROADCAST
+//|
+//| property: allowed in advertising packets
+//|
+//| .. data:: INDICATE
+//|
+//| property: server will indicate to the client when the value is set and wait for a response
+//|
+//| .. data:: NOTIFY
+//|
+//| property: server will notify the client when the value is set
+//|
+//| .. data:: READ
+//|
+//| property: clients may read this characteristic
+//|
+//| .. data:: WRITE
+//|
+//| property: clients may write this characteristic; a response will be sent back
+//|
+//| .. data:: WRITE_NO_RESPONSE
+//|
+//| property: clients may write this characteristic; no response will be sent back
+//|
+ { MP_ROM_QSTR(MP_QSTR_BROADCAST), MP_ROM_INT(CHAR_PROP_BROADCAST) },
+ { MP_ROM_QSTR(MP_QSTR_INDICATE), MP_ROM_INT(CHAR_PROP_INDICATE) },
+ { MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(CHAR_PROP_NOTIFY) },
+ { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(CHAR_PROP_READ) },
+ { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(CHAR_PROP_WRITE) },
+ { MP_ROM_QSTR(MP_QSTR_WRITE_NO_RESPONSE), MP_ROM_INT(CHAR_PROP_WRITE_NO_RESPONSE) },
+
};
STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table);
@@ -330,5 +321,5 @@ const mp_obj_type_t bleio_characteristic_type = {
.name = MP_QSTR_Characteristic,
.make_new = bleio_characteristic_make_new,
.print = bleio_characteristic_print,
- .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict
+ .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict,
};
diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h
index d450c42b4..87942c8e9 100644
--- a/shared-bindings/bleio/Characteristic.h
+++ b/shared-bindings/bleio/Characteristic.h
@@ -28,17 +28,19 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
+#include "shared-bindings/bleio/Attribute.h"
#include "shared-module/bleio/Characteristic.h"
#include "common-hal/bleio/Characteristic.h"
extern const mp_obj_type_t bleio_characteristic_type;
-extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list);
+extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, 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_obj_list_t *descriptor_list);
extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self);
extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self);
extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self);
extern mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self);
+extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self);
extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c
index f2e5aa01d..d7c2a85c7 100644
--- a/shared-bindings/bleio/Descriptor.c
+++ b/shared-bindings/bleio/Descriptor.c
@@ -28,6 +28,7 @@
#include "py/objproperty.h"
#include "py/runtime.h"
+#include "shared-bindings/bleio/Attribute.h"
#include "shared-bindings/bleio/Descriptor.h"
#include "shared-bindings/bleio/UUID.h"
@@ -41,23 +42,30 @@
//| information about the characteristic.
//|
-//| .. class:: Descriptor(uuid)
+//| .. class:: Descriptor(uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`)
//|
-//| Create a new descriptor object with the UUID uuid.
-
-//| .. attribute:: handle
-//|
-//| The descriptor handle. (read-only)
-//|
-
-//| .. attribute:: uuid
+//| Create a new descriptor object with the UUID uuid
//|
-//| The descriptor uuid. (read-only)
+//| :param bleio.UUID uuid: The uuid of the descriptor
+//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which
+//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
+//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
+//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
+//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which
+//| security mode is required. Values allowed are the same as ``read_perm``.
+//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
+//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
+//| number of data bytes that fit in a single BLE 4.x ATT packet.
+//| :param bool fixed_length: True if the characteristic value is of fixed length.
//|
STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_uuid };
+ enum { ARG_uuid, ARG_read_perm, ARG_write_perm, ARG_max_length, ARG_fixed_length };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN } },
+ { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN } },
+ { 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_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -69,28 +77,28 @@ STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_ar
mp_raise_ValueError(translate("Expected a UUID"));
}
+ const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(read_perm);
+
+ const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(write_perm);
+
bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t);
self->base.type = type;
bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_arg);
- common_hal_bleio_descriptor_construct(self, uuid);
-
- return MP_OBJ_FROM_PTR(self);
-}
-STATIC mp_obj_t bleio_descriptor_get_handle(mp_obj_t self_in) {
- bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ // Range checking on max_length arg is done by the common_hal layer, because
+ // it may vary depending on underlying BLE implementation.
+ common_hal_bleio_descriptor_construct(self, uuid, read_perm, write_perm,
+ args[ARG_max_length].u_int, args[ARG_fixed_length].u_bool);
- return mp_obj_new_int(common_hal_bleio_descriptor_get_handle(self));
+ return MP_OBJ_FROM_PTR(self);
}
-MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_handle_obj, bleio_descriptor_get_handle);
-
-const mp_obj_property_t bleio_descriptor_handle_obj = {
- .base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&bleio_descriptor_get_handle_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj},
-};
+//| .. attribute:: uuid
+//|
+//| The descriptor uuid. (read-only)
+//|
STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) {
bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -106,56 +114,59 @@ const mp_obj_property_t bleio_descriptor_uuid_obj = {
(mp_obj_t)&mp_const_none_obj},
};
-STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
- // Properties
- { MP_ROM_QSTR(MP_QSTR_handle), MP_ROM_PTR(&bleio_descriptor_handle_obj) },
- { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
-
- // Static variables
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_EXTENDED_PROPERTIES) },
-
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION) },
-
- { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION),
- MP_ROM_INT(DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION) },
-
- { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION),
- MP_ROM_INT(DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION) },
-
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_PRESENTATION_FORMAT) },
+//| .. attribute:: characteristic (read-only)
+//|
+//| The Characteristic this Descriptor is a part of. None if not yet assigned to a Characteristic.
+//|
+STATIC mp_obj_t bleio_descriptor_get_characteristic(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_AGGREGATE_FORMAT) },
+ return common_hal_bleio_descriptor_get_characteristic(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_characteristic_obj, bleio_descriptor_get_characteristic);
- { MP_ROM_QSTR(MP_QSTR_VALID_RANGE),
- MP_ROM_INT(DESCRIPTOR_UUID_VALID_RANGE) },
+const mp_obj_property_t bleio_descriptor_characteristic_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_descriptor_get_characteristic_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
- { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE),
- MP_ROM_INT(DESCRIPTOR_UUID_EXTERNAL_REPORT_REFERENCE) },
+//| .. attribute:: value
+//|
+//| The value of this descriptor.
+//|
+STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
- { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE),
- MP_ROM_INT(DESCRIPTOR_UUID_REPORT_REFERENCE) },
+ return common_hal_bleio_descriptor_get_value(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_value_obj, bleio_descriptor_get_value);
- { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS),
- MP_ROM_INT(DESCRIPTOR_UUID_NUMBER_OF_DIGITALS) },
+STATIC mp_obj_t bleio_descriptor_set_value(mp_obj_t self_in, mp_obj_t value_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
- { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING),
- MP_ROM_INT(DESCRIPTOR_UUID_VALUE_TRIGGER_SETTING) },
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ);
- { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION),
- MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_CONFIGURATION) },
+ common_hal_bleio_descriptor_set_value(self, &bufinfo);
- { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ),
- MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_MEASUREMENT) },
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_descriptor_set_value_obj, bleio_descriptor_set_value);
- { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING),
- MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_TRIGGER_SETTING) },
+const mp_obj_property_t bleio_descriptor_value_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_descriptor_get_value_obj,
+ (mp_obj_t)&bleio_descriptor_set_value_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
- { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING),
- MP_ROM_INT(DESCRIPTOR_UUID_TIME_TRIGGER_SETTING) },
+STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_characteristic), MP_ROM_PTR(&bleio_descriptor_characteristic_obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_descriptor_value_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table);
diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h
index fd11ea08c..430c0d0b6 100644
--- a/shared-bindings/bleio/Descriptor.h
+++ b/shared-bindings/bleio/Descriptor.h
@@ -28,31 +28,16 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
+#include "shared-module/bleio/Attribute.h"
#include "common-hal/bleio/Descriptor.h"
#include "common-hal/bleio/UUID.h"
-enum {
- DESCRIPTOR_UUID_CHARACTERISTIC_EXTENDED_PROPERTIES = 0x2900,
- DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION = 0x2901,
- DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION = 0x2902,
- DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION = 0x2903,
- DESCRIPTOR_UUID_CHARACTERISTIC_PRESENTATION_FORMAT = 0x2904,
- DESCRIPTOR_UUID_CHARACTERISTIC_AGGREGATE_FORMAT = 0x2905,
- DESCRIPTOR_UUID_VALID_RANGE = 0x2906,
- DESCRIPTOR_UUID_EXTERNAL_REPORT_REFERENCE = 0x2907,
- DESCRIPTOR_UUID_REPORT_REFERENCE = 0x2908,
- DESCRIPTOR_UUID_NUMBER_OF_DIGITALS = 0x2909,
- DESCRIPTOR_UUID_VALUE_TRIGGER_SETTING = 0x290A,
- DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_CONFIGURATION = 0x290B,
- DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_MEASUREMENT = 0x290C,
- DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_TRIGGER_SETTING = 0x290D,
- DESCRIPTOR_UUID_TIME_TRIGGER_SETTING = 0x290E,
-};
-
extern const mp_obj_type_t bleio_descriptor_type;
-extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid);
-extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self);
-extern mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
+extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length);
+extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
+extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self);
+extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self);
+extern void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c
index 570896d27..630e6ed36 100644
--- a/shared-bindings/bleio/Peripheral.c
+++ b/shared-bindings/bleio/Peripheral.c
@@ -44,8 +44,6 @@
#include "common-hal/bleio/Peripheral.h"
-static const char default_name[] = "CIRCUITPY";
-
#define ADV_INTERVAL_DEFAULT (1.0f)
#define ADV_INTERVAL_MIN (0.0020f)
#define ADV_INTERVAL_MIN_STRING "0.0020"
@@ -80,14 +78,14 @@ static const char default_name[] = "CIRCUITPY";
//| # Wait for connection.
//| pass
//|
-//| .. class:: Peripheral(services=(), \*, name='CIRCUITPY')
+//| .. class:: Peripheral(services=(), \*, name=None)
//|
//| Create a new Peripheral object.
//|
//| :param iterable services: the Service objects representing services available from this peripheral, if any.
//| A non-connectable peripheral will have no services.
-//| :param str name: The name used when advertising this peripheral. Use ``None`` when a name is not needed,
-//| such as when the peripheral is a beacon
+//| :param str name: The name used when advertising this peripheral. If name is None,
+//| bleio.adapter.default_name will be used.
//|
STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_services, ARG_name };
@@ -107,33 +105,30 @@ STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_ar
self->base.type = &bleio_peripheral_type;
// Copy the services list and validate its items.
- mp_obj_t service_list_obj = mp_obj_new_list(0, NULL);
- mp_obj_list_t *service_list = MP_OBJ_FROM_PTR(service_list_obj);
+ mp_obj_t services_list_obj = mp_obj_new_list(0, NULL);
+ mp_obj_list_t *services_list = MP_OBJ_FROM_PTR(services_list_obj);
mp_obj_t service;
while ((service = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (!MP_OBJ_IS_TYPE(service, &bleio_service_type)) {
mp_raise_ValueError(translate("non-Service found in services"));
}
- mp_obj_list_append(service_list, service);
+ mp_obj_list_append(services_list, service);
}
- const mp_obj_t name = args[ARG_name].u_obj;
- mp_obj_t name_str;
+ mp_obj_t name = args[ARG_name].u_obj;
if (name == MP_OBJ_NULL || name == mp_const_none) {
- name_str = mp_obj_new_str(default_name, strlen(default_name));
- } else if (MP_OBJ_IS_STR(name)) {
- name_str = name;
- } else {
+ name = common_hal_bleio_adapter_get_default_name();
+ } else if (!MP_OBJ_IS_STR(name)) {
mp_raise_ValueError(translate("name must be a string"));
}
- common_hal_bleio_peripheral_construct(self, service_list, name_str);
+ common_hal_bleio_peripheral_construct(self, services_list, name);
return MP_OBJ_FROM_PTR(self);
}
-//| .. attribute:: connected
+//| .. attribute:: connected (read-only)
//|
//| True if connected to a BLE Central device.
//|
@@ -158,8 +153,8 @@ const mp_obj_property_t bleio_peripheral_connected_obj = {
STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) {
bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *service_list = common_hal_bleio_peripheral_get_service_list(self);
- return mp_obj_new_tuple(service_list->len, service_list->items);
+ mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services(self);
+ return mp_obj_new_tuple(services_list->len, services_list->items);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services);
@@ -265,16 +260,75 @@ STATIC mp_obj_t bleio_peripheral_disconnect(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripheral_disconnect);
+//| .. method:: discover_remote_services(service_uuids_whitelist=None)
+//| Do BLE discovery for all services or for the given service UUIDS,
+//| to find their handles and characteristics, and return the discovered services.
+//| `Peripheral.connected` must be True.
+//|
+//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services
+//| provided by the peripheral that you want to use.
+//| The peripheral may provide more services, but services not listed are ignored
+//| and will not be returned.
+//|
+//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
+//|
+//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
+//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
+//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered
+//| for use. (This restriction may be lifted in the future.)
+//|
+//| Thought it is unusual for a peripheral to act as a BLE client, it can do so, and
+//| needs to be able to do discovery on its peer (a central).
+//| Examples include a peripheral accessing a central that provides Current Time Service,
+//| Apple Notification Center Service, or Battery Service.
+//|
+//| :return: A tuple of services provided by the remote central.
+//|
+STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_service_uuids_whitelist };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ if (!common_hal_bleio_peripheral_get_connected(self)) {
+ mp_raise_ValueError(translate("Not connected"));
+ }
+
+ return MP_OBJ_FROM_PTR(common_hal_bleio_peripheral_discover_remote_services(
+ MP_OBJ_FROM_PTR(self),
+ args[ARG_service_uuids_whitelist].u_obj));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services);
+
+//| .. method:: pair()
+//|
+//| Request pairing with connected central.
+STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) {
+ bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_peripheral_pair(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair);
+
STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = {
// Methods
- { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) },
- { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pair) , MP_ROM_PTR(&bleio_peripheral_pair_obj) },
// Properties
- { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) },
- { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table);
diff --git a/shared-bindings/bleio/Peripheral.h b/shared-bindings/bleio/Peripheral.h
index 846250a5f..597b65ce2 100644
--- a/shared-bindings/bleio/Peripheral.h
+++ b/shared-bindings/bleio/Peripheral.h
@@ -28,16 +28,19 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
+#include "py/objtuple.h"
#include "common-hal/bleio/Peripheral.h"
extern const mp_obj_type_t bleio_peripheral_type;
extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name);
-extern mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self);
+extern mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self);
extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self);
extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self);
extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device);
extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device);
+extern mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist);
+extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c
index db0606991..6961b0b52 100644
--- a/shared-bindings/bleio/Service.c
+++ b/shared-bindings/bleio/Service.c
@@ -43,12 +43,16 @@
//| .. class:: Service(uuid, characteristics, *, secondary=False)
//|
//| Create a new Service object identified by the specified UUID.
+//|
//| To mark the service as secondary, pass `True` as :py:data:`secondary`.
//|
//| :param bleio.UUID uuid: The uuid of the service
//| :param iterable characteristics: the Characteristic objects for this service
//| :param bool secondary: If the service is a secondary one
//|
+//| A Service may be remote (:py:data:`remote` is ``True``), but a remote Service
+//| cannot be constructed directly. It is created by `Central.discover_remote_services()`
+//| or `Peripheral.discover_remote_services()`.
STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_uuid, ARG_characteristics, ARG_secondary };
@@ -92,6 +96,9 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args,
// The descriptor base UUID doesn't match the characteristic base UUID.
mp_raise_ValueError(translate("Characteristic UUID doesn't match Service UUID"));
}
+ if (common_hal_bleio_characteristic_get_service(characteristic) != MP_OBJ_NULL) {
+ mp_raise_ValueError(translate("Characteristic is already attached to a Service"));
+ }
mp_obj_list_append(char_list_obj, characteristic_obj);
}
@@ -119,6 +126,24 @@ const mp_obj_property_t bleio_service_characteristics_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: remote
+//|
+//| True if this is a service provided by a remote device. (read-only)
+//|
+STATIC mp_obj_t bleio_service_get_remote(mp_obj_t self_in) {
+ bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(common_hal_bleio_service_get_is_remote(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_remote_obj, bleio_service_get_remote);
+
+const mp_obj_property_t bleio_service_remote_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_service_get_remote_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
//| .. attribute:: secondary
//|
//| True if this is a secondary service. (read-only)
diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/bleio/Service.h
index f646c81a9..716c2e8a9 100644
--- a/shared-bindings/bleio/Service.h
+++ b/shared-bindings/bleio/Service.h
@@ -35,6 +35,7 @@ const mp_obj_type_t bleio_service_type;
extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, mp_obj_list_t *characteristic_list, bool is_secondary);
extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self);
extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(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_all_characteristics(bleio_service_obj_t *self);
diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c
index ba3bae6c7..739f461a5 100644
--- a/shared-bindings/bleio/__init__.c
+++ b/shared-bindings/bleio/__init__.c
@@ -28,24 +28,30 @@
#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Address.h"
+#include "shared-bindings/bleio/Attribute.h"
#include "shared-bindings/bleio/Central.h"
#include "shared-bindings/bleio/Characteristic.h"
#include "shared-bindings/bleio/CharacteristicBuffer.h"
-// #include "shared-bindings/bleio/Descriptor.h"
+#include "shared-bindings/bleio/Descriptor.h"
#include "shared-bindings/bleio/Peripheral.h"
#include "shared-bindings/bleio/ScanEntry.h"
#include "shared-bindings/bleio/Scanner.h"
#include "shared-bindings/bleio/Service.h"
#include "shared-bindings/bleio/UUID.h"
-//| :mod:`bleio` --- Bluetooth Low Energy functionality
+//| :mod:`bleio` --- Bluetooth Low Energy (BLE) communication
//| ================================================================
//|
//| .. module:: bleio
//| :synopsis: Bluetooth Low Energy functionality
//| :platform: nRF
//|
-//| The `bleio` module contains methods for managing the BLE adapter.
+//| The `bleio` module provides necessary low-level functionality for communicating
+//| using Bluetooth Low Energy (BLE). We recommend you use `bleio` in conjunction
+//| with the `adafruit_ble <https://circuitpython.readthedocs.io/projects/ble/en/latest/>`_
+//| CircuitPython library, which builds on `bleio`, and
+//| provides higher-level convenience functionality, including predefined beacons, clients,
+//| servers.
//|
//| Libraries
//|
@@ -54,6 +60,7 @@
//|
//| Address
//| Adapter
+//| Attribute
//| Central
//| Characteristic
//| CharacteristicBuffer
@@ -72,20 +79,21 @@
//|
STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) },
- { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
- { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) },
- { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
- { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) },
-// { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
- { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) },
- { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
- { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
- { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
- { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) },
+ { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
+ { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) },
+ { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) },
+ { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
+ { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) },
+ { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
+ { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) },
+ { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
+ { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
+ { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
+ { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
// Properties
- { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
+ { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table);
diff --git a/shared-bindings/bleio/__init__.h b/shared-bindings/bleio/__init__.h
index 4aa6dd45b..6a4c804f5 100644
--- a/shared-bindings/bleio/__init__.h
+++ b/shared-bindings/bleio/__init__.h
@@ -29,8 +29,24 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
+#include "py/objlist.h"
+
+#include "shared-bindings/bleio/__init__.h"
+#include "shared-bindings/bleio/Adapter.h"
+
#include "common-hal/bleio/Adapter.h"
extern const super_adapter_obj_t common_hal_bleio_adapter_obj;
+extern void common_hal_bleio_check_connected(uint16_t conn_handle);
+
+extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
+extern mp_obj_list_t *common_hal_bleio_device_get_remote_services_list(mp_obj_t device);
+extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist);
+
+extern mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle);
+extern void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo);
+extern void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response);
+
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
diff --git a/shared-bindings/displayio/FourWire.c b/shared-bindings/displayio/FourWire.c
index af64a2028..0d41359ee 100644
--- a/shared-bindings/displayio/FourWire.c
+++ b/shared-bindings/displayio/FourWire.c
@@ -119,9 +119,7 @@ STATIC mp_obj_t displayio_fourwire_obj_send(mp_obj_t self, mp_obj_t command_obj,
// Wait for display bus to be available.
while (!common_hal_displayio_fourwire_begin_transaction(self)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
}
common_hal_displayio_fourwire_send(self, true, &command, 1);
common_hal_displayio_fourwire_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
diff --git a/shared-bindings/displayio/I2CDisplay.c b/shared-bindings/displayio/I2CDisplay.c
index 1f74e8c9e..9ef989d71 100644
--- a/shared-bindings/displayio/I2CDisplay.c
+++ b/shared-bindings/displayio/I2CDisplay.c
@@ -111,9 +111,7 @@ STATIC mp_obj_t displayio_i2cdisplay_obj_send(mp_obj_t self, mp_obj_t command_ob
// Wait for display bus to be available.
while (!common_hal_displayio_i2cdisplay_begin_transaction(self)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
}
uint8_t full_command[bufinfo.len + 1];
full_command[0] = command;
diff --git a/shared-bindings/displayio/ParallelBus.c b/shared-bindings/displayio/ParallelBus.c
index 00a96d230..c29c79fff 100644
--- a/shared-bindings/displayio/ParallelBus.c
+++ b/shared-bindings/displayio/ParallelBus.c
@@ -122,9 +122,7 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o
// Wait for display bus to be available.
while (!common_hal_displayio_parallelbus_begin_transaction(self)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
}
common_hal_displayio_parallelbus_send(self, true, &command, 1);
common_hal_displayio_parallelbus_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c
index 6ba4914a0..53fbb51c8 100644
--- a/shared-bindings/displayio/TileGrid.c
+++ b/shared-bindings/displayio/TileGrid.c
@@ -131,7 +131,8 @@ STATIC mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_
displayio_tilegrid_t *self = m_new_obj(displayio_tilegrid_t);
self->base.type = &displayio_tilegrid_type;
- common_hal_displayio_tilegrid_construct(self, native, bitmap_width / tile_width,
+ common_hal_displayio_tilegrid_construct(self, native,
+ bitmap_width / tile_width, bitmap_height / tile_height,
pixel_shader, args[ARG_width].u_int, args[ARG_height].u_int,
tile_width, tile_height, x, y, args[ARG_default_tile].u_int);
return MP_OBJ_FROM_PTR(self);
@@ -346,7 +347,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v
}
if (x >= common_hal_displayio_tilegrid_get_width(self) ||
y >= common_hal_displayio_tilegrid_get_height(self)) {
- mp_raise_IndexError(translate("tile index out of bounds"));
+ mp_raise_IndexError(translate("Tile index out of bounds"));
}
if (value_obj == MP_OBJ_SENTINEL) {
@@ -357,7 +358,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v
} else {
mp_int_t value = mp_obj_get_int(value_obj);
if (value < 0 || value > 255) {
- mp_raise_ValueError(translate("Tile indices must be 0 - 255"));
+ mp_raise_ValueError(translate("Tile value out of bounds"));
}
common_hal_displayio_tilegrid_set_tile(self, x, y, value);
}
diff --git a/shared-bindings/displayio/TileGrid.h b/shared-bindings/displayio/TileGrid.h
index 1f9995a94..8227abfd3 100644
--- a/shared-bindings/displayio/TileGrid.h
+++ b/shared-bindings/displayio/TileGrid.h
@@ -32,7 +32,8 @@
extern const mp_obj_type_t displayio_tilegrid_type;
void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap,
- uint16_t bitmap_width_in_tiles, mp_obj_t pixel_shader, uint16_t width, uint16_t height,
+ uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles,
+ mp_obj_t pixel_shader, uint16_t width, uint16_t height,
uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile);
mp_int_t common_hal_displayio_tilegrid_get_x(displayio_tilegrid_t *self);
diff --git a/shared-bindings/i2cslave/I2CSlave.c b/shared-bindings/i2cslave/I2CSlave.c
index 2598accbb..c98ea52e0 100644
--- a/shared-bindings/i2cslave/I2CSlave.c
+++ b/shared-bindings/i2cslave/I2CSlave.c
@@ -182,7 +182,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request(size_t n_args, const mp_obj_t *pos_ar
bool is_read;
bool is_restart;
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
return mp_const_none;
}
@@ -337,7 +337,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request_read(size_t n_args, const mp_obj_t *p
uint8_t *buffer = NULL;
uint64_t timeout_end = common_hal_time_monotonic() + 10 * 1000;
while (common_hal_time_monotonic() < timeout_end) {
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
@@ -382,7 +382,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request_write(mp_obj_t self_in, mp_obj_t buf_
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
for (size_t i = 0; i < bufinfo.len; i++) {
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index 70c01c2d8..2654de09a 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -99,16 +99,17 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp
//|
//| Structure used to capture a date and time. Note that it takes a tuple!
//|
-//| :param Tuple[tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst] time_tuple: Tuple of time info.
-//| * the year, 2017 for example
-//| * the month, range [1, 12]
-//| * the day of the month, range [1, 31]
-//| * the hour, range [0, 23]
-//| * the minute, range [0, 59]
-//| * the second, range [0, 61]
-//| * the day of the week, range [0, 6], Monday is 0
-//| * the day of the year, range [1, 366], -1 indicates not known
-//| * 1 when in daylight savings, 0 when not, -1 if unknown.
+//| :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)``
+//|
+//| * ``tm_year``: the year, 2017 for example
+//| * ``tm_month``: the month, range [1, 12]
+//| * ``tm_mday``: the day of the month, range [1, 31]
+//| * ``tm_hour``: the hour, range [0, 23]
+//| * ``tm_minute``: the minute, range [0, 59]
+//| * ``tm_sec``: the second, range [0, 61]
+//| * ``tm_wday``: the day of the week, range [0, 6], Monday is 0
+//| * ``tm_yday``: the day of the year, range [1, 366], -1 indicates not known
+//| * ``tm_isdst``: 1 when in daylight savings, 0 when not, -1 if unknown.
//|
const mp_obj_namedtuple_type_t struct_time_type_obj = {
.base = {
@@ -235,9 +236,16 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
return rtc_get_time_source_time();
}
- mp_int_t secs = mp_obj_int_get_checked(args[0]);
- if (secs < EPOCH1970_EPOCH2000_DIFF_SECS)
+ mp_obj_t arg = args[0];
+ if (mp_obj_is_float(arg)) {
+ arg = mp_obj_new_int_from_float(mp_obj_get_float(arg));
+ }
+
+ mp_int_t secs = mp_obj_get_int(arg);
+
+ if (secs < EPOCH1970_EPOCH2000_DIFF_SECS) {
mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t"));
+ }
timeutils_struct_time_t tm;
timeutils_seconds_since_epoch_to_struct_time(secs, &tm);
@@ -269,8 +277,9 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_raise_TypeError(translate("function takes exactly 9 arguments"));
}
- if (mp_obj_get_int(elem[0]) < 2000)
+ if (mp_obj_get_int(elem[0]) < 2000) {
mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t"));
+ }
mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]));
diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c
index 1af279e92..ca71b758e 100644
--- a/shared-module/_stage/__init__.c
+++ b/shared-module/_stage/__init__.c
@@ -34,30 +34,35 @@
void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
mp_obj_t *layers, size_t layers_size,
uint16_t *buffer, size_t buffer_size,
- displayio_display_obj_t *display) {
+ displayio_display_obj_t *display, uint8_t scale) {
size_t index = 0;
for (uint16_t y = y0; y < y1; ++y) {
- for (uint16_t x = x0; x < x1; ++x) {
- for (size_t layer = 0; layer < layers_size; ++layer) {
+ for (uint8_t yscale = 0; yscale < scale; ++yscale) {
+ for (uint16_t x = x0; x < x1; ++x) {
uint16_t c = TRANSPARENT;
- layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]);
- if (obj->base.type == &mp_type_layer) {
- c = get_layer_pixel(obj, x, y);
- } else if (obj->base.type == &mp_type_text) {
- c = get_text_pixel((text_obj_t *)obj, x, y);
+ for (size_t layer = 0; layer < layers_size; ++layer) {
+ layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]);
+ if (obj->base.type == &mp_type_layer) {
+ c = get_layer_pixel(obj, x, y);
+ } else if (obj->base.type == &mp_type_text) {
+ c = get_text_pixel((text_obj_t *)obj, x, y);
+ }
+ if (c != TRANSPARENT) {
+ break;
+ }
}
- if (c != TRANSPARENT) {
+ for (uint8_t xscale = 0; xscale < scale; ++xscale) {
buffer[index] = c;
- break;
+ index += 1;
+ // The buffer is full, send it.
+ if (index >= buffer_size) {
+ display->send(display->bus, false, ((uint8_t*)buffer),
+ buffer_size * 2);
+ index = 0;
+ }
}
}
- index += 1;
- // The buffer is full, send it.
- if (index >= buffer_size) {
- display->send(display->bus, false, ((uint8_t*)buffer), buffer_size * 2);
- index = 0;
- }
}
}
// Send the remaining data.
diff --git a/shared-module/_stage/__init__.h b/shared-module/_stage/__init__.h
index d263302b4..5af2124ae 100644
--- a/shared-module/_stage/__init__.h
+++ b/shared-module/_stage/__init__.h
@@ -37,6 +37,6 @@
void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
mp_obj_t *layers, size_t layers_size,
uint16_t *buffer, size_t buffer_size,
- displayio_display_obj_t *display);
+ displayio_display_obj_t *display, uint8_t scale);
#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE
diff --git a/shared-module/audiocore/WaveFile.c b/shared-module/audiocore/WaveFile.c
index 810d9c33b..df5d4b61d 100644
--- a/shared-module/audiocore/WaveFile.c
+++ b/shared-module/audiocore/WaveFile.c
@@ -46,7 +46,9 @@ struct wave_format_chunk {
};
void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
- pyb_file_obj_t* file) {
+ pyb_file_obj_t* file,
+ uint8_t *buffer,
+ size_t buffer_size) {
// Load the wave
self->file = file;
uint8_t chunk_header[16];
@@ -84,7 +86,6 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
}
// Get the sample_rate
self->sample_rate = format.sample_rate;
- self->len = 256;
self->channel_count = format.num_channels;
self->bits_per_sample = format.bits_per_sample;
@@ -111,21 +112,31 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
// Try to allocate two buffers, one will be loaded from file and the other
// DMAed to DAC.
- self->buffer = m_malloc(self->len, false);
- if (self->buffer == NULL) {
- common_hal_audioio_wavefile_deinit(self);
- mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer"));
- }
+ if (buffer_size) {
+ self->len = buffer_size / 2;
+ self->buffer = buffer;
+ self->second_buffer = buffer + self->len;
+ } else {
+ self->len = 256;
+ self->buffer = m_malloc(self->len, false);
+ if (self->buffer == NULL) {
+ common_hal_audioio_wavefile_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate first buffer"));
+ }
- self->second_buffer = m_malloc(self->len, false);
- if (self->second_buffer == NULL) {
- common_hal_audioio_wavefile_deinit(self);
- mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer"));
+ self->second_buffer = m_malloc(self->len, false);
+ if (self->second_buffer == NULL) {
+ common_hal_audioio_wavefile_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate second buffer"));
+ }
}
}
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self) {
self->buffer = NULL;
+ self->second_buffer = NULL;
}
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self) {
diff --git a/shared-module/audiocore/WaveFile.h b/shared-module/audiocore/WaveFile.h
index 97dd6a46f..3eecbf15c 100644
--- a/shared-module/audiocore/WaveFile.h
+++ b/shared-module/audiocore/WaveFile.h
@@ -27,6 +27,7 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_WAVEFILE_H
#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_WAVEFILE_H
+#include "extmod/vfs_fat.h"
#include "py/obj.h"
#include "shared-module/audiocore/__init__.h"
diff --git a/shared-module/audiopwmio/__init__.c b/shared-module/audiopwmio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/audiopwmio/__init__.c
diff --git a/shared-module/bleio/__init__.h b/shared-module/audiopwmio/__init__.h
index 07d148594..964e4aafe 100644
--- a/shared-module/bleio/__init__.h
+++ b/shared-module/audiopwmio/__init__.h
@@ -24,15 +24,9 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
-#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H
-typedef enum {
- GATT_ROLE_NONE,
- GATT_ROLE_SERVER,
- GATT_ROLE_CLIENT,
-} gatt_role_t;
+#include "shared-module/audiocore/__init__.h"
-extern void bleio_reset(void);
-
-#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H
diff --git a/shared-module/bleio/Attribute.c b/shared-module/bleio/Attribute.c
new file mode 100644
index 000000000..2275003c9
--- /dev/null
+++ b/shared-module/bleio/Attribute.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Attribute.h"
+
+void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode) {
+ switch (security_mode) {
+ case SECURITY_MODE_NO_ACCESS:
+ case SECURITY_MODE_OPEN:
+ case SECURITY_MODE_ENC_NO_MITM:
+ case SECURITY_MODE_ENC_WITH_MITM:
+ case SECURITY_MODE_LESC_ENC_WITH_MITM:
+ case SECURITY_MODE_SIGNED_NO_MITM:
+ case SECURITY_MODE_SIGNED_WITH_MITM:
+ break;
+ default:
+ mp_raise_ValueError(translate("Invalid security_mode"));
+ break;
+ }
+}
diff --git a/shared-module/bleio/Attribute.h b/shared-module/bleio/Attribute.h
new file mode 100644
index 000000000..a498a14a5
--- /dev/null
+++ b/shared-module/bleio/Attribute.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H
+
+// BLE security modes: 0x<level><mode>
+typedef enum {
+ SECURITY_MODE_NO_ACCESS = 0x00,
+ SECURITY_MODE_OPEN = 0x11,
+ SECURITY_MODE_ENC_NO_MITM = 0x21,
+ SECURITY_MODE_ENC_WITH_MITM = 0x31,
+ SECURITY_MODE_LESC_ENC_WITH_MITM = 0x41,
+ SECURITY_MODE_SIGNED_NO_MITM = 0x12,
+ SECURITY_MODE_SIGNED_WITH_MITM = 0x22,
+} bleio_attribute_security_mode_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H
diff --git a/shared-module/bleio/Characteristic.h b/shared-module/bleio/Characteristic.h
index 27b43588f..409a57c76 100644
--- a/shared-module/bleio/Characteristic.h
+++ b/shared-module/bleio/Characteristic.h
@@ -27,14 +27,17 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
-// Flags for each characteristic property. Common across ports.
-typedef struct {
- bool broadcast : 1;
- bool read : 1;
- bool write_no_response : 1;
- bool write : 1;
- bool notify : 1;
- bool indicate : 1;
-} bleio_characteristic_properties_t;
+typedef enum {
+ CHAR_PROP_NONE = 0,
+ CHAR_PROP_BROADCAST = 1u << 0,
+ CHAR_PROP_INDICATE = 1u << 1,
+ CHAR_PROP_NOTIFY = 1u << 2,
+ CHAR_PROP_READ = 1u << 3,
+ CHAR_PROP_WRITE = 1u << 4,
+ CHAR_PROP_WRITE_NO_RESPONSE = 1u << 5,
+ CHAR_PROP_ALL = (CHAR_PROP_BROADCAST | CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY |
+ CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE)
+} bleio_characteristic_properties_enum_t;
+typedef uint8_t bleio_characteristic_properties_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c
index 5a1dead78..dd07d7190 100644
--- a/shared-module/board/__init__.c
+++ b/shared-module/board/__init__.c
@@ -40,17 +40,25 @@
#endif
#if BOARD_I2C
+// Statically allocate the I2C object so it can live past the end of the heap and into the next VM.
+// That way it can be used by built-in I2CDisplay displays and be accessible through board.I2C().
+STATIC busio_i2c_obj_t i2c_obj;
+STATIC mp_obj_t i2c_singleton = NULL;
+
mp_obj_t common_hal_board_get_i2c(void) {
- return MP_STATE_VM(shared_i2c_bus);
+ return i2c_singleton;
}
mp_obj_t common_hal_board_create_i2c(void) {
- busio_i2c_obj_t *self = m_new_ll_obj(busio_i2c_obj_t);
+ if (i2c_singleton != NULL) {
+ return i2c_singleton;
+ }
+ busio_i2c_obj_t *self = &i2c_obj;
self->base.type = &busio_i2c_type;
common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 0);
- MP_STATE_VM(shared_i2c_bus) = MP_OBJ_FROM_PTR(self);
- return MP_STATE_VM(shared_i2c_bus);
+ i2c_singleton = (mp_obj_t)self;
+ return i2c_singleton;
}
#endif
@@ -101,7 +109,18 @@ mp_obj_t common_hal_board_create_uart(void) {
void reset_board_busses(void) {
#if BOARD_I2C
- MP_STATE_VM(shared_i2c_bus) = NULL;
+ bool display_using_i2c = false;
+ #if CIRCUITPY_DISPLAYIO
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].i2cdisplay_bus.bus == i2c_singleton) {
+ display_using_i2c = true;
+ break;
+ }
+ }
+ #endif
+ if (!display_using_i2c) {
+ i2c_singleton = NULL;
+ }
#endif
#if BOARD_SPI
bool display_using_spi = false;
diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c
index f8dc24c15..59971d25c 100644
--- a/shared-module/displayio/Bitmap.c
+++ b/shared-module/displayio/Bitmap.c
@@ -63,6 +63,11 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi
}
self->x_mask = (1 << self->x_shift) - 1; // Used as a modulus on the x value
self->bitmask = (1 << bits_per_value) - 1;
+
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = width;
+ self->dirty_area.y1 = 0;
+ self->dirty_area.y2 = height;
}
uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self) {
@@ -104,6 +109,26 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x,
if (self->read_only) {
mp_raise_RuntimeError(translate("Read-only object"));
}
+ // Update the dirty area.
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ self->dirty_area.x1 = x;
+ self->dirty_area.x2 = x + 1;
+ self->dirty_area.y1 = y;
+ self->dirty_area.y2 = y + 1;
+ } else {
+ if (x < self->dirty_area.x1) {
+ self->dirty_area.x1 = x;
+ } else if (x >= self->dirty_area.x2) {
+ self->dirty_area.x2 = x + 1;
+ }
+ if (y < self->dirty_area.y1) {
+ self->dirty_area.y1 = y;
+ } else if (y >= self->dirty_area.y2) {
+ self->dirty_area.y2 = y + 1;
+ }
+ }
+
+ // Update our data
int32_t row_start = y * self->stride;
uint32_t bytes_per_value = self->bits_per_value / 8;
if (bytes_per_value < 1) {
@@ -124,3 +149,16 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x,
}
}
}
+
+displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail) {
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ return tail;
+ }
+ self->dirty_area.next = tail;
+ return &self->dirty_area;
+}
+
+void displayio_bitmap_finish_refresh(displayio_bitmap_t *self) {
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = 0;
+}
diff --git a/shared-module/displayio/Bitmap.h b/shared-module/displayio/Bitmap.h
index 48ca9e2cf..f4bd7ce4d 100644
--- a/shared-module/displayio/Bitmap.h
+++ b/shared-module/displayio/Bitmap.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include "py/obj.h"
+#include "shared-module/displayio/area.h"
typedef struct {
mp_obj_base_t base;
@@ -41,8 +42,12 @@ typedef struct {
uint8_t bits_per_value;
uint8_t x_shift;
size_t x_mask;
+ displayio_area_t dirty_area;
uint16_t bitmask;
bool read_only;
} displayio_bitmap_t;
+void displayio_bitmap_finish_refresh(displayio_bitmap_t *self);
+displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index 51c6f292a..c23c66b8b 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -85,9 +85,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
uint32_t i = 0;
while (!self->begin_transaction(self->bus)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
}
while (i < init_sequence_len) {
uint8_t *cmd = init_sequence + i;
@@ -199,19 +197,26 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
bool common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
if (root_group == NULL) {
- root_group = &circuitpython_splash;
+ if (!circuitpython_splash.in_group) {
+ root_group = &circuitpython_splash;
+ } else if (self->current_group == &circuitpython_splash) {
+ return false;
+ }
}
if (root_group == self->current_group) {
return true;
}
- if (root_group->in_group) {
+ if (root_group != NULL && root_group->in_group) {
return false;
}
if (self->current_group != NULL) {
self->current_group->in_group = false;
}
- displayio_group_update_transform(root_group, &self->transform);
- root_group->in_group = true;
+
+ if (root_group != NULL) {
+ displayio_group_update_transform(root_group, &self->transform);
+ root_group->in_group = true;
+ }
self->current_group = root_group;
self->full_refresh = true;
common_hal_displayio_display_refresh_soon(self);
@@ -235,7 +240,7 @@ int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* sel
uint64_t last_refresh = self->last_refresh;
// Don't try to refresh if we got an exception.
while (last_refresh == self->last_refresh && MP_STATE_VM(mp_pending_exception) == NULL) {
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
}
return 0;
}
@@ -402,6 +407,10 @@ void displayio_display_update_backlight(displayio_display_obj_t* self) {
}
void release_display(displayio_display_obj_t* self) {
+ if (self->current_group != NULL) {
+ self->current_group->in_group = false;
+ }
+
if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
common_hal_pulseio_pwmout_reset_ok(&self->backlight_pwm);
common_hal_pulseio_pwmout_deinit(&self->backlight_pwm);
diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c
index fee2ae978..6144f8f99 100644
--- a/shared-module/displayio/TileGrid.c
+++ b/shared-module/displayio/TileGrid.c
@@ -26,6 +26,7 @@
#include "shared-bindings/displayio/TileGrid.h"
+#include "py/runtime.h"
#include "shared-bindings/displayio/Bitmap.h"
#include "shared-bindings/displayio/ColorConverter.h"
#include "shared-bindings/displayio/OnDiskBitmap.h"
@@ -33,7 +34,7 @@
#include "shared-bindings/displayio/Shape.h"
void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap,
- uint16_t bitmap_width_in_tiles,
+ uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles,
mp_obj_t pixel_shader, uint16_t width, uint16_t height,
uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) {
uint32_t total_tiles = width * height;
@@ -54,6 +55,7 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_
self->inline_tiles = false;
}
self->bitmap_width_in_tiles = bitmap_width_in_tiles;
+ self->tiles_in_bitmap = bitmap_width_in_tiles * bitmap_height_in_tiles;
self->width_in_tiles = width;
self->height_in_tiles = height;
self->x = x;
@@ -204,6 +206,9 @@ uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint1
}
void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index) {
+ if (tile_index >= self->tiles_in_bitmap) {
+ mp_raise_ValueError(translate("Tile value out of bounds"));
+ }
uint8_t* tiles = self->tiles;
if (self->inline_tiles) {
tiles = (uint8_t*) &self->tiles;
@@ -462,6 +467,14 @@ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
displayio_colorconverter_finish_refresh(self->pixel_shader);
}
+ if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
+ displayio_bitmap_finish_refresh(self->bitmap);
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
+ // TODO: Support shape changes.
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
+ // OnDiskBitmap changes will trigger a complete reload so no need to
+ // track changes.
+ }
// TODO(tannewt): We could double buffer changes to position and move them over here.
// That way they won't change during a refresh and tear.
}
@@ -478,8 +491,21 @@ displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *sel
return &self->current_area;
}
- // We must recheck if our sources require a refresh because needs_refresh may or may not have
- // been called.
+ // If we have an in-memory bitmap, then check it for modifications.
+ if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
+ displayio_area_t* refresh_area = displayio_bitmap_get_refresh_areas(self->bitmap, tail);
+ if (refresh_area != tail) {
+ // Special case a TileGrid that shows a full bitmap and use its
+ // dirty area. Copy it to ours so we can transform it.
+ if (self->tiles_in_bitmap == 1) {
+ displayio_area_copy(refresh_area, &self->dirty_area);
+ self->partial_change = true;
+ } else {
+ self->full_change = true;
+ }
+ }
+ }
+
self->full_change = self->full_change ||
(MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) &&
displayio_palette_needs_refresh(self->pixel_shader)) ||
diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h
index fb6033e9c..222aaed19 100644
--- a/shared-module/displayio/TileGrid.h
+++ b/shared-module/displayio/TileGrid.h
@@ -42,7 +42,8 @@ typedef struct {
int16_t y;
uint16_t pixel_width;
uint16_t pixel_height;
- uint16_t bitmap_width_in_tiles;
+ uint16_t bitmap_width_in_tiles;;
+ uint8_t tiles_in_bitmap;
uint16_t width_in_tiles;
uint16_t height_in_tiles;
uint16_t tile_width;
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index 8f6e650a1..3e9c4aa2a 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -163,7 +163,7 @@ void displayio_refresh_displays(void) {
void common_hal_displayio_release_displays(void) {
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
mp_const_obj_t bus_type = displays[i].fourwire_bus.base.type;
- if (bus_type == NULL) {
+ if (bus_type == NULL || bus_type == &mp_type_NoneType) {
continue;
} else if (bus_type == &displayio_fourwire_type) {
common_hal_displayio_fourwire_deinit(&displays[i].fourwire_bus);
@@ -235,12 +235,14 @@ void reset_displays(void) {
// Not an active display.
continue;
}
+ }
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
// Reset the displayed group. Only the first will get the terminal but
// that's ok.
displayio_display_obj_t* display = &displays[i].display;
display->auto_brightness = true;
- common_hal_displayio_display_show(display, &circuitpython_splash);
+ common_hal_displayio_display_show(display, NULL);
}
}
diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c
index 86c3e903e..df92a5dc4 100644
--- a/shared-module/terminalio/Terminal.c
+++ b/shared-module/terminalio/Terminal.c
@@ -36,6 +36,12 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, d
self->tilegrid = tilegrid;
self->first_row = 0;
+ for (uint16_t x = 0; x < self->tilegrid->width_in_tiles; x++) {
+ for (uint16_t y = 0; y < self->tilegrid->height_in_tiles; y++) {
+ common_hal_displayio_tilegrid_set_tile(self->tilegrid, x, y, 0);
+ }
+ }
+
common_hal_displayio_tilegrid_set_top_left(self->tilegrid, 0, 1);
}
diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c
index a5a57419c..26d70cb82 100644
--- a/shared-module/usb_hid/Device.c
+++ b/shared-module/usb_hid/Device.c
@@ -47,7 +47,11 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t*
// Wait until interface is ready, timeout = 2 seconds
uint64_t end_ticks = ticks_ms + 2000;
- while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) { }
+ while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) {
+#ifdef MICROPY_VM_HOOK_LOOP
+ MICROPY_VM_HOOK_LOOP;
+#endif
+ }
if ( !tud_hid_ready() ) {
mp_raise_msg(&mp_type_OSError, translate("USB Busy"));
diff --git a/supervisor/shared/display.h b/supervisor/shared/display.h
index d5faa7777..2a2ccf46d 100644
--- a/supervisor/shared/display.h
+++ b/supervisor/shared/display.h
@@ -35,11 +35,10 @@
// These are autogenerated resources.
// This is fixed so it doesn't need to be in RAM.
-extern const displayio_bitmap_t supervisor_terminal_font_bitmap;
-
extern const fontio_builtinfont_t supervisor_terminal_font;
// These will change so they must live in RAM.
+extern displayio_bitmap_t supervisor_terminal_font_bitmap;
extern displayio_tilegrid_t supervisor_terminal_text_grid;
extern terminalio_terminal_obj_t supervisor_terminal;
diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c
index 0678a3a3f..c1d70c5b0 100644
--- a/supervisor/shared/usb/usb.c
+++ b/supervisor/shared/usb/usb.c
@@ -25,6 +25,7 @@
*/
#include "tick.h"
+#include "py/objstr.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "shared-module/usb_midi/__init__.h"
#include "supervisor/port.h"
@@ -43,13 +44,11 @@ void load_serial_number(void) {
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
common_hal_mcu_processor_get_uid(raw_id);
- static const char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F'};
for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) {
for (int j = 0; j < 2; j++) {
uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf;
// Strings are UTF-16-LE encoded.
- usb_serial_number[1 + i * 2 + j] = nibble_to_hex[nibble];
+ usb_serial_number[1 + i * 2 + j] = nibble_to_hex_upper[nibble];
}
}
}
diff --git a/tools/check_translations.py b/tools/check_translations.py
index 4bea040bf..7c008d3da 100644
--- a/tools/check_translations.py
+++ b/tools/check_translations.py
@@ -16,8 +16,10 @@ for po_filename in po_filenames:
po_file = polib.pofile(po_filename)
po_ids = set([x.msgid for x in po_file])
- if all_ids - po_ids:
+ missing = all_ids - po_ids
+ if missing:
print("Missing message id. Please run `make translate`")
+ print(missing)
sys.exit(-1)
else:
print("ok")
diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py
index a731cbd9c..0f6b9014b 100644
--- a/tools/gen_display_resources.py
+++ b/tools/gen_display_resources.py
@@ -129,6 +129,7 @@ displayio_tilegrid_t supervisor_terminal_text_grid = {{
.pixel_width = {1},
.pixel_height = {2},
.bitmap_width_in_tiles = {0},
+ .tiles_in_bitmap = {0},
.width_in_tiles = 1,
.height_in_tiles = 1,
.tile_width = {1},
@@ -157,7 +158,7 @@ c_file.write("""\
""")
c_file.write("""\
-const displayio_bitmap_t supervisor_terminal_font_bitmap = {{
+displayio_bitmap_t supervisor_terminal_font_bitmap = {{
.base = {{.type = &displayio_bitmap_type }},
.width = {},
.height = {},