summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.travis.yml2
m---------lib/tinyusb0
-rw-r--r--locale/ID.po2587
-rw-r--r--locale/de_DE.po35
-rw-r--r--locale/es.po35
-rw-r--r--locale/fil.po35
-rw-r--r--locale/fr.po41
-rw-r--r--locale/it_IT.po43
-rw-r--r--locale/pt_BR.po25
-rw-r--r--ports/atmel-samd/Makefile9
-rw-r--r--ports/atmel-samd/README.rst58
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/board.c39
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.h24
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk11
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/pins.c53
-rw-r--r--ports/atmel-samd/mpconfigport.h3
-rwxr-xr-xports/nrf/Makefile3
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.c4
-rw-r--r--ports/nrf/common-hal/neopixel_write/__init__.c2
-rw-r--r--ports/nrf/common-hal/pulseio/PulseIn.c220
-rw-r--r--ports/nrf/common-hal/pulseio/PulseIn.h12
-rw-r--r--ports/nrf/mpconfigport.h2
-rw-r--r--ports/nrf/nrfx_config.h5
-rw-r--r--ports/nrf/supervisor/port.c2
-rw-r--r--shared-bindings/bleio/Peripheral.c3
-rw-r--r--shared-bindings/usb_midi/PortIn.c128
-rw-r--r--shared-bindings/usb_midi/PortIn.h44
-rw-r--r--shared-bindings/usb_midi/PortOut.c110
-rw-r--r--shared-bindings/usb_midi/PortOut.h44
-rw-r--r--shared-bindings/usb_midi/__init__.c78
-rw-r--r--shared-bindings/usb_midi/__init__.h34
-rw-r--r--shared-module/usb_midi/PortIn.c40
-rw-r--r--shared-module/usb_midi/PortIn.h39
-rw-r--r--shared-module/usb_midi/PortOut.c40
-rw-r--r--shared-module/usb_midi/PortOut.h39
-rw-r--r--shared-module/usb_midi/__init__.c63
-rw-r--r--shared-module/usb_midi/__init__.h32
-rwxr-xr-xsupervisor/memory.h9
-rw-r--r--supervisor/shared/usb/tusb_config.h1
-rw-r--r--supervisor/shared/usb/usb.c5
-rw-r--r--supervisor/supervisor.mk7
-rw-r--r--tools/gen_usb_descriptor.py74
m---------tools/usb_descriptor0
43 files changed, 3852 insertions, 188 deletions
diff --git a/.travis.yml b/.travis.yml
index 6c141385b..06231a594 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,7 @@ env:
- TRAVIS_BOARDS="metro_m0_express metro_m4_express pirkey_m0 trellis_m4_express trinket_m0" TRAVIS_SDK=arm
- TRAVIS_BOARDS="feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow" TRAVIS_SDK=arm
- TRAVIS_BOARDS="feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300 arduino_mkrzero" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="circuitplayground_express_crickit feather_m0_adalogger feather_m0_basic feather_m0_express catwan_usbstick pyportal" TRAVIS_SDK=arm
+ - TRAVIS_BOARDS="circuitplayground_express_crickit feather_m0_adalogger feather_m0_basic feather_m0_express catwan_usbstick pyportal sparkfun_samd21_mini" TRAVIS_SDK=arm
addons:
artifacts:
diff --git a/lib/tinyusb b/lib/tinyusb
-Subproject 3bb53273cd3770328f55ba317af3df0cce4333c
+Subproject 5804e56e3c2ab4480bf72d94d997f769a645af4
diff --git a/locale/ID.po b/locale/ID.po
new file mode 100644
index 000000000..405b3a0e3
--- /dev/null
+++ b/locale/ID.po
@@ -0,0 +1,2587 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2019-01-10 11:05-0800\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"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: extmod/machine_i2c.c:299
+msgid "invalid I2C peripheral"
+msgstr "perangkat I2C tidak valid"
+
+#: extmod/machine_i2c.c:340 extmod/machine_i2c.c:354 extmod/machine_i2c.c:368
+#: extmod/machine_i2c.c:392
+msgid "I2C operation not supported"
+msgstr "operasi I2C tidak didukung"
+
+#: extmod/machine_mem.c:45 ports/unix/modmachine.c:53
+#, c-format
+msgid "address %08x is not aligned to %d bytes"
+msgstr "alamat %08x tidak selaras dengan %d bytes"
+
+#: extmod/machine_spi.c:57
+msgid "invalid SPI peripheral"
+msgstr "perangkat SPI tidak valid"
+
+#: extmod/machine_spi.c:124
+msgid "buffers must be the same length"
+msgstr "buffers harus mempunyai panjang yang sama"
+
+#: extmod/machine_spi.c:207
+msgid "bits must be 8"
+msgstr "bits harus memilki nilai 8"
+
+#: extmod/machine_spi.c:210
+msgid "firstbit must be MSB"
+msgstr "bit pertama(firstbit) harus berupa MSB"
+
+#: extmod/machine_spi.c:215
+msgid "must specify all of sck/mosi/miso"
+msgstr "harus menentukan semua pin sck/mosi/miso"
+
+#: extmod/modframebuf.c:299
+msgid "invalid format"
+msgstr "format tidak valid"
+
+#: extmod/modubinascii.c:38 extmod/moduhashlib.c:102
+msgid "a bytes-like object is required"
+msgstr "sebuah objek menyerupai byte (bytes-like) dibutuhkan"
+
+#: extmod/modubinascii.c:90
+msgid "odd-length string"
+msgstr "panjang data string memiliki keganjilan (odd-length)"
+
+#: extmod/modubinascii.c:101
+msgid "non-hex digit found"
+msgstr "digit non-hex ditemukan"
+
+#: extmod/modubinascii.c:169
+msgid "incorrect padding"
+msgstr "lapisan (padding) tidak benar"
+
+#: extmod/moductypes.c:122
+msgid "syntax error in uctypes descriptor"
+msgstr "sintaksis error pada pendeskripsi uctypes"
+
+#: extmod/moductypes.c:219
+msgid "Cannot unambiguously get sizeof scalar"
+msgstr "tidak dapat mendapatkan ukuran scalar secara tidak ambigu"
+
+#: extmod/moductypes.c:397
+msgid "struct: no fields"
+msgstr "struct: tidak ada fields"
+
+#: extmod/moductypes.c:530
+msgid "struct: cannot index"
+msgstr "struct: tidak bisa melakukan index"
+
+#: extmod/moductypes.c:544
+msgid "struct: index out of range"
+msgstr "struct: index keluar dari jangkauan"
+
+#: extmod/moduheapq.c:38
+msgid "heap must be a list"
+msgstr "heap harus berupa sebuah list"
+
+#: extmod/moduheapq.c:86 extmod/modutimeq.c:147 extmod/modutimeq.c:172
+msgid "empty heap"
+msgstr "heap kosong"
+
+#: extmod/modujson.c:281
+msgid "syntax error in JSON"
+msgstr "sintaksis error pada JSON"
+
+#: extmod/modure.c:161
+msgid "Splitting with sub-captures"
+msgstr "Memisahkan dengan menggunakan sub-captures"
+
+#: extmod/modure.c:207
+msgid "Error in regex"
+msgstr "Error pada regex"
+
+#: extmod/modussl_axtls.c:81
+msgid "invalid key"
+msgstr "key tidak valid"
+
+#: extmod/modussl_axtls.c:87
+msgid "invalid cert"
+msgstr "cert tidak valid"
+
+#: extmod/modutimeq.c:131
+msgid "queue overflow"
+msgstr "antrian meluap (overflow)"
+
+#: extmod/moduzlib.c:98
+msgid "compression header"
+msgstr "kompresi header"
+
+#: extmod/uos_dupterm.c:120
+msgid "invalid dupterm index"
+msgstr "indeks dupterm tidak valid"
+
+#: extmod/vfs_fat.c:426 py/moduerrno.c:154
+msgid "Read-only filesystem"
+msgstr "sistem file (filesystem) bersifat Read-only"
+
+#: extmod/vfs_posix_file.c:48 ports/unix/file.c:50 py/objstringio.c:43
+msgid "I/O operation on closed file"
+msgstr "operasi I/O pada file tertutup"
+
+#: lib/embed/abort_.c:8
+msgid "abort() called"
+msgstr "abort() dipanggil"
+
+#: lib/netutils/netutils.c:83
+msgid "invalid arguments"
+msgstr "argumen-argumen tidak valid"
+
+#: lib/utils/pyexec.c:97 py/builtinimport.c:251
+msgid "script compilation not supported"
+msgstr "kompilasi script tidak didukung"
+
+#: main.c:150
+msgid " output:\n"
+msgstr "output:\n"
+
+#: main.c:164 main.c:237
+msgid ""
+"Auto-reload is on. Simply save files over USB to run them or enter REPL to "
+"disable.\n"
+msgstr ""
+"Auto-reload aktif. Silahkan simpan data-data (files) melalui USB untuk "
+"menjalankannya atau masuk ke REPL untukmenonaktifkan.\n"
+
+#: main.c:166
+msgid "Running in safe mode! Auto-reload is off.\n"
+msgstr "Berjalan di mode aman(safe mode)! Auto-reload tidak aktif.\n"
+
+#: main.c:168 main.c:239
+msgid "Auto-reload is off.\n"
+msgstr "Auto-reload tidak aktif.\n"
+
+#: main.c:182
+msgid "Running in safe mode! Not running saved code.\n"
+msgstr ""
+"Berjalan di mode aman(safe mode)! tidak menjalankan kode yang tersimpan.\n"
+
+#: main.c:198
+msgid "WARNING: Your code filename has two extensions\n"
+msgstr "PERINGATAN: Nama file kode anda mempunyai dua ekstensi\n"
+
+#: main.c:244
+msgid "Press any key to enter the REPL. Use CTRL-D to reload."
+msgstr ""
+"Tekan tombol apa saja untuk masuk ke dalam REPL. Gunakan CTRL+D untuk reset "
+"(Reload)"
+
+#: main.c:407
+msgid "soft reboot\n"
+msgstr "memulai ulang software(soft reboot)\n"
+
+#: ports/atmel-samd/audio_dma.c:209
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361
+msgid "All sync event channels in use"
+msgstr "Semua channel event yang disinkronisasi sedang digunakan"
+
+#: ports/atmel-samd/bindings/samd/Clock.c:135
+msgid "calibration is read only"
+msgstr "kalibrasi adalah read only"
+
+#: ports/atmel-samd/bindings/samd/Clock.c:137
+msgid "calibration is out of range"
+msgstr "kalibrasi keluar dari jangkauan"
+
+#: ports/atmel-samd/board_busses.c:59 ports/nrf/board_busses.c:39
+msgid "No default I2C bus"
+msgstr "Tidak ada standar bus I2C"
+
+#: ports/atmel-samd/board_busses.c:85 ports/nrf/board_busses.c:64
+msgid "No default SPI bus"
+msgstr "Tidak ada standar bus SPI"
+
+#: ports/atmel-samd/board_busses.c:112 ports/nrf/board_busses.c:91
+msgid "No default UART bus"
+msgstr "Tidak ada standar bus UART"
+
+#: ports/atmel-samd/common-hal/analogio/AnalogIn.c:63
+#: ports/nrf/common-hal/analogio/AnalogIn.c:39
+msgid "Pin does not have ADC capabilities"
+msgstr "Pin tidak mempunya kemampuan untuk ADC (Analog Digital Converter)"
+
+#: ports/atmel-samd/common-hal/analogio/AnalogOut.c:49
+msgid "No DAC on chip"
+msgstr "Tidak ada DAC (Digital Analog Converter) di dalam chip"
+
+#: ports/atmel-samd/common-hal/analogio/AnalogOut.c:56
+msgid "AnalogOut not supported on given pin"
+msgstr "pin yang dipakai tidak mendukung AnalogOut"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:147
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:150
+msgid "Invalid bit clock pin"
+msgstr "Bit clock pada pin tidak valid"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:153
+msgid "Bit clock and word select must share a clock unit"
+msgstr "Bit clock dan word harus memiliki kesamaan pada clock unit"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:156
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:130
+msgid "Invalid data pin"
+msgstr "data pin tidak valid"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:169
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:174
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:145
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:150
+msgid "Serializer in use"
+msgstr "Serializer sedang digunakan"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:230
+msgid "Clock unit in use"
+msgstr "Clock unit sedang digunakan"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:240
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:172
+msgid "Unable to find free GCLK"
+msgstr "Tidak dapat menemukan GCLK yang kosong"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:254
+msgid "Too many channels in sample."
+msgstr "Terlalu banyak channel dalam sampel"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417
+msgid "No DMA channel found"
+msgstr "tidak ada channel DMA ditemukan"
+
+#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419
+msgid "Unable to allocate buffers for signed conversion"
+msgstr "Tidak dapat mengalokasikan buffer untuk signed conversion"
+
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:109
+msgid "Invalid clock pin"
+msgstr "Clock pada pin tidak valid"
+
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:134
+msgid "Only 8 or 16 bit mono with "
+msgstr "Hanya 8 atau 16 bit mono dengan "
+
+#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:167
+msgid "sampling rate out of range"
+msgstr "nilai sampling keluar dari jangkauan"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132
+msgid "DAC already in use"
+msgstr "DAC sudah digunakan"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136
+msgid "Right channel unsupported"
+msgstr "Channel Kanan tidak didukung"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139
+#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116
+#: ports/atmel-samd/common-hal/touchio/TouchIn.c:65
+msgid "Invalid pin"
+msgstr "Pin tidak valid"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147
+msgid "Invalid pin for left channel"
+msgstr "Pin untuk channel kiri tidak valid"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151
+msgid "Invalid pin for right channel"
+msgstr "Pin untuk channel kanan tidak valid"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154
+msgid "Cannot output both channels on the same pin"
+msgstr ""
+"Tidak dapat menggunakan output di kedua channel dengan menggunakan pin yang "
+"sama"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243
+#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189
+#: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110
+#: ports/nrf/common-hal/pulseio/PulseOut.c:107
+msgid "All timers in use"
+msgstr "Semua timer sedang digunakan"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285
+msgid "All event channels in use"
+msgstr "Semua channel event sedang digunakan"
+
+#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375
+#, c-format
+msgid "Sample rate too high. It must be less than %d"
+msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d"
+
+#: ports/atmel-samd/common-hal/busio/I2C.c:71
+msgid "Not enough pins available"
+msgstr "Pin yang tersedia tidak cukup"
+
+#: ports/atmel-samd/common-hal/busio/I2C.c:78
+#: ports/atmel-samd/common-hal/busio/SPI.c:171
+#: ports/atmel-samd/common-hal/busio/UART.c:120
+#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45
+#: ports/nrf/common-hal/busio/I2C.c:84
+msgid "Invalid pins"
+msgstr "Pin-pin tidak valid"
+
+#: ports/atmel-samd/common-hal/busio/I2C.c:101
+msgid "SDA or SCL needs a pull up"
+msgstr "SDA atau SCL membutuhkan pull up"
+
+#: ports/atmel-samd/common-hal/busio/I2C.c:121
+msgid "Unsupported baudrate"
+msgstr "Baudrate tidak didukung"
+
+#: ports/atmel-samd/common-hal/busio/UART.c:67
+msgid "bytes > 8 bits not supported"
+msgstr "byte > 8 bit tidak didukung"
+
+#: ports/atmel-samd/common-hal/busio/UART.c:73
+#: ports/nrf/common-hal/busio/UART.c:118
+msgid "tx and rx cannot both be None"
+msgstr "tx dan rx keduanya tidak boleh kosong"
+
+#: ports/atmel-samd/common-hal/busio/UART.c:146
+#: ports/nrf/common-hal/busio/UART.c:152
+msgid "Failed to allocate RX buffer"
+msgstr "Gagal untuk mengalokasikan buffer RX"
+
+#: ports/atmel-samd/common-hal/busio/UART.c:154
+msgid "Could not initialize UART"
+msgstr "Tidak dapat menginisialisasi UART"
+
+#: ports/atmel-samd/common-hal/busio/UART.c:241
+#: ports/nrf/common-hal/busio/UART.c:197
+msgid "No RX pin"
+msgstr "Tidak pin RX"
+
+#: ports/atmel-samd/common-hal/busio/UART.c:300
+#: ports/nrf/common-hal/busio/UART.c:232
+msgid "No TX pin"
+msgstr "Tidak ada pin TX"
+
+#: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170
+#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147
+msgid "Cannot get pull while in output mode"
+msgstr "Tidak bisa mendapatkan pull pada saat mode output"
+
+#: ports/atmel-samd/common-hal/microcontroller/__init__.c:74
+#: ports/esp8266/common-hal/microcontroller/__init__.c:64
+msgid "Cannot reset into bootloader because no bootloader is present."
+msgstr ""
+"Tidak dapat melakukan reset ke bootloader karena tidak ada bootloader yang "
+"terisi"
+
+#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120
+#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369
+#: ports/nrf/common-hal/pulseio/PWMOut.c:119
+#: ports/nrf/common-hal/pulseio/PWMOut.c:233
+msgid "Invalid PWM frequency"
+msgstr "Frekuensi PWM tidak valid"
+
+#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:187
+msgid "All timers for this pin are in use"
+msgstr "Semua timer untuk pin ini sedang digunakan"
+
+#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:110
+msgid "No hardware support on pin"
+msgstr "Tidak ada dukungan hardware untuk pin"
+
+#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:113
+msgid "EXTINT channel already in use"
+msgstr "Channel EXTINT sedang digunakan"
+
+#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:118
+#: ports/esp8266/common-hal/pulseio/PulseIn.c:86
+#, c-format
+msgid "Failed to allocate RX buffer of %d bytes"
+msgstr "Gagal untuk megalokasikan buffer RX dari %d byte"
+
+#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:205
+#: ports/esp8266/common-hal/pulseio/PulseIn.c:151
+msgid "pop from an empty PulseIn"
+msgstr "Muncul dari PulseIn yang kosong"
+
+#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:237
+#: ports/esp8266/common-hal/pulseio/PulseIn.c:182 py/obj.c:422
+msgid "index out of range"
+msgstr "index keluar dari jangkauan"
+
+#: ports/atmel-samd/common-hal/pulseio/PulseOut.c:178
+msgid "Another send is already active"
+msgstr "Send yang lain sudah aktif"
+
+#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:38
+msgid "Both pins must support hardware interrupts"
+msgstr "Kedua pin harus mendukung hardware interrut"
+
+#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:46
+msgid "A hardware interrupt channel is already in use"
+msgstr "Sebuah channel hardware interrupt sedang digunakan"
+
+#: ports/atmel-samd/common-hal/rtc/RTC.c:101
+msgid "calibration value out of range +/-127"
+msgstr "nilai kalibrasi keluar dari jangkauan +/-127"
+
+#: ports/atmel-samd/common-hal/touchio/TouchIn.c:75
+msgid "No free GCLKs"
+msgstr "Tidak ada GCLK yang kosong"
+
+#: ports/esp8266/common-hal/analogio/AnalogIn.c:43
+msgid "Pin %q does not have ADC capabilities"
+msgstr "Pin %q tidak memiliki kemampuan ADC"
+
+#: ports/esp8266/common-hal/analogio/AnalogOut.c:39
+msgid "No hardware support for analog out."
+msgstr "Tidak dukungan hardware untuk analog out."
+
+#: ports/esp8266/common-hal/busio/SPI.c:72
+msgid "Pins not valid for SPI"
+msgstr "Pin-pin tidak valid untuk SPI"
+
+#: ports/esp8266/common-hal/busio/UART.c:45
+msgid "Only tx supported on UART1 (GPIO2)."
+msgstr "Hanya tx yang mendukung pada UART1 (GPIO2)."
+
+#: ports/esp8266/common-hal/busio/UART.c:67 ports/esp8266/machine_uart.c:108
+msgid "invalid data bits"
+msgstr "bit data tidak valid"
+
+#: ports/esp8266/common-hal/busio/UART.c:91 ports/esp8266/machine_uart.c:144
+msgid "invalid stop bits"
+msgstr "stop bit tidak valid"
+
+#: ports/esp8266/common-hal/digitalio/DigitalInOut.c:200
+msgid "ESP8266 does not support pull down."
+msgstr "ESP866 tidak mendukung pull down"
+
+#: ports/esp8266/common-hal/digitalio/DigitalInOut.c:210
+msgid "GPIO16 does not support pull up."
+msgstr "GPIO16 tidak mendukung pull up"
+
+#: ports/esp8266/common-hal/microcontroller/__init__.c:66
+msgid "ESP8226 does not support safe mode."
+msgstr "ESP8266 tidak mendukung safe mode"
+
+#: ports/esp8266/common-hal/pulseio/PWMOut.c:54
+#: ports/esp8266/common-hal/pulseio/PWMOut.c:113
+#, c-format
+msgid "Maximum PWM frequency is %dhz."
+msgstr "Nilai maksimum frekuensi PWM adalah %dhz"
+
+#: ports/esp8266/common-hal/pulseio/PWMOut.c:57
+#: ports/esp8266/common-hal/pulseio/PWMOut.c:116
+msgid "Minimum PWM frequency is 1hz."
+msgstr "Nilai minimum frekuensi PWM is 1hz"
+
+#: ports/esp8266/common-hal/pulseio/PWMOut.c:68
+#, c-format
+msgid "Multiple PWM frequencies not supported. PWM already set to %dhz."
+msgstr "Nilai Frekuensi PWM ganda tidak didukung. PWM sudah diatur pada %dhz"
+
+#: ports/esp8266/common-hal/pulseio/PWMOut.c:77 ports/esp8266/machine_pwm.c:70
+#, c-format
+msgid "PWM not supported on pin %d"
+msgstr "PWM tidak didukung pada pin %d"
+
+#: ports/esp8266/common-hal/pulseio/PulseIn.c:78
+msgid "No PulseIn support for %q"
+msgstr "Tidak ada dukungan PulseIn untuk %q"
+
+#: ports/esp8266/common-hal/storage/__init__.c:34
+msgid "Unable to remount filesystem"
+msgstr "Tidak dapat memasang filesystem kembali"
+
+#: ports/esp8266/common-hal/storage/__init__.c:38
+msgid "Use esptool to erase flash and re-upload Python instead"
+msgstr ""
+"Gunakan esptool untuk menghapus flash dan upload ulang Python sebagai "
+"gantinya"
+
+#: ports/esp8266/esp_mphal.c:154
+msgid "C-level assert"
+msgstr "Dukungan C-level"
+
+#: ports/esp8266/machine_adc.c:57
+#, c-format
+msgid "not a valid ADC Channel: %d"
+msgstr "tidak valid channel ADC: %d"
+
+#: ports/esp8266/machine_hspi.c:131 ports/esp8266/machine_hspi.c:137
+msgid "impossible baudrate"
+msgstr "baudrate tidak memungkinkan"
+
+#: ports/esp8266/machine_pin.c:129
+msgid "expecting a pin"
+msgstr "mengharapkan sebuah pin"
+
+#: ports/esp8266/machine_pin.c:284
+msgid "Pin(16) doesn't support pull"
+msgstr "Pin(16) tidak mendukung pull"
+
+#: ports/esp8266/machine_pin.c:323
+msgid "invalid pin"
+msgstr "pin tidak valid"
+
+#: ports/esp8266/machine_pin.c:389
+msgid "pin does not have IRQ capabilities"
+msgstr "pin tidak memiliki kemampuan IRQ"
+
+#: ports/esp8266/machine_rtc.c:185
+msgid "buffer too long"
+msgstr "buffer terlalu panjang"
+
+#: ports/esp8266/machine_rtc.c:209 ports/esp8266/machine_rtc.c:223
+#: ports/esp8266/machine_rtc.c:246
+msgid "invalid alarm"
+msgstr "alarm tidak valid"
+
+#: ports/esp8266/machine_uart.c:169
+#, c-format
+msgid "UART(%d) does not exist"
+msgstr "UART(%d) tidak ada"
+
+#: ports/esp8266/machine_uart.c:219
+msgid "UART(1) can't read"
+msgstr "UART(1) tidak dapat dibaca"
+
+#: ports/esp8266/modesp.c:119
+msgid "len must be multiple of 4"
+msgstr "len harus kelipatan dari 4"
+
+#: ports/esp8266/modesp.c:274
+#, c-format
+msgid "memory allocation failed, allocating %u bytes for native code"
+msgstr "alokasi memori gagal, mengalokasikan %u byte untuk kode native"
+
+#: ports/esp8266/modesp.c:317
+msgid "flash location must be below 1MByte"
+msgstr "alokasi flash harus dibawah 1MByte"
+
+#: ports/esp8266/modmachine.c:63
+msgid "frequency can only be either 80Mhz or 160MHz"
+msgstr "frekuensi hanya bisa didefinisikan 80Mhz atau 160Mhz"
+
+#: ports/esp8266/modnetwork.c:61
+msgid "AP required"
+msgstr "AP dibutuhkan"
+
+#: ports/esp8266/modnetwork.c:61
+msgid "STA required"
+msgstr "STA dibutuhkan"
+
+#: ports/esp8266/modnetwork.c:87
+msgid "Cannot update i/f status"
+msgstr "Tidak dapat memperbarui status i/f"
+
+#: ports/esp8266/modnetwork.c:142
+msgid "Cannot set STA config"
+msgstr "Tidak dapat mengatur konfigurasi STA"
+
+#: ports/esp8266/modnetwork.c:144
+msgid "Cannot connect to AP"
+msgstr "Tidak dapat menyambungkan ke AP"
+
+#: ports/esp8266/modnetwork.c:152
+msgid "Cannot disconnect from AP"
+msgstr "Tidak dapat memutuskna dari AP"
+
+#: ports/esp8266/modnetwork.c:173
+msgid "unknown status param"
+msgstr "status param tidak diketahui"
+
+#: ports/esp8266/modnetwork.c:222
+msgid "STA must be active"
+msgstr "STA harus aktif"
+
+#: ports/esp8266/modnetwork.c:239
+msgid "scan failed"
+msgstr "scan gagal"
+
+#: ports/esp8266/modnetwork.c:306
+msgid "wifi_set_ip_info() failed"
+msgstr "wifi_set_ip_info() gagal"
+
+#: ports/esp8266/modnetwork.c:319
+msgid "either pos or kw args are allowed"
+msgstr "hanya antar pos atau kw args yang diperbolehkan"
+
+#: ports/esp8266/modnetwork.c:329
+msgid "can't get STA config"
+msgstr "tidak bisa mendapatkan konfigurasi STA"
+
+#: ports/esp8266/modnetwork.c:331
+msgid "can't get AP config"
+msgstr "tidak bisa mendapatkan konfigurasi AP"
+
+#: ports/esp8266/modnetwork.c:346
+msgid "invalid buffer length"
+msgstr "panjang buffer tidak valid"
+
+#: ports/esp8266/modnetwork.c:405
+msgid "can't set STA config"
+msgstr "tidak bisa mendapatkan konfigurasi STA"
+
+#: ports/esp8266/modnetwork.c:407
+msgid "can't set AP config"
+msgstr "tidak bisa mendapatkan konfigurasi AP"
+
+#: ports/esp8266/modnetwork.c:416
+msgid "can query only one param"
+msgstr "hanya bisa melakukan query satu param"
+
+#: ports/esp8266/modnetwork.c:469
+msgid "unknown config param"
+msgstr "konfigurasi param tidak diketahui"
+
+#: ports/nrf/common-hal/analogio/AnalogOut.c:37
+msgid "AnalogOut functionality not supported"
+msgstr "fungsionalitas AnalogOut tidak didukung"
+
+#: ports/nrf/common-hal/bleio/Adapter.c:41
+#, c-format
+msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
+msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l"
+
+#: ports/nrf/common-hal/bleio/Adapter.c:125
+#, c-format
+msgid "Failed to change softdevice state, error: 0x%08lX"
+msgstr "Gagal untuk merubah status softdevice, error: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Adapter.c:135
+#, c-format
+msgid "Failed to get softdevice state, error: 0x%08lX"
+msgstr "Gagal untuk mendapatkan status softdevice, error: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Adapter.c:155
+#, c-format
+msgid "Failed to get local address, error: 0x%08lX"
+msgstr "Gagal untuk mendapatkan alamat lokal, error: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Characteristic.c:52
+#, c-format
+msgid "Failed to write gatts value, status: 0x%08lX"
+msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Characteristic.c:76
+#, c-format
+msgid "Failed to notify attribute value, status: 0x%08lX"
+msgstr "Gagal untuk melaporkan nilai atribut, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Characteristic.c:91
+#, c-format
+msgid "Failed to read attribute value, status: 0x%08lX"
+msgstr "Gagal untuk membaca nilai atribut, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Characteristic.c:119
+#: ports/nrf/common-hal/bleio/Device.c:272
+#: ports/nrf/common-hal/bleio/Device.c:307
+#, c-format
+msgid "Failed to acquire mutex, status: 0x%08lX"
+msgstr "Gagal untuk mendapatkan mutex, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Characteristic.c:126
+#, c-format
+msgid "Failed to write attribute value, status: 0x%08lX"
+msgstr "Gagal untuk menulis nilai atribut, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Characteristic.c:138
+#: ports/nrf/common-hal/bleio/Device.c:284
+#: ports/nrf/common-hal/bleio/Device.c:319
+#: ports/nrf/common-hal/bleio/Device.c:354
+#: ports/nrf/common-hal/bleio/Device.c:391
+#, c-format
+msgid "Failed to release mutex, status: 0x%08lX"
+msgstr "Gagal untuk melepaskan mutex, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:81
+#: ports/nrf/common-hal/bleio/Device.c:114
+msgid "Can not fit data into the advertisment packet"
+msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment"
+
+#: ports/nrf/common-hal/bleio/Device.c:266
+#, fuzzy, c-format
+msgid "Failed to discover serivices, status: 0x%08lX"
+msgstr "Gagal untuk menemukan layanan, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:403
+#: ports/nrf/common-hal/bleio/Scanner.c:76
+#, c-format
+msgid "Failed to continue scanning, status: 0x%0xlX"
+msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:436
+#, c-format
+msgid "Failed to connect, status: 0x%08lX"
+msgstr "Gagal untuk menyambungkan, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:513
+#, c-format
+msgid "Failed to add service, status: 0x%08lX"
+msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:531
+#, c-format
+msgid "Failed to start advertisment, status: 0x%08lX"
+msgstr "Gagal untuk memulai advertisement, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:549
+#, c-format
+msgid "Failed to stop advertisment, status: 0x%08lX"
+msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:575
+#: ports/nrf/common-hal/bleio/Scanner.c:103
+#, c-format
+msgid "Failed to start scanning, status: 0x%0xlX"
+msgstr "Gagal untuk melakukan scanning, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Device.c:592
+#, c-format
+msgid "Failed to create mutex, status: 0x%0xlX"
+msgstr "Gagal untuk membuat mutex, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/Service.c:83
+#, c-format
+msgid "Failed to add characteristic, status: 0x%08lX"
+msgstr "Gagal untuk menambahkan karakteristik, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/UUID.c:97
+#, c-format
+msgid "Failed to add Vendor Specific UUID, status: 0x%08lX"
+msgstr "Gagal untuk menambahkan Vendor Spesific UUID, status: 0x%08lX"
+
+#: ports/nrf/common-hal/bleio/UUID.c:102
+msgid "Invalid UUID string length"
+msgstr "Panjang string UUID tidak valid"
+
+#: ports/nrf/common-hal/bleio/UUID.c:109
+#: shared-bindings/bleio/Characteristic.c:125
+#: shared-bindings/bleio/Service.c:105
+msgid "Invalid UUID parameter"
+msgstr "Parameter UUID tidak valid"
+
+#: ports/nrf/common-hal/busio/I2C.c:98
+msgid "All I2C peripherals are in use"
+msgstr "Semua perangkat I2C sedang digunakan"
+
+#: ports/nrf/common-hal/busio/SPI.c:133
+msgid "All SPI peripherals are in use"
+msgstr "Semua perangkat SPI sedang digunakan"
+
+#: ports/nrf/common-hal/busio/UART.c:49
+#, c-format
+msgid "error = 0x%08lX"
+msgstr "error = 0x%08lX"
+
+#: ports/nrf/common-hal/busio/UART.c:122
+msgid "Invalid buffer size"
+msgstr "Ukuran buffer tidak valid"
+
+#: ports/nrf/common-hal/busio/UART.c:126
+msgid "Odd parity is not supported"
+msgstr "Parity ganjil tidak didukung"
+
+#: ports/nrf/common-hal/busio/UART.c:358 ports/nrf/common-hal/busio/UART.c:362
+#: ports/nrf/common-hal/busio/UART.c:367 ports/nrf/common-hal/busio/UART.c:372
+#: ports/nrf/common-hal/busio/UART.c:378 ports/nrf/common-hal/busio/UART.c:383
+#: ports/nrf/common-hal/busio/UART.c:388 ports/nrf/common-hal/busio/UART.c:392
+#: ports/nrf/common-hal/busio/UART.c:400
+msgid "busio.UART not available"
+msgstr "busio.UART tidak tersedia"
+
+#: ports/nrf/common-hal/microcontroller/Processor.c:49
+#, c-format
+msgid "Can not get temperature. status: 0x%02x"
+msgstr "Tidak bisa mendapatkan temperatur. status: 0x%02x"
+
+#: ports/nrf/common-hal/pulseio/PWMOut.c:161
+msgid "All PWM peripherals are in use"
+msgstr "Semua perangkat PWM sedang digunakan"
+
+#: ports/unix/modffi.c:138
+msgid "Unknown type"
+msgstr "Tipe tidak diketahui"
+
+#: ports/unix/modffi.c:207 ports/unix/modffi.c:265
+msgid "Error in ffi_prep_cif"
+msgstr "Errod pada ffi_prep_cif"
+
+#: ports/unix/modffi.c:270
+msgid "ffi_prep_closure_loc"
+msgstr "ffi_prep_closure_loc"
+
+#: ports/unix/modffi.c:413
+msgid "Don't know how to pass object to native function"
+msgstr "Tidak tahu cara meloloskan objek ke fungsi native"
+
+#: ports/unix/modusocket.c:474
+#, c-format
+msgid "[addrinfo error %d]"
+msgstr "[addrinfo error %d]"
+
+#: py/argcheck.c:44
+msgid "function does not take keyword arguments"
+msgstr "fungsi tidak dapat mengambil argumen keyword"
+
+#: py/argcheck.c:54 py/bc.c:85 py/objnamedtuple.c:104
+#, c-format
+msgid "function takes %d positional arguments but %d were given"
+msgstr "fungsi mengambil posisi argumen %d tapi %d yang diberikan"
+
+#: py/argcheck.c:64
+#, c-format
+msgid "function missing %d required positional arguments"
+msgstr "fungsi kehilangan %d argumen posisi yang dibutuhkan"
+
+#: py/argcheck.c:72
+#, c-format
+msgid "function expected at most %d arguments, got %d"
+msgstr "fungsi diharapkan setidaknya %d argumen, hanya mendapatkan %d"
+
+#: py/argcheck.c:97
+msgid "'%q' argument required"
+msgstr "'%q' argumen dibutuhkan"
+
+#: py/argcheck.c:122
+msgid "extra positional arguments given"
+msgstr "argumen posisi ekstra telah diberikan"
+
+#: py/argcheck.c:130
+msgid "extra keyword arguments given"
+msgstr "argumen keyword ekstra telah diberikan"
+
+#: py/argcheck.c:142
+msgid "argument num/types mismatch"
+msgstr "argumen num/types tidak cocok"
+
+#: py/argcheck.c:147
+msgid "keyword argument(s) not yet implemented - use normal args instead"
+msgstr "argumen keyword belum diimplementasi - gunakan args normal"
+
+#: py/bc.c:88 py/objnamedtuple.c:108
+msgid "%q() takes %d positional arguments but %d were given"
+msgstr "%q() mengambil posisi argumen %d tapi %d yang diberikan"
+
+#: py/bc.c:197 py/bc.c:215
+msgid "unexpected keyword argument"
+msgstr "argumen keyword tidak diharapkan"
+
+#: py/bc.c:199
+msgid "keywords must be strings"
+msgstr "keyword harus berupa string"
+
+#: py/bc.c:206 py/objnamedtuple.c:138
+msgid "function got multiple values for argument '%q'"
+msgstr "fungsi mendapatkan nilai ganda untuk argumen '%q'"
+
+#: py/bc.c:218 py/objnamedtuple.c:130
+msgid "unexpected keyword argument '%q'"
+msgstr "keyword argumen '%q' tidak diharapkan"
+
+#: py/bc.c:244
+#, c-format
+msgid "function missing required positional argument #%d"
+msgstr "fungsi kehilangan argumen posisi #%d yang dibutuhkan"
+
+#: py/bc.c:260
+msgid "function missing required keyword argument '%q'"
+msgstr "fungsi kehilangan argumen keyword '%q' yang dibutuhkan"
+
+#: py/bc.c:269
+msgid "function missing keyword-only argument"
+msgstr "fungsi kehilangan argumen keyword-only"
+
+#: py/binary.c:112
+msgid "bad typecode"
+msgstr "typecode buruk"
+
+#: py/builtinevex.c:99
+msgid "bad compile mode"
+msgstr "mode compile buruk"
+
+#: py/builtinhelp.c:137
+msgid "Plus any modules on the filesystem\n"
+msgstr "Tambahkan module apapun pada filesystem\n"
+
+#: py/builtinhelp.c:183
+#, c-format
+msgid ""
+"Welcome to Adafruit CircuitPython %s!\n"
+"\n"
+"Please visit learn.adafruit.com/category/circuitpython for project guides.\n"
+"\n"
+"To list built-in modules please do `help(\"modules\")`.\n"
+msgstr ""
+"Selamat datang ke Adafruit CircuitPython %s!\n"
+"\n"
+"Silahkan kunjungi learn.adafruit.com/category/circuitpython untuk panduan "
+"project.\n"
+"\n"
+"Untuk menampilkan modul built-in silahkan ketik `help(\"modules\")`.\n"
+
+#: py/builtinimport.c:336
+msgid "cannot perform relative import"
+msgstr "tidak dapat melakukan relative import"
+
+#: py/builtinimport.c:420 py/builtinimport.c:532
+msgid "module not found"
+msgstr "modul tidak ditemukan"
+
+#: py/builtinimport.c:423 py/builtinimport.c:535
+msgid "no module named '%q'"
+msgstr "tidak ada modul yang bernama '%q'"
+
+#: py/builtinimport.c:510
+msgid "relative import"
+msgstr "relative import"
+
+#: py/compile.c:397 py/compile.c:542
+msgid "can't assign to expression"
+msgstr "tidak dapat menetapkan ke ekspresi"
+
+#: py/compile.c:416
+msgid "multiple *x in assignment"
+msgstr "perkalian *x dalam assignment"
+
+#: py/compile.c:642
+msgid "non-default argument follows default argument"
+msgstr "argumen non-default mengikuti argumen standar(default)"
+
+#: py/compile.c:771 py/compile.c:789
+msgid "invalid micropython decorator"
+msgstr "micropython decorator tidak valid"
+
+#: py/compile.c:943
+msgid "can't delete expression"
+msgstr "tidak bisa menghapus ekspresi"
+
+#: py/compile.c:955
+msgid "'break' outside loop"
+msgstr "'break' diluar loop"
+
+#: py/compile.c:958
+msgid "'continue' outside loop"
+msgstr "'continue' diluar loop"
+
+#: py/compile.c:969
+msgid "'return' outside function"
+msgstr "'return' diluar fungsi"
+
+#: py/compile.c:1169
+msgid "identifier redefined as global"
+msgstr "identifier didefinisi ulang sebagai global"
+
+#: py/compile.c:1185
+msgid "no binding for nonlocal found"
+msgstr "tidak ada ikatan/bind pada temuan nonlocal"
+
+#: py/compile.c:1188
+msgid "identifier redefined as nonlocal"
+msgstr "identifier didefinisi ulang sebagai nonlocal"
+
+#: py/compile.c:1197
+msgid "can't declare nonlocal in outer code"
+msgstr "tidak dapat mendeklarasikan nonlocal diluar jangkauan kode"
+
+#: py/compile.c:1542
+msgid "default 'except' must be last"
+msgstr "'except' standar harus terakhir"
+
+#: py/compile.c:2095
+msgid "*x must be assignment target"
+msgstr "*x harus menjadi target assignment"
+
+#: py/compile.c:2193
+msgid "super() can't find self"
+msgstr "super() tidak dapat menemukan dirinya sendiri"
+
+#: py/compile.c:2256
+msgid "can't have multiple *x"
+msgstr "tidak bisa memiliki *x ganda"
+
+#: py/compile.c:2263
+msgid "can't have multiple **x"
+msgstr "tidak bisa memiliki **x ganda"
+
+#: py/compile.c:2271
+msgid "LHS of keyword arg must be an id"
+msgstr "LHS dari keyword arg harus menjadi sebuah id"
+
+#: py/compile.c:2287
+msgid "non-keyword arg after */**"
+msgstr "non-keyword arg setelah */**"
+
+#: py/compile.c:2291
+msgid "non-keyword arg after keyword arg"
+msgstr "non-keyword arg setelah keyword arg"
+
+#: py/compile.c:2463 py/compile.c:2473 py/compile.c:2712 py/compile.c:2742
+#: py/parse.c:1176
+msgid "invalid syntax"
+msgstr "syntax tidak valid"
+
+#: py/compile.c:2465
+msgid "expecting key:value for dict"
+msgstr "key:value diharapkan untuk dict"
+
+#: py/compile.c:2475
+msgid "expecting just a value for set"
+msgstr "hanya mengharapkan sebuah nilai (value) untuk set"
+
+#: py/compile.c:2600
+msgid "'yield' outside function"
+msgstr "'yield' diluar fungsi"
+
+#: py/compile.c:2619
+msgid "'await' outside function"
+msgstr "'await' diluar fungsi"
+
+#: py/compile.c:2774
+msgid "name reused for argument"
+msgstr "nama digunakan kembali untuk argumen"
+
+#: py/compile.c:2827
+msgid "parameter annotation must be an identifier"
+msgstr "anotasi parameter haruse sebuah identifier"
+
+#: py/compile.c:2969 py/compile.c:3137
+msgid "return annotation must be an identifier"
+msgstr "anotasi return harus sebuah identifier"
+
+#: py/compile.c:3097
+msgid "inline assembler must be a function"
+msgstr "inline assembler harus sebuah fungsi"
+
+#: py/compile.c:3134
+msgid "unknown type"
+msgstr "tipe tidak diketahui"
+
+#: py/compile.c:3154
+msgid "expecting an assembler instruction"
+msgstr "sebuah instruksi assembler diharapkan"
+
+#: py/compile.c:3184
+msgid "'label' requires 1 argument"
+msgstr "'label' membutuhkan 1 argumen"
+
+#: py/compile.c:3190
+msgid "label redefined"
+msgstr "label didefinis ulang"
+
+#: py/compile.c:3196
+msgid "'align' requires 1 argument"
+msgstr "'align' membutuhkan 1 argumen"
+
+#: py/compile.c:3205
+msgid "'data' requires at least 2 arguments"
+msgstr "'data' membutuhkan setidaknya 2 argumen"
+
+#: py/compile.c:3212
+msgid "'data' requires integer arguments"
+msgstr "'data' membutuhkan argumen integer"
+
+#: py/emitinlinethumb.c:102
+msgid "can only have up to 4 parameters to Thumb assembly"
+msgstr "hanya mampu memiliki hingga 4 parameter untuk Thumb assembly"
+
+#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112
+msgid "parameters must be registers in sequence r0 to r3"
+msgstr "parameter harus menjadi register dalam urutan r0 sampai r3"
+
+#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230
+#, c-format
+msgid "'%s' expects at most r%d"
+msgstr "'%s' mengharapkan setidaknya r%d"
+
+#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162
+#, c-format
+msgid "'%s' expects a register"
+msgstr "'%s' mengharapkan sebuah register"
+
+#: py/emitinlinethumb.c:211
+#, c-format
+msgid "'%s' expects a special register"
+msgstr "'%s' mengharapkan sebuah register spesial"
+
+#: py/emitinlinethumb.c:239
+#, c-format
+msgid "'%s' expects an FPU register"
+msgstr "'%s' mengharapkan sebuah FPU register"
+
+#: py/emitinlinethumb.c:292
+#, c-format
+msgid "'%s' expects {r0, r1, ...}"
+msgstr "'%s' mengharapkan {r0, r1, ...}"
+
+#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169
+#, c-format
+msgid "'%s' expects an integer"
+msgstr "'%s' mengharapkan integer"
+
+#: py/emitinlinethumb.c:304
+#, c-format
+msgid "'%s' integer 0x%x does not fit in mask 0x%x"
+msgstr "'%s' integer 0x%x tidak cukup didalam mask 0x%x"
+
+#: py/emitinlinethumb.c:328
+#, c-format
+msgid "'%s' expects an address of the form [a, b]"
+msgstr "'%s' mengharapkan sebuah alamat dengan bentuk [a, b]"
+
+#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182
+#, c-format
+msgid "'%s' expects a label"
+msgstr ""
+
+#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193
+msgid "label '%q' not defined"
+msgstr ""
+
+#: py/emitinlinethumb.c:806
+#, c-format
+msgid "unsupported Thumb instruction '%s' with %d arguments"
+msgstr ""
+
+#: py/emitinlinethumb.c:810
+msgid "branch not in range"
+msgstr ""
+
+#: py/emitinlinextensa.c:86
+msgid "can only have up to 4 parameters to Xtensa assembly"
+msgstr ""
+
+#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96
+msgid "parameters must be registers in sequence a2 to a5"
+msgstr ""
+
+#: py/emitinlinextensa.c:174
+#, c-format
+msgid "'%s' integer %d is not within range %d..%d"
+msgstr ""
+
+#: py/emitinlinextensa.c:327
+#, c-format
+msgid "unsupported Xtensa instruction '%s' with %d arguments"
+msgstr ""
+
+#: py/emitnative.c:183
+msgid "unknown type '%q'"
+msgstr ""
+
+#: py/emitnative.c:260
+msgid "Viper functions don't currently support more than 4 arguments"
+msgstr ""
+
+#: py/emitnative.c:742
+msgid "conversion to object"
+msgstr ""
+
+#: py/emitnative.c:921
+msgid "local '%q' used before type known"
+msgstr ""
+
+#: py/emitnative.c:1118 py/emitnative.c:1156
+msgid "can't load from '%q'"
+msgstr ""
+
+#: py/emitnative.c:1128
+msgid "can't load with '%q' index"
+msgstr ""
+
+#: py/emitnative.c:1188
+msgid "local '%q' has type '%q' but source is '%q'"
+msgstr ""
+
+#: py/emitnative.c:1289 py/emitnative.c:1379
+msgid "can't store '%q'"
+msgstr ""
+
+#: py/emitnative.c:1358 py/emitnative.c:1419
+msgid "can't store to '%q'"
+msgstr ""
+
+#: py/emitnative.c:1369
+msgid "can't store with '%q' index"
+msgstr ""
+
+#: py/emitnative.c:1540
+msgid "can't implicitly convert '%q' to 'bool'"
+msgstr ""
+
+#: py/emitnative.c:1774
+msgid "unary op %q not implemented"
+msgstr ""
+
+#: py/emitnative.c:1930
+msgid "binary op %q not implemented"
+msgstr ""
+
+#: py/emitnative.c:1951
+msgid "can't do binary op between '%q' and '%q'"
+msgstr ""
+
+#: py/emitnative.c:2126
+msgid "casting"
+msgstr ""
+
+#: py/emitnative.c:2173
+msgid "return expected '%q' but got '%q'"
+msgstr ""
+
+#: py/emitnative.c:2191
+msgid "must raise an object"
+msgstr ""
+
+#: py/emitnative.c:2201
+msgid "native yield"
+msgstr ""
+
+#: py/lexer.c:345
+msgid "unicode name escapes"
+msgstr ""
+
+#: py/modbuiltins.c:162
+msgid "chr() arg not in range(0x110000)"
+msgstr ""
+
+#: py/modbuiltins.c:171
+msgid "chr() arg not in range(256)"
+msgstr ""
+
+#: py/modbuiltins.c:285
+msgid "arg is an empty sequence"
+msgstr ""
+
+#: py/modbuiltins.c:350
+msgid "ord expects a character"
+msgstr ""
+
+#: py/modbuiltins.c:353
+#, c-format
+msgid "ord() expected a character, but string of length %d found"
+msgstr ""
+
+#: py/modbuiltins.c:363
+msgid "3-arg pow() not supported"
+msgstr ""
+
+#: py/modbuiltins.c:517
+msgid "must use keyword argument for key function"
+msgstr ""
+
+#: py/modmath.c:41 shared-bindings/math/__init__.c:53
+msgid "math domain error"
+msgstr ""
+
+#: py/modmath.c:196 py/objfloat.c:270 py/objint_longlong.c:222
+#: py/objint_mpz.c:230 py/runtime.c:619 shared-bindings/math/__init__.c:346
+msgid "division by zero"
+msgstr ""
+
+#: py/modmicropython.c:155
+msgid "schedule stack full"
+msgstr ""
+
+#: py/modstruct.c:145 py/modstruct.c:153 py/modstruct.c:234 py/modstruct.c:244
+#: shared-bindings/struct/__init__.c:103 shared-bindings/struct/__init__.c:145
+#: shared-module/struct/__init__.c:91 shared-module/struct/__init__.c:175
+msgid "buffer too small"
+msgstr ""
+
+#: py/modthread.c:240
+msgid "expecting a dict for keyword args"
+msgstr ""
+
+#: py/moduerrno.c:147 py/moduerrno.c:150
+msgid "Permission denied"
+msgstr ""
+
+#: py/moduerrno.c:148
+msgid "No such file/directory"
+msgstr ""
+
+#: py/moduerrno.c:149
+msgid "Input/output error"
+msgstr ""
+
+#: py/moduerrno.c:151
+msgid "File exists"
+msgstr ""
+
+#: py/moduerrno.c:152
+msgid "Unsupported operation"
+msgstr ""
+
+#: py/moduerrno.c:153
+msgid "Invalid argument"
+msgstr ""
+
+#: py/obj.c:92
+msgid "Traceback (most recent call last):\n"
+msgstr ""
+
+#: py/obj.c:96
+msgid " File \"%q\", line %d"
+msgstr ""
+
+#: py/obj.c:98
+msgid " File \"%q\""
+msgstr ""
+
+#: py/obj.c:102
+msgid ", in %q\n"
+msgstr ""
+
+#: py/obj.c:259
+msgid "can't convert to int"
+msgstr ""
+
+#: py/obj.c:262
+#, c-format
+msgid "can't convert %s to int"
+msgstr ""
+
+#: py/obj.c:322
+msgid "can't convert to float"
+msgstr ""
+
+#: py/obj.c:325
+#, c-format
+msgid "can't convert %s to float"
+msgstr ""
+
+#: py/obj.c:355
+msgid "can't convert to complex"
+msgstr ""
+
+#: py/obj.c:358
+#, c-format
+msgid "can't convert %s to complex"
+msgstr ""
+
+#: py/obj.c:373
+msgid "expected tuple/list"
+msgstr ""
+
+#: py/obj.c:376
+#, c-format
+msgid "object '%s' is not a tuple or list"
+msgstr ""
+
+#: py/obj.c:387
+msgid "tuple/list has wrong length"
+msgstr ""
+
+#: py/obj.c:389
+#, c-format
+msgid "requested length %d but object has length %d"
+msgstr ""
+
+#: py/obj.c:402
+msgid "indices must be integers"
+msgstr ""
+
+#: py/obj.c:405
+msgid "%q indices must be integers, not %s"
+msgstr ""
+
+#: py/obj.c:425
+msgid "%q index out of range"
+msgstr ""
+
+#: py/obj.c:457
+msgid "object has no len"
+msgstr ""
+
+#: py/obj.c:460
+#, c-format
+msgid "object of type '%s' has no len()"
+msgstr ""
+
+#: py/obj.c:500
+msgid "object does not support item deletion"
+msgstr ""
+
+#: py/obj.c:503
+#, c-format
+msgid "'%s' object does not support item deletion"
+msgstr ""
+
+#: py/obj.c:507
+msgid "object is not subscriptable"
+msgstr ""
+
+#: py/obj.c:510
+#, c-format
+msgid "'%s' object is not subscriptable"
+msgstr ""
+
+#: py/obj.c:514
+msgid "object does not support item assignment"
+msgstr ""
+
+#: py/obj.c:517
+#, c-format
+msgid "'%s' object does not support item assignment"
+msgstr ""
+
+#: py/obj.c:548
+msgid "object with buffer protocol required"
+msgstr ""
+
+#: py/objarray.c:413 py/objstr.c:427 py/objstrunicode.c:191 py/objtuple.c:187
+#: shared-bindings/nvm/ByteArray.c:85
+msgid "only slices with step=1 (aka None) are supported"
+msgstr ""
+
+#: py/objarray.c:426
+msgid "lhs and rhs should be compatible"
+msgstr ""
+
+#: py/objarray.c:444 shared-bindings/nvm/ByteArray.c:107
+msgid "array/bytes required on right side"
+msgstr ""
+
+#: py/objcomplex.c:203
+msgid "can't do truncated division of a complex number"
+msgstr ""
+
+#: py/objcomplex.c:209
+msgid "complex division by zero"
+msgstr ""
+
+#: py/objcomplex.c:237
+msgid "0.0 to a complex power"
+msgstr ""
+
+#: py/objdeque.c:107
+msgid "full"
+msgstr ""
+
+#: py/objdeque.c:127
+msgid "empty"
+msgstr ""
+
+#: py/objdict.c:314
+msgid "popitem(): dictionary is empty"
+msgstr ""
+
+#: py/objdict.c:357
+msgid "dict update sequence has wrong length"
+msgstr ""
+
+#: py/objfloat.c:308 py/parsenum.c:331
+msgid "complex values not supported"
+msgstr ""
+
+#: py/objgenerator.c:108
+msgid "can't send non-None value to a just-started generator"
+msgstr ""
+
+#: py/objgenerator.c:126
+msgid "generator already executing"
+msgstr ""
+
+#: py/objgenerator.c:229
+msgid "generator ignored GeneratorExit"
+msgstr ""
+
+#: py/objgenerator.c:251
+msgid "can't pend throw to just-started generator"
+msgstr ""
+
+#: py/objint.c:144
+msgid "can't convert inf to int"
+msgstr ""
+
+#: py/objint.c:146
+msgid "can't convert NaN to int"
+msgstr ""
+
+#: py/objint.c:163
+msgid "float too big"
+msgstr ""
+
+#: py/objint.c:328
+msgid "long int not supported in this build"
+msgstr ""
+
+#: py/objint.c:334 py/objint.c:340 py/objint.c:350 py/objint.c:358
+msgid "small int overflow"
+msgstr ""
+
+#: py/objint_longlong.c:189 py/objint_mpz.c:283 py/runtime.c:486
+msgid "negative power with no float support"
+msgstr ""
+
+#: py/objint_longlong.c:251
+msgid "ulonglong too large"
+msgstr ""
+
+#: py/objint_mpz.c:267 py/runtime.c:396 py/runtime.c:411
+msgid "negative shift count"
+msgstr ""
+
+#: py/objint_mpz.c:336
+msgid "pow() with 3 arguments requires integers"
+msgstr ""
+
+#: py/objint_mpz.c:347
+msgid "pow() 3rd argument cannot be 0"
+msgstr ""
+
+#: py/objint_mpz.c:415
+msgid "overflow converting long int to machine word"
+msgstr ""
+
+#: py/objlist.c:273
+msgid "pop from empty list"
+msgstr ""
+
+#: py/objnamedtuple.c:92
+msgid "can't set attribute"
+msgstr ""
+
+#: py/objobject.c:55
+msgid "__new__ arg must be a user-type"
+msgstr ""
+
+#: py/objrange.c:110
+msgid "zero step"
+msgstr ""
+
+#: py/objset.c:371
+msgid "pop from an empty set"
+msgstr ""
+
+#: py/objslice.c:66
+msgid "Length must be an int"
+msgstr ""
+
+#: py/objslice.c:71
+msgid "Length must be non-negative"
+msgstr ""
+
+#: py/objslice.c:86 py/sequence.c:57
+msgid "slice step cannot be zero"
+msgstr ""
+
+#: py/objslice.c:159
+msgid "Cannot subclass slice"
+msgstr ""
+
+#: py/objstr.c:261
+msgid "bytes value out of range"
+msgstr ""
+
+#: py/objstr.c:270
+msgid "wrong number of arguments"
+msgstr ""
+
+#: py/objstr.c:467
+msgid "join expects a list of str/bytes objects consistent with self object"
+msgstr ""
+
+#: py/objstr.c:542 py/objstr.c:647 py/objstr.c:1744
+msgid "empty separator"
+msgstr ""
+
+#: py/objstr.c:641
+msgid "rsplit(None,n)"
+msgstr ""
+
+#: py/objstr.c:713
+msgid "substring not found"
+msgstr ""
+
+#: py/objstr.c:770
+msgid "start/end indices"
+msgstr ""
+
+#: py/objstr.c:931
+msgid "bad format string"
+msgstr ""
+
+#: py/objstr.c:953
+msgid "single '}' encountered in format string"
+msgstr ""
+
+#: py/objstr.c:992
+msgid "bad conversion specifier"
+msgstr ""
+
+#: py/objstr.c:996
+msgid "end of format while looking for conversion specifier"
+msgstr ""
+
+#: py/objstr.c:998
+#, c-format
+msgid "unknown conversion specifier %c"
+msgstr ""
+
+#: py/objstr.c:1029
+msgid "unmatched '{' in format"
+msgstr ""
+
+#: py/objstr.c:1036
+msgid "expected ':' after format specifier"
+msgstr ""
+
+#: py/objstr.c:1050
+msgid ""
+"can't switch from automatic field numbering to manual field specification"
+msgstr ""
+
+#: py/objstr.c:1055 py/objstr.c:1083
+msgid "tuple index out of range"
+msgstr ""
+
+#: py/objstr.c:1071
+msgid "attributes not supported yet"
+msgstr ""
+
+#: py/objstr.c:1079
+msgid ""
+"can't switch from manual field specification to automatic field numbering"
+msgstr ""
+
+#: py/objstr.c:1171
+msgid "invalid format specifier"
+msgstr ""
+
+#: py/objstr.c:1192
+msgid "sign not allowed in string format specifier"
+msgstr ""
+
+#: py/objstr.c:1200
+msgid "sign not allowed with integer format specifier 'c'"
+msgstr ""
+
+#: py/objstr.c:1259
+#, c-format
+msgid "unknown format code '%c' for object of type '%s'"
+msgstr ""
+
+#: py/objstr.c:1331
+#, c-format
+msgid "unknown format code '%c' for object of type 'float'"
+msgstr ""
+
+#: py/objstr.c:1343
+msgid "'=' alignment not allowed in string format specifier"
+msgstr ""
+
+#: py/objstr.c:1367
+#, c-format
+msgid "unknown format code '%c' for object of type 'str'"
+msgstr ""
+
+#: py/objstr.c:1415
+msgid "format requires a dict"
+msgstr ""
+
+#: py/objstr.c:1424
+msgid "incomplete format key"
+msgstr ""
+
+#: py/objstr.c:1482
+msgid "incomplete format"
+msgstr ""
+
+#: py/objstr.c:1490
+msgid "not enough arguments for format string"
+msgstr ""
+
+#: py/objstr.c:1500
+#, c-format
+msgid "%%c requires int or char"
+msgstr ""
+
+#: py/objstr.c:1507
+msgid "integer required"
+msgstr ""
+
+#: py/objstr.c:1570
+#, c-format
+msgid "unsupported format character '%c' (0x%x) at index %d"
+msgstr ""
+
+#: py/objstr.c:1577
+msgid "not all arguments converted during string formatting"
+msgstr ""
+
+#: py/objstr.c:2102
+msgid "can't convert to str implicitly"
+msgstr ""
+
+#: py/objstr.c:2106
+msgid "can't convert '%q' object to %q implicitly"
+msgstr ""
+
+#: py/objstrunicode.c:134
+#, c-format
+msgid "string indices must be integers, not %s"
+msgstr ""
+
+#: py/objstrunicode.c:145 py/objstrunicode.c:164
+msgid "string index out of range"
+msgstr ""
+
+#: py/objtype.c:358
+msgid "__init__() should return None"
+msgstr ""
+
+#: py/objtype.c:360
+#, c-format
+msgid "__init__() should return None, not '%s'"
+msgstr ""
+
+#: py/objtype.c:623 py/objtype.c:1275 py/runtime.c:1065
+msgid "unreadable attribute"
+msgstr ""
+
+#: py/objtype.c:868 py/runtime.c:653
+msgid "object not callable"
+msgstr ""
+
+#: py/objtype.c:870 py/runtime.c:655
+#, c-format
+msgid "'%s' object is not callable"
+msgstr ""
+
+#: py/objtype.c:978
+msgid "type takes 1 or 3 arguments"
+msgstr ""
+
+#: py/objtype.c:989
+msgid "cannot create instance"
+msgstr ""
+
+#: py/objtype.c:991
+msgid "cannot create '%q' instances"
+msgstr ""
+
+#: py/objtype.c:1047
+msgid "can't add special method to already-subclassed class"
+msgstr ""
+
+#: py/objtype.c:1091 py/objtype.c:1097
+msgid "type is not an acceptable base type"
+msgstr ""
+
+#: py/objtype.c:1100
+msgid "type '%q' is not an acceptable base type"
+msgstr ""
+
+#: py/objtype.c:1137
+msgid "multiple inheritance not supported"
+msgstr ""
+
+#: py/objtype.c:1164
+msgid "multiple bases have instance lay-out conflict"
+msgstr ""
+
+#: py/objtype.c:1205
+msgid "first argument to super() must be type"
+msgstr ""
+
+#: py/objtype.c:1370
+msgid "issubclass() arg 2 must be a class or a tuple of classes"
+msgstr ""
+
+#: py/objtype.c:1384
+msgid "issubclass() arg 1 must be a class"
+msgstr ""
+
+#: py/parse.c:726
+msgid "constant must be an integer"
+msgstr ""
+
+#: py/parse.c:868
+msgid "Unable to init parser"
+msgstr ""
+
+#: py/parse.c:1170
+msgid "unexpected indent"
+msgstr ""
+
+#: py/parse.c:1173
+msgid "unindent does not match any outer indentation level"
+msgstr ""
+
+#: py/parsenum.c:60
+msgid "int() arg 2 must be >= 2 and <= 36"
+msgstr ""
+
+#: py/parsenum.c:151
+msgid "invalid syntax for integer"
+msgstr ""
+
+#: py/parsenum.c:155
+#, c-format
+msgid "invalid syntax for integer with base %d"
+msgstr ""
+
+#: py/parsenum.c:339
+msgid "invalid syntax for number"
+msgstr ""
+
+#: py/parsenum.c:342
+msgid "decimal numbers not supported"
+msgstr ""
+
+#: py/persistentcode.c:223
+msgid ""
+"Incompatible .mpy file. Please update all .mpy files. See http://adafru.it/"
+"mpy-update for more info."
+msgstr ""
+
+#: py/persistentcode.c:326
+msgid "can only save bytecode"
+msgstr ""
+
+#: py/runtime.c:206
+msgid "name not defined"
+msgstr ""
+
+#: py/runtime.c:209
+msgid "name '%q' is not defined"
+msgstr ""
+
+#: py/runtime.c:304 py/runtime.c:611
+msgid "unsupported type for operator"
+msgstr ""
+
+#: py/runtime.c:307
+msgid "unsupported type for %q: '%s'"
+msgstr ""
+
+#: py/runtime.c:614
+msgid "unsupported types for %q: '%s', '%s'"
+msgstr ""
+
+#: py/runtime.c:881 py/runtime.c:888 py/runtime.c:945
+msgid "wrong number of values to unpack"
+msgstr ""
+
+#: py/runtime.c:883 py/runtime.c:947
+#, c-format
+msgid "need more than %d values to unpack"
+msgstr ""
+
+#: py/runtime.c:890
+#, c-format
+msgid "too many values to unpack (expected %d)"
+msgstr ""
+
+#: py/runtime.c:984
+msgid "argument has wrong type"
+msgstr ""
+
+#: py/runtime.c:986
+msgid "argument should be a '%q' not a '%q'"
+msgstr ""
+
+#: py/runtime.c:1123 py/runtime.c:1197
+msgid "no such attribute"
+msgstr ""
+
+#: py/runtime.c:1128
+msgid "type object '%q' has no attribute '%q'"
+msgstr ""
+
+#: py/runtime.c:1132 py/runtime.c:1200
+msgid "'%s' object has no attribute '%q'"
+msgstr ""
+
+#: py/runtime.c:1238
+msgid "object not iterable"
+msgstr ""
+
+#: py/runtime.c:1241
+#, c-format
+msgid "'%s' object is not iterable"
+msgstr ""
+
+#: py/runtime.c:1260 py/runtime.c:1296
+msgid "object not an iterator"
+msgstr ""
+
+#: py/runtime.c:1262 py/runtime.c:1298
+#, c-format
+msgid "'%s' object is not an iterator"
+msgstr ""
+
+#: py/runtime.c:1401
+msgid "exceptions must derive from BaseException"
+msgstr ""
+
+#: py/runtime.c:1430
+msgid "cannot import name %q"
+msgstr ""
+
+#: py/runtime.c:1535
+msgid "memory allocation failed, heap is locked"
+msgstr ""
+
+#: py/runtime.c:1539
+#, c-format
+msgid "memory allocation failed, allocating %u bytes"
+msgstr ""
+
+#: py/runtime.c:1609
+msgid "maximum recursion depth exceeded"
+msgstr ""
+
+#: py/sequence.c:264
+msgid "object not in sequence"
+msgstr ""
+
+#: py/stream.c:96
+msgid "stream operation not supported"
+msgstr ""
+
+#: py/stream.c:254
+msgid "string not supported; use bytes or bytearray"
+msgstr ""
+
+#: py/stream.c:289
+msgid "length argument not allowed for this type"
+msgstr ""
+
+#: py/vm.c:255
+msgid "local variable referenced before assignment"
+msgstr ""
+
+#: py/vm.c:1142
+msgid "no active exception to reraise"
+msgstr ""
+
+#: py/vm.c:1284
+msgid "byte code not implemented"
+msgstr ""
+
+#: shared-bindings/_stage/Layer.c:71
+msgid "graphic must be 2048 bytes long"
+msgstr ""
+
+#: shared-bindings/_stage/Layer.c:77 shared-bindings/_stage/Text.c:75
+msgid "palette must be 32 bytes long"
+msgstr ""
+
+#: shared-bindings/_stage/Layer.c:84
+msgid "map buffer too small"
+msgstr ""
+
+#: shared-bindings/_stage/Text.c:69
+msgid "font must be 2048 bytes long"
+msgstr ""
+
+#: shared-bindings/_stage/Text.c:81
+msgid "chars buffer too small"
+msgstr ""
+
+#: shared-bindings/analogio/AnalogOut.c:118
+msgid "AnalogOut is only 16 bits. Value must be less than 65536."
+msgstr ""
+
+#: shared-bindings/audiobusio/I2SOut.c:225
+#: shared-bindings/audioio/AudioOut.c:226
+msgid "Not playing"
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:124
+msgid "Bit depth must be multiple of 8."
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:128
+msgid "Oversample must be multiple of 8."
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:136
+msgid "Microphone startup delay must be in range 0.0 to 1.0"
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:193
+msgid "destination_length must be an int >= 0"
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:199
+msgid "Cannot record to a file"
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:202
+msgid "Destination capacity is smaller than destination_length."
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:206
+msgid "destination buffer must be an array of type 'H' for bit_depth = 16"
+msgstr ""
+
+#: shared-bindings/audiobusio/PDMIn.c:208
+msgid ""
+"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:94
+msgid "Invalid voice count"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:99
+msgid "Invalid channel count"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:103
+msgid "Sample rate must be positive"
+msgstr ""
+
+#: shared-bindings/audioio/Mixer.c:107
+msgid "bits_per_sample must be 8 or 16"
+msgstr ""
+
+#: shared-bindings/audioio/RawSample.c:98
+msgid ""
+"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
+"'B'"
+msgstr ""
+
+#: shared-bindings/audioio/RawSample.c:104
+msgid "buffer must be a bytes-like object"
+msgstr ""
+
+#: shared-bindings/audioio/WaveFile.c:78
+#: shared-bindings/displayio/OnDiskBitmap.c:85
+msgid "file must be a file opened in byte mode"
+msgstr ""
+
+#: shared-bindings/bitbangio/I2C.c:111 shared-bindings/bitbangio/SPI.c:121
+#: shared-bindings/busio/SPI.c:133
+msgid "Function requires lock"
+msgstr ""
+
+#: shared-bindings/bitbangio/I2C.c:195 shared-bindings/busio/I2C.c:210
+msgid "Buffer must be at least length 1"
+msgstr ""
+
+#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175
+msgid "Invalid polarity"
+msgstr ""
+
+#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179
+msgid "Invalid phase"
+msgstr ""
+
+#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183
+msgid "Invalid number of bits"
+msgstr ""
+
+#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348
+msgid "buffer slices must be of equal length"
+msgstr ""
+
+#: shared-bindings/bleio/Address.c:101
+msgid "Wrong address length"
+msgstr ""
+
+#: shared-bindings/bleio/Address.c:107
+msgid "Wrong number of bytes provided"
+msgstr ""
+
+#: shared-bindings/bleio/Device.c:210
+msgid "Can't add services in Central mode"
+msgstr ""
+
+#: shared-bindings/bleio/Device.c:226
+msgid "Can't connect in Peripheral mode"
+msgstr ""
+
+#: shared-bindings/bleio/Device.c:256
+msgid "Can't change the name in Central mode"
+msgstr ""
+
+#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313
+msgid "Can't advertise in Central mode"
+msgstr ""
+
+#: shared-bindings/busio/I2C.c:120
+msgid "Function requires lock."
+msgstr ""
+
+#: shared-bindings/busio/UART.c:106
+msgid "bits must be 7, 8 or 9"
+msgstr ""
+
+#: shared-bindings/busio/UART.c:118
+msgid "stop must be 1 or 2"
+msgstr ""
+
+#: shared-bindings/busio/UART.c:123
+msgid "timeout >100 (units are now seconds, not msecs)"
+msgstr ""
+
+#: shared-bindings/digitalio/DigitalInOut.c:211
+msgid "Invalid direction."
+msgstr ""
+
+#: shared-bindings/digitalio/DigitalInOut.c:240
+msgid "Cannot set value when direction is input."
+msgstr ""
+
+#: shared-bindings/digitalio/DigitalInOut.c:266
+#: shared-bindings/digitalio/DigitalInOut.c:281
+msgid "Drive mode not used when direction is input."
+msgstr ""
+
+#: shared-bindings/digitalio/DigitalInOut.c:314
+#: shared-bindings/digitalio/DigitalInOut.c:331
+msgid "Pull not used when direction is output."
+msgstr ""
+
+#: shared-bindings/digitalio/DigitalInOut.c:340
+msgid "Unsupported pull value."
+msgstr ""
+
+#: shared-bindings/displayio/Bitmap.c:84
+msgid "y should be an int"
+msgstr ""
+
+#: shared-bindings/displayio/Bitmap.c:89
+msgid "row buffer must be a bytearray or array of type 'b' or 'B'"
+msgstr ""
+
+#: shared-bindings/displayio/Bitmap.c:94
+msgid "row data must be a buffer"
+msgstr ""
+
+#: shared-bindings/displayio/ColorConverter.c:72
+msgid "color should be an int"
+msgstr ""
+
+#: shared-bindings/displayio/FourWire.c:55
+#: shared-bindings/displayio/FourWire.c:64
+msgid "displayio is a work in progress"
+msgstr ""
+
+#: shared-bindings/displayio/Group.c:65
+msgid "Group must have size at least 1"
+msgstr ""
+
+#: shared-bindings/displayio/Palette.c:96
+msgid "color buffer must be a bytearray or array of type 'b' or 'B'"
+msgstr ""
+
+#: shared-bindings/displayio/Palette.c:102
+msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)"
+msgstr ""
+
+#: shared-bindings/displayio/Palette.c:106
+msgid "color must be between 0x000000 and 0xffffff"
+msgstr ""
+
+#: shared-bindings/displayio/Palette.c:110
+msgid "color buffer must be a buffer or int"
+msgstr ""
+
+#: shared-bindings/displayio/Palette.c:123
+#: shared-bindings/displayio/Palette.c:137
+msgid "palette_index should be an int"
+msgstr ""
+
+#: shared-bindings/displayio/Sprite.c:48
+msgid "position must be 2-tuple"
+msgstr ""
+
+#: shared-bindings/displayio/Sprite.c:97
+msgid "unsupported bitmap type"
+msgstr ""
+
+#: shared-bindings/displayio/Sprite.c:162
+msgid "pixel_shader must be displayio.Palette or displayio.ColorConverter"
+msgstr ""
+
+#: shared-bindings/gamepad/GamePad.c:100
+msgid "too many arguments"
+msgstr ""
+
+#: shared-bindings/gamepad/GamePad.c:104
+msgid "expected a DigitalInOut"
+msgstr ""
+
+#: shared-bindings/i2cslave/I2CSlave.c:98
+msgid "can't convert address to int"
+msgstr ""
+
+#: shared-bindings/i2cslave/I2CSlave.c:101
+msgid "address out of bounds"
+msgstr ""
+
+#: shared-bindings/i2cslave/I2CSlave.c:107
+msgid "addresses is empty"
+msgstr ""
+
+#: shared-bindings/microcontroller/Pin.c:89
+#: shared-bindings/neopixel_write/__init__.c:67
+#: shared-bindings/pulseio/PulseOut.c:76
+msgid "Expected a %q"
+msgstr ""
+
+#: shared-bindings/microcontroller/Pin.c:100
+msgid "%q in use"
+msgstr ""
+
+#: shared-bindings/microcontroller/__init__.c:126
+msgid "Invalid run mode."
+msgstr ""
+
+#: shared-bindings/multiterminal/__init__.c:68
+msgid "Stream missing readinto() or write() method."
+msgstr ""
+
+#: shared-bindings/nvm/ByteArray.c:99
+msgid "Slice and value different lengths."
+msgstr ""
+
+#: shared-bindings/nvm/ByteArray.c:104
+msgid "Array values should be single bytes."
+msgstr ""
+
+#: shared-bindings/nvm/ByteArray.c:111 shared-bindings/nvm/ByteArray.c:141
+msgid "Unable to write to nvm."
+msgstr ""
+
+#: shared-bindings/nvm/ByteArray.c:137
+msgid "Bytes must be between 0 and 255."
+msgstr ""
+
+#: shared-bindings/os/__init__.c:200
+msgid "No hardware random available"
+msgstr ""
+
+#: shared-bindings/pulseio/PWMOut.c:164
+msgid ""
+"PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)"
+msgstr ""
+
+#: shared-bindings/pulseio/PWMOut.c:195
+msgid ""
+"PWM frequency not writable when variable_frequency is False on construction."
+msgstr ""
+
+#: shared-bindings/pulseio/PulseIn.c:275
+msgid "Cannot delete values"
+msgstr ""
+
+#: shared-bindings/pulseio/PulseIn.c:281
+msgid "Slices not supported"
+msgstr ""
+
+#: shared-bindings/pulseio/PulseIn.c:287
+msgid "index must be int"
+msgstr ""
+
+#: shared-bindings/pulseio/PulseIn.c:293
+msgid "Read-only"
+msgstr ""
+
+#: shared-bindings/pulseio/PulseOut.c:135
+msgid "Array must contain halfwords (type 'H')"
+msgstr ""
+
+#: shared-bindings/random/__init__.c:92 shared-bindings/random/__init__.c:100
+msgid "stop not reachable from start"
+msgstr ""
+
+#: shared-bindings/random/__init__.c:111
+msgid "step must be non-zero"
+msgstr ""
+
+#: shared-bindings/random/__init__.c:114
+msgid "invalid step"
+msgstr ""
+
+#: shared-bindings/random/__init__.c:146
+msgid "empty sequence"
+msgstr ""
+
+#: shared-bindings/rtc/RTC.c:40 shared-bindings/rtc/RTC.c:44
+#: shared-bindings/time/__init__.c:190
+msgid "RTC is not supported on this board"
+msgstr ""
+
+#: shared-bindings/rtc/RTC.c:52
+msgid "RTC calibration is not supported on this board"
+msgstr ""
+
+#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81
+msgid "no available NIC"
+msgstr ""
+
+#: shared-bindings/storage/__init__.c:77
+msgid "filesystem must provide mount method"
+msgstr ""
+
+#: shared-bindings/supervisor/__init__.c:93
+msgid "Brightness must be between 0 and 255"
+msgstr ""
+
+#: shared-bindings/supervisor/__init__.c:119
+msgid "Stack size must be at least 256"
+msgstr ""
+
+#: shared-bindings/time/__init__.c:78
+msgid "sleep length must be non-negative"
+msgstr ""
+
+#: shared-bindings/time/__init__.c:88
+msgid "time.struct_time() takes exactly 1 argument"
+msgstr ""
+
+#: shared-bindings/time/__init__.c:91
+msgid "time.struct_time() takes a 9-sequence"
+msgstr ""
+
+#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:263
+msgid "Tuple or struct_time argument required"
+msgstr ""
+
+#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:268
+msgid "function takes exactly 9 arguments"
+msgstr ""
+
+#: shared-bindings/time/__init__.c:239 shared-bindings/time/__init__.c:272
+msgid "timestamp out of range for platform time_t"
+msgstr ""
+
+#: shared-bindings/touchio/TouchIn.c:173
+msgid "threshold must be in the range 0-65536"
+msgstr ""
+
+#: shared-bindings/util.c:38
+msgid ""
+"Object has been deinitialized and can no longer be used. Create a new object."
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117
+msgid "Couldn't allocate first buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123
+msgid "Couldn't allocate second buffer"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:82
+msgid "Voice index too high"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:85
+msgid "The sample's sample rate does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:88
+msgid "The sample's channel count does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:91
+msgid "The sample's bits_per_sample does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/Mixer.c:100
+msgid "The sample's signedness does not match the mixer's"
+msgstr ""
+
+#: shared-module/audioio/WaveFile.c:61
+msgid "Invalid wave file"
+msgstr ""
+
+#: shared-module/audioio/WaveFile.c:69
+msgid "Invalid format chunk size"
+msgstr ""
+
+#: shared-module/audioio/WaveFile.c:83
+msgid "Unsupported format"
+msgstr ""
+
+#: shared-module/audioio/WaveFile.c:99
+msgid "Data chunk must follow fmt chunk"
+msgstr ""
+
+#: shared-module/audioio/WaveFile.c:107
+msgid "Invalid file"
+msgstr ""
+
+#: shared-module/bitbangio/I2C.c:58
+msgid "Clock stretch too long"
+msgstr ""
+
+#: shared-module/bitbangio/SPI.c:44
+msgid "Clock pin init failed."
+msgstr ""
+
+#: shared-module/bitbangio/SPI.c:50
+msgid "MOSI pin init failed."
+msgstr ""
+
+#: shared-module/bitbangio/SPI.c:61
+msgid "MISO pin init failed."
+msgstr ""
+
+#: shared-module/bitbangio/SPI.c:121
+msgid "Cannot write without MOSI pin."
+msgstr ""
+
+#: shared-module/bitbangio/SPI.c:176
+msgid "Cannot read without MISO pin."
+msgstr ""
+
+#: shared-module/bitbangio/SPI.c:240
+msgid "Cannot transfer without MOSI and MISO pins."
+msgstr ""
+
+#: shared-module/displayio/Bitmap.c:49
+msgid "Only bit maps of 8 bit color or less are supported"
+msgstr ""
+
+#: shared-module/displayio/Bitmap.c:69
+msgid "row must be packed and word aligned"
+msgstr ""
+
+#: shared-module/displayio/Group.c:39
+msgid "Group full"
+msgstr ""
+
+#: shared-module/displayio/Group.c:48
+msgid "Group empty"
+msgstr ""
+
+#: shared-module/displayio/OnDiskBitmap.c:49
+msgid "Invalid BMP file"
+msgstr ""
+
+#: shared-module/displayio/OnDiskBitmap.c:59
+#, c-format
+msgid "Only Windows format, uncompressed BMP supported %d"
+msgstr ""
+
+#: shared-module/displayio/OnDiskBitmap.c:64
+#, c-format
+msgid "Only true color (24 bpp or higher) BMP supported %x"
+msgstr ""
+
+#: shared-module/storage/__init__.c:155
+msgid "Cannot remount '/' when USB is active."
+msgstr ""
+
+#: shared-module/struct/__init__.c:39
+msgid "'S' and 'O' are not supported format types"
+msgstr ""
+
+#: shared-module/struct/__init__.c:83
+msgid "too many arguments provided with the given format"
+msgstr ""
+
+#: shared-module/usb_hid/Device.c:45
+#, c-format
+msgid "Buffer incorrect size. Should be %d bytes."
+msgstr ""
+
+#: shared-module/usb_hid/Device.c:53
+msgid "USB Busy"
+msgstr ""
+
+#: shared-module/usb_hid/Device.c:59
+msgid "USB Error"
+msgstr ""
+
+#: supervisor/shared/safe_mode.c:97
+msgid "You requested starting safe mode by "
+msgstr "Anda mengajukan untuk memulai mode aman pada (safe mode) pada "
+
+#: supervisor/shared/safe_mode.c:100
+msgid "To exit, please reset the board without "
+msgstr "Untuk keluar, silahkan reset board tanpa "
+
+#: supervisor/shared/safe_mode.c:107
+#, fuzzy
+msgid ""
+"You are running in safe mode which means something unanticipated happened.\n"
+msgstr ""
+"Anda sedang menjalankan mode aman (safe mode) yang berarti sesuatu yang "
+"sangat buruk telah terjadi.\n"
+
+#: supervisor/shared/safe_mode.c:109
+msgid ""
+"Looks like our core CircuitPython code crashed hard. Whoops!\n"
+"Please file an issue at https://github.com/adafruit/circuitpython/issues\n"
+" with the contents of your CIRCUITPY drive and this message:\n"
+msgstr ""
+
+#: supervisor/shared/safe_mode.c:111
+msgid "Crash into the HardFault_Handler.\n"
+msgstr ""
+
+#: supervisor/shared/safe_mode.c:113
+msgid "MicroPython NLR jump failed. Likely memory corruption.\n"
+msgstr ""
+
+#: supervisor/shared/safe_mode.c:115
+msgid "MicroPython fatal error.\n"
+msgstr ""
+
+#: supervisor/shared/safe_mode.c:118
+#, fuzzy
+msgid ""
+"The microcontroller's power dipped. Please make sure your power supply "
+"provides\n"
+"enough power for the whole circuit and press reset (after ejecting "
+"CIRCUITPY).\n"
+msgstr ""
+"Tegangan dari mikrokontroler turun atau mati. Pastikan sumber tegangan "
+"memberikan daya\n"
+
+#: supervisor/shared/safe_mode.c:120
+msgid ""
+"The CircuitPython heap was corrupted because the stack was too small.\n"
+"Please increase stack size limits and press reset (after ejecting "
+"CIRCUITPY).\n"
+"If you didn't change the stack, then file an issue here with the contents of "
+"your CIRCUITPY drive:\n"
+msgstr ""
+
+#: supervisor/shared/safe_mode.c:123
+msgid ""
+"The reset button was pressed while booting CircuitPython. Press again to "
+"exit safe mode.\n"
+msgstr ""
+
+#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
+#~ msgstr ""
+#~ "Sepertinya inti kode CircuitPython kita crash dengan sangat keras. Ups!\n"
+
+#~ msgid ""
+#~ "enough power for the whole circuit and press reset (after ejecting "
+#~ "CIRCUITPY).\n"
+#~ msgstr ""
+#~ "tegangan cukup untuk semua sirkuit dan tekan reset (setelah mencabut "
+#~ "CIRCUITPY).\n"
+
+#~ msgid ""
+#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
+#~ msgstr ""
+#~ "Silahkan taruh masalah disini dengan isi dari CIRCUITPY drive: anda \n"
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 691d83762..88471e090 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -2694,12 +2694,23 @@ msgstr ""
#~ msgid "Can not apply advertisement data. status: 0x%02x"
#~ msgstr "Kann advertisement data nicht anwenden. Status: 0x%02x"
+#~ msgid ""
+#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
+#~ msgstr ""
+#~ "Bitte erstelle ein issue hier mit dem Inhalt deines CIRCUITPY-speichers:\n"
+
+#~ msgid "Can not encode UUID, to check length."
+#~ msgstr "Kann UUID nicht kodieren, um die Länge zu überprüfen."
+
+#~ msgid "Can not add Characteristic."
+#~ msgstr "Kann das Merkmal nicht hinzufügen."
+
+#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
+#~ msgstr "CircuitPython ist abgestürzt. Ups!\n"
+
#~ msgid "Cannot apply GAP parameters."
#~ msgstr "Kann GAP Parameter nicht anwenden."
-#~ msgid "Can not apply device name in the stack."
-#~ msgstr "Der Gerätename kann nicht im Stack verwendet werden."
-
#~ msgid ""
#~ "enough power for the whole circuit and press reset (after ejecting "
#~ "CIRCUITPY).\n"
@@ -2707,22 +2718,14 @@ msgstr ""
#~ "genug Strom für den ganzen Schaltkreis liefert und drücke reset (nach dem "
#~ "sicheren Auswerfen von CIRCUITPY.)\n"
-#~ msgid "Can not query for the device address."
-#~ msgstr "Kann nicht nach der Geräteadresse suchen."
-
-#~ msgid "Can not encode UUID, to check length."
-#~ msgstr "Kann UUID nicht kodieren, um die Länge zu überprüfen."
-
#~ msgid "Can encode UUID into the advertisement packet."
#~ msgstr "Kann UUID in das advertisement packet kodieren."
+#~ msgid "Can not query for the device address."
+#~ msgstr "Kann nicht nach der Geräteadresse suchen."
+
#~ msgid "Can not add Service."
#~ msgstr "Kann den Dienst nicht hinzufügen."
-#~ msgid ""
-#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
-#~ msgstr ""
-#~ "Bitte erstelle ein issue hier mit dem Inhalt deines CIRCUITPY-speichers:\n"
-
-#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
-#~ msgstr "CircuitPython ist abgestürzt. Ups!\n"
+#~ msgid "Can not apply device name in the stack."
+#~ msgstr "Der Gerätename kann nicht im Stack verwendet werden."
diff --git a/locale/es.po b/locale/es.po
index f9debc7f4..be9f47c9d 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -2710,15 +2710,33 @@ msgstr ""
#~ msgid "Wrong number of bytes provided"
#~ msgstr "Numero erroneo de bytes dados"
+
#~ msgid "Cannot apply GAP parameters."
#~ msgstr "No se pueden aplicar los parámetros GAP."
#~ msgid "Can not apply device name in the stack."
#~ msgstr "No se puede aplicar el nombre del dispositivo en el stack."
+#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
+#~ msgstr ""
+#~ "Parece que nuestro código CircuitPython dejó de funcionar. Whoops!\n"
+
+#~ msgid "Baud rate too high for this SPI peripheral"
+#~ msgstr "Baud rate demasiado alto para este periférico SPI"
+
#~ msgid "Can not encode UUID, to check length."
#~ msgstr "No se puede codificar el UUID, para revisar la longitud."
+#~ msgid "Can not query for the device address."
+#~ msgstr "No se puede consultar la dirección del dispositivo."
+
+#, fuzzy
+#~ msgid ""
+#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
+#~ msgstr ""
+#~ "Por favor registra un issue en la siguiente URL con el contenidos de tu "
+#~ "unidad de almacenamiento CIRCUITPY:\n"
+
#~ msgid "Can encode UUID into the advertisement packet."
#~ msgstr "Se puede codificar el UUID en el paquete de anuncio."
@@ -2728,12 +2746,6 @@ msgstr ""
#~ msgid "Can not add Service."
#~ msgstr "No se puede agregar el Servicio."
-#~ msgid "Can not query for the device address."
-#~ msgstr "No se puede consultar la dirección del dispositivo."
-
-#~ msgid "Baud rate too high for this SPI peripheral"
-#~ msgstr "Baud rate demasiado alto para este periférico SPI"
-
#~ msgid "Can not apply advertisement data. status: 0x%02x"
#~ msgstr "No se puede aplicar los datos de anuncio. status: 0x%02x"
@@ -2746,14 +2758,3 @@ msgstr ""
#~ msgstr ""
#~ "suficiente poder para todo el circuito y presiona reset (después de "
#~ "expulsar CIRCUITPY).\n"
-
-#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
-#~ msgstr ""
-#~ "Parece que nuestro código CircuitPython dejó de funcionar. Whoops!\n"
-
-#, fuzzy
-#~ msgid ""
-#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
-#~ msgstr ""
-#~ "Por favor registra un issue en la siguiente URL con el contenidos de tu "
-#~ "unidad de almacenamiento CIRCUITPY:\n"
diff --git a/locale/fil.po b/locale/fil.po
index ffcdef1dc..a25f6dfb0 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -2727,15 +2727,33 @@ msgstr ""
#~ msgid "Wrong number of bytes provided"
#~ msgstr "Mali ang bilang ng bytes"
+
#~ msgid "Cannot apply GAP parameters."
#~ msgstr "Hindi ma-apply ang GAP parameters."
#~ msgid "Can not apply device name in the stack."
#~ msgstr "Hindi maaaring ma-aplay ang device name sa stack."
+#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
+#~ msgstr ""
+#~ "Mukhang ang core CircuitPython code ay nag-crash ng malakas. Aray!\n"
+
+#, fuzzy
+#~ msgid "palette must be displayio.Palette"
+#~ msgstr "ang palette ay dapat 32 bytes ang haba"
+
#~ msgid "Can not encode UUID, to check length."
#~ msgstr "Hindi ma-encode UUID, para suriin ang haba."
+#~ msgid "Can not query for the device address."
+#~ msgstr "Hindi maaaring mag-query para sa address ng device."
+
+#~ msgid ""
+#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
+#~ msgstr ""
+#~ "Mag-file ng isang isyu dito gamit ang mga nilalaman ng iyong CIRCUITPY "
+#~ "drive:\n"
+
#~ msgid "Can encode UUID into the advertisement packet."
#~ msgstr "Maaring i-encode ang UUID sa advertisement packet."
@@ -2745,13 +2763,6 @@ msgstr ""
#~ msgid "Can not add Service."
#~ msgstr "Hindi maidaragdag ang serbisyo."
-#~ msgid "Can not query for the device address."
-#~ msgstr "Hindi maaaring mag-query para sa address ng device."
-
-#, fuzzy
-#~ msgid "palette must be displayio.Palette"
-#~ msgstr "ang palette ay dapat 32 bytes ang haba"
-
#~ msgid "Can not apply advertisement data. status: 0x%02x"
#~ msgstr "Hindi ma i-apply ang advertisement data. status: 0x%02x"
@@ -2764,13 +2775,3 @@ msgstr ""
#~ msgstr ""
#~ "ay nagbibigay ng sapat na power para sa buong circuit at i-press ang "
#~ "reset (pagkatapos i-eject ang CIRCUITPY).\n"
-
-#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
-#~ msgstr ""
-#~ "Mukhang ang core CircuitPython code ay nag-crash ng malakas. Aray!\n"
-
-#~ msgid ""
-#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
-#~ msgstr ""
-#~ "Mag-file ng isang isyu dito gamit ang mga nilalaman ng iyong CIRCUITPY "
-#~ "drive:\n"
diff --git a/locale/fr.po b/locale/fr.po
index 4cca9d8d4..af90c6f6f 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -2766,17 +2766,12 @@ msgstr ""
#~ msgstr ""
#~ "SVP, remontez le problème là avec le contenu du lecteur CIRCUITPY:\n"
-#~ msgid "Can not add Service."
-#~ msgstr "Impossible d'ajouter le Service"
-
-#~ msgid "Invalid Service type"
-#~ msgstr "Type de service invalide"
-
-#~ msgid "Can not encode UUID, to check length."
-#~ msgstr "Impossible d'encoder l'UUID pour vérifier la longueur."
+#, fuzzy
+#~ msgid "value_size must be power of two"
+#~ msgstr "value_size doit être une puissance de 2"
-#~ msgid "Can not query for the device address."
-#~ msgstr "Impossible d'obtenir l'adresse du périphérique"
+#~ msgid "Cannot set PPCP parameters."
+#~ msgstr "Impossible d'appliquer les paramètres PPCP"
#~ msgid ""
#~ "enough power for the whole circuit and press reset (after ejecting "
@@ -2785,19 +2780,27 @@ msgstr ""
#~ "assez de puissance pour l'ensemble du circuit et appuyez sur "
#~ "'reset' (après avoir éjecter CIRCUITPY).\n"
-#~ msgid "Cannot set PPCP parameters."
-#~ msgstr "Impossible d'appliquer les paramètres PPCP"
+#, fuzzy
+#~ msgid "palette must be displayio.Palette"
+#~ msgstr "la palette doit être une displayio.Palette"
+
+#~ msgid "Can not encode UUID, to check length."
+#~ msgstr "Impossible d'encoder l'UUID pour vérifier la longueur."
+
+#~ msgid "Can not add Service."
+#~ msgstr "Impossible d'ajouter le Service"
+
+#~ msgid "Can not add Characteristic."
+#~ msgstr "Impossible d'ajouter la Characteristic."
#~ msgid "Can not apply device name in the stack."
#~ msgstr "Impossible d'appliquer le nom de périphérique dans la pile"
+#~ msgid "Can not query for the device address."
+#~ msgstr "Impossible d'obtenir l'adresse du périphérique"
+
#~ msgid "Cannot apply GAP parameters."
#~ msgstr "Impossible d'appliquer les paramètres GAP"
-#, fuzzy
-#~ msgid "value_size must be power of two"
-#~ msgstr "value_size doit être une puissance de 2"
-
-#, fuzzy
-#~ msgid "palette must be displayio.Palette"
-#~ msgstr "la palette doit être une displayio.Palette"
+#~ msgid "Invalid Service type"
+#~ msgstr "Type de service invalide"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index d08d2d356..cbb497e57 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -2729,15 +2729,29 @@ msgstr ""
#~ msgid "Can not apply advertisement data. status: 0x%02x"
#~ msgstr "Impossible inserire dati advertisement. status: 0x%02x"
-#~ msgid "Cannot apply GAP parameters."
-#~ msgstr "Impossibile applicare i parametri GAP."
+#~ msgid ""
+#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
+#~ msgstr ""
+#~ "Ti preghiamo di compilare una issue con il contenuto del tuo drie "
+#~ "CIRCUITPY:\n"
-#~ msgid "Can not apply device name in the stack."
-#~ msgstr "Non è possibile inserire il nome del dipositivo nella lista."
+#~ msgid "Can not encode UUID, to check length."
+#~ msgstr "Non è possibile codificare l'UUID, lunghezza da controllare."
+
+#~ msgid "Can not add Characteristic."
+#~ msgstr "Non è possibile aggiungere Characteristic."
+
+#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
+#~ msgstr ""
+#~ "Sembra che il codice del core di CircuitPython sia crashato malamente. "
+#~ "Whoops!\n"
#~ msgid "Cannot set PPCP parameters."
#~ msgstr "Impossibile impostare i parametri PPCP."
+#~ msgid "Cannot apply GAP parameters."
+#~ msgstr "Impossibile applicare i parametri GAP."
+
#~ msgid ""
#~ "enough power for the whole circuit and press reset (after ejecting "
#~ "CIRCUITPY).\n"
@@ -2745,25 +2759,14 @@ msgstr ""
#~ "abbastanza potenza per l'intero circuito e premere reset (dopo aver "
#~ "espulso CIRCUITPY).\n"
-#~ msgid "Can not query for the device address."
-#~ msgstr "Non è possibile trovare l'indirizzo del dispositivo."
-
-#~ msgid "Can not encode UUID, to check length."
-#~ msgstr "Non è possibile codificare l'UUID, lunghezza da controllare."
-
#~ msgid "Can encode UUID into the advertisement packet."
#~ msgstr "È possibile codificare l'UUID nel pacchetto di advertisement."
+#~ msgid "Can not query for the device address."
+#~ msgstr "Non è possibile trovare l'indirizzo del dispositivo."
+
#~ msgid "Can not add Service."
#~ msgstr "Non è possibile aggiungere Service."
-#~ msgid ""
-#~ "Please file an issue here with the contents of your CIRCUITPY drive:\n"
-#~ msgstr ""
-#~ "Ti preghiamo di compilare una issue con il contenuto del tuo drie "
-#~ "CIRCUITPY:\n"
-
-#~ msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n"
-#~ msgstr ""
-#~ "Sembra che il codice del core di CircuitPython sia crashato malamente. "
-#~ "Whoops!\n"
+#~ msgid "Can not apply device name in the stack."
+#~ msgstr "Non è possibile inserire il nome del dipositivo nella lista."
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 955a8e198..974bdb41b 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -2670,17 +2670,23 @@ msgstr ""
#~ msgid "Invalid UUID parameter"
#~ msgstr "Parâmetro UUID inválido"
+#~ msgid "Can not apply advertisement data. status: 0x%02x"
+#~ msgstr "Não é possível aplicar dados de anúncio. status: 0x%02x"
+
#~ msgid "Can not apply device name in the stack."
#~ msgstr "Não é possível aplicar o nome do dispositivo na pilha."
-#~ msgid "Can encode UUID into the advertisement packet."
-#~ msgstr "Pode codificar o UUID no pacote de anúncios."
+#~ msgid "Baud rate too high for this SPI peripheral"
+#~ msgstr "Taxa de transmissão muito alta para esse periférico SPI"
+
+#~ msgid "Cannot apply GAP parameters."
+#~ msgstr "Não é possível aplicar parâmetros GAP."
#~ msgid "Invalid Service type"
#~ msgstr "Tipo de serviço inválido"
-#~ msgid "Cannot apply GAP parameters."
-#~ msgstr "Não é possível aplicar parâmetros GAP."
+#~ msgid "Can encode UUID into the advertisement packet."
+#~ msgstr "Pode codificar o UUID no pacote de anúncios."
#~ msgid "Cannot set PPCP parameters."
#~ msgstr "Não é possível definir parâmetros PPCP."
@@ -2688,11 +2694,8 @@ msgstr ""
#~ msgid "Can not query for the device address."
#~ msgstr "Não é possível consultar o endereço do dispositivo."
-#~ msgid "Baud rate too high for this SPI peripheral"
-#~ msgstr "Taxa de transmissão muito alta para esse periférico SPI"
-
-#~ msgid "Can not apply advertisement data. status: 0x%02x"
-#~ msgstr "Não é possível aplicar dados de anúncio. status: 0x%02x"
+#~ msgid "Can not add Characteristic."
+#~ msgstr "Não é possível adicionar Característica."
-#~ msgid "Can not add Service."
-#~ msgstr "Não é possível adicionar o serviço."
+#~ msgid "Cannot set PPCP parameters."
+#~ msgstr "Não é possível definir parâmetros PPCP."
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 91795ab01..852de75f3 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -90,13 +90,13 @@ BASE_CFLAGS = \
ifeq ($(CHIP_FAMILY), samd21)
CFLAGS += -Os -DNDEBUG
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512
endif
ifeq ($(CHIP_FAMILY), samd51)
CFLAGS += -Os -DNDEBUG
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
endif
#Debugging/Optimization
@@ -104,9 +104,9 @@ ifeq ($(DEBUG), 1)
# Turn on Python modules useful for debugging (e.g. uheap, ustack).
CFLAGS += -ggdb
# You may want to disable -flto if it interferes with debugging.
- CFLAGS += -flto
+ # CFLAGS += -flto
# You may want to enable these flags to make setting breakpoints easier.
- # CFLAGS += -fno-inline -fno-ipa-sra
+ CFLAGS += -fno-inline -fno-ipa-sra
ifeq ($(CHIP_FAMILY), samd21)
CFLAGS += -DENABLE_MICRO_TRACE_BUFFER
endif
@@ -267,7 +267,6 @@ SRC_C = \
lib/oofatfs/option/ccsbcs.c \
lib/timeutils/timeutils.c \
lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c \
- lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/hal_$(CHIP_FAMILY).c \
lib/utils/buffer_helper.c \
lib/utils/context_manager_helpers.c \
lib/utils/interrupt_char.c \
diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst
index 6037c7d3b..b0b3bb40e 100644
--- a/ports/atmel-samd/README.rst
+++ b/ports/atmel-samd/README.rst
@@ -22,51 +22,51 @@ different names. The table below matches the pin order in
and omits the pins only available on the largest package because all supported
boards use smaller version.
-===================== =================== =============== =========================== ====================== ================ ================== ========================= ================ ================
+===================== =================== =============== =========================== ====================== ================ ================== ========================= ================ ================================ ================
`microcontroller.pin` `board`
---------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-Datasheet arduino_mkrzero arduino_zero circuitplayground_express feather_m0_adalogger feather_m0_basic feather_m0_express gemma_m0 metro_m0_express trinket_m0
-===================== =================== =============== =========================== ====================== ================ ================== ========================= ================ ================
-PA00 ``ACCELEROMETER_SDA`` ``APA102_MOSI`` ``APA102_MOSI``
-PA01 ``ACCELEROMETER_SCL`` ``APA102_SCK`` ``APA102_SCK``
-PA02 ``A0`` ``A0`` ``A0`` / ``SPEAKER`` ``A0`` ``A0`` ``A0`` ``A0`` / ``D1`` ``A0`` ``D1`` / ``A0``
+--------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+Datasheet arduino_mkrzero arduino_zero circuitplayground_express feather_m0_adalogger feather_m0_basic feather_m0_express gemma_m0 metro_m0_express sparkfun_samd21_mini trinket_m0
+===================== =================== =============== =========================== ====================== ================ ================== ========================= ================ ================================ ================
+PA00 ``ACCELEROMETER_SDA`` ``APA102_MOSI`` ``APA102_MOSI``
+PA01 ``ACCELEROMETER_SCL`` ``APA102_SCK`` ``APA102_SCK``
+PA02 ``A0`` ``A0`` ``A0`` / ``SPEAKER`` ``A0`` ``A0`` ``A0`` ``A0`` / ``D1`` ``A0`` ``A0`` ``D1`` / ``A0``
PA03
-PB08 ``L`` ``A1`` ``A7`` / ``TX`` ``A1`` ``A1`` ``A1`` ``A1``
-PB09 ``BATTERY`` ``A2`` ``A6`` / ``RX`` ``A2`` ``A2`` ``A2`` ``A2``
-PA04 ``A3`` ``A3`` ``IR_PROXIMITY`` ``A3`` ``A3`` ``A3`` ``D0`` / ``TX`` / ``SDA`` ``A3``
+PB08 ``L`` ``A1`` ``A7`` / ``TX`` ``A1`` ``A1`` ``A1`` ``A1`` ``A1``
+PB09 ``BATTERY`` ``A2`` ``A6`` / ``RX`` ``A2`` ``A2`` ``A2`` ``A2`` ``A2``
+PA04 ``A3`` ``A3`` ``IR_PROXIMITY`` ``A3`` ``A3`` ``A3`` ``D0`` / ``TX`` / ``SDA`` ``A3`` ``A3``
PA05 ``A4`` ``A4`` ``A1`` ``A4`` ``A4`` ``A4`` ``D2`` / ``RX`` / ``SCL`` ``A4``
-PA06 ``A5`` ``D8`` ``A2`` ``D8`` / ``GREEN_LED`` ``NEOPIXEL`` ``D8`` ``D4`` / ``TX``
-PA07 ``A6`` ``D9`` ``A3`` ``D9`` ``D9`` ``D9`` ``D9`` ``D3`` / ``RX``
-PA08 ``D11`` / ``SDA`` ``D4`` ``MICROPHONE_DO`` ``D4`` / ``SD_CS`` ``D4`` ``D0`` / ``SDA``
-PA09 ``D12`` / ``SCL`` ``D3`` ``TEMPERATURE`` / ``A9`` ``D3`` ``D2`` / ``SCL``
-PA10 ``D2`` ``D1`` / ``TX`` ``MICROPHONE_SCK`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D13``
-PA11 ``D3`` ``D0`` / ``RX`` ``LIGHT`` / ``A8`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX``
+PA06 ``A5`` ``D8`` ``A2`` ``D8`` / ``GREEN_LED`` ``NEOPIXEL`` ``D8`` ``D8`` ``D4`` / ``TX``
+PA07 ``A6`` ``D9`` ``A3`` ``D9`` ``D9`` ``D9`` ``D9`` ``D9`` ``D3`` / ``RX``
+PA08 ``D11`` / ``SDA`` ``D4`` ``MICROPHONE_DO`` ``D4`` / ``SD_CS`` ``D4`` ``D4`` ``D0`` / ``SDA``
+PA09 ``D12`` / ``SCL`` ``D3`` ``TEMPERATURE`` / ``A9`` ``D3`` ``D3`` ``D2`` / ``SCL``
+PA10 ``D2`` ``D1`` / ``TX`` ``MICROPHONE_SCK`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D1`` / ``TX`` ``D13``
+PA11 ``D3`` ``D0`` / ``RX`` ``LIGHT`` / ``A8`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX`` ``D0`` / ``RX``
PB10 ``D4`` ``MOSI`` ``MOSI`` ``MOSI`` ``MOSI`` ``MOSI``
PB11 ``D5`` ``SCK`` ``SCK`` ``SCK`` ``SCK`` ``SCK``
PA12 ``SD_MOSI`` ``MISO`` ``REMOTEIN`` / ``IR_RX`` ``MISO`` ``MISO`` ``MISO`` ``MISO``
PA13 ``SD_SCK`` ``ACCELEROMETER_INTERRUPT`` ``FLASH_CS``
-PA14 ``SD_CS`` ``D2`` ``BUTTON_B`` / ``D5`` ``D2``
-PA15 ``SD_MISO`` ``D5`` ``SLIDE_SWITCH`` / ``D7`` ``D5`` ``D5`` ``D5`` ``D5``
-PA16 ``D8`` / ``MOSI`` ``D11`` ``MISO`` ``D11`` ``D11`` ``D11`` ``D11``
-PA17 ``D9`` / ``SCK`` ``D13`` ``D13`` ``D13`` / ``RED_LED`` ``D13`` ``D13`` ``D13``
-PA18 ``D10`` ``D10`` ``D10`` ``D10`` ``D10``
-PA19 ``D10`` / ``MISO`` ``D12`` ``D12`` ``D12`` ``D12`` ``D12``
-PA20 ``D6`` ``D6`` ``MOSI`` ``D6`` ``D6`` ``D6`` ``D6``
-PA21 ``D7`` ``D7`` ``SCK`` ``D7`` / ``SD_CD`` ``D7``
-PA22 ``D0`` ``SDA`` ``SDA`` ``SDA`` ``SDA`` ``SDA``
-PA23 ``D1`` ``SCL`` ``REMOTEOUT`` / ``IR_TX`` ``SCL`` ``SCL`` ``SCL`` ``L`` / ``D13`` ``SCL``
+PA14 ``SD_CS`` ``D2`` ``BUTTON_B`` / ``D5`` ``D2`` ``D2``
+PA15 ``SD_MISO`` ``D5`` ``SLIDE_SWITCH`` / ``D7`` ``D5`` ``D5`` ``D5`` ``D5`` ``D5``
+PA16 ``D8`` / ``MOSI`` ``D11`` ``MISO`` ``D11`` ``D11`` ``D11`` ``D11`` ``D11`` / ``MOSI``
+PA17 ``D9`` / ``SCK`` ``D13`` ``D13`` ``D13`` / ``RED_LED`` ``D13`` ``D13`` ``D13`` ``D13`` / ``SCK`` / ``BLUE_LED``
+PA18 ``D10`` ``D10`` ``D10`` ``D10`` ``D10`` ``D10``
+PA19 ``D10`` / ``MISO`` ``D12`` ``D12`` ``D12`` ``D12`` ``D12`` ``D12`` / ``MISO``
+PA20 ``D6`` ``D6`` ``MOSI`` ``D6`` ``D6`` ``D6`` ``D6`` ``D6``
+PA21 ``D7`` ``D7`` ``SCK`` ``D7`` / ``SD_CD`` ``D7`` ``D7``
+PA22 ``D0`` ``SDA`` ``SDA`` ``SDA`` ``SDA`` ``SDA`` ``SDA``
+PA23 ``D1`` ``SCL`` ``REMOTEOUT`` / ``IR_TX`` ``SCL`` ``SCL`` ``SCL`` ``L`` / ``D13`` ``SCL`` ``SCL``
PA24
PA25
PB22 ``D14`` / ``TX`` ``FLASH_CS``
PB23 ``D13`` / ``RX`` ``NEOPIXEL`` / ``D8``
-PA27 ``SD_CD``
+PA27 ``SD_CD`` ``GREEN_LED``
PA28 ``BUTTON_A`` / ``D4``
PA29
PA30 ``SPEAKER_ENABLE`` ``NEOPIXEL``
PA31
PB02 ``A1`` ``A5`` ``A5`` / ``SDA`` ``A5`` ``A5`` ``A5`` ``A5``
-PB03 ``A2`` ``A4`` / ``SCL``
-===================== =================== =============== =========================== ====================== ================ ================== ========================= ================ ================
+PB03 ``A2`` ``A4`` / ``SCL`` ``YELLOW_LED``
+===================== =================== =============== =========================== ====================== ================ ================== ========================= ================ ================================ ================
Here is a table about which pins can do what in CircuitPython terms. However,
just because something is listed, doesn't mean it will always work. Existing use
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_mini/board.c b/ports/atmel-samd/boards/sparkfun_samd21_mini/board.c
new file mode 100644
index 000000000..0f60736a2
--- /dev/null
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/board.c
@@ -0,0 +1,39 @@
+/*
+ * 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"
+#include "mpconfigboard.h"
+#include "hal/include/hal_gpio.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.h b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.h
new file mode 100644
index 000000000..aec54ddfb
--- /dev/null
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.h
@@ -0,0 +1,24 @@
+#define MICROPY_HW_BOARD_NAME "SparkFun SAMD21 Mini Breakout"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define MICROPY_PORT_A (0)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE 0
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA17)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA16)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA19)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
+
+// 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/sparkfun_samd21_mini/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
new file mode 100644
index 000000000..0cba15d70
--- /dev/null
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
@@ -0,0 +1,11 @@
+LD_FILE = boards/samd21x18-bootloader.ld
+USB_VID = 0x1B4F
+USB_PID = 0x8D22
+USB_PRODUCT = "SparkFun SAMD21 Mini Breakout"
+USB_MANUFACTURER = "SparkFun"
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_mini/pins.c b/ports/atmel-samd/boards/sparkfun_samd21_mini/pins.c
new file mode 100644
index 000000000..abe63d064
--- /dev/null
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/pins.c
@@ -0,0 +1,53 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+
+ // Analog pins
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) },
+
+ // Digital pins
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) },
+
+ // UART pins
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) },
+
+ // SPI pins
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA19) },
+
+ // I2C pins
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
+
+ // LED pins
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_GREEN_LED), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_YELLOW_LED), MP_ROM_PTR(&pin_PB03) },
+
+ // Comm objects
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index d0ebbfa39..65b8c94c5 100644
--- a/ports/atmel-samd/mpconfigport.h
+++ b/ports/atmel-samd/mpconfigport.h
@@ -237,6 +237,7 @@ extern const struct _mp_obj_module_t gamepad_module;
extern const struct _mp_obj_module_t stage_module;
extern const struct _mp_obj_module_t touchio_module;
extern const struct _mp_obj_module_t usb_hid_module;
+extern const struct _mp_obj_module_t usb_midi_module;
extern const struct _mp_obj_module_t network_module;
extern const struct _mp_obj_module_t socket_module;
extern const struct _mp_obj_module_t wiznet_module;
@@ -382,6 +383,7 @@ extern const struct _mp_obj_module_t wiznet_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR__time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_midi),(mp_obj_t)&usb_midi_module }, \
TOUCHIO_MODULE \
EXTRA_BUILTIN_MODULES
@@ -410,6 +412,7 @@ extern const struct _mp_obj_module_t wiznet_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_midi),(mp_obj_t)&usb_midi_module }, \
TOUCHIO_MODULE \
EXTRA_BUILTIN_MODULES
#endif
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index 2e345b9c7..2bc508475 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -75,7 +75,7 @@ LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) -L boards/
LDFLAGS += -Wl,--gc-sections
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128
#Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -103,6 +103,7 @@ SRC_NRFX = $(addprefix nrfx/,\
drivers/src/nrfx_timer.c \
drivers/src/nrfx_twim.c \
drivers/src/nrfx_uarte.c \
+ drivers/src/nrfx_gpiote.c \
)
ifdef EXTERNAL_FLASH_DEVICES
diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c
index 85f3b6b6c..710825960 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.c
+++ b/ports/nrf/common-hal/bleio/Peripheral.c
@@ -100,6 +100,10 @@ STATIC uint32_t add_services_to_advertisement(bleio_peripheral_obj_t *self, size
+// if raw_data is a zero-length buffer, generate an advertising packet that advertises the
+// services passed in when this Peripheral was created.
+// If raw_data contains some bytes, use those bytes as the advertising packet.
+// TODO: Generate the advertising packet in Python, not here.
STATIC uint32_t set_advertisement_data(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
common_hal_bleio_adapter_set_enabled(true);
diff --git a/ports/nrf/common-hal/neopixel_write/__init__.c b/ports/nrf/common-hal/neopixel_write/__init__.c
index 76bc170e8..f47188ea2 100644
--- a/ports/nrf/common-hal/neopixel_write/__init__.c
+++ b/ports/nrf/common-hal/neopixel_write/__init__.c
@@ -141,7 +141,7 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
for ( uint16_t n = 0; n < numBytes; n++ ) {
uint8_t pix = pixels[n];
- for ( uint8_t mask = 0x80, i = 0; mask > 0; mask >>= 1, i++ ) {
+ for ( uint8_t mask = 0x80; mask > 0; mask >>= 1 ) {
pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H : MAGIC_T0H;
pos++;
}
diff --git a/ports/nrf/common-hal/pulseio/PulseIn.c b/ports/nrf/common-hal/pulseio/PulseIn.c
index 3d6d266af..6e5825af6 100644
--- a/ports/nrf/common-hal/pulseio/PulseIn.c
+++ b/ports/nrf/common-hal/pulseio/PulseIn.c
@@ -27,6 +27,7 @@
#include "common-hal/pulseio/PulseIn.h"
#include <stdint.h>
+#include <string.h>
#include "py/mpconfig.h"
#include "py/gc.h"
@@ -35,50 +36,247 @@
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/pulseio/PulseIn.h"
+#include "tick.h"
+#include "nrfx_gpiote.h"
+
+// obj array to map pin -> self since nrfx hide the mapping
+static pulseio_pulsein_obj_t* _objs[GPIOTE_CH_NUM];
+
+// return index of the object in array
+static int _find_pulsein_obj(pulseio_pulsein_obj_t* obj) {
+ for(int i = 0; i < NRFX_ARRAY_SIZE(_objs); i++ ) {
+ if ( _objs[i] == obj) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static void _pulsein_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
+ // Grab the current time first.
+ uint32_t current_us;
+ uint64_t current_ms;
+ current_tick(&current_ms, &current_us);
+
+ // current_tick gives us the remaining us until the next tick but we want the number since the last ms.
+ current_us = 1000 - current_us;
+
+ pulseio_pulsein_obj_t* self = NULL;
+ for(int i = 0; i < NRFX_ARRAY_SIZE(_objs); i++ ) {
+ if ( _objs[i] && _objs[i]->pin == pin ) {
+ self = _objs[i];
+ break;
+ }
+ }
+ if ( !self ) return;
+
+ if (self->first_edge) {
+ // first pulse is opposite state from idle
+ bool state = nrf_gpio_pin_read(self->pin);
+ if ( self->idle_state != state ) {
+ self->first_edge = false;
+ }
+ }else {
+ uint32_t ms_diff = current_ms - self->last_ms;
+ uint16_t us_diff = current_us - self->last_us;
+ uint32_t total_diff = us_diff;
+
+ if (self->last_us > current_us) {
+ total_diff = 1000 + current_us - self->last_us;
+ if (ms_diff > 1) {
+ total_diff += (ms_diff - 1) * 1000;
+ }
+ } else {
+ total_diff += ms_diff * 1000;
+ }
+ uint16_t duration = 0xffff;
+ if (total_diff < duration) {
+ duration = total_diff;
+ }
+
+ uint16_t i = (self->start + self->len) % self->maxlen;
+ self->buffer[i] = duration;
+ if (self->len < self->maxlen) {
+ self->len++;
+ } else {
+ self->start++;
+ }
+ }
+
+ self->last_ms = current_ms;
+ self->last_us = current_us;
+}
+
void pulsein_reset(void) {
+ if ( nrfx_gpiote_is_init() ) {
+ nrfx_gpiote_uninit();
+ }
+ nrfx_gpiote_init();
+ memset(_objs, 0, sizeof(_objs));
}
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, uint16_t maxlen, bool idle_state) {
- mp_raise_NotImplementedError(NULL);
+ int idx = _find_pulsein_obj(NULL);
+ if ( idx < 0 ) {
+ mp_raise_NotImplementedError(NULL);
+ }
+ _objs[idx] = self;
+
+ self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false);
+ if (self->buffer == NULL) {
+ mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t));
+ }
+
+ self->pin = pin->number;
+ self->maxlen = maxlen;
+ self->idle_state = idle_state;
+ self->start = 0;
+ self->len = 0;
+ self->first_edge = true;
+ self->paused = false;
+ self->last_us = 0;
+ self->last_ms = 0;
+
+ claim_pin(pin);
+
+ nrfx_gpiote_in_config_t cfg = {
+ .sense = NRF_GPIOTE_POLARITY_TOGGLE,
+ .pull = NRF_GPIO_PIN_NOPULL, // idle_state ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_PULLUP,
+ .is_watcher = false, // nrf_gpio_cfg_watcher vs nrf_gpio_cfg_input
+ .hi_accuracy = true,
+ .skip_gpio_setup = false
+ };
+ nrfx_gpiote_in_init(self->pin, &cfg, _pulsein_handler);
+ nrfx_gpiote_in_event_enable(self->pin, true);
}
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
- return 1;
+ return self->pin == NO_PIN;
}
void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
+ if (common_hal_pulseio_pulsein_deinited(self)) {
+ return;
+ }
+
+ nrfx_gpiote_in_event_disable(self->pin);
+ nrfx_gpiote_in_uninit(self->pin);
+
+ // mark local array as invalid
+ int idx = _find_pulsein_obj(self);
+ if ( idx < 0 ) {
+ mp_raise_NotImplementedError(NULL);
+ }
+ _objs[idx] = NULL;
+ reset_pin_number(self->pin);
+ self->pin = NO_PIN;
}
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
-
+ nrfx_gpiote_in_event_disable(self->pin);
+ self->paused = true;
}
void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) {
+ // Make sure we're paused.
+ if ( !self->paused ) {
+ common_hal_pulseio_pulsein_pause(self);
+ }
+
+ // Send the trigger pulse.
+ if (trigger_duration > 0) {
+ nrfx_gpiote_in_uninit(self->pin);
+
+ nrf_gpio_cfg_output(self->pin);
+ nrf_gpio_pin_write(self->pin, !self->idle_state);
+ common_hal_mcu_delay_us((uint32_t)trigger_duration);
+ nrf_gpio_pin_write(self->pin, self->idle_state);
+
+ nrfx_gpiote_in_config_t cfg = {
+ .sense = NRF_GPIOTE_POLARITY_TOGGLE,
+ .pull = NRF_GPIO_PIN_NOPULL, // idle_state ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_PULLUP,
+ .is_watcher = false, // nrf_gpio_cfg_watcher vs nrf_gpio_cfg_input
+ .hi_accuracy = true,
+ .skip_gpio_setup = false
+ };
+ nrfx_gpiote_in_init(self->pin, &cfg, _pulsein_handler);
+ }
+
+ self->first_edge = true;
+ self->paused = false;
+ self->last_ms = 0;
+ self->last_us = 0;
+ nrfx_gpiote_in_event_enable(self->pin, true);
}
void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_disable(self->pin);
+ }
+ self->start = 0;
+ self->len = 0;
+
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_enable(self->pin, true);
+ }
+}
+
+uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_disable(self->pin);
+ }
+
+ if (index < 0) {
+ index += self->len;
+ }
+ if (index < 0 || index >= self->len) {
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_enable(self->pin, true);
+ }
+ mp_raise_IndexError(translate("index out of range"));
+ }
+ uint16_t value = self->buffer[(self->start + index) % self->maxlen];
+
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_enable(self->pin, true);
+ }
+
+ return value;
}
uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
- return 0;
+ if (self->len == 0) {
+ mp_raise_IndexError(translate("pop from an empty PulseIn"));
+ }
+
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_disable(self->pin);
+ }
+
+ uint16_t value = self->buffer[self->start];
+ self->start = (self->start + 1) % self->maxlen;
+ self->len--;
+
+ if ( !self->paused ) {
+ nrfx_gpiote_in_event_enable(self->pin, true);
+ }
+
+ return value;
}
uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) {
- return 0xadaf;
+ return self->maxlen;
}
bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) {
- return false;
+ return self->paused;
}
uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) {
- return 0xadaf;
-}
-
-uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
- return 0xadaf;
+ return self->len;
}
diff --git a/ports/nrf/common-hal/pulseio/PulseIn.h b/ports/nrf/common-hal/pulseio/PulseIn.h
index 666f5a164..4b2c6eee3 100644
--- a/ports/nrf/common-hal/pulseio/PulseIn.h
+++ b/ports/nrf/common-hal/pulseio/PulseIn.h
@@ -33,15 +33,19 @@
typedef struct {
mp_obj_base_t base;
- uint8_t channel;
+
uint8_t pin;
+ bool idle_state;
+ bool paused;
+ volatile bool first_edge;
+
uint16_t* buffer;
uint16_t maxlen;
- bool idle_state;
+
volatile uint16_t start;
volatile uint16_t len;
- volatile bool first_edge;
- uint16_t ticks_per_ms;
+ volatile uint16_t last_us;
+ volatile uint64_t last_ms;
} pulseio_pulsein_obj_t;
void pulsein_reset(void);
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index 25710cea2..d38b14578 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -175,6 +175,7 @@ extern const struct _mp_obj_module_t supervisor_module;
extern const struct _mp_obj_module_t gamepad_module;
extern const struct _mp_obj_module_t neopixel_write_module;
extern const struct _mp_obj_module_t usb_hid_module;
+extern const struct _mp_obj_module_t usb_midi_module;
extern const struct _mp_obj_module_t bleio_module;
#if MICROPY_PY_BLEIO
@@ -207,6 +208,7 @@ extern const struct _mp_obj_module_t bleio_module;
{ MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR (MP_QSTR_json ), (mp_obj_t)&mp_module_ujson }, \
USBHID_MODULE \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_midi),(mp_obj_t)&usb_midi_module }, \
BLEIO_MODULE
// extra built in names to add to the global namespace
diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h
index 1d3085e2b..8676bd7f8 100644
--- a/ports/nrf/nrfx_config.h
+++ b/ports/nrf/nrfx_config.h
@@ -84,4 +84,9 @@
#define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 7
+// GPIO interrupt
+#define NRFX_GPIOTE_ENABLED 1
+#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1
+#define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 7
+
#endif // NRFX_CONFIG_H__
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index cf0434793..b2e98fd5b 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -43,6 +43,7 @@
#include "common-hal/busio/SPI.h"
#include "common-hal/pulseio/PWMOut.h"
#include "common-hal/pulseio/PulseOut.h"
+#include "common-hal/pulseio/PulseIn.h"
#include "tick.h"
static void power_warning_handler(void) {
@@ -85,6 +86,7 @@ void reset_port(void) {
spi_reset();
pwmout_reset();
pulseout_reset();
+ pulsein_reset();
timers_reset();
bleio_reset();
diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c
index 1027bbb1f..cea44486f 100644
--- a/shared-bindings/bleio/Peripheral.c
+++ b/shared-bindings/bleio/Peripheral.c
@@ -192,7 +192,8 @@ const mp_obj_property_t bleio_peripheral_name_obj = {
//| services are included in the advertisement packets.
//|
//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral.
-//| :param buf data: If not None, then send data bytes in advertising packets.
+//| :param buf data: If `None`, advertise the services passed to this Peripheral when it was created.
+//| If not `None`, then send the bytes in ``data`` as the advertising packet.
//|
STATIC mp_obj_t bleio_peripheral_start_advertising(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]);
diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c
new file mode 100644
index 000000000..e1e6eabcc
--- /dev/null
+++ b/shared-bindings/usb_midi/PortIn.c
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/util.h"
+
+#include "py/ioctl.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+
+
+//| .. currentmodule:: usb_midi
+//|
+//| :class:`PortIn` -- receives midi commands over USB
+//| ===================================================
+//|
+//| .. class:: PortIn()
+//|
+//| Not currently dynamically supported.
+//|
+//| PortIn objects are constructed for every corresponding entry in the USB descriptor and added
+//| to the ``usb_midi.ports`` tuple.
+//|
+
+STATIC mp_obj_t usb_midi_portin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ return mp_const_none;
+}
+
+// These are standard stream methods. Code is in py/stream.c.
+//
+//| .. method:: read(nbytes=None)
+//|
+//| Read characters. If ``nbytes`` is specified then read at most that many
+//| bytes. Otherwise, read everything that arrives until the connection
+//| times out. Providing the number of bytes expected is highly recommended
+//| because it will be faster.
+//|
+//| :return: Data read
+//| :rtype: bytes or None
+//|
+//| .. method:: readinto(buf, nbytes=None)
+//|
+//| Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
+//| that many bytes. Otherwise, read at most ``len(buf)`` bytes.
+//|
+//| :return: number of bytes read and stored into ``buf``
+//| :rtype: bytes or None
+//|
+
+// These three methods are used by the shared stream methods.
+STATIC mp_uint_t usb_midi_portin_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+ usb_midi_portin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ byte *buf = buf_in;
+
+ // make sure we want at least 1 char
+ if (size == 0) {
+ return 0;
+ }
+
+ return common_hal_usb_midi_portin_read(self, buf, size, errcode);
+}
+
+STATIC mp_uint_t usb_midi_portin_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ usb_midi_portin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t ret;
+ if (request == MP_IOCTL_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ if ((flags & MP_IOCTL_POLL_RD) && common_hal_usb_midi_portin_bytes_available(self) > 0) {
+ ret |= MP_IOCTL_POLL_RD;
+ }
+ } else {
+ *errcode = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+STATIC const mp_rom_map_elem_t usb_midi_portin_locals_dict_table[] = {
+ // Standard stream methods.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(usb_midi_portin_locals_dict, usb_midi_portin_locals_dict_table);
+
+STATIC const mp_stream_p_t usb_midi_portin_stream_p = {
+ .read = usb_midi_portin_read,
+ .write = NULL,
+ .ioctl = usb_midi_portin_ioctl,
+ .is_text = false,
+};
+
+const mp_obj_type_t usb_midi_portin_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PortIn,
+ .make_new = usb_midi_portin_make_new,
+ .getiter = mp_identity_getiter,
+ .iternext = mp_stream_unbuffered_iter,
+ .protocol = &usb_midi_portin_stream_p,
+ .locals_dict = (mp_obj_dict_t*)&usb_midi_portin_locals_dict,
+};
diff --git a/shared-bindings/usb_midi/PortIn.h b/shared-bindings/usb_midi/PortIn.h
new file mode 100644
index 000000000..89bb59b71
--- /dev/null
+++ b/shared-bindings/usb_midi/PortIn.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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_USB_MIDI_PORTIN_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTIN_H
+
+#include "shared-module/usb_midi/PortIn.h"
+
+extern const mp_obj_type_t usb_midi_portin_type;
+
+// Construct an underlying UART object.
+extern void common_hal_usb_midi_portin_construct(usb_midi_portin_obj_t *self,
+ uint8_t receiver_buffer_size);
+// Read characters.
+extern size_t common_hal_usb_midi_portin_read(usb_midi_portin_obj_t *self,
+ uint8_t *data, size_t len, int *errcode);
+
+extern uint32_t common_hal_usb_midi_portin_bytes_available(usb_midi_portin_obj_t *self);
+extern void common_hal_usb_midi_portin_clear_buffer(usb_midi_portin_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTIN_H
diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c
new file mode 100644
index 000000000..0588eed90
--- /dev/null
+++ b/shared-bindings/usb_midi/PortOut.c
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 "shared-bindings/usb_midi/PortOut.h"
+#include "shared-bindings/util.h"
+
+#include "py/ioctl.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+
+
+//| .. currentmodule:: usb_midi
+//|
+//| :class:`PortOut` -- sends midi messages to a computer over USB
+//| ==============================================================
+//|
+//| .. class:: PortOut()
+//|
+//| Not currently dynamically supported.
+//|
+//| PortOut objects are constructed for every corresponding entry in the USB descriptor and added
+//| to the ``usb_midi.ports`` tuple.
+//|
+
+STATIC mp_obj_t usb_midi_portout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ return mp_const_none;
+}
+
+// These are standard stream methods. Code is in py/stream.c.
+//
+//| .. method:: write(buf)
+//|
+//| Write the buffer of bytes to the bus.
+//|
+//| :return: the number of bytes written
+//| :rtype: int or None
+//|
+
+STATIC mp_uint_t usb_midi_portout_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
+ usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ const byte *buf = buf_in;
+
+ return common_hal_usb_midi_portout_write(self, buf, size, errcode);
+}
+
+STATIC mp_uint_t usb_midi_portout_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t ret;
+ if (request == MP_IOCTL_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ if ((flags & MP_IOCTL_POLL_WR) && common_hal_usb_midi_portout_ready_to_tx(self)) {
+ ret |= MP_IOCTL_POLL_WR;
+ }
+ } else {
+ *errcode = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+STATIC const mp_rom_map_elem_t usb_midi_portout_locals_dict_table[] = {
+ // Standard stream methods.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(usb_midi_portout_locals_dict, usb_midi_portout_locals_dict_table);
+
+STATIC const mp_stream_p_t usb_midi_portout_stream_p = {
+ .read = NULL,
+ .write = usb_midi_portout_write,
+ .ioctl = usb_midi_portout_ioctl,
+ .is_text = false,
+};
+
+const mp_obj_type_t usb_midi_portout_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PortOut,
+ .make_new = usb_midi_portout_make_new,
+ .getiter = mp_identity_getiter,
+ .iternext = mp_stream_unbuffered_iter,
+ .protocol = &usb_midi_portout_stream_p,
+ .locals_dict = (mp_obj_dict_t*)&usb_midi_portout_locals_dict,
+};
diff --git a/shared-bindings/usb_midi/PortOut.h b/shared-bindings/usb_midi/PortOut.h
new file mode 100644
index 000000000..dd42d7cdb
--- /dev/null
+++ b/shared-bindings/usb_midi/PortOut.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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_USB_MIDI_PORTOUT_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTOUT_H
+
+#include "shared-module/usb_midi/PortOut.h"
+
+extern const mp_obj_type_t usb_midi_portout_type;
+
+// Construct an underlying UART object.
+extern void common_hal_usb_midi_portout_construct(usb_midi_portout_obj_t *self,
+ uint8_t receiver_buffer_size);
+
+// Write characters. len is in characters NOT bytes!
+extern size_t common_hal_usb_midi_portout_write(usb_midi_portout_obj_t *self,
+ const uint8_t *data, size_t len, int *errcode);
+
+extern bool common_hal_usb_midi_portout_ready_to_tx(usb_midi_portout_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI_PORTOUT_H
diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c
new file mode 100644
index 000000000..f57d3631b
--- /dev/null
+++ b/shared-bindings/usb_midi/__init__.c
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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/usb_midi/__init__.h"
+#include "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/usb_midi/PortOut.h"
+
+#include "py/runtime.h"
+
+//| :mod:`usb_midi` --- MIDI over USB
+//| =================================================
+//|
+//| .. module:: usb_midi
+//| :synopsis: MIDI over USB
+//|
+//| The `usb_midi` module contains classes to transmit and receive MIDI messages over USB
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| PortIn
+//| PortOut
+//|
+//|
+mp_map_elem_t usb_midi_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_midi) },
+ { MP_ROM_QSTR(MP_QSTR_ports), mp_const_empty_tuple },
+ { MP_ROM_QSTR(MP_QSTR_PortIn), MP_OBJ_FROM_PTR(&usb_midi_portin_type) },
+ { MP_ROM_QSTR(MP_QSTR_PortOut), MP_OBJ_FROM_PTR(&usb_midi_portout_type) },
+};
+
+// This isn't const so we can set ports dynamically.
+mp_obj_dict_t usb_midi_module_globals = {
+ .base = {&mp_type_dict},
+ .map = {
+ .all_keys_are_qstrs = 1,
+ .is_fixed = 1,
+ .is_ordered = 1,
+ .used = MP_ARRAY_SIZE(usb_midi_module_globals_table),
+ .alloc = MP_ARRAY_SIZE(usb_midi_module_globals_table),
+ .table = usb_midi_module_globals_table,
+ },
+};
+
+const mp_obj_module_t usb_midi_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&usb_midi_module_globals,
+};
diff --git a/shared-bindings/usb_midi/__init__.h b/shared-bindings/usb_midi/__init__.h
new file mode 100644
index 000000000..e81818e04
--- /dev/null
+++ b/shared-bindings/usb_midi/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft
+ *
+ * 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_USB_MIDI___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H
+
+#include "py/obj.h"
+
+extern mp_obj_dict_t usb_midi_module_globals;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H
diff --git a/shared-module/usb_midi/PortIn.c b/shared-module/usb_midi/PortIn.c
new file mode 100644
index 000000000..b256c5937
--- /dev/null
+++ b/shared-module/usb_midi/PortIn.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 "shared-module/usb_midi/PortIn.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+void common_hal_usb_midi_portin_construct(usb_midi_portin_obj_t *self, uint8_t receiver_buffer_size) {
+}
+
+size_t common_hal_usb_midi_portin_read(usb_midi_portin_obj_t *self, uint8_t *data, size_t len, int *errcode) {
+ return tud_midi_read(data, len);
+}
+
+uint32_t common_hal_usb_midi_portin_bytes_available(usb_midi_portin_obj_t *self) {
+ return tud_midi_available();
+}
diff --git a/shared-module/usb_midi/PortIn.h b/shared-module/usb_midi/PortIn.h
new file mode 100644
index 000000000..2f72aa4c2
--- /dev/null
+++ b/shared-module/usb_midi/PortIn.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 SHARED_MODULE_USB_MIDI_PORTIN_H
+#define SHARED_MODULE_USB_MIDI_PORTIN_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} usb_midi_portin_obj_t;
+
+#endif /* SHARED_MODULE_USB_MIDI_PORTIN_H */
diff --git a/shared-module/usb_midi/PortOut.c b/shared-module/usb_midi/PortOut.c
new file mode 100644
index 000000000..3b9998c73
--- /dev/null
+++ b/shared-module/usb_midi/PortOut.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 "shared-module/usb_midi/PortOut.h"
+#include "supervisor/shared/translate.h"
+#include "tusb.h"
+
+void common_hal_usb_midi_portout_construct(usb_midi_portout_obj_t *self) {
+}
+
+size_t common_hal_usb_midi_portout_write(usb_midi_portout_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
+ return tud_midi_write(0, data, len);
+}
+
+bool common_hal_usb_midi_portout_ready_to_tx(usb_midi_portout_obj_t *self) {
+ return tud_midi_connected();
+}
diff --git a/shared-module/usb_midi/PortOut.h b/shared-module/usb_midi/PortOut.h
new file mode 100644
index 000000000..6b1b88464
--- /dev/null
+++ b/shared-module/usb_midi/PortOut.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 SHARED_MODULE_USB_MIDI_PORTOUT_H
+#define SHARED_MODULE_USB_MIDI_PORTOUT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} usb_midi_portout_obj_t;
+
+#endif /* SHARED_MODULE_USB_MIDI_PORTOUT_H */
diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c
new file mode 100644
index 000000000..73a314b99
--- /dev/null
+++ b/shared-module/usb_midi/__init__.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach 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/usb_midi/__init__.h"
+
+#include "genhdr/autogen_usb_descriptor.h"
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "py/runtime.h"
+#include "py/objtuple.h"
+#include "shared-bindings/usb_midi/PortIn.h"
+#include "shared-bindings/usb_midi/PortOut.h"
+#include "supervisor/memory.h"
+#include "tusb.h"
+
+supervisor_allocation* usb_midi_allocation;
+
+void usb_midi_init(void) {
+ // TODO(tannewt): Make this dynamic.
+ uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2);
+ uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
+ uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t));
+
+ // For each embedded MIDI Jack in the descriptor we create a Port
+ usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false);
+
+ mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr;
+ ports->base.type = &mp_type_tuple;
+ ports->len = 2;
+
+ usb_midi_portin_obj_t* in = (usb_midi_portin_obj_t *) (usb_midi_allocation->ptr + tuple_size / 4);
+ in->base.type = &usb_midi_portin_type;
+ ports->items[0] = MP_OBJ_FROM_PTR(in);
+
+ usb_midi_portout_obj_t* out = (usb_midi_portout_obj_t *) (usb_midi_allocation->ptr + tuple_size / 4 + portin_size / 4);
+ out->base.type = &usb_midi_portout_type;
+ ports->items[1] = MP_OBJ_FROM_PTR(out);
+
+ mp_map_lookup(&usb_midi_module_globals.map, MP_ROM_QSTR(MP_QSTR_ports), MP_MAP_LOOKUP)->value = MP_OBJ_FROM_PTR(ports);
+}
diff --git a/shared-module/usb_midi/__init__.h b/shared-module/usb_midi/__init__.h
new file mode 100644
index 000000000..e1ad1fbaf
--- /dev/null
+++ b/shared-module/usb_midi/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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 SHARED_MODULE_USB_MIDI___INIT___H
+#define SHARED_MODULE_USB_MIDI___INIT___H
+
+void usb_midi_init(void);
+
+#endif /* SHARED_MODULE_USB_MIDI___INIT___H */
diff --git a/supervisor/memory.h b/supervisor/memory.h
index 4f8317a2d..c89f14bd9 100755
--- a/supervisor/memory.h
+++ b/supervisor/memory.h
@@ -39,6 +39,8 @@ typedef struct {
uint32_t length; // in bytes
} supervisor_allocation;
+
+
void memory_init(void);
void free_memory(supervisor_allocation* allocation);
supervisor_allocation* allocate_remaining_memory(void);
@@ -48,4 +50,11 @@ supervisor_allocation* allocate_remaining_memory(void);
// statically allocated memory.
supervisor_allocation* allocate_memory(uint32_t length, bool high_address);
+static inline uint16_t align32_size(uint16_t size) {
+ if (size % 4 != 0) {
+ return (size & 0xfffc) + 0x4;
+ }
+ return size;
+}
+
#endif // MICROPY_INCLUDED_SUPERVISOR_MEMORY_H
diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h
index 649c390ac..301805275 100644
--- a/supervisor/shared/usb/tusb_config.h
+++ b/supervisor/shared/usb/tusb_config.h
@@ -75,6 +75,7 @@
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
#define CFG_TUD_HID 1
+#define CFG_TUD_MIDI 1
#define CFG_TUD_CUSTOM_CLASS 0
/*------------------------------------------------------------------*/
diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c
index 1aa34e9e6..5898323e8 100644
--- a/supervisor/shared/usb/usb.c
+++ b/supervisor/shared/usb/usb.c
@@ -26,6 +26,7 @@
#include "tick.h"
#include "shared-bindings/microcontroller/Processor.h"
+#include "shared-module/usb_midi/__init__.h"
#include "supervisor/port.h"
#include "supervisor/usb.h"
#include "lib/utils/interrupt_char.h"
@@ -71,11 +72,13 @@ void usb_init(void) {
// This callback always got invoked regardless of mp_interrupt_char value since we only set it once here
tud_cdc_set_wanted_char(CHAR_CTRL_C);
#endif
+
+ usb_midi_init();
}
void usb_background(void) {
if (usb_enabled()) {
- tusb_task();
+ tud_task();
tud_cdc_write_flush();
}
}
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index 56ad8a3ba..191af7b25 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -49,6 +49,7 @@ else
lib/tinyusb/src/class/msc/msc_device.c \
lib/tinyusb/src/class/cdc/cdc_device.c \
lib/tinyusb/src/class/hid/hid_device.c \
+ lib/tinyusb/src/class/midi/midi_device.c \
lib/tinyusb/src/tusb.c \
supervisor/shared/serial.c \
supervisor/usb.c \
@@ -57,8 +58,14 @@ else
supervisor/shared/usb/usb_msc_flash.c \
shared-bindings/usb_hid/__init__.c \
shared-bindings/usb_hid/Device.c \
+ shared-bindings/usb_midi/__init__.c \
+ shared-bindings/usb_midi/PortIn.c \
+ shared-bindings/usb_midi/PortOut.c \
shared-module/usb_hid/__init__.c \
shared-module/usb_hid/Device.c \
+ shared-module/usb_midi/__init__.c \
+ shared-module/usb_midi/PortIn.c \
+ shared-module/usb_midi/PortOut.c \
$(BUILD)/autogen_usb_descriptor.c
CFLAGS += -DUSB_AVAILABLE
endif
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 2cb06ec2f..10bbf5066 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -176,16 +176,33 @@ hid_interfaces = [
]
# Audio!
-midi_in_jack = midi.InJackDescriptor(
- description="MIDI PC <- CircuitPython internals",
+# In and out here are relative to CircuitPython
+
+# USB OUT -> midi_in_jack_emb -> midi_out_jack_ext -> CircuitPython
+midi_in_jack_emb = midi.InJackDescriptor(
+ description="MIDI PC -> CircuitPython",
bJackType=midi.JACK_TYPE_EMBEDDED,
- iJack=0)
-midi_out_jack = midi.OutJackDescriptor(
- description="MIDI PC -> CircuitPython internals",
+ iJack=StringIndex.index("CircuitPython usb_midi.ports[0]"))
+midi_out_jack_ext = midi.OutJackDescriptor(
+ description="MIDI data out to user code.",
+ bJackType=midi.JACK_TYPE_EXTERNAL,
+ input_pins=[(midi_in_jack_emb, 1)],
+ iJack=0)
+
+# USB IN <- midi_out_jack_emb <- midi_in_jack_ext <- CircuitPython
+midi_in_jack_ext = midi.InJackDescriptor(
+ description="MIDI data in from user code.",
+ bJackType=midi.JACK_TYPE_EXTERNAL,
+ iJack=0)
+midi_out_jack_emb = midi.OutJackDescriptor(
+ description="MIDI PC <- CircuitPython",
bJackType=midi.JACK_TYPE_EMBEDDED,
- iJack=0)
+ input_pins=[(midi_in_jack_ext, 1)],
+ iJack=StringIndex.index("CircuitPython usb_midi.ports[1]"))
+
+
audio_midi_interface = standard.InterfaceDescriptor(
- description="All the audio",
+ description="Midi goodness",
bInterfaceClass=audio.AUDIO_CLASS_DEVICE,
bInterfaceSubClass=audio.AUDIO_SUBCLASS_MIDI_STREAMING,
bInterfaceProtocol=audio.AUDIO_PROTOCOL_V1,
@@ -193,26 +210,23 @@ audio_midi_interface = standard.InterfaceDescriptor(
subdescriptors=[
midi.Header(
jacks_and_elements=[
- midi_in_jack,
- midi.InJackDescriptor(
- description="MIDI data in from user code.",
- bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0),
- midi_out_jack,
- midi.OutJackDescriptor(
- description="MIDI data out to user code.",
- bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0),
- ]
+ midi_in_jack_emb,
+ midi_in_jack_ext,
+ midi_out_jack_emb,
+ midi_out_jack_ext
+ ],
),
standard.EndpointDescriptor(
- description="MIDI data out",
+ description="MIDI data out to CircuitPython",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT,
bmAttributes=standard.EndpointDescriptor.TYPE_BULK),
- midi.DataEndpointDescriptor(baAssocJack=[midi_out_jack]),
+ midi.DataEndpointDescriptor(baAssocJack=[midi_in_jack_emb]),
standard.EndpointDescriptor(
- description="MIDI data in",
+ description="MIDI data in from CircuitPython",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
- bmAttributes=standard.EndpointDescriptor.TYPE_BULK),
- midi.DataEndpointDescriptor(baAssocJack=[midi_in_jack]),
+ bmAttributes=standard.EndpointDescriptor.TYPE_BULK,
+ bInterval = 0x0),
+ midi.DataEndpointDescriptor(baAssocJack=[midi_out_jack_emb]),
])
cs_ac_interface = audio10.AudioControlInterface(
@@ -234,12 +248,12 @@ audio_control_interface = standard.InterfaceDescriptor(
])
# Audio streaming interfaces must occur before MIDI ones.
-# audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces
+audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces
# This will renumber the endpoints to make them unique across descriptors,
# and renumber the interfaces in order. But we still need to fix up certain
# interface cross-references.
-interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces)
+interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces, audio_interfaces)
# Now adjust the CDC interface cross-references.
@@ -256,21 +270,13 @@ cdc_iad = standard.InterfaceAssociationDescriptor(
bFunctionSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model
bFunctionProtocol=cdc.CDC_PROTOCOL_NONE)
-# audio_iad = standard.InterfaceAssociationDescriptor(
-# description="Audio IAD",
-# bFirstInterface=audio_control_interface.bInterfaceNumber,
-# bInterfaceCount=len(audio_interfaces),
-# bFunctionClass=audio.AUDIO_CLASS_DEVICE,
-# bFunctionSubClass=audio.AUDIO_SUBCLASS_UNKNOWN,
-# bFunctionProtocol=audio.AUDIO_PROTOCOL_V1)
-
-
descriptor_list = []
descriptor_list.append(cdc_iad)
-# descriptor_list.append(audio_iad)
descriptor_list.extend(cdc_interfaces)
descriptor_list.extend(msc_interfaces)
-# descriptor_list.append(audio_control_interface)
+# Only add the control interface because other audio interfaces are managed by it to ensure the
+# correct ordering.
+descriptor_list.append(audio_control_interface)
# Put the CDC IAD just before the CDC interfaces.
# There appears to be a bug in the Windows composite USB driver that requests the
# HID report descriptor with the wrong interface number if the HID interface is not given
diff --git a/tools/usb_descriptor b/tools/usb_descriptor
-Subproject 57bf602dac9cba8c4226f764c286cbc60103d67
+Subproject e2e79566a807b7230dddbc53a103c19b2f65e2c