summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml200
-rw-r--r--.github/workflows/create_website_pr.yml38
-rw-r--r--.gitmodules3
-rwxr-xr-x.travis.yml145
-rw-r--r--README.rst2
-rw-r--r--conf.py27
-rw-r--r--docs/c2rst.py46
-rw-r--r--docs/library/network.rst1
-rw-r--r--docs/rstjinja.py24
-rw-r--r--docs/shared_bindings_matrix.py289
m---------frozen/Adafruit_CircuitPython_BusDevice0
m---------frozen/Adafruit_CircuitPython_CircuitPlayground0
m---------frozen/Adafruit_CircuitPython_Crickit0
m---------frozen/Adafruit_CircuitPython_IRRemote0
m---------frozen/Adafruit_CircuitPython_LIS3DH0
m---------frozen/Adafruit_CircuitPython_Thermistor0
m---------frozen/Adafruit_CircuitPython_seesaw0
m---------frozen/circuitpython-stage0
m---------lib/tinyusb0
-rw-r--r--lib/utils/buffer_helper.c4
-rw-r--r--lib/utils/buffer_helper.h3
-rw-r--r--locale/ID.po310
-rw-r--r--locale/circuitpython.pot308
-rw-r--r--locale/de_DE.po317
-rw-r--r--locale/en_US.po308
-rw-r--r--locale/en_x_pirate.po308
-rw-r--r--locale/es.po342
-rw-r--r--locale/fil.po311
-rw-r--r--locale/fr.po340
-rw-r--r--locale/it_IT.po320
-rw-r--r--locale/pl.po343
-rw-r--r--locale/pt_BR.po308
-rw-r--r--locale/zh_Latn_pinyin.po387
-rwxr-xr-xmain.c17
-rw-r--r--ports/atmel-samd/Makefile3
-rw-r--r--ports/atmel-samd/README.rst17
-rw-r--r--ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h4
-rw-r--r--ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h15
-rw-r--r--ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h2
-rw-r--r--ports/atmel-samd/audio_dma.c54
-rw-r--r--ports/atmel-samd/audio_dma.h10
-rw-r--r--ports/atmel-samd/background.c4
-rw-r--r--ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/board.c65
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h48
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk31
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/pins.c63
-rw-r--r--ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk7
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/board.c9
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h4
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/hallowing_m4_express/board.c99
-rw-r--r--ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.h39
-rw-r--r--ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk17
-rw-r--r--ports/atmel-samd/boards/hallowing_m4_express/pins.c71
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h1
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk8
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/boards/monster_m4sk/board.c100
-rw-r--r--ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h29
-rw-r--r--ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk16
-rw-r--r--ports/atmel-samd/boards/monster_m4sk/pins.c52
-rw-r--r--ports/atmel-samd/boards/pewpew_m4/board.c121
-rw-r--r--ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h51
-rw-r--r--ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk40
-rw-r--r--ports/atmel-samd/boards/pewpew_m4/pins.c45
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/pybadge/board.c9
-rw-r--r--ports/atmel-samd/boards/pybadge/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pybadge_airlift/board.c9
-rw-r--r--ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pygamer/board.c9
-rw-r--r--ports/atmel-samd/boards/pygamer/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pygamer_advance/board.c9
-rw-r--r--ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pyportal/board.c11
-rw-r--r--ports/atmel-samd/boards/pyportal/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/board.c131
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h39
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/pyportal_titano/pins.c94
-rw-r--r--ports/atmel-samd/boards/robohatmm1/pins.c88
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m0/board.c (renamed from ports/atmel-samd/boards/robohatmm1/board.c)0
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m0/mpconfigboard.h (renamed from ports/atmel-samd/boards/robohatmm1/mpconfigboard.h)18
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m0/mpconfigboard.mk (renamed from ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk)24
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m0/pins.c92
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m4/board.c39
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.h44
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk28
-rw-r--r--ports/atmel-samd/boards/robohatmm1_m4/pins.c92
-rw-r--r--ports/atmel-samd/boards/sam32/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/serpente/board.c37
-rw-r--r--ports/atmel-samd/boards/serpente/mpconfigboard.h39
-rw-r--r--ports/atmel-samd/boards/serpente/mpconfigboard.mk17
-rw-r--r--ports/atmel-samd/boards/serpente/pins.c40
-rw-r--r--ports/atmel-samd/boards/snekboard/board.c38
-rw-r--r--ports/atmel-samd/boards/snekboard/mpconfigboard.h35
-rw-r--r--ports/atmel-samd/boards/snekboard/mpconfigboard.mk20
-rw-r--r--ports/atmel-samd/boards/snekboard/pins.c28
-rwxr-xr-xports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/ugame10/board.c9
-rw-r--r--ports/atmel-samd/boards/ugame10/mpconfigboard.mk22
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/I2SOut.c2
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/PDMIn.c10
-rw-r--r--ports/atmel-samd/common-hal/audioio/AudioOut.c24
-rw-r--r--ports/atmel-samd/common-hal/busio/I2C.c9
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.c4
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.h1
-rw-r--r--ports/atmel-samd/common-hal/busio/UART.c8
-rw-r--r--ports/atmel-samd/common-hal/displayio/ParallelBus.c35
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseOut.c4
-rw-r--r--ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c2
-rw-r--r--ports/atmel-samd/common-hal/touchio/TouchIn.c11
-rw-r--r--ports/atmel-samd/common-hal/touchio/TouchIn.h5
-rw-r--r--ports/atmel-samd/mpconfigport.mk8
-rw-r--r--ports/atmel-samd/mphalport.c4
m---------ports/atmel-samd/peripherals0
-rw-r--r--ports/atmel-samd/supervisor/port.c6
-rw-r--r--ports/atmel-samd/tick.c12
-rwxr-xr-xports/nrf/Makefile14
-rw-r--r--ports/nrf/background.c17
-rw-r--r--ports/nrf/bluetooth/ble_uart.c18
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/board.c (renamed from supervisor/shared/usb/usb_desc.h)23
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h72
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk26
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/pins.c71
-rw-r--r--ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h2
-rw-r--r--ports/nrf/boards/make-pins.py208
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/board.c38
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h73
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk26
-rw-r--r--ports/nrf/boards/metro_nrf52840_express/pins.c56
-rw-r--r--ports/nrf/boards/particle_argon/mpconfigboard.h2
-rw-r--r--ports/nrf/boards/particle_boron/mpconfigboard.h2
-rw-r--r--ports/nrf/boards/particle_xenon/mpconfigboard.h2
-rw-r--r--ports/nrf/common-hal/_bleio/Adapter.c (renamed from ports/nrf/common-hal/bleio/Adapter.c)81
-rw-r--r--ports/nrf/common-hal/_bleio/Adapter.h (renamed from ports/nrf/common-hal/bleio/Adapter.h)0
-rw-r--r--ports/nrf/common-hal/_bleio/Attribute.c60
-rw-r--r--ports/nrf/common-hal/_bleio/Attribute.h34
-rw-r--r--ports/nrf/common-hal/_bleio/Central.c145
-rw-r--r--ports/nrf/common-hal/_bleio/Central.h (renamed from ports/nrf/common-hal/bleio/Central.h)7
-rw-r--r--ports/nrf/common-hal/_bleio/Characteristic.c299
-rw-r--r--ports/nrf/common-hal/_bleio/Characteristic.h (renamed from ports/nrf/common-hal/bleio/Characteristic.h)14
-rw-r--r--ports/nrf/common-hal/_bleio/CharacteristicBuffer.c (renamed from ports/nrf/common-hal/bleio/CharacteristicBuffer.c)6
-rw-r--r--ports/nrf/common-hal/_bleio/CharacteristicBuffer.h (renamed from ports/nrf/common-hal/bleio/CharacteristicBuffer.h)2
-rw-r--r--ports/nrf/common-hal/_bleio/Descriptor.c143
-rw-r--r--ports/nrf/common-hal/_bleio/Descriptor.h (renamed from ports/nrf/common-hal/bleio/Descriptor.h)13
-rw-r--r--ports/nrf/common-hal/_bleio/Peripheral.c (renamed from ports/nrf/common-hal/bleio/Peripheral.c)212
-rw-r--r--ports/nrf/common-hal/_bleio/Peripheral.h (renamed from ports/nrf/common-hal/bleio/Peripheral.h)19
-rw-r--r--ports/nrf/common-hal/_bleio/Scanner.c (renamed from ports/nrf/common-hal/bleio/Scanner.c)8
-rw-r--r--ports/nrf/common-hal/_bleio/Scanner.h (renamed from ports/nrf/common-hal/bleio/Scanner.h)0
-rw-r--r--ports/nrf/common-hal/_bleio/Service.c122
-rw-r--r--ports/nrf/common-hal/_bleio/Service.h (renamed from ports/nrf/common-hal/bleio/Service.h)4
-rw-r--r--ports/nrf/common-hal/_bleio/UUID.c (renamed from ports/nrf/common-hal/bleio/UUID.c)4
-rw-r--r--ports/nrf/common-hal/_bleio/UUID.h (renamed from ports/nrf/common-hal/bleio/UUID.h)0
-rw-r--r--ports/nrf/common-hal/_bleio/__init__.c (renamed from ports/nrf/common-hal/bleio/Central.c)327
-rw-r--r--ports/nrf/common-hal/_bleio/__init__.h (renamed from ports/nrf/common-hal/bleio/__init__.h)12
-rw-r--r--ports/nrf/common-hal/analogio/AnalogIn.c5
-rw-r--r--ports/nrf/common-hal/audiobusio/I2SOut.c328
-rw-r--r--ports/nrf/common-hal/audiobusio/I2SOut.h63
-rw-r--r--ports/nrf/common-hal/audiobusio/PDMIn.c130
-rw-r--r--ports/nrf/common-hal/audiobusio/PDMIn.h40
-rw-r--r--ports/nrf/common-hal/audiobusio/__init__.c0
-rw-r--r--ports/nrf/common-hal/audiopwmio/PWMAudioOut.c316
-rw-r--r--ports/nrf/common-hal/audiopwmio/PWMAudioOut.h59
-rw-r--r--ports/nrf/common-hal/audiopwmio/__init__.c0
-rw-r--r--ports/nrf/common-hal/bleio/Characteristic.c329
-rw-r--r--ports/nrf/common-hal/bleio/Service.c126
-rw-r--r--ports/nrf/common-hal/bleio/__init__.c68
-rw-r--r--ports/nrf/common-hal/busio/I2C.c17
-rw-r--r--ports/nrf/common-hal/busio/SPI.c2
-rw-r--r--ports/nrf/common-hal/busio/UART.c12
-rw-r--r--ports/nrf/common-hal/displayio/ParallelBus.c36
-rw-r--r--ports/nrf/common-hal/microcontroller/Pin.c2
-rw-r--r--ports/nrf/common-hal/microcontroller/__init__.c9
-rw-r--r--ports/nrf/common-hal/neopixel_write/__init__.c4
-rw-r--r--ports/nrf/common-hal/pulseio/PWMOut.c114
-rw-r--r--ports/nrf/common-hal/pulseio/PWMOut.h3
-rw-r--r--ports/nrf/common-hal/pulseio/PulseOut.c4
-rw-r--r--ports/nrf/device/nrf52/startup_nrf52840.c2
-rw-r--r--ports/nrf/mpconfigport.h5
-rw-r--r--ports/nrf/mpconfigport.mk9
-rw-r--r--ports/nrf/mphalport.c4
-rw-r--r--ports/nrf/nrfx_config.h5
-rw-r--r--ports/nrf/peripherals/nrf/clocks.c8
-rw-r--r--ports/nrf/peripherals/nrf/timers.c2
-rw-r--r--ports/nrf/sd_mutex.c4
-rw-r--r--ports/nrf/supervisor/port.c19
-rw-r--r--ports/stm32f4/.gitignore9
-rwxr-xr-xports/stm32f4/Makefile261
-rw-r--r--ports/stm32f4/README.md3
-rw-r--r--ports/stm32f4/background.c60
-rw-r--r--ports/stm32f4/background.h (renamed from shared-bindings/bleio/__init__.h)13
-rw-r--r--ports/stm32f4/boards/STM32F405.ld108
-rw-r--r--ports/stm32f4/boards/STM32F411VETx_FLASH.ld109
-rw-r--r--ports/stm32f4/boards/STM32F412ZGTx_FLASH.ld105
-rw-r--r--ports/stm32f4/boards/board.h45
-rw-r--r--ports/stm32f4/boards/feather_f405/board.c38
-rw-r--r--ports/stm32f4/boards/feather_f405/mpconfigboard.h43
-rw-r--r--ports/stm32f4/boards/feather_f405/mpconfigboard.mk19
-rw-r--r--ports/stm32f4/boards/feather_f405/pins.c29
-rw-r--r--ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h440
-rw-r--r--ports/stm32f4/boards/pyboard_v11/board.c38
-rw-r--r--ports/stm32f4/boards/pyboard_v11/mpconfigboard.h (renamed from ports/nrf/common-hal/bleio/Descriptor.c)21
-rw-r--r--ports/stm32f4/boards/pyboard_v11/mpconfigboard.mk17
-rw-r--r--ports/stm32f4/boards/pyboard_v11/pins.c50
-rw-r--r--ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h440
-rw-r--r--ports/stm32f4/boards/startup_stm32f405xx.s516
-rw-r--r--ports/stm32f4/boards/startup_stm32f411xe.s452
-rw-r--r--ports/stm32f4/boards/startup_stm32f412zx.s524
-rw-r--r--ports/stm32f4/boards/stm32f411ve_discovery/board.c38
-rw-r--r--ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h40
-rw-r--r--ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.mk17
-rw-r--r--ports/stm32f4/boards/stm32f411ve_discovery/pins.c106
-rw-r--r--ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h439
-rw-r--r--ports/stm32f4/boards/stm32f412zg_discovery/board.c38
-rw-r--r--ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h38
-rw-r--r--ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.mk22
-rw-r--r--ports/stm32f4/boards/stm32f412zg_discovery/pins.c92
-rw-r--r--ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h438
-rw-r--r--ports/stm32f4/common-hal/analogio/AnalogIn.c129
-rw-r--r--ports/stm32f4/common-hal/analogio/AnalogIn.h48
-rw-r--r--ports/stm32f4/common-hal/analogio/AnalogOut.c57
-rw-r--r--ports/stm32f4/common-hal/analogio/AnalogOut.h42
-rw-r--r--ports/stm32f4/common-hal/analogio/__init__.c1
-rw-r--r--ports/stm32f4/common-hal/board/__init__.c25
-rw-r--r--ports/stm32f4/common-hal/busio/I2C.c231
-rw-r--r--ports/stm32f4/common-hal/busio/I2C.h48
-rw-r--r--ports/stm32f4/common-hal/busio/OneWire.h33
-rw-r--r--ports/stm32f4/common-hal/busio/SPI.c415
-rw-r--r--ports/stm32f4/common-hal/busio/SPI.h55
-rw-r--r--ports/stm32f4/common-hal/busio/UART.c80
-rw-r--r--ports/stm32f4/common-hal/busio/UART.h46
-rw-r--r--ports/stm32f4/common-hal/busio/__init__.c1
-rw-r--r--ports/stm32f4/common-hal/digitalio/DigitalInOut.c160
-rw-r--r--ports/stm32f4/common-hal/digitalio/DigitalInOut.h38
-rw-r--r--ports/stm32f4/common-hal/digitalio/__init__.c1
-rw-r--r--ports/stm32f4/common-hal/microcontroller/Pin.c94
-rw-r--r--ports/stm32f4/common-hal/microcontroller/Pin.h44
-rw-r--r--ports/stm32f4/common-hal/microcontroller/Processor.c48
-rw-r--r--ports/stm32f4/common-hal/microcontroller/Processor.h39
-rw-r--r--ports/stm32f4/common-hal/microcontroller/__init__.c205
-rw-r--r--ports/stm32f4/common-hal/os/__init__.c66
-rwxr-xr-xports/stm32f4/common-hal/supervisor/Runtime.c38
-rwxr-xr-xports/stm32f4/common-hal/supervisor/Runtime.h37
-rwxr-xr-xports/stm32f4/common-hal/supervisor/__init__.c40
-rw-r--r--ports/stm32f4/common-hal/time/__init__.c37
-rw-r--r--ports/stm32f4/fatfs_port.c33
-rw-r--r--ports/stm32f4/mpconfigport.h45
-rw-r--r--ports/stm32f4/mpconfigport.mk29
-rw-r--r--ports/stm32f4/mphalport.c52
-rw-r--r--ports/stm32f4/mphalport.h45
-rw-r--r--ports/stm32f4/peripherals/stm32f4/clocks.h27
-rw-r--r--ports/stm32f4/peripherals/stm32f4/gpio.h28
-rw-r--r--ports/stm32f4/peripherals/stm32f4/periph.h114
-rw-r--r--ports/stm32f4/peripherals/stm32f4/pins.h89
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f405xx/clocks.c63
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f405xx/gpio.c56
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c88
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h45
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.c161
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.h158
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c61
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c169
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c122
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h44
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.c123
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.h121
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f412zx/clocks.c74
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f412zx/gpio.c243
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c123
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h45
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.c161
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.h158
-rw-r--r--ports/stm32f4/qstrdefsport.h1
m---------ports/stm32f4/stm32f40
-rwxr-xr-xports/stm32f4/supervisor/cpu.s27
-rw-r--r--ports/stm32f4/supervisor/internal_flash.c204
-rw-r--r--ports/stm32f4/supervisor/internal_flash.h58
-rw-r--r--ports/stm32f4/supervisor/internal_flash_root_pointers.h31
-rw-r--r--ports/stm32f4/supervisor/port.c85
-rw-r--r--ports/stm32f4/supervisor/qspi_flash.c162
-rw-r--r--ports/stm32f4/supervisor/serial.c75
-rw-r--r--ports/stm32f4/supervisor/usb.c85
-rw-r--r--ports/stm32f4/system_stm32f4xx.c761
-rw-r--r--ports/stm32f4/tick.c90
-rw-r--r--ports/stm32f4/tick.h46
-rw-r--r--py/circuitpy_defns.mk103
-rw-r--r--py/circuitpy_mpconfig.h41
-rw-r--r--py/circuitpy_mpconfig.mk92
-rw-r--r--py/makeqstrdata.py4
-rw-r--r--py/obj.c3
-rw-r--r--py/obj.h2
-rw-r--r--py/objlist.c5
-rw-r--r--py/objstr.c14
-rw-r--r--py/objstr.h3
-rw-r--r--py/objtuple.c3
-rw-r--r--py/stream.c3
-rw-r--r--shared-bindings/_bleio/Adapter.c (renamed from shared-bindings/bleio/Adapter.c)52
-rw-r--r--shared-bindings/_bleio/Adapter.h (renamed from shared-bindings/bleio/Adapter.h)5
-rw-r--r--shared-bindings/_bleio/Address.c (renamed from shared-bindings/bleio/Address.c)53
-rw-r--r--shared-bindings/_bleio/Address.h (renamed from shared-bindings/bleio/Address.h)2
-rw-r--r--shared-bindings/_bleio/Attribute.c94
-rw-r--r--shared-bindings/_bleio/Attribute.h (renamed from shared-module/bleio/Characteristic.h)23
-rw-r--r--shared-bindings/_bleio/Central.c (renamed from shared-bindings/bleio/Central.c)116
-rw-r--r--shared-bindings/_bleio/Central.h (renamed from shared-bindings/bleio/Central.h)9
-rw-r--r--shared-bindings/_bleio/Characteristic.c341
-rw-r--r--shared-bindings/_bleio/Characteristic.h (renamed from shared-bindings/bleio/Characteristic.h)11
-rw-r--r--shared-bindings/_bleio/CharacteristicBuffer.c (renamed from shared-bindings/bleio/CharacteristicBuffer.c)8
-rw-r--r--shared-bindings/_bleio/CharacteristicBuffer.h (renamed from shared-bindings/bleio/CharacteristicBuffer.h)2
-rw-r--r--shared-bindings/_bleio/Descriptor.c231
-rw-r--r--shared-bindings/_bleio/Descriptor.h (renamed from shared-bindings/bleio/Descriptor.h)32
-rw-r--r--shared-bindings/_bleio/Peripheral.c (renamed from shared-bindings/bleio/Peripheral.c)168
-rw-r--r--shared-bindings/_bleio/Peripheral.h (renamed from shared-bindings/bleio/Peripheral.h)11
-rw-r--r--shared-bindings/_bleio/ScanEntry.c (renamed from shared-bindings/bleio/ScanEntry.c)14
-rw-r--r--shared-bindings/_bleio/ScanEntry.h (renamed from shared-bindings/bleio/ScanEntry.h)2
-rw-r--r--shared-bindings/_bleio/Scanner.c (renamed from shared-bindings/bleio/Scanner.c)10
-rw-r--r--shared-bindings/_bleio/Scanner.h (renamed from shared-bindings/bleio/Scanner.h)2
-rw-r--r--shared-bindings/_bleio/Service.c (renamed from shared-bindings/bleio/Service.c)117
-rw-r--r--shared-bindings/_bleio/Service.h (renamed from shared-bindings/bleio/Service.h)8
-rw-r--r--shared-bindings/_bleio/UUID.c (renamed from shared-bindings/bleio/UUID.c)4
-rw-r--r--shared-bindings/_bleio/UUID.h (renamed from shared-bindings/bleio/UUID.h)2
-rw-r--r--shared-bindings/_bleio/__init__.c107
-rw-r--r--shared-bindings/_bleio/__init__.h52
-rw-r--r--shared-bindings/_stage/__init__.c20
-rw-r--r--shared-bindings/audiobusio/I2SOut.c9
-rw-r--r--shared-bindings/audiocore/RawSample.c (renamed from shared-bindings/audioio/RawSample.c)7
-rw-r--r--shared-bindings/audiocore/RawSample.h (renamed from shared-bindings/audioio/RawSample.h)3
-rw-r--r--shared-bindings/audiocore/WaveFile.c (renamed from shared-bindings/audioio/WaveFile.c)30
-rw-r--r--shared-bindings/audiocore/WaveFile.h (renamed from shared-bindings/audioio/WaveFile.h)7
-rw-r--r--shared-bindings/audiocore/__init__.c67
-rw-r--r--shared-bindings/audiocore/__init__.h34
-rw-r--r--shared-bindings/audioio/AudioOut.c9
-rw-r--r--shared-bindings/audioio/AudioOut.h2
-rw-r--r--shared-bindings/audioio/__init__.c28
-rw-r--r--shared-bindings/audiomixer/Mixer.c (renamed from shared-bindings/audioio/Mixer.c)213
-rw-r--r--shared-bindings/audiomixer/Mixer.h (renamed from shared-bindings/audioio/Mixer.h)37
-rw-r--r--shared-bindings/audiomixer/MixerVoice.c178
-rw-r--r--shared-bindings/audiomixer/MixerVoice.h47
-rw-r--r--shared-bindings/audiomixer/__init__.c62
-rw-r--r--shared-bindings/audiomixer/__init__.h34
-rw-r--r--shared-bindings/audiopwmio/PWMAudioOut.c294
-rw-r--r--shared-bindings/audiopwmio/PWMAudioOut.h49
-rw-r--r--shared-bindings/audiopwmio/__init__.c71
-rw-r--r--shared-bindings/audiopwmio/__init__.h34
-rw-r--r--shared-bindings/bitbangio/I2C.c123
-rw-r--r--shared-bindings/bitbangio/SPI.c4
-rw-r--r--shared-bindings/bleio/Characteristic.c334
-rw-r--r--shared-bindings/bleio/Descriptor.c180
-rw-r--r--shared-bindings/bleio/__init__.c96
-rw-r--r--shared-bindings/busio/I2C.c117
-rw-r--r--shared-bindings/busio/I2C.h3
-rw-r--r--shared-bindings/busio/SPI.c8
-rw-r--r--shared-bindings/displayio/ColorConverter.c53
-rw-r--r--shared-bindings/displayio/ColorConverter.h9
-rw-r--r--shared-bindings/displayio/Display.c196
-rw-r--r--shared-bindings/displayio/Display.h43
-rw-r--r--shared-bindings/displayio/EPaperDisplay.c313
-rw-r--r--shared-bindings/displayio/EPaperDisplay.h61
-rw-r--r--shared-bindings/displayio/FourWire.c50
-rw-r--r--shared-bindings/displayio/FourWire.h7
-rw-r--r--shared-bindings/displayio/Group.c27
-rw-r--r--shared-bindings/displayio/Group.h2
-rw-r--r--shared-bindings/displayio/I2CDisplay.c152
-rw-r--r--shared-bindings/displayio/I2CDisplay.h51
-rw-r--r--shared-bindings/displayio/Palette.c27
-rw-r--r--shared-bindings/displayio/Palette.h2
-rw-r--r--shared-bindings/displayio/ParallelBus.c24
-rw-r--r--shared-bindings/displayio/ParallelBus.h8
-rw-r--r--shared-bindings/displayio/TileGrid.c32
-rw-r--r--shared-bindings/displayio/TileGrid.h5
-rw-r--r--shared-bindings/displayio/__init__.c8
-rw-r--r--shared-bindings/displayio/__init__.h18
-rw-r--r--shared-bindings/i2cslave/I2CSlave.c6
-rw-r--r--shared-bindings/index.rst61
-rw-r--r--shared-bindings/support_matrix.rst16
-rw-r--r--shared-bindings/time/__init__.c35
-rw-r--r--shared-bindings/touchio/TouchIn.c3
-rw-r--r--shared-bindings/touchio/TouchIn.h5
-rw-r--r--shared-module/_bleio/Address.c (renamed from shared-module/bleio/Address.c)4
-rw-r--r--shared-module/_bleio/Address.h (renamed from shared-module/bleio/Address.h)0
-rw-r--r--shared-module/_bleio/Attribute.c46
-rw-r--r--shared-module/_bleio/Attribute.h41
-rw-r--r--shared-module/_bleio/Characteristic.h43
-rw-r--r--shared-module/_bleio/ScanEntry.c (renamed from shared-module/bleio/ScanEntry.c)6
-rw-r--r--shared-module/_bleio/ScanEntry.h (renamed from shared-module/bleio/ScanEntry.h)2
-rw-r--r--shared-module/_stage/__init__.c60
-rw-r--r--shared-module/_stage/__init__.h2
-rw-r--r--shared-module/audiocore/RawSample.c (renamed from shared-module/audioio/RawSample.c)4
-rw-r--r--shared-module/audiocore/RawSample.h (renamed from shared-module/audioio/RawSample.h)2
-rw-r--r--shared-module/audiocore/WaveFile.c (renamed from shared-module/audioio/WaveFile.c)39
-rw-r--r--shared-module/audiocore/WaveFile.h (renamed from shared-module/audioio/WaveFile.h)3
-rw-r--r--shared-module/audiocore/__init__.c138
-rw-r--r--shared-module/audiocore/__init__.h53
-rw-r--r--shared-module/audioio/__init__.c125
-rw-r--r--shared-module/audioio/__init__.h23
-rw-r--r--shared-module/audiomixer/Mixer.c (renamed from shared-module/audioio/Mixer.c)283
-rw-r--r--shared-module/audiomixer/Mixer.h (renamed from shared-module/audioio/Mixer.h)28
-rw-r--r--shared-module/audiomixer/MixerVoice.c87
-rw-r--r--shared-module/audiomixer/MixerVoice.h46
-rw-r--r--shared-module/audiomixer/__init__.c0
-rw-r--r--shared-module/audiomixer/__init__.h (renamed from shared-module/bleio/__init__.h)14
-rw-r--r--shared-module/audiopwmio/__init__.c0
-rw-r--r--shared-module/audiopwmio/__init__.h32
-rw-r--r--shared-module/board/__init__.c41
-rw-r--r--shared-module/displayio/Bitmap.c38
-rw-r--r--shared-module/displayio/Bitmap.h5
-rw-r--r--shared-module/displayio/ColorConverter.c160
-rw-r--r--shared-module/displayio/ColorConverter.h12
-rw-r--r--shared-module/displayio/Display.c414
-rw-r--r--shared-module/displayio/Display.h38
-rw-r--r--shared-module/displayio/EPaperDisplay.c385
-rw-r--r--shared-module/displayio/EPaperDisplay.h68
-rw-r--r--shared-module/displayio/FourWire.c45
-rw-r--r--shared-module/displayio/FourWire.h6
-rw-r--r--shared-module/displayio/Group.c47
-rw-r--r--shared-module/displayio/Group.h15
-rw-r--r--shared-module/displayio/I2CDisplay.c123
-rw-r--r--shared-module/displayio/I2CDisplay.h41
-rw-r--r--shared-module/displayio/OnDiskBitmap.c47
-rw-r--r--shared-module/displayio/Palette.c66
-rw-r--r--shared-module/displayio/Palette.h42
-rw-r--r--shared-module/displayio/TileGrid.c173
-rw-r--r--shared-module/displayio/TileGrid.h28
-rw-r--r--shared-module/displayio/__init__.c219
-rw-r--r--shared-module/displayio/__init__.h10
-rw-r--r--shared-module/displayio/display_core.c335
-rw-r--r--shared-module/displayio/display_core.h88
-rw-r--r--shared-module/os/__init__.c1
-rw-r--r--shared-module/terminalio/Terminal.c8
-rw-r--r--shared-module/touchio/TouchIn.c (renamed from ports/nrf/common-hal/touchio/TouchIn.c)33
-rw-r--r--shared-module/touchio/TouchIn.h (renamed from ports/nrf/common-hal/touchio/TouchIn.h)9
-rw-r--r--shared-module/touchio/__init__.c (renamed from ports/nrf/common-hal/touchio/__init__.c)0
-rw-r--r--shared-module/usb_hid/Device.c12
-rw-r--r--shared-module/usb_hid/__init__.c129
-rw-r--r--shared-module/usb_midi/PortOut.c2
-rw-r--r--supervisor/shared/display.c69
-rw-r--r--supervisor/shared/display.h3
-rw-r--r--supervisor/shared/external_flash/devices.h21
-rw-r--r--supervisor/shared/external_flash/external_flash.c1
-rw-r--r--supervisor/shared/rgb_led_status.c49
-rw-r--r--supervisor/shared/rgb_led_status.h2
-rw-r--r--supervisor/shared/status_leds.c2
-rw-r--r--supervisor/shared/usb/tusb_config.h2
-rw-r--r--supervisor/shared/usb/usb.c5
-rw-r--r--supervisor/shared/usb/usb_desc.c42
-rw-r--r--supervisor/shared/usb/usb_msc_flash.c96
-rw-r--r--supervisor/stub/internal_flash.c66
-rw-r--r--supervisor/supervisor.mk25
-rw-r--r--tools/build_board_info.py37
-rwxr-xr-xtools/build_release_files.py34
-rw-r--r--tools/check_translations.py4
-rw-r--r--tools/ci_new_boards_check.py51
-rw-r--r--tools/convert_release_notes.py5
-rw-r--r--tools/gen_display_resources.py25
-rw-r--r--tools/gen_usb_descriptor.py214
-rw-r--r--tools/hid_report_descriptors.py467
-rwxr-xr-xtools/preprocess_frozen_modules.py5
-rwxr-xr-xtools/upload_release_files.py35
475 files changed, 26159 insertions, 5523 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..8c1f46f6f
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,200 @@
+name: Build CI
+
+on: [push, pull_request, release]
+
+jobs:
+ test:
+ runs-on: ubuntu-16.04
+ steps:
+ - name: Dump GitHub context
+ env:
+ GITHUB_CONTEXT: ${{ toJson(github) }}
+ run: echo "$GITHUB_CONTEXT"
+ - name: Fail if not a release publish # workaround has `on` doesn't have this filter
+ run: exit 1
+ if: github.event_name == 'release' && (github.event.action != 'published' && github.event.action != 'rerequested')
+ - name: Set up Python 3.5
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.5
+ - name: Install deps
+ run: |
+ sudo apt-get install -y gettext librsvg2-bin
+ pip install requests sh click setuptools cpp-coveralls Sphinx sphinx-rtd-theme recommonmark sphinxcontrib-svg2pdfconverter polib pyyaml
+ - name: Versions
+ run: |
+ gcc --version
+ python3 --version
+ - uses: actions/checkout@v1
+ with:
+ submodules: true
+ - name: CircuitPython version
+ run: git describe --dirty --always --tags
+ - name: Build mpy-cross
+ run: make -C mpy-cross -j2
+ - name: Build unix port
+ run: |
+ make -C ports/unix deplibs -j2
+ make -C ports/unix -j2
+ make -C ports/unix coverage -j2
+ - name: Test all
+ run: MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1
+ working-directory: tests
+ - name: Print failure info
+ run: |
+ for exp in *.exp;
+ do testbase=$(basename $exp .exp);
+ echo -e "\nFAILURE $testbase";
+ diff -u $testbase.exp $testbase.out;
+ done
+ working-directory: tests
+ if: failure()
+ - name: Test threads
+ run: MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 -d thread
+ working-directory: tests
+ - name: Native Tests
+ run: MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --emit native
+ working-directory: tests
+ - name: mpy Tests
+ run: MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float
+ working-directory: tests
+ - name: Docs
+ run: sphinx-build -E -W -b html . _build/html
+ - name: Translations
+ run: make check-translate
+ - name: New boards check
+ run: python3 -u ci_new_boards_check.py
+ working-directory: tools
+
+ build-arm:
+ runs-on: ubuntu-16.04
+ needs: test
+ strategy:
+ fail-fast: false
+ matrix:
+ board:
+ - "arduino_mkr1300"
+ - "arduino_mkrzero"
+ - "arduino_zero"
+ - "bast_pro_mini_m0"
+ - "capablerobot_usbhub"
+ - "catwan_usbstick"
+ - "circuitplayground_bluefruit"
+ - "circuitplayground_express"
+ - "circuitplayground_express_crickit"
+ - "circuitplayground_express_displayio"
+ - "cp32-m4"
+ - "datalore_ip_m4"
+ - "datum_distance"
+ - "datum_imu"
+ - "datum_light"
+ - "datum_weather"
+ - "electronut_labs_blip"
+ - "electronut_labs_papyr"
+ - "escornabot_makech"
+ - "feather_f405"
+ - "feather_m0_adalogger"
+ - "feather_m0_basic"
+ - "feather_m0_express"
+ - "feather_m0_express_crickit"
+ - "feather_m0_rfm69"
+ - "feather_m0_rfm9x"
+ - "feather_m0_supersized"
+ - "feather_m4_express"
+ - "feather_nrf52840_express"
+ - "feather_radiofruit_zigbee"
+ - "gemma_m0"
+ - "grandcentral_m4_express"
+ - "hallowing_m0_express"
+ - "hallowing_m4_express"
+ - "itsybitsy_m0_express"
+ - "itsybitsy_m4_express"
+ - "kicksat-sprite"
+ - "makerdiary_nrf52840_mdk"
+ - "makerdiary_nrf52840_mdk_usb_dongle"
+ - "meowmeow"
+ - "metro_m0_express"
+ - "metro_m4_airlift_lite"
+ - "metro_m4_express"
+ - "metro_nrf52840_express"
+ - "mini_sam_m4"
+ - "monster_m4sk"
+ - "particle_argon"
+ - "particle_boron"
+ - "particle_xenon"
+ - "pca10056"
+ - "pca10059"
+ - "pewpew10"
+ - "pewpew_m4"
+ - "pirkey_m0"
+ - "pybadge"
+ - "pybadge_airlift"
+ - "pyboard_v11"
+ - "pygamer"
+ - "pygamer_advance"
+ - "pyportal"
+ - "pyportal_titano"
+ - "pyruler"
+ - "robohatmm1_m0"
+ - "robohatmm1_m4"
+ - "sam32"
+ - "serpente"
+ - "snekboard"
+ - "sparkfun_lumidrive"
+ - "sparkfun_nrf52840_mini"
+ - "sparkfun_redboard_turbo"
+ - "sparkfun_samd21_dev"
+ - "sparkfun_samd21_mini"
+ - "stm32f411ve_discovery"
+ - "stm32f412zg_discovery"
+ - "trellis_m4_express"
+ - "trinket_m0"
+ - "trinket_m0_haxpress"
+ - "uchip"
+ - "ugame10"
+
+ steps:
+ - name: Set up Python 3.5
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.5
+ - name: Install deps
+ run: |
+ sudo apt-get install -y gettext
+ pip install requests sh click setuptools awscli
+ wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2018q2-1~xenial1_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb
+ - name: Versions
+ run: |
+ gcc --version
+ arm-none-eabi-gcc --version
+ python3 --version
+ - uses: actions/checkout@v1
+ with:
+ submodules: true
+ - name: mpy-cross
+ run: make -C mpy-cross -j2
+ - name: build
+ run: python3 -u build_release_files.py
+ working-directory: tools
+ env:
+ BOARDS: ${{ matrix.board }}
+ - uses: actions/upload-artifact@v1.0.0
+ with:
+ name: ${{ matrix.board }}
+ path: bin/${{ matrix.board }}
+ - name: Upload to S3
+ run: aws s3 cp bin/ s3://adafruit-circuit-python/bin/ --recursive --no-progress --region us-east-1
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ if: github.event_name == 'push' || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
+ - name: Install upload deps
+ run: |
+ pip install uritemplate
+ - name: Upload to Release
+ run: python3 -u upload_release_files.py
+ working-directory: tools
+ env:
+ UPLOAD_URL: ${{ github.event.release.upload_url }}
+ ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.BLINKA_GITHUB_ACCESS_TOKEN }}
+ if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')
diff --git a/.github/workflows/create_website_pr.yml b/.github/workflows/create_website_pr.yml
new file mode 100644
index 000000000..ce9323702
--- /dev/null
+++ b/.github/workflows/create_website_pr.yml
@@ -0,0 +1,38 @@
+name: Update CircuitPython.org
+
+on: release
+
+jobs:
+ website:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Dump GitHub context
+ env:
+ GITHUB_CONTEXT: ${{ toJson(github) }}
+ run: echo "$GITHUB_CONTEXT"
+ - name: Fail if not a release publish # workaround has `on` doesn't have this filter
+ run: exit 1
+ if: github.event.action != 'published'
+ - name: Set up Python 3.5
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.5
+ - name: Install deps
+ run: |
+ pip install requests sh click
+ - name: Versions
+ run: |
+ gcc --version
+ python3 --version
+ - uses: actions/checkout@v1
+ with:
+ submodules: true
+ - name: CircuitPython version
+ run: git describe --dirty --always --tags
+ - name: Website
+ run: python3 build_board_info.py
+ working-directory: tools
+ env:
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
+ ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.BLINKA_GITHUB_ACCESS_TOKEN }}
+ if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')
diff --git a/.gitmodules b/.gitmodules
index 163d45fcd..7b57cab54 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -95,3 +95,6 @@
[submodule "frozen/circuitpython-stage"]
path = frozen/circuitpython-stage
url = https://github.com/python-ugame/circuitpython-stage.git
+[submodule "ports/stm32f4/stm32f4"]
+ path = ports/stm32f4/stm32f4
+ url = https://github.com/adafruit/stm32f4.git
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100755
index d75b4e7d4..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,145 +0,0 @@
-sudo: required
-dist: xenial
-language: c
-compiler:
- - gcc
-git:
- depth: 6
-
-# Each item under 'env' is a separate Travis job to execute.
-# They run in separate environments, so each one must take the time
-# to clone the repository and submodules; to download and install SDKs,
-# pip packages, and so forth. By gathering activities together in optimal
-# ways, the "run time" and "total time" of the travis jobs can be minimized.
-#
-# Since at the time of writing Travis generally starts 5 or 6 jobs, the
-# builds have been organized into 5 groups of *approximately* equal durations.
-# Additionally, the jobs that need extra SDKs are also organized together.
-#
-# When adding new boards, take a look on the travis CI page
-# https://travis-ci.org/adafruit/circuitpython to which build that installs
-# that SDK is shortest and add it there. In the case of major re-organizations,
-# just try to make the builds "about equal in run time"
-env:
- - TRAVIS_TESTS="unix docs translations website" TRAVIS_BOARDS="circuitplayground_express mini_sam_m4 grandcentral_m4_express capablerobot_usbhub pygamer pca10056 pca10059 feather_nrf52840_express makerdiary_nrf52840_mdk makerdiary_nrf52840_mdk_usb_dongle particle_boron particle_argon particle_xenon sparkfun_nrf52840_mini electronut_labs_papyr electronut_labs_blip" TRAVIS_SDK=arm:nrf
- - TRAVIS_BOARDS="metro_m0_express metro_m4_express metro_m4_airlift_lite pirkey_m0 trellis_m4_express trinket_m0 sparkfun_lumidrive sparkfun_redboard_turbo bast_pro_mini_m0 datum_distance pyruler" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow sam32 uchip escornabot_makech pygamer_advance datum_imu" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300 arduino_mkrzero pewpew10 kicksat-sprite ugame10 robohatmm1 datum_light" TRAVIS_SDK=arm
- - TRAVIS_BOARDS="circuitplayground_express_crickit feather_m0_adalogger feather_m0_basic feather_m0_express catwan_usbstick pyportal sparkfun_samd21_mini sparkfun_samd21_dev pybadge pybadge_airlift datum_weather" TRAVIS_SDK=arm
-
-addons:
- artifacts:
- paths:
- - $(ls -d1 bin/*/*/* | tr "\n" ":")
- target_paths: /
-
-# Some deploy jobs take over 10 minutes so use this keep alive hack to make sure Travis doesn't kill us.
-before_deploy: |
- function keep_alive() {
- while true; do
- echo -en "\a"
- sleep 5
- done
- }
- keep_alive &
-
-deploy:
- provider: releases
- api_key:
- secure: "jdqVFw6itRY4qwQF4ReXo0uaymT+Mob6RhYX0lw8KWFNqBgHnLVuKmKKcGMEuRvBVMPkvxF7bMuOQzSBOunqwlHFse3oMzdWvQODv1zwV7pSRXGwTdIvTPbBjKWxnBG9uSNRf2R5AMflJFUxy2CbtBpgvNzr+4VLREZDrrjEu8C1iTtXGpSm5AQ5iIp2fkMAWD85FP7CQPpkqRoxhSIFZmTdurfYRmenq1OZ/4SeD5TESKcyvqJNzVT9z210B3cg3eAkP6ukvelW4qE2zgIANqUkGqvDEnAvEII9M89kuwhCMAekdfwnUSPrry+g77i1dUZHoRN1+MFj+waYtPaqxdYo2G1sysa6enxlu4jHMR5MfMk9eKHgaNgL3PiyANusYSS44amh8QIiVaX5nw82myZDCpQOZW7YqJKE6WX70Lbs4mS+wIs+ig4KIXO1B0p9kMb0OeVjHRl+KcXsWGRu/ECG/ExpqlVIssSPU407LohMXT2cJ37CY/R/EeK2XSDsQ2M3L3EAGUjCJdBGuwsOJ+2lG+HQpAVu9vAB4kq5jy9Ye+MG+8Xlkly3XZZ5+FkXyYxKnXb26/QVv0e5sIG5OmdJCPYFaH2J1QdKo7CdhEcBtrf6DMPWaimGMldShFqzLjOz3b3qLysRxFF0aGb7ipKPa57vawNzYHoPAViOcXQ="
- file_glob: true
- file: "$TRAVIS_BUILD_DIR/bin/*/*/*"
- skip_cleanup: true
- on:
- tags: true
-
-notifications:
- webhooks:
- urls:
- - https://rosie-ci.ngrok.io/travis
- on_success: always
- on_failure: always
- on_start: always
- on_cancel: always
- on_error: always
-
-before_script:
- # Expand the git tree back to 4.0.0-alpha.1 and then fetch the latest tag.
- - LAST_TAG=`git ls-remote --quiet --tags --sort=version:refname | egrep -o "refs/tags/[0-9]+.*\$" | tail -n 1`
- - git fetch --depth 1 origin $LAST_TAG:$LAST_TAG
- - git describe --dirty --always --tags
- - function var_search () { case "$1" in *$2*) true;; *) false;; esac; }
- - sudo dpkg --add-architecture i386
-
-
- - (! var_search "${TRAVIS_SDK-}" arm || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2018q2-1~xenial1_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb))
-
- # For huzzah builds
- - (! var_search "${TRAVIS_SDK-}" esp8266 || (wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz && tar -C .. -xaf xtensa-lx106-elf-standalone.tar.gz))
- - if var_search "${TRAVIS_SDK-}" esp8266 ; then PATH=$(readlink -f ../xtensa-lx106-elf/bin):$PATH; fi
-
- # For coverage testing (upgrade is used to get latest urllib3 version)
- - sudo apt-get install -y python3-pip
- - pip3 install --user sh click
- - ([[ -z "$TRAVIS_TESTS" ]] || sudo pip install --upgrade cpp-coveralls)
- - (! var_search "${TRAVIS_TESTS-}" docs || sudo apt-get install -y librsvg2-bin)
- - (! var_search "${TRAVIS_TESTS-}" docs || pip install --user Sphinx sphinx-rtd-theme recommonmark sphinxcontrib-svg2pdfconverter)
- - (! var_search "${TRAVIS_TESTS-}" translations || pip3 install --user polib)
-
- # report some good version numbers to the build
- - gcc --version
- - (! var_search "${TRAVIS_SDK-}" arm || arm-none-eabi-gcc --version)
- - (! var_search "${TRAVIS_SDK-}" esp8266 || xtensa-lx106-elf-gcc --version)
- - python3 --version
-
-script:
- # Build mpy-cross first because other builds depend on it.
- - echo 'Building mpy-cross' && echo 'travis_fold:start:mpy-cross'
- - make -C mpy-cross -j2 ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:mpy-cross' && tools/print_status.py status
-
- # Use unbuffered output because building all the releases can take a long time.
- # Travis will cancel the job if it sees no output for >10 minutes.
- - cd tools && python3 -u build_release_files.py
- - cd ..
-
- - echo 'Building unix' && echo 'travis_fold:start:unix'
- - (! var_search "${TRAVIS_TESTS-}" unix || (make -C ports/unix deplibs -j2 && make -C ports/unix -j2 && make -C ports/unix coverage -j2)) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:unix' && tools/print_status.py status
-
- # run tests without coverage info
- #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests -j1)
- #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests -j1 --emit native)
-
- # run tests with coverage info
- - echo 'Test all' && echo 'travis_fold:start:test_all'
- - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1)) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:test_all' && tools/print_status.py status
-
- - echo 'Test threads' && echo 'travis_fold:start:test_threads'
- - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 -d thread)) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:test_threads' && tools/print_status.py status
-
- - echo 'Testing with native' && echo 'travis_fold:start:test_native'
- - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --emit native)) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:test_native' && tools/print_status.py status
-
- - (echo 'Testing with mpy' && echo 'travis_fold:start:test_mpy')
- - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float)) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:test_mpy' && tools/print_status.py status
-
- - (echo 'Building docs' && echo 'travis_fold:start:build_docs')
- - (! var_search "${TRAVIS_TESTS-}" docs || sphinx-build -E -W -b html . _build/html) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:build_docs' && tools/print_status.py status
-
- - (echo 'Building translations' && echo 'travis_fold:start:build_translations')
- - (! var_search "${TRAVIS_TESTS-}" translations || make check-translate) ; S=$? ; echo $S > status ; (exit $S)
- - echo 'travis_fold:end:build_translations' && tools/print_status.py status
-
- # run coveralls coverage analysis (try to, even if some builds/tests failed)
- #- (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod)
-
- - (! var_search "${TRAVIS_TESTS-}" website || (cd tools && python3 build_board_info.py && cd ..))
-
-after_failure:
- - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done)
diff --git a/README.rst b/README.rst
index f5f9cccea..03116be88 100644
--- a/README.rst
+++ b/README.rst
@@ -78,7 +78,7 @@ If you'd like to use the term "CircuitPython" and Blinka for your product here i
* Your product is supported by the primary
`"adafruit/circuitpython" <https://github.com/adafruit/circuitpython>`_ repo. This way we can
update any custom code as we update the CircuitPython internals.
-* Your product is listed on `circuitpython.org <https:/circuitpython.org>`__ (source
+* Your product is listed on `circuitpython.org <https://circuitpython.org>`__ (source
`here <https://github.com/adafruit/circuitpython-org/>`_). This is to ensure that a user of your
product can always download the latest version of CircuitPython from the standard place.
* Your product has a user accessible USB plug which appears as a CIRCUITPY drive when plugged in.
diff --git a/conf.py b/conf.py
index 6b0f40da6..3df958fe1 100644
--- a/conf.py
+++ b/conf.py
@@ -13,6 +13,7 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
+import json
import sys
import os
@@ -24,8 +25,20 @@ from recommonmark.parser import CommonMarkParser
sys.path.insert(0, os.path.abspath('docs'))
sys.path.insert(0, os.path.abspath('.'))
+import shared_bindings_matrix
+
master_doc = 'docs/index'
+# Grab the JSON values to use while building the module support matrix
+# in 'shared-bindings/index.rst'
+
+#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards()
+modules_support_matrix = shared_bindings_matrix.support_matrix_by_board()
+
+html_context = {
+ 'support_matrix': modules_support_matrix
+}
+
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
@@ -40,7 +53,9 @@ extensions = [
'sphinxcontrib.rsvgconverter',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
- 'sphinx.ext.coverage'
+ 'sphinx.ext.coverage',
+ 'rstjinja',
+ 'c2rst'
]
# Add any paths that contain templates here, relative to this directory.
@@ -49,8 +64,7 @@ templates_path = ['templates']
# The suffix of source filenames.
source_suffix = ['.rst', '.md', '.c', '.h']
-source_parsers = {'.md': CommonMarkParser,
- '.c': "c2rst.CStrip", '.h': "c2rst.CStrip"}
+source_parsers = {'.md': CommonMarkParser}
# The encoding of source files.
#source_encoding = 'utf-8-sig'
@@ -122,6 +136,10 @@ exclude_patterns = ["**/build*",
"ports/nrf/nrfx",
"ports/nrf/peripherals",
"ports/nrf/usb",
+ "ports/stm32f4/stm32f4",
+ "ports/stm32f4/peripherals",
+ "ports/stm32f4/ref",
+ "ports/stm32f4/README.md",
"ports/pic16bit",
"ports/qemu-arm",
"ports/stm32",
@@ -351,3 +369,6 @@ texinfo_documents = [
intersphinx_mapping = {"cpython": ('https://docs.python.org/3/', None),
"bus_device": ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),
"register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None)}
+
+def setup(app):
+ app.add_stylesheet("customstyle.css")
diff --git a/docs/c2rst.py b/docs/c2rst.py
index 904fb7408..76489dca3 100644
--- a/docs/c2rst.py
+++ b/docs/c2rst.py
@@ -1,19 +1,31 @@
-import sphinx.parsers
+def c2rst(app, docname, source):
+ """ Pre-parse '.c' & '.h' files that contain rST source.
+ """
+ # Make sure we're outputting HTML
+ if app.builder.format != 'html':
+ return
-class CStrip(sphinx.parsers.Parser):
- def __init__(self):
- self.rst_parser = sphinx.parsers.RSTParser()
+ fname = app.env.doc2path(docname)
+ if (not fname.endswith(".c") and
+ not fname.endswith(".h")):
+ #print("skipping:", fname)
+ return
- def parse(self, inputstring, document):
- # This setting is missing starting with Sphinx 1.7.1 so we set it ourself.
- document.settings.tab_width = 4
- document.settings.character_level_inline_markup = False
- stripped = []
- for line in inputstring.split("\n"):
- line = line.strip()
- if line == "//|":
- stripped.append("")
- elif line.startswith("//| "):
- stripped.append(line[len("//| "):])
- stripped = "\r\n".join(stripped)
- self.rst_parser.parse(stripped, document)
+ src = source[0]
+
+ stripped = []
+ for line in src.split("\n"):
+ line = line.strip()
+ if line == "//|":
+ stripped.append("")
+ elif line.startswith("//| "):
+ stripped.append(line[len("//| "):])
+ stripped = "\r\n".join(stripped)
+
+ rendered = app.builder.templates.render_string(
+ stripped, app.config.html_context
+ )
+ source[0] = rendered
+
+def setup(app):
+ app.connect("source-read", c2rst)
diff --git a/docs/library/network.rst b/docs/library/network.rst
index d25f9f388..cdcc5f323 100644
--- a/docs/library/network.rst
+++ b/docs/library/network.rst
@@ -5,6 +5,7 @@
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: network
+ :noindex:
:synopsis: network configuration
This module provides network drivers and routing configuration. To use this
diff --git a/docs/rstjinja.py b/docs/rstjinja.py
new file mode 100644
index 000000000..3a08b2599
--- /dev/null
+++ b/docs/rstjinja.py
@@ -0,0 +1,24 @@
+# Derived from code on Eric Holscher's blog, found at:
+# https://www.ericholscher.com/blog/2016/jul/25/integrating-jinja-rst-sphinx/
+
+def rstjinja(app, docname, source):
+ """
+ Render our pages as a jinja template for fancy templating goodness.
+ """
+ # Make sure we're outputting HTML
+ if app.builder.format != 'html':
+ return
+
+ # we only want our one jinja template to run through this func
+ if "shared-bindings/support_matrix" not in docname:
+ return
+
+ src = source[0]
+ print(docname)
+ rendered = app.builder.templates.render_string(
+ src, app.config.html_context
+ )
+ source[0] = rendered
+
+def setup(app):
+ app.connect("source-read", rstjinja)
diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py
new file mode 100644
index 000000000..ba0ec0e4f
--- /dev/null
+++ b/docs/shared_bindings_matrix.py
@@ -0,0 +1,289 @@
+# The MIT License (MIT)
+#
+# Copyright (c) 2019 Michael Schroeder
+#
+# 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.
+#
+
+import json
+import os
+import re
+
+
+SUPPORTED_PORTS = ["atmel-samd", "nrf"]
+
+
+def parse_port_config(contents, chip_keyword=None):
+ """ Compile a dictionary of port-wide module configs, which may
+ be categorized by chipset.
+ """
+ chip_fam = "all"
+ ifeq_found = False
+ port_config_results = {"all": []}
+
+ chip_pattern = ""
+ if chip_keyword:
+ chip_pattern = (
+ re.compile("(?<=ifeq\s\(\$\({}\)\,)(\w+)".format(chip_keyword))
+ )
+
+ for line in contents:
+ if chip_keyword:
+ if not ifeq_found:
+ check_ifeq = chip_pattern.search(line)
+ if check_ifeq:
+ ifeq_found = True
+ chip_fam = check_ifeq.group(1)
+ #print("found chip:", chip_fam)
+ else:
+ ifeq_found = False
+ chip_fam = "all"
+ else:
+ if "endif" in line:
+ ifeq_found = False
+ chip_fam = "all"
+
+ if "CIRCUITPY_" in line:
+ if chip_fam in port_config_results:
+ port_config_results[chip_fam].append(line.rstrip("\n"))
+ else:
+ port_config_results[chip_fam] = [line.rstrip("\n")]
+
+ #print(port_config_results)
+ return port_config_results
+
+def get_shared_bindings():
+ """ Get a list of modules in shared-bindings based on folder names
+ """
+ return [item for item in os.listdir("./shared-bindings")]
+
+
+def read_mpconfig():
+ """ Open 'circuitpy_mpconfig.mk' and return the contents.
+ """
+ configs = []
+ with open("py/circuitpy_mpconfig.mk") as mpconfig:
+ configs = mpconfig.read()
+
+ return configs
+
+
+def build_module_map():
+ """ Establish the base of the JSON file, based on the contents from
+ `configs`. Base will contain module names, if they're part of
+ the `FULL_BUILD`, or their default value (0, 1, or a list of
+ modules that determine default [see audiocore, audiomixer, etc.]).
+
+ """
+ base = dict()
+ modules = get_shared_bindings()
+ configs = read_mpconfig()
+ full_build = False
+ for module in modules:
+ full_name = module
+ search_name = module.lstrip("_")
+ re_pattern = "CIRCUITPY_{}\s=\s(.+)".format(search_name.upper())
+ find_config = re.findall(re_pattern, configs)
+ if not find_config:
+ continue
+ find_config = ", ".join([x.strip("$()") for x in find_config])
+
+ full_build = int("CIRCUITPY_FULL_BUILD" in find_config)
+ if not full_build:
+ default_val = find_config
+ else:
+ default_val = "None"
+
+ base[search_name] = {
+ "name": full_name,
+ "full_build": str(full_build),
+ "default_value": default_val,
+ "excluded": {}
+ }
+
+ #print(base)
+ return base
+
+
+def get_excluded_boards(base):
+ """ Cycles through each board's `mpconfigboard.mk` file to determine
+ if each module is included or not. Boards are selected by existence
+ in a port listed in `SUPPORTED_PORTS` (e.g. `/port/nrf/feather_52840`)
+
+ Boards are further categorized by their respective chipset (SAMD21,
+ SAMD51, nRF52840, etc.)
+ """
+ modules = list(base.keys())
+
+ re_board_chip = None
+ chip_keyword = None
+ for port in SUPPORTED_PORTS:
+ # each port appears to use its own define for the chipset
+ if port in ["atmel-samd"]:
+ re_board_chip = re.compile("CHIP_FAMILY\s=\s(\w+)")
+ chip_keyword = "CHIP_FAMILY"
+ elif port in ["nrf"]:
+ re_board_chip = re.compile("MCU_VARIANT\s=\s(\w+)")
+
+ port_dir = "ports/{}".format(port)
+
+ port_config_contents = ""
+ with open(os.path.join(port_dir, "mpconfigport.mk")) as port_config:
+ port_config_contents = port_config.readlines()
+ port_config = parse_port_config(port_config_contents, chip_keyword)
+
+ for entry in os.scandir(os.path.join(port_dir, "boards")):
+ if not entry.is_dir():
+ continue
+
+ contents = ""
+ board_dir = os.path.join(entry.path, "mpconfigboard.mk")
+ with open(board_dir) as board:
+ contents = board.read()
+
+ board_chip = re_board_chip.search(contents)
+ #print(entry.name, board_chip.group(1))
+ if not board_chip:
+ board_chip = "Unknown Chip"
+ else:
+ board_chip = board_chip.group(1)
+
+ # add port_config results to contents
+ contents += "\n" + "\n".join(port_config["all"])
+ if board_chip in port_config:
+ contents += "\n" + "\n".join(port_config[board_chip])
+
+ check_dependent_modules = dict()
+ for module in modules:
+ board_is_excluded = False
+ # check if board uses `SMALL_BUILD`. if yes, and current
+ # module is marked as `FULL_BUILD`, board is excluded
+ small_build = re.search("CIRCUITPY_SMALL_BUILD = 1", contents)
+ if small_build and base[module]["full_build"] == "1":
+ board_is_excluded = True
+
+ # check if board uses `MINIMAL_BUILD`. if yes, and current
+ # module is marked as `DEFAULT_BUILD`, board is excluded
+ min_build = re.search("CIRCUITPY_MINIMAL_BUILD = 1", contents)
+ if min_build and base[module]["default_value"] == "CIRCUITPY_DEFAULT_BUILD":
+ board_is_excluded = True
+
+ # check if module is specifically disabled for this board
+ re_pattern = "CIRCUITPY_{}\s=\s(\w)".format(module.upper())
+ find_module = re.search(re_pattern, contents)
+ if not find_module:
+ if base[module]["default_value"].isdigit():
+ # check if default inclusion is off ('0'). if the board doesn't
+ # have it explicitly enabled, its excluded.
+ if base[module]["default_value"] == "0":
+ board_is_excluded = True
+ else:
+ # this module is dependent on another module. add it
+ # to the list to check after processing all other modules.
+ # only need to check exclusion if it isn't already excluded.
+ if (not board_is_excluded and
+ base[module]["default_value"] not in [
+ "None",
+ "CIRCUITPY_DEFAULT_BUILD"
+ ]):
+ check_dependent_modules[module] = base[module]["default_value"]
+ else:
+ if (find_module.group(1) == "0" and
+ find_module.group(1) != base[module]["default_value"]):
+ board_is_excluded = True
+
+ if board_is_excluded:
+ if board_chip in base[module]["excluded"]:
+ base[module]["excluded"][board_chip].append(entry.name)
+ else:
+ base[module]["excluded"][board_chip] = [entry.name]
+
+ for module in check_dependent_modules:
+ depend_results = set()
+
+ parents = check_dependent_modules[module].split("CIRCUITPY_")
+ parents = [item.strip(", ").lower() for item in parents if item]
+
+ for parent in parents:
+ if parent in base:
+ if (board_chip in base[parent]["excluded"] and
+ entry.name in base[parent]["excluded"][board_chip]):
+ depend_results.add(False)
+ else:
+ depend_results.add(True)
+
+ # only exclude the module if there were zero parents enabled
+ # as determined by the 'depend_results' set.
+ if not any(depend_results):
+ if board_chip in base[module]["excluded"]:
+ base[module]["excluded"][board_chip].append(entry.name)
+ else:
+ base[module]["excluded"][board_chip] = [entry.name]
+
+ #print(json.dumps(base, indent=2))
+ return base
+
+
+def support_matrix_excluded_boards():
+ """ Compiles a list of available modules, and which board definitions
+ do not include them.
+ """
+ base = build_module_map()
+
+ return get_excluded_boards(base)
+
+def support_matrix_by_board():
+ """ Compiles a list of the available core modules available for each
+ board.
+ """
+ base = build_module_map()
+ base_with_exclusions = get_excluded_boards(base)
+
+ boards = dict()
+ for port in SUPPORTED_PORTS:
+ port_dir = "ports/{}/boards".format(port)
+ for entry in os.scandir(port_dir):
+ if not entry.is_dir():
+ continue
+ board_modules = []
+
+ board_name = entry.name
+ board_contents = ""
+ with open(os.path.join(entry.path, "mpconfigboard.h")) as get_name:
+ board_contents = get_name.read()
+ board_name_re = re.search("(?<=MICROPY_HW_BOARD_NAME)\s+(.+)",
+ board_contents)
+ if board_name_re:
+ board_name = board_name_re.group(1).strip('"')
+
+ for module in base_with_exclusions.keys():
+ #print(module)
+ board_has_module = True
+ if base_with_exclusions[module]["excluded"]:
+ for port in base_with_exclusions[module]["excluded"].values():
+ #print(port)
+ if entry.name in port:
+ board_has_module = False
+
+ if board_has_module:
+ board_modules.append(base_with_exclusions[module]["name"])
+ boards[board_name] = sorted(board_modules)
+
+ #print(json.dumps(boards, indent=2))
+ return boards
diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice
-Subproject b9280af5142fc41639229544678e23b5cca07c3
+Subproject 52d87bd7e571af66ecb57ee32b5af9253113415
diff --git a/frozen/Adafruit_CircuitPython_CircuitPlayground b/frozen/Adafruit_CircuitPython_CircuitPlayground
-Subproject 154b74de020764597ba49f0d1e8cc18d55b3643
+Subproject d87ea261c40ecbc6d893d72d337beefbea1cf93
diff --git a/frozen/Adafruit_CircuitPython_Crickit b/frozen/Adafruit_CircuitPython_Crickit
-Subproject 617bb0787f2c61283d248632a62b27be80f64b2
+Subproject a6100fb5d867c7f4980f071119bfa7e0a76e1d4
diff --git a/frozen/Adafruit_CircuitPython_IRRemote b/frozen/Adafruit_CircuitPython_IRRemote
-Subproject 70865ac6e09f821b26ec727e2df300a6d9ebf6b
+Subproject 8b7611a2cc076a2ac1b368c70227519f69f1e3e
diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH
-Subproject bd7ddc67dc86f7ad0115f58ab80d5605739c648
+Subproject 53146ab2e82c318c3c37bd76bac34035a597b31
diff --git a/frozen/Adafruit_CircuitPython_Thermistor b/frozen/Adafruit_CircuitPython_Thermistor
-Subproject 893c5ec6a9aeef38284985074c2058e87754ad3
+Subproject 2e5aedf18eb417a4120d4998ac1f387a4f60073
diff --git a/frozen/Adafruit_CircuitPython_seesaw b/frozen/Adafruit_CircuitPython_seesaw
-Subproject f1171f94083ba64d153ff3f90eeb07500331d6e
+Subproject ea5e445edd4441cacd207aa2d2bfd724b813a25
diff --git a/frozen/circuitpython-stage b/frozen/circuitpython-stage
-Subproject 6d1ae72916cf240ea86185c45f844d59f56d8ec
+Subproject c1d8e1d645cbc83d857e12cf4ba67549b988a4e
diff --git a/lib/tinyusb b/lib/tinyusb
-Subproject 0848c462b3e431a9da42e96537d2b597a457963
+Subproject d3e48da5a1266a88f5f0fdfe28818c8599b0984
diff --git a/lib/utils/buffer_helper.c b/lib/utils/buffer_helper.c
index f6eb8bf1e..694952e3d 100644
--- a/lib/utils/buffer_helper.c
+++ b/lib/utils/buffer_helper.c
@@ -26,10 +26,10 @@
#include "lib/utils/buffer_helper.h"
-void normalize_buffer_bounds(int32_t* start, int32_t end, uint32_t* length) {
+void normalize_buffer_bounds(int32_t* start, int32_t end, size_t* length) {
if (end < 0) {
end += *length;
- } else if (((uint32_t) end) > *length) {
+ } else if (((size_t) end) > *length) {
end = *length;
}
if (*start < 0) {
diff --git a/lib/utils/buffer_helper.h b/lib/utils/buffer_helper.h
index 47042e7ef..7487b9df5 100644
--- a/lib/utils/buffer_helper.h
+++ b/lib/utils/buffer_helper.h
@@ -28,7 +28,8 @@
#define MICROPY_INCLUDED_LIB_UTILS_BUFFER_HELPER_H
#include <stdint.h>
+#include <string.h>
-void normalize_buffer_bounds(int32_t* start, int32_t end, uint32_t* length);
+void normalize_buffer_bounds(int32_t* start, int32_t end, size_t* length);
#endif // MICROPY_INCLUDED_LIB_UTILS_BUFFER_HELPER_H
diff --git a/locale/ID.po b/locale/ID.po
index 33e63bd2c..63e3466b6 100644
--- a/locale/ID.po
+++ b/locale/ID.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\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"
@@ -52,7 +52,7 @@ msgstr ""
msgid "%q indices must be integers, not %s"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
#, fuzzy
msgid "%q must be >= 1"
@@ -218,12 +218,12 @@ msgstr ""
msgid "A hardware interrupt channel is already in use"
msgstr "Sebuah channel hardware interrupt sedang digunakan"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, fuzzy, c-format
msgid "Address must be %d bytes long"
msgstr "buffers harus mempunyai panjang yang sama"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -255,6 +255,7 @@ msgstr "Semua timer untuk pin ini sedang digunakan"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -300,6 +301,10 @@ msgstr ""
"Auto-reload aktif. Silahkan simpan data-data (files) melalui USB untuk "
"menjalankannya atau masuk ke REPL untukmenonaktifkan.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "Bit clock dan word harus memiliki kesamaan pada clock unit"
@@ -312,6 +317,10 @@ msgstr ""
msgid "Both pins must support hardware interrupts"
msgstr "Kedua pin harus mendukung hardware interrut"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr ""
@@ -325,6 +334,19 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -335,7 +357,7 @@ msgstr ""
msgid "Bus pin %d is already in use"
msgstr "DAC sudah digunakan"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
#, fuzzy
msgid "Byte buffer must be 16 bytes."
msgstr "buffers harus mempunyai panjang yang sama"
@@ -353,8 +375,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -415,15 +437,7 @@ msgstr "tidak dapat mendapatkan ukuran scalar secara tidak ambigu"
msgid "Cannot write without MOSI pin."
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr ""
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -443,6 +457,10 @@ msgstr "Clock unit sedang digunakan"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr ""
@@ -455,7 +473,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -464,11 +482,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Tidak dapat menginisialisasi UART"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -485,11 +503,11 @@ msgstr "DAC sudah digunakan"
msgid "Data 0 pin must be byte aligned"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy
msgid "Data too large for advertisement packet"
msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment"
@@ -498,7 +516,16 @@ msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment"
msgid "Destination capacity is smaller than destination_length."
msgstr ""
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -522,16 +549,25 @@ msgstr "Error pada regex"
msgid "Expected a %q"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr ""
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr ""
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -549,12 +585,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Gagal untuk mendapatkan mutex, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Gagal untuk menambahkan karakteristik, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX"
@@ -569,61 +610,66 @@ msgstr "Gagal untuk mengalokasikan buffer RX"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Gagal untuk megalokasikan buffer RX dari %d byte"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to change softdevice state"
msgstr "Gagal untuk merubah status softdevice, error: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Gagal untuk menemukan layanan, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get local address"
msgstr "Gagal untuk mendapatkan alamat lokal, error: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get softdevice state"
msgstr "Gagal untuk mendapatkan status softdevice, error: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Gagal untuk membaca nilai atribut, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Gagal untuk menambahkan Vendor Spesific UUID, status: 0x%08lX"
@@ -633,42 +679,47 @@ msgstr "Gagal untuk menambahkan Vendor Spesific UUID, status: 0x%08lX"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Gagal untuk melepaskan mutex, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Gagal untuk memulai advertisement, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Gagal untuk melakukan scanning, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Gagal untuk menulis nilai atribut, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX"
@@ -704,6 +755,11 @@ msgstr ""
msgid "Function requires lock"
msgstr ""
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr ""
@@ -760,7 +816,7 @@ msgstr "Ukuran buffer tidak valid"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr ""
@@ -768,11 +824,11 @@ msgstr ""
msgid "Invalid direction."
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr ""
@@ -810,15 +866,27 @@ msgstr "Pin-pin tidak valid"
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr ""
@@ -878,7 +946,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -924,6 +992,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr "Tidak ada dukungan hardware untuk pin"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
@@ -932,13 +1004,15 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Tidak dapat menyambungkan ke AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -964,8 +1038,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1042,6 +1116,10 @@ msgstr "sistem file (filesystem) bersifat Read-only"
msgid "Read-only object"
msgstr "sistem file (filesystem) bersifat Read-only"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Channel Kanan tidak didukung"
@@ -1063,11 +1141,12 @@ msgstr ""
msgid "SDA or SCL needs a pull up"
msgstr "SDA atau SCL membutuhkan pull up"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d"
@@ -1086,8 +1165,8 @@ msgstr ""
msgid "Slices not supported"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
-#, c-format
+#: ports/nrf/common-hal/_bleio/Adapter.c
+#, fuzzy, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l"
@@ -1135,19 +1214,19 @@ msgid ""
"exit safe mode.\n"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1155,8 +1234,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1171,11 +1254,13 @@ msgstr "Untuk keluar, silahkan reset board tanpa "
msgid "Too many channels in sample."
msgstr "Terlalu banyak channel dalam sampel"
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr ""
@@ -1195,15 +1280,15 @@ msgstr ""
msgid "USB Error"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1212,6 +1297,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr "Tidak dapat mengalokasikan buffer untuk signed conversion"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1229,7 +1319,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr ""
@@ -1242,12 +1332,12 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr "Baudrate tidak didukung"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
#, fuzzy
msgid "Unsupported display bus type"
msgstr "Baudrate tidak didukung"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr ""
@@ -1259,12 +1349,18 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
-#: py/emitnative.c
-msgid "Viper functions don't currently support more than 4 arguments"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
msgstr ""
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
+#: py/emitnative.c
+msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
#: main.c
@@ -1358,10 +1454,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "mode compile buruk"
@@ -1390,7 +1482,7 @@ msgstr ""
msgid "bits must be 8"
msgstr "bits harus memilki nilai 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr ""
@@ -1403,7 +1495,7 @@ msgstr ""
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr ""
@@ -1615,10 +1707,6 @@ msgstr "tidak dapat melakukan relative import"
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr ""
@@ -1766,7 +1854,8 @@ msgstr "argumen keyword ekstra telah diberikan"
msgid "extra positional arguments given"
msgstr "argumen posisi ekstra telah diberikan"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
@@ -1895,7 +1984,7 @@ msgstr ""
msgid "integer required"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -1989,6 +2078,10 @@ msgstr "label didefinis ulang"
msgid "length argument not allowed for this type"
msgstr ""
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr ""
@@ -2017,6 +2110,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2062,7 +2161,7 @@ msgstr ""
msgid "name '%q' is not defined"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "name must be a string"
msgstr "keyword harus berupa string"
@@ -2108,16 +2207,17 @@ msgstr "tidak ada ikatan/bind pada temuan nonlocal"
msgid "no module named '%q'"
msgstr "tidak ada modul yang bernama '%q'"
-#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
-msgid "no such attribute"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
+#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
+msgid "no such attribute"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2136,7 +2236,7 @@ msgstr "non-keyword arg setelah */**"
msgid "non-keyword arg after keyword arg"
msgstr "non-keyword arg setelah keyword arg"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2203,6 +2303,14 @@ msgstr "panjang data string memiliki keganjilan (odd-length)"
msgid "offset out of bounds"
msgstr "modul tidak ditemukan"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2311,7 +2419,7 @@ msgstr ""
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2426,10 +2534,6 @@ msgstr "sintaksis error pada pendeskripsi uctypes"
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2442,7 +2546,7 @@ msgstr ""
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#, fuzzy
msgid "timeout must be >= 0.0"
msgstr "bits harus memilki nilai 8"
@@ -2596,7 +2700,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 2ad3316c7..d709a69cc 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-11 18:42-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\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"
@@ -52,7 +52,7 @@ msgstr ""
msgid "%q indices must be integers, not %s"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr ""
@@ -217,12 +217,12 @@ msgstr ""
msgid "A hardware interrupt channel is already in use"
msgstr ""
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr ""
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -253,6 +253,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -296,6 +297,10 @@ msgid ""
"disable.\n"
msgstr ""
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr ""
@@ -308,6 +313,10 @@ msgstr ""
msgid "Both pins must support hardware interrupts"
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr ""
@@ -321,6 +330,19 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -331,7 +353,7 @@ msgstr ""
msgid "Bus pin %d is already in use"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr ""
@@ -348,8 +370,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -405,15 +427,7 @@ msgstr ""
msgid "Cannot write without MOSI pin."
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr ""
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -433,6 +447,10 @@ msgstr ""
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr ""
@@ -445,7 +463,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -454,11 +472,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -475,11 +493,11 @@ msgstr ""
msgid "Data 0 pin must be byte aligned"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr ""
@@ -487,7 +505,16 @@ msgstr ""
msgid "Destination capacity is smaller than destination_length."
msgstr ""
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -511,16 +538,25 @@ msgstr ""
msgid "Expected a %q"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr ""
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr ""
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -538,12 +574,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr ""
@@ -558,57 +599,62 @@ msgstr ""
msgid "Failed to allocate RX buffer of %d bytes"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Failed to discover services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr ""
@@ -618,42 +664,47 @@ msgstr ""
msgid "Failed to release mutex, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr ""
@@ -689,6 +740,11 @@ msgstr ""
msgid "Function requires lock"
msgstr ""
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr ""
@@ -745,7 +801,7 @@ msgstr ""
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr ""
@@ -753,11 +809,11 @@ msgstr ""
msgid "Invalid direction."
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr ""
@@ -795,15 +851,27 @@ msgstr ""
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr ""
@@ -863,7 +931,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -909,6 +977,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr ""
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
@@ -917,12 +989,14 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr ""
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -948,8 +1022,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1023,6 +1097,10 @@ msgstr ""
msgid "Read-only object"
msgstr ""
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr ""
@@ -1043,11 +1121,12 @@ msgstr ""
msgid "SDA or SCL needs a pull up"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1066,7 +1145,7 @@ msgstr ""
msgid "Slices not supported"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1112,19 +1191,19 @@ msgid ""
"exit safe mode.\n"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1132,8 +1211,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1148,11 +1231,13 @@ msgstr ""
msgid "Too many channels in sample."
msgstr ""
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr ""
@@ -1172,15 +1257,15 @@ msgstr ""
msgid "USB Error"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1189,6 +1274,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1206,7 +1296,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr ""
@@ -1219,11 +1309,11 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr ""
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
msgid "Unsupported display bus type"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr ""
@@ -1235,12 +1325,18 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
-#: py/emitnative.c
-msgid "Viper functions don't currently support more than 4 arguments"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
msgstr ""
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
+#: py/emitnative.c
+msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
#: main.c
@@ -1325,10 +1421,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1357,7 +1449,7 @@ msgstr ""
msgid "bits must be 8"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr ""
@@ -1370,7 +1462,7 @@ msgstr ""
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr ""
@@ -1581,10 +1673,6 @@ msgstr ""
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr ""
@@ -1732,7 +1820,8 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
@@ -1861,7 +1950,7 @@ msgstr ""
msgid "integer required"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -1955,6 +2044,10 @@ msgstr ""
msgid "length argument not allowed for this type"
msgstr ""
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr ""
@@ -1983,6 +2076,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2028,7 +2127,7 @@ msgstr ""
msgid "name '%q' is not defined"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr ""
@@ -2073,16 +2172,17 @@ msgstr ""
msgid "no module named '%q'"
msgstr ""
-#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
-msgid "no such attribute"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
+#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
+msgid "no such attribute"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2101,7 +2201,7 @@ msgstr ""
msgid "non-keyword arg after keyword arg"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2167,6 +2267,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2275,7 +2383,7 @@ msgstr ""
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2390,10 +2498,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2406,7 +2510,7 @@ msgstr ""
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr ""
@@ -2559,7 +2663,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index cf115716f..c846b646b 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Pascal Deneaux\n"
"Language-Team: Sebastian Plamauer, Pascal Deneaux\n"
@@ -54,7 +54,7 @@ msgstr "Der Index %q befindet sich außerhalb der Reihung"
msgid "%q indices must be integers, not %s"
msgstr "%q Indizes müssen ganze Zahlen sein, nicht %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr "%q muss >= 1 sein"
@@ -219,12 +219,12 @@ msgstr "3-arg pow() wird nicht unterstützt"
msgid "A hardware interrupt channel is already in use"
msgstr "Ein Hardware Interrupt Kanal wird schon benutzt"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr "Die Adresse muss %d Bytes lang sein"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -255,6 +255,7 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -300,6 +301,10 @@ msgstr ""
"Automatisches Neuladen ist aktiv. Speichere Dateien über USB um sie "
"auszuführen oder verbinde dich mit der REPL zum Deaktivieren.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "Bit clock und word select müssen eine clock unit teilen"
@@ -312,6 +317,10 @@ msgstr "Bit depth muss ein Vielfaches von 8 sein."
msgid "Both pins must support hardware interrupts"
msgstr "Beide pins müssen Hardware Interrupts unterstützen"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "Die Helligkeit muss zwischen 0 und 255 liegen"
@@ -325,6 +334,19 @@ msgstr "Die Helligkeit ist nicht einstellbar"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Der Puffergröße ist inkorrekt. Sie sollte %d bytes haben."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Der Puffer muss eine Mindestenslänge von 1 haben"
@@ -335,7 +357,7 @@ msgstr "Der Puffer muss eine Mindestenslänge von 1 haben"
msgid "Bus pin %d is already in use"
msgstr "Bus pin %d wird schon benutzt"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr "Der Puffer muss 16 Bytes lang sein"
@@ -352,8 +374,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr "Kann dotstar nicht mit %s verwenden"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -409,15 +431,7 @@ msgstr "sizeof scalar kann nicht eindeutig bestimmt werden"
msgid "Cannot write without MOSI pin."
msgstr "Kann nicht ohne MOSI-Pin schreiben."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr "Characteristic UUID stimmt nicht mit der Service-UUID überein"
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr "Characteristic wird bereits von einem anderen Dienst verwendet."
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Schreiben von CharacteristicBuffer ist nicht vorgesehen"
@@ -437,6 +451,10 @@ msgstr "Clock unit wird benutzt"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr "Der Befehl muss ein int zwischen 0 und 255 sein"
@@ -449,7 +467,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr "Konnte ble_uuid nicht decodieren. Status: 0x%04x"
@@ -458,11 +476,11 @@ msgstr "Konnte ble_uuid nicht decodieren. Status: 0x%04x"
msgid "Could not initialize UART"
msgstr "Konnte UART nicht initialisieren"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Konnte first buffer nicht zuteilen"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Konnte second buffer nicht zuteilen"
@@ -479,11 +497,11 @@ msgstr "DAC wird schon benutzt"
msgid "Data 0 pin must be byte aligned"
msgstr "Data 0 pin muss am Byte ausgerichtet sein"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr "Zu vielen Daten für das advertisement packet"
@@ -491,7 +509,16 @@ msgstr "Zu vielen Daten für das advertisement packet"
msgid "Destination capacity is smaller than destination_length."
msgstr "Die Zielkapazität ist kleiner als destination_length."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr "Die Rotation der Anzeige muss in 90-Grad-Schritten erfolgen"
@@ -515,16 +542,25 @@ msgstr "Fehler in regex"
msgid "Expected a %q"
msgstr "Erwartet ein(e) %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr "Characteristic wird erwartet"
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr "Eine UUID wird erwartet"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -542,12 +578,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Mutex konnte nicht akquiriert werden. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Hinzufügen des Characteristic ist gescheitert. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Dienst konnte nicht hinzugefügt werden. Status: 0x%04x"
@@ -562,57 +603,62 @@ msgstr "Konnte keinen RX Buffer allozieren"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Konnte keine RX Buffer mit %d allozieren"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr "Fehler beim Ändern des Softdevice-Status"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Failed to discover services"
msgstr "Es konnten keine Dienste gefunden werden"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr "Lokale Adresse konnte nicht abgerufen werden"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr "Fehler beim Abrufen des Softdevice-Status"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Kann CCCD value nicht lesen. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "gatts value konnte nicht gelesen werden. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Kann keine herstellerspezifische UUID hinzufügen. Status: 0x%04x"
@@ -622,42 +668,47 @@ msgstr "Kann keine herstellerspezifische UUID hinzufügen. Status: 0x%04x"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Mutex konnte nicht freigegeben werden. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Kann advertisement nicht starten. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Der Scanvorgang kann nicht gestartet werden. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Kann advertisement nicht stoppen. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Kann den Attributwert nicht schreiben. Status: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "gatts value konnte nicht geschrieben werden. Status: 0x%04x"
@@ -693,6 +744,11 @@ msgstr ""
msgid "Function requires lock"
msgstr "Die Funktion erwartet, dass der 'lock'-Befehl zuvor ausgeführt wurde"
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Gruppe voll"
@@ -751,7 +807,7 @@ msgstr "Ungültige Puffergröße"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr "Ungültige Anzahl von Kanälen"
@@ -759,11 +815,11 @@ msgstr "Ungültige Anzahl von Kanälen"
msgid "Invalid direction."
msgstr "Ungültige Richtung"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Ungültige Datei"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Ungültige format chunk size"
@@ -801,15 +857,27 @@ msgstr "Ungültige Pins"
msgid "Invalid polarity"
msgstr "Ungültige Polarität"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Ungültiger Ausführungsmodus"
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr "Ungültige Anzahl von Stimmen"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "Ungültige wave Datei"
@@ -876,7 +944,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -922,6 +990,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr "Keine Hardwareunterstützung an diesem Pin"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr "Kein Speicherplatz auf Gerät"
@@ -930,12 +1002,14 @@ msgstr "Kein Speicherplatz auf Gerät"
msgid "No such file/directory"
msgstr "Keine solche Datei/Verzeichnis"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr "Nicht verbunden"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Spielt nicht"
@@ -963,8 +1037,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1040,6 +1114,10 @@ msgstr "Schreibgeschützte Dateisystem"
msgid "Read-only object"
msgstr "Schreibgeschützte Objekt"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Rechter Kanal wird nicht unterstützt"
@@ -1060,11 +1138,12 @@ msgstr "Sicherheitsmodus aktiv! Gespeicherter Code wird nicht ausgeführt\n"
msgid "SDA or SCL needs a pull up"
msgstr "SDA oder SCL brauchen pull up"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr "Abtastrate muss positiv sein"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Abtastrate zu hoch. Wert muss unter %d liegen"
@@ -1083,7 +1162,7 @@ msgstr "Slice und Wert (value) haben unterschiedliche Längen."
msgid "Slices not supported"
msgstr "Slices werden nicht unterstützt"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1141,19 +1220,19 @@ msgstr ""
"Die Reset-Taste wurde beim Booten von CircuitPython gedrückt. Drücke sie "
"erneut um den abgesicherten Modus zu verlassen. \n"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1161,8 +1240,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1177,11 +1260,13 @@ msgstr "Zum beenden, resette bitte das board ohne "
msgid "Too many channels in sample."
msgstr "Zu viele Kanäle im sample"
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr "Zu viele displays"
@@ -1201,15 +1286,15 @@ msgstr "USB beschäftigt"
msgid "USB Error"
msgstr "USB Fehler"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr "UUID Zeichenfolge ist nicht 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr "Der UUID-Wert ist kein str-, int- oder Byte-Puffer"
@@ -1218,6 +1303,11 @@ msgstr "Der UUID-Wert ist kein str-, int- oder Byte-Puffer"
msgid "Unable to allocate buffers for signed conversion"
msgstr "Konnte keine Buffer für Vorzeichenumwandlung allozieren"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1235,7 +1325,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr "Schreiben in nvm nicht möglich."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr "Unerwarteter nrfx uuid-Typ"
@@ -1250,11 +1340,11 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr "Baudrate wird nicht unterstützt"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
msgid "Unsupported display bus type"
msgstr "Nicht unterstützter display bus type"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Nicht unterstütztes Format"
@@ -1266,14 +1356,20 @@ msgstr "Nicht unterstützte Operation"
msgid "Unsupported pull value."
msgstr "Nicht unterstützter Pull-Wert"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Viper-Funktionen unterstützen derzeit nicht mehr als 4 Argumente"
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr "Voice index zu hoch"
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr ""
@@ -1365,10 +1461,6 @@ msgstr "Array/Bytes auf der rechten Seite erforderlich"
msgid "attributes not supported yet"
msgstr "Attribute werden noch nicht unterstützt"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1397,7 +1489,7 @@ msgstr "bits muss 7, 8 oder 9 sein"
msgid "bits must be 8"
msgstr "bits müssen 8 sein"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr "Es müssen 8 oder 16 bits_per_sample sein"
@@ -1410,7 +1502,7 @@ msgstr "Zweig ist außerhalb der Reichweite"
msgid "buf is too small. need %d bytes"
msgstr "buf ist zu klein. brauche %d Bytes"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr "Puffer muss ein bytes-artiges Objekt sein"
@@ -1621,10 +1713,6 @@ msgstr "kann keinen relativen Import durchführen"
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr ""
@@ -1772,7 +1860,8 @@ msgstr "Es wurden zusätzliche Keyword-Argumente angegeben"
msgid "extra positional arguments given"
msgstr "Es wurden zusätzliche Argumente ohne Keyword angegeben"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "Die Datei muss eine im Byte-Modus geöffnete Datei sein"
@@ -1902,7 +1991,7 @@ msgstr "int() arg 2 muss >= 2 und <= 36 sein"
msgid "integer required"
msgstr "integer erforderlich"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -2000,6 +2089,10 @@ msgstr "Label neu definiert"
msgid "length argument not allowed for this type"
msgstr "Für diesen Typ ist length nicht zulässig"
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "lhs und rhs sollten kompatibel sein"
@@ -2030,6 +2123,12 @@ msgstr "map buffer zu klein"
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "maximale Rekursionstiefe überschritten"
@@ -2075,7 +2174,7 @@ msgstr "muss Schlüsselwortargument für key function verwenden"
msgid "name '%q' is not defined"
msgstr "Name '%q' ist nirgends definiert worden (Schreibweise kontrollieren)"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr "name muss ein String sein"
@@ -2120,16 +2219,17 @@ msgstr ""
msgid "no module named '%q'"
msgstr "Kein Modul mit dem Namen '%q'"
-#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
-msgid "no such attribute"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
+#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
+msgid "no such attribute"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2148,7 +2248,7 @@ msgstr ""
msgid "non-keyword arg after keyword arg"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr "keine 128-bit UUID"
@@ -2214,6 +2314,14 @@ msgstr "String mit ungerader Länge"
msgid "offset out of bounds"
msgstr "offset außerhalb der Grenzen"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2324,7 +2432,7 @@ msgstr ""
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2442,10 +2550,6 @@ msgstr "Syntaxfehler in uctypes Deskriptor"
msgid "threshold must be in the range 0-65536"
msgstr "threshold muss im Intervall 0-65536 liegen"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2458,7 +2562,7 @@ msgstr ""
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr "timeout muss >= 0.0 sein"
@@ -2615,7 +2719,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
@@ -2680,6 +2784,12 @@ msgstr ""
#~ msgid "Cannot update i/f status"
#~ msgstr "Kann i/f Status nicht updaten"
+#~ msgid "Characteristic UUID doesn't match Service UUID"
+#~ msgstr "Characteristic UUID stimmt nicht mit der Service-UUID überein"
+
+#~ msgid "Characteristic already in use by another Service."
+#~ msgstr "Characteristic wird bereits von einem anderen Dienst verwendet."
+
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Daten sind zu groß für das advertisement packet"
@@ -2813,6 +2923,9 @@ msgstr ""
#~ msgstr ""
#~ "Benutze das esptool um den flash zu löschen und Python erneut hochzuladen"
+#~ msgid "Voice index too high"
+#~ msgstr "Voice index zu hoch"
+
#~ msgid "buffer too long"
#~ msgstr "Buffer zu lang"
diff --git a/locale/en_US.po b/locale/en_US.po
index ab1776aa2..652053ee9 100644
--- a/locale/en_US.po
+++ b/locale/en_US.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -52,7 +52,7 @@ msgstr ""
msgid "%q indices must be integers, not %s"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr ""
@@ -217,12 +217,12 @@ msgstr ""
msgid "A hardware interrupt channel is already in use"
msgstr ""
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr ""
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -253,6 +253,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -296,6 +297,10 @@ msgid ""
"disable.\n"
msgstr ""
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr ""
@@ -308,6 +313,10 @@ msgstr ""
msgid "Both pins must support hardware interrupts"
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr ""
@@ -321,6 +330,19 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -331,7 +353,7 @@ msgstr ""
msgid "Bus pin %d is already in use"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr ""
@@ -348,8 +370,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -405,15 +427,7 @@ msgstr ""
msgid "Cannot write without MOSI pin."
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr ""
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -433,6 +447,10 @@ msgstr ""
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr ""
@@ -445,7 +463,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -454,11 +472,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -475,11 +493,11 @@ msgstr ""
msgid "Data 0 pin must be byte aligned"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr ""
@@ -487,7 +505,16 @@ msgstr ""
msgid "Destination capacity is smaller than destination_length."
msgstr ""
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -511,16 +538,25 @@ msgstr ""
msgid "Expected a %q"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr ""
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr ""
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -538,12 +574,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr ""
@@ -558,57 +599,62 @@ msgstr ""
msgid "Failed to allocate RX buffer of %d bytes"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Failed to discover services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr ""
@@ -618,42 +664,47 @@ msgstr ""
msgid "Failed to release mutex, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr ""
@@ -689,6 +740,11 @@ msgstr ""
msgid "Function requires lock"
msgstr ""
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr ""
@@ -745,7 +801,7 @@ msgstr ""
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr ""
@@ -753,11 +809,11 @@ msgstr ""
msgid "Invalid direction."
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr ""
@@ -795,15 +851,27 @@ msgstr ""
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr ""
@@ -863,7 +931,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -909,6 +977,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr ""
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
@@ -917,12 +989,14 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr ""
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -948,8 +1022,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1023,6 +1097,10 @@ msgstr ""
msgid "Read-only object"
msgstr ""
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr ""
@@ -1043,11 +1121,12 @@ msgstr ""
msgid "SDA or SCL needs a pull up"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1066,7 +1145,7 @@ msgstr ""
msgid "Slices not supported"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1112,19 +1191,19 @@ msgid ""
"exit safe mode.\n"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1132,8 +1211,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1148,11 +1231,13 @@ msgstr ""
msgid "Too many channels in sample."
msgstr ""
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr ""
@@ -1172,15 +1257,15 @@ msgstr ""
msgid "USB Error"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1189,6 +1274,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1206,7 +1296,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr ""
@@ -1219,11 +1309,11 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr ""
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
msgid "Unsupported display bus type"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr ""
@@ -1235,12 +1325,18 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
-#: py/emitnative.c
-msgid "Viper functions don't currently support more than 4 arguments"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
msgstr ""
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
+#: py/emitnative.c
+msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
#: main.c
@@ -1325,10 +1421,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1357,7 +1449,7 @@ msgstr ""
msgid "bits must be 8"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr ""
@@ -1370,7 +1462,7 @@ msgstr ""
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr ""
@@ -1581,10 +1673,6 @@ msgstr ""
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr ""
@@ -1732,7 +1820,8 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
@@ -1861,7 +1950,7 @@ msgstr ""
msgid "integer required"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -1955,6 +2044,10 @@ msgstr ""
msgid "length argument not allowed for this type"
msgstr ""
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr ""
@@ -1983,6 +2076,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2028,7 +2127,7 @@ msgstr ""
msgid "name '%q' is not defined"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr ""
@@ -2073,16 +2172,17 @@ msgstr ""
msgid "no module named '%q'"
msgstr ""
-#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
-msgid "no such attribute"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
+#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
+msgid "no such attribute"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2101,7 +2201,7 @@ msgstr ""
msgid "non-keyword arg after keyword arg"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2167,6 +2267,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2275,7 +2383,7 @@ msgstr ""
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2390,10 +2498,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2406,7 +2510,7 @@ msgstr ""
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr ""
@@ -2559,7 +2663,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po
index 550966a94..1d2fcb659 100644
--- a/locale/en_x_pirate.po
+++ b/locale/en_x_pirate.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: @sommersoft, @MrCertainly\n"
@@ -54,7 +54,7 @@ msgstr ""
msgid "%q indices must be integers, not %s"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr ""
@@ -219,12 +219,12 @@ msgstr ""
msgid "A hardware interrupt channel is already in use"
msgstr "Avast! A hardware interrupt channel be used already"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr ""
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -255,6 +255,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -300,6 +301,10 @@ msgstr ""
"Auto-reload be on. Put yer files on USB to weigh anchor, er' bring'er about "
"t' the REPL t' scuttle.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr ""
@@ -312,6 +317,10 @@ msgstr ""
msgid "Both pins must support hardware interrupts"
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr ""
@@ -325,6 +334,19 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr ""
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -335,7 +357,7 @@ msgstr ""
msgid "Bus pin %d is already in use"
msgstr "Belay that! Bus pin %d already be in use"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr ""
@@ -352,8 +374,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -409,15 +431,7 @@ msgstr ""
msgid "Cannot write without MOSI pin."
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr ""
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -437,6 +451,10 @@ msgstr ""
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr ""
@@ -449,7 +467,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -458,11 +476,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr ""
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -479,11 +497,11 @@ msgstr ""
msgid "Data 0 pin must be byte aligned"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr ""
@@ -491,7 +509,16 @@ msgstr ""
msgid "Destination capacity is smaller than destination_length."
msgstr ""
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -515,16 +542,25 @@ msgstr ""
msgid "Expected a %q"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr ""
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr ""
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -542,12 +578,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr ""
@@ -562,57 +603,62 @@ msgstr ""
msgid "Failed to allocate RX buffer of %d bytes"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Failed to discover services"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr ""
@@ -622,42 +668,47 @@ msgstr ""
msgid "Failed to release mutex, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr ""
@@ -693,6 +744,11 @@ msgstr ""
msgid "Function requires lock"
msgstr ""
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr ""
@@ -749,7 +805,7 @@ msgstr ""
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr ""
@@ -757,11 +813,11 @@ msgstr ""
msgid "Invalid direction."
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr ""
@@ -799,15 +855,27 @@ msgstr ""
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr ""
@@ -867,7 +935,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -913,6 +981,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr ""
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
@@ -921,12 +993,14 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr ""
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -952,8 +1026,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1027,6 +1101,10 @@ msgstr ""
msgid "Read-only object"
msgstr ""
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr ""
@@ -1047,11 +1125,12 @@ msgstr "Runnin' in safe mode! Nay runnin' saved code.\n"
msgid "SDA or SCL needs a pull up"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1070,7 +1149,7 @@ msgstr ""
msgid "Slices not supported"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1116,19 +1195,19 @@ msgid ""
"exit safe mode.\n"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1136,8 +1215,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1152,11 +1235,13 @@ msgstr ""
msgid "Too many channels in sample."
msgstr ""
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr ""
@@ -1176,15 +1261,15 @@ msgstr ""
msgid "USB Error"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1193,6 +1278,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr ""
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1210,7 +1300,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr ""
@@ -1223,11 +1313,11 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr ""
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
msgid "Unsupported display bus type"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr ""
@@ -1239,12 +1329,18 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
-#: py/emitnative.c
-msgid "Viper functions don't currently support more than 4 arguments"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
msgstr ""
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
+#: py/emitnative.c
+msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
#: main.c
@@ -1329,10 +1425,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1361,7 +1453,7 @@ msgstr ""
msgid "bits must be 8"
msgstr "pieces must be of 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr ""
@@ -1374,7 +1466,7 @@ msgstr ""
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr ""
@@ -1585,10 +1677,6 @@ msgstr ""
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr ""
@@ -1736,7 +1824,8 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
@@ -1865,7 +1954,7 @@ msgstr ""
msgid "integer required"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -1959,6 +2048,10 @@ msgstr ""
msgid "length argument not allowed for this type"
msgstr ""
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr ""
@@ -1987,6 +2080,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2032,7 +2131,7 @@ msgstr ""
msgid "name '%q' is not defined"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr ""
@@ -2077,16 +2176,17 @@ msgstr ""
msgid "no module named '%q'"
msgstr ""
-#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
-msgid "no such attribute"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
+#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
+msgid "no such attribute"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2105,7 +2205,7 @@ msgstr ""
msgid "non-keyword arg after keyword arg"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2171,6 +2271,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2279,7 +2387,7 @@ msgstr ""
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2394,10 +2502,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr ""
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2410,7 +2514,7 @@ msgstr ""
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr ""
@@ -2563,7 +2667,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index a1e90b0eb..ca8593dcd 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:07-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -54,7 +54,7 @@ msgstr "%q indice fuera de rango"
msgid "%q indices must be integers, not %s"
msgstr "%q indices deben ser enteros, no %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr "%q debe ser >= 1"
@@ -219,12 +219,12 @@ msgstr "pow() con 3 argumentos no soportado"
msgid "A hardware interrupt channel is already in use"
msgstr "El canal EXTINT ya está siendo utilizado"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr "La dirección debe ser %d bytes de largo"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -257,6 +257,7 @@ msgstr "Todos los timers para este pin están siendo utilizados"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -304,6 +305,10 @@ msgstr ""
"Auto-reload habilitado. Simplemente guarda los archivos via USB para "
"ejecutarlos o entra al REPL para desabilitarlos.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "Bit clock y word select deben compartir una unidad de reloj"
@@ -316,6 +321,10 @@ msgstr "Bits depth debe ser múltiplo de 8."
msgid "Both pins must support hardware interrupts"
msgstr "Ambos pines deben soportar interrupciones por hardware"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "El brillo debe estar entro 0 y 255"
@@ -329,6 +338,19 @@ msgstr "El brillo no se puede ajustar"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Tamaño de buffer incorrecto. Debe ser de %d bytes."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Buffer debe ser de longitud 1 como minimo"
@@ -339,7 +361,7 @@ msgstr "Buffer debe ser de longitud 1 como minimo"
msgid "Bus pin %d is already in use"
msgstr "Bus pin %d ya está siendo utilizado"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr "Byte buffer debe de ser 16 bytes"
@@ -356,8 +378,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr "No se puede usar dotstar con %s"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -413,15 +435,7 @@ msgstr "No se puede obtener inequívocamente sizeof escalar"
msgid "Cannot write without MOSI pin."
msgstr "No se puede escribir sin pin MOSI."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr "Características UUID no concide con el Service UUID"
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr "Características ya esta en uso por otro Serivice"
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "CharateristicBuffer escritura no proporcionada"
@@ -441,6 +455,10 @@ msgstr "Clock unit está siendo utilizado"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr "Entrada de columna debe ser digitalio.DigitalInOut"
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr "Command debe estar entre 0 y 255."
@@ -453,7 +471,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr "No se puede descodificar ble_uuid, err 0x%04x"
@@ -462,11 +480,11 @@ msgstr "No se puede descodificar ble_uuid, err 0x%04x"
msgid "Could not initialize UART"
msgstr "No se puede inicializar la UART"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "No se pudo asignar el primer buffer"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "No se pudo asignar el segundo buffer"
@@ -483,11 +501,11 @@ msgstr "DAC ya está siendo utilizado"
msgid "Data 0 pin must be byte aligned"
msgstr "El pin Data 0 debe estar alineado a bytes"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr "Trozo de datos debe seguir fmt chunk"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr "Data es muy grande para el paquete de advertisement."
@@ -495,7 +513,16 @@ msgstr "Data es muy grande para el paquete de advertisement."
msgid "Destination capacity is smaller than destination_length."
msgstr "Capacidad de destino es mas pequeña que destination_length."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr "Rotación de display debe ser en incrementos de 90 grados"
@@ -519,16 +546,25 @@ msgstr "Error en regex"
msgid "Expected a %q"
msgstr "Se espera un %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr "Se esperaba una Característica."
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr "Se esperaba un UUID"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -546,12 +582,17 @@ msgstr "Fallo enviando comando"
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "No se puede adquirir el mutex, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Fallo al añadir caracteristica, err: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Fallo al agregar servicio. err: 0x%02x"
@@ -566,58 +607,63 @@ msgstr "Ha fallado la asignación del buffer RX"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Falló la asignación del buffer RX de %d bytes"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr "No se puede cambiar el estado del softdevice"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "No se puede iniciar el escaneo. err: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "No se puede descubrir servicios"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr "No se puede obtener la dirección local"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr "No se puede obtener el estado del softdevice"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Error al notificar o indicar el valor del atributo, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "No se puede leer el valor del atributo. err 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#, c-format
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, fuzzy, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Error al leer valor del atributo, err 0x%04"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "No se puede escribir el valor del atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Fallo al registrar el Vendor-Specific UUID, err 0x%04x"
@@ -627,42 +673,47 @@ msgstr "Fallo al registrar el Vendor-Specific UUID, err 0x%04x"
msgid "Failed to release mutex, err 0x%04x"
msgstr "No se puede liberar el mutex, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "No se puede inicar el anuncio. err: 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "No se puede iniciar el escaneo. err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "No se puede detener el anuncio. err: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "No se puede escribir el valor del atributo. err: 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "No se puede escribir el valor del atributo. err: 0x%04x"
@@ -698,6 +749,11 @@ msgstr "Frecuencia capturada por encima de la capacidad. Captura en pausa."
msgid "Function requires lock"
msgstr "La función requiere lock"
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Group lleno"
@@ -756,7 +812,7 @@ msgstr "Tamaño de buffer inválido"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr "Inválido periodo de captura. Rango válido: 1 - 500"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr "Cuenta de canales inválida"
@@ -764,11 +820,11 @@ msgstr "Cuenta de canales inválida"
msgid "Invalid direction."
msgstr "Dirección inválida."
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Archivo inválido"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Formato de fragmento de formato no válido"
@@ -806,15 +862,27 @@ msgstr "pines inválidos"
msgid "Invalid polarity"
msgstr "Polaridad inválida"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Modo de ejecución inválido."
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr "Cuenta de voces inválida"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "Archivo wave inválido"
@@ -878,7 +946,7 @@ msgstr "Micrófono demora de inicio debe estar en el rango 0.0 a 1.0"
msgid "Must be a %q subclass."
msgstr "Debe de ser una subclase de %q"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -924,6 +992,10 @@ msgstr "Sin soporte de hardware en el pin clk"
msgid "No hardware support on pin"
msgstr "Sin soporte de hardware en pin"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr "No queda espacio en el dispositivo"
@@ -932,12 +1004,14 @@ msgstr "No queda espacio en el dispositivo"
msgid "No such file/directory"
msgstr "No existe el archivo/directorio"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr "No conectado"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "No reproduciendo"
@@ -967,11 +1041,9 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
-"Solo se admiten BMP monocromos, indexados de 8bpp y 16bpp o superiores:% d "
-"bppdado"
#: shared-bindings/_pixelbuf/PixelBuf.c
#, fuzzy
@@ -1051,6 +1123,10 @@ msgstr "Sistema de archivos de solo-Lectura"
msgid "Read-only object"
msgstr "Solo-lectura"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Canal derecho no soportado"
@@ -1071,11 +1147,12 @@ msgstr "Ejecutando en modo seguro! No se esta ejecutando el código guardado.\n"
msgid "SDA or SCL needs a pull up"
msgstr "SDA o SCL necesitan una pull up"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr "Sample rate debe ser positivo"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d"
@@ -1094,7 +1171,7 @@ msgstr "Slice y value tienen diferentes longitudes"
msgid "Slices not supported"
msgstr "Rebanadas no soportadas"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
@@ -1152,19 +1229,19 @@ msgstr ""
"El botón reset fue presionado mientras arrancaba CircuitPython. Presiona "
"otra vez para salir del modo seguro.\n"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr "Los bits_per_sample del sample no igualan a los del mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr "La cuenta de canales del sample no iguala a las del mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr "El sample rate del sample no iguala al del mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr "El signo del sample no iguala al del mixer"
@@ -1172,9 +1249,13 @@ msgstr "El signo del sample no iguala al del mixer"
msgid "Tile height must exactly divide bitmap height"
msgstr "La altura del Tile debe dividir exacto la altura del bitmap"
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Los índices de Tile deben ser 0 - 255"
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1188,11 +1269,13 @@ msgstr "Para salir, por favor reinicia la tarjeta sin "
msgid "Too many channels in sample."
msgstr "Demasiados canales en sample."
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr "Demasiados buses de pantalla"
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr "Muchos displays"
@@ -1212,15 +1295,15 @@ msgstr "USB ocupado"
msgid "USB Error"
msgstr "Error USB"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr "UUID string no es 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr "UUID valor no es un str, int o byte buffer"
@@ -1229,6 +1312,11 @@ msgstr "UUID valor no es un str, int o byte buffer"
msgid "Unable to allocate buffers for signed conversion"
msgstr "No se pudieron asignar buffers para la conversión con signo"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1246,7 +1334,7 @@ msgstr "No se pudo leer los datos de la paleta de colores"
msgid "Unable to write to nvm."
msgstr "Imposible escribir en nvm"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr "Tipo de uuid nrfx inesperado"
@@ -1259,12 +1347,12 @@ msgstr "Número incomparable de elementos en RHS (%d esperado,%d obtenido)"
msgid "Unsupported baudrate"
msgstr "Baudrate no soportado"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
#, fuzzy
msgid "Unsupported display bus type"
msgstr "tipo de bitmap no soportado"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Formato no soportado"
@@ -1276,14 +1364,20 @@ msgstr "Operación no soportada"
msgid "Unsupported pull value."
msgstr "valor pull no soportado."
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "funciones Viper actualmente no soportan más de 4 argumentos."
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr "Index de voz demasiado alto"
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr "ADVERTENCIA: El nombre de archivo de tu código tiene dos extensiones\n"
@@ -1374,10 +1468,6 @@ msgstr "array/bytes requeridos en el lado derecho"
msgid "attributes not supported yet"
msgstr "atributos aún no soportados"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "mal GATT role"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "modo de compilación erroneo"
@@ -1406,7 +1496,7 @@ msgstr "bits deben ser 7, 8 ó 9"
msgid "bits must be 8"
msgstr "bits debe ser 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr "bits_per_sample debe ser 8 ó 16"
@@ -1419,7 +1509,7 @@ msgstr "El argumento de chr() no esta en el rango(256)"
msgid "buf is too small. need %d bytes"
msgstr "buf es demasiado pequeño. necesita %d bytes"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr "buffer debe de ser un objeto bytes-like"
@@ -1635,10 +1725,6 @@ msgstr "no se puedo realizar importación relativa"
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr "characteristics incluye un objeto que no es una Characteristica"
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr "chars buffer es demasiado pequeño"
@@ -1788,7 +1874,8 @@ msgstr "argumento(s) por palabra clave adicionales fueron dados"
msgid "extra positional arguments given"
msgstr "argumento posicional adicional dado"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "el archivo deberia ser una archivo abierto en modo byte"
@@ -1917,7 +2004,7 @@ msgstr "int() arg 2 debe ser >= 2 y <= 36"
msgid "integer required"
msgstr "Entero requerido"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -2014,6 +2101,10 @@ msgstr "etiqueta redefinida"
msgid "length argument not allowed for this type"
msgstr "argumento length no permitido para este tipo"
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "lhs y rhs deben ser compatibles"
@@ -2042,6 +2133,12 @@ msgstr "map buffer muy pequeño"
msgid "math domain error"
msgstr "error de dominio matemático"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "profundidad máxima de recursión excedida"
@@ -2087,7 +2184,7 @@ msgstr "debe utilizar argumento de palabra clave para la función clave"
msgid "name '%q' is not defined"
msgstr "name '%q' no esta definido"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr "name debe de ser un string"
@@ -2132,16 +2229,17 @@ msgstr "no se ha encontrado ningún enlace para nonlocal"
msgid "no module named '%q'"
msgstr "ningún módulo se llama '%q'"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
+msgstr ""
+
#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
msgid "no such attribute"
msgstr "no hay tal atributo"
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2162,7 +2260,7 @@ msgstr ""
"no deberia estar/tener agumento por palabra clave despues de argumento por "
"palabra clave"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr "no es 128-bit UUID"
@@ -2230,6 +2328,14 @@ msgstr "string de longitud impar"
msgid "offset out of bounds"
msgstr "address fuera de límites"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2339,7 +2445,7 @@ msgstr "retorno esperado '%q' pero se obtuvo '%q'"
msgid "rsplit(None,n)"
msgstr "rsplit(None,n)"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2457,10 +2563,6 @@ msgstr "error de sintaxis en el descriptor uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "limite debe ser en el rango 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "el indice del tile fuera de limite"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() toma un sequencio 9"
@@ -2473,7 +2575,7 @@ msgstr "time.struct_time() acepta exactamente 1 argumento"
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr "timepo muerto >100 (unidades en segundos)"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr "tiempo muerto debe ser >= 0.0"
@@ -2626,7 +2728,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
@@ -2690,6 +2792,12 @@ msgstr "paso cero"
#~ msgid "Cannot update i/f status"
#~ msgstr "No se puede actualizar i/f status"
+#~ msgid "Characteristic UUID doesn't match Service UUID"
+#~ msgstr "Características UUID no concide con el Service UUID"
+
+#~ msgid "Characteristic already in use by another Service."
+#~ msgstr "Características ya esta en uso por otro Serivice"
+
#, fuzzy
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Los datos no caben en el paquete de anuncio."
@@ -2793,6 +2901,13 @@ msgstr "paso cero"
#~ msgid "Only bit maps of 8 bit color or less are supported"
#~ msgstr "Solo se admiten bit maps de color de 8 bits o menos"
+#~ msgid ""
+#~ "Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d "
+#~ "bpp given"
+#~ msgstr ""
+#~ "Solo se admiten BMP monocromos, indexados de 8bpp y 16bpp o superiores:% "
+#~ "d bppdado"
+
#~ msgid "Only true color (24 bpp or higher) BMP supported %x"
#~ msgstr "Solo color verdadero (24 bpp o superior) BMP admitido %x"
@@ -2817,6 +2932,9 @@ msgstr "paso cero"
#~ msgid "STA required"
#~ msgstr "STA requerido"
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Los índices de Tile deben ser 0 - 255"
+
#~ msgid "UART(%d) does not exist"
#~ msgstr "UART(%d) no existe"
@@ -2836,6 +2954,12 @@ msgstr "paso cero"
#~ msgstr ""
#~ "Usa esptool para borrar la flash y vuelve a cargar Python en su lugar"
+#~ msgid "Voice index too high"
+#~ msgstr "Index de voz demasiado alto"
+
+#~ msgid "bad GATT role"
+#~ msgstr "mal GATT role"
+
#~ msgid "buffer too long"
#~ msgstr "buffer demasiado largo"
@@ -2854,6 +2978,9 @@ msgstr "paso cero"
#~ msgid "can't set STA config"
#~ msgstr "no se puede establecer STA config"
+#~ msgid "characteristics includes an object that is not a Characteristic"
+#~ msgstr "characteristics incluye un objeto que no es una Characteristica"
+
#~ msgid "either pos or kw args are allowed"
#~ msgstr "ya sea pos o kw args son permitidos"
@@ -2918,6 +3045,9 @@ msgstr "paso cero"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "services incluye un objeto que no es servicio"
+#~ msgid "tile index out of bounds"
+#~ msgstr "el indice del tile fuera de limite"
+
#~ msgid "too many arguments"
#~ msgstr "muchos argumentos"
diff --git a/locale/fil.po b/locale/fil.po
index 29e969566..6f460c94c 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-12-20 22:15-0800\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n"
@@ -52,7 +52,7 @@ msgstr "%q indeks wala sa sakop"
msgid "%q indices must be integers, not %s"
msgstr "%q indeks ay dapat integers, hindi %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
#, fuzzy
msgid "%q must be >= 1"
@@ -220,12 +220,12 @@ msgstr "3-arg pow() hindi suportado"
msgid "A hardware interrupt channel is already in use"
msgstr "Isang channel ng hardware interrupt ay ginagamit na"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, fuzzy, c-format
msgid "Address must be %d bytes long"
msgstr "ang palette ay dapat 32 bytes ang haba"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -257,6 +257,7 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -302,6 +303,10 @@ msgstr ""
"Ang awtomatikong pag re-reload ay ON. i-save lamang ang mga files sa USB "
"para patakbuhin sila o pasukin ang REPL para i-disable ito.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "Ang bit clock at word select dapat makibahagi sa isang clock unit"
@@ -314,6 +319,10 @@ msgstr "Bit depth ay dapat multiple ng 8."
msgid "Both pins must support hardware interrupts"
msgstr "Ang parehong mga pin ay dapat na sumusuporta sa hardware interrupts"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "Ang liwanag ay dapat sa gitna ng 0 o 255"
@@ -327,6 +336,19 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Mali ang size ng buffer. Dapat %d bytes."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Buffer dapat ay hindi baba sa 1 na haba"
@@ -337,7 +359,7 @@ msgstr "Buffer dapat ay hindi baba sa 1 na haba"
msgid "Bus pin %d is already in use"
msgstr "Ginagamit na ang DAC"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
#, fuzzy
msgid "Byte buffer must be 16 bytes."
msgstr "buffer ay dapat bytes-like object"
@@ -355,8 +377,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -413,15 +435,7 @@ msgstr "Hindi puedeng hindi sigurado ang get sizeof scalar"
msgid "Cannot write without MOSI pin."
msgstr "Hindi maaring isulat kapag walang MOSI pin."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr ""
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -441,6 +455,10 @@ msgstr "Clock unit ginagamit"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
#, fuzzy
msgid "Command must be an int between 0 and 255"
@@ -454,7 +472,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -463,11 +481,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Hindi ma-initialize ang UART"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Hindi ma-iallocate ang first buffer"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Hindi ma-iallocate ang second buffer"
@@ -485,11 +503,11 @@ msgstr "Ginagamit na ang DAC"
msgid "Data 0 pin must be byte aligned"
msgstr "graphic ay dapat 2048 bytes ang haba"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr "Dapat sunurin ng Data chunk ang fmt chunk"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy
msgid "Data too large for advertisement packet"
msgstr "Hindi makasya ang data sa loob ng advertisement packet"
@@ -499,7 +517,16 @@ msgid "Destination capacity is smaller than destination_length."
msgstr ""
"Ang kapasidad ng destinasyon ay mas maliit kaysa sa destination_length."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -523,18 +550,27 @@ msgstr "May pagkakamali sa REGEX"
msgid "Expected a %q"
msgstr "Umasa ng %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
#, fuzzy
msgid "Expected a Characteristic"
msgstr "Hindi mabasa and Characteristic."
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
#, fuzzy
msgid "Expected a UUID"
msgstr "Umasa ng %q"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -552,12 +588,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Nabigo sa pag kuha ng mutex, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Nabigo sa paglagay ng characteristic, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX"
@@ -572,61 +613,66 @@ msgstr "Nabigong ilaan ang RX buffer"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Nabigong ilaan ang RX buffer ng %d bytes"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to change softdevice state"
msgstr "Nabigo sa pagbago ng softdevice state, error: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Nabigo sa pagdiscover ng services, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get local address"
msgstr "Nabigo sa pagkuha ng local na address, , error: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get softdevice state"
msgstr "Nabigo sa pagkuha ng softdevice state, error: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Hindi mabasa ang value ng attribute, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Hindi maisulat ang gatts value, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Hindi matagumpay ang paglagay ng Vender Specific UUID, status: 0x%08lX"
@@ -636,42 +682,47 @@ msgstr "Hindi matagumpay ang paglagay ng Vender Specific UUID, status: 0x%08lX"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Nabigo sa pagrelease ng mutex, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Hindi masimulaan mag i-scan, status: 0x%0xlX"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Hindi mahinto ang advertisement, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Hindi maisulat ang attribute value, status: 0x%08lX"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Hindi maisulat ang gatts value, status: 0x%08lX"
@@ -707,6 +758,11 @@ msgstr ""
msgid "Function requires lock"
msgstr "Function nangangailangan ng lock"
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Puno ang group"
@@ -765,7 +821,7 @@ msgstr "Mali ang buffer size"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr "Maling bilang ng channel"
@@ -773,11 +829,11 @@ msgstr "Maling bilang ng channel"
msgid "Invalid direction."
msgstr "Mali ang direksyon."
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Mali ang file"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Mali ang format ng chunk size"
@@ -815,15 +871,27 @@ msgstr "Mali ang pins"
msgid "Invalid polarity"
msgstr "Mali ang polarity"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Mali ang run mode."
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr "Maling bilang ng voice"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "May hindi tama sa wave file"
@@ -887,7 +955,7 @@ msgstr "Ang delay ng startup ng mikropono ay dapat na nasa 0.0 hanggang 1.0"
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -933,6 +1001,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr "Walang support sa hardware ang pin"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
@@ -941,13 +1013,15 @@ msgstr ""
msgid "No such file/directory"
msgstr "Walang file/directory"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Hindi maka connect sa AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Hindi playing"
@@ -975,8 +1049,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1056,6 +1130,10 @@ msgstr "Basahin-lamang mode"
msgid "Read-only object"
msgstr "Basahin-lamang"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Hindi supportado ang kanang channel"
@@ -1076,11 +1154,12 @@ msgstr "Tumatakbo sa safe mode! Hindi tumatakbo ang nai-save na code.\n"
msgid "SDA or SCL needs a pull up"
msgstr "Kailangan ng pull up resistors ang SDA o SCL"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr "Sample rate ay dapat positibo"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Sample rate ay masyadong mataas. Ito ay dapat hindi hiigit sa %d"
@@ -1099,7 +1178,7 @@ msgstr "Slice at value iba't ibang haba."
msgid "Slices not supported"
msgstr "Hindi suportado ang Slices"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1155,19 +1234,19 @@ msgstr ""
"Ang reset button ay pinindot habang nag boot ang CircuitPython. Pindutin "
"ulit para lumabas sa safe mode.\n"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr "Ang bits_per_sample ng sample ay hindi tugma sa mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr "Ang channel count ng sample ay hindi tugma sa mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr "Ang sample rate ng sample ay hindi tugma sa mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr "Ang signedness ng sample hindi tugma sa mixer"
@@ -1175,8 +1254,12 @@ msgstr "Ang signedness ng sample hindi tugma sa mixer"
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1191,11 +1274,13 @@ msgstr "Para lumabas, paki-reset ang board na wala ang "
msgid "Too many channels in sample."
msgstr "Sobra ang channels sa sample."
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr ""
@@ -1215,15 +1300,15 @@ msgstr "Busy ang USB"
msgid "USB Error"
msgstr "May pagkakamali ang USB"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1232,6 +1317,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr "Hindi ma-allocate ang buffers para sa naka-sign na conversion"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1249,7 +1339,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr "Hindi ma i-sulat sa NVM."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy
msgid "Unexpected nrfx uuid type"
msgstr "hindi inaasahang indent"
@@ -1263,12 +1353,12 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr "Hindi supportadong baudrate"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
#, fuzzy
msgid "Unsupported display bus type"
msgstr "Hindi supportadong tipo ng bitmap"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Hindi supportadong format"
@@ -1280,16 +1370,22 @@ msgstr "Hindi sinusuportahang operasyon"
msgid "Unsupported pull value."
msgstr "Hindi suportado ang pull value."
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
"Ang mga function ng Viper ay kasalukuyang hindi sumusuporta sa higit sa 4 na "
"argumento"
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr "Index ng Voice ay masyadong mataas"
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr "BABALA: Ang pangalan ng file ay may dalawang extension\n"
@@ -1378,10 +1474,6 @@ msgstr "array/bytes kinakailangan sa kanang bahagi"
msgid "attributes not supported yet"
msgstr "attributes hindi sinusuportahan"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "masamang mode ng compile"
@@ -1410,7 +1502,7 @@ msgstr "bits ay dapat 7, 8 o 9"
msgid "bits must be 8"
msgstr "bits ay dapat walo (8)"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr "bits_per_sample ay dapat 8 o 16"
@@ -1423,7 +1515,7 @@ msgstr "branch wala sa range"
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr "buffer ay dapat bytes-like object"
@@ -1641,10 +1733,6 @@ msgstr "hindi maaring isagawa ang relative import"
msgid "casting"
msgstr "casting"
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr "masyadong maliit ang buffer"
@@ -1797,7 +1885,8 @@ msgstr "dagdag na keyword argument na ibinigay"
msgid "extra positional arguments given"
msgstr "dagdag na positional argument na ibinigay"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "file ay dapat buksan sa byte mode"
@@ -1927,7 +2016,7 @@ msgstr "int() arg 2 ay dapat >=2 at <= 36"
msgid "integer required"
msgstr "kailangan ng int"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -2025,6 +2114,10 @@ msgstr "ang label ay na-define ulit"
msgid "length argument not allowed for this type"
msgstr "length argument ay walang pahintulot sa ganitong type"
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "lhs at rhs ay dapat magkasundo"
@@ -2053,6 +2146,12 @@ msgstr "masyadong maliit ang buffer map"
msgid "math domain error"
msgstr "may pagkakamali sa math domain"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "lumagpas ang maximum recursion depth"
@@ -2098,7 +2197,7 @@ msgstr "dapat gumamit ng keyword argument para sa key function"
msgid "name '%q' is not defined"
msgstr "name '%q' ay hindi defined"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "name must be a string"
msgstr "ang keywords dapat strings"
@@ -2144,16 +2243,17 @@ msgstr "no binding para sa nonlocal, nahanap"
msgid "no module named '%q'"
msgstr "walang module na '%q'"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
+msgstr ""
+
#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
msgid "no such attribute"
msgstr "walang ganoon na attribute"
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2172,7 +2272,7 @@ msgstr "non-keyword arg sa huli ng */**"
msgid "non-keyword arg after keyword arg"
msgstr "non-keyword arg sa huli ng keyword arg"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2239,6 +2339,14 @@ msgstr "odd-length string"
msgid "offset out of bounds"
msgstr "wala sa sakop ang address"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2349,7 +2457,7 @@ msgstr "return umasa ng '%q' pero ang nakuha ay ‘%q’"
msgid "rsplit(None,n)"
msgstr "rsplit(None,n)"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2467,10 +2575,6 @@ msgstr "may pagkakamali sa sintaks sa uctypes descriptor"
msgid "threshold must be in the range 0-65536"
msgstr "ang threshold ay dapat sa range 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() kumukuha ng 9-sequence"
@@ -2483,7 +2587,7 @@ msgstr "time.struct_time() kumukuha ng 1 argument"
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr "timeout >100 (units ay seconds, hindi na msecs)"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#, fuzzy
msgid "timeout must be >= 0.0"
msgstr "bits ay dapat walo (8)"
@@ -2637,7 +2741,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
@@ -2839,6 +2943,9 @@ msgstr "zero step"
#~ msgstr ""
#~ "Gamitin ang esptool upang burahin ang flash at muling i-upload ang Python"
+#~ msgid "Voice index too high"
+#~ msgstr "Index ng Voice ay masyadong mataas"
+
#~ msgid "[addrinfo error %d]"
#~ msgstr "[addrinfo error %d]"
diff --git a/locale/fr.po b/locale/fr.po
index 3a4c418d4..c176fd8bc 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2019-04-14 20:05+0100\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -54,7 +54,7 @@ msgstr "index %q hors gamme"
msgid "%q indices must be integers, not %s"
msgstr "les indices %q doivent être des entiers, pas %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
#, fuzzy
msgid "%q must be >= 1"
@@ -221,12 +221,12 @@ msgstr "pow() non supporté avec 3 arguments"
msgid "A hardware interrupt channel is already in use"
msgstr "Un canal d'interruptions matérielles est déjà utilisé"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, fuzzy, c-format
msgid "Address must be %d bytes long"
msgstr "L'adresse doit être longue de %d octets"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -260,6 +260,7 @@ msgstr "Tous les timers pour cette broche sont utilisés"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -307,6 +308,10 @@ msgstr ""
"Auto-chargement activé. Copiez simplement les fichiers en USB pour les "
"lancer ou entrez sur REPL pour le désactiver.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "'bit clock' et 'word select' doivent partager une horloge"
@@ -319,6 +324,10 @@ msgstr "La profondeur de bit doit être un multiple de 8."
msgid "Both pins must support hardware interrupts"
msgstr "Les deux entrées doivent supporter les interruptions matérielles"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "La luminosité doit être entre 0 et 255"
@@ -332,6 +341,19 @@ msgstr "Luminosité non-ajustable"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Tampon de taille incorrect. Devrait être de %d octets."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Le tampon doit être de longueur au moins 1"
@@ -342,7 +364,7 @@ msgstr "Le tampon doit être de longueur au moins 1"
msgid "Bus pin %d is already in use"
msgstr "La broche %d du bus est déjà utilisée"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
#, fuzzy
msgid "Byte buffer must be 16 bytes."
msgstr "Le tampon d'octets doit être de 16 octets."
@@ -360,8 +382,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr "Impossible d'utiliser 'dotstar' avec %s"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -419,15 +441,7 @@ msgstr "Impossible d'obtenir la taille du scalaire sans ambigüité"
msgid "Cannot write without MOSI pin."
msgstr "Impossible d'écrire sans broche MOSI."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr "L'UUID de 'Characteristic' ne correspond pas à l'UUID du Service"
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr "'Characteristic' déjà en utilisation par un autre service"
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Ecriture sur 'CharacteristicBuffer' non fournie"
@@ -447,6 +461,10 @@ msgstr "Horloge en cours d'utilisation"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr "L'entrée 'Column' doit être un digitalio.DigitalInOut"
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
#, fuzzy
msgid "Command must be an int between 0 and 255"
@@ -460,7 +478,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr "Impossible de décoder le 'ble_uuid', err 0x%04x"
@@ -469,11 +487,11 @@ msgstr "Impossible de décoder le 'ble_uuid', err 0x%04x"
msgid "Could not initialize UART"
msgstr "L'UART n'a pu être initialisé"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Impossible d'allouer le 1er tampon"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Impossible d'allouer le 2e tampon"
@@ -491,11 +509,11 @@ msgstr "DAC déjà utilisé"
msgid "Data 0 pin must be byte aligned"
msgstr "La broche 'Data 0' doit être aligné sur l'octet"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr "Un bloc de données doit suivre un bloc de format"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr "Données trop volumineuses pour un paquet de diffusion"
@@ -503,7 +521,16 @@ msgstr "Données trop volumineuses pour un paquet de diffusion"
msgid "Destination capacity is smaller than destination_length."
msgstr "La capacité de destination est plus petite que 'destination_length'."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr "La rotation d'affichage doit se faire par incréments de 90 degrés"
@@ -527,18 +554,27 @@ msgstr "Erreur dans l'expression régulière"
msgid "Expected a %q"
msgstr "Attendu un %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
#, fuzzy
msgid "Expected a Characteristic"
msgstr "Une 'Characteristic' est attendue"
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
#, fuzzy
msgid "Expected a UUID"
msgstr "Un UUID est attendu"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -556,12 +592,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Echec de l'obtention de mutex, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Echec de l'ajout de caractéristique, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Echec de l'ajout de service, err 0x%04x"
@@ -576,62 +617,67 @@ msgstr "Echec de l'allocation du tampon RX"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Echec de l'allocation de %d octets du tampon RX"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to change softdevice state"
msgstr "Echec de la modification de l'état du périphérique"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Impossible de poursuivre le scan, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Echec de la découverte de services"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get local address"
msgstr "Echec de l'obtention de l'adresse locale"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get softdevice state"
msgstr "Echec de l'obtention de l'état du périphérique"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
"Impossible de notifier ou d'indiquer la valeur de l'attribut, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Impossible de lire la valeur 'CCCD', err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Impossible de lire la valeur de l'attribut, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Impossible de lire la valeur de 'gatts', err 0x%04x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Echec de l'ajout de l'UUID du fournisseur, err 0x%04x"
@@ -641,42 +687,47 @@ msgstr "Echec de l'ajout de l'UUID du fournisseur, err 0x%04x"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Impossible de libérer mutex, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Impossible de commencer à diffuser, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Impossible de commencer à scanner, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Echec de l'arrêt de diffusion, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Impossible d'écrire la valeur de l'attribut, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Impossible d'écrire la valeur de 'gatts', err 0x%04x"
@@ -712,6 +763,11 @@ msgstr "La fréquence capturée est au delà des capacités. Capture en pause."
msgid "Function requires lock"
msgstr "La fonction nécessite un verrou"
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Groupe plein"
@@ -772,7 +828,7 @@ msgstr "Longueur de tampon invalide"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr "Période de capture invalide. Gamme valide: 1 à 500"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Invalid channel count"
msgstr "Nombre de canaux invalide"
@@ -781,11 +837,11 @@ msgstr "Nombre de canaux invalide"
msgid "Invalid direction."
msgstr "Direction invalide"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Fichier invalide"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Taille de bloc de formatage invalide"
@@ -823,16 +879,28 @@ msgstr "Broches invalides"
msgid "Invalid polarity"
msgstr "Polarité invalide"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Mode de lancement invalide."
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Invalid voice count"
msgstr "Nombre de voix invalide"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "Fichier WAVE invalide"
@@ -896,7 +964,7 @@ msgstr "Le délais au démarrage du micro doit être entre 0.0 et 1.0"
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -942,6 +1010,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr "Pas de support matériel pour cette broche"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr "Il n'y a plus d'espace libre sur le périphérique"
@@ -950,13 +1022,15 @@ msgstr "Il n'y a plus d'espace libre sur le périphérique"
msgid "No such file/directory"
msgstr "Fichier/dossier introuvable"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Non connecté"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Ne joue pas"
@@ -987,10 +1061,9 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
-"Seul les BMP monochromes, 8bit indexé et 16bit sont supportés: %d bpp fourni"
#: shared-bindings/_pixelbuf/PixelBuf.c
#, fuzzy
@@ -1072,6 +1145,10 @@ msgstr "Système de fichier en lecture seule"
msgid "Read-only object"
msgstr "Objet en lecture seule"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Canal droit non supporté"
@@ -1092,12 +1169,13 @@ msgstr "Mode sans-échec! Le code sauvegardé n'est pas éxecuté.\n"
msgid "SDA or SCL needs a pull up"
msgstr "SDA ou SCL a besoin d'une résistance de tirage ('pull up')"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Sample rate must be positive"
msgstr "Le taux d'échantillonage doit être positif"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Taux d'échantillonage trop élevé. Doit être inf. à %d"
@@ -1116,7 +1194,7 @@ msgstr "Tranche et valeur de tailles différentes"
msgid "Slices not supported"
msgstr "Tranches non supportées"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr "Assertion en mode 'soft-device', id: 0x%08lX, pc: 0x%08lX"
@@ -1175,20 +1253,20 @@ msgstr ""
"Le bouton 'reset' a été appuyé pendant le démarrage de CircuitPython. "
"Appuyer de nouveau pour quitter de le mode sans-échec.\n"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
"Le 'bits_per_sample' de l'échantillon ne correspond pas à celui du mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr "Le canal de l'échantillon ne correspond pas à celui du mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr "L'échantillonage de l'échantillon ne correspond pas à celui du mixer"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr "Le signe de l'échantillon ne correspond pas à celui du mixer"
@@ -1196,9 +1274,13 @@ msgstr "Le signe de l'échantillon ne correspond pas à celui du mixer"
msgid "Tile height must exactly divide bitmap height"
msgstr "La hauteur de la tuile doit diviser exactement la hauteur de l'image"
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Les indices des tuiles doivent être compris entre 0 et 255 "
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1212,11 +1294,13 @@ msgstr "Pour quitter, redémarrez la carte SVP sans "
msgid "Too many channels in sample."
msgstr "Trop de canaux dans l'échantillon."
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr "Trop de bus d'affichage"
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr "Trop d'affichages"
@@ -1236,16 +1320,16 @@ msgstr "USB occupé"
msgid "USB Error"
msgstr "Erreur USB"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
"La chaîne UUID n'est pas au format 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
"la valeur de l'UUID n'est pas une chaîne de caractères, un entier ou un "
@@ -1256,6 +1340,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr "Impossible d'allouer des tampons pour une conversion signée"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1273,7 +1362,7 @@ msgstr "Impossible de lire les données de la palette de couleurs"
msgid "Unable to write to nvm."
msgstr "Impossible d'écrire sur la mémoire non-volatile."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy
msgid "Unexpected nrfx uuid type"
msgstr "Type inattendu pour l'uuid nrfx"
@@ -1288,12 +1377,12 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr "Débit non supporté"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
#, fuzzy
msgid "Unsupported display bus type"
msgstr "Type de bus d'affichage non supporté"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Format non supporté"
@@ -1305,15 +1394,21 @@ msgstr "Opération non supportée"
msgid "Unsupported pull value."
msgstr "Valeur de tirage 'pull' non supportée."
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
"les fonctions de Viper ne supportent pas plus de 4 arguments actuellement"
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr "Index de la voix trop grand"
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr "ATTENTION: le nom de fichier de votre code a deux extensions\n"
@@ -1403,10 +1498,6 @@ msgstr "tableau/octets requis à droite"
msgid "attributes not supported yet"
msgstr "attribut pas encore supporté"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "mauvais rôle GATT"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "mauvais mode de compilation"
@@ -1435,7 +1526,7 @@ msgstr "bits doivent être 7, 8 ou 9"
msgid "bits must be 8"
msgstr "les bits doivent être 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "bits_per_sample must be 8 or 16"
msgstr "'bits_per_sample' doivent être 8 ou 16"
@@ -1450,7 +1541,7 @@ msgstr "branche hors-bornes"
msgid "buf is too small. need %d bytes"
msgstr "'buf' est trop petit. Besoin de %d octets"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr "le tampon doit être un objet bytes-like"
@@ -1672,10 +1763,6 @@ msgstr "ne peut pas réaliser un import relatif"
msgid "casting"
msgstr "typage"
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr "'characteristics' inclut un objet qui n'est pas une 'Characteristic'"
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr "tampon de caractères trop petit"
@@ -1831,7 +1918,8 @@ msgstr "argument(s) nommé(s) supplémentaire(s) donné(s)"
msgid "extra positional arguments given"
msgstr "argument(s) positionnel(s) supplémentaire(s) donné(s)"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "le fichier doit être un fichier ouvert en mode 'byte'"
@@ -1960,7 +2048,7 @@ msgstr "l'argument 2 de int() doit être >=2 et <=36"
msgid "integer required"
msgstr "entier requis"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -2058,6 +2146,10 @@ msgstr "label redéfini"
msgid "length argument not allowed for this type"
msgstr "argument 'length' non-permis pour ce type"
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "Les parties gauches et droites doivent être compatibles"
@@ -2086,6 +2178,12 @@ msgstr "tampon trop petit"
msgid "math domain error"
msgstr "erreur de domaine math"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "profondeur maximale de récursivité dépassée"
@@ -2131,7 +2229,7 @@ msgstr "doit utiliser un argument nommé pour une fonction key"
msgid "name '%q' is not defined"
msgstr "nom '%q' non défini"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "name must be a string"
msgstr "les noms doivent être des chaînes de caractère"
@@ -2178,16 +2276,17 @@ msgstr "pas de lien trouvé pour nonlocal"
msgid "no module named '%q'"
msgstr "pas de module '%q'"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
+msgstr ""
+
#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
msgid "no such attribute"
msgstr "pas de tel attribut"
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2207,7 +2306,7 @@ msgstr "argument non-nommé après */**"
msgid "non-keyword arg after keyword arg"
msgstr "argument non-nommé après argument nommé"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr "n'est pas un UUID 128 bits"
@@ -2275,6 +2374,14 @@ msgstr "chaîne de longueur impaire"
msgid "offset out of bounds"
msgstr "adresse hors limites"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2390,7 +2497,7 @@ msgstr "return attendait '%q' mais a reçu '%q'"
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2509,10 +2616,6 @@ msgstr "erreur de syntaxe dans le descripteur d'uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "le seuil doit être dans la gamme 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "indice de tuile hors limites"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() prend une séquence de longueur 9"
@@ -2525,7 +2628,7 @@ msgstr "time.struct_time() prend exactement 1 argument"
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr "timeout >100 (exprimé en secondes, pas en ms)"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#, fuzzy
msgid "timeout must be >= 0.0"
msgstr "'timeout' doit être >=0.0"
@@ -2680,7 +2783,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr "'value_count' doit être > 0"
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
@@ -2745,6 +2848,12 @@ msgstr "'step' nul"
#~ msgid "Cannot update i/f status"
#~ msgstr "le status i/f ne peut être mis à jour"
+#~ msgid "Characteristic UUID doesn't match Service UUID"
+#~ msgstr "L'UUID de 'Characteristic' ne correspond pas à l'UUID du Service"
+
+#~ msgid "Characteristic already in use by another Service."
+#~ msgstr "'Characteristic' déjà en utilisation par un autre service"
+
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Données trop volumineuses pour le paquet de diffusion"
@@ -2844,6 +2953,13 @@ msgstr "'step' nul"
#~ msgid "Only bit maps of 8 bit color or less are supported"
#~ msgstr "Seules les bitmaps de 8bits par couleur ou moins sont supportées"
+#~ msgid ""
+#~ "Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d "
+#~ "bpp given"
+#~ msgstr ""
+#~ "Seul les BMP monochromes, 8bit indexé et 16bit sont supportés: %d bpp "
+#~ "fourni"
+
#~ msgid "Only true color (24 bpp or higher) BMP supported %x"
#~ msgstr "Seul les BMP 24bits ou plus sont supportés %x"
@@ -2868,6 +2984,9 @@ msgstr "'step' nul"
#~ msgid "STA required"
#~ msgstr "'STA' requis"
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Les indices des tuiles doivent être compris entre 0 et 255 "
+
#~ msgid "UART(%d) does not exist"
#~ msgstr "UART(%d) n'existe pas"
@@ -2887,6 +3006,12 @@ msgstr "'step' nul"
#~ msgstr ""
#~ "Utilisez 'esptool' pour effacer la flash et recharger Python à la place"
+#~ msgid "Voice index too high"
+#~ msgstr "Index de la voix trop grand"
+
+#~ msgid "bad GATT role"
+#~ msgstr "mauvais rôle GATT"
+
#~ msgid "buffer too long"
#~ msgstr "tampon trop long"
@@ -2905,6 +3030,10 @@ msgstr "'step' nul"
#~ msgid "can't set STA config"
#~ msgstr "impossible de régler la config de 'STA'"
+#~ msgid "characteristics includes an object that is not a Characteristic"
+#~ msgstr ""
+#~ "'characteristics' inclut un objet qui n'est pas une 'Characteristic'"
+
#~ msgid "either pos or kw args are allowed"
#~ msgstr "soit 'pos', soit 'kw' est permis en argument"
@@ -2964,6 +3093,9 @@ msgstr "'step' nul"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "'services' inclut un object qui n'est pas un 'Service'"
+#~ msgid "tile index out of bounds"
+#~ msgstr "indice de tuile hors limites"
+
#~ msgid "too many arguments"
#~ msgstr "trop d'arguments"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 7504fb157..883c65d41 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -52,7 +52,7 @@ msgstr "indice %q fuori intervallo"
msgid "%q indices must be integers, not %s"
msgstr "gli indici %q devono essere interi, non %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
#, fuzzy
msgid "%q must be >= 1"
@@ -112,7 +112,7 @@ msgid "'%s' expects {r0, r1, ...}"
msgstr "'%s' aspetta un registro"
#: py/emitinlinextensa.c
-#, c-format
+#, fuzzy, c-format
msgid "'%s' integer %d is not within range %d..%d"
msgstr "intero '%s' non è nell'intervallo %d..%d"
@@ -219,12 +219,12 @@ msgstr "pow() con tre argmomenti non supportata"
msgid "A hardware interrupt channel is already in use"
msgstr "Un canale di interrupt hardware è già in uso"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, fuzzy, c-format
msgid "Address must be %d bytes long"
msgstr "la palette deve essere lunga 32 byte"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -256,6 +256,7 @@ msgstr "Tutti i timer per questo pin sono in uso"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -301,6 +302,10 @@ msgstr ""
"L'auto-reload è attivo. Salva i file su USB per eseguirli o entra nel REPL "
"per disabilitarlo.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr ""
@@ -314,6 +319,10 @@ msgstr "La profondità di bit deve essere multipla di 8."
msgid "Both pins must support hardware interrupts"
msgstr "Entrambi i pin devono supportare gli interrupt hardware"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "La luminosità deve essere compreso tra 0 e 255"
@@ -327,6 +336,19 @@ msgstr "Illiminazione non è regolabile"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Buffer di lunghezza non valida. Dovrebbe essere di %d bytes."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Il buffer deve essere lungo almeno 1"
@@ -337,7 +359,7 @@ msgstr "Il buffer deve essere lungo almeno 1"
msgid "Bus pin %d is already in use"
msgstr "DAC già in uso"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
#, fuzzy
msgid "Byte buffer must be 16 bytes."
msgstr "i buffer devono essere della stessa lunghezza"
@@ -355,8 +377,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr "dotstar non può essere usato con %s"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -414,15 +436,7 @@ msgstr "Impossibile ricavare la grandezza scalare di sizeof inequivocabilmente"
msgid "Cannot write without MOSI pin."
msgstr "Impossibile scrivere senza pin MOSI."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr "caratteristico UUID non assomiglia servizio UUID"
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr "caratteristico già usato da un altro servizio"
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "CharacteristicBuffer scritura non dato"
@@ -442,6 +456,10 @@ msgstr "Unità di clock in uso"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
#, fuzzy
msgid "Command must be an int between 0 and 255"
@@ -455,7 +473,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -464,11 +482,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Impossibile inizializzare l'UART"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Impossibile allocare il primo buffer"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Impossibile allocare il secondo buffer"
@@ -486,11 +504,11 @@ msgstr "DAC già in uso"
msgid "Data 0 pin must be byte aligned"
msgstr "graphic deve essere lunga 2048 byte"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy
msgid "Data too large for advertisement packet"
msgstr "Impossibile inserire dati nel pacchetto di advertisement."
@@ -499,7 +517,16 @@ msgstr "Impossibile inserire dati nel pacchetto di advertisement."
msgid "Destination capacity is smaller than destination_length."
msgstr "La capacità di destinazione è più piccola di destination_length."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -523,18 +550,27 @@ msgstr "Errore nella regex"
msgid "Expected a %q"
msgstr "Atteso un %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
#, fuzzy
msgid "Expected a Characteristic"
msgstr "Non è possibile aggiungere Characteristic."
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
#, fuzzy
msgid "Expected a UUID"
msgstr "Atteso un %q"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -552,12 +588,17 @@ msgstr ""
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
@@ -572,60 +613,65 @@ msgstr "Impossibile allocare buffer RX"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Fallita allocazione del buffer RX di %d byte"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to change softdevice state"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Impossible iniziare la scansione. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get softdevice state"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Notificamento o indicazione di attribute value fallito, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Tentative leggere attribute value fallito, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Non è possibile aggiungere l'UUID del vendor specifico da 128-bit"
@@ -635,42 +681,47 @@ msgstr "Non è possibile aggiungere l'UUID del vendor specifico da 128-bit"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Impossibile avviare advertisement. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Impossible iniziare la scansione. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Impossibile fermare advertisement. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
@@ -706,6 +757,11 @@ msgstr ""
msgid "Function requires lock"
msgstr ""
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Gruppo pieno"
@@ -765,7 +821,7 @@ msgstr "lunghezza del buffer non valida"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr "periodo di cattura invalido. Zona valida: 1 - 500"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Invalid channel count"
msgstr "Argomento non valido"
@@ -774,11 +830,11 @@ msgstr "Argomento non valido"
msgid "Invalid direction."
msgstr "Direzione non valida."
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "File non valido"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr ""
@@ -816,16 +872,28 @@ msgstr "Pin non validi"
msgid "Invalid polarity"
msgstr "Polarità non valida"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Modalità di esecuzione non valida."
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Invalid voice count"
msgstr "Tipo di servizio non valido"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "File wave non valido"
@@ -886,7 +954,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -932,6 +1000,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr "Nessun supporto hardware sul pin"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr "Non che spazio sul dispositivo"
@@ -940,13 +1012,15 @@ msgstr "Non che spazio sul dispositivo"
msgid "No such file/directory"
msgstr "Nessun file/directory esistente"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Impossible connettersi all'AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "In pausa"
@@ -975,8 +1049,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1060,6 +1134,10 @@ msgstr "Filesystem in sola lettura"
msgid "Read-only object"
msgstr "Sola lettura"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Canale destro non supportato"
@@ -1080,12 +1158,13 @@ msgstr "Modalità sicura in esecuzione! Codice salvato non in esecuzione.\n"
msgid "SDA or SCL needs a pull up"
msgstr "SDA o SCL necessitano un pull-up"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Sample rate must be positive"
msgstr "STA deve essere attiva"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr ""
@@ -1105,7 +1184,7 @@ msgstr ""
msgid "Slices not supported"
msgstr "Slice non supportate"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1154,19 +1233,19 @@ msgid ""
"exit safe mode.\n"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1174,8 +1253,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1190,11 +1273,13 @@ msgstr "Per uscire resettare la scheda senza "
msgid "Too many channels in sample."
msgstr ""
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr "Troppi schermi"
@@ -1214,15 +1299,15 @@ msgstr "USB occupata"
msgid "USB Error"
msgstr "Errore USB"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1231,6 +1316,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr "Ipossibilitato ad allocare buffer per la conversione con segno"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1248,7 +1338,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr "Imposibile scrivere su nvm."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy
msgid "Unexpected nrfx uuid type"
msgstr "indentazione inaspettata"
@@ -1262,12 +1352,12 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr "baudrate non supportato"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
#, fuzzy
msgid "Unsupported display bus type"
msgstr "tipo di bitmap non supportato"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Formato non supportato"
@@ -1279,14 +1369,20 @@ msgstr "Operazione non supportata"
msgid "Unsupported pull value."
msgstr "Valore di pull non supportato."
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Le funzioni Viper non supportano più di 4 argomenti al momento"
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr ""
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr "ATTENZIONE: Il nome del sorgente ha due estensioni\n"
@@ -1372,10 +1468,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr "attributi non ancora supportati"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1404,7 +1496,7 @@ msgstr "i bit devono essere 7, 8 o 9"
msgid "bits must be 8"
msgstr "i bit devono essere 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "bits_per_sample must be 8 or 16"
msgstr "i bit devono essere 7, 8 o 9"
@@ -1419,7 +1511,7 @@ msgstr "argomento di chr() non è in range(256)"
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr ""
@@ -1496,7 +1588,7 @@ msgid "can't assign to expression"
msgstr "impossibile assegnare all'espressione"
#: py/obj.c
-#, c-format
+#, fuzzy, c-format
msgid "can't convert %s to complex"
msgstr "non è possibile convertire a complex"
@@ -1632,10 +1724,6 @@ msgstr "impossibile effettuare l'importazione relativa"
msgid "casting"
msgstr "casting"
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr "buffer dei caratteri troppo piccolo"
@@ -1789,7 +1877,8 @@ msgstr "argomento nominato aggiuntivo fornito"
msgid "extra positional arguments given"
msgstr "argomenti posizonali extra dati"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
@@ -1919,7 +2008,7 @@ msgstr "il secondo argomanto di int() deve essere >= 2 e <= 36"
msgid "integer required"
msgstr "intero richiesto"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -2018,6 +2107,10 @@ msgstr "etichetta ridefinita"
msgid "length argument not allowed for this type"
msgstr ""
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "lhs e rhs devono essere compatibili"
@@ -2046,6 +2139,12 @@ msgstr "map buffer troppo piccolo"
msgid "math domain error"
msgstr "errore di dominio matematico"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "profondità massima di ricorsione superata"
@@ -2091,7 +2190,7 @@ msgstr ""
msgid "name '%q' is not defined"
msgstr "nome '%q'non definito"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "name must be a string"
msgstr "argomenti nominati devono essere stringhe"
@@ -2138,16 +2237,17 @@ msgstr "nessun binding per nonlocal trovato"
msgid "no module named '%q'"
msgstr "nessun modulo chiamato '%q'"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
+msgstr ""
+
#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
msgid "no such attribute"
msgstr "attributo inesistente"
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2166,7 +2266,7 @@ msgstr "argomento non nominato dopo */**"
msgid "non-keyword arg after keyword arg"
msgstr "argomento non nominato seguito da argomento nominato"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2235,6 +2335,14 @@ msgstr "stringa di lunghezza dispari"
msgid "offset out of bounds"
msgstr "indirizzo fuori limite"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2347,7 +2455,7 @@ msgstr "return aspettava '%q' ma ha ottenuto '%q'"
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2465,10 +2573,6 @@ msgstr "errore di sintassi nel descrittore uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "la soglia deve essere nell'intervallo 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2481,7 +2585,7 @@ msgstr "time.struct_time() prende esattamente un argomento"
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#, fuzzy
msgid "timeout must be >= 0.0"
msgstr "i bit devono essere 8"
@@ -2560,7 +2664,7 @@ msgid "unindent does not match any outer indentation level"
msgstr ""
#: py/objstr.c
-#, c-format
+#, fuzzy, c-format
msgid "unknown conversion specifier %c"
msgstr "specificatore di conversione %s sconosciuto"
@@ -2635,7 +2739,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
@@ -2699,6 +2803,12 @@ msgstr "zero step"
#~ msgid "Cannot update i/f status"
#~ msgstr "Impossibile aggiornare status di i/f"
+#~ msgid "Characteristic UUID doesn't match Service UUID"
+#~ msgstr "caratteristico UUID non assomiglia servizio UUID"
+
+#~ msgid "Characteristic already in use by another Service."
+#~ msgstr "caratteristico già usato da un altro servizio"
+
#, fuzzy
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Impossibile inserire dati nel pacchetto di advertisement."
diff --git a/locale/pl.po b/locale/pl.po
index dd4cf7db4..9ed76924b 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2019-03-19 18:37-0700\n"
"Last-Translator: Radomir Dopieralski <circuitpython@sheep.art.pl>\n"
"Language-Team: pl\n"
@@ -53,7 +53,7 @@ msgstr "%q poza zakresem"
msgid "%q indices must be integers, not %s"
msgstr "%q indeks musi być liczbą całkowitą, a nie %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr "%q musi być >= 1"
@@ -218,12 +218,12 @@ msgstr "3-argumentowy pow() jest niewspierany"
msgid "A hardware interrupt channel is already in use"
msgstr "Kanał przerwań sprzętowych w użyciu"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr "Adres musi mieć %d bajtów"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -254,6 +254,7 @@ msgstr "Wszystkie timery tej nóżki w użyciu"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -299,6 +300,10 @@ msgstr ""
"Samo-przeładowywanie włączone. Po prostu zapisz pliki przez USB aby je "
"uruchomić, albo wejdź w konsolę aby wyłączyć.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "Zegar bitowy i wybór słowa muszą współdzielić jednostkę zegara"
@@ -311,6 +316,10 @@ msgstr "Głębia musi być wielokrotnością 8."
msgid "Both pins must support hardware interrupts"
msgstr "Obie nóżki muszą wspierać przerwania sprzętowe"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "Jasność musi być pomiędzy 0 a 255"
@@ -324,6 +333,19 @@ msgstr "Jasność nie jest regulowana"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Zła wielkość bufora. Powinno być %d bajtów."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Bufor musi mieć długość 1 lub więcej"
@@ -334,7 +356,7 @@ msgstr "Bufor musi mieć długość 1 lub więcej"
msgid "Bus pin %d is already in use"
msgstr "Nóżka magistrali %d jest w użyciu"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr "Bufor musi mieć 16 bajtów."
@@ -351,8 +373,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr "Nie można używać dotstar z %s"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -408,15 +430,7 @@ msgstr "Wielkość skalara jest niejednoznaczna"
msgid "Cannot write without MOSI pin."
msgstr "Nie można pisać bez nóżki MOSI."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr "UUID charakterystyki inny niż UUID serwisu"
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr "Charakterystyka w użyciu w innym serwisie"
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Pisanie do CharacteristicBuffer niewspierane"
@@ -436,6 +450,10 @@ msgstr "Jednostka zegara w użyciu"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr "Kolumny muszą być typu digitalio.DigitalInOut"
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr "Komenda musi być int pomiędzy 0 a 255"
@@ -448,7 +466,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr "Nie można zdekodować ble_uuid, błąd 0x%04x"
@@ -457,11 +475,11 @@ msgstr "Nie można zdekodować ble_uuid, błąd 0x%04x"
msgid "Could not initialize UART"
msgstr "Ustawienie UART nie powiodło się"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Nie udała się alokacja pierwszego bufora"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Nie udała się alokacja drugiego bufora"
@@ -478,11 +496,11 @@ msgstr "DAC w użyciu"
msgid "Data 0 pin must be byte aligned"
msgstr "Nóżka data 0 musi być wyrównana do bajtu"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr "Fragment danych musi następować po fragmencie fmt"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr "Zbyt dużo danych pakietu rozgłoszeniowego"
@@ -490,7 +508,16 @@ msgstr "Zbyt dużo danych pakietu rozgłoszeniowego"
msgid "Destination capacity is smaller than destination_length."
msgstr "Pojemność celu mniejsza od destination_length."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr "Wyświetlacz można obracać co 90 stopni"
@@ -514,16 +541,25 @@ msgstr "Błąd w regex"
msgid "Expected a %q"
msgstr "Oczekiwano %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr "Oczekiwano charakterystyki"
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr "Oczekiwano UUID"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -537,16 +573,21 @@ msgid "Failed sending command."
msgstr ""
#: ports/nrf/sd_mutex.c
-#, c-format
+#, fuzzy, c-format
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Nie udało się uzyskać blokady, błąd 0x$04x"
-#: ports/nrf/common-hal/bleio/Service.c
-#, c-format
+#: ports/nrf/common-hal/_bleio/Service.c
+#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Nie udało się dodać charakterystyki, błąd 0x$04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Nie udało się dodać serwisu, błąd 0x%04x"
@@ -561,57 +602,62 @@ msgstr "Nie udała się alokacja bufora RX"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Nie udała się alokacja %d bajtów na bufor RX"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr "Nie udało się zmienić stanu softdevice"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Failed to discover services"
msgstr "Nie udało się odkryć serwisów"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr "Nie udało się uzyskać lokalnego adresu"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr "Nie udało się odczytać stanu softdevice"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Nie udało się powiadomić o wartości atrybutu, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Nie udało się odczytać CCCD, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Nie udało się odczytać wartości atrybutu, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Nie udało się odczytać gatts, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Nie udało się zarejestrować UUID dostawcy, błąd 0x%04x"
@@ -621,42 +667,47 @@ msgstr "Nie udało się zarejestrować UUID dostawcy, błąd 0x%04x"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Nie udało się zwolnić blokady, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Nie udało się rozpocząć skanowania, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Nie udało się zapisać atrybutu, błąd 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Nie udało się zapisać gatts, błąd 0x%04x"
@@ -692,6 +743,11 @@ msgstr "Uzyskana częstotliwość jest niemożliwa. Spauzowano."
msgid "Function requires lock"
msgstr "Funkcja wymaga blokady"
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Grupa pełna"
@@ -750,7 +806,7 @@ msgstr "Zła wielkość bufora"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr "Zły okres. Poprawny zakres to: 1 - 500"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr "Zła liczba kanałów"
@@ -758,11 +814,11 @@ msgstr "Zła liczba kanałów"
msgid "Invalid direction."
msgstr "Zły tryb"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Zły plik"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Zła wielkość fragmentu formatu"
@@ -800,15 +856,27 @@ msgstr "Złe nóżki"
msgid "Invalid polarity"
msgstr "Zła polaryzacja"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Zły tryb uruchomienia"
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr "Zła liczba głosów"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "Zły plik wave"
@@ -873,7 +941,7 @@ msgstr "Opóźnienie włączenia mikrofonu musi być w zakresie od 0.0 do 1.0"
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -919,6 +987,10 @@ msgstr ""
msgid "No hardware support on pin"
msgstr "Brak sprzętowej obsługi na nóżce"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr "Brak miejsca"
@@ -927,12 +999,14 @@ msgstr "Brak miejsca"
msgid "No such file/directory"
msgstr "Brak pliku/katalogu"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr "Nie podłączono"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Nic nie jest odtwarzane"
@@ -958,9 +1032,9 @@ msgstr "Wspierane są tylko nieskompresowane pliki BMP: wielkość nagłówka %d
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
-msgstr "Wspierane są tylko pliki BMP czarno-białe, 8bpp i 16bpp: %d bpp "
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
+msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
msgid "Only slices with step=1 (aka None) are supported"
@@ -1033,6 +1107,10 @@ msgstr "System plików tylko do odczytu"
msgid "Read-only object"
msgstr "Obiekt tylko do odczytu"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Prawy kanał jest niewspierany"
@@ -1053,11 +1131,12 @@ msgstr "Uruchomiony tryb bezpieczeństwa! Zapisany kod nie jest uruchamiany.\n"
msgid "SDA or SCL needs a pull up"
msgstr "SDA lub SCL wymagają podciągnięcia"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr "Częstotliwość próbkowania musi być dodatnia"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Zbyt wysoka częstotliwość próbkowania. Musi być mniejsza niż %d"
@@ -1076,7 +1155,7 @@ msgstr "Fragment i wartość są różnych długości."
msgid "Slices not supported"
msgstr "Fragmenty nieobsługiwane"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
@@ -1132,19 +1211,19 @@ msgstr ""
"Przycisk reset został wciśnięty podczas startu CircuitPythona. Wciśnij go "
"ponownie aby wyjść z trybu bezpieczeństwa.\n"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr "Wartość bits_per_sample nie pasuje do miksera"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr "Liczba kanałów nie pasuje do miksera "
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr "Sample rate nie pasuje do miksera"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr "Znak nie pasuje do miksera"
@@ -1152,9 +1231,13 @@ msgstr "Znak nie pasuje do miksera"
msgid "Tile height must exactly divide bitmap height"
msgstr "Wysokość bitmapy musi być wielokrotnością wysokości kafelka"
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie"
+msgid "Tile value out of bounds"
+msgstr ""
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1168,11 +1251,13 @@ msgstr "By wyjść, proszę zresetować płytkę bez "
msgid "Too many channels in sample."
msgstr "Zbyt wiele kanałów."
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr "Zbyt wiele magistrali"
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr "Zbyt wiele wyświetlaczy"
@@ -1192,15 +1277,15 @@ msgstr "USB Zajęte"
msgid "USB Error"
msgstr "Błąd USB"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr "UUID inny, niż `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr "UUID nie jest typu str, int lub bytes"
@@ -1209,6 +1294,11 @@ msgstr "UUID nie jest typu str, int lub bytes"
msgid "Unable to allocate buffers for signed conversion"
msgstr "Nie udała się alokacja buforów do konwersji ze znakiem"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1226,7 +1316,7 @@ msgstr "Nie można odczytać danych palety"
msgid "Unable to write to nvm."
msgstr "Błąd zapisu do NVM."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr "Nieoczekiwany typ nrfx uuid."
@@ -1239,11 +1329,11 @@ msgstr "Zła liczba obiektów po prawej stronie (oczekiwano %d, jest %d)."
msgid "Unsupported baudrate"
msgstr "Zła szybkość transmisji"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
msgid "Unsupported display bus type"
msgstr "Zły typ magistrali wyświetlaczy"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Zły format"
@@ -1255,14 +1345,20 @@ msgstr "Zła operacja"
msgid "Unsupported pull value."
msgstr "Zła wartość podciągnięcia."
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Funkcje Viper nie obsługują obecnie więcej niż 4 argumentów"
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr "Zbyt wysoki indeks głosu"
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr "UWAGA: Nazwa pliku ma dwa rozszerzenia\n"
@@ -1349,10 +1445,6 @@ msgstr "tablica/bytes wymagane po prawej stronie"
msgid "attributes not supported yet"
msgstr "atrybuty nie są jeszcze obsługiwane"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "zła rola GATT"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "zły tryb kompilacji"
@@ -1381,7 +1473,7 @@ msgstr "bits musi być 7, 8 lub 9"
msgid "bits must be 8"
msgstr "bits musi być 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr "bits_per_sample musi być 8 lub 16"
@@ -1394,7 +1486,7 @@ msgstr "skok poza zakres"
msgid "buf is too small. need %d bytes"
msgstr "buf zbyt mały. Wymagane %d bajtów"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr "bufor mysi być typu bytes"
@@ -1605,10 +1697,6 @@ msgstr "nie można wykonać relatywnego importu"
msgid "casting"
msgstr "rzutowanie"
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr "charakterystyki zawierają obiekt, który nie jest typu Characteristic"
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr "bufor chars zbyt mały"
@@ -1757,7 +1845,8 @@ msgstr "nadmiarowe argumenty nazwane"
msgid "extra positional arguments given"
msgstr "nadmiarowe argumenty pozycyjne"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "file musi być otwarte w trybie bajtowym"
@@ -1886,7 +1975,7 @@ msgstr "argument 2 do int() busi być pomiędzy 2 a 36"
msgid "integer required"
msgstr "wymagana liczba całkowita"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -1980,6 +2069,10 @@ msgstr "etykieta przedefiniowana"
msgid "length argument not allowed for this type"
msgstr "ten typ nie pozawala na podanie długości"
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "lewa i prawa strona powinny być kompatybilne"
@@ -2008,6 +2101,12 @@ msgstr "bufor mapy zbyt mały"
msgid "math domain error"
msgstr "błąd domeny"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "przekroczono dozwoloną głębokość rekurencji"
@@ -2053,7 +2152,7 @@ msgstr "funkcja key musi być podana jako argument nazwany"
msgid "name '%q' is not defined"
msgstr "nazwa '%q' niezdefiniowana"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr "nazwa musi być łańcuchem"
@@ -2098,16 +2197,17 @@ msgstr "brak wiązania dla zmiennej nielokalnej"
msgid "no module named '%q'"
msgstr "brak modułu o nazwie '%q'"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
+msgstr ""
+
#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
msgid "no such attribute"
msgstr "nie ma takiego atrybutu"
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2126,7 +2226,7 @@ msgstr "argument nienazwany po */**"
msgid "non-keyword arg after keyword arg"
msgstr "argument nienazwany po nazwanym"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr "to nie jest 128-bitowy UUID"
@@ -2192,6 +2292,14 @@ msgstr "łańcuch o nieparzystej długości"
msgid "offset out of bounds"
msgstr "offset poza zakresem"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2301,7 +2409,7 @@ msgstr "return oczekiwał '%q', a jest '%q'"
msgid "rsplit(None,n)"
msgstr "rsplit(None,n)"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2417,10 +2525,6 @@ msgstr "błąd składni w deskryptorze uctypes"
msgid "threshold must be in the range 0-65536"
msgstr "threshold musi być w zakresie 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "indeks kafelka poza zakresem"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() wymaga 9-elementowej sekwencji"
@@ -2433,7 +2537,7 @@ msgstr "time.struct_time() wymaga jednego argumentu"
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr "timeout > 100 (jednostkami są sekundy)"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr "timeout musi być >= 0.0"
@@ -2586,7 +2690,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr "value_count musi być > 0"
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
@@ -2633,6 +2737,12 @@ msgstr "zerowy krok"
#~ msgid "Can't connect in Peripheral mode"
#~ msgstr "Nie można się łączyć w trybie Peripheral"
+#~ msgid "Characteristic UUID doesn't match Service UUID"
+#~ msgstr "UUID charakterystyki inny niż UUID serwisu"
+
+#~ msgid "Characteristic already in use by another Service."
+#~ msgstr "Charakterystyka w użyciu w innym serwisie"
+
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Zbyt dużo danych pakietu rozgłoszeniowego"
@@ -2675,11 +2785,32 @@ msgstr "zerowy krok"
#~ msgid "Must be a Group subclass."
#~ msgstr "Musi dziedziczyć z Group."
+#~ msgid ""
+#~ "Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d "
+#~ "bpp given"
+#~ msgstr "Wspierane są tylko pliki BMP czarno-białe, 8bpp i 16bpp: %d bpp "
+
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie"
+
#~ msgid "UUID integer value not in range 0 to 0xffff"
#~ msgstr "Wartość UUID poza zakresem 0 do 0xffff"
+#~ msgid "Voice index too high"
+#~ msgstr "Zbyt wysoki indeks głosu"
+
+#~ msgid "bad GATT role"
+#~ msgstr "zła rola GATT"
+
+#~ msgid "characteristics includes an object that is not a Characteristic"
+#~ msgstr ""
+#~ "charakterystyki zawierają obiekt, który nie jest typu Characteristic"
+
#~ msgid "interval not in range 0.0020 to 10.24"
#~ msgstr "przedział poza zakresem 0.0020 do 10.24"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "obiekt typu innego niż Service w services"
+
+#~ msgid "tile index out of bounds"
+#~ msgstr "indeks kafelka poza zakresem"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 8b74349fa..a17a27539 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2018-10-02 21:14-0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -52,7 +52,7 @@ msgstr ""
msgid "%q indices must be integers, not %s"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
#, fuzzy
msgid "%q must be >= 1"
@@ -219,12 +219,12 @@ msgstr ""
msgid "A hardware interrupt channel is already in use"
msgstr "Um canal de interrupção de hardware já está em uso"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, fuzzy, c-format
msgid "Address must be %d bytes long"
msgstr "buffers devem ser o mesmo tamanho"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
msgstr ""
@@ -256,6 +256,7 @@ msgstr "Todos os temporizadores para este pino estão em uso"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -299,6 +300,10 @@ msgid ""
"disable.\n"
msgstr ""
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr ""
@@ -311,6 +316,10 @@ msgstr ""
msgid "Both pins must support hardware interrupts"
msgstr "Ambos os pinos devem suportar interrupções de hardware"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr ""
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "O brilho deve estar entre 0 e 255"
@@ -324,6 +333,19 @@ msgstr ""
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Buffer de tamanho incorreto. Deve ser %d bytes."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr ""
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr ""
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr ""
@@ -334,7 +356,7 @@ msgstr ""
msgid "Bus pin %d is already in use"
msgstr "DAC em uso"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
#, fuzzy
msgid "Byte buffer must be 16 bytes."
msgstr "buffers devem ser o mesmo tamanho"
@@ -352,8 +374,8 @@ msgstr ""
msgid "Can not use dotstar with %s"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -410,15 +432,7 @@ msgstr ""
msgid "Cannot write without MOSI pin."
msgstr "Não é possível ler sem um pino MOSI"
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr ""
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr ""
@@ -438,6 +452,10 @@ msgstr "Unidade de Clock em uso"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr ""
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr ""
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
#, fuzzy
msgid "Command must be an int between 0 and 255"
@@ -451,7 +469,7 @@ msgstr ""
msgid "Corrupt raw code"
msgstr ""
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr ""
@@ -460,11 +478,11 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Não foi possível inicializar o UART"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Não pôde alocar primeiro buffer"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Não pôde alocar segundo buffer"
@@ -481,11 +499,11 @@ msgstr "DAC em uso"
msgid "Data 0 pin must be byte aligned"
msgstr ""
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr "Pedaço de dados deve seguir o pedaço de cortes"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy
msgid "Data too large for advertisement packet"
msgstr "Não é possível ajustar dados no pacote de anúncios."
@@ -494,7 +512,16 @@ msgstr "Não é possível ajustar dados no pacote de anúncios."
msgid "Destination capacity is smaller than destination_length."
msgstr ""
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr ""
+
+#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr ""
+
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr ""
@@ -518,18 +545,27 @@ msgstr "Erro no regex"
msgid "Expected a %q"
msgstr "Esperado um"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
#, fuzzy
msgid "Expected a Characteristic"
msgstr "Não é possível adicionar Característica."
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr ""
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
#, fuzzy
msgid "Expected a UUID"
msgstr "Esperado um"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
msgstr ""
@@ -547,12 +583,17 @@ msgstr "Falha ao enviar comando."
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Não é possível ler o valor do atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, fuzzy, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Não pode parar propaganda. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Não pode parar propaganda. status: 0x%02x"
@@ -567,60 +608,65 @@ msgstr "Falha ao alocar buffer RX"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Falha ao alocar buffer RX de %d bytes"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to change softdevice state"
msgstr "Não pode parar propaganda. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Não é possível iniciar o anúncio. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy
msgid "Failed to discover services"
msgstr "Não pode parar propaganda. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, fuzzy
msgid "Failed to get softdevice state"
msgstr "Não pode parar propaganda. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, fuzzy, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Não é possível ler o valor do atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, fuzzy, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Não é possível adicionar o UUID de 128 bits específico do fornecedor."
@@ -630,42 +676,47 @@ msgstr "Não é possível adicionar o UUID de 128 bits específico do fornecedor
msgid "Failed to release mutex, err 0x%04x"
msgstr "Não é possível ler o valor do atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Não é possível iniciar o anúncio. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr ""
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, fuzzy, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Não é possível iniciar o anúncio. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, fuzzy, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Não pode parar propaganda. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, fuzzy, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
@@ -701,6 +752,11 @@ msgstr ""
msgid "Function requires lock"
msgstr ""
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr ""
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Grupo cheio"
@@ -758,7 +814,7 @@ msgstr "Arquivo inválido"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Invalid channel count"
msgstr "certificado inválido"
@@ -767,11 +823,11 @@ msgstr "certificado inválido"
msgid "Invalid direction."
msgstr "Direção inválida"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Arquivo inválido"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Tamanho do pedaço de formato inválido"
@@ -809,16 +865,28 @@ msgstr "Pinos inválidos"
msgid "Invalid polarity"
msgstr ""
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr ""
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr ""
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr ""
+
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "Invalid voice count"
msgstr "certificado inválido"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "Aqruivo de ondas inválido"
@@ -878,7 +946,7 @@ msgstr ""
msgid "Must be a %q subclass."
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
@@ -924,6 +992,10 @@ msgstr "Sem suporte de hardware no pino de clock"
msgid "No hardware support on pin"
msgstr "Nenhum suporte de hardware no pino"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr ""
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
@@ -932,13 +1004,15 @@ msgstr ""
msgid "No such file/directory"
msgstr ""
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "Not connected"
msgstr "Não é possível conectar-se ao AP"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
@@ -966,8 +1040,8 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c
@@ -1043,6 +1117,10 @@ msgstr "Sistema de arquivos somente leitura"
msgid "Read-only object"
msgstr "Somente leitura"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Canal direito não suportado"
@@ -1063,11 +1141,12 @@ msgstr "Rodando em modo seguro! Não está executando o código salvo.\n"
msgid "SDA or SCL needs a pull up"
msgstr "SDA ou SCL precisa de um pull up"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr ""
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Taxa de amostragem muito alta. Deve ser menor que %d"
@@ -1086,7 +1165,7 @@ msgstr ""
msgid "Slices not supported"
msgstr ""
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr ""
@@ -1132,19 +1211,19 @@ msgid ""
"exit safe mode.\n"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr ""
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr ""
@@ -1152,8 +1231,12 @@ msgstr ""
msgid "Tile height must exactly divide bitmap height"
msgstr ""
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr ""
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
+msgid "Tile value out of bounds"
msgstr ""
#: shared-bindings/displayio/TileGrid.c
@@ -1168,11 +1251,13 @@ msgstr "Para sair, por favor, reinicie a placa sem "
msgid "Too many channels in sample."
msgstr "Muitos canais na amostra."
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr ""
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr ""
@@ -1192,15 +1277,15 @@ msgstr "USB ocupada"
msgid "USB Error"
msgstr "Erro na USB"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr ""
@@ -1209,6 +1294,11 @@ msgstr ""
msgid "Unable to allocate buffers for signed conversion"
msgstr "Não é possível alocar buffers para conversão assinada"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr ""
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1226,7 +1316,7 @@ msgstr ""
msgid "Unable to write to nvm."
msgstr "Não é possível gravar no nvm."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr ""
@@ -1239,12 +1329,12 @@ msgstr ""
msgid "Unsupported baudrate"
msgstr "Taxa de transmissão não suportada"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
#, fuzzy
msgid "Unsupported display bus type"
msgstr "Taxa de transmissão não suportada"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Formato não suportado"
@@ -1256,12 +1346,18 @@ msgstr ""
msgid "Unsupported pull value."
msgstr ""
-#: py/emitnative.c
-msgid "Viper functions don't currently support more than 4 arguments"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
msgstr ""
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr ""
+
+#: py/emitnative.c
+msgid "Viper functions don't currently support more than 4 arguments"
msgstr ""
#: main.c
@@ -1346,10 +1442,6 @@ msgstr ""
msgid "attributes not supported yet"
msgstr "atributos ainda não suportados"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr ""
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr ""
@@ -1378,7 +1470,7 @@ msgstr ""
msgid "bits must be 8"
msgstr "bits devem ser 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
#, fuzzy
msgid "bits_per_sample must be 8 or 16"
msgstr "bits devem ser 8"
@@ -1393,7 +1485,7 @@ msgstr "Calibração está fora do intervalo"
msgid "buf is too small. need %d bytes"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr ""
@@ -1605,10 +1697,6 @@ msgstr ""
msgid "casting"
msgstr ""
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr ""
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr ""
@@ -1757,7 +1845,8 @@ msgstr "argumentos extras de palavras-chave passados"
msgid "extra positional arguments given"
msgstr "argumentos extra posicionais passados"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
@@ -1886,7 +1975,7 @@ msgstr ""
msgid "integer required"
msgstr "inteiro requerido"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
msgstr ""
@@ -1980,6 +2069,10 @@ msgstr ""
msgid "length argument not allowed for this type"
msgstr ""
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr ""
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr ""
@@ -2008,6 +2101,12 @@ msgstr ""
msgid "math domain error"
msgstr ""
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr ""
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr ""
@@ -2053,7 +2152,7 @@ msgstr ""
msgid "name '%q' is not defined"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
#, fuzzy
msgid "name must be a string"
msgstr "heap deve ser uma lista"
@@ -2099,16 +2198,17 @@ msgstr ""
msgid "no module named '%q'"
msgstr ""
-#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
-msgid "no such attribute"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
msgstr ""
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
+#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
+msgid "no such attribute"
msgstr ""
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
msgstr ""
#: py/compile.c
@@ -2127,7 +2227,7 @@ msgstr ""
msgid "non-keyword arg after keyword arg"
msgstr ""
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr ""
@@ -2193,6 +2293,14 @@ msgstr ""
msgid "offset out of bounds"
msgstr ""
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr ""
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr ""
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2302,7 +2410,7 @@ msgstr ""
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2418,10 +2526,6 @@ msgstr ""
msgid "threshold must be in the range 0-65536"
msgstr "Limite deve estar no alcance de 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr ""
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr ""
@@ -2434,7 +2538,7 @@ msgstr ""
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr ""
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#, fuzzy
msgid "timeout must be >= 0.0"
msgstr "bits devem ser 8"
@@ -2588,7 +2692,7 @@ msgstr ""
msgid "value_count must be > 0"
msgstr ""
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
msgstr ""
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index d8d11cd85..d5df0b7b0 100644
--- a/locale/zh_Latn_pinyin.po
+++ b/locale/zh_Latn_pinyin.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: circuitpython-cn\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-09 09:06-0400\n"
+"POT-Creation-Date: 2019-09-08 17:30-0500\n"
"PO-Revision-Date: 2019-04-13 10:10-0700\n"
"Last-Translator: hexthat\n"
"Language-Team: Chinese Hanyu Pinyin\n"
@@ -54,7 +54,7 @@ msgstr "%q suǒyǐn chāochū fànwéi"
msgid "%q indices must be integers, not %s"
msgstr "%q suǒyǐn bìxū shì zhěngshù, ér bùshì %s"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
#: shared-bindings/displayio/Group.c shared-bindings/displayio/Shape.c
msgid "%q must be >= 1"
msgstr "%q bìxū dàyú huò děngyú 1"
@@ -219,14 +219,14 @@ msgstr "bù zhīchí 3-arg pow ()"
msgid "A hardware interrupt channel is already in use"
msgstr "Yìngjiàn zhōngduàn tōngdào yǐ zài shǐyòng zhōng"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
#, c-format
msgid "Address must be %d bytes long"
msgstr "Dìzhǐ bìxū shì %d zì jié zhǎng"
-#: shared-bindings/bleio/Address.c
+#: shared-bindings/_bleio/Address.c
msgid "Address type out of range"
-msgstr ""
+msgstr "Dìzhǐ lèixíng chāochū fànwéi"
#: ports/nrf/common-hal/busio/I2C.c
msgid "All I2C peripherals are in use"
@@ -255,6 +255,7 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseOut.c shared-bindings/pulseio/PWMOut.c
#: shared-module/_pew/PewPew.c
msgid "All timers in use"
@@ -300,6 +301,10 @@ msgstr ""
"Zìdòng chóngxīn jiāzài. Zhǐ xū tōngguò USB bǎocún wénjiàn lái yùnxíng tāmen "
"huò shūrù REPL jìnyòng.\n"
+#: shared-module/displayio/Display.c
+msgid "Below minimum frame rate"
+msgstr "Dī yú zuìdī zhèng sùlǜ"
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
msgstr "Bǐtè shízhōng hé dānzì xuǎnzé bìxū gòngxiǎng shízhōng dānwèi"
@@ -312,6 +317,10 @@ msgstr "Bǐtè shēndù bìxū shì 8 bèi yǐshàng."
msgid "Both pins must support hardware interrupts"
msgstr "Liǎng gè yǐn jiǎo dōu bìxū zhīchí yìngjiàn zhōngduàn"
+#: shared-bindings/displayio/Display.c
+msgid "Brightness must be 0-1.0"
+msgstr "Liàngdù bìxū wèi 0-1.0"
+
#: shared-bindings/supervisor/__init__.c
msgid "Brightness must be between 0 and 255"
msgstr "Liàngdù bìxū jiè yú 0 dào 255 zhī jiān"
@@ -325,6 +334,19 @@ msgstr "Liàngdù wúfǎ tiáozhěng"
msgid "Buffer incorrect size. Should be %d bytes."
msgstr "Huǎnchōng qū dàxiǎo bù zhèngquè. Yīnggāi shì %d zì jié."
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is not a bytearray."
+msgstr "Huǎnchōng qū bùshì bytearray"
+
+#: shared-bindings/displayio/Display.c
+msgid "Buffer is too small"
+msgstr "Huǎnchōng qū tài xiǎo"
+
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+#, c-format
+msgid "Buffer length %d too big. It must be less than %d"
+msgstr "Huǎnchōng qū chángdù%d tài dà. Tā bìxū xiǎoyú%d"
+
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
msgid "Buffer must be at least length 1"
msgstr "Huǎnchōng qū bìxū zhìshǎo chángdù 1"
@@ -335,7 +357,7 @@ msgstr "Huǎnchōng qū bìxū zhìshǎo chángdù 1"
msgid "Bus pin %d is already in use"
msgstr "Zǒngxiàn yǐn jiǎo %d yǐ zài shǐyòng zhōng"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
msgstr "Zì jié huǎnchōng qū bìxū shì 16 zì jié."
@@ -345,15 +367,15 @@ msgstr "Zì jié bìxū jiè yú 0 dào 255 zhī jiān."
#: py/objtype.c
msgid "Call super().__init__() before accessing native object."
-msgstr ""
+msgstr "Zài fǎngwèn běn jī wùjiàn zhīqián diàoyòng super().__init__()"
#: shared-bindings/_pixelbuf/PixelBuf.c
#, c-format
msgid "Can not use dotstar with %s"
msgstr "Wúfǎ yǔ dotstar yīqǐ shǐyòng %s"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "Can't set CCCD for local Characteristic"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+msgid "Can't set CCCD on local Characteristic"
msgstr ""
#: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c
@@ -409,15 +431,7 @@ msgstr "Wúfǎ míngquè de huòdé biāoliàng de dàxiǎo"
msgid "Cannot write without MOSI pin."
msgstr "Wúfǎ xiě rù MOSI de yǐn jiǎo."
-#: shared-bindings/bleio/Service.c
-msgid "Characteristic UUID doesn't match Service UUID"
-msgstr "Zìfú UUID bù fúhé fúwù UUID"
-
-#: ports/nrf/common-hal/bleio/Service.c
-msgid "Characteristic already in use by another Service."
-msgstr "Qítā fúwù bùmén yǐ shǐyòng de gōngnéng."
-
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "CharacteristicBuffer writing not provided"
msgstr "Wèi tígōng zìfú huǎncún xiě rù"
@@ -437,19 +451,23 @@ msgstr "Shǐyòng shízhōng dānwèi"
msgid "Column entry must be digitalio.DigitalInOut"
msgstr "Liè tiáomù bìxū shì digitalio.DigitalInOut"
+#: shared-bindings/displayio/I2CDisplay.c
+msgid "Command must be 0-255"
+msgstr "Mìnglìng bìxū wèi 0-255"
+
#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
msgid "Command must be an int between 0 and 255"
msgstr "Mìnglìng bìxū shì 0 dào 255 zhī jiān de int"
#: py/persistentcode.c
msgid "Corrupt .mpy file"
-msgstr ""
+msgstr "Fǔbài de .mpy wénjiàn"
#: py/emitglue.c
msgid "Corrupt raw code"
-msgstr ""
+msgstr "Sǔnhuài de yuánshǐ dàimǎ"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Could not decode ble_uuid, err 0x%04x"
msgstr "Wúfǎ jiěmǎ kě dú_uuid, err 0x%04x"
@@ -458,11 +476,11 @@ msgstr "Wúfǎ jiěmǎ kě dú_uuid, err 0x%04x"
msgid "Could not initialize UART"
msgstr "Wúfǎ chūshǐhuà UART"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate first buffer"
msgstr "Wúfǎ fēnpèi dì yī gè huǎnchōng qū"
-#: shared-module/audioio/Mixer.c shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
msgid "Couldn't allocate second buffer"
msgstr "Wúfǎ fēnpèi dì èr gè huǎnchōng qū"
@@ -479,11 +497,11 @@ msgstr "Fā yuán huì yǐjīng shǐyòng"
msgid "Data 0 pin must be byte aligned"
msgstr "Shùjù 0 de yǐn jiǎo bìxū shì zì jié duìqí"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Data chunk must follow fmt chunk"
msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
msgid "Data too large for advertisement packet"
msgstr "Guǎnggào bāo de shùjù tài dà"
@@ -491,7 +509,16 @@ msgstr "Guǎnggào bāo de shùjù tài dà"
msgid "Destination capacity is smaller than destination_length."
msgstr "Mùbiāo róngliàng xiǎoyú mùdì de_chángdù."
+#: ports/nrf/common-hal/audiobusio/I2SOut.c
+msgid "Device in use"
+msgstr "Zhèngzài shǐyòng de shèbèi"
+
#: shared-bindings/displayio/Display.c
+msgid "Display must have a 16 bit colorspace."
+msgstr "Xiǎnshì bìxū jùyǒu 16 wèi yánsè kōngjiān."
+
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Display rotation must be in 90 degree increments"
msgstr "Xiǎnshì xuánzhuǎn bìxū 90 dù jiā xīn"
@@ -515,18 +542,27 @@ msgstr "Zhèngzé biǎodá shì cuòwù"
msgid "Expected a %q"
msgstr "Yùqí %q"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Descriptor.c
msgid "Expected a Characteristic"
msgstr "Yùqí de tèdiǎn"
-#: shared-bindings/bleio/Characteristic.c shared-bindings/bleio/Descriptor.c
-#: shared-bindings/bleio/Service.c
+#: shared-bindings/_bleio/Service.c
+msgid "Expected a Peripheral"
+msgstr "Qídài yīgè wàiwéi shèbèi"
+
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Expected a Service"
+msgstr "Yùqí fúwù"
+
+#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c
+#: shared-bindings/_bleio/Service.c
msgid "Expected a UUID"
msgstr "Yùqí UUID"
-#: shared-bindings/bleio/Central.c
+#: shared-bindings/_bleio/Central.c
msgid "Expected an Address"
-msgstr ""
+msgstr "Qídài yīgè dìzhǐ"
#: shared-module/_pixelbuf/PixelBuf.c
#, c-format
@@ -535,19 +571,24 @@ msgstr "Qīwàng de chángdù wèi %d de yuán zǔ, dédào %d"
#: shared-bindings/ps2io/Ps2.c
msgid "Failed sending command."
-msgstr ""
+msgstr "Fāsòng mìnglìng shībài."
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to acquire mutex, err 0x%04x"
msgstr "Wúfǎ huòdé mutex, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Service.c
+#: ports/nrf/common-hal/_bleio/Service.c
#, c-format
msgid "Failed to add characteristic, err 0x%04x"
msgstr "Tiānjiā tèxìng shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#, c-format
+msgid "Failed to add descriptor, err 0x%04x"
+msgstr "Wúfǎ tiānjiā miáoshù fú, err 0x%04x"
+
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to add service, err 0x%04x"
msgstr "Tiānjiā fúwù shībài, err 0x%04x"
@@ -562,57 +603,62 @@ msgstr "Fēnpèi RX huǎnchōng shībài"
msgid "Failed to allocate RX buffer of %d bytes"
msgstr "Fēnpèi RX huǎnchōng qū%d zì jié shībài"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to change softdevice state"
msgstr "Gēnggǎi ruǎn shèbèi zhuàngtài shībài"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to configure advertising, err 0x%04x"
-msgstr ""
+msgstr "Wúfǎ pèizhì guǎnggào, cuòwù 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
msgid "Failed to connect: timeout"
-msgstr ""
+msgstr "Liánjiē shībài: Chāoshí"
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to continue scanning, err 0x%04x"
msgstr "Jìxù sǎomiáo shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Failed to discover services"
msgstr "Fāxiàn fúwù shībài"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get local address"
msgstr "Huòqǔ běndì dìzhǐ shībài"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Failed to get softdevice state"
msgstr "Wúfǎ huòdé ruǎnjiàn shèbèi zhuàngtài"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to notify or indicate attribute value, err 0x%04x"
msgstr "Wúfǎ tōngzhī huò xiǎnshì shǔxìng zhí, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+msgid "Failed to pair"
+msgstr "Pèiduì shībài"
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to read CCCD value, err 0x%04x"
msgstr "Dòu qǔ CCCD zhí, err 0x%04x shībài"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
#, c-format
msgid "Failed to read attribute value, err 0x%04x"
msgstr "Dòu qǔ shǔxìng zhí shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to read gatts value, err 0x%04x"
msgstr "Wúfǎ dòu qǔ gatts zhí, err 0x%04x"
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
#, c-format
msgid "Failed to register Vendor-Specific UUID, err 0x%04x"
msgstr "Wúfǎ zhùcè màizhǔ tèdìng de UUID, err 0x%04x"
@@ -622,42 +668,47 @@ msgstr "Wúfǎ zhùcè màizhǔ tèdìng de UUID, err 0x%04x"
msgid "Failed to release mutex, err 0x%04x"
msgstr "Wúfǎ shìfàng mutex, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to set device name, err 0x%04x"
-msgstr ""
+msgstr "Wúfǎ shèzhì shèbèi míngchēng, cuòwù 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to start advertising, err 0x%04x"
msgstr "Qǐdòng guǎnggào shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Central.c
+#: ports/nrf/common-hal/_bleio/Central.c
#, c-format
msgid "Failed to start connecting, error 0x%04x"
-msgstr ""
+msgstr "Wúfǎ kāishǐ liánjiē, cuòwù 0x%04x"
-#: ports/nrf/common-hal/bleio/Scanner.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
+#, c-format
+msgid "Failed to start pairing, error 0x%04x"
+msgstr "Wúfǎ kāishǐ pèiduì, cuòwù 0x%04x"
+
+#: ports/nrf/common-hal/_bleio/Scanner.c
#, c-format
msgid "Failed to start scanning, err 0x%04x"
msgstr "Qǐdòng sǎomiáo shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Peripheral.c
+#: ports/nrf/common-hal/_bleio/Peripheral.c
#, c-format
msgid "Failed to stop advertising, err 0x%04x"
msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
#, c-format
msgid "Failed to write CCCD, err 0x%04x"
-msgstr ""
+msgstr "Wúfǎ xiě rù CCCD, cuòwù 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write attribute value, err 0x%04x"
msgstr "Xiě rù shǔxìng zhí shībài, err 0x%04x"
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/__init__.c
#, c-format
msgid "Failed to write gatts value, err 0x%04x"
msgstr "Xiě rù gatts zhí,err 0x%04x shībài"
@@ -693,6 +744,11 @@ msgstr "Pínlǜ bǔhuò gāo yú nénglì. Bǔhuò zàntíng."
msgid "Function requires lock"
msgstr "Hánshù xūyào suǒdìng"
+#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Group already used"
+msgstr "Jítuán yǐjīng shǐyòngguò"
+
#: shared-module/displayio/Group.c
msgid "Group full"
msgstr "Fēnzǔ yǐ mǎn"
@@ -751,7 +807,7 @@ msgstr "Wúxiào de huǎnchōng qū dàxiǎo"
msgid "Invalid capture period. Valid range: 1 - 500"
msgstr "Wúxiào de bǔhuò zhōuqí. Yǒuxiào fànwéi: 1-500"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid channel count"
msgstr "Wúxiào de tōngdào jìshù"
@@ -759,11 +815,11 @@ msgstr "Wúxiào de tōngdào jìshù"
msgid "Invalid direction."
msgstr "Wúxiào de fāngxiàng."
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid file"
msgstr "Wúxiào de wénjiàn"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid format chunk size"
msgstr "Géshì kuài dàxiǎo wúxiào"
@@ -801,15 +857,27 @@ msgstr "Wúxiào de yǐn jiǎo"
msgid "Invalid polarity"
msgstr "Wúxiào liǎng jí zhí"
+#: shared-bindings/_bleio/Characteristic.c
+msgid "Invalid properties"
+msgstr "Wúxiào de shǔxìng"
+
#: shared-bindings/microcontroller/__init__.c
msgid "Invalid run mode."
msgstr "Wúxiào de yùnxíng móshì."
-#: shared-bindings/audioio/Mixer.c
+#: shared-module/_bleio/Attribute.c
+msgid "Invalid security_mode"
+msgstr "Ānquán móshì wúxiào"
+
+#: shared-bindings/audiomixer/Mixer.c
+msgid "Invalid voice"
+msgstr "Yǔyīn wúxiào"
+
+#: shared-bindings/audiomixer/Mixer.c
msgid "Invalid voice count"
msgstr "Wúxiào de yǔyīn jìshù"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Invalid wave file"
msgstr "Wúxiào de làng làngcháo wénjiàn"
@@ -819,7 +887,7 @@ msgstr "Guānjiàn zì arg de LHS bìxū shì id"
#: shared-module/displayio/Group.c
msgid "Layer already in a group."
-msgstr ""
+msgstr "Tú céng yǐjīng zài yīgè zǔ zhōng."
#: shared-module/displayio/Group.c
msgid "Layer must be a Group or TileGrid subclass."
@@ -871,11 +939,11 @@ msgstr "Màikèfēng qǐdòng yánchí bìxū zài 0.0 Dào 1.0 De fànwéi nèi
#: shared-bindings/displayio/Group.c
msgid "Must be a %q subclass."
-msgstr ""
+msgstr "Bìxū shì %q zi lèi."
-#: ports/nrf/common-hal/bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
-msgstr ""
+msgstr "Zhège tèzhēng méiyǒu CCCD"
#: ports/atmel-samd/common-hal/analogio/AnalogOut.c
msgid "No DAC on chip"
@@ -912,13 +980,17 @@ msgstr "Méiyǒu kěyòng de yìngjiàn suíjī"
#: ports/atmel-samd/common-hal/ps2io/Ps2.c
msgid "No hardware support on clk pin"
-msgstr ""
+msgstr "Shízhōng yǐn jiǎo wú yìngjiàn zhīchí"
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
msgstr "Méiyǒu zài yǐn jiǎo shàng de yìngjiàn zhīchí"
+#: shared-module/touchio/TouchIn.c
+msgid "No pulldown on pin; 1Mohm recommended"
+msgstr "Yǐn jiǎo shàng méiyǒu xiàlā; 1Mohm tuījiàn"
+
#: py/moduerrno.c
msgid "No space left on device"
msgstr "Shèbèi shàng méiyǒu kònggé"
@@ -927,12 +999,14 @@ msgstr "Shèbèi shàng méiyǒu kònggé"
msgid "No such file/directory"
msgstr "Méiyǒu cǐ lèi wénjiàn/mùlù"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "Not connected"
msgstr "Wèi liánjiē"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
+#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr "Wèi bòfàng"
@@ -961,10 +1035,9 @@ msgstr ""
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
msgid ""
-"Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp "
-"given"
+"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: "
+"%d bpp given"
msgstr ""
-"Jǐn zhīchí dān sè, suǒyǐn 8bpp hé 16bpp huò gèng dà de BMP: %d bpp tígōng"
#: shared-bindings/_pixelbuf/PixelBuf.c
msgid "Only slices with step=1 (aka None) are supported"
@@ -1004,7 +1077,7 @@ msgstr "Zài wénjiàn xìtǒng shàng tiānjiā rènhé mókuài\n"
#: shared-bindings/ps2io/Ps2.c
msgid "Pop from an empty Ps2 buffer"
-msgstr ""
+msgstr "Cóng kōng de Ps2 huǎnchōng qū dànchū"
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
@@ -1038,6 +1111,10 @@ msgstr "Zhǐ dú wénjiàn xìtǒng"
msgid "Read-only object"
msgstr "Zhǐ dú duìxiàng"
+#: shared-bindings/displayio/EPaperDisplay.c
+msgid "Refresh too soon"
+msgstr "Shuāxīn tài kuàile"
+
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
msgid "Right channel unsupported"
msgstr "Bù zhīchí yòu tōngdào"
@@ -1058,11 +1135,12 @@ msgstr "Zài ānquán móshì xià yùnxíng! Bù yùnxíng yǐ bǎocún de dài
msgid "SDA or SCL needs a pull up"
msgstr "SDA huò SCL xūyào lādòng"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "Sample rate must be positive"
msgstr "Cǎiyàng lǜ bìxū wèi zhèng shù"
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
+#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#, c-format
msgid "Sample rate too high. It must be less than %d"
msgstr "Cǎiyàng lǜ tài gāo. Tā bìxū xiǎoyú %d"
@@ -1081,7 +1159,7 @@ msgstr "Qiēpiàn hé zhí bùtóng chángdù."
msgid "Slices not supported"
msgstr "Qiēpiàn bù shòu zhīchí"
-#: ports/nrf/common-hal/bleio/Adapter.c
+#: ports/nrf/common-hal/_bleio/Adapter.c
#, c-format
msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX"
msgstr "Ruǎn shèbèi wéihù, id: 0X%08lX, pc: 0X%08lX"
@@ -1117,6 +1195,8 @@ msgid ""
"The `microcontroller` module was used to boot into safe mode. Press reset to "
"exit safe mode.\n"
msgstr ""
+"“Wēi kòngzhì qì” mókuài yòng yú qǐdòng ānquán móshì. Àn chóng zhì kě tuìchū "
+"ānquán móshì.\n"
#: supervisor/shared/safe_mode.c
msgid ""
@@ -1137,19 +1217,19 @@ msgstr ""
"Qǐdòng CircuitPython shí, chóng zhì ànniǔ bèi àn xià. Zàicì àn xià yǐ tuìchū "
"ānquán móshì\n"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
msgstr "Yàngběn de bits_per_sample yǔ hǔn yīn qì bù pǐpèi"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's channel count does not match the mixer's"
msgstr "Yàngběn de píndào jìshù yǔ hǔn yīn qì bù xiāngfú"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's sample rate does not match the mixer's"
msgstr "Yàngběn de yàngběn sùdù yǔ hǔn yīn qì de xiāngchà bù pǐpèi"
-#: shared-module/audioio/Mixer.c
+#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's signedness does not match the mixer's"
msgstr "Yàngběn de qiānmíng yǔ hǔn yīn qì de qiānmíng bù pǐpèi"
@@ -1157,9 +1237,13 @@ msgstr "Yàngběn de qiānmíng yǔ hǔn yīn qì de qiānmíng bù pǐpèi"
msgid "Tile height must exactly divide bitmap height"
msgstr "Píng pū gāodù bìxū huàfēn wèi tú gāodù"
+#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
+msgid "Tile index out of bounds"
+msgstr "Píng pū zhǐshù chāochū fànwéi"
+
#: shared-bindings/displayio/TileGrid.c
-msgid "Tile indices must be 0 - 255"
-msgstr "Píng pū zhǐshù bìxū wèi 0 - 255"
+msgid "Tile value out of bounds"
+msgstr "Píng pū zhí chāochū fànwéi"
#: shared-bindings/displayio/TileGrid.c
msgid "Tile width must exactly divide bitmap width"
@@ -1173,11 +1257,13 @@ msgstr "Yào tuìchū, qǐng chóng zhì bǎnkuài ér bùyòng "
msgid "Too many channels in sample."
msgstr "Chōuyàng zhōng de píndào tài duō."
-#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/ParallelBus.c
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
msgid "Too many display busses"
msgstr "Xiǎnshì zǒngxiàn tài duōle"
#: shared-bindings/displayio/Display.c
+#: shared-bindings/displayio/EPaperDisplay.c
msgid "Too many displays"
msgstr "Xiǎnshì tài duō"
@@ -1197,15 +1283,15 @@ msgstr "USB máng"
msgid "USB Error"
msgstr "USB Cuòwù"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID integer value must be 0-0xffff"
-msgstr ""
+msgstr "UUID zhěngshù zhí bìxū wèi 0-0xffff"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
msgstr "UUID Zìfú chuàn bùshì 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "UUID value is not str, int or byte buffer"
msgstr "UUID zhí bùshì str,int huò zì jié huǎnchōng qū"
@@ -1214,6 +1300,11 @@ msgstr "UUID zhí bùshì str,int huò zì jié huǎnchōng qū"
msgid "Unable to allocate buffers for signed conversion"
msgstr "Wúfǎ fēnpèi huǎnchōng qū yòng yú qiānmíng zhuǎnhuàn"
+#: shared-module/displayio/I2CDisplay.c
+#, c-format
+msgid "Unable to find I2C Display at %x"
+msgstr "Wúfǎ zài%x zhǎodào I2C xiǎnshìqì"
+
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
msgid "Unable to find free GCLK"
@@ -1231,7 +1322,7 @@ msgstr "Wúfǎ dòu qǔ sè tiáo shùjù"
msgid "Unable to write to nvm."
msgstr "Wúfǎ xiě rù nvm."
-#: ports/nrf/common-hal/bleio/UUID.c
+#: ports/nrf/common-hal/_bleio/UUID.c
msgid "Unexpected nrfx uuid type"
msgstr "Yìwài de nrfx uuid lèixíng"
@@ -1244,11 +1335,11 @@ msgstr "RHS (yùqí %d, huòdé %d) shàng wèi pǐpèi de xiàngmù."
msgid "Unsupported baudrate"
msgstr "Bù zhīchí de baudrate"
-#: shared-module/displayio/Display.c
+#: shared-module/displayio/display_core.c
msgid "Unsupported display bus type"
msgstr "Bù zhīchí de gōnggòng qìchē lèixíng"
-#: shared-module/audioio/WaveFile.c
+#: shared-module/audiocore/WaveFile.c
msgid "Unsupported format"
msgstr "Bù zhīchí de géshì"
@@ -1260,14 +1351,20 @@ msgstr "Bù zhīchí de cāozuò"
msgid "Unsupported pull value."
msgstr "Bù zhīchí de lādòng zhí."
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length != required fixed length"
+msgstr "Zhí chángdù != Suǒ xū de gùdìng chángdù"
+
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+msgid "Value length > max_length"
+msgstr "Zhí chángdù > zuìdà chángdù"
+
#: py/emitnative.c
msgid "Viper functions don't currently support more than 4 arguments"
msgstr "Viper hánshù mùqián bù zhīchí chāoguò 4 gè cānshù"
-#: shared-module/audioio/Mixer.c
-msgid "Voice index too high"
-msgstr "Yǔyīn suǒyǐn tài gāo"
-
#: main.c
msgid "WARNING: Your code filename has two extensions\n"
msgstr "Jǐnggào: Nǐ de dàimǎ wénjiàn míng yǒu liǎng gè kuòzhǎn míng\n"
@@ -1357,10 +1454,6 @@ msgstr "yòu cè xūyào shùzǔ/zì jié"
msgid "attributes not supported yet"
msgstr "shǔxìng shàngwèi zhīchí"
-#: ports/nrf/common-hal/bleio/Characteristic.c
-msgid "bad GATT role"
-msgstr "zǒng xiédìng de bùliáng juésè"
-
#: py/builtinevex.c
msgid "bad compile mode"
msgstr "biānyì móshì cuòwù"
@@ -1389,7 +1482,7 @@ msgstr "bǐtè bìxū shì 7,8 huò 9"
msgid "bits must be 8"
msgstr "bǐtè bìxū shì 8"
-#: shared-bindings/audioio/Mixer.c
+#: shared-bindings/audiomixer/Mixer.c
msgid "bits_per_sample must be 8 or 16"
msgstr "měi jiàn yàngběn bìxū wèi 8 huò 16"
@@ -1402,7 +1495,7 @@ msgstr "fēnzhī bùzài fànwéi nèi"
msgid "buf is too small. need %d bytes"
msgstr "huǎnchōng tài xiǎo. Xūyào%d zì jié"
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid "buffer must be a bytes-like object"
msgstr "huǎnchōng qū bìxū shì zì jié lèi duìxiàng"
@@ -1613,10 +1706,6 @@ msgstr "wúfǎ zhíxíng xiāngguān dǎorù"
msgid "casting"
msgstr "tóuyǐng"
-#: shared-bindings/bleio/Service.c
-msgid "characteristics includes an object that is not a Characteristic"
-msgstr "tèxìng bāokuò bùshì zìfú de wùtǐ"
-
#: shared-bindings/_stage/Text.c
msgid "chars buffer too small"
msgstr "zìfú huǎnchōng qū tài xiǎo"
@@ -1767,7 +1856,8 @@ msgstr "éwài de guānjiàn cí cānshù"
msgid "extra positional arguments given"
msgstr "gěi chūle éwài de wèizhì cānshù"
-#: shared-bindings/audioio/WaveFile.c shared-bindings/displayio/OnDiskBitmap.c
+#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "wénjiàn bìxū shì zài zì jié móshì xià dǎkāi de wénjiàn"
@@ -1896,10 +1986,10 @@ msgstr "zhěngshù() cānshù 2 bìxū > = 2 qiě <= 36"
msgid "integer required"
msgstr "xūyào zhěngshù"
-#: shared-bindings/bleio/Peripheral.c shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c
#, c-format
msgid "interval must be in range %s-%s"
-msgstr ""
+msgstr "Jiàngé bìxū zài %s-%s fànwéi nèi"
#: extmod/machine_i2c.c
msgid "invalid I2C peripheral"
@@ -1991,6 +2081,10 @@ msgstr "biāoqiān chóngxīn dìngyì"
msgid "length argument not allowed for this type"
msgstr "bù yǔnxǔ gāi lèixíng de chángdù cānshù"
+#: shared-bindings/audiomixer/MixerVoice.c
+msgid "level must be between 0 and 1"
+msgstr "Level bìxū jiè yú 0 hé 1 zhī jiān"
+
#: py/objarray.c
msgid "lhs and rhs should be compatible"
msgstr "lhs hé rhs yīnggāi jiānróng"
@@ -2019,6 +2113,12 @@ msgstr "dìtú huǎnchōng qū tài xiǎo"
msgid "math domain error"
msgstr "shùxué yù cuòwù"
+#: ports/nrf/common-hal/_bleio/Characteristic.c
+#: ports/nrf/common-hal/_bleio/Descriptor.c
+#, c-format
+msgid "max_length must be 0-%d when fixed_length is %s"
+msgstr "Dāng gùdìng chángdù wèi %s shí, zuìdà chángdù bìxū wèi 0-%d"
+
#: py/runtime.c
msgid "maximum recursion depth exceeded"
msgstr "chāochū zuìdà dìguī shēndù"
@@ -2064,7 +2164,7 @@ msgstr "bìxū shǐyòng guānjiàn cí cānshù"
msgid "name '%q' is not defined"
msgstr "míngchēng '%q' wèi dìngyì"
-#: shared-bindings/bleio/Peripheral.c
+#: shared-bindings/_bleio/Peripheral.c
msgid "name must be a string"
msgstr "míngchēng bìxū shì yīgè zìfú chuàn"
@@ -2110,17 +2210,18 @@ msgstr "zhǎo bù dào fēi běndì de bǎng dìng"
msgid "no module named '%q'"
msgstr "méiyǒu mókuài '%q'"
+#: shared-bindings/displayio/FourWire.c shared-bindings/displayio/I2CDisplay.c
+#: shared-bindings/displayio/ParallelBus.c
+msgid "no reset pin available"
+msgstr "Méiyǒu kěyòng de fùwèi yǐn jiǎo"
+
#: py/runtime.c shared-bindings/_pixelbuf/__init__.c
msgid "no such attribute"
msgstr "méiyǒu cǐ shǔxìng"
-#: shared-bindings/bleio/Peripheral.c
-msgid "non-Service found in services"
-msgstr ""
-
-#: ports/nrf/common-hal/bleio/Central.c
-msgid "non-UUID found in service_uuids"
-msgstr ""
+#: ports/nrf/common-hal/_bleio/__init__.c
+msgid "non-UUID found in service_uuids_whitelist"
+msgstr "Zài service_uuids bái míngdān zhōng zhǎodào fēi UUID"
#: py/compile.c
msgid "non-default argument follows default argument"
@@ -2138,7 +2239,7 @@ msgstr "zài */** zhīhòu fēi guānjiàn cí cānshù"
msgid "non-keyword arg after keyword arg"
msgstr "guānjiàn zì cānshù zhīhòu de fēi guānjiàn zì cānshù"
-#: shared-bindings/bleio/UUID.c
+#: shared-bindings/_bleio/UUID.c
msgid "not a 128-bit UUID"
msgstr "bùshì 128 wèi UUID"
@@ -2204,6 +2305,14 @@ msgstr "jīshù zìfú chuàn"
msgid "offset out of bounds"
msgstr "piānlí biānjiè"
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only bit_depth=16 is supported"
+msgstr "Jǐn zhīchí wèi shēndù = 16"
+
+#: ports/nrf/common-hal/audiobusio/PDMIn.c
+msgid "only sample_rate=16000 is supported"
+msgstr "Jǐn zhīchí cǎiyàng lǜ = 16000"
+
#: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c
#: shared-bindings/nvm/ByteArray.c
msgid "only slices with step=1 (aka None) are supported"
@@ -2312,7 +2421,7 @@ msgstr "fǎnhuí yùqí de '%q' dàn huòdéle '%q'"
msgid "rsplit(None,n)"
msgstr ""
-#: shared-bindings/audioio/RawSample.c
+#: shared-bindings/audiocore/RawSample.c
msgid ""
"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or "
"'B'"
@@ -2429,10 +2538,6 @@ msgstr "uctypes miáoshù fú zhōng de yǔfǎ cuòwù"
msgid "threshold must be in the range 0-65536"
msgstr "yùzhí bìxū zài fànwéi 0-65536"
-#: shared-bindings/displayio/TileGrid.c
-msgid "tile index out of bounds"
-msgstr "kuài suǒyǐn chāochū fànwéi"
-
#: shared-bindings/time/__init__.c
msgid "time.struct_time() takes a 9-sequence"
msgstr "time.struct_time() xūyào 9 xùliè"
@@ -2445,7 +2550,7 @@ msgstr "time.struct_time() xūyào wánquán 1 cānshù"
msgid "timeout >100 (units are now seconds, not msecs)"
msgstr "chāoshí >100 (dānwèi shì miǎo, ér bùshì háomiǎo)"
-#: shared-bindings/bleio/CharacteristicBuffer.c
+#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
msgstr "chāoshí bìxū shì >= 0.0"
@@ -2528,7 +2633,7 @@ msgid "unknown conversion specifier %c"
msgstr "wèizhī de zhuǎnhuàn biāozhù %c"
#: py/objstr.c
-#, c-format
+#, fuzzy, c-format
msgid "unknown format code '%c' for object of type '%s'"
msgstr "lèixíng '%s' duìxiàng wèizhī de géshì dàimǎ '%c'"
@@ -2592,15 +2697,15 @@ msgstr "bù zhīchí de lèixíng wèi %q: '%s', '%s'"
#: py/objint.c
#, c-format
msgid "value must fit in %d byte(s)"
-msgstr ""
+msgstr "Zhí bìxū fúhé %d zì jié"
#: shared-bindings/displayio/Bitmap.c
msgid "value_count must be > 0"
msgstr "zhí jìshù bìxū wèi > 0"
-#: shared-bindings/bleio/Scanner.c
+#: shared-bindings/_bleio/Scanner.c
msgid "window must be <= interval"
-msgstr ""
+msgstr "Chuāngkǒu bìxū shì <= jiàngé"
#: shared-bindings/_pixelbuf/PixelBuf.c
msgid "write_args must be a list, tuple, or None"
@@ -2645,6 +2750,15 @@ msgstr "líng bù"
#~ msgid "Can't connect in Peripheral mode"
#~ msgstr "Wúfǎ zài biānyuán móshì zhōng liánjiē"
+#~ msgid "Can't set CCCD for local Characteristic"
+#~ msgstr "Wúfǎ wéi běndì tèzhēng shèzhì CCCD"
+
+#~ msgid "Characteristic UUID doesn't match Service UUID"
+#~ msgstr "Zìfú UUID bù fúhé fúwù UUID"
+
+#~ msgid "Characteristic already in use by another Service."
+#~ msgstr "Qítā fúwù bùmén yǐ shǐyòng de gōngnéng."
+
#~ msgid "Data too large for the advertisement packet"
#~ msgstr "Guǎnggào bāo de shùjù tài dà"
@@ -2699,9 +2813,27 @@ msgstr "líng bù"
#~ msgid "Only bit maps of 8 bit color or less are supported"
#~ msgstr "Jǐn zhīchí 8 wèi yánsè huò xiǎoyú"
+#~ msgid ""
+#~ "Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d "
+#~ "bpp given"
+#~ msgstr ""
+#~ "Jǐn zhīchí dān sè, suǒyǐn 8bpp hé 16bpp huò gèng dà de BMP: %d bpp tígōng"
+
+#~ msgid "Tile indices must be 0 - 255"
+#~ msgstr "Píng pū zhǐshù bìxū wèi 0 - 255"
+
#~ msgid "UUID integer value not in range 0 to 0xffff"
#~ msgstr "UUID zhěngshù zhí bùzài fànwéi 0 zhì 0xffff"
+#~ msgid "Voice index too high"
+#~ msgstr "Yǔyīn suǒyǐn tài gāo"
+
+#~ msgid "bad GATT role"
+#~ msgstr "zǒng xiédìng de bùliáng juésè"
+
+#~ msgid "characteristics includes an object that is not a Characteristic"
+#~ msgstr "tèxìng bāokuò bùshì zìfú de wùtǐ"
+
#~ msgid "expected a DigitalInOut"
#~ msgstr "qídài de DigitalInOut"
@@ -2714,6 +2846,9 @@ msgstr "líng bù"
#~ msgid "services includes an object that is not a Service"
#~ msgstr "fúwù bāokuò yīgè bùshì fúwù de wùjiàn"
+#~ msgid "tile index out of bounds"
+#~ msgstr "kuài suǒyǐn chāochū fànwéi"
+
#~ msgid "too many arguments"
#~ msgstr "tài duō cānshù"
diff --git a/main.c b/main.c
index 6d7502ba4..6b56f5ff6 100755
--- a/main.c
+++ b/main.c
@@ -45,7 +45,6 @@
#include "background.h"
#include "mpconfigboard.h"
-#include "shared-module/displayio/__init__.h"
#include "supervisor/cpu.h"
#include "supervisor/memory.h"
#include "supervisor/port.h"
@@ -58,6 +57,10 @@
#include "supervisor/shared/stack.h"
#include "supervisor/serial.h"
+#if CIRCUITPY_DISPLAYIO
+#include "shared-module/displayio/__init__.h"
+#endif
+
#if CIRCUITPY_NETWORK
#include "shared-module/network/__init__.h"
#endif
@@ -187,7 +190,9 @@ void cleanup_after_vm(supervisor_allocation* heap) {
supervisor_move_memory();
reset_port();
+ #if CIRCUITPY_BOARD
reset_board_busses();
+ #endif
reset_board();
reset_status_led();
}
@@ -248,6 +253,9 @@ bool run_code_py(safe_mode_t safe_mode) {
}
bool serial_connected_before_animation = false;
+ #if CIRCUITPY_DISPLAYIO
+ bool refreshed_epaper_display = false;
+ #endif
rgb_status_animation_t animation;
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
while (true) {
@@ -285,6 +293,13 @@ bool run_code_py(safe_mode_t safe_mode) {
}
serial_connected_before_animation = serial_connected();
+ // Refresh the ePaper display if we have one. That way it'll show an error message.
+ #if CIRCUITPY_DISPLAYIO
+ if (!refreshed_epaper_display) {
+ refreshed_epaper_display = maybe_refresh_epaperdisplay();
+ }
+ #endif
+
tick_rgb_status_animation(&animation);
}
}
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 8e3fe9460..11e6874ed 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -289,7 +289,8 @@ SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix common-hal/, $(SRC_COMMON_HAL))
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
- $(addprefix shared-module/, $(SRC_SHARED_MODULE))
+ $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \
+ $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL))
SRC_S = supervisor/$(CHIP_FAMILY)_cpu.s
diff --git a/ports/atmel-samd/README.rst b/ports/atmel-samd/README.rst
index 167373b26..9afa19b83 100644
--- a/ports/atmel-samd/README.rst
+++ b/ports/atmel-samd/README.rst
@@ -124,15 +124,20 @@ Setup
-----
An ARM compiler is required for the build, along with the associated binary
-utilities. On Ubuntu, these can be installed as follows:
+utilities. They can be installed as follows:
-.. code-block:: shell
+- Ubuntu
+
+ .. code-block:: shell
+
+ sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
+ sudo apt-get install gcc-arm-embedded
+
+- Arch Linux
- sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
- sudo apt-get install gcc-arm-embedded
+ .. code-block:: shell
-On Arch Linux the compiler is available for via the package
-``arm-none-eabi-gcc``.
+ sudo pacman -S arm-none-eabi-gcc arm-none-eabi-newlib
For other systems, the `GNU Arm Embedded Toolchain <https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads>`_
may be available in binary form.
diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h
index d6f1898db..c46f99b7d 100644
--- a/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h
+++ b/ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h
@@ -51,7 +51,7 @@
// <i> This defines the current in output buffer according to conversion rate
// <id> dac0_arch_cctrl
#ifndef CONF_DAC0_CCTRL
-#define CONF_DAC0_CCTRL 1
+#define CONF_DAC0_CCTRL 0
#endif
// <q> Run in standby
@@ -90,7 +90,7 @@
// <i> This defines the current in output buffer according to conversion rate
// <id> dac1_arch_cctrl
#ifndef CONF_DAC1_CCTRL
-#define CONF_DAC1_CCTRL 1
+#define CONF_DAC1_CCTRL 0
#endif
// <q> Run in standby
diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h
index a0748d0fa..6f4f01a7e 100644
--- a/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h
+++ b/ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h
@@ -1,8 +1,9 @@
// Circuit Python SAMD51 clock tree:
-// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK1, GCLK5
+// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK1, GCLK5, GCLK6
// GCLK1 (48MHz) -> 48 MHz peripherals
-// GCLK5 (48 MHz divided down to 2 MHz) -> DPLL0, DAC peripherals
+// GCLK5 (48 MHz divided down to 2 MHz) -> DPLL0
// DPLL0 (multiplied up to 120 MHz) -> GCLK0, GCLK4 (output for monitoring)
+// GCLK6 (48 MHz divided down to 12 MHz) -> DAC
// We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal,
// but haven't figured that out yet.
@@ -472,7 +473,7 @@
// <i> Indicates whether generic clock 6 configuration is enabled or not
// <id> enable_gclk_gen_6
#ifndef CONF_GCLK_GENERATOR_6_CONFIG
-#define CONF_GCLK_GENERATOR_6_CONFIG 0
+#define CONF_GCLK_GENERATOR_6_CONFIG 1
#endif
// <h> Generic Clock Generator Control
@@ -488,7 +489,7 @@
// <i> This defines the clock source for generic clock generator 6
// <id> gclk_gen_6_oscillator
#ifndef CONF_GCLK_GEN_6_SOURCE
-#define CONF_GCLK_GEN_6_SOURCE GCLK_GENCTRL_SRC_XOSC1
+#define CONF_GCLK_GEN_6_SOURCE GCLK_GENCTRL_SRC_DFLL
#endif
// <q> Run in Standby
@@ -523,14 +524,14 @@
// <i> Indicates whether Improve Duty Cycle is enabled or not
// <id> gclk_arch_gen_6_idc
#ifndef CONF_GCLK_GEN_6_IDC
-#define CONF_GCLK_GEN_6_IDC 0
+#define CONF_GCLK_GEN_6_IDC 1
#endif
// <q> Generic Clock Generator Enable
// <i> Indicates whether Generic Clock Generator Enable is enabled or not
// <id> gclk_arch_gen_6_enable
#ifndef CONF_GCLK_GEN_6_GENEN
-#define CONF_GCLK_GEN_6_GENEN 0
+#define CONF_GCLK_GEN_6_GENEN 1
#endif
// </h>
@@ -538,7 +539,7 @@
//<o> Generic clock generator 6 division <0x0000-0xFFFF>
// <id> gclk_gen_6_div
#ifndef CONF_GCLK_GEN_6_DIV
-#define CONF_GCLK_GEN_6_DIV 1
+#define CONF_GCLK_GEN_6_DIV 4
#endif
// </h>
// </e>
diff --git a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
index 41efca755..030a90a7a 100644
--- a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
+++ b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
@@ -73,7 +73,7 @@
// <id> dac_gclk_selection
// <i> Select the clock source for DAC.
#ifndef CONF_GCLK_DAC_SRC
-#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK5_Val
+#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK6_Val
#endif
/**
diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c
index 68d6f182d..0478cc9bf 100644
--- a/ports/atmel-samd/audio_dma.c
+++ b/ports/atmel-samd/audio_dma.c
@@ -29,25 +29,49 @@
#include "samd/events.h"
#include "samd/dma.h"
-#include "shared-bindings/audioio/RawSample.h"
-#include "shared-bindings/audioio/WaveFile.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/audiocore/WaveFile.h"
#include "py/mpstate.h"
#include "py/runtime.h"
+#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
+
static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];
// This cannot be in audio_dma_state because it's volatile.
static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT];
-uint8_t find_free_audio_dma_channel(void) {
+static bool audio_dma_allocated[AUDIO_DMA_CHANNEL_COUNT];
+
+uint8_t audio_dma_allocate_channel(void) {
uint8_t channel;
for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) {
- if (!dma_channel_enabled(channel)) {
+ if (!audio_dma_allocated[channel]) {
+ audio_dma_allocated[channel] = true;
return channel;
}
}
- return channel;
+ return channel; // i.e., return failure
+}
+
+void audio_dma_free_channel(uint8_t channel) {
+ assert(channel < AUDIO_DMA_CHANNEL_COUNT);
+ assert(audio_dma_allocated[channel]);
+ audio_dma_disable_channel(channel);
+ audio_dma_allocated[channel] = false;
+}
+
+void audio_dma_disable_channel(uint8_t channel) {
+ if (channel >= AUDIO_DMA_CHANNEL_COUNT)
+ return;
+ dma_disable_channel(channel);
+}
+
+void audio_dma_enable_channel(uint8_t channel) {
+ if (channel >= AUDIO_DMA_CHANNEL_COUNT)
+ return;
+ dma_enable_channel(channel);
}
void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer_length,
@@ -153,7 +177,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
bool output_signed,
uint32_t output_register_address,
uint8_t dma_trigger_source) {
- uint8_t dma_channel = find_free_audio_dma_channel();
+ uint8_t dma_channel = audio_dma_allocate_channel();
if (dma_channel >= AUDIO_DMA_CHANNEL_COUNT) {
return AUDIO_DMA_DMA_BUSY;
}
@@ -252,16 +276,20 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
}
dma_configure(dma_channel, dma_trigger_source, true);
- dma_enable_channel(dma_channel);
+ audio_dma_enable_channel(dma_channel);
return AUDIO_DMA_OK;
}
void audio_dma_stop(audio_dma_t* dma) {
- dma_disable_channel(dma->dma_channel);
- disable_event_channel(dma->event_channel);
- MP_STATE_PORT(playing_audio)[dma->dma_channel] = NULL;
-
+ uint8_t channel = dma->dma_channel;
+ if (channel < AUDIO_DMA_CHANNEL_COUNT) {
+ audio_dma_disable_channel(channel);
+ disable_event_channel(dma->event_channel);
+ MP_STATE_PORT(playing_audio)[channel] = NULL;
+ audio_dma_state[channel] = NULL;
+ audio_dma_free_channel(dma->dma_channel);
+ }
dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT;
}
@@ -290,7 +318,8 @@ void audio_dma_reset(void) {
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
audio_dma_state[i] = NULL;
audio_dma_pending[i] = false;
- dma_disable_channel(i);
+ audio_dma_allocated[i] = false;
+ audio_dma_disable_channel(i);
dma_descriptor(i)->BTCTRL.bit.VALID = false;
MP_STATE_PORT(playing_audio)[i] = NULL;
}
@@ -333,3 +362,4 @@ void audio_dma_background(void) {
audio_dma_pending[i] = false;
}
}
+#endif
diff --git a/ports/atmel-samd/audio_dma.h b/ports/atmel-samd/audio_dma.h
index 041d675a2..1ebec6f7e 100644
--- a/ports/atmel-samd/audio_dma.h
+++ b/ports/atmel-samd/audio_dma.h
@@ -29,8 +29,8 @@
#include "extmod/vfs_fat.h"
#include "py/obj.h"
-#include "shared-module/audioio/RawSample.h"
-#include "shared-module/audioio/WaveFile.h"
+#include "shared-module/audiocore/RawSample.h"
+#include "shared-module/audiocore/WaveFile.h"
typedef struct {
mp_obj_t sample;
@@ -64,7 +64,8 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj);
void audio_dma_init(audio_dma_t* dma);
void audio_dma_reset(void);
-uint8_t find_free_audio_dma_channel(void);
+uint8_t audio_dma_allocate_channel(void);
+void audio_dma_free_channel(uint8_t channel);
// This sets everything up but doesn't start the timer.
// Sample is the python object for the sample to play.
@@ -83,6 +84,9 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
bool output_signed,
uint32_t output_register_address,
uint8_t dma_trigger_source);
+
+void audio_dma_disable_channel(uint8_t channel);
+void audio_dma_enable_channel(uint8_t channel);
void audio_dma_stop(audio_dma_t* dma);
bool audio_dma_get_playing(audio_dma_t* dma);
void audio_dma_pause(audio_dma_t* dma);
diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c
index 4e88d34e7..386ba0715 100644
--- a/ports/atmel-samd/background.c
+++ b/ports/atmel-samd/background.c
@@ -56,11 +56,11 @@ void run_background_tasks(void) {
assert_heap_ok();
running_background_tasks = true;
- #if (defined(SAMD21) && defined(PIN_PA02)) || defined(SAMD51)
+ #if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
audio_dma_background();
#endif
#if CIRCUITPY_DISPLAYIO
- displayio_refresh_displays();
+ displayio_background();
#endif
#if CIRCUITPY_NETWORK
diff --git a/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk b/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
index 97c8eb863..f390a8681 100644
--- a/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/capablerobot_usbhub/mpconfigboard.mk
@@ -14,5 +14,3 @@ LONGINT_IMPL = MPZ
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/board.c b/ports/atmel-samd/boards/circuitplayground_express_displayio/board.c
new file mode 100644
index 000000000..578963642
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/board.c
@@ -0,0 +1,65 @@
+/*
+ * 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 <string.h>
+
+#include "boards/board.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "hal/include/hal_gpio.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/neopixel_write/__init__.h"
+
+void board_init(void)
+{
+}
+
+// Check the status of the two buttons on CircuitPlayground Express. If both are
+// pressed, then boot into user safe mode.
+bool board_requests_safe_mode(void) {
+ gpio_set_pin_function(PIN_PA14, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(PIN_PA14, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(PIN_PA14, GPIO_PULL_DOWN);
+
+ gpio_set_pin_function(PIN_PA28, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(PIN_PA28, GPIO_PULL_DOWN);
+ bool safe_mode = gpio_get_pin_level(PIN_PA14) &&
+ gpio_get_pin_level(PIN_PA28);
+ reset_pin_number(PIN_PA14);
+ reset_pin_number(PIN_PA28);
+ return safe_mode;
+}
+
+void reset_board(void) {
+ uint8_t empty[30];
+ memset(empty, 0, 30);
+ digitalio_digitalinout_obj_t neopixel_pin;
+ common_hal_digitalio_digitalinout_construct(&neopixel_pin, &pin_PB23);
+ common_hal_digitalio_digitalinout_switch_to_output(&neopixel_pin, false,
+ DRIVE_MODE_PUSH_PULL);
+ common_hal_neopixel_write(&neopixel_pin, empty, 30);
+ common_hal_digitalio_digitalinout_deinit(&neopixel_pin);
+}
diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
new file mode 100644
index 000000000..333fc79f9
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
@@ -0,0 +1,48 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit CircuitPlayground Express with displayio"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA17)
+
+// Don't allow touch on A0 (PA02), because it's connected to the speaker.
+#define PA02_NO_TOUCH (true)
+
+// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+// On-board flash
+#define SPI_FLASH_MOSI_PIN &pin_PA20
+#define SPI_FLASH_MISO_PIN &pin_PA16
+#define SPI_FLASH_SCK_PIN &pin_PA21
+#define SPI_FLASH_CS_PIN &pin_PB22
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (0)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+
+#define SPEAKER_ENABLE_PIN (&pin_PA30)
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code.
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define CALIBRATE_CRYSTALLESS 1
+
+// Explanation of how a user got into safe mode.
+#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA05)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA07)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA06)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB09)
+#define DEFAULT_UART_BUS_TX (&pin_PB08)
+
+// 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/circuitplayground_express_displayio/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
new file mode 100644
index 000000000..f0c9c6b8c
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk
@@ -0,0 +1,31 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
+USB_VID = 0x239A
+USB_PID = 0x8019
+USB_PRODUCT = "CircuitPlayground Express with displayio"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 2
+EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
+
+# Turn off features and optimizations for Crickit build to make room for additional frozen libs.
+LONGINT_IMPL = NONE
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CSLAVE = 0
+CIRCUITPY_PIXELBUF = 0
+CIRCUITPY_GAMEPAD = 0
+CIRCUITPY_RTC = 0
+
+SUPEROPT_GC = 0
+CFLAGS_INLINE_LIMIT = 55
+
+# Include these Python libraries in firmware.
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor
diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/pins.c b/ports/atmel-samd/boards/circuitplayground_express_displayio/pins.c
new file mode 100644
index 000000000..6fc46bd21
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/pins.c
@@ -0,0 +1,63 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_TEMPERATURE), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_PA09) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_PA28) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA28) },
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_SLIDE_SWITCH), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PB23) },
+
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) },
+
+ { MP_ROM_QSTR(MP_QSTR_REMOTEIN), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_IR_RX), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_REMOTEOUT), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_IR_TX), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_IR_PROXIMITY), MP_ROM_PTR(&pin_PA04) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_PA08) },
+
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SDA), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SCL), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA30) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA06) },
+ { 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/boards/cp32-m4/mpconfigboard.mk b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
index 72a191044..86a7719b8 100644
--- a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
@@ -14,5 +14,3 @@ EXTERNAL_FLASH_DEVICES = "W25Q128JV_PM"
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G.
CIRCUITPY_AUDIOBUSIO = 0
-# No touch on SAMD51 yet.
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
index 794920fe3..aa5f47d40 100644
--- a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
@@ -15,5 +15,3 @@ LONGINT_IMPL = MPZ
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index 756c293ad..5b89f1be4 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -12,5 +12,9 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CSLAVE = 0
+
CFLAGS_INLINE_LIMIT = 60
SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
index 33229044b..c5fef4373 100644
--- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
@@ -11,3 +11,10 @@ SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "S25FL064L"
LONGINT_IMPL = MPZ
+
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CSLAVE = 0
+
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
index 8169345f5..176ebac82 100644
--- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
@@ -15,5 +15,3 @@ LONGINT_IMPL = MPZ
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
index bc60ba49b..5f09ab4d2 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
@@ -6,8 +6,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PA00)
#define MICROPY_HW_APA102_SCK (&pin_PA01)
-// #define CIRCUITPY_BITBANG_APA102
-
#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B (0)
#define MICROPY_PORT_C (0)
diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
index 13631a736..423761c3f 100644
--- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
@@ -13,5 +13,3 @@ EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/board.c b/ports/atmel-samd/boards/hallowing_m0_express/board.c
index a0e160757..b4c54062f 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/board.c
+++ b/ports/atmel-samd/boards/hallowing_m0_express/board.c
@@ -91,6 +91,10 @@ void board_init(void) {
1, // row start
0, // rotation
16, // Color depth
+ false, // Grayscale
+ false, // Pixels in a byte share a row. Only used for depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
@@ -98,10 +102,13 @@ void board_init(void) {
display_init_sequence,
sizeof(display_init_sequence),
&pin_PA00,
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
- false); // data_as_commands
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h
index 4b5460706..d5c274500 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h
@@ -35,3 +35,7 @@
// USB is always used internally so skip the pin objects for it.
#define IGNORE_PIN_PA24 1
#define IGNORE_PIN_PA25 1
+
+// SWD is only available on the test pads so skip the pin objects.
+#define IGNORE_PIN_PA30 1
+#define IGNORE_PIN_PA31 1
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
index 8dfc741e5..988d10d1c 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
@@ -13,9 +13,15 @@ EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
# To keep the build small
-CIRCUITPY_I2CSLAVE = 0
-CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_GAMEPAD = 0
+CIRCUITPY_I2CSLAVE = 0
+CIRCUITPY_ROTARYIO = 0
+CIRCUITPY_RTC = 0
+
+CFLAGS_INLINE_LIMIT = 60
SUPEROPT_GC = 0
# Include these Python libraries in firmware.
diff --git a/ports/atmel-samd/boards/hallowing_m4_express/board.c b/ports/atmel-samd/boards/hallowing_m4_express/board.c
new file mode 100644
index 000000000..6bb2a591f
--- /dev/null
+++ b/ports/atmel-samd/boards/hallowing_m4_express/board.c
@@ -0,0 +1,99 @@
+/*
+ * 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"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+#include "tick.h"
+
+displayio_fourwire_obj_t board_display_obj;
+
+#define DELAY 0x80
+
+uint8_t display_init_sequence[] = {
+ 0x01, 0 | DELAY, 150, // SWRESET
+ 0x11, 0 | DELAY, 255, // SLPOUT
+ 0x36, 1, 0x00, // _MADCTL bottom to top refresh in vsync aligned order.
+ 0x3a, 1, 0x55, // COLMOD - 16bit color
+ 0x21, 0 | DELAY, 10, // _INVON
+ 0x13, 0 | DELAY, 10, // _NORON
+ 0x29, 0 | DELAY, 255, // _DISPON
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_PA01, &pin_PA00, NULL);
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+ common_hal_displayio_fourwire_construct(bus,
+ spi,
+ &pin_PB31, // TFT_DC Command or data
+ &pin_PA27, // TFT_CS Chip select
+ &pin_PB30, // TFT_RST Reset
+ 60000000);
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 240, // Width (after rotation)
+ 240, // Height (after rotation)
+ 0, // column start
+ 0, // row start
+ 180, // rotation
+ 16, // Color depth
+ false, // Grayscale
+ false, // Pixels in a byte share a row. Only used for depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 0x37, // set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_PB14, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.h
new file mode 100644
index 000000000..654632db5
--- /dev/null
+++ b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.h
@@ -0,0 +1,39 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit Hallowing M4 Express"
+#define MICROPY_HW_MCU_NAME "samd51j19"
+
+#define CIRCUITPY_MCU_FAMILY samd51
+
+// Rev C
+
+#define MICROPY_HW_LED_STATUS (&pin_PA23)
+#define MICROPY_HW_NEOPIXEL (&pin_PB16)
+
+// These are pins not to reset.
+// QSPI Data pins
+#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
+// NeoPixel pin, QSPI CS, and QSPI SCK
+#define MICROPY_PORT_B (PORT_PB16 | PORT_PB10 | PORT_PB11)
+#define MICROPY_PORT_C (0)
+#define MICROPY_PORT_D (0)
+
+#define AUTORESET_DELAY_MS 500
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code
+#define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA13)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA12)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA22)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB23)
+#define DEFAULT_SPI_BUS_MISO (&pin_PB22)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB12)
+#define DEFAULT_UART_BUS_TX (&pin_PB13)
+
+// 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/hallowing_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk
new file mode 100644
index 000000000..0d891abc8
--- /dev/null
+++ b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk
@@ -0,0 +1,17 @@
+LD_FILE = boards/samd51x19-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x804A
+USB_PRODUCT = "Hallowing M4 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = GD25Q64C
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_NETWORK = 1
+MICROPY_PY_WIZNET5K = 5500
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/hallowing_m4_express/pins.c b/ports/atmel-samd/boards/hallowing_m4_express/pins.c
new file mode 100644
index 000000000..89fe3fbcf
--- /dev/null
+++ b/ports/atmel-samd/boards/hallowing_m4_express/pins.c
@@ -0,0 +1,71 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "shared-module/displayio/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_TOUCH1), MP_ROM_PTR(&pin_PA06) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_TOUCH2), MP_ROM_PTR(&pin_PB09) },
+
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_TOUCH3), MP_ROM_PTR(&pin_PB08) },
+
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_TOUCH4), MP_ROM_PTR(&pin_PA04) },
+
+ { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB22) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_PB15) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PB15) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA23) },
+
+ { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB31) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_PB30) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB16) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PB16) },
+ { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PB01) },
+
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_EXTERNAL_NEOPIXEL), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_SENSE), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PB03) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_CAP_PIN), MP_ROM_PTR(&pin_PA15) },
+
+ { 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_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h
index 79d0cd269..6f9f661d9 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h
@@ -3,7 +3,6 @@
#define MICROPY_HW_LED_STATUS (&pin_PA17)
-#define CIRCUITPY_BITBANG_APA102
#define MICROPY_HW_APA102_MOSI (&pin_PA01)
#define MICROPY_HW_APA102_SCK (&pin_PA00)
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
index e427e9430..2b64e9027 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
@@ -12,5 +12,13 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C"
LONGINT_IMPL = MPZ
+CIRCUITPY_BITBANG_APA102 = 1
+
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_GAMEPAD = 0
+CIRCUITPY_I2CSLAVE = 0
+CIRCUITPY_RTC = 0
+
CFLAGS_INLINE_LIMIT = 60
SUPEROPT_GC = 0
+
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
index f4d17ac64..9e4d4a10c 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
@@ -9,8 +9,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)
-#define CIRCUITPY_BITBANG_APA102
-
// These are pins not to reset.
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
index 31bb38e20..5cab5bf43 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
@@ -15,5 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
+
+CIRCUITPY_BITBANG_APA102 = 1
diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
index 5871cca2a..706e551c5 100644
--- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
@@ -11,8 +11,6 @@ QSPI_FLASH_FILESYSTEM = 0
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
# Not needed.
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_DISPLAYIO = 0
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index 93a8ffc11..d3f35ba8b 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -12,5 +12,8 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
LONGINT_IMPL = MPZ
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_I2CSLAVE = 0
+
CFLAGS_INLINE_LIMIT = 60
SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
index d7d0c1d6e..98d85ba82 100644
--- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
@@ -15,5 +15,3 @@ LONGINT_IMPL = MPZ
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index 829bf749f..68b6f6406 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -15,5 +15,3 @@ LONGINT_IMPL = MPZ
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h
index cd754924e..c4563964f 100644
--- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h
+++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h
@@ -9,8 +9,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)
-#define CIRCUITPY_BITBANG_APA102
-
// These are pins not to reset.
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
index a8f47dced..4bd1d6e52 100644
--- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
@@ -15,5 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
+
+CIRCUITPY_BITBANG_APA102 = 1
diff --git a/ports/atmel-samd/boards/monster_m4sk/board.c b/ports/atmel-samd/boards/monster_m4sk/board.c
new file mode 100644
index 000000000..2377f4a9d
--- /dev/null
+++ b/ports/atmel-samd/boards/monster_m4sk/board.c
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+#include "mpconfigboard.h"
+#include "hal/include/hal_gpio.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+#include "tick.h"
+
+displayio_fourwire_obj_t board_display_obj;
+
+#define DELAY 0x80
+
+uint8_t display_init_sequence[] = {
+ 0x01, 0 | DELAY, 150, // SWRESET
+ 0x11, 0 | DELAY, 255, // SLPOUT
+ 0x36, 1, 0x00, // _MADCTL bottom to top refresh in vsync aligned order.
+ 0x3a, 1, 0x55, // COLMOD - 16bit color
+ 0x38, 0, // Idle mode off
+ 0x21, 0, // _INVON
+ 0x13, 0, // _NORON
+ 0x29, 0 | DELAY, 255 // _DISPON
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, NULL);
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+ common_hal_displayio_fourwire_construct(bus,
+ spi,
+ &pin_PA07, // TFT_DC Command or data
+ &pin_PA06, // TFT_CS Chip select
+ &pin_PA04, // TFT_RST Reset
+ 60000000);
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 240, // Width (after rotation)
+ 240, // Height (after rotation)
+ 0, // column start
+ 0, // row start
+ 180, // rotation
+ 16, // Color depth
+ false, // Grayscale
+ false, // pixels in a byte share a row. Only valid for depths < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 0x37, // set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_PA23, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h
new file mode 100644
index 000000000..fc77520f5
--- /dev/null
+++ b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h
@@ -0,0 +1,29 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit Monster M4SK"
+#define MICROPY_HW_MCU_NAME "samd51j19"
+
+#define CIRCUITPY_MCU_FAMILY samd51
+
+#define MICROPY_HW_LED_STATUS (&pin_PA27)
+
+// These are pins not to reset.
+// QSPI Data pins
+#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
+// DotStar pins, QSPI CS, and QSPI SCK
+#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11)
+#define MICROPY_PORT_C (0)
+#define MICROPY_PORT_D (0)
+
+#define AUTORESET_DELAY_MS 500
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code
+#define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA01)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA00)
+
+// 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/monster_m4sk/mpconfigboard.mk b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk
new file mode 100644
index 000000000..a3db7dc89
--- /dev/null
+++ b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk
@@ -0,0 +1,16 @@
+LD_FILE = boards/samd51x19-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x8048
+USB_PRODUCT = "Monster M4SK"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+CHIP_VARIANT = SAMD51J19A
+CHIP_FAMILY = samd51
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = GD25Q64C
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_AUDIOIO = 1
+CIRCUITPY_DISPLAYIO = 1
diff --git a/ports/atmel-samd/boards/monster_m4sk/pins.c b/ports/atmel-samd/boards/monster_m4sk/pins.c
new file mode 100644
index 000000000..7272b9ed8
--- /dev/null
+++ b/ports/atmel-samd/boards/monster_m4sk/pins.c
@@ -0,0 +1,52 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "boards/board.h"
+#include "shared-module/displayio/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_HEADPHONE_LEFT), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_HEADPHONE_RIGHT), MP_ROM_PTR(&pin_PA05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB08) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB08) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_NOSE), MP_ROM_PTR(&pin_PB08) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB09) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA27) },
+
+ // I2C
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_PA22) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA14) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_PA17) },
+
+ // Right TFT control pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RIGHT_TFT_LITE), MP_ROM_PTR(&pin_PA23) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RIGHT_TFT_MOSI), MP_ROM_PTR(&pin_PA12) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RIGHT_TFT_SCK), MP_ROM_PTR(&pin_PA13) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RIGHT_TFT_RST), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_RIGHT_TFT_CS), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_RIGHT_TFT_DC), MP_ROM_PTR(&pin_PA07) },
+
+ // Left TFT control pins. Some pins are attached through the SeeSaw chip.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LEFT_TFT_MOSI), MP_ROM_PTR(&pin_PB02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LEFT_TFT_SCK), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_LEFT_TFT_CS), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_LEFT_TFT_DC), MP_ROM_PTR(&pin_PB22) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)},
+ { MP_ROM_QSTR(MP_QSTR_RIGHT_DISPLAY), MP_ROM_PTR(&displays[0].display)}
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/pewpew_m4/board.c b/ports/atmel-samd/boards/pewpew_m4/board.c
new file mode 100644
index 000000000..b684f5601
--- /dev/null
+++ b/ports/atmel-samd/boards/pewpew_m4/board.c
@@ -0,0 +1,121 @@
+/*
+ * 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"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+#include "tick.h"
+
+displayio_fourwire_obj_t board_display_obj;
+
+#define DELAY 0x80
+
+uint8_t display_init_sequence[] = {
+ 0x01, 0 | DELAY, 150, // SWRESET
+ 0x11, 0 | DELAY, 255, // SLPOUT
+ 0xb1, 3, 0x01, 0x2C, 0x2D, // _FRMCTR1
+ 0xb2, 3, 0x01, 0x2C, 0x2D, //
+ 0xb3, 6, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D,
+ 0xb4, 1, 0x07, // _INVCTR line inversion
+ 0xc0, 3, 0xa2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA
+ 0xc1, 1, 0xc5, // _PWCTR2 VGH=14.7V, VGL=-7.35V
+ 0xc2, 2, 0x0a, 0x00, // _PWCTR3 Opamp current small, Boost frequency
+ 0xc3, 2, 0x8a, 0x2a,
+ 0xc4, 2, 0x8a, 0xee,
+ 0xc5, 1, 0x0e, // _VMCTR1 VCOMH = 4V, VOML = -1.1V
+ 0x2a, 0, // _INVOFF
+ 0x36, 1, 0xa8, // _MADCTL
+ // 1 clk cycle nonoverlap, 2 cycle gate rise, 3 cycle osc equalie,
+ // fix on VTL
+ 0x3a, 1, 0x05, // COLMOD - 16bit color
+ 0xe0, 16, 0x02, 0x1c, 0x07, 0x12, // _GMCTRP1 Gamma
+ 0x37, 0x32, 0x29, 0x2d,
+ 0x29, 0x25, 0x2B, 0x39,
+ 0x00, 0x01, 0x03, 0x10,
+ 0xe1, 16, 0x03, 0x1d, 0x07, 0x06, // _GMCTRN1
+ 0x2E, 0x2C, 0x29, 0x2D,
+ 0x2E, 0x2E, 0x37, 0x3F,
+ 0x00, 0x00, 0x02, 0x10,
+ 0x2a, 3, 0x02, 0x00, 0x81, // _CASET XSTART = 2, XEND = 129
+ 0x2b, 3, 0x02, 0x00, 0x81, // _RASET XSTART = 2, XEND = 129
+ 0x13, 0 | DELAY, 10, // _NORON
+ 0x29, 0 | DELAY, 100, // _DISPON
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA15, NULL);
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+ common_hal_displayio_fourwire_construct(bus,
+ spi,
+ &pin_PA16, // TFT_DC Command or data
+ &pin_PA11, // TFT_CS Chip select
+ &pin_PA17, // TFT_RST Reset
+ 60000000);
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 160, // Width (after rotation)
+ 128, // Height (after rotation)
+ 0, // column start
+ 0, // row start
+ 0, // rotation
+ 16, // Color depth
+ false, // grayscale
+ false, // pixels in byte share row. only used for depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 0x37, // set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ NULL, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ false, // auto_refresh
+ 20); // native_frames_per_second
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h
new file mode 100644
index 000000000..1b3035e12
--- /dev/null
+++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h
@@ -0,0 +1,51 @@
+#define MICROPY_HW_BOARD_NAME "PewPew M4"
+#define MICROPY_HW_MCU_NAME "samd51g19"
+
+#define CIRCUITPY_MCU_FAMILY samd51
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (0)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+#define MICROPY_PORT_D (0)
+
+#define AUTORESET_DELAY_MS 500
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code
+#define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA01)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA00)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA04)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA05)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA00)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA05)
+#define DEFAULT_UART_BUS_TX (&pin_PA00)
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
+
+// Unused pins
+#define IGNORE_PIN_PA03 1
+#define IGNORE_PIN_PA06 1
+#define IGNORE_PIN_PA08 1
+#define IGNORE_PIN_PA12 1
+#define IGNORE_PIN_PA14 1
+#define IGNORE_PIN_PA18 1
+#define IGNORE_PIN_PA19 1
+#define IGNORE_PIN_PA20 1
+#define IGNORE_PIN_PA21 1
+
+#define IGNORE_PIN_PB02 1
+#define IGNORE_PIN_PB03 1
+#define IGNORE_PIN_PB08 1
+#define IGNORE_PIN_PB09 1
+#define IGNORE_PIN_PB10 1
+#define IGNORE_PIN_PB11 1
+
diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk
new file mode 100644
index 000000000..54ec3d1d0
--- /dev/null
+++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk
@@ -0,0 +1,40 @@
+LD_FILE = boards/samd51x19-bootloader.ld
+USB_VID = 0x1d50
+USB_PID = 0x60e8
+USB_PRODUCT = "PewPew M4"
+USB_MANUFACTURER = "Radomir Dopieralski"
+
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+
+CIRCUITPY_SMALL_BUILD = 1
+CIRCUITPY_PS2IO = 0
+CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CSLAVE = 0
+CIRCUITPY_NEOPIXEL_WRITE = 0
+CIRCUITPY_PIXELBUF = 0
+CIRCUITPY_RTC = 0
+CIRCUITPY_TOUCHIO = 0
+CIRCUITPY_USB_HID = 0
+CIRCUITPY_USB_MIDI = 0
+
+CIRCUITPY_AUDIOIO = 1
+CIRCUITPY_DISPLAYIO = 1
+CIRCUITPY_GAMEPAD = 1
+CIRCUITPY_STAGE = 1
+CIRCUITPY_MATH = 1
+
+FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pewpew_m4
+CIRCUITPY_DISPLAY_FONT = $(TOP)/ports/atmel-samd/boards/ugame10/brutalist-6.bdf
+
+# Tweak inlining depending on language.
+ifeq ($(TRANSLATION), zh_Latn_pinyin)
+CFLAGS_INLINE_LIMIT = 45
+else
+CFLAGS_INLINE_LIMIT = 70
+endif
diff --git a/ports/atmel-samd/boards/pewpew_m4/pins.c b/ports/atmel-samd/boards/pewpew_m4/pins.c
new file mode 100644
index 000000000..7654432f5
--- /dev/null
+++ b/ports/atmel-samd/boards/pewpew_m4/pins.c
@@ -0,0 +1,45 @@
+#include "shared-bindings/board/__init__.h"
+#include "shared-module/displayio/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_PB23) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_PB22) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_PA23) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_PA27) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_O), MP_ROM_PTR(&pin_PA10) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_X), MP_ROM_PTR(&pin_PA09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_Z), MP_ROM_PTR(&pin_PA22) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P1), MP_ROM_PTR(&pin_PA30) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_PA31) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_PA00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_PA01) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P6), MP_ROM_PTR(&pin_PA04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_P7), MP_ROM_PTR(&pin_PA05) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_PA17) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PA16) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_PA15) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_PA13) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PA11) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA00) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA00) },
+
+ { 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_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
index 288208f65..5a8eb9d14 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
@@ -4,8 +4,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PA00)
#define MICROPY_HW_APA102_SCK (&pin_PA01)
-// #define CIRCUITPY_BITBANG_APA102
-
#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B (0)
#define MICROPY_PORT_C (0)
diff --git a/ports/atmel-samd/boards/pybadge/board.c b/ports/atmel-samd/boards/pybadge/board.c
index 38902315a..37f7991d1 100644
--- a/ports/atmel-samd/boards/pybadge/board.c
+++ b/ports/atmel-samd/boards/pybadge/board.c
@@ -93,6 +93,10 @@ void board_init(void) {
0, // row start
270, // rotation
16, // Color depth
+ false, // grayscale
+ false, // pixels in byte share row. only used for depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
@@ -100,10 +104,13 @@ void board_init(void) {
display_init_sequence,
sizeof(display_init_sequence),
&pin_PA01, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
- false); // data_as_commands
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
index b8d10387b..7e2cb6439 100644
--- a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk
@@ -17,7 +17,5 @@ CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_GAMEPAD = 1
CIRCUITPY_GAMEPADSHIFT = 1
CIRCUITPY_STAGE = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge
diff --git a/ports/atmel-samd/boards/pybadge_airlift/board.c b/ports/atmel-samd/boards/pybadge_airlift/board.c
index a1f778df1..7622de6f0 100644
--- a/ports/atmel-samd/boards/pybadge_airlift/board.c
+++ b/ports/atmel-samd/boards/pybadge_airlift/board.c
@@ -71,6 +71,10 @@ void board_init(void) {
0, // row start
90, // rotation
16, // Color depth
+ false, // grayscale
+ false, // pixels in byte share row. Only used for depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
@@ -78,10 +82,13 @@ void board_init(void) {
display_init_sequence,
sizeof(display_init_sequence),
&pin_PA01, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
- false); // data_as_commands
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk b/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk
index 12683e995..7e77b0fea 100644
--- a/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pybadge_airlift/mpconfigboard.mk
@@ -17,7 +17,5 @@ CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_GAMEPAD = 1
CIRCUITPY_GAMEPADSHIFT = 1
CIRCUITPY_STAGE = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge
diff --git a/ports/atmel-samd/boards/pygamer/board.c b/ports/atmel-samd/boards/pygamer/board.c
index 7b54b6fb5..b33ae4fb0 100644
--- a/ports/atmel-samd/boards/pygamer/board.c
+++ b/ports/atmel-samd/boards/pygamer/board.c
@@ -93,6 +93,10 @@ void board_init(void) {
0, // row start
270, // rotation
16, // Color depth
+ false, // Grayscale
+ false, // pixels in a byte share a row. Only valid for depths < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
@@ -100,10 +104,13 @@ void board_init(void) {
display_init_sequence,
sizeof(display_init_sequence),
&pin_PA01, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
- false); // data_as_commands
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
index 69fb14358..0fce468d9 100644
--- a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk
@@ -17,7 +17,5 @@ CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_GAMEPAD = 1
CIRCUITPY_GAMEPADSHIFT = 1
CIRCUITPY_STAGE = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pygamer
diff --git a/ports/atmel-samd/boards/pygamer_advance/board.c b/ports/atmel-samd/boards/pygamer_advance/board.c
index d1c5edc99..8eb501243 100644
--- a/ports/atmel-samd/boards/pygamer_advance/board.c
+++ b/ports/atmel-samd/boards/pygamer_advance/board.c
@@ -71,6 +71,10 @@ void board_init(void) {
0, // row start
90, // rotation
16, // Color depth
+ false, // Grayscale
+ false, // pixels in a byte share a row. Only valid for depths < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
@@ -78,10 +82,13 @@ void board_init(void) {
display_init_sequence,
sizeof(display_init_sequence),
&pin_PA01, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
- false); // data_as_commands
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk b/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk
index 1bb2c553d..8711738d4 100644
--- a/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pygamer_advance/mpconfigboard.mk
@@ -17,7 +17,5 @@ CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_GAMEPAD = 1
CIRCUITPY_GAMEPADSHIFT = 1
CIRCUITPY_STAGE = 1
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge
diff --git a/ports/atmel-samd/boards/pyportal/board.c b/ports/atmel-samd/boards/pyportal/board.c
index bb80c5b48..2a7289778 100644
--- a/ports/atmel-samd/boards/pyportal/board.c
+++ b/ports/atmel-samd/boards/pyportal/board.c
@@ -83,17 +83,24 @@ void board_init(void) {
0, // row start
0, // rotation
16, // Color depth
+ false, // grayscale
+ false, // pixels_in_byte_share_row (unused for depths > 8)
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
0x37, // Set vertical scroll command
display_init_sequence,
sizeof(display_init_sequence),
- &pin_PB31,
+ &pin_PB31, // Backlight pin
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness (ignored)
true, // auto_brightness
false, // single_byte_bounds
- false); // data_as_commands
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/pyportal/mpconfigboard.mk b/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
index 996b17b3b..f763c74fa 100644
--- a/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyportal/mpconfigboard.mk
@@ -11,6 +11,3 @@ QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
-
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c
new file mode 100644
index 000000000..a18bb380b
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/board.c
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+#include "mpconfigboard.h"
+#include "hal/include/hal_gpio.h"
+
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+
+#include "tick.h"
+
+#define DELAY 0x80
+
+uint8_t display_init_sequence[] = {
+ 0x01, DELAY, 100/5, // Soft reset, then delay 10 ms
+ 0xB9, 3, 0xFF, 0x83, 0x57, // Extension command set
+ 0xFF, DELAY, 500/5,
+ 0xB3, 4, 0x80, 0x00, 0x06, 0x06, // 0x80 enables SDO pin (0x00 disables)
+ 0xB6, 2, 0x01, 0x25, // -1.52V
+ 0xB0, 1, 0x68, // Normal mode 70Hz, Idle mode 55 Hz
+ 0xCC, 1, 0x05,
+ 0xB1, 6,
+ 0x00, // Not deep standby
+ 0x15, // BT
+ 0x1C, // VSPR
+ 0x1C, // VSNR
+ 0x83, // AP
+ 0xAA, // FS
+ 0xC0, 6,
+ 0x50, // OPON normal
+ 0x50, // OPON idle
+ 0x01, // STBA
+ 0x3C, // STBA
+ 0x1E, // STBA
+ 0x08, // GEN
+ 0xB4, 7,
+ 0x02, // NW 0x02
+ 0x40, // RTN
+ 0x00, // DIV
+ 0x2A, // DUM
+ 0x2A, // DUM
+ 0x0D, // GDON
+ 0x78, // GDOFF
+ 0xE0, 34,
+ 0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b,
+ 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x02, 0x0A,
+ 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A,
+ 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01,
+ 0x3a, 1, 0x55,
+ 0x36, 1, 0x00,
+ 0x11, DELAY, 150/5, // Exit Sleep, then delay 150 ms
+ 0x29, DELAY, 50/5
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, &pin_PA14);
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+ common_hal_displayio_fourwire_construct(bus,
+ spi,
+ &pin_PB05, // TFT_DC Command or data
+ &pin_PB06, // TFT_CS Chip select
+ &pin_PA00, // TFT_RST Reset
+ 24000000);
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 480, // Width
+ 320, // Height
+ 0, // column start
+ 0, // row start
+ 270, // rotation
+ 16, // Color depth
+ false, // grayscale
+ false, // pixels_in_byte_share_row (unused for depths > 8)
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 0x37, // Set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_PB31, // Backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h
new file mode 100644
index 000000000..91c118810
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h
@@ -0,0 +1,39 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit PyPortal Titano"
+#define MICROPY_HW_MCU_NAME "samd51j20"
+
+#define CIRCUITPY_MCU_FAMILY samd51
+
+
+#define MICROPY_HW_LED_STATUS (&pin_PA27)
+
+#define MICROPY_HW_NEOPIXEL (&pin_PB22)
+
+// These are pins not to reset.
+// QSPI Data pins
+#define MICROPY_PORT_A ( PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 )
+// QSPI CS, and QSPI SCK
+#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11 | PORT_PB22 )
+#define MICROPY_PORT_C ( 0 )
+#define MICROPY_PORT_D (0)
+
+#define AUTORESET_DELAY_MS 500
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code
+#define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA13)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA12)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA14)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB13)
+#define DEFAULT_UART_BUS_TX (&pin_PB12)
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
new file mode 100644
index 000000000..58b363779
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.mk
@@ -0,0 +1,13 @@
+LD_FILE = boards/samd51x20-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x8054
+USB_PRODUCT = "PyPortal Titano"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+CHIP_VARIANT = SAMD51J20A
+CHIP_FAMILY = samd51
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 2
+EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
+LONGINT_IMPL = MPZ
diff --git a/ports/atmel-samd/boards/pyportal_titano/pins.c b/ports/atmel-samd/boards/pyportal_titano/pins.c
new file mode 100644
index 000000000..6bc0a504a
--- /dev/null
+++ b/ports/atmel-samd/boards/pyportal_titano/pins.c
@@ -0,0 +1,94 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "boards/board.h"
+#include "shared-module/displayio/__init__.h"
+
+// This mapping only includes functional names because pins broken
+// out on connectors are labeled with their MCU name available from
+// microcontroller.pin.
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AUDIO_OUT), MP_ROM_PTR(&pin_PA02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, // analog out/in
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA27) },
+
+ // Light sensor
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA07) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA07) },
+
+ // STEMMA connectors
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) },
+
+ // Indicator LED
+ { MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB23) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PB23) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_PB22) },
+
+ // LCD pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_PA00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RD), MP_ROM_PTR(&pin_PB04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RS), MP_ROM_PTR(&pin_PB05) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB06) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_TE), MP_ROM_PTR(&pin_PB07) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_WR), MP_ROM_PTR(&pin_PB09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_PB31) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA0), MP_ROM_PTR(&pin_PA16) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA1), MP_ROM_PTR(&pin_PA17) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA2), MP_ROM_PTR(&pin_PA18) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA3), MP_ROM_PTR(&pin_PA19) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA4), MP_ROM_PTR(&pin_PA20) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA5), MP_ROM_PTR(&pin_PA21) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA6), MP_ROM_PTR(&pin_PA22) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DATA7), MP_ROM_PTR(&pin_PA23) },
+
+ // Touch pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_YD), MP_ROM_PTR(&pin_PB00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_XL), MP_ROM_PTR(&pin_PB01) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_YU), MP_ROM_PTR(&pin_PA06) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_XR), MP_ROM_PTR(&pin_PB08) },
+
+ // ESP control
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_PB14) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_GPIO0), MP_ROM_PTR(&pin_PB15) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_PB16) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_PB17) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RTS), MP_ROM_PTR(&pin_PA15) },
+
+ // UART
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB12) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB13) },
+
+ // SPI
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI),MP_ROM_PTR(&pin_PA12) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCK),MP_ROM_PTR(&pin_PA13) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MISO),MP_ROM_PTR(&pin_PA14) },
+
+ // I2C
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SDA),MP_ROM_PTR(&pin_PB02) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SCL),MP_ROM_PTR(&pin_PB03) },
+
+ // SD Card
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS),MP_ROM_PTR(&pin_PB30) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CARD_DETECT),MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+
+ // TFT control pins
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(&pin_PB31)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_PA12)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_PA13)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MISO), MP_ROM_PTR(&pin_PA14)},
+ {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_PA00)},
+ {MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB06)},
+ {MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB05)},
+
+ { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/robohatmm1/pins.c b/ports/atmel-samd/boards/robohatmm1/pins.c
deleted file mode 100644
index fc3db7a30..000000000
--- a/ports/atmel-samd/boards/robohatmm1/pins.c
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "shared-bindings/board/__init__.h"
-
-STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
- // SERVO Pins
- { MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_PA16) },
- { MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_PA17) },
- { MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_PA18) },
- { MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_PA19) },
- { MP_ROM_QSTR(MP_QSTR_SERVO5), MP_ROM_PTR(&pin_PA11) },
- { MP_ROM_QSTR(MP_QSTR_SERVO6), MP_ROM_PTR(&pin_PA10) },
- { MP_ROM_QSTR(MP_QSTR_SERVO7), MP_ROM_PTR(&pin_PA09) },
- { MP_ROM_QSTR(MP_QSTR_SERVO8), MP_ROM_PTR(&pin_PA08) },
-
- // RC_CH Pins
- { MP_ROM_QSTR(MP_QSTR_RCH1), MP_ROM_PTR(&pin_PA07) },
- { MP_ROM_QSTR(MP_QSTR_RCH2), MP_ROM_PTR(&pin_PA06) },
- { MP_ROM_QSTR(MP_QSTR_RCH3), MP_ROM_PTR(&pin_PA05) },
- { MP_ROM_QSTR(MP_QSTR_RCH4), MP_ROM_PTR(&pin_PA04) },
-
- // Special Function
- { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA02) },
- { MP_ROM_QSTR(MP_QSTR_POWER_OFF), MP_ROM_PTR(&pin_PA03) },
- { MP_ROM_QSTR(MP_QSTR_POWER_ENABLE), MP_ROM_PTR(&pin_PA28) },
-
- { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA20) },
- { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA21) },
- { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
- { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
- { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB22) },
- { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB23) },
-
- // UART on SERCOM0
- { MP_ROM_QSTR(MP_QSTR_UART_TX), MP_ROM_PTR(&pin_PA04) },
- { MP_ROM_QSTR(MP_QSTR_UART_RX), MP_ROM_PTR(&pin_PA05) },
- { MP_ROM_QSTR(MP_QSTR_UART_CTS), MP_ROM_PTR(&pin_PA06) },
- { MP_ROM_QSTR(MP_QSTR_UART_RTS), MP_ROM_PTR(&pin_PA07) },
-
- // SPI Flash on SERCOM2
- { MP_ROM_QSTR(MP_QSTR_FLASH_SCK), MP_ROM_PTR(&pin_PA13) },
- { MP_ROM_QSTR(MP_QSTR_FLASH_MISO), MP_ROM_PTR(&pin_PA14) },
- { MP_ROM_QSTR(MP_QSTR_FLASH_MOSI), MP_ROM_PTR(&pin_PA12) },
- { MP_ROM_QSTR(MP_QSTR_FLASH_CS), MP_ROM_PTR(&pin_PA15) },
-
- // I2C on SERCOM3
- { MP_ROM_QSTR(MP_QSTR_I2C_SDA), MP_ROM_PTR(&pin_PA00) },
- { MP_ROM_QSTR(MP_QSTR_I2C_SCL), MP_ROM_PTR(&pin_PA01) },
-
- // SPI on SERCOM4
- { MP_ROM_QSTR(MP_QSTR_SPI_SCK), MP_ROM_PTR(&pin_PB11) },
- { MP_ROM_QSTR(MP_QSTR_SPI_MISO), MP_ROM_PTR(&pin_PB08) },
- { MP_ROM_QSTR(MP_QSTR_SPI_MOSI), MP_ROM_PTR(&pin_PB10) },
- { MP_ROM_QSTR(MP_QSTR_SPI_SS), MP_ROM_PTR(&pin_PB09) },
-
- // GPS on SERCOM5
- { MP_ROM_QSTR(MP_QSTR_GPS_TX), MP_ROM_PTR(&pin_PB02) },
- { MP_ROM_QSTR(MP_QSTR_GPS_RX), MP_ROM_PTR(&pin_PB03) },
- { MP_ROM_QSTR(MP_QSTR_GPS_SDA), MP_ROM_PTR(&pin_PA00) },
- { MP_ROM_QSTR(MP_QSTR_GPS_SCL), MP_ROM_PTR(&pin_PA01) },
-
- // Raspberry Pi
- { MP_ROM_QSTR(MP_QSTR_PI_GP25), MP_ROM_PTR(&pin_PA30) },
- { MP_ROM_QSTR(MP_QSTR_PI_GP24), MP_ROM_PTR(&pin_PA31) },
- { MP_ROM_QSTR(MP_QSTR_PI_GP5), MP_ROM_PTR(&pin_PA27) },
- { MP_ROM_QSTR(MP_QSTR_PI_RX), MP_ROM_PTR(&pin_PB22) },
- { MP_ROM_QSTR(MP_QSTR_PI_TX), MP_ROM_PTR(&pin_PB23) },
-
- // SIGNAL / Digital pins (for reference)
- { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB23) },
- { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB22) },
- { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB02) },
- { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB03) },
- { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA00) },
- { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA01) },
- { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA28) },
- { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA03) },
- { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA20) },
- { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PB11) },
- { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PB09) },
- { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PB10) },
- { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PB08) },
- { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA21) },
- { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PA03) },
-
- { 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/boards/robohatmm1/board.c b/ports/atmel-samd/boards/robohatmm1_m0/board.c
index c8e20206a..c8e20206a 100644
--- a/ports/atmel-samd/boards/robohatmm1/board.c
+++ b/ports/atmel-samd/boards/robohatmm1_m0/board.c
diff --git a/ports/atmel-samd/boards/robohatmm1/mpconfigboard.h b/ports/atmel-samd/boards/robohatmm1_m0/mpconfigboard.h
index dd31e912a..c6856c68f 100644
--- a/ports/atmel-samd/boards/robohatmm1/mpconfigboard.h
+++ b/ports/atmel-samd/boards/robohatmm1_m0/mpconfigboard.h
@@ -1,7 +1,7 @@
-#define MICROPY_HW_BOARD_NAME "Robo HAT MM1"
+#define MICROPY_HW_BOARD_NAME "Robo HAT MM1 M0"
#define MICROPY_HW_MCU_NAME "samd21g18"
-#define MICROPY_HW_LED_STATUS (&pin_PA21)
+#define MICROPY_HW_LED_STATUS (&pin_PB22)
// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
#define SPI_FLASH_BAUDRATE (8000000)
@@ -24,23 +24,19 @@
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
-//#define BOARD_HAS_CRYSTAL 0
#define CALIBRATE_CRYSTALLESS 1
#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
-#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
-#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
-#define DEFAULT_SPI_BUS_MISO (&pin_PB08)
+#define DEFAULT_SPI_BUS_SCK (&pin_PB09)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB08)
+#define DEFAULT_SPI_BUS_MISO (&pin_PB11)
-#define DEFAULT_UART_BUS_RX (&pin_PB23)
-#define DEFAULT_UART_BUS_TX (&pin_PB22)
+//#define DEFAULT_UART_BUS_RX (&pin_PB03)
+//#define DEFAULT_UART_BUS_TX (&pin_PB02)
// USB is always used internally so skip the pin objects for it.
#define IGNORE_PIN_PA24 1
#define IGNORE_PIN_PA25 1
-//#define CIRCUITPY_I2CSLAVE
-//#define CIRCUITPY_DISPLAYIO (0)
-
diff --git a/ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk b/ports/atmel-samd/boards/robohatmm1_m0/mpconfigboard.mk
index 9523984b7..e703fbfb9 100644
--- a/ports/atmel-samd/boards/robohatmm1/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/robohatmm1_m0/mpconfigboard.mk
@@ -1,33 +1,29 @@
LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
USB_VID = 0x1209
USB_PID = 0x4D43
-USB_PRODUCT = "Robo HAT MM1"
+USB_PRODUCT = "Robo HAT MM1 M0"
USB_MANUFACTURER = "Robotics Masters"
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
-# Non-Flash Edition
-#INTERNAL_FLASH_FILESYSTEM = 1
-#LONGINT_IMPL = NONE
-#SUPEROPT_GC = 0
-
-# SPI-Flash Edition
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ"
LONGINT_IMPL = MPZ
-# Make room for frozen Libraries
+
+# Non-Flash Edition
+#INTERNAL_FLASH_FILESYSTEM = 1
+#LONGINT_IMPL = NONE
+
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
-CFLAGS_INLINE_LIMIT = 55
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
# Include these Python libraries in firmware.
-FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_INA219
#FROZEN_MPY_DIRS += $(TOP)/frozen/RoboticsMasters_CircuitPython_MPU9250
-FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
-#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Crickit
-#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor
-#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw
diff --git a/ports/atmel-samd/boards/robohatmm1_m0/pins.c b/ports/atmel-samd/boards/robohatmm1_m0/pins.c
new file mode 100644
index 000000000..edaf0bc4c
--- /dev/null
+++ b/ports/atmel-samd/boards/robohatmm1_m0/pins.c
@@ -0,0 +1,92 @@
+#include "shared-bindings/board/__init__.h"
+// Version 2.4
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ // SERVO Pins
+ { MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO5), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO6), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO7), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO8), MP_ROM_PTR(&pin_PA08) },
+
+ // RCC Pins
+ { MP_ROM_QSTR(MP_QSTR_RCC1), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_RCC2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_RCC3), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_RCC4), MP_ROM_PTR(&pin_PA04) },
+
+ // Special Function
+ { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_OFF), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_DISABLE), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_ON), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_ENABLE), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_PA27) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PB22) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB03) },
+
+ // GROVE on SERCOM0
+ { MP_ROM_QSTR(MP_QSTR_GROVE_SCL), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_SDA), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_RX), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_TX), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_D1), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_D0), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_A1), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_A0), MP_ROM_PTR(&pin_PA08) },
+
+ // UART on SERCOM0
+ { MP_ROM_QSTR(MP_QSTR_UART_TX), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_UART_RX), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_UART_CTS), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_UART_RTS), MP_ROM_PTR(&pin_PA07) },
+
+ // UART on SERCOM1 (Raspberry Pi)
+ { MP_ROM_QSTR(MP_QSTR_TX1), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_RX1), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_PI_RX), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_PI_TX), MP_ROM_PTR(&pin_PA17) },
+
+ // I2C on SERCOM1 (External Connector)
+ { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_PA01) },
+
+ // SPI Flash on SERCOM2
+ { MP_ROM_QSTR(MP_QSTR_FLASH_SCK), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_FLASH_MISO), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_FLASH_MOSI), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_FLASH_CS), MP_ROM_PTR(&pin_PA15) },
+
+ // I2C on SERCOM3 (RPi & Internal)
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_PI_SDA), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_PI_SCL), MP_ROM_PTR(&pin_PA23) },
+
+ // SPI on SERCOM4
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB11) },
+
+ // GPS on SERCOM5
+ { MP_ROM_QSTR(MP_QSTR_GPS_TX), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_GPS_RX), MP_ROM_PTR(&pin_PB03) },
+
+ // Raspberry Pi
+ { MP_ROM_QSTR(MP_QSTR_PI_GP25), MP_ROM_PTR(&pin_PA30) },
+ { MP_ROM_QSTR(MP_QSTR_SWCLK), MP_ROM_PTR(&pin_PA30) },
+ { MP_ROM_QSTR(MP_QSTR_PI_GP24), MP_ROM_PTR(&pin_PA31) },
+ { MP_ROM_QSTR(MP_QSTR_SWDIO), MP_ROM_PTR(&pin_PA31) },
+
+ { 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/boards/robohatmm1_m4/board.c b/ports/atmel-samd/boards/robohatmm1_m4/board.c
new file mode 100644
index 000000000..0f60736a2
--- /dev/null
+++ b/ports/atmel-samd/boards/robohatmm1_m4/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/robohatmm1_m4/mpconfigboard.h b/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.h
new file mode 100644
index 000000000..64040a658
--- /dev/null
+++ b/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.h
@@ -0,0 +1,44 @@
+#define MICROPY_HW_BOARD_NAME "Robo HAT MM1 M4"
+#define MICROPY_HW_MCU_NAME "samd51g19"
+
+#define CIRCUITPY_MCU_FAMILY samd51
+
+#define MICROPY_HW_LED_STATUS (&pin_PB22)
+
+// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+// On-board flash
+#define SPI_FLASH_MOSI_PIN &pin_PA12
+#define SPI_FLASH_MISO_PIN &pin_PA14
+#define SPI_FLASH_SCK_PIN &pin_PA13
+#define SPI_FLASH_CS_PIN &pin_PA15
+
+// These are pins not to reset.
+// SPI Data pins
+#define MICROPY_PORT_A (0)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+#define MICROPY_PORT_D (0)
+
+#define AUTORESET_DELAY_MS 500
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code
+#define CIRCUITPY_INTERNAL_NVM_SIZE 8192
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB09)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB08)
+#define DEFAULT_SPI_BUS_MISO (&pin_PB11)
+
+//#define DEFAULT_UART_BUS_RX (&pin_PB03)
+//#define DEFAULT_UART_BUS_TX (&pin_PB02)
+
+// 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/robohatmm1_m4/mpconfigboard.mk b/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk
new file mode 100644
index 000000000..56f1617db
--- /dev/null
+++ b/ports/atmel-samd/boards/robohatmm1_m4/mpconfigboard.mk
@@ -0,0 +1,28 @@
+LD_FILE = boards/samd51x19-bootloader-external-flash.ld
+USB_VID = 0x1209
+USB_PID = 0x4D43
+USB_PRODUCT = "Robo HAT MM1 M4"
+USB_MANUFACTURER = "Robotics Masters"
+
+CHIP_VARIANT = SAMD51G19A
+CHIP_FAMILY = samd51
+
+#QSPI_FLASH_FILESYSTEM = 0
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ"
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_PS2IO = 1
+# No I2S on SAMD51G
+CIRCUITPY_AUDIOBUSIO = 0
+# Make room for more stuff
+CIRCUITPY_DISPLAYIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+
+# Include these Python libraries in firmware.
+#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
+#FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_INA219
+#FROZEN_MPY_DIRS += $(TOP)/frozen/RoboticsMasters_CircuitPython_MPU9250
diff --git a/ports/atmel-samd/boards/robohatmm1_m4/pins.c b/ports/atmel-samd/boards/robohatmm1_m4/pins.c
new file mode 100644
index 000000000..edaf0bc4c
--- /dev/null
+++ b/ports/atmel-samd/boards/robohatmm1_m4/pins.c
@@ -0,0 +1,92 @@
+#include "shared-bindings/board/__init__.h"
+// Version 2.4
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ // SERVO Pins
+ { MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO5), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO6), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO7), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_SERVO8), MP_ROM_PTR(&pin_PA08) },
+
+ // RCC Pins
+ { MP_ROM_QSTR(MP_QSTR_RCC1), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_RCC2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_RCC3), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_RCC4), MP_ROM_PTR(&pin_PA04) },
+
+ // Special Function
+ { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_OFF), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_DISABLE), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_ON), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_POWER_ENABLE), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_PA27) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PB22) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB03) },
+
+ // GROVE on SERCOM0
+ { MP_ROM_QSTR(MP_QSTR_GROVE_SCL), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_SDA), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_RX), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_TX), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_D1), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_D0), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_A1), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_GROVE_A0), MP_ROM_PTR(&pin_PA08) },
+
+ // UART on SERCOM0
+ { MP_ROM_QSTR(MP_QSTR_UART_TX), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_UART_RX), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_UART_CTS), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_UART_RTS), MP_ROM_PTR(&pin_PA07) },
+
+ // UART on SERCOM1 (Raspberry Pi)
+ { MP_ROM_QSTR(MP_QSTR_TX1), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_RX1), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_PI_RX), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_PI_TX), MP_ROM_PTR(&pin_PA17) },
+
+ // I2C on SERCOM1 (External Connector)
+ { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_PA01) },
+
+ // SPI Flash on SERCOM2
+ { MP_ROM_QSTR(MP_QSTR_FLASH_SCK), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_FLASH_MISO), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_FLASH_MOSI), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_FLASH_CS), MP_ROM_PTR(&pin_PA15) },
+
+ // I2C on SERCOM3 (RPi & Internal)
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_PI_SDA), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_PI_SCL), MP_ROM_PTR(&pin_PA23) },
+
+ // SPI on SERCOM4
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB11) },
+
+ // GPS on SERCOM5
+ { MP_ROM_QSTR(MP_QSTR_GPS_TX), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_GPS_RX), MP_ROM_PTR(&pin_PB03) },
+
+ // Raspberry Pi
+ { MP_ROM_QSTR(MP_QSTR_PI_GP25), MP_ROM_PTR(&pin_PA30) },
+ { MP_ROM_QSTR(MP_QSTR_SWCLK), MP_ROM_PTR(&pin_PA30) },
+ { MP_ROM_QSTR(MP_QSTR_PI_GP24), MP_ROM_PTR(&pin_PA31) },
+ { MP_ROM_QSTR(MP_QSTR_SWDIO), MP_ROM_PTR(&pin_PA31) },
+
+ { 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/boards/sam32/mpconfigboard.mk b/ports/atmel-samd/boards/sam32/mpconfigboard.mk
index ca1e11f01..12884a9cc 100644
--- a/ports/atmel-samd/boards/sam32/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sam32/mpconfigboard.mk
@@ -9,6 +9,3 @@ CHIP_FAMILY = samd51
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
-
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
diff --git a/ports/atmel-samd/boards/serpente/board.c b/ports/atmel-samd/boards/serpente/board.c
new file mode 100644
index 000000000..d7e856d61
--- /dev/null
+++ b/ports/atmel-samd/boards/serpente/board.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/serpente/mpconfigboard.h b/ports/atmel-samd/boards/serpente/mpconfigboard.h
new file mode 100644
index 000000000..034e1f6c3
--- /dev/null
+++ b/ports/atmel-samd/boards/serpente/mpconfigboard.h
@@ -0,0 +1,39 @@
+#define MICROPY_HW_BOARD_NAME "Serpente"
+#define MICROPY_HW_MCU_NAME "samd21e18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA23)
+
+#define SPI_FLASH_MOSI_PIN &pin_PA16
+#define SPI_FLASH_MISO_PIN &pin_PA18
+#define SPI_FLASH_SCK_PIN &pin_PA17
+#define SPI_FLASH_CS_PIN &pin_PA15
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code.
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA09)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA08)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA05)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA04)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA06)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA09)
+#define DEFAULT_UART_BUS_TX (&pin_PA08)
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
+
+// Not connected
+#define IGNORE_PIN_PA13 1
+#define IGNORE_PIN_PA28 1
+
diff --git a/ports/atmel-samd/boards/serpente/mpconfigboard.mk b/ports/atmel-samd/boards/serpente/mpconfigboard.mk
new file mode 100644
index 000000000..98e1e3729
--- /dev/null
+++ b/ports/atmel-samd/boards/serpente/mpconfigboard.mk
@@ -0,0 +1,17 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
+USB_VID = 0x239A
+USB_PID = 0x8058
+USB_PRODUCT = "Serpente"
+USB_MANUFACTURER = "arturo182"
+
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = GD25Q32C
+LONGINT_IMPL = NONE
+
+CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_GAMEPAD = 0
diff --git a/ports/atmel-samd/boards/serpente/pins.c b/ports/atmel-samd/boards/serpente/pins.c
new file mode 100644
index 000000000..0bf686656
--- /dev/null
+++ b/ports/atmel-samd/boards/serpente/pins.c
@@ -0,0 +1,40 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA09) },
+
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA09) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_PA23) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA05) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA08) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA08) },
+
+ { MP_ROM_QSTR(MP_QSTR_RX2), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_TX2), MP_ROM_PTR(&pin_PA04) },
+
+ { 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/boards/snekboard/board.c b/ports/atmel-samd/boards/snekboard/board.c
new file mode 100644
index 000000000..c8e20206a
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void)
+{
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.h b/ports/atmel-samd/boards/snekboard/mpconfigboard.h
new file mode 100644
index 000000000..a349143d9
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.h
@@ -0,0 +1,35 @@
+#define MICROPY_HW_BOARD_NAME "keithp.com snekboard"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA02)
+
+#define MICROPY_HW_NEOPIXEL (&pin_PB11)
+
+#define SPI_FLASH_MOSI_PIN &pin_PB22
+#define SPI_FLASH_MISO_PIN &pin_PB03
+#define SPI_FLASH_SCK_PIN &pin_PB23
+#define SPI_FLASH_CS_PIN &pin_PA27
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (PORT_PB11)
+#define MICROPY_PORT_B ( 0 )
+#define MICROPY_PORT_C ( 0 )
+
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code.
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 0
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA08) /* ANALOG 5 */
+#define DEFAULT_I2C_BUS_SDA (&pin_PA09) /* ANALOG 6 */
+
+#define DEFAULT_UART_BUS_RX (&pin_PB08) /* ANALOG 1 */
+#define DEFAULT_UART_BUS_TX (&pin_PB09) /* ANALOG 2 */
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
new file mode 100644
index 000000000..db2e511ab
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk
@@ -0,0 +1,20 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x804E
+USB_PRODUCT = "snekboard"
+USB_MANUFACTURER = "keithp.com"
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "W25Q16JV_IQ"
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_GAMEPAD = 0
+CIRCUITPY_I2CSLAVE = 0
+
+CFLAGS_INLINE_LIMIT = 60
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/snekboard/pins.c b/ports/atmel-samd/boards/snekboard/pins.c
new file mode 100644
index 000000000..48bdc672e
--- /dev/null
+++ b/ports/atmel-samd/boards/snekboard/pins.c
@@ -0,0 +1,28 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_POWER1), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_DIR1), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_POWER2), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_DIR2), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_POWER3), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_DIR3), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_POWER4), MP_ROM_PTR(&pin_PA19) },
+ { MP_ROM_QSTR(MP_QSTR_DIR4), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB11) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
index 3be1a17d3..e80ef6277 100755
--- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk
@@ -12,5 +12,8 @@ EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "W25Q32FV"
LONGINT_IMPL = MPZ
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_I2CSLAVE = 0
+
CFLAGS_INLINE_LIMIT = 60
SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h
index 6870b86ba..8ca1df162 100644
--- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h
@@ -8,8 +8,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)
-#define CIRCUITPY_BITBANG_APA102
-
// These are pins not to reset.
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
index 6d108e649..ec37186c3 100644
--- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
@@ -15,5 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0
-# No touch on SAMD51 yet
-CIRCUITPY_TOUCHIO = 0
+
+CIRCUITPY_BITBANG_APA102 = 1
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index b9d36a741..c20358e19 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -11,3 +11,9 @@ SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = W25Q32BV
LONGINT_IMPL = MPZ
+
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CSLAVE = 0
+
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/ugame10/board.c b/ports/atmel-samd/boards/ugame10/board.c
index 828f0c87d..ce389a2b1 100644
--- a/ports/atmel-samd/boards/ugame10/board.c
+++ b/ports/atmel-samd/boards/ugame10/board.c
@@ -91,6 +91,10 @@ void board_init(void) {
2, // row start
0, // rotation
16, // Color depth
+ false, // grayscale
+ false, // pixels in byte share row. Only used with depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
@@ -98,10 +102,13 @@ void board_init(void) {
display_init_sequence,
sizeof(display_init_sequence),
NULL,
+ NO_BRIGHTNESS_COMMAND,
1.0f, // brightness
false, // auto_brightness
false, // single_byte_bounds
- false); // data as commands
+ false, // data as commands
+ true, // auto_refresh
+ 60); // native_frames_per_second
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
index 6361da2a6..f0310b4aa 100644
--- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
@@ -10,7 +10,7 @@ CHIP_FAMILY = samd21
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = S25FL216K
-LONGINT_IMPL = MPZ
+LONGINT_IMPL = NONE
CIRCUITPY_STAGE = 1
CIRCUITPY_MATH = 1
@@ -19,16 +19,24 @@ CIRCUITPY_ANALOGIO = 1
CIRCUITPY_GAMEPAD = 1
CIRCUITPY_DISPLAYIO = 1
-CIRCUITPY_TOUCHIO = 0
+CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CSLAVE = 0
CIRCUITPY_NEOPIXEL_WRITE = 0
+CIRCUITPY_PIXELBUF = 0
CIRCUITPY_RTC = 0
-CIRCUITPY_USB_MIDI = 0
+CIRCUITPY_TOUCHIO = 0
CIRCUITPY_USB_HID = 0
-CIRCUITPY_I2CSLAVE = 0
-CIRCUITPY_FREQUENCYIO = 0
-CIRCUITPY_AUDIOBUSIO = 0
-CIRCUITPY_PIXELBUF = 0
+CIRCUITPY_USB_MIDI = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/ugame10
CIRCUITPY_DISPLAY_FONT = $(TOP)/ports/atmel-samd/boards/ugame10/brutalist-6.bdf
+
+# Tweak inlining depending on language.
+ifeq ($(TRANSLATION), zh_Latn_pinyin)
+CFLAGS_INLINE_LIMIT = 45
+else
+CFLAGS_INLINE_LIMIT = 70
+endif
diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
index 20934bed4..05a6aaf7b 100644
--- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
+++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
@@ -33,7 +33,7 @@
#include "py/runtime.h"
#include "common-hal/audiobusio/I2SOut.h"
#include "shared-bindings/audiobusio/I2SOut.h"
-#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audiocore/RawSample.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/translate.h"
diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
index 8b308b60b..3a51cce8f 100644
--- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
+++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@@ -355,7 +355,7 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) {
// output_buffer_length is the number of slots, not the number of bytes.
uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self,
uint16_t* output_buffer, uint32_t output_buffer_length) {
- uint8_t dma_channel = find_free_audio_dma_channel();
+ uint8_t dma_channel = audio_dma_allocate_channel();
uint8_t event_channel = find_sync_event_channel();
if (event_channel >= EVSYS_SYNCH_NUM) {
mp_raise_RuntimeError(translate("All sync event channels in use"));
@@ -385,7 +385,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
init_event_channel_interrupt(event_channel, CORE_GCLK, EVSYS_ID_GEN_DMAC_CH_0 + dma_channel);
// Turn on serializer now to get it in sync with DMA.
i2s_set_serializer_enable(self->serializer, true);
- dma_enable_channel(dma_channel);
+ audio_dma_enable_channel(dma_channel);
// Record
uint32_t buffers_processed = 0;
@@ -408,9 +408,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
// If wait_counts exceeds the max count, buffer has probably stopped filling;
// DMA may have missed an I2S trigger event.
while (!event_interrupt_active(event_channel) && ++wait_counts < MAX_WAIT_COUNTS) {
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
// The mic is running all the time, so we don't need to wait the usual 10msec or 100msec
@@ -466,7 +464,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
}
disable_event_channel(event_channel);
- dma_disable_channel(dma_channel);
+ audio_dma_free_channel(dma_channel);
// Turn off serializer, but leave clock on, to avoid mic startup delay.
i2s_set_serializer_enable(self->serializer, false);
diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c
index a75abd324..36ab52006 100644
--- a/ports/atmel-samd/common-hal/audioio/AudioOut.c
+++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c
@@ -69,9 +69,7 @@ static void ramp_value(uint16_t start, uint16_t end) {
DAC->DATA.reg = value;
DAC->DATABUF.reg = value;
common_hal_mcu_delay_us(50);
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
}
#endif
@@ -94,9 +92,7 @@ static void ramp_value(uint16_t start, uint16_t end) {
DAC->DATABUF[1].reg = value;
common_hal_mcu_delay_us(50);
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
}
#endif
@@ -202,7 +198,7 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self,
#endif
#ifdef SAMD51
DAC->EVCTRL.reg |= DAC_EVCTRL_STARTEI0;
- DAC->DACCTRL[0].reg = DAC_DACCTRL_CCTRL_CC1M |
+ DAC->DACCTRL[0].reg = DAC_DACCTRL_CCTRL_CC100K |
DAC_DACCTRL_ENABLE |
DAC_DACCTRL_LEFTADJ;
DAC->CTRLB.reg = DAC_CTRLB_REFSEL_VREFPU;
@@ -211,7 +207,7 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self,
#ifdef SAMD51
if (channel1_enabled) {
DAC->EVCTRL.reg |= DAC_EVCTRL_STARTEI1;
- DAC->DACCTRL[1].reg = DAC_DACCTRL_CCTRL_CC1M |
+ DAC->DACCTRL[1].reg = DAC_DACCTRL_CCTRL_CC100K |
DAC_DACCTRL_ENABLE |
DAC_DACCTRL_LEFTADJ;
DAC->CTRLB.reg = DAC_CTRLB_REFSEL_VREFPU;
@@ -316,6 +312,10 @@ void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self) {
return;
}
+ if (common_hal_audioio_audioout_get_playing(self)) {
+ common_hal_audioio_audioout_stop(self);
+ }
+
// Ramp the DAC down.
ramp_value(self->quiescent_value, 0);
@@ -385,19 +385,17 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self,
#ifdef SAMD51
uint32_t left_channel_reg = (uint32_t) &DAC->DATABUF[0].reg;
- uint8_t left_channel_trigger = DAC_DMAC_ID_EMPTY_0;
+ uint8_t tc_trig_id = TC0_DMAC_ID_OVF + 3 * self->tc_index;
+ uint8_t left_channel_trigger = tc_trig_id;
uint32_t right_channel_reg = 0;
- uint8_t right_channel_trigger = 0;
+ uint8_t right_channel_trigger = tc_trig_id;
if (self->left_channel == &pin_PA05) {
left_channel_reg = (uint32_t) &DAC->DATABUF[1].reg;
- left_channel_trigger = DAC_DMAC_ID_EMPTY_1;
} else if (self->right_channel == &pin_PA05) {
right_channel_reg = (uint32_t) &DAC->DATABUF[1].reg;
- right_channel_trigger = DAC_DMAC_ID_EMPTY_1;
}
if (self->right_channel == &pin_PA02) {
right_channel_reg = (uint32_t) &DAC->DATABUF[0].reg;
- right_channel_trigger = DAC_DMAC_ID_EMPTY_0;
}
result = audio_dma_setup_playback(&self->left_dma, sample, loop, true, 0,
false /* output unsigned */,
diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c
index a0c04d65d..cdc616bbc 100644
--- a/ports/atmel-samd/common-hal/busio/I2C.c
+++ b/ports/atmel-samd/common-hal/busio/I2C.c
@@ -36,6 +36,8 @@
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/shared/translate.h"
+#include "common-hal/busio/SPI.h" // for never_reset_sercom
+
// Number of times to try to send packet if failed.
#define ATTEMPTS 2
@@ -225,3 +227,10 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
}
return MP_EIO;
}
+
+void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
+ never_reset_sercom(self->i2c_desc.device.hw);
+
+ never_reset_pin_number(self->scl_pin);
+ never_reset_pin_number(self->sda_pin);
+}
diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c
index 644b9a87b..7a1426bed 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.c
+++ b/ports/atmel-samd/common-hal/busio/SPI.c
@@ -122,7 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
}
Sercom* potential_sercom = sercom_insts[sercom_index];
if (
- #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
+ #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
(potential_sercom->SPI.CTRLA.bit.ENABLE != 0 &&
potential_sercom != status_apa102.spi_desc.dev.prvt &&
!apa102_sck_in_use)) {
@@ -181,7 +181,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
// Set up SPI clocks on SERCOM.
samd_peripherals_sercom_clock_init(sercom, sercom_index);
- #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
+ #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
// if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out
hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom);
#endif
diff --git a/ports/atmel-samd/common-hal/busio/SPI.h b/ports/atmel-samd/common-hal/busio/SPI.h
index 56d163a9d..a1c0e1517 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.h
+++ b/ports/atmel-samd/common-hal/busio/SPI.h
@@ -43,6 +43,7 @@ typedef struct {
} busio_spi_obj_t;
void reset_sercoms(void);
+void never_reset_sercom(Sercom* sercom);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_H
diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c
index f04594842..2505e894a 100644
--- a/ports/atmel-samd/common-hal/busio/UART.c
+++ b/ports/atmel-samd/common-hal/busio/UART.c
@@ -291,13 +291,11 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
// Reset the timeout on every character read.
start_ticks = ticks_ms;
}
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
+ RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
break;
}
-#endif
// If we are zero timeout, make sure we don't loop again (in the event
// we read in under 1ms)
if (self->timeout_ms == 0) {
@@ -339,9 +337,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
done = true;
break;
}
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
if (!done) {
diff --git a/ports/atmel-samd/common-hal/displayio/ParallelBus.c b/ports/atmel-samd/common-hal/displayio/ParallelBus.c
index 7a5f61448..2479e3b40 100644
--- a/ports/atmel-samd/common-hal/displayio/ParallelBus.c
+++ b/ports/atmel-samd/common-hal/displayio/ParallelBus.c
@@ -31,6 +31,7 @@
#include "common-hal/microcontroller/Pin.h"
#include "py/runtime.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "tick.h"
@@ -66,10 +67,6 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
- self->reset.base.type = &digitalio_digitalinout_type;
- common_hal_digitalio_digitalinout_construct(&self->reset, reset);
- common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
-
self->write.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->write, write);
common_hal_digitalio_digitalinout_switch_to_output(&self->write, true, DRIVE_MODE_PUSH_PULL);
@@ -82,11 +79,19 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
self->write_group = &PORT->Group[write->number / 32];
self->write_mask = 1 << (write->number % 32);
+ self->reset.base.type = &mp_type_NoneType;
+ if (reset != NULL) {
+ self->reset.base.type = &digitalio_digitalinout_type;
+ common_hal_digitalio_digitalinout_construct(&self->reset, reset);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
+ never_reset_pin_number(reset->number);
+ common_hal_displayio_parallelbus_reset(self);
+ }
+
never_reset_pin_number(command->number);
never_reset_pin_number(chip_select->number);
never_reset_pin_number(write->number);
never_reset_pin_number(read->number);
- never_reset_pin_number(reset->number);
for (uint8_t i = 0; i < 8; i++) {
never_reset_pin_number(data_pin + i);
}
@@ -104,15 +109,31 @@ void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self)
reset_pin_number(self->reset.pin->number);
}
+bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
+ displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (self->reset.base.type == &mp_type_NoneType) {
+ return false;
+ }
+
+ common_hal_digitalio_digitalinout_set_value(&self->reset, false);
+ common_hal_mcu_delay_us(4);
+ common_hal_digitalio_digitalinout_set_value(&self->reset, true);
+ return true;
+}
+
+bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
+ return true;
+}
+
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
return true;
}
-void common_hal_displayio_parallelbus_send(mp_obj_t obj, bool command, uint8_t *data, uint32_t data_length) {
+void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
- common_hal_digitalio_digitalinout_set_value(&self->command, !command);
+ common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA);
uint32_t* clear_write = (uint32_t*) &self->write_group->OUTCLR.reg;
uint32_t* set_write = (uint32_t*) &self->write_group->OUTSET.reg;
uint32_t mask = self->write_mask;
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
index 528a5c808..8b8bc6dc6 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
@@ -198,9 +198,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
while(pulse_index < length) {
// Do other things while we wait. The interrupts will handle sending the
// signal.
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP;
diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
index e3bcf395b..0922718f9 100644
--- a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
+++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
@@ -35,7 +35,7 @@
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self,
const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b) {
- if (!pin_a->has_extint || !pin_a->has_extint) {
+ if (!pin_a->has_extint || !pin_b->has_extint) {
mp_raise_RuntimeError(translate("Both pins must support hardware interrupts"));
}
diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c
index 9fb3a2ea1..908d8d722 100644
--- a/ports/atmel-samd/common-hal/touchio/TouchIn.c
+++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c
@@ -34,9 +34,10 @@
#include "shared-bindings/touchio/TouchIn.h"
#include "supervisor/shared/translate.h"
+// Native touchio only exists for SAMD21
#ifdef SAMD21
+
#include "hpl/pm/hpl_pm_base.h"
-#endif
#include "samd/clocks.h"
#include "samd/pins.h"
@@ -51,9 +52,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
while (!adafruit_ptc_is_conversion_finished(PTC)) {
// wait
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
return adafruit_ptc_get_conversion_result(PTC);
@@ -67,7 +66,6 @@ void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self,
claim_pin(pin);
// Turn on the PTC if its not in use. We won't turn it off until reset.
- #ifdef SAMD21
if ((( Ptc *) PTC)->CTRLA.bit.ENABLE == 0) {
// We run the PTC at 8mhz so divide the 48mhz clock by 6.
uint8_t gclk = find_free_gclk(6);
@@ -96,7 +94,6 @@ void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self,
// but for touches using fruit or other objects, the difference is much less.
self->threshold = get_raw_reading(self) + 100;
- #endif
}
bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t* self) {
@@ -141,3 +138,5 @@ uint16_t common_hal_touchio_touchin_get_threshold(touchio_touchin_obj_t *self) {
void common_hal_touchio_touchin_set_threshold(touchio_touchin_obj_t *self, uint16_t new_threshold) {
self->threshold = new_threshold;
}
+
+#endif // SAMD21
diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.h b/ports/atmel-samd/common-hal/touchio/TouchIn.h
index ffe8a6c01..85550b8a3 100644
--- a/ports/atmel-samd/common-hal/touchio/TouchIn.h
+++ b/ports/atmel-samd/common-hal/touchio/TouchIn.h
@@ -27,6 +27,9 @@
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_TOUCHIO_TOUCHIN_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_TOUCHIO_TOUCHIN_H
+// Native touchio only exists for SAMD21
+#ifdef SAMD21
+
#include "common-hal/microcontroller/Pin.h"
#include "samd21_ptc_component.h"
@@ -42,4 +45,6 @@ typedef struct {
void touchin_reset(void);
+#endif // SAMD21
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_TOUCHIO_TOUCHIN_H
diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk
index 66ee92e6b..51bbdd658 100644
--- a/ports/atmel-samd/mpconfigport.mk
+++ b/ports/atmel-samd/mpconfigport.mk
@@ -17,12 +17,18 @@ endif
# Put samd21-only choices here.
ifeq ($(CHIP_FAMILY),samd21)
# frequencyio not yet verified as working on SAMD21.
-CIRCUITPY_FRQUENCYIO = 0
+CIRCUITPY_AUDIOMIXER = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_TOUCHIO_USE_NATIVE = 1
+
+# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
+USB_MSC_NUM_ENDPOINT_PAIRS = 2
endif
# Put samd51-only choices here.
ifeq ($(CHIP_FAMILY),samd51)
CIRCUITPY_SAMD = 1
+CIRCUITPY_TOUCHIO_USE_NATIVE = 0
endif
INTERNAL_LIBM = 1
diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c
index 5c34a576a..957bf6073 100644
--- a/ports/atmel-samd/mphalport.c
+++ b/ports/atmel-samd/mphalport.c
@@ -53,9 +53,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t duration = 0;
while (duration < delay) {
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
// Check to see if we've been CTRL-Ced by autoreload or the user.
if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) ||
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals
-Subproject 83a4759d186574d8034435cd2303def85e4ed79
+Subproject 2ba5b20ba725e1c91c77875fba3a5e22059cdb9
diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c
index 37360deb0..512fd8eb8 100644
--- a/ports/atmel-samd/supervisor/port.c
+++ b/ports/atmel-samd/supervisor/port.c
@@ -54,7 +54,11 @@
#include "common-hal/pulseio/PWMOut.h"
#include "common-hal/ps2io/Ps2.h"
#include "common-hal/rtc/RTC.h"
+
+#if CIRCUITPY_TOUCHIO_USE_NATIVE
#include "common-hal/touchio/TouchIn.h"
+#endif
+
#include "samd/cache.h"
#include "samd/clocks.h"
#include "samd/events.h"
@@ -211,7 +215,7 @@ void reset_port(void) {
//pdmin_reset();
#endif
-#if CIRCUITPY_TOUCHIO
+#if CIRCUITPY_TOUCHIO && CIRCUITPY_TOUCHIO_USE_NATIVE
touchin_reset();
#endif
eic_reset();
diff --git a/ports/atmel-samd/tick.c b/ports/atmel-samd/tick.c
index dde473375..4d7bb9dca 100644
--- a/ports/atmel-samd/tick.c
+++ b/ports/atmel-samd/tick.c
@@ -29,6 +29,7 @@
#include "peripheral_clk_config.h"
#include "supervisor/shared/autoreload.h"
+#include "supervisor/filesystem.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
@@ -52,10 +53,13 @@ void SysTick_Handler(void) {
(void) SysTick->CTRL;
common_hal_mcu_enable_interrupts();
- #ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
+#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
+ filesystem_tick();
+#endif
+#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
- #endif
- #ifdef CIRCUITPY_GAMEPAD_TICKS
+#endif
+#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
#if CIRCUITPY_GAMEPAD
gamepad_tick();
@@ -64,7 +68,7 @@ void SysTick_Handler(void) {
gamepadshift_tick();
#endif
}
- #endif
+#endif
}
void tick_init() {
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index 83f87536b..be8a71b3f 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -81,6 +81,7 @@ INC += -I./nrfx
INC += -I./nrfx/hal
INC += -I./nrfx/mdk
INC += -I./nrfx/drivers/include
+INC += -I./nrfx/drivers/src
INC += -I./bluetooth
INC += -I./peripherals
INC += -I../../lib/mp-readline
@@ -89,13 +90,10 @@ INC += -I../../supervisor/shared/usb
#Debugging/Optimization
ifeq ($(DEBUG), 1)
- CFLAGS += -ggdb
- # You may want to enable these flags to make setting breakpoints easier.
- CFLAGS += -fno-inline -fno-ipa-sra
+ CFLAGS += -ggdb3 -Og
else
CFLAGS += -Os -DNDEBUG
- # TODO: Test with -flto
- ### CFLAGS += -flto
+ CFLAGS += -flto -flto-partition=none
endif
@@ -184,8 +182,7 @@ SRC_C += \
# USB source files for nrf52840
ifeq ($(MCU_SUB_VARIANT),nrf52840)
SRC_C += \
- lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c \
- lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c
+ lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c
endif
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
@@ -193,7 +190,8 @@ SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix common-hal/, $(SRC_COMMON_HAL))
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
- $(addprefix shared-module/, $(SRC_SHARED_MODULE))
+ $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \
+ $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL))
SRC_S = supervisor/cpu.s
diff --git a/ports/nrf/background.c b/ports/nrf/background.c
index 9c4f3ab27..305f607c5 100644
--- a/ports/nrf/background.c
+++ b/ports/nrf/background.c
@@ -33,6 +33,14 @@
#include "shared-module/displayio/__init__.h"
#endif
+#if CIRCUITPY_AUDIOBUSIO
+#include "common-hal/audiobusio/I2SOut.h"
+#endif
+
+#if CIRCUITPY_AUDIOPWMIO
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#endif
+
static bool running_background_tasks = false;
void background_tasks_reset(void) {
@@ -47,9 +55,16 @@ void run_background_tasks(void) {
running_background_tasks = true;
filesystem_background();
usb_background();
+#if CIRCUITPY_AUDIOPWMIO
+ audiopwmout_background();
+#endif
+#if CIRCUITPY_AUDIOBUSIO
+ i2s_background();
+#endif
+
#if CIRCUITPY_DISPLAYIO
- displayio_refresh_displays();
+ displayio_background();
#endif
running_background_tasks = false;
diff --git a/ports/nrf/bluetooth/ble_uart.c b/ports/nrf/bluetooth/ble_uart.c
index 91d10cff1..787a2a117 100644
--- a/ports/nrf/bluetooth/ble_uart.c
+++ b/ports/nrf/bluetooth/ble_uart.c
@@ -34,11 +34,11 @@
#include "py/mphal.h"
#include "py/runtime.h"
#include "lib/utils/interrupt_char.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Device.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Device.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
#if (MICROPY_PY_BLE_NUS == 1)
@@ -138,9 +138,7 @@ void ble_uart_init(void) {
m_cccd_enabled = false;
while (!m_cccd_enabled) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
}
@@ -150,9 +148,7 @@ bool ble_uart_connected(void) {
char ble_uart_rx_chr(void) {
while (isBufferEmpty(&m_rx_ring_buffer)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
uint8_t byte;
diff --git a/supervisor/shared/usb/usb_desc.h b/ports/nrf/boards/circuitplayground_bluefruit/board.c
index 250147aa6..4421970ee 100644
--- a/supervisor/shared/usb/usb_desc.h
+++ b/ports/nrf/boards/circuitplayground_bluefruit/board.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 hathach for Adafruit Industries
+ * 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
@@ -24,20 +24,15 @@
* THE SOFTWARE.
*/
-#ifndef USB_DESC_H_
-#define USB_DESC_H_
+#include "boards/board.h"
-#include "lib/tinyusb/src/tusb.h"
+void board_init(void) {
+}
-#ifdef __cplusplus
- extern "C" {
-#endif
+bool board_requests_safe_mode(void) {
+ return false;
+}
-// Descriptors set used by tinyusb stack
-extern tud_desc_set_t tud_desc_set;
+void reset_board(void) {
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* USB_DESC_H_ */
+}
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
new file mode 100644
index 000000000..1e55cd026
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "Adafruit Circuit Playground Bluefruit"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+#define MICROPY_PY_SYS_PLATFORM "CircuitPlaygroundBluefruit"
+
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (4096)
+
+#define MICROPY_HW_LED_STATUS (&pin_P1_14)
+
+// Unusually, board does not have a 32 kHz xtal. Nearly all boards do.
+#define BOARD_HAS_32KHZ_XTAL (0)
+
+#if QSPI_FLASH_FILESYSTEM
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 21)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 23)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 00)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 22)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 15)
+#endif
+
+#if SPI_FLASH_FILESYSTEM
+#define SPI_FLASH_MOSI_PIN &pin_P0_21
+#define SPI_FLASH_MISO_PIN &pin_P0_23
+#define SPI_FLASH_SCK_PIN &pin_P0_19
+#define SPI_FLASH_CS_PIN &pin_P0_15
+#endif
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_04)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_05)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_05)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P1_03)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_29)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_30)
+#define DEFAULT_UART_BUS_TX (&pin_P0_14)
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
new file mode 100644
index 000000000..dbb32629c
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk
@@ -0,0 +1,26 @@
+USB_VID = 0x239A
+USB_PID = 0x8046
+USB_PRODUCT = "Circuit Playground Bluefruit"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+MCU_CHIP = nrf52840
+SD ?= s140
+SOFTDEV_VERSION ?= 6.1.0
+
+BOOT_SETTING_ADDR = 0xFF000
+
+ifeq ($(SD),)
+ LD_FILE = boards/nrf52840_1M_256k.ld
+else
+ LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld
+ CIRCUITPY_BLEIO = 1
+endif
+
+NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/pins.c b/ports/nrf/boards/circuitplayground_bluefruit/pins.c
new file mode 100644
index 000000000..e8e5f4110
--- /dev/null
+++ b/ports/nrf/boards/circuitplayground_bluefruit/pins.c
@@ -0,0 +1,71 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_P0_26) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_02) },
+
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_29) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_03) },
+
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_04) },
+
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_05) },
+
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_30) },
+
+ // This cannot be A7, as it is on CPX. We don't have enough analog inputs.
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_P0_28) },
+
+ { MP_ROM_QSTR(MP_QSTR_TEMPERATURE), MP_ROM_PTR(&pin_P0_31) },
+ { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_P1_02) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P1_02) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_P1_15) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_SLIDE_SWITCH), MP_ROM_PTR(&pin_P1_06) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P1_06) },
+
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_14) },
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_P0_17) },
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_P0_16) },
+
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_P1_13) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SDA), MP_ROM_PTR(&pin_P1_10) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SCL), MP_ROM_PTR(&pin_P1_12) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_P1_04) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h
index e1f43e3c9..70ccffc3f 100644
--- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h
+++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Feather52840Express"
diff --git a/ports/nrf/boards/make-pins.py b/ports/nrf/boards/make-pins.py
deleted file mode 100644
index d1cfd5b70..000000000
--- a/ports/nrf/boards/make-pins.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/env python
-"""Creates the pin file for the nRF5."""
-
-from __future__ import print_function
-
-import argparse
-import sys
-import csv
-
-
-def parse_port_pin(name_str):
- """Parses a string and returns a (port-num, pin-num) tuple."""
- if len(name_str) < 4:
- raise ValueError("Expecting pin name to be at least 5 charcters.")
- if name_str[0] != 'P':
- raise ValueError("Expecting pin name to start with P")
- if name_str[1] not in ('0', '1'):
- raise ValueError("Expecting pin port to be in 0 or 1")
- port = ord(name_str[1]) - ord('0')
- pin_str = name_str[3:]
- if not pin_str.isdigit():
- raise ValueError("Expecting numeric pin number.")
- return (port, int(pin_str))
-
-
-class Pin(object):
- """Holds the information associated with a pin."""
-
- def __init__(self, port, pin):
- self.port = port
- self.pin = pin
- self.adc_channel = '0'
- self.board_pin = False
-
- def cpu_pin_name(self):
- return 'P{:d}_{:02d}'.format(self.port, self.pin)
-
- def is_board_pin(self):
- return self.board_pin
-
- def set_is_board_pin(self):
- self.board_pin = True
-
- def parse_adc(self, adc_str):
- if (adc_str[:3] != 'AIN'):
- return
- self.adc_channel = 'SAADC_CH_PSELP_PSELP_AnalogInput%d' % int(adc_str[3])
-
- def print(self):
- print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s});'.format(
- self.cpu_pin_name(), self.cpu_pin_name(),
- self.port, self.pin, self.adc_channel))
-
- def print_header(self, hdr_file):
- hdr_file.write('extern const pin_obj_t pin_{:s};\n'.
- format(self.cpu_pin_name()))
-
-
-class NamedPin(object):
-
- def __init__(self, name, pin):
- self._name = name
- self._pin = pin
-
- def pin(self):
- return self._pin
-
- def name(self):
- return self._name
-
-
-class Pins(object):
-
- def __init__(self):
- self.cpu_pins = [] # list of NamedPin objects
- self.board_pins = [] # list of NamedPin objects
-
- def find_pin(self, port_num, pin_num):
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.port == port_num and pin.pin == pin_num:
- return pin
-
- def parse_af_file(self, filename):
- with open(filename, 'r') as csvfile:
- rows = csv.reader(csvfile)
- for row in rows:
- try:
- (port_num, pin_num) = parse_port_pin(row[0])
- except:
- continue
- pin = Pin(port_num, pin_num)
- if len(row) > 1:
- pin.parse_adc(row[1])
- self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin))
-
- def parse_board_file(self, filename):
- with open(filename, 'r') as csvfile:
- rows = csv.reader(csvfile)
- for row in rows:
- try:
- (port_num, pin_num) = parse_port_pin(row[1])
- except:
- continue
- pin = self.find_pin(port_num, pin_num)
- if pin:
- pin.set_is_board_pin()
- self.board_pins.append(NamedPin(row[0], pin))
-
- def print_named(self, label, named_pins):
- print('')
- print('STATIC const mp_rom_map_elem_t {:s}_table[] = {{'.format(label))
- for named_pin in named_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},'.format(named_pin.name(), pin.cpu_pin_name()))
- print('};')
- print('MP_DEFINE_CONST_DICT({:s}, {:s}_table);'.format(label, label))
-
- def print(self):
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- pin.print()
- self.print_named('mcu_pin_globals', self.cpu_pins)
- self.print_named('board_module_globals', self.board_pins)
-
- def print_header(self, hdr_filename):
- with open(hdr_filename, 'wt') as hdr_file:
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- pin.print_header(hdr_file)
-
- def print_qstr(self, qstr_filename):
- with open(qstr_filename, 'wt') as qstr_file:
- qstr_set = set([])
- for named_pin in self.cpu_pins:
- pin = named_pin.pin()
- if pin.is_board_pin():
- qstr_set |= set([named_pin.name()])
- for named_pin in self.board_pins:
- qstr_set |= set([named_pin.name()])
- for qstr in sorted(qstr_set):
- print('Q({})'.format(qstr), file=qstr_file)
-
-
-def main():
- parser = argparse.ArgumentParser(
- prog="make-pins.py",
- usage="%(prog)s [options] [command]",
- description="Generate board specific pin file"
- )
- parser.add_argument(
- "-a", "--af",
- dest="af_filename",
- help="Specifies the alternate function file for the chip",
- default="nrf_af.csv"
- )
- parser.add_argument(
- "-b", "--board",
- dest="board_filename",
- help="Specifies the board file",
- )
- parser.add_argument(
- "-p", "--prefix",
- dest="prefix_filename",
- help="Specifies beginning portion of generated pins file",
- default="nrf52_prefix.c"
- )
- parser.add_argument(
- "-q", "--qstr",
- dest="qstr_filename",
- help="Specifies name of generated qstr header file",
- default="build/pins_qstr.h"
- )
- parser.add_argument(
- "-r", "--hdr",
- dest="hdr_filename",
- help="Specifies name of generated pin header file",
- default="build/pins.h"
- )
- args = parser.parse_args(sys.argv[1:])
-
- pins = Pins()
-
- print('// This file was automatically generated by make-pins.py')
- print('//')
- if args.af_filename:
- print('// --af {:s}'.format(args.af_filename))
- pins.parse_af_file(args.af_filename)
-
- if args.board_filename:
- print('// --board {:s}'.format(args.board_filename))
- pins.parse_board_file(args.board_filename)
-
- if args.prefix_filename:
- print('// --prefix {:s}'.format(args.prefix_filename))
- print('')
- with open(args.prefix_filename, 'r') as prefix_file:
- print(prefix_file.read())
- pins.print()
- pins.print_header(args.hdr_filename)
- pins.print_qstr(args.qstr_filename)
-
-
-if __name__ == "__main__":
- main()
diff --git a/ports/nrf/boards/metro_nrf52840_express/board.c b/ports/nrf/boards/metro_nrf52840_express/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h
new file mode 100644
index 000000000..520eef90d
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "Adafruit Metro nRF52840 Express"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+#define MICROPY_PY_SYS_PLATFORM "Metro52840Express"
+
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (4096)
+
+#define MICROPY_HW_NEOPIXEL (&pin_P0_13)
+
+#define MICROPY_HW_LED_STATUS (&pin_P1_13)
+
+#if QSPI_FLASH_FILESYSTEM
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 23)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20)
+#endif
+
+#if SPI_FLASH_FILESYSTEM
+#define SPI_FLASH_MOSI_PIN &pin_P0_17
+#define SPI_FLASH_MISO_PIN &pin_P0_23
+#define SPI_FLASH_SCK_PIN &pin_P0_19
+#define SPI_FLASH_CS_PIN &pin_P0_20
+#endif
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_16)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_15)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_07)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P1_08)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_11)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_24)
+#define DEFAULT_UART_BUS_TX (&pin_P0_25)
diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
new file mode 100644
index 000000000..4c1c93c10
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.mk
@@ -0,0 +1,26 @@
+USB_VID = 0x239A
+USB_PID = 0x8040
+USB_PRODUCT = "Metro nRF52840 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+MCU_CHIP = nrf52840
+SD ?= s140
+SOFTDEV_VERSION ?= 6.1.0
+
+BOOT_SETTING_ADDR = 0xFF000
+
+ifeq ($(SD),)
+ LD_FILE = boards/nrf52840_1M_256k.ld
+else
+ LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld
+ CIRCUITPY_BLEIO = 1
+endif
+
+NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/metro_nrf52840_express/pins.c b/ports/nrf/boards/metro_nrf52840_express/pins.c
new file mode 100644
index 000000000..452e31202
--- /dev/null
+++ b/ports/nrf/boards/metro_nrf52840_express/pins.c
@@ -0,0 +1,56 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) },
+
+ { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P1_02) },
+
+ { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_24) },
+
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_25) },
+
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P1_10) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P1_04) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P1_11) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_12) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P1_14) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P1_09) },
+ { MP_ROM_QSTR(MP_QSTR_D13),MP_ROM_PTR(&pin_P0_14) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_16) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_P0_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P1_08) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_11) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_13) },
+ { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P1_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P1_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/particle_argon/mpconfigboard.h b/ports/nrf/boards/particle_argon/mpconfigboard.h
index 0ee785c31..a4ecb2bb4 100644
--- a/ports/nrf/boards/particle_argon/mpconfigboard.h
+++ b/ports/nrf/boards/particle_argon/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Particle Argon"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Particle Argon"
diff --git a/ports/nrf/boards/particle_boron/mpconfigboard.h b/ports/nrf/boards/particle_boron/mpconfigboard.h
index b814fc694..5e817311f 100644
--- a/ports/nrf/boards/particle_boron/mpconfigboard.h
+++ b/ports/nrf/boards/particle_boron/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Particle Boron"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Particle Boron"
diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h
index c8da66736..6c8cc7cef 100644
--- a/ports/nrf/boards/particle_xenon/mpconfigboard.h
+++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h
@@ -27,8 +27,6 @@
#include "nrfx/hal/nrf_gpio.h"
-#define FEATHER52840
-
#define MICROPY_HW_BOARD_NAME "Particle Xenon"
#define MICROPY_HW_MCU_NAME "nRF52840"
#define MICROPY_PY_SYS_PLATFORM "Particle Xenon"
diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c
index 9d0912930..a8e1f1905 100644
--- a/ports/nrf/common-hal/bleio/Adapter.c
+++ b/ports/nrf/common-hal/_bleio/Adapter.c
@@ -34,10 +34,16 @@
#include "nrfx_power.h"
#include "nrf_nvic.h"
#include "nrf_sdm.h"
+#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-
#include "supervisor/usb.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Address.h"
+
+#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
+#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
+#define BLE_SLAVE_LATENCY 0
+#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) {
mp_raise_msg_varg(&mp_type_AssertionError,
@@ -46,17 +52,28 @@ STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) {
STATIC uint32_t ble_stack_enable(void) {
nrf_clock_lf_cfg_t clock_config = {
- .source = NRF_CLOCK_LF_SRC_XTAL,
- .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM
+#if BOARD_HAS_32KHZ_XTAL
+ .source = NRF_CLOCK_LF_SRC_XTAL,
+ .rc_ctiv = 0,
+ .rc_temp_ctiv = 0,
+ .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM,
+#else
+ .source = NRF_CLOCK_LF_SRC_RC,
+ .rc_ctiv = 16,
+ .rc_temp_ctiv = 2,
+ .accuracy = NRF_CLOCK_LF_ACCURACY_250_PPM,
+#endif
};
uint32_t err_code = sd_softdevice_enable(&clock_config, softdevice_assert_handler);
- if (err_code != NRF_SUCCESS)
+ if (err_code != NRF_SUCCESS) {
return err_code;
+ }
err_code = sd_nvic_EnableIRQ(SD_EVT_IRQn);
- if (err_code != NRF_SUCCESS)
+ if (err_code != NRF_SUCCESS) {
return err_code;
+ }
// Start with no event handlers, etc.
ble_drv_reset();
@@ -87,8 +104,22 @@ STATIC uint32_t ble_stack_enable(void) {
return err_code;
err_code = sd_ble_enable(&app_ram_start);
+ if (err_code != NRF_SUCCESS)
+ return err_code;
- return err_code;
+ ble_gap_conn_params_t gap_conn_params = {
+ .min_conn_interval = BLE_MIN_CONN_INTERVAL,
+ .max_conn_interval = BLE_MAX_CONN_INTERVAL,
+ .slave_latency = BLE_SLAVE_LATENCY,
+ .conn_sup_timeout = BLE_CONN_SUP_TIMEOUT,
+ };
+ err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
+ if (err_code != NRF_SUCCESS) {
+ return err_code;
+ }
+
+ err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN);
+ return err_code;
}
void common_hal_bleio_adapter_set_enabled(bool enabled) {
@@ -132,20 +163,42 @@ bool common_hal_bleio_adapter_get_enabled(void) {
return is_enabled;
}
-void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) {
- ble_gap_addr_t local_address;
+void get_address(ble_gap_addr_t *address) {
uint32_t err_code;
common_hal_bleio_adapter_set_enabled(true);
- err_code = sd_ble_gap_addr_get(&local_address);
+ err_code = sd_ble_gap_addr_get(address);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg(translate("Failed to get local address"));
}
+}
+
+bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) {
+ common_hal_bleio_adapter_set_enabled(true);
+
+ ble_gap_addr_t local_address;
+ get_address(&local_address);
+
+ bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
+ address->base.type = &bleio_address_type;
+
+ common_hal_bleio_address_construct(address, local_address.addr, local_address.addr_type);
+ return address;
+}
+
+mp_obj_t common_hal_bleio_adapter_get_default_name(void) {
+ common_hal_bleio_adapter_set_enabled(true);
+
+ ble_gap_addr_t local_address;
+ get_address(&local_address);
+
+ char name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 };
- address->type = local_address.addr_type;
+ name[sizeof(name) - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf];
+ name[sizeof(name) - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf];
+ name[sizeof(name) - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf];
+ name[sizeof(name) - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf];
- mp_buffer_info_t buf_info;
- mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
- memcpy(address->bytes, buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
+ return mp_obj_new_str(name, sizeof(name));
}
diff --git a/ports/nrf/common-hal/bleio/Adapter.h b/ports/nrf/common-hal/_bleio/Adapter.h
index 5dcc62540..5dcc62540 100644
--- a/ports/nrf/common-hal/bleio/Adapter.h
+++ b/ports/nrf/common-hal/_bleio/Adapter.h
diff --git a/ports/nrf/common-hal/_bleio/Attribute.c b/ports/nrf/common-hal/_bleio/Attribute.c
new file mode 100644
index 000000000..c55914b10
--- /dev/null
+++ b/ports/nrf/common-hal/_bleio/Attribute.c
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/_bleio/Attribute.h"
+
+// Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting.
+void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) {
+ switch (security_mode) {
+ case SECURITY_MODE_NO_ACCESS:
+ BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm);
+ break;
+
+ case SECURITY_MODE_OPEN:
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm);
+ break;
+
+ case SECURITY_MODE_ENC_NO_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm);
+ break;
+
+ case SECURITY_MODE_ENC_WITH_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm);
+ break;
+
+ case SECURITY_MODE_LESC_ENC_WITH_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm);
+ break;
+
+ case SECURITY_MODE_SIGNED_NO_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm);
+ break;
+
+ case SECURITY_MODE_SIGNED_WITH_MITM:
+ BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm);
+ break;
+ }
+}
diff --git a/ports/nrf/common-hal/_bleio/Attribute.h b/ports/nrf/common-hal/_bleio/Attribute.h
new file mode 100644
index 000000000..8cc361046
--- /dev/null
+++ b/ports/nrf/common-hal/_bleio/Attribute.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H
+
+#include "shared-module/_bleio/Attribute.h"
+
+extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode);
+
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H
diff --git a/ports/nrf/common-hal/_bleio/Central.c b/ports/nrf/common-hal/_bleio/Central.c
new file mode 100644
index 000000000..db67b763c
--- /dev/null
+++ b/ports/nrf/common-hal/_bleio/Central.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "ble.h"
+#include "ble_drv.h"
+#include "ble_hci.h"
+#include "nrf_soc.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Central.h"
+
+STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
+ bleio_central_obj_t *central = (bleio_central_obj_t*)central_in;
+
+ switch (ble_evt->header.evt_id) {
+ case BLE_GAP_EVT_CONNECTED:
+ central->conn_handle = ble_evt->evt.gap_evt.conn_handle;
+ central->waiting_to_connect = false;
+ break;
+
+ case BLE_GAP_EVT_TIMEOUT:
+ // Handle will be invalid.
+ central->waiting_to_connect = false;
+ break;
+
+ case BLE_GAP_EVT_DISCONNECTED:
+ central->conn_handle = BLE_CONN_HANDLE_INVALID;
+ break;
+
+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+ sd_ble_gap_sec_params_reply(central->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
+ break;
+
+ case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
+ ble_gap_evt_conn_param_update_request_t *request =
+ &ble_evt->evt.gap_evt.params.conn_param_update_request;
+ sd_ble_gap_conn_param_update(central->conn_handle, &request->conn_params);
+ break;
+ }
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
+ }
+}
+
+void common_hal_bleio_central_construct(bleio_central_obj_t *self) {
+ common_hal_bleio_adapter_set_enabled(true);
+
+ self->remote_service_list = mp_obj_new_list(0, NULL);
+ self->conn_handle = BLE_CONN_HANDLE_INVALID;
+}
+
+void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) {
+ common_hal_bleio_adapter_set_enabled(true);
+ ble_drv_add_event_handler(central_on_ble_evt, self);
+
+ ble_gap_addr_t addr;
+
+ addr.addr_type = address->type;
+ mp_buffer_info_t address_buf_info;
+ mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ);
+ memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
+
+ ble_gap_scan_params_t scan_params = {
+ .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS),
+ .window = MSEC_TO_UNITS(100, UNIT_0_625_MS),
+ .scan_phys = BLE_GAP_PHY_1MBPS,
+ // timeout of 0 means no timeout
+ .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS),
+ };
+
+ ble_gap_conn_params_t conn_params = {
+ .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS),
+ .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS),
+ .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS),
+ .slave_latency = 0, // number of conn events
+ };
+
+ self->waiting_to_connect = true;
+
+ uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code);
+ }
+
+ while (self->waiting_to_connect) {
+ RUN_BACKGROUND_TASKS;
+ }
+
+ if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
+ mp_raise_OSError_msg(translate("Failed to connect: timeout"));
+ }
+}
+
+void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) {
+ sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+}
+
+bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) {
+ return self->conn_handle != BLE_CONN_HANDLE_INVALID;
+}
+
+mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist) {
+ common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist);
+ // Convert to a tuple and then clear the list so the callee will take ownership.
+ mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_service_list->len,
+ self->remote_service_list->items);
+ mp_obj_list_clear(self->remote_service_list);
+ return services_tuple;
+}
+
+mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) {
+ return self->remote_service_list;
+}
diff --git a/ports/nrf/common-hal/bleio/Central.h b/ports/nrf/common-hal/_bleio/Central.h
index ac1670088..01f7faca7 100644
--- a/ports/nrf/common-hal/bleio/Central.h
+++ b/ports/nrf/common-hal/_bleio/Central.h
@@ -31,15 +31,14 @@
#include <stdbool.h>
#include "py/objlist.h"
-#include "shared-module/bleio/__init__.h"
-#include "shared-module/bleio/Address.h"
+#include "shared-module/_bleio/Address.h"
typedef struct {
mp_obj_base_t base;
- gatt_role_t gatt_role;
volatile bool waiting_to_connect;
volatile uint16_t conn_handle;
- mp_obj_list_t *service_list;
+ // Services discovered after connecting to a remote peripheral.
+ mp_obj_list_t *remote_service_list;
} bleio_central_obj_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H
diff --git a/ports/nrf/common-hal/_bleio/Characteristic.c b/ports/nrf/common-hal/_bleio/Characteristic.c
new file mode 100644
index 000000000..e8454d528
--- /dev/null
+++ b/ports/nrf/common-hal/_bleio/Characteristic.c
@@ -0,0 +1,299 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+
+#include "shared-bindings/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-bindings/_bleio/Service.h"
+
+static volatile bleio_characteristic_obj_t *m_read_characteristic;
+
+STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) {
+ uint16_t cccd;
+ ble_gatts_value_t value = {
+ .p_value = (uint8_t*) &cccd,
+ .len = 2,
+ };
+
+ const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value);
+
+ if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
+ // CCCD is not set, so say that neither Notify nor Indicate is enabled.
+ cccd = 0;
+ } else if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to read CCCD value, err 0x%04x"), err_code);
+ }
+
+ return cccd;
+}
+
+STATIC void characteristic_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
+ switch (ble_evt->header.evt_id) {
+
+ // More events may be handled later, so keep this as a switch.
+
+ case BLE_GATTC_EVT_READ_RSP: {
+ ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
+ if (m_read_characteristic) {
+ m_read_characteristic->value = mp_obj_new_bytearray(response->len, response->data);
+ }
+ // Indicate to busy-wait loop that we've read the attribute value.
+ m_read_characteristic = NULL;
+ break;
+ }
+
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
+ }
+}
+
+STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
+ uint16_t hvx_len = bufinfo->len;
+
+ ble_gatts_hvx_params_t hvx_params = {
+ .handle = handle,
+ .type = hvx_type,
+ .offset = 0,
+ .p_len = &hvx_len,
+ .p_data = bufinfo->buf,
+ };
+
+ while (1) {
+ const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
+ }
+ // TX buffer is full
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ if (err_code == NRF_ERROR_RESOURCES) {
+ RUN_BACKGROUND_TASKS;
+ continue;
+ }
+
+ // Some real error has occurred.
+ mp_raise_OSError_msg_varg(translate("Failed to notify or indicate attribute value, err 0x%04x"), err_code);
+ }
+}
+
+STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic) {
+ const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
+ common_hal_bleio_check_connected(conn_handle);
+
+ // Set to NULL in event loop after event.
+ m_read_characteristic = characteristic;
+
+ ble_drv_add_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic);
+
+ const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
+ }
+
+ while (m_read_characteristic != NULL) {
+ RUN_BACKGROUND_TASKS;
+ }
+
+ ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic);
+}
+
+void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
+ self->service = service;
+ self->uuid = uuid;
+ self->handle = BLE_GATT_HANDLE_INVALID;
+ self->props = props;
+ self->read_perm = read_perm;
+ self->write_perm = write_perm;
+ self->descriptor_list = mp_obj_new_list(0, NULL);
+
+ const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
+ if (max_length < 0 || max_length > max_length_max) {
+ mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
+ max_length_max, fixed_length ? "True" : "False");
+ }
+ self->max_length = max_length;
+ self->fixed_length = fixed_length;
+
+ common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo);
+}
+
+mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) {
+ return self->descriptor_list;
+}
+
+bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) {
+ return self->service;
+}
+
+mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
+ // Do GATT operations only if this characteristic has been added to a registered service.
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+ if (common_hal_bleio_service_get_is_remote(self->service)) {
+ // self->value is set by evt handler.
+ characteristic_gattc_read(self);
+ } else {
+ self->value = common_hal_bleio_gatts_read(self->handle, conn_handle);
+ }
+ }
+
+ return self->value;
+}
+
+void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
+ if (self->fixed_length && bufinfo->len != self->max_length) {
+ mp_raise_ValueError(translate("Value length != required fixed length"));
+ }
+ if (bufinfo->len > self->max_length) {
+ mp_raise_ValueError(translate("Value length > max_length"));
+ }
+
+ self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
+
+ // Do GATT operations only if this characteristic has been added to a registered service.
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+
+ if (common_hal_bleio_service_get_is_remote(self->service)) {
+ // Last argument is true if write-no-reponse desired.
+ common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo,
+ (self->props & CHAR_PROP_WRITE_NO_RESPONSE));
+ } else {
+
+ bool sent = false;
+ uint16_t cccd = 0;
+
+ const bool notify = self->props & CHAR_PROP_NOTIFY;
+ const bool indicate = self->props & CHAR_PROP_INDICATE;
+ if (notify | indicate) {
+ cccd = characteristic_get_cccd(self->cccd_handle, conn_handle);
+ }
+
+ // It's possible that both notify and indicate are set.
+ if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
+ characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION);
+ sent = true;
+ }
+ if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
+ characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION);
+ sent = true;
+ }
+
+ if (!sent) {
+ common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo);
+ }
+ }
+ }
+}
+
+bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) {
+ return self->uuid;
+}
+
+bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) {
+ return self->props;
+}
+
+void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
+ ble_uuid_t desc_uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid);
+
+ ble_gatts_attr_md_t desc_attr_md = {
+ // Data passed is not in a permanent location and should be copied.
+ .vloc = BLE_GATTS_VLOC_STACK,
+ .vlen = !descriptor->fixed_length,
+ };
+
+ bleio_attribute_gatts_set_security_mode(&desc_attr_md.read_perm, descriptor->read_perm);
+ bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm);
+
+ mp_buffer_info_t desc_value_bufinfo;
+ mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
+
+ ble_gatts_attr_t desc_attr = {
+ .p_uuid = &desc_uuid,
+ .p_attr_md = &desc_attr_md,
+ .init_len = desc_value_bufinfo.len,
+ .p_value = desc_value_bufinfo.buf,
+ .init_offs = 0,
+ .max_len = descriptor->max_length,
+ };
+
+ uint32_t err_code = sd_ble_gatts_descriptor_add(self->handle, &desc_attr, &descriptor->handle);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to add descriptor, err 0x%04x"), err_code);
+ }
+
+ mp_obj_list_append(self->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
+}
+
+void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
+ if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) {
+ mp_raise_ValueError(translate("No CCCD for this Characteristic"));
+ }
+
+ if (!common_hal_bleio_service_get_is_remote(self->service)) {
+ mp_raise_ValueError(translate("Can't set CCCD on local Characteristic"));
+ }
+
+ const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+ common_hal_bleio_check_connected(conn_handle);
+
+ uint16_t cccd_value =
+ (notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
+ (indicate ? BLE_GATT_HVX_INDICATION : 0);
+
+ ble_gattc_write_params_t write_params = {
+ .write_op = BLE_GATT_OP_WRITE_REQ,
+ .handle = self->cccd_handle,
+ .p_value = (uint8_t *) &cccd_value,
+ .len = 2,
+ };
+
+ while (1) {
+ uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
+ }
+
+ // Write with response will return NRF_ERROR_BUSY if the response has not been received.
+ // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
+ if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ RUN_BACKGROUND_TASKS;
+ continue;
+ }
+
+ // Some real error occurred.
+ mp_raise_OSError_msg_varg(translate("Failed to write CCCD, err 0x%04x"), err_code);
+ }
+
+}
diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/_bleio/Characteristic.h
index 7cb227596..3a7691d07 100644
--- a/ports/nrf/common-hal/bleio/Characteristic.h
+++ b/ports/nrf/common-hal/_bleio/Characteristic.h
@@ -28,17 +28,23 @@
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
-#include "common-hal/bleio/Service.h"
-#include "common-hal/bleio/UUID.h"
-#include "shared-module/bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Attribute.h"
+#include "shared-module/_bleio/Characteristic.h"
+#include "common-hal/_bleio/Service.h"
+#include "common-hal/_bleio/UUID.h"
typedef struct {
mp_obj_base_t base;
+ // Will be MP_OBJ_NULL before being assigned to a Service.
bleio_service_obj_t *service;
bleio_uuid_obj_t *uuid;
- volatile mp_obj_t value_data;
+ mp_obj_t value;
+ uint16_t max_length;
+ bool fixed_length;
uint16_t handle;
bleio_characteristic_properties_t props;
+ bleio_attribute_security_mode_t read_perm;
+ bleio_attribute_security_mode_t write_perm;
mp_obj_list_t *descriptor_list;
uint16_t user_desc_handle;
uint16_t cccd_handle;
diff --git a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c
index 59eaaf02b..95794feec 100644
--- a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
+++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c
@@ -37,8 +37,8 @@
#include "tick.h"
-#include "common-hal/bleio/__init__.h"
-#include "common-hal/bleio/CharacteristicBuffer.h"
+#include "shared-bindings/_bleio/__init__.h"
+#include "common-hal/_bleio/CharacteristicBuffer.h"
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
// Push all the data onto the ring buffer.
@@ -99,7 +99,7 @@ int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
- MICROPY_VM_HOOK_LOOP;
+ RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
return 0;
diff --git a/ports/nrf/common-hal/bleio/CharacteristicBuffer.h b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.h
index db8fd2fad..f0949251c 100644
--- a/ports/nrf/common-hal/bleio/CharacteristicBuffer.h
+++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.h
@@ -30,7 +30,7 @@
#include "nrf_soc.h"
#include "py/ringbuf.h"
-#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Characteristic.h"
typedef struct {
mp_obj_base_t base;
diff --git a/ports/nrf/common-hal/_bleio/Descriptor.c b/ports/nrf/common-hal/_bleio/Descriptor.c
new file mode 100644
index 000000000..137f004ba
--- /dev/null
+++ b/ports/nrf/common-hal/_bleio/Descriptor.c
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+
+#include "shared-bindings/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
+
+static volatile bleio_descriptor_obj_t *m_read_descriptor;
+
+void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
+ self->characteristic = characteristic;
+ self->uuid = uuid;
+ self->handle = BLE_GATT_HANDLE_INVALID;
+ self->read_perm = read_perm;
+ self->write_perm = write_perm;
+
+ const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
+ if (max_length < 0 || max_length > max_length_max) {
+ mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
+ max_length_max, fixed_length ? "True" : "False");
+ }
+ self->max_length = max_length;
+ self->fixed_length = fixed_length;
+
+ common_hal_bleio_descriptor_set_value(self, initial_value_bufinfo);
+}
+
+bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
+ return self->uuid;
+}
+
+bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) {
+ return self->characteristic;
+}
+
+STATIC void descriptor_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
+ switch (ble_evt->header.evt_id) {
+
+ // More events may be handled later, so keep this as a switch.
+
+ case BLE_GATTC_EVT_READ_RSP: {
+ ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
+ if (m_read_descriptor) {
+ m_read_descriptor->value = mp_obj_new_bytearray(response->len, response->data);
+ }
+ // Indicate to busy-wait loop that we've read the attribute value.
+ m_read_descriptor = NULL;
+ break;
+ }
+
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled descriptor event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
+ }
+}
+
+STATIC void descriptor_gattc_read(bleio_descriptor_obj_t *descriptor) {
+ const uint16_t conn_handle =
+ common_hal_bleio_device_get_conn_handle(descriptor->characteristic->service->device);
+ common_hal_bleio_check_connected(conn_handle);
+
+ // Set to NULL in event loop after event.
+ m_read_descriptor = descriptor;
+
+ ble_drv_add_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor);
+
+ const uint32_t err_code = sd_ble_gattc_read(conn_handle, descriptor->handle, 0);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
+ }
+
+ while (m_read_descriptor != NULL) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+
+ ble_drv_remove_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor);
+}
+
+mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self) {
+ // Do GATT operations only if this descriptor has been registered
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
+ descriptor_gattc_read(self);
+ } else {
+ self->value = common_hal_bleio_gatts_read(
+ self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device));
+ }
+ }
+
+ return self->value;
+}
+
+void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) {
+ if (self->fixed_length && bufinfo->len != self->max_length) {
+ mp_raise_ValueError(translate("Value length != required fixed length"));
+ }
+ if (bufinfo->len > self->max_length) {
+ mp_raise_ValueError(translate("Value length > max_length"));
+ }
+
+ self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
+
+ // Do GATT operations only if this descriptor has been registered.
+ if (self->handle != BLE_GATT_HANDLE_INVALID) {
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device);
+ if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
+ // false means WRITE_REQ, not write-no-response
+ common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false);
+ } else {
+ common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo);
+ }
+ }
+
+}
diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/_bleio/Descriptor.h
index b7af6a42f..3adb0df18 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.h
+++ b/ports/nrf/common-hal/_bleio/Descriptor.h
@@ -30,14 +30,21 @@
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
#include "py/obj.h"
-#include "common-hal/bleio/Characteristic.h"
-#include "common-hal/bleio/UUID.h"
+
+#include "common-hal/_bleio/Characteristic.h"
+#include "common-hal/_bleio/UUID.h"
typedef struct {
mp_obj_base_t base;
- uint16_t handle;
+ // Will be MP_OBJ_NULL before being assigned to a Characteristic.
bleio_characteristic_obj_t *characteristic;
bleio_uuid_obj_t *uuid;
+ mp_obj_t value;
+ uint16_t max_length;
+ bool fixed_length;
+ uint16_t handle;
+ bleio_attribute_security_mode_t read_perm;
+ bleio_attribute_security_mode_t write_perm;
} bleio_descriptor_obj_t;
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/_bleio/Peripheral.c
index 608bd1342..9b0f96d48 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.c
+++ b/ports/nrf/common-hal/_bleio/Peripheral.c
@@ -36,22 +36,31 @@
#include "py/objlist.h"
#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Peripheral.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
-#include "common-hal/bleio/Service.h"
-
-#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
-#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS)
-#define BLE_SLAVE_LATENCY 0
-#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
+#include "shared-bindings/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Attribute.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Peripheral.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
#define BLE_ADV_LENGTH_FIELD_SIZE 1
#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
+static const ble_gap_sec_params_t pairing_sec_params = {
+ .bond = 1,
+ .mitm = 0,
+ .lesc = 0,
+ .keypress = 0,
+ .oob = 0,
+ .io_caps = BLE_GAP_IO_CAPS_NONE,
+ .min_key_size = 7,
+ .max_key_size = 16,
+ .kdist_own = { .enc = 1, .id = 1},
+ .kdist_peer = { .enc = 1, .id = 1},
+};
+
STATIC void check_data_fit(size_t data_len) {
if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
mp_raise_ValueError(translate("Data too large for advertisement packet"));
@@ -61,13 +70,24 @@ STATIC void check_data_fit(size_t data_len) {
STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in;
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Peripheral event: 0x%04x\n", ble_evt->header.evt_id);
+
switch (ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED: {
// Central has connected.
- ble_gap_conn_params_t conn_params;
+ ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected;
+
self->conn_handle = ble_evt->evt.gap_evt.conn_handle;
+
+ // See if connection interval set by Central is out of range.
+ // If so, negotiate our preferred range.
+ ble_gap_conn_params_t conn_params;
sd_ble_gap_ppcp_get(&conn_params);
- sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params);
+ if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval ||
+ conn_params.min_conn_interval > connected->conn_params.max_conn_interval) {
+ sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params);
+ }
break;
}
@@ -86,25 +106,16 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
}
case BLE_GAP_EVT_ADV_SET_TERMINATED:
- // Someday may handle timeouts or limit reached.
- break;
-
- case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
- sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
- break;
-
- case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
- ble_gap_evt_conn_param_update_request_t *request =
- &ble_evt->evt.gap_evt.params.conn_param_update_request;
- sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params);
+ // TODO: Someday may handle timeouts or limit reached.
break;
- }
case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
+ // SoftDevice will respond to a length update request.
sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL);
break;
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: {
+ // We only handle MTU of size BLE_GATT_ATT_MTU_DEFAULT.
sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT);
break;
}
@@ -113,6 +124,82 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
break;
+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST: {
+ ble_gap_sec_keyset_t keyset = {
+ .keys_own = {
+ .p_enc_key = &self->bonding_keys.own_enc,
+ .p_id_key = NULL,
+ .p_sign_key = NULL,
+ .p_pk = NULL
+ },
+
+ .keys_peer = {
+ .p_enc_key = &self->bonding_keys.peer_enc,
+ .p_id_key = &self->bonding_keys.peer_id,
+ .p_sign_key = NULL,
+ .p_pk = NULL
+ }
+ };
+
+ sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS,
+ &pairing_sec_params, &keyset);
+ break;
+ }
+
+ case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
+ // TODO for LESC pairing:
+ // sd_ble_gap_lesc_dhkey_reply(...);
+ break;
+
+ case BLE_GAP_EVT_AUTH_STATUS: {
+ // Pairing process completed
+ ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status;
+ if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) {
+ // TODO _ediv = bonding_keys->own_enc.master_id.ediv;
+ self->pair_status = PAIR_PAIRED;
+ } else {
+ self->pair_status = PAIR_NOT_PAIRED;
+ }
+ break;
+ }
+
+ case BLE_GAP_EVT_SEC_INFO_REQUEST: {
+ // Peer asks for the stored keys.
+ // - load key and return if bonded previously.
+ // - Else return NULL --> Initiate key exchange
+ ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request;
+ (void) sec_info_request;
+ //if ( bond_load_keys(_role, sec_req->master_id.ediv, &bkeys) ) {
+ //sd_ble_gap_sec_info_reply(_conn_hdl, &bkeys.own_enc.enc_info, &bkeys.peer_id.id_info, NULL);
+ //
+ //_ediv = bkeys.own_enc.master_id.ediv;
+ // } else {
+ sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL);
+ // }
+ break;
+ }
+
+ case BLE_GAP_EVT_CONN_SEC_UPDATE: {
+ ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec;
+ if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) {
+ // Security setup did not succeed:
+ // mode 0, level 0 means no access
+ // mode 1, level 1 means open link
+ // mode >=1 and/or level >=1 means encryption is set up
+ self->pair_status = PAIR_NOT_PAIRED;
+ } else {
+ //if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) {
+ if (true) { // TODO: no bonding yet
+ // Initialize system attributes fresh.
+ sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
+ }
+ // Not quite paired yet: wait for BLE_GAP_EVT_AUTH_STATUS SUCCESS.
+ self->ediv = self->bonding_keys.own_enc.master_id.ediv;
+ }
+ break;
+ }
+
+
default:
// For debugging.
// mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id);
@@ -120,43 +207,39 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
}
}
-void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name) {
+void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name) {
common_hal_bleio_adapter_set_enabled(true);
- self->service_list = service_list;
+ self->service_list = mp_obj_new_list(0, NULL);
+ // Used only for discovery when acting as a client.
+ self->remote_service_list = mp_obj_new_list(0, NULL);
self->name = name;
- self->gatt_role = GATT_ROLE_SERVER;
self->conn_handle = BLE_CONN_HANDLE_INVALID;
self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
+ self->pair_status = PAIR_NOT_PAIRED;
- // Add all the services.
-
- for (size_t service_idx = 0; service_idx < service_list->len; ++service_idx) {
- bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[service_idx]);
-
- service->device = MP_OBJ_FROM_PTR(self);
+ memset(&self->bonding_keys, 0, sizeof(self->bonding_keys));
+}
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
+void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service) {
+ ble_uuid_t uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
- uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
- if (common_hal_bleio_service_get_is_secondary(service)) {
- service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
- }
-
- const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to add service, err 0x%04x"), err_code);
- }
+ uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
+ if (common_hal_bleio_service_get_is_secondary(service)) {
+ service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
+ }
- // Once the service has been registered, its characteristics can be added.
- common_hal_bleio_service_add_all_characteristics(service);
+ const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to add service, err 0x%04x"), err_code);
}
-}
+ mp_obj_list_append(self->service_list, MP_OBJ_FROM_PTR(service));
+}
-mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self) {
+mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) {
return self->service_list;
}
@@ -182,9 +265,9 @@ void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self,
GET_STR_DATA_LEN(self->name, name_data, name_len);
if (name_len > 0) {
+ // Set device name, and make it available to anyone.
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
-
err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Failed to set device name, err 0x%04x"), err_code);
@@ -247,3 +330,32 @@ void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self)
void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) {
sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
}
+
+mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist) {
+ common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist);
+ // Convert to a tuple and then clear the list so the callee will take ownership.
+ mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_service_list->len,
+ self->remote_service_list->items);
+ mp_obj_list_clear(self->remote_service_list);
+ return services_tuple;
+}
+
+void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *self) {
+ self->pair_status = PAIR_WAITING;
+
+ uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to start pairing, error 0x%04x"), err_code);
+ }
+
+ while (self->pair_status == PAIR_WAITING) {
+ RUN_BACKGROUND_TASKS;
+ }
+
+ if (self->pair_status == PAIR_NOT_PAIRED) {
+ mp_raise_OSError_msg(translate("Failed to pair"));
+ }
+
+
+}
diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/_bleio/Peripheral.h
index 2a1251715..a4f62d288 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.h
+++ b/ports/nrf/common-hal/_bleio/Peripheral.h
@@ -35,22 +35,33 @@
#include "py/obj.h"
#include "py/objlist.h"
-#include "shared-module/bleio/__init__.h"
-#include "shared-module/bleio/Address.h"
+#include "common-hal/_bleio/__init__.h"
+#include "shared-module/_bleio/Address.h"
+
+typedef enum {
+ PAIR_NOT_PAIRED,
+ PAIR_WAITING,
+ PAIR_PAIRED,
+} pair_status_t;
typedef struct {
mp_obj_base_t base;
mp_obj_t name;
- gatt_role_t gatt_role;
volatile uint16_t conn_handle;
+ // Services provided by this peripheral.
mp_obj_list_t *service_list;
+ // Remote services discovered when this peripheral is acting as a client.
+ mp_obj_list_t *remote_service_list;
// The advertising data and scan response buffers are held by us, not by the SD, so we must
// maintain them and not change it. If we need to change the contents during advertising,
// there are tricks to get the SD to notice (see DevZone - TBS).
+ // EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing.
+ bonding_keys_t bonding_keys;
+ uint16_t ediv;
uint8_t* advertising_data;
uint8_t* scan_response_data;
uint8_t adv_handle;
-
+ pair_status_t pair_status;
} bleio_peripheral_obj_t;
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H
diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/_bleio/Scanner.c
index 57ce940ab..ec73f7eb8 100644
--- a/ports/nrf/common-hal/bleio/Scanner.c
+++ b/ports/nrf/common-hal/_bleio/Scanner.c
@@ -33,10 +33,10 @@
#include "py/mphal.h"
#include "py/objlist.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/ScanEntry.h"
-#include "shared-bindings/bleio/Scanner.h"
-#include "shared-module/bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Scanner.h"
+#include "shared-module/_bleio/ScanEntry.h"
static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN];
diff --git a/ports/nrf/common-hal/bleio/Scanner.h b/ports/nrf/common-hal/_bleio/Scanner.h
index 3768a52cb..3768a52cb 100644
--- a/ports/nrf/common-hal/bleio/Scanner.h
+++ b/ports/nrf/common-hal/_bleio/Scanner.h
diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c
new file mode 100644
index 000000000..650cdc4ec
--- /dev/null
+++ b/ports/nrf/common-hal/_bleio/Service.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * 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 "ble_drv.h"
+#include "ble.h"
+#include "py/runtime.h"
+#include "common-hal/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-bindings/_bleio/Peripheral.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/Adapter.h"
+
+void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary) {
+ self->device = MP_OBJ_FROM_PTR(peripheral);
+ self->handle = 0xFFFF;
+ self->uuid = uuid;
+ self->characteristic_list = mp_obj_new_list(0, NULL);
+ self->is_remote = false;
+ self->is_secondary = is_secondary;
+}
+
+bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
+ return self->uuid;
+}
+
+mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self) {
+ return self->characteristic_list;
+}
+
+bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
+ return self->is_remote;
+}
+
+bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
+ return self->is_secondary;
+}
+
+void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) {
+ ble_gatts_char_md_t char_md = {
+ .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0,
+ .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0,
+ .char_props.write_wo_resp = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0,
+ .char_props.write = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0,
+ .char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0,
+ .char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0,
+ };
+
+ ble_gatts_attr_md_t cccd_md = {
+ .vloc = BLE_GATTS_VLOC_STACK,
+ };
+
+ ble_uuid_t char_uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid);
+
+ ble_gatts_attr_md_t char_attr_md = {
+ .vloc = BLE_GATTS_VLOC_STACK,
+ .vlen = !characteristic->fixed_length,
+ };
+
+ if (char_md.char_props.notify || char_md.char_props.indicate) {
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
+ // Make CCCD write permission match characteristic read permission.
+ bleio_attribute_gatts_set_security_mode(&cccd_md.write_perm, characteristic->read_perm);
+
+ char_md.p_cccd_md = &cccd_md;
+ }
+
+ bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm);
+ bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm);
+
+ mp_buffer_info_t char_value_bufinfo;
+ mp_get_buffer_raise(characteristic->value, &char_value_bufinfo, MP_BUFFER_READ);
+
+ ble_gatts_attr_t char_attr = {
+ .p_uuid = &char_uuid,
+ .p_attr_md = &char_attr_md,
+ .init_len = char_value_bufinfo.len,
+ .p_value = char_value_bufinfo.buf,
+ .init_offs = 0,
+ .max_len = characteristic->max_length,
+ };
+
+ ble_gatts_char_handles_t char_handles;
+
+ uint32_t err_code;
+ err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code);
+ }
+
+ characteristic->user_desc_handle = char_handles.user_desc_handle;
+ characteristic->cccd_handle = char_handles.cccd_handle;
+ characteristic->sccd_handle = char_handles.sccd_handle;
+ characteristic->handle = char_handles.value_handle;
+
+ mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
+}
diff --git a/ports/nrf/common-hal/bleio/Service.h b/ports/nrf/common-hal/_bleio/Service.h
index 583593fb8..a4614b9f5 100644
--- a/ports/nrf/common-hal/bleio/Service.h
+++ b/ports/nrf/common-hal/_bleio/Service.h
@@ -29,12 +29,14 @@
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H
#include "py/objlist.h"
-#include "common-hal/bleio/UUID.h"
+#include "common-hal/_bleio/UUID.h"
typedef struct {
mp_obj_base_t base;
// Handle for this service.
uint16_t handle;
+ // True if created during discovery.
+ bool is_remote;
bool is_secondary;
bleio_uuid_obj_t *uuid;
// May be a Peripheral, Central, etc.
diff --git a/ports/nrf/common-hal/bleio/UUID.c b/ports/nrf/common-hal/_bleio/UUID.c
index ebd6b6d1f..0e65b7d58 100644
--- a/ports/nrf/common-hal/bleio/UUID.c
+++ b/ports/nrf/common-hal/_bleio/UUID.c
@@ -29,8 +29,8 @@
#include <string.h>
#include "py/runtime.h"
-#include "common-hal/bleio/UUID.h"
-#include "shared-bindings/bleio/Adapter.h"
+#include "common-hal/_bleio/UUID.h"
+#include "shared-bindings/_bleio/Adapter.h"
#include "ble.h"
#include "ble_drv.h"
diff --git a/ports/nrf/common-hal/bleio/UUID.h b/ports/nrf/common-hal/_bleio/UUID.h
index 7d3a6204e..7d3a6204e 100644
--- a/ports/nrf/common-hal/bleio/UUID.h
+++ b/ports/nrf/common-hal/_bleio/UUID.h
diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/_bleio/__init__.c
index d90737411..553044190 100644
--- a/ports/nrf/common-hal/bleio/Central.c
+++ b/ports/nrf/common-hal/_bleio/__init__.c
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,34 +26,72 @@
* THE SOFTWARE.
*/
-#include <string.h>
-#include <stdio.h>
-
-#include "ble.h"
-#include "ble_drv.h"
-#include "ble_hci.h"
-#include "nrf_soc.h"
-#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Central.h"
-#include "shared-bindings/bleio/Descriptor.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
+#include "shared-bindings/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Central.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-bindings/_bleio/Peripheral.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
-static bleio_service_obj_t *m_char_discovery_service;
-static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
+#include "common-hal/_bleio/__init__.h"
static volatile bool m_discovery_in_process;
static volatile bool m_discovery_successful;
+static bleio_service_obj_t *m_char_discovery_service;
+static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
+
+// Turn off BLE on a reset or reload.
+void bleio_reset() {
+ if (common_hal_bleio_adapter_get_enabled()) {
+ common_hal_bleio_adapter_set_enabled(false);
+ }
+}
+
+// The singleton _bleio.Adapter object, bound to _bleio.adapter
+// It currently only has properties and no state
+const super_adapter_obj_t common_hal_bleio_adapter_obj = {
+ .base = {
+ .type = &bleio_adapter_type,
+ },
+};
+
+void common_hal_bleio_check_connected(uint16_t conn_handle) {
+ if (conn_handle == BLE_CONN_HANDLE_INVALID) {
+ mp_raise_OSError_msg(translate("Not connected"));
+ }
+}
+
+uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) {
+ if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
+ return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
+ } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
+ return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
+ } else {
+ return BLE_CONN_HANDLE_INVALID;
+ }
+}
+
+mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device) {
+ if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
+ return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->remote_service_list;
+ } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
+ return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->remote_service_list;
+ } else {
+ return NULL;
+ }
+}
+
// service_uuid may be NULL, to discover all services.
-STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_handle, ble_uuid_t *service_uuid) {
+STATIC bool discover_next_services(mp_obj_t device, uint16_t start_handle, ble_uuid_t *service_uuid) {
m_discovery_successful = false;
m_discovery_in_process = true;
- uint32_t err_code = sd_ble_gattc_primary_services_discover(self->conn_handle, start_handle, service_uuid);
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device);
+ uint32_t err_code = sd_ble_gattc_primary_services_discover(conn_handle, start_handle, service_uuid);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg(translate("Failed to discover services"));
@@ -65,7 +104,7 @@ STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_han
return m_discovery_successful;
}
-STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_service_obj_t *service, uint16_t start_handle) {
+STATIC bool discover_next_characteristics(mp_obj_t device, bleio_service_obj_t *service, uint16_t start_handle) {
m_char_discovery_service = service;
ble_gattc_handle_range_t handle_range;
@@ -75,7 +114,8 @@ STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_servi
m_discovery_successful = false;
m_discovery_in_process = true;
- uint32_t err_code = sd_ble_gattc_characteristics_discover(self->conn_handle, &handle_range);
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device);
+ uint32_t err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range);
if (err_code != NRF_SUCCESS) {
return false;
}
@@ -87,7 +127,7 @@ STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_servi
return m_discovery_successful;
}
-STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) {
+STATIC bool discover_next_descriptors(mp_obj_t device, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) {
m_desc_discovery_characteristic = characteristic;
ble_gattc_handle_range_t handle_range;
@@ -97,7 +137,8 @@ STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_character
m_discovery_successful = false;
m_discovery_in_process = true;
- uint32_t err_code = sd_ble_gattc_descriptors_discover(self->conn_handle, &handle_range);
+ uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device);
+ uint32_t err_code = sd_ble_gattc_descriptors_discover(conn_handle, &handle_range);
if (err_code != NRF_SUCCESS) {
return false;
}
@@ -109,7 +150,7 @@ STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_character
return m_discovery_successful;
}
-STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_central_obj_t *central) {
+STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, mp_obj_t device) {
for (size_t i = 0; i < response->count; ++i) {
ble_gattc_service_t *gattc_service = &response->services[i];
@@ -117,9 +158,9 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res
service->base.type = &bleio_service_type;
// Initialize several fields at once.
- common_hal_bleio_service_construct(service, NULL, mp_obj_new_list(0, NULL), false);
+ common_hal_bleio_service_construct(service, device, NULL, false);
- service->device = MP_OBJ_FROM_PTR(central);
+ service->is_remote = true;
service->start_handle = gattc_service->handle_range.start_handle;
service->end_handle = gattc_service->handle_range.end_handle;
service->handle = gattc_service->handle_range.start_handle;
@@ -130,7 +171,6 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res
uuid->base.type = &bleio_uuid_type;
bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
service->uuid = uuid;
- service->device = MP_OBJ_FROM_PTR(central);
} else {
// The discovery response contained a 128-bit UUID that has not yet been registered with the
// softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
@@ -138,7 +178,7 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res
service->uuid = NULL;
}
- mp_obj_list_append(central->service_list, service);
+ mp_obj_list_append(common_hal_bleio_device_get_remote_service_list(device), service);
}
if (response->count > 0) {
@@ -147,15 +187,13 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res
m_discovery_in_process = false;
}
-STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_central_obj_t *central) {
+STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_obj_t device) {
for (size_t i = 0; i < response->count; ++i) {
ble_gattc_char_t *gattc_char = &response->chars[i];
bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
characteristic->base.type = &bleio_characteristic_type;
- characteristic->descriptor_list = mp_obj_new_list(0, NULL);
-
bleio_uuid_obj_t *uuid = NULL;
if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
@@ -169,19 +207,20 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio
// For now, just leave the UUID as NULL.
}
- bleio_characteristic_properties_t props;
-
- props.broadcast = gattc_char->char_props.broadcast;
- props.indicate = gattc_char->char_props.indicate;
- props.notify = gattc_char->char_props.notify;
- props.read = gattc_char->char_props.read;
- props.write = gattc_char->char_props.write;
- props.write_no_response = gattc_char->char_props.write_wo_resp;
+ bleio_characteristic_properties_t props =
+ (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) |
+ (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) |
+ (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) |
+ (gattc_char->char_props.read ? CHAR_PROP_READ : 0) |
+ (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) |
+ (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0);
// Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
- common_hal_bleio_characteristic_construct(characteristic, uuid, props, mp_obj_new_list(0, NULL));
+ common_hal_bleio_characteristic_construct(
+ characteristic, m_char_discovery_service, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
+ GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
+ mp_obj_new_list(0, NULL));
characteristic->handle = gattc_char->handle_value;
- characteristic->service = m_char_discovery_service;
mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
}
@@ -192,21 +231,21 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio
m_discovery_in_process = false;
}
-STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_central_obj_t *central) {
+STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_obj_t device) {
for (size_t i = 0; i < response->count; ++i) {
ble_gattc_desc_t *gattc_desc = &response->descs[i];
// Remember handles for certain well-known descriptors.
switch (gattc_desc->uuid.uuid) {
- case DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION:
+ case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG:
m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle;
break;
- case DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION:
+ case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG:
m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle;
break;
- case DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION:
+ case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC:
m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle;
break;
@@ -233,9 +272,11 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio
// For now, just leave the UUID as NULL.
}
- common_hal_bleio_descriptor_construct(descriptor, uuid);
+ common_hal_bleio_descriptor_construct(
+ descriptor, m_desc_discovery_characteristic, uuid,
+ SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
+ GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
descriptor->handle = gattc_desc->handle;
- descriptor->characteristic = m_desc_discovery_characteristic;
mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
}
@@ -246,131 +287,62 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio
m_discovery_in_process = false;
}
-STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
- bleio_central_obj_t *central = (bleio_central_obj_t*)central_in;
-
+STATIC void discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t device) {
switch (ble_evt->header.evt_id) {
- case BLE_GAP_EVT_CONNECTED:
- central->conn_handle = ble_evt->evt.gap_evt.conn_handle;
- central->waiting_to_connect = false;
- break;
-
- case BLE_GAP_EVT_TIMEOUT:
- // Handle will be invalid.
- central->waiting_to_connect = false;
- break;
-
case BLE_GAP_EVT_DISCONNECTED:
- central->conn_handle = BLE_CONN_HANDLE_INVALID;
m_discovery_successful = false;
m_discovery_in_process = false;
break;
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
- on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, central);
+ on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device);
break;
case BLE_GATTC_EVT_CHAR_DISC_RSP:
- on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, central);
+ on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device);
break;
case BLE_GATTC_EVT_DESC_DISC_RSP:
- on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, central);
- break;
-
- case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
- sd_ble_gap_sec_params_reply(central->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
- break;
-
- case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
- ble_gap_evt_conn_param_update_request_t *request =
- &ble_evt->evt.gap_evt.params.conn_param_update_request;
- sd_ble_gap_conn_param_update(central->conn_handle, &request->conn_params);
+ on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, device);
break;
- }
default:
// For debugging.
- // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
+ // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id);
break;
}
}
-void common_hal_bleio_central_construct(bleio_central_obj_t *self) {
- common_hal_bleio_adapter_set_enabled(true);
-
- self->service_list = mp_obj_new_list(0, NULL);
- self->gatt_role = GATT_ROLE_CLIENT;
- self->conn_handle = BLE_CONN_HANDLE_INVALID;
-}
-
-void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids) {
- common_hal_bleio_adapter_set_enabled(true);
- ble_drv_add_event_handler(central_on_ble_evt, self);
- ble_gap_addr_t addr;
-
- addr.addr_type = address->type;
- mp_buffer_info_t address_buf_info;
- mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ);
- memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
-
- ble_gap_scan_params_t scan_params = {
- .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS),
- .window = MSEC_TO_UNITS(100, UNIT_0_625_MS),
- .scan_phys = BLE_GAP_PHY_1MBPS,
- // timeout of 0 means no timeout
- .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS),
- };
-
- ble_gap_conn_params_t conn_params = {
- .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS),
- .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS),
- .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS),
- .slave_latency = 0, // number of conn events
- };
+void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) {
+ mp_obj_list_t *remote_services_list = common_hal_bleio_device_get_remote_service_list(device);
- self->waiting_to_connect = true;
+ ble_drv_add_event_handler(discovery_on_ble_evt, device);
- uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM);
-
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code);
- }
-
- while (self->waiting_to_connect) {
- MICROPY_VM_HOOK_LOOP;
- }
-
- if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
- mp_raise_OSError_msg(translate("Failed to connect: timeout"));
- }
-
- // Connection successful.
- // Now discover services on the remote peripheral.
-
- if (service_uuids == mp_const_none) {
+ // Start over with an empty list.
+ mp_obj_list_clear(MP_OBJ_FROM_PTR(common_hal_bleio_device_get_remote_service_list(device)));
+ if (service_uuids_whitelist == mp_const_none) {
// List of service UUID's not given, so discover all available services.
uint16_t next_service_start_handle = BLE_GATT_HANDLE_START;
- while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) {
- // discover_next_services() appends to service_list.
+ while (discover_next_services(device, next_service_start_handle, MP_OBJ_NULL)) {
+ // discover_next_services() appends to remote_services_list.
// Get the most recently discovered service, and then ask for services
// whose handles start after the last attribute handle inside that service.
const bleio_service_obj_t *service =
- MP_OBJ_TO_PTR(self->service_list->items[self->service_list->len - 1]);
+ MP_OBJ_TO_PTR(remote_services_list->items[remote_services_list->len - 1]);
next_service_start_handle = service->end_handle + 1;
}
} else {
mp_obj_iter_buf_t iter_buf;
- mp_obj_t iterable = mp_getiter(service_uuids, &iter_buf);
+ mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf);
mp_obj_t uuid_obj;
while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
- mp_raise_ValueError(translate("non-UUID found in service_uuids"));
+ mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist"));
}
bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
@@ -380,13 +352,13 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
// Service might or might not be discovered; that's ok. Caller has to check
// Central.remote_services to find out.
// We only need to call this once for each service to discover.
- discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid);
+ discover_next_services(device, BLE_GATT_HANDLE_START, &nrf_uuid);
}
}
- for (size_t service_idx = 0; service_idx < self->service_list->len; ++service_idx) {
- bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->service_list->items[service_idx]);
+ for (size_t service_idx = 0; service_idx < remote_services_list->len; ++service_idx) {
+ bleio_service_obj_t *service = MP_OBJ_TO_PTR(remote_services_list->items[service_idx]);
// Skip the service if it had an unknown (unregistered) UUID.
if (service->uuid == NULL) {
@@ -399,7 +371,7 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
// discovery call returns nothing.
// discover_next_characteristics() appends to the characteristic_list.
while (next_char_start_handle <= service->end_handle &&
- discover_next_characteristics(self, service, next_char_start_handle)) {
+ discover_next_characteristics(device, service, next_char_start_handle)) {
// Get the most recently discovered characteristic, and then ask for characteristics
@@ -436,7 +408,7 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
// discover_next_descriptors() appends to the descriptor_list.
while (next_desc_start_handle <= service->end_handle &&
next_desc_start_handle < next_desc_end_handle &&
- discover_next_descriptors(self, characteristic,
+ discover_next_descriptors(device, characteristic,
next_desc_start_handle, next_desc_end_handle)) {
// Get the most recently discovered descriptor, and then ask for descriptors
@@ -446,18 +418,85 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
next_desc_start_handle = descriptor->handle + 1;
}
}
-
}
+
+ // This event handler is no longer needed.
+ ble_drv_remove_event_handler(discovery_on_ble_evt, device);
+
}
-void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) {
- sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+// GATTS read of a Characteristic or Descriptor.
+mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle) {
+ // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
+ // we can still read and write the local value.
+
+ mp_buffer_info_t bufinfo;
+ ble_gatts_value_t gatts_value = {
+ .p_value = NULL,
+ .len = 0,
+ };
+
+ // Read once to find out what size buffer we need, then read again to fill buffer.
+
+ mp_obj_t value = mp_const_none;
+ uint32_t err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value);
+ if (err_code == NRF_SUCCESS) {
+ value = mp_obj_new_bytearray_of_zeros(gatts_value.len);
+ mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_WRITE);
+ gatts_value.p_value = bufinfo.buf;
+
+ // Read again, with the correct size of buffer.
+ err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value);
+ }
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code);
+ }
+
+ return value;
}
-bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) {
- return self->conn_handle != BLE_CONN_HANDLE_INVALID;
+void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) {
+ // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
+ // we can still read and write the local value.
+
+ ble_gatts_value_t gatts_value = {
+ .p_value = bufinfo->buf,
+ .len = bufinfo->len,
+ };
+
+ const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, handle, &gatts_value);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code);
+ }
}
-mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) {
- return self->service_list;
+void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) {
+ common_hal_bleio_check_connected(conn_handle);
+
+ ble_gattc_write_params_t write_params = {
+ .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ,
+ .handle = handle,
+ .p_value = bufinfo->buf,
+ .len = bufinfo->len,
+ };
+
+ while (1) {
+ uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
+ }
+
+ // Write with response will return NRF_ERROR_BUSY if the response has not been received.
+ // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
+ if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ MICROPY_VM_HOOK_LOOP;
+ continue;
+ }
+
+ // Some real error occurred.
+ mp_raise_OSError_msg_varg(translate("Failed to write attribute value, err 0x%04x"), err_code);
+ }
+
}
diff --git a/ports/nrf/common-hal/bleio/__init__.h b/ports/nrf/common-hal/_bleio/__init__.h
index 0c46b631f..cf1a06945 100644
--- a/ports/nrf/common-hal/bleio/__init__.h
+++ b/ports/nrf/common-hal/_bleio/__init__.h
@@ -27,16 +27,16 @@
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
-#include "shared-bindings/bleio/__init__.h"
-#include "shared-bindings/bleio/Adapter.h"
+void bleio_reset(void);
-#include "shared-module/bleio/__init__.h"
+typedef struct {
+ ble_gap_enc_key_t own_enc;
+ ble_gap_enc_key_t peer_enc;
+ ble_gap_id_key_t peer_id;
+} bonding_keys_t;
// We assume variable length data.
// 20 bytes max (23 - 3).
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
-gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device);
-uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
-
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
diff --git a/ports/nrf/common-hal/analogio/AnalogIn.c b/ports/nrf/common-hal/analogio/AnalogIn.c
index f20802ac9..7cf6a6423 100644
--- a/ports/nrf/common-hal/analogio/AnalogIn.c
+++ b/ports/nrf/common-hal/analogio/AnalogIn.c
@@ -67,8 +67,8 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
const nrf_saadc_channel_config_t config = {
.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
.resistor_n = NRF_SAADC_RESISTOR_DISABLED,
- .gain = NRF_SAADC_GAIN1_6,
- .reference = NRF_SAADC_REFERENCE_INTERNAL,
+ .gain = NRF_SAADC_GAIN1_4,
+ .reference = NRF_SAADC_REFERENCE_VDD4,
.acq_time = NRF_SAADC_ACQTIME_3US,
.mode = NRF_SAADC_MODE_SINGLE_ENDED,
.burst = NRF_SAADC_BURST_DISABLED,
@@ -108,5 +108,6 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
}
float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) {
+ // The nominal VCC voltage
return 3.3f;
}
diff --git a/ports/nrf/common-hal/audiobusio/I2SOut.c b/ports/nrf/common-hal/audiobusio/I2SOut.c
new file mode 100644
index 000000000..ac369277f
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/I2SOut.c
@@ -0,0 +1,328 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/audiobusio/I2SOut.h"
+#include "shared-bindings/audiobusio/I2SOut.h"
+#include "shared-module/audiocore/__init__.h"
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+static audiobusio_i2sout_obj_t *instance;
+
+struct { int16_t l, r; } static_sample16 = {0x8000, 0x8000};
+struct { uint8_t l1, r1, l2, r2; } static_sample8 = {0x80, 0x80, 0x80, 0x80};
+
+struct frequency_info { uint32_t RATIO; uint32_t MCKFREQ; int sample_rate; float abserr; };
+struct ratio_info { uint32_t RATIO; int16_t divisor; bool can_16bit; };
+struct ratio_info ratios[] = {
+ { I2S_CONFIG_RATIO_RATIO_32X, 32, true },
+ { I2S_CONFIG_RATIO_RATIO_48X, 48, false },
+ { I2S_CONFIG_RATIO_RATIO_64X, 64, true },
+ { I2S_CONFIG_RATIO_RATIO_96X, 96, true },
+ { I2S_CONFIG_RATIO_RATIO_128X, 128, true },
+ { I2S_CONFIG_RATIO_RATIO_192X, 192, true },
+ { I2S_CONFIG_RATIO_RATIO_256X, 256, true },
+ { I2S_CONFIG_RATIO_RATIO_384X, 384, true },
+ { I2S_CONFIG_RATIO_RATIO_512X, 512, true },
+};
+
+struct mclk_info { uint32_t MCKFREQ; int divisor; };
+struct mclk_info mclks[] = {
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV8, 8 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV10, 10 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV11, 11 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV15, 15 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16, 16 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV21, 21 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV23, 23 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV31, 31 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV42, 42 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV63, 63 },
+ { I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV125, 125 },
+};
+
+static void calculate_ratio_info(uint32_t target_sample_rate, struct frequency_info *info,
+ int ratio_index, int mclk_index) {
+ info->RATIO = ratios[ratio_index].RATIO;
+ info->MCKFREQ = mclks[mclk_index].MCKFREQ;
+ info->sample_rate = 32000000
+ / ratios[ratio_index].divisor / mclks[mclk_index].divisor;
+ info->abserr = fabsf(1.0f * target_sample_rate - info->sample_rate)
+ / target_sample_rate;
+}
+
+void choose_i2s_clocking(audiobusio_i2sout_obj_t *self, uint32_t sample_rate) {
+ struct frequency_info best = {0, 0, 0, 1.0};
+ for (size_t ri=0; ri<sizeof(ratios) / sizeof(ratios[0]); ri++) {
+ if (NRF_I2S->CONFIG.SWIDTH == I2S_CONFIG_SWIDTH_SWIDTH_16Bit
+ && !ratios[ri].can_16bit) {
+ continue;
+ }
+
+ for (size_t mi=0; mi<sizeof(mclks) / sizeof(mclks[0]); mi++) {
+ struct frequency_info info = {0, 0, 1.0};
+ calculate_ratio_info(sample_rate, &info, ri, mi);
+ if (info.abserr < best.abserr) {
+ best = info;
+ }
+#ifdef DEBUG_CLOCKING
+ mp_printf(&mp_plat_print,
+ "RATIO=%3d MCKFREQ=%08x rate=%d abserr=%.4f\n",
+ info.RATIO, info.MCKFREQ, info.sample_rate,
+ (double)info.abserr);
+#endif
+ }
+ }
+ NRF_I2S->CONFIG.RATIO = best.RATIO;
+ NRF_I2S->CONFIG.MCKFREQ = best.MCKFREQ;
+ self->sample_rate = best.sample_rate;
+}
+
+static void i2s_buffer_fill(audiobusio_i2sout_obj_t* self) {
+ void *buffer = self->buffers[self->next_buffer];
+ NRF_I2S->TXD.PTR = (uintptr_t)buffer;
+ self->next_buffer = !self->next_buffer;
+ size_t bytesleft = self->buffer_length;
+
+ while (!self->paused && !self->stopping && bytesleft) {
+ if (self->sample_data == self->sample_end) {
+ uint32_t sample_buffer_length;
+ audioio_get_buffer_result_t get_buffer_result =
+ audiosample_get_buffer(self->sample, false, 0,
+ &self->sample_data, &sample_buffer_length);
+ self->sample_end = self->sample_data + sample_buffer_length;
+ if (get_buffer_result == GET_BUFFER_DONE) {
+ if (self->loop) {
+ audiosample_reset_buffer(self->sample, false, 0);
+ } else {
+ self->stopping = true;
+ break;
+ }
+ }
+ if (get_buffer_result == GET_BUFFER_ERROR || sample_buffer_length == 0) {
+ self->stopping = true;
+ break;
+ }
+ }
+ uint16_t bytecount = MIN(bytesleft, (size_t)(self->sample_end - self->sample_data));
+ if (self->samples_signed) {
+ memcpy(buffer, self->sample_data, bytecount);
+ } else if (self->bytes_per_sample == 2) {
+ uint16_t *bp = (uint16_t*)buffer;
+ uint16_t *be = (uint16_t*)(buffer + bytecount);
+ uint16_t *sp = (uint16_t*)self->sample_data;
+ for (; bp != be; bp++) {
+ *bp++ = *sp++ + 0x8000;
+ }
+ } else {
+ uint8_t *bp = (uint8_t*)buffer;
+ uint8_t *be = (uint8_t*)(buffer + bytecount);
+ uint8_t *sp = (uint8_t*)self->sample_data;
+ for (; bp != be; bp++) {
+ *bp++ = *sp++ + 0x80;
+ }
+ }
+ buffer += bytecount;
+ self->sample_data += bytecount;
+ bytesleft -= bytecount;
+ }
+
+ // Find the last frame of real audio data and replicate its samples until
+ // you have 32 bits worth, which is the fundamental unit of nRF I2S DMA
+ if (self->bytes_per_sample == 1 && self->channel_count == 1) {
+ // For 8-bit mono, 4 copies of the final sample are required
+ self->hold_value = 0x01010101 * *(uint8_t*)(buffer-1);
+ } else if (self->bytes_per_sample == 2 && self->channel_count == 2) {
+ // For 16-bit stereo, 1 copy of the final sample is required
+ self->hold_value = *(uint32_t*)(buffer-4);
+ } else {
+ // For 8-bit stereo and 16-bit mono, 2 copies of the final sample are required
+ self->hold_value = 0x00010001 * *(uint16_t*)(buffer-2);
+ }
+
+ // Emulate pausing and stopping by filling the DMA buffer with copies of
+ // the last sample. This includes the case where this iteration of
+ // i2s_buffer_fill exhausted a non-looping sample.
+ if (self->paused || self->stopping) {
+ if (self->stopping) {
+ NRF_I2S->TASKS_STOP = 1;
+ self->playing = false;
+ }
+ uint32_t *bp = (uint32_t*)buffer;
+ uint32_t *be = (uint32_t*)(buffer + bytesleft);
+ for (; bp != be; )
+ *bp++ = self->hold_value;
+ return;
+ }
+}
+
+void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t* self,
+ const mcu_pin_obj_t* bit_clock, const mcu_pin_obj_t* word_select,
+ const mcu_pin_obj_t* data, bool left_justified) {
+ if (instance)
+ mp_raise_RuntimeError(translate("Device in use"));
+ instance = self;
+
+ claim_pin(bit_clock);
+ claim_pin(word_select);
+ claim_pin(data);
+
+ NRF_I2S->PSEL.SCK = self->bit_clock_pin_number = bit_clock->number;
+ NRF_I2S->PSEL.LRCK = self->word_select_pin_number = word_select->number;
+ NRF_I2S->PSEL.SDOUT = self->data_pin_number = data->number;
+
+ NRF_I2S->CONFIG.MODE = I2S_CONFIG_MODE_MODE_Master;
+ NRF_I2S->CONFIG.RXEN = I2S_CONFIG_RXEN_RXEN_Disabled;
+ NRF_I2S->CONFIG.TXEN = I2S_CONFIG_TXEN_TXEN_Enabled;
+ NRF_I2S->CONFIG.MCKEN = I2S_CONFIG_MCKEN_MCKEN_Enabled;
+ NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16Bit;
+
+ NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_Left;
+ NRF_I2S->CONFIG.FORMAT = left_justified ? I2S_CONFIG_FORMAT_FORMAT_Aligned
+ : I2S_CONFIG_FORMAT_FORMAT_I2S;
+}
+
+bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t* self) {
+ return self->data_pin_number == 0xff;
+}
+
+void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t* self) {
+ if (common_hal_audiobusio_i2sout_deinited(self)) {
+ return;
+ }
+ reset_pin_number(self->bit_clock_pin_number);
+ self->bit_clock_pin_number = 0xff;
+ reset_pin_number(self->word_select_pin_number);
+ self->word_select_pin_number = 0xff;
+ reset_pin_number(self->data_pin_number);
+ self->data_pin_number = 0xff;
+ instance = NULL;
+}
+
+void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self,
+ mp_obj_t sample, bool loop) {
+ if (common_hal_audiobusio_i2sout_get_playing(self)) {
+ common_hal_audiobusio_i2sout_stop(self);
+ }
+
+ self->sample = sample;
+ self->loop = loop;
+ uint32_t sample_rate = audiosample_sample_rate(sample);
+ self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
+
+ uint32_t max_buffer_length;
+ bool single_buffer, samples_signed;
+ audiosample_get_buffer_structure(sample, /* single channel */ false,
+ &single_buffer, &samples_signed, &max_buffer_length,
+ &self->channel_count);
+ self->single_buffer = single_buffer;
+ self->samples_signed = samples_signed;
+
+ choose_i2s_clocking(self, sample_rate);
+ /* Allocate buffers based on a maximum duration
+ * This duration was chosen empirically based on what would
+ * cause os.listdir('') to cause stuttering. It seems like a
+ * rather long time.
+ */
+ enum { buffer_length_ms = 16 };
+ self->buffer_length = sample_rate * buffer_length_ms
+ * self->bytes_per_sample * self->channel_count / 1000;
+ self->buffer_length = (self->buffer_length + 3) & ~3;
+ self->buffers[0] = m_malloc(self->buffer_length, false);
+ self->buffers[1] = m_malloc(self->buffer_length, false);
+
+
+ audiosample_reset_buffer(self->sample, false, 0);
+
+ self->next_buffer = 0;
+ self->sample_data = self->sample_end = 0;
+ self->playing = true;
+ self->paused = false;
+ self->stopping = false;
+ i2s_buffer_fill(self);
+
+ NRF_I2S->CONFIG.CHANNELS = self->channel_count == 1 ? I2S_CONFIG_CHANNELS_CHANNELS_Left : I2S_CONFIG_CHANNELS_CHANNELS_Stereo;
+
+
+ NRF_I2S->RXTXD.MAXCNT = self->buffer_length / 4;
+ NRF_I2S->ENABLE = I2S_ENABLE_ENABLE_Enabled;
+
+ NRF_I2S->TASKS_START = 1;
+
+ i2s_background();
+}
+
+void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t* self) {
+ self->paused = true;
+}
+
+void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t* self) {
+ self->paused = false;
+}
+
+bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t* self) {
+ return self->paused;
+}
+
+void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t* self) {
+ NRF_I2S->TASKS_STOP = 1;
+ self->stopping = true;
+}
+
+bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) {
+ if (NRF_I2S->EVENTS_STOPPED) {
+ self->playing = false;
+ NRF_I2S->EVENTS_STOPPED = 0;
+ }
+ return self->playing;
+}
+
+void i2s_background(void) {
+ if (NRF_I2S->EVENTS_TXPTRUPD) {
+ NRF_I2S->EVENTS_TXPTRUPD = 0;
+ if (instance) {
+ i2s_buffer_fill(instance);
+ } else {
+ NRF_I2S->TASKS_STOP = 1;
+ }
+ }
+}
+
+void i2s_reset(void) {
+ NRF_I2S->TASKS_STOP = 1;
+ NRF_I2S->ENABLE = I2S_ENABLE_ENABLE_Disabled;
+ NRF_I2S->PSEL.MCK = 0xFFFFFFFF;
+ NRF_I2S->PSEL.SCK = 0xFFFFFFFF;
+ NRF_I2S->PSEL.LRCK = 0xFFFFFFFF;
+ NRF_I2S->PSEL.SDOUT = 0xFFFFFFFF;
+ NRF_I2S->PSEL.SDIN = 0xFFFFFFFF;
+ instance = NULL;
+}
diff --git a/ports/nrf/common-hal/audiobusio/I2SOut.h b/ports/nrf/common-hal/audiobusio/I2SOut.h
new file mode 100644
index 000000000..16047e0ab
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/I2SOut.h
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+
+ mp_obj_t *sample;
+ uint8_t *buffers[2];
+ uint8_t *sample_data, *sample_end;
+
+ uint16_t buffer_length;
+ uint16_t sample_rate;
+ uint32_t hold_value;
+
+ uint8_t next_buffer;
+ uint8_t bit_clock_pin_number;
+ uint8_t word_select_pin_number;
+ uint8_t data_pin_number;
+
+ uint8_t channel_count;
+ uint8_t bytes_per_sample;
+
+ bool left_justified : 1;
+ bool playing : 1;
+ bool stopping : 1;
+ bool paused : 1;
+ bool loop : 1;
+ bool samples_signed : 1;
+ bool single_buffer : 1;
+} audiobusio_i2sout_obj_t;
+
+void i2s_reset(void);
+void i2s_background(void);
+
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
diff --git a/ports/nrf/common-hal/audiobusio/PDMIn.c b/ports/nrf/common-hal/audiobusio/PDMIn.c
new file mode 100644
index 000000000..a7f9c9d74
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/PDMIn.c
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/audiobusio/PDMIn.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+#include "py/runtime.h"
+
+__attribute__((used))
+NRF_PDM_Type *nrf_pdm = NRF_PDM;
+
+static uint32_t dummy_buffer[4];
+
+void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
+ const mcu_pin_obj_t* clock_pin,
+ const mcu_pin_obj_t* data_pin,
+ uint32_t sample_rate,
+ uint8_t bit_depth,
+ bool mono,
+ uint8_t oversample) {
+ assert_pin_free(clock_pin);
+ assert_pin_free(data_pin);
+ claim_pin(clock_pin);
+ claim_pin(data_pin);
+
+ self->mono = mono;
+ self->clock_pin_number = clock_pin->number;
+ self->data_pin_number = data_pin->number;
+
+ if (sample_rate != 16000) {
+ mp_raise_ValueError(translate("only sample_rate=16000 is supported"));
+ }
+ if (bit_depth != 16) {
+ mp_raise_ValueError(translate("only bit_depth=16 is supported"));
+ }
+ nrf_pdm->PSEL.CLK = self->clock_pin_number;
+ nrf_pdm->PSEL.DIN = self->data_pin_number;
+ nrf_pdm->PDMCLKCTRL = PDM_PDMCLKCTRL_FREQ_Default; // For Ratio64
+ nrf_pdm->RATIO = PDM_RATIO_RATIO_Ratio64;
+ nrf_pdm->GAINL = PDM_GAINL_GAINL_DefaultGain;
+ nrf_pdm->GAINR = PDM_GAINR_GAINR_DefaultGain;
+ nrf_pdm->ENABLE = 1;
+
+ nrf_pdm->SAMPLE.PTR = (uintptr_t)&dummy_buffer;
+ nrf_pdm->SAMPLE.MAXCNT = 1;
+ nrf_pdm->TASKS_START = 1;
+}
+
+bool common_hal_audiobusio_pdmin_deinited(audiobusio_pdmin_obj_t* self) {
+ return !self->clock_pin_number;
+}
+
+void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) {
+ nrf_pdm->ENABLE = 0;
+
+ reset_pin_number(self->clock_pin_number);
+ self->clock_pin_number = 0;
+ reset_pin_number(self->data_pin_number);
+ self->data_pin_number = 0;
+}
+
+uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t* self) {
+ return 16;
+}
+
+uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t* self) {
+ return 16000;
+}
+
+uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self,
+ uint16_t* output_buffer, uint32_t output_buffer_length) {
+ // Note: Adafruit's module has SELECT pulled to GND, which makes the DATA
+ // valid when the CLK is low, therefore it must be sampled on the rising edge.
+ if (self->mono) {
+ nrf_pdm->MODE = PDM_MODE_OPERATION_Stereo | PDM_MODE_EDGE_LeftRising;
+ } else {
+ nrf_pdm->MODE = PDM_MODE_OPERATION_Mono | PDM_MODE_EDGE_LeftRising;
+ }
+
+ // step 1. Redirect to real buffer
+ nrf_pdm->SAMPLE.PTR = (uintptr_t)output_buffer;
+ nrf_pdm->SAMPLE.MAXCNT = output_buffer_length;
+
+ // a delay is the safest simple way to ensure that the above requested sample has started
+ mp_hal_delay_us(200);
+ nrf_pdm->EVENTS_END = 0;
+
+ // step 2. Registers are double buffered, so pre-redirect back to dummy buffer
+ nrf_pdm->SAMPLE.PTR = (uintptr_t)&dummy_buffer;
+ nrf_pdm->SAMPLE.MAXCNT = 1;
+
+ // Step 3. wait for PDM to end
+ while (!nrf_pdm->EVENTS_END) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+
+ // Step 4. They want unsigned
+ for (uint32_t i=0; i<output_buffer_length; i++) {
+ output_buffer[i] += 32768;
+ }
+
+ if (self->mono) {
+ return (output_buffer_length / 2) * 2;
+ } else {
+ return (output_buffer_length / 4) * 4;
+ }
+}
diff --git a/ports/nrf/common-hal/audiobusio/PDMIn.h b/ports/nrf/common-hal/audiobusio/PDMIn.h
new file mode 100644
index 000000000..d921e42ff
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/PDMIn.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_AUDIOOUT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOBUSIO_AUDIOOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t clock_pin_number, data_pin_number;
+ bool mono;
+} audiobusio_pdmin_obj_t;
+
+#endif
diff --git a/ports/nrf/common-hal/audiobusio/__init__.c b/ports/nrf/common-hal/audiobusio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/nrf/common-hal/audiobusio/__init__.c
diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
new file mode 100644
index 000000000..0321b751c
--- /dev/null
+++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
@@ -0,0 +1,316 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "extmod/vfs_fat.h"
+#include "py/gc.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#include "common-hal/pulseio/PWMOut.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "supervisor/shared/translate.h"
+
+// TODO: This should be the same size as PWMOut.c:pwms[], but there's no trivial way to accomplish that
+STATIC audiopwmio_pwmaudioout_obj_t* active_audio[4];
+
+#define F_TARGET (62500)
+#define F_PWM (16000000)
+// return the REFRESH value, store the TOP value in an out-parameter
+// Tested for key values (worst relative error = 0.224% = 3.84 cents)
+// 8000: top = 250 refresh = 7 [ 8000.0]
+// 22050: top = 242 refresh = 2 [22038.5]
+// 24000: top = 222 refresh = 2 [24024.0]
+// 44100: top = 181 refresh = 1 [44198.8]
+// 48000: top = 167 refresh = 1 [47904.1]
+STATIC uint32_t calculate_pwm_parameters(uint32_t sample_rate, uint32_t *top_out) {
+ // the desired frequency is the closest integer multiple of sample_rate not less than F_TARGET
+ uint32_t desired_frequency = (F_TARGET + sample_rate - 1) / sample_rate * sample_rate;
+ // The top value is the PWM frequency divided by the desired frequency (round to nearest)
+ uint32_t top = (F_PWM + desired_frequency/2) / desired_frequency;
+ // The actual frequency is the PWM frequency divided by the top value (round to nearest)
+ uint32_t actual_frequency = (F_PWM + top/2) / top;
+ // The multiplier is the actual frequency divided by the sample rate (round to nearest)
+ uint32_t multiplier = (actual_frequency + sample_rate/2) / sample_rate;
+ *top_out = top;
+ return multiplier - 1;
+}
+
+STATIC void activate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
+ if(!active_audio[i]) {
+ active_audio[i] = self;
+ break;
+ }
+ }
+}
+STATIC void deactivate_audiopwmout_obj(audiopwmio_pwmaudioout_obj_t *self) {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
+ if(active_audio[i] == self)
+ active_audio[i] = NULL;
+ }
+}
+
+void audiopwmout_reset() {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++)
+ active_audio[i] = NULL;
+}
+
+STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) {
+ self->pwm->EVENTS_SEQSTARTED[1-buf] = 0;
+ uint16_t *dev_buffer = self->buffers[buf];
+ uint8_t *buffer;
+ uint32_t buffer_length;
+ audioio_get_buffer_result_t get_buffer_result =
+ audiosample_get_buffer(self->sample, false, 0,
+ &buffer, &buffer_length);
+ if (get_buffer_result == GET_BUFFER_ERROR) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ return;
+ }
+ uint32_t num_samples = buffer_length / self->bytes_per_sample / self->spacing;
+
+ if(self->bytes_per_sample == 1) {
+ uint8_t offset = self->signed_to_unsigned ? 0x80 : 0;
+ uint16_t scale = self->scale;
+ for(uint32_t i=0; i<buffer_length/self->spacing; i++) {
+ uint8_t rawval = (*buffer++ + offset);
+ uint16_t val = (uint16_t)(((uint32_t)rawval * (uint32_t)scale) >> 8);
+ *dev_buffer++ = val;
+ if(self->spacing == 1)
+ *dev_buffer++ = val;
+ }
+ } else {
+ uint16_t offset = self->signed_to_unsigned ? 0x8000 : 0;
+ uint16_t scale = self->scale;
+ uint16_t *buffer16 = (uint16_t*)buffer;
+ for(uint32_t i=0; i<buffer_length/2/self->spacing; i++) {
+ uint16_t rawval = (*buffer16++ + offset);
+ uint16_t val = (uint16_t)((rawval * (uint32_t)scale) >> 16);
+ *dev_buffer++ = val;
+ if(self->spacing == 1)
+ *dev_buffer++ = val;
+ }
+ }
+ self->pwm->SEQ[buf].PTR = (intptr_t)self->buffers[buf];
+ self->pwm->SEQ[buf].CNT = num_samples*2;
+
+ if (self->loop && get_buffer_result == GET_BUFFER_DONE) {
+ audiosample_reset_buffer(self->sample, false, 0);
+ } else if(get_buffer_result == GET_BUFFER_DONE) {
+ self->pwm->SHORTS = NRF_PWM_SHORT_SEQEND0_STOP_MASK | NRF_PWM_SHORT_SEQEND1_STOP_MASK;
+ self->stopping = true;
+ }
+}
+
+STATIC void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) {
+ if(!common_hal_audiopwmio_pwmaudioout_get_playing(self))
+ return;
+ if(self->stopping) {
+ bool stopped =
+ (self->pwm->EVENTS_SEQEND[0] || !self->pwm->EVENTS_SEQSTARTED[0]) &&
+ (self->pwm->EVENTS_SEQEND[1] || !self->pwm->EVENTS_SEQSTARTED[1]);
+ if(stopped)
+ self->pwm->TASKS_STOP = 1;
+ } else if(!self->paused && !self->single_buffer) {
+ if(self->pwm->EVENTS_SEQSTARTED[0]) fill_buffers(self, 1);
+ if(self->pwm->EVENTS_SEQSTARTED[1]) fill_buffers(self, 0);
+ }
+}
+
+void audiopwmout_background() {
+ for(size_t i=0; i < MP_ARRAY_SIZE(active_audio); i++) {
+ if(!active_audio[i]) continue;
+ audiopwmout_background_obj(active_audio[i]);
+ }
+}
+
+void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t quiescent_value) {
+ assert_pin_free(left_channel);
+ assert_pin_free(right_channel);
+ self->pwm = pwmout_allocate(256, PWM_PRESCALER_PRESCALER_DIV_1, true, NULL, NULL);
+ if(!self->pwm) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+
+ self->pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1;
+ // two uint16_t values per sample when Grouped
+ // n.b. SEQ[#].CNT "counts" are 2 per sample (left and right channels)
+ self->pwm->DECODER = PWM_DECODER_LOAD_Grouped;
+
+ // we use channels 0 and 2 because these are GROUPED; it lets us save half
+ // the space for sample data (no additional optimization is possible for
+ // single channel)
+ self->pwm->PSEL.OUT[0] = self->left_channel_number = left_channel->number;
+ claim_pin(left_channel);
+
+ if(right_channel)
+ {
+ self->pwm->PSEL.OUT[2] = self->right_channel_number = right_channel->number;
+ claim_pin(right_channel);
+ }
+
+ self->quiescent_value = quiescent_value >> 8;
+
+ self->pwm->ENABLE = 1;
+ // TODO: Ramp from 0 to quiescent value
+}
+
+bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self) {
+ return !self->pwm;
+}
+
+void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self) {
+ if (common_hal_audiopwmio_pwmaudioout_deinited(self)) {
+ return;
+ }
+ // TODO: ramp the pwm down from quiescent value to 0
+ self->pwm->ENABLE = 0;
+
+ if(self->left_channel_number)
+ reset_pin_number(self->left_channel_number);
+ if(self->right_channel_number)
+ reset_pin_number(self->right_channel_number);
+
+ pwmout_free_channel(self->pwm, 0);
+ pwmout_free_channel(self->pwm, 2);
+
+ self->pwm = NULL;
+
+ m_free(self->buffers[0]);
+ self->buffers[0] = NULL;
+
+ m_free(self->buffers[1]);
+ self->buffers[1] = NULL;
+}
+
+void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop) {
+ if (common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ }
+ self->sample = sample;
+ self->loop = loop;
+
+ uint32_t sample_rate = audiosample_sample_rate(sample);
+ uint32_t max_sample_rate = 62500;
+ if (sample_rate > max_sample_rate) {
+ mp_raise_ValueError_varg(translate("Sample rate too high. It must be less than %d"), max_sample_rate);
+ }
+ self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
+
+ uint32_t max_buffer_length;
+ audiosample_get_buffer_structure(sample, /* single channel */ false,
+ &self->single_buffer, &self->signed_to_unsigned, &max_buffer_length,
+ &self->spacing);
+ if(max_buffer_length > UINT16_MAX) {
+ mp_raise_ValueError_varg(translate("Buffer length %d too big. It must be less than %d"), max_buffer_length, UINT16_MAX);
+ }
+ self->buffer_length = (uint16_t)max_buffer_length;
+ self->buffers[0] = m_malloc(self->buffer_length * 2 * sizeof(uint16_t), false);
+ if(!self->single_buffer)
+ self->buffers[1] = m_malloc(self->buffer_length * 2 * sizeof(uint16_t), false);
+
+
+ uint32_t top;
+ self->pwm->SEQ[0].REFRESH = self->pwm->SEQ[1].REFRESH = calculate_pwm_parameters(sample_rate, &top);
+ self->scale = top-1;
+ self->pwm->COUNTERTOP = top;
+
+ self->pwm->LOOP = 1;
+ audiosample_reset_buffer(self->sample, false, 0);
+ activate_audiopwmout_obj(self);
+ fill_buffers(self, 0);
+ self->pwm->SEQ[1].PTR = self->pwm->SEQ[0].PTR;
+ self->pwm->SEQ[1].CNT = self->pwm->SEQ[0].CNT;
+ self->pwm->EVENTS_SEQSTARTED[0] = 0;
+ self->pwm->EVENTS_SEQSTARTED[1] = 0;
+ self->pwm->EVENTS_STOPPED = 0;
+ self->pwm->SHORTS = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+ self->pwm->TASKS_SEQSTART[0] = 1;
+ self->playing = true;
+ self->stopping = false;
+ self->paused = false;
+}
+
+void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self) {
+ deactivate_audiopwmout_obj(self);
+ self->pwm->TASKS_STOP = 1;
+ self->stopping = false;
+ self->paused = false;
+
+ m_free(self->buffers[0]);
+ self->buffers[0] = NULL;
+
+ m_free(self->buffers[1]);
+ self->buffers[1] = NULL;
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self) {
+ if(!self->paused && self->pwm->EVENTS_STOPPED) {
+ self->playing = false;
+ self->pwm->EVENTS_STOPPED = 0;
+ }
+ return self->playing;
+}
+
+/* pause/resume present difficulties for the NRF PWM audio module.
+ *
+ * A PWM sequence can be stopped in its tracks by sending a TASKS_STOP event,
+ * but there's no way to pick up the sequence where it was stopped; you could
+ * start at the start of one of the two sequences, but especially for "single buffer"
+ * sample, this seems undesirable.
+ *
+ * Or, you can stop at the end of a sequence so that you don't duplicate anything
+ * when restarting, but again this is unsatisfactory for a "single buffer" sample.
+ *
+ * For now, I've taken the coward's way and left these methods unimplemented.
+ * Perhaps the way forward is to divide even "single buffer" samples into tasks of
+ * only a few ms long, so that they can be stopped/restarted quickly enough that it
+ * feels instant. (This also saves on memory, for long in-memory "single buffer"
+ * samples, since we have to locally take a resampled copy!)
+ */
+void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self) {
+ self->paused = true;
+ self->pwm->SHORTS = NRF_PWM_SHORT_SEQEND1_STOP_MASK;
+}
+
+void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self) {
+ self->paused = false;
+ self->pwm->SHORTS = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;
+ if (self->pwm->EVENTS_STOPPED) {
+ self->pwm->EVENTS_STOPPED = 0;
+ self->pwm->TASKS_SEQSTART[0] = 1;
+ }
+}
+
+bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self) {
+ return self->paused;
+}
diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
new file mode 100644
index 000000000..8deff5d34
--- /dev/null
+++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jeff Epler for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOPWM_AUDIOOUT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_AUDIOPWM_AUDIOOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t *sample;
+ NRF_PWM_Type *pwm;
+ uint16_t *buffers[2];
+
+ uint16_t buffer_length;
+ uint16_t quiescent_value;
+ uint16_t scale;
+
+ uint8_t left_channel_number;
+ uint8_t right_channel_number;
+ uint8_t spacing;
+ uint8_t bytes_per_sample;
+
+ bool playing;
+ bool stopping;
+ bool paused;
+ bool loop;
+ bool signed_to_unsigned;
+ bool single_buffer;
+} audiopwmio_pwmaudioout_obj_t;
+
+void audiopwmout_reset(void);
+
+void audiopwmout_background(void);
+
+#endif
diff --git a/ports/nrf/common-hal/audiopwmio/__init__.c b/ports/nrf/common-hal/audiopwmio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/nrf/common-hal/audiopwmio/__init__.c
diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c
deleted file mode 100644
index 17417a5e6..000000000
--- a/ports/nrf/common-hal/bleio/Characteristic.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <string.h>
-#include <stdio.h>
-
-#include "ble_drv.h"
-#include "ble_gatts.h"
-#include "nrf_soc.h"
-
-#include "py/runtime.h"
-#include "common-hal/bleio/__init__.h"
-#include "common-hal/bleio/Characteristic.h"
-
-STATIC volatile bleio_characteristic_obj_t *m_read_characteristic;
-
-STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- uint16_t cccd;
- ble_gatts_value_t value = {
- .p_value = (uint8_t*) &cccd,
- .len = 2,
- };
-
- const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->cccd_handle, &value);
-
-
- if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
- // CCCD is not set, so say that neither Notify nor Indicate is enabled.
- cccd = 0;
- } else if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to read CCCD value, err 0x%04x"), err_code);
- }
-
- return cccd;
-}
-
-STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) {
- // This might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
- // we can still read and write the local value.
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
-
- mp_buffer_info_t bufinfo;
- ble_gatts_value_t gatts_value = {
- .p_value = NULL,
- .len = 0,
- };
-
- // Read once to find out what size buffer we need, then read again to fill buffer.
-
- uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
- if (err_code == NRF_SUCCESS) {
- characteristic->value_data = mp_obj_new_bytearray_of_zeros(gatts_value.len);
- mp_get_buffer_raise(characteristic->value_data, &bufinfo, MP_BUFFER_WRITE);
- gatts_value.p_value = bufinfo.buf;
-
- // Read again, with the correct size of buffer.
- err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
- }
-
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code);
- }
-}
-
-
-STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
- // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
- // we can still read and write the local value.
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
-
- ble_gatts_value_t gatts_value = {
- .p_value = bufinfo->buf,
- .len = bufinfo->len,
- };
-
- const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code);
- }
-}
-
-STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
- uint16_t hvx_len = bufinfo->len;
-
- ble_gatts_hvx_params_t hvx_params = {
- .handle = characteristic->handle,
- .type = hvx_type,
- .offset = 0,
- .p_len = &hvx_len,
- .p_data = bufinfo->buf,
- };
-
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
-
- while (1) {
- const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
- if (err_code == NRF_SUCCESS) {
- break;
- }
- // TX buffer is full
- // We could wait for an event indicating the write is complete, but just retrying is easier.
- if (err_code == NRF_ERROR_RESOURCES) {
- MICROPY_VM_HOOK_LOOP;
- continue;
- }
-
- // Some real error has occurred.
- mp_raise_OSError_msg_varg(translate("Failed to notify or indicate attribute value, err 0x%04x"), err_code);
- }
-
-}
-
-STATIC void check_connected(uint16_t conn_handle) {
- if (conn_handle == BLE_CONN_HANDLE_INVALID) {
- mp_raise_OSError_msg(translate("Not connected"));
- }
-}
-
-STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) {
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- check_connected(conn_handle);
-
- m_read_characteristic = characteristic;
-
- const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
- }
-
- while (m_read_characteristic != NULL) {
- MICROPY_VM_HOOK_LOOP;
- }
-}
-
-STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- check_connected(conn_handle);
-
- ble_gattc_write_params_t write_params = {
- .write_op = characteristic->props.write_no_response ? BLE_GATT_OP_WRITE_CMD : BLE_GATT_OP_WRITE_REQ,
- .handle = characteristic->handle,
- .p_value = bufinfo->buf,
- .len = bufinfo->len,
- };
-
- while (1) {
- uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
- if (err_code == NRF_SUCCESS) {
- break;
- }
-
- // Write with response will return NRF_ERROR_BUSY if the response has not been received.
- // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
- if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
- // We could wait for an event indicating the write is complete, but just retrying is easier.
- MICROPY_VM_HOOK_LOOP;
- continue;
- }
-
- // Some real error occurred.
- mp_raise_OSError_msg_varg(translate("Failed to write attribute value, err 0x%04x"), err_code);
- }
-
-}
-
-STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) {
- switch (ble_evt->header.evt_id) {
-
- // More events may be handled later, so keep this as a switch.
-
- case BLE_GATTC_EVT_READ_RSP: {
- ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
- m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data);
- // Indicate to busy-wait loop that we've read the characteristic.
- m_read_characteristic = NULL;
- break;
- }
-
- // For debugging.
- default:
- // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
- break;
- }
-
-}
-
-void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list) {
- self->service = mp_const_none;
- self->uuid = uuid;
- self->value_data = mp_const_none;
- self->props = props;
- self->descriptor_list = descriptor_list;
- self->handle = BLE_GATT_HANDLE_INVALID;
-
- ble_drv_add_event_handler(characteristic_on_ble_evt, self);
-}
-
-mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) {
- return self->descriptor_list;
-}
-
-mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
- switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
- case GATT_ROLE_CLIENT:
- gattc_read(self);
- break;
-
- case GATT_ROLE_SERVER:
- gatts_read(self);
- break;
-
- default:
- mp_raise_RuntimeError(translate("bad GATT role"));
- break;
- }
-
- return self->value_data;
-}
-
-void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
- bool sent = false;
- uint16_t cccd = 0;
-
- switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
- case GATT_ROLE_SERVER:
- if (self->props.notify || self->props.indicate) {
- cccd = get_cccd(self);
- }
- // It's possible that both notify and indicate are set.
- if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
- gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION);
- sent = true;
- }
- if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
- gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION);
- sent = true;
- }
- if (!sent) {
- gatts_write(self, bufinfo);
- }
- break;
-
- case GATT_ROLE_CLIENT:
- gattc_write(self, bufinfo);
- break;
-
- default:
- mp_raise_RuntimeError(translate("bad GATT role"));
- break;
- }
-}
-
-
-bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) {
- return self->uuid;
-}
-
-bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) {
- return self->props;
-}
-
-void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
- if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) {
- mp_raise_ValueError(translate("No CCCD for this Characteristic"));
- }
-
- if (common_hal_bleio_device_get_gatt_role(self->service->device) != GATT_ROLE_CLIENT) {
- mp_raise_ValueError(translate("Can't set CCCD for local Characteristic"));
- }
-
- uint16_t cccd_value =
- (notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
- (indicate ? BLE_GATT_HVX_INDICATION : 0);
-
- const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
- check_connected(conn_handle);
-
-
- ble_gattc_write_params_t write_params = {
- .write_op = BLE_GATT_OP_WRITE_REQ,
- .handle = self->cccd_handle,
- .p_value = (uint8_t *) &cccd_value,
- .len = 2,
- };
-
- while (1) {
- uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
- if (err_code == NRF_SUCCESS) {
- break;
- }
-
- // Write with response will return NRF_ERROR_BUSY if the response has not been received.
- // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
- if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
- // We could wait for an event indicating the write is complete, but just retrying is easier.
- MICROPY_VM_HOOK_LOOP;
- continue;
- }
-
- // Some real error occurred.
- mp_raise_OSError_msg_varg(translate("Failed to write CCCD, err 0x%04x"), err_code);
- }
-
-}
diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c
deleted file mode 100644
index b6fcde827..000000000
--- a/ports/nrf/common-hal/bleio/Service.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- *
- * 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 "ble_drv.h"
-#include "ble.h"
-#include "py/runtime.h"
-#include "common-hal/bleio/__init__.h"
-#include "common-hal/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/Adapter.h"
-
-void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, mp_obj_list_t *characteristic_list, bool is_secondary) {
- self->device = mp_const_none;
- self->handle = 0xFFFF;
- self->uuid = uuid;
- self->characteristic_list = characteristic_list;
- self->is_secondary = is_secondary;
-
- for (size_t characteristic_idx = 0; characteristic_idx < characteristic_list->len; ++characteristic_idx) {
- bleio_characteristic_obj_t *characteristic =
- MP_OBJ_TO_PTR(characteristic_list->items[characteristic_idx]);
- characteristic->service = self;
- }
-
-}
-
-bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
- return self->uuid;
-}
-
-mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self) {
- return self->characteristic_list;
-}
-
-bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
- return self->is_secondary;
-}
-
-// Call this after the Service has been added to the Peripheral.
-void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) {
- // Add all the characteristics.
- for (size_t characteristic_idx = 0; characteristic_idx < self->characteristic_list->len; ++characteristic_idx) {
- bleio_characteristic_obj_t *characteristic =
- MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]);
-
- ble_gatts_char_md_t char_md = {
- .char_props.broadcast = characteristic->props.broadcast,
- .char_props.read = characteristic->props.read,
- .char_props.write_wo_resp = characteristic->props.write_no_response,
- .char_props.write = characteristic->props.write,
- .char_props.notify = characteristic->props.notify,
- .char_props.indicate = characteristic->props.indicate,
- };
-
- ble_gatts_attr_md_t cccd_md = {
- .vloc = BLE_GATTS_VLOC_STACK,
- };
-
- if (char_md.char_props.notify || char_md.char_props.indicate) {
- BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
- BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
-
- char_md.p_cccd_md = &cccd_md;
- }
-
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &uuid);
-
- ble_gatts_attr_md_t attr_md = {
- .vloc = BLE_GATTS_VLOC_STACK,
- .vlen = 1,
- };
-
- BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
- BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
-
- ble_gatts_attr_t attr_char_value = {
- .p_uuid = &uuid,
- .p_attr_md = &attr_md,
- .init_len = sizeof(uint8_t),
- .max_len = GATT_MAX_DATA_LENGTH,
- };
-
- ble_gatts_char_handles_t handles;
-
- uint32_t err_code;
- err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &attr_char_value, &handles);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code);
- }
-
- if (characteristic->handle != BLE_GATT_HANDLE_INVALID) {
- mp_raise_ValueError(translate("Characteristic already in use by another Service."));
- }
-
- characteristic->user_desc_handle = handles.user_desc_handle;
- characteristic->cccd_handle = handles.cccd_handle;
- characteristic->sccd_handle = handles.sccd_handle;
- characteristic->handle = handles.value_handle;
- }
-}
diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c
deleted file mode 100644
index 2dba5780c..000000000
--- a/ports/nrf/common-hal/bleio/__init__.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2016 Glenn Ruben Bakke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "shared-bindings/bleio/__init__.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Central.h"
-#include "shared-bindings/bleio/Peripheral.h"
-#include "common-hal/bleio/__init__.h"
-
-// Turn off BLE on a reset or reload.
-void bleio_reset() {
- if (common_hal_bleio_adapter_get_enabled()) {
- common_hal_bleio_adapter_set_enabled(false);
- }
-}
-
-// The singleton bleio.Adapter object, bound to bleio.adapter
-// It currently only has properties and no state
-const super_adapter_obj_t common_hal_bleio_adapter_obj = {
- .base = {
- .type = &bleio_adapter_type,
- },
-};
-
-gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) {
- if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
- return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
- } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
- return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
- } else {
- return GATT_ROLE_NONE;
- }
-}
-
-uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) {
- if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
- return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
- } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
- return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
- } else {
- return 0;
- }
-}
diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c
index 538c87f2d..71835d16a 100644
--- a/ports/nrf/common-hal/busio/I2C.c
+++ b/ports/nrf/common-hal/busio/I2C.c
@@ -57,13 +57,30 @@ STATIC twim_peripheral_t twim_peripherals[] = {
#endif
};
+STATIC bool never_reset[MP_ARRAY_SIZE(twim_peripherals)];
+
void i2c_reset(void) {
for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) {
+ if (never_reset[i]) {
+ continue;
+ }
nrf_twim_disable(twim_peripherals[i].twim.p_twim);
twim_peripherals[i].in_use = false;
}
}
+void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
+ for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) {
+ if (self->twim_peripheral == &twim_peripherals[i]) {
+ never_reset[i] = true;
+
+ never_reset_pin_number(self->scl_pin_number);
+ never_reset_pin_number(self->sda_pin_number);
+ break;
+ }
+ }
+}
+
static uint8_t twi_error_to_mp(const nrfx_err_t err) {
switch (err) {
case NRFX_ERROR_DRV_TWI_ERR_ANACK:
diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c
index 6ab6d9493..5f1aac193 100644
--- a/ports/nrf/common-hal/busio/SPI.c
+++ b/ports/nrf/common-hal/busio/SPI.c
@@ -61,7 +61,7 @@ STATIC spim_peripheral_t spim_peripherals[] = {
#endif
};
-STATIC bool never_reset[4];
+STATIC bool never_reset[MP_ARRAY_SIZE(spim_peripherals)];
void spi_reset(void) {
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c
index b9e9e5538..54a66ddbe 100644
--- a/ports/nrf/common-hal/busio/UART.c
+++ b/ports/nrf/common-hal/busio/UART.c
@@ -235,13 +235,11 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
+ RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
return 0;
}
-#endif
}
// prevent conflict with uart irq
@@ -271,9 +269,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data,
// Wait for on-going transfer to complete
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
// Time up
@@ -295,9 +291,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data,
(*errcode) = 0;
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
if ( !nrfx_is_in_ram(data) ) {
diff --git a/ports/nrf/common-hal/displayio/ParallelBus.c b/ports/nrf/common-hal/displayio/ParallelBus.c
index 42231be52..be4b28a6e 100644
--- a/ports/nrf/common-hal/displayio/ParallelBus.c
+++ b/ports/nrf/common-hal/displayio/ParallelBus.c
@@ -31,6 +31,7 @@
#include "common-hal/microcontroller/Pin.h"
#include "py/runtime.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "tick.h"
@@ -70,10 +71,6 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
- self->reset.base.type = &digitalio_digitalinout_type;
- common_hal_digitalio_digitalinout_construct(&self->reset, reset);
- common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
-
self->write.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->write, write);
common_hal_digitalio_digitalinout_switch_to_output(&self->write, true, DRIVE_MODE_PUSH_PULL);
@@ -93,11 +90,19 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
}
self->write_mask = 1 << (write->number % num_pins_in_write_port);
+ self->reset.base.type = &mp_type_NoneType;
+ if (reset != NULL) {
+ self->reset.base.type = &digitalio_digitalinout_type;
+ common_hal_digitalio_digitalinout_construct(&self->reset, reset);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
+ never_reset_pin_number(reset->number);
+ common_hal_displayio_parallelbus_reset(self);
+ }
+
never_reset_pin_number(command->number);
never_reset_pin_number(chip_select->number);
never_reset_pin_number(write->number);
never_reset_pin_number(read->number);
- never_reset_pin_number(reset->number);
for (uint8_t i = 0; i < 8; i++) {
never_reset_pin_number(data_pin + i);
}
@@ -115,15 +120,32 @@ void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self)
reset_pin_number(self->reset.pin->number);
}
+bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
+ displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (self->reset.base.type == &mp_type_NoneType) {
+ return false;
+ }
+
+ common_hal_digitalio_digitalinout_set_value(&self->reset, false);
+ common_hal_mcu_delay_us(4);
+ common_hal_digitalio_digitalinout_set_value(&self->reset, true);
+ return true;
+}
+
+bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
+ return true;
+}
+
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
return true;
}
-void common_hal_displayio_parallelbus_send(mp_obj_t obj, bool command, uint8_t *data, uint32_t data_length) {
+// This ignores chip_select behaviour because data is clocked in by the write line toggling.
+void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
- common_hal_digitalio_digitalinout_set_value(&self->command, !command);
+ common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA);
uint32_t* clear_write = (uint32_t*) &self->write_group->OUTCLR;
uint32_t* set_write = (uint32_t*) &self->write_group->OUTSET;
uint32_t mask = self->write_mask;
diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c
index b9c0ecaca..3cee784b6 100644
--- a/ports/nrf/common-hal/microcontroller/Pin.c
+++ b/ports/nrf/common-hal/microcontroller/Pin.c
@@ -105,7 +105,7 @@ void reset_pin_number(uint8_t pin_number) {
#ifdef SPEAKER_ENABLE_PIN
if (pin_number == SPEAKER_ENABLE_PIN->number) {
speaker_enable_in_use = false;
- common_hal_digitalio_digitalinout_switch_to_output(
+ common_hal_digitalio_digitalinout_switch_to_output(SPEAKER_ENABLE_PIN, true, DRIVE_MODE_PUSH_PULL);
nrf_gpio_pin_dir_set(pin_number, NRF_GPIO_PIN_DIR_OUTPUT);
nrf_gpio_pin_write(pin_number, false);
}
diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c
index ab7b5d5d6..a6b1c4ba3 100644
--- a/ports/nrf/common-hal/microcontroller/__init__.c
+++ b/ports/nrf/common-hal/microcontroller/__init__.c
@@ -37,6 +37,7 @@
#include "shared-bindings/microcontroller/Processor.h"
#include "supervisor/filesystem.h"
+#include "supervisor/shared/safe_mode.h"
#include "nrfx_glue.h"
// This routine should work even when interrupts are disabled. Used by OneWire
@@ -52,7 +53,13 @@ void common_hal_mcu_enable_interrupts() {
}
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
- // TODO: see atmel-samd for functionality
+ enum { DFU_MAGIC_UF2_RESET = 0x57 };
+ if(runmode == RUNMODE_BOOTLOADER)
+ NRF_POWER->GPREGRET = DFU_MAGIC_UF2_RESET;
+ else
+ NRF_POWER->GPREGRET = 0;
+ if(runmode == RUNMODE_SAFE_MODE)
+ safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
}
void common_hal_mcu_reset(void) {
diff --git a/ports/nrf/common-hal/neopixel_write/__init__.c b/ports/nrf/common-hal/neopixel_write/__init__.c
index 78e0038e8..3b67778a6 100644
--- a/ports/nrf/common-hal/neopixel_write/__init__.c
+++ b/ports/nrf/common-hal/neopixel_write/__init__.c
@@ -200,9 +200,7 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
// But we have to wait for the flag to be set.
while ( !nrf_pwm_event_check(pwm, NRF_PWM_EVENT_SEQEND0) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
// Before leave we clear the flag for the event.
diff --git a/ports/nrf/common-hal/pulseio/PWMOut.c b/ports/nrf/common-hal/pulseio/PWMOut.c
index 5233c9adc..6921091f8 100644
--- a/ports/nrf/common-hal/pulseio/PWMOut.c
+++ b/ports/nrf/common-hal/pulseio/PWMOut.c
@@ -57,6 +57,12 @@ STATIC uint16_t pwm_seq[MP_ARRAY_SIZE(pwms)][CHANNELS_PER_PWM];
static uint8_t never_reset_pwm[MP_ARRAY_SIZE(pwms)];
+STATIC int pwm_idx(NRF_PWM_Type *pwm) {
+ for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++)
+ if(pwms[i] == pwm) return i;
+ return -1;
+}
+
void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) {
for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) {
NRF_PWM_Type* pwm = pwms[i];
@@ -133,29 +139,11 @@ bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t *
return false;
}
-pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
- const mcu_pin_obj_t* pin,
- uint16_t duty,
- uint32_t frequency,
- bool variable_frequency) {
-
- // We don't use the nrfx driver here because we want to dynamically allocate channels
- // as needed in an already-enabled PWM.
-
- uint16_t countertop;
- nrf_pwm_clk_t base_clock;
- if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) {
- return PWMOUT_INVALID_FREQUENCY;
- }
-
- self->pwm = NULL;
- self->channel = CHANNELS_PER_PWM; // out-of-range value.
- bool pwm_already_in_use;
- NRF_PWM_Type* pwm;
- size_t pwm_index = 0;
- for (; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
- pwm = pwms[pwm_index];
- pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
+NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
+ bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out) {
+ for (size_t pwm_index = 0; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
+ NRF_PWM_Type *pwm = pwms[pwm_index];
+ bool pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
if (pwm_already_in_use) {
if (variable_frequency) {
// Variable frequency requires exclusive use of a PWM, so try the next one.
@@ -168,28 +156,65 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) {
if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) {
// Channel is free.
- self->pwm = pwm;
- self->channel = chan;
- break;
+ if(channel_out)
+ *channel_out = chan;
+ if(pwm_already_in_use_out)
+ *pwm_already_in_use_out = pwm_already_in_use;
+ return pwm;
}
}
- // Did we find a channel? If not, loop and check the next pwm.
- if (self->pwm != NULL) {
- break;
- }
}
} else {
// PWM not yet in use, so we can start to use it. Use channel 0.
- self->pwm = pwm;
- self->channel = 0;
- break;
+ if(channel_out)
+ *channel_out = 0;
+ if(pwm_already_in_use_out)
+ *pwm_already_in_use_out = pwm_already_in_use;
+ return pwm;
+ }
+ }
+ return NULL;
+}
+
+void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel) {
+ // Disconnect pin from channel.
+ pwm->PSEL.OUT[channel] = 0xFFFFFFFF;
+
+ for(int i=0; i < CHANNELS_PER_PWM; i++) {
+ if (pwm->PSEL.OUT[i] != 0xFFFFFFFF) {
+ // Some channel is still being used, so don't disable.
+ return;
}
}
+ nrf_pwm_disable(pwm);
+}
+
+pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
+ const mcu_pin_obj_t* pin,
+ uint16_t duty,
+ uint32_t frequency,
+ bool variable_frequency) {
+
+ // We don't use the nrfx driver here because we want to dynamically allocate channels
+ // as needed in an already-enabled PWM.
+
+ uint16_t countertop;
+ nrf_pwm_clk_t base_clock;
+ if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) {
+ return PWMOUT_INVALID_FREQUENCY;
+ }
+
+ int8_t channel;
+ bool pwm_already_in_use;
+ self->pwm = pwmout_allocate(countertop, base_clock, variable_frequency,
+ &channel, &pwm_already_in_use);
+
if (self->pwm == NULL) {
return PWMOUT_ALL_TIMERS_IN_USE;
}
+ self->channel = channel;
self->pin_number = pin->number;
claim_pin(pin);
@@ -200,17 +225,17 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
nrf_gpio_cfg_output(self->pin_number);
// disable before mapping pin channel
- nrf_pwm_disable(pwm);
+ nrf_pwm_disable(self->pwm);
if (!pwm_already_in_use) {
- reset_single_pwmout(pwm_index);
- nrf_pwm_configure(pwm, base_clock, NRF_PWM_MODE_UP, countertop);
+ reset_single_pwmout(pwm_idx(self->pwm));
+ nrf_pwm_configure(self->pwm, base_clock, NRF_PWM_MODE_UP, countertop);
}
// Connect channel to pin, without disturbing other channels.
- pwm->PSEL.OUT[self->channel] = pin->number;
+ self->pwm->PSEL.OUT[self->channel] = pin->number;
- nrf_pwm_enable(pwm);
+ nrf_pwm_enable(self->pwm);
common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
return PWMOUT_OK;
@@ -230,17 +255,10 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
NRF_PWM_Type* pwm = self->pwm;
self->pwm = NULL;
- // Disconnect pin from channel.
- pwm->PSEL.OUT[self->channel] = 0xFFFFFFFF;
-
- for(int i=0; i < CHANNELS_PER_PWM; i++) {
- if (self->pwm->PSEL.OUT[i] != 0xFFFFFFFF) {
- // Some channel is still being used, so don't disable.
- return;
- }
- }
+ pwmout_free_channel(pwm, self->channel);
- nrf_pwm_disable(pwm);
+ reset_pin_number(self->pin_number);
+ self->pin_number = NO_PIN;
}
void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) {
diff --git a/ports/nrf/common-hal/pulseio/PWMOut.h b/ports/nrf/common-hal/pulseio/PWMOut.h
index a4e58dc1a..b6798cb68 100644
--- a/ports/nrf/common-hal/pulseio/PWMOut.h
+++ b/ports/nrf/common-hal/pulseio/PWMOut.h
@@ -41,5 +41,8 @@ typedef struct {
} pulseio_pwmout_obj_t;
void pwmout_reset(void);
+NRF_PWM_Type *pwmout_allocate(uint16_t countertop, nrf_pwm_clk_t base_clock,
+ bool variable_frequency, int8_t *channel_out, bool *pwm_already_in_use_out);
+void pwmout_free_channel(NRF_PWM_Type *pwm, int8_t channel);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H
diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c
index be5deca9f..d0433247a 100644
--- a/ports/nrf/common-hal/pulseio/PulseOut.c
+++ b/ports/nrf/common-hal/pulseio/PulseOut.c
@@ -155,9 +155,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
while(pulse_array_index < length) {
// Do other things while we wait. The interrupts will handle sending the
// signal.
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
}
nrfx_timer_disable(timer);
diff --git a/ports/nrf/device/nrf52/startup_nrf52840.c b/ports/nrf/device/nrf52/startup_nrf52840.c
index 30634a1b5..8e1c36012 100644
--- a/ports/nrf/device/nrf52/startup_nrf52840.c
+++ b/ports/nrf/device/nrf52/startup_nrf52840.c
@@ -116,7 +116,7 @@ void CRYPTOCELL_IRQHandler (void) __attribute__ ((weak, alias("Default_Han
void SPIM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
void PWM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
-const func __Vectors[] __attribute__ ((section(".isr_vector"))) = {
+const func __Vectors[] __attribute__ ((used, section(".isr_vector"))) = {
(func)&_estack,
Reset_Handler,
NMI_Handler,
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index 5ed521e85..0b755a156 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -53,6 +53,11 @@
#include "py/circuitpy_mpconfig.h"
+#ifndef BOARD_HAS_32KHZ_XTAL
+// Assume crystal is present, which is the most common case.
+#define BOARD_HAS_32KHZ_XTAL (1)
+#endif
+
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS \
ble_drv_evt_handler_entry_t* ble_drv_evt_handler_entries; \
diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk
index 83166708a..02bde3eff 100644
--- a/ports/nrf/mpconfigport.mk
+++ b/ports/nrf/mpconfigport.mk
@@ -10,11 +10,12 @@ USB_SERIAL_NUMBER_LENGTH = 16
# All nRF ports have longints.
LONGINT_IMPL = MPZ
-# No DAC, so no regular audio.
+# Audio via PWM
+CIRCUITPY_AUDIOCORE = 1
CIRCUITPY_AUDIOIO = 0
-
-# No I2S yet.
-CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_AUDIOMIXER = 1
+CIRCUITPY_AUDIOPWMIO = 1
+CIRCUITPY_AUDIOBUSIO = 1
# No I2CSlave implementation
CIRCUITPY_I2CSLAVE = 0
diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c
index 7d9463d0b..bcd9fb114 100644
--- a/ports/nrf/mphalport.c
+++ b/ports/nrf/mphalport.c
@@ -39,9 +39,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t duration = 0;
while (duration < delay) {
- #ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
- #endif
+ RUN_BACKGROUND_TASKS;
// Check to see if we've been CTRL-Ced by autoreload or the user.
if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) ||
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h
index d51739fac..8fa6721e2 100644
--- a/ports/nrf/nrfx_config.h
+++ b/ports/nrf/nrfx_config.h
@@ -78,16 +78,17 @@
// TIMERS
#define NRFX_TIMER_ENABLED 1
// Don't enable TIMER0: it's used by the SoftDevice.
+#define NRFX_TIMER0_ENABLED 0
#define NRFX_TIMER1_ENABLED 1
#define NRFX_TIMER2_ENABLED 1
-#ifdef NRFX_TIMER3
+#ifdef NRF_TIMER3
#define NRFX_TIMER3_ENABLED 1
#else
#define NRFX_TIMER3_ENABLED 0
#endif
-#ifdef NRFX_TIMER4
+#ifdef NRF_TIMER4
#define NRFX_TIMER4_ENABLED 1
#else
#define NRFX_TIMER4_ENABLED 0
diff --git a/ports/nrf/peripherals/nrf/clocks.c b/ports/nrf/peripherals/nrf/clocks.c
index 4acb878db..269365cc9 100644
--- a/ports/nrf/peripherals/nrf/clocks.c
+++ b/ports/nrf/peripherals/nrf/clocks.c
@@ -26,11 +26,15 @@
*/
#include "nrfx.h"
+#include "mpconfigport.h"
void nrf_peripherals_clocks_init(void) {
- // Set low-frequency clock source to be crystal. If there's a crystalless board, this will need to be
- // generalized.
+
+#if BOARD_HAS_32KHZ_XTAL
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
+#else
+ NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
+#endif
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
// Wait for clocks to start.
diff --git a/ports/nrf/peripherals/nrf/timers.c b/ports/nrf/peripherals/nrf/timers.c
index 7f7a003d3..88f3dd468 100644
--- a/ports/nrf/peripherals/nrf/timers.c
+++ b/ports/nrf/peripherals/nrf/timers.c
@@ -36,7 +36,7 @@
STATIC nrfx_timer_t nrfx_timers[] = {
#if NRFX_CHECK(NRFX_TIMER0_ENABLED)
- // Note that TIMER0 is reserved for use by the SoftDevice, so it should not usually be enabled.
+ #error NRFX_TIMER0_ENABLED should not be on: TIMER0 is used by the SoftDevice
NRFX_TIMER_INSTANCE(0),
#endif
#if NRFX_CHECK(NRFX_TIMER1_ENABLED)
diff --git a/ports/nrf/sd_mutex.c b/ports/nrf/sd_mutex.c
index 7682ffa62..b3162e6af 100644
--- a/ports/nrf/sd_mutex.c
+++ b/ports/nrf/sd_mutex.c
@@ -37,9 +37,7 @@ void sd_mutex_acquire_check(nrf_mutex_t* p_mutex) {
void sd_mutex_acquire_wait(nrf_mutex_t* p_mutex) {
while (sd_mutex_acquire(p_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ RUN_BACKGROUND_TASKS;
}
}
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index 8fbf75498..e061c90b0 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -38,7 +38,7 @@
#include "shared-module/gamepad/__init__.h"
#include "common-hal/microcontroller/Pin.h"
-#include "common-hal/bleio/__init__.h"
+#include "common-hal/_bleio/__init__.h"
#include "common-hal/busio/I2C.h"
#include "common-hal/busio/SPI.h"
#include "common-hal/busio/UART.h"
@@ -50,6 +50,14 @@
#include "shared-bindings/rtc/__init__.h"
+#ifdef CIRCUITPY_AUDIOBUSIO
+#include "common-hal/audiobusio/I2SOut.h"
+#endif
+
+#ifdef CIRCUITPY_AUDIOPWMIO
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#endif
+
static void power_warning_handler(void) {
reset_into_safe_mode(BROWNOUT);
}
@@ -94,6 +102,15 @@ void reset_port(void) {
spi_reset();
uart_reset();
+#ifdef CIRCUITPY_AUDIOBUSIO
+ i2s_reset();
+#endif
+
+#ifdef CIRCUITPY_AUDIOPWMIO
+ audiopwmout_reset();
+#endif
+
+
#if CIRCUITPY_PULSEIO
pwmout_reset();
pulseout_reset();
diff --git a/ports/stm32f4/.gitignore b/ports/stm32f4/.gitignore
new file mode 100644
index 000000000..3080ece14
--- /dev/null
+++ b/ports/stm32f4/.gitignore
@@ -0,0 +1,9 @@
+# Build files
+#####################
+build-*/
+
+# Reference files
+#####################
+ref/
+
+.gdb_history \ No newline at end of file
diff --git a/ports/stm32f4/Makefile b/ports/stm32f4/Makefile
new file mode 100755
index 000000000..bef26d662
--- /dev/null
+++ b/ports/stm32f4/Makefile
@@ -0,0 +1,261 @@
+# This file is part of the MicroPython project, http://micropython.org/
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2019 Dan Halbert for Adafruit Industries
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+DEBUG = 1
+
+# Select the board to build for.
+ifeq ($(BOARD),)
+ $(error You must provide a BOARD parameter)
+else
+ ifeq ($(wildcard boards/$(BOARD)/.),)
+ $(error Invalid BOARD specified)
+ endif
+endif
+
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
+include ../../py/mkenv.mk
+# Board-specific
+include boards/$(BOARD)/mpconfigboard.mk
+# Port-specific
+include mpconfigport.mk
+
+# CircuitPython-specific
+include $(TOP)/py/circuitpy_mpconfig.mk
+
+# qstr definitions (must come before including py.mk)
+QSTR_DEFS = qstrdefsport.h
+
+# include py core make definitions
+include $(TOP)/py/py.mk
+
+include $(TOP)/supervisor/supervisor.mk
+
+# Include make rules and variables common across CircuitPython builds.
+include $(TOP)/py/circuitpy_defns.mk
+
+CROSS_COMPILE = arm-none-eabi-
+
+#######################################
+# CFLAGS
+#######################################
+
+INC += -I.
+INC += -I../..
+INC += -I$(BUILD)
+INC += -I$(BUILD)/genhdr
+INC += -I./stm32f4/STM32F4xx_HAL_Driver/Inc
+INC += -I./stm32f4/STM32F4xx_HAL_Driver/Inc/Legacy
+INC += -I./stm32f4/CMSIS/Device/ST/STM32F4xx/Include
+INC += -I./stm32f4/CMSIS/Include
+INC += -I./boards
+INC += -I./boards/$(BOARD)
+INC += -I./peripherals
+INC += -I../../lib/mp-readline
+INC += -I../../lib/tinyusb/src
+INC += -I../../supervisor/shared/usb
+
+
+#Debugging/Optimization
+ifeq ($(DEBUG), 1)
+ CFLAGS += -ggdb
+ # You may want to enable these flags to make setting breakpoints easier.
+ CFLAGS += -fno-inline -fno-ipa-sra
+else
+ CFLAGS += -Os -DNDEBUG
+ # TODO: Test with -flto
+ ### CFLAGS += -flto
+endif
+
+C_DEFS = -DMCU_PACKAGE=$(MCU_PACKAGE) -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -D$(CMSIS_MCU)
+
+CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostdlib $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
+
+# Undo some warnings.
+# STM32 apparently also uses undefined preprocessor variables quite casually,
+# so we can't do warning checks for these.
+CFLAGS += -Wno-undef
+# STM32 might do casts that increase alignment requirements.
+CFLAGS += -Wno-cast-align
+
+CFLAGS += \
+ -mthumb \
+ -mabi=aapcs-linux \
+ -mfloat-abi=hard \
+ -mcpu=cortex-m4 \
+ -mfpu=fpv4-sp-d16
+
+# TODO: check this
+CFLAGS += -D__START=main
+
+LDFLAGS = $(CFLAGS) -fshort-enums -Wl,-nostdlib -Wl,-T,$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nano.specs
+LIBS := -lgcc -lc
+
+LDFLAGS += -mthumb -mcpu=cortex-m4
+
+# Use toolchain libm if we're not using our own.
+ifndef INTERNAL_LIBM
+LIBS += -lm
+endif
+
+# TinyUSB defines
+CFLAGS += -DHSE_VALUE=8000000 -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -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
+
+
+######################################
+# source
+######################################
+
+SRC_STM32 = \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c \
+ stm32f4/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c \
+ system_stm32f4xx.c
+
+SRC_C += \
+ background.c \
+ fatfs_port.c \
+ mphalport.c \
+ tick.c \
+ boards/$(BOARD)/board.c \
+ boards/$(BOARD)/pins.c \
+ peripherals/stm32f4/$(MCU_SUB_VARIANT)/pins.c \
+ peripherals/stm32f4/$(MCU_SUB_VARIANT)/clocks.c \
+ peripherals/stm32f4/$(MCU_SUB_VARIANT)/gpio.c \
+ peripherals/stm32f4/$(MCU_SUB_VARIANT)/periph.c \
+ lib/libc/string0.c \
+ lib/mp-readline/readline.c \
+ lib/oofatfs/ff.c \
+ lib/oofatfs/option/ccsbcs.c \
+ lib/timeutils/timeutils.c \
+ lib/utils/buffer_helper.c \
+ lib/utils/context_manager_helpers.c \
+ lib/utils/interrupt_char.c \
+ lib/utils/pyexec.c \
+ lib/utils/stdout_helpers.c \
+ lib/utils/sys_stdio_mphal.c \
+ supervisor/shared/memory.c
+
+ifneq ($(USB),FALSE)
+SRC_C += lib/tinyusb/src/portable/st/synopsys/dcd_synopsys.c
+endif
+
+SRC_S = \
+ supervisor/cpu.s \
+ boards/startup_$(MCU_SUB_VARIANT).s
+
+SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
+ $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
+ $(addprefix common-hal/, $(SRC_COMMON_HAL))
+
+SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
+ $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \
+ $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL))
+
+
+ifneq ($(FROZEN_MPY_DIR),)
+FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
+FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
+endif
+
+OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_STM32:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o))
+ifeq ($(INTERNAL_LIBM),1)
+OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o))
+endif
+OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
+
+$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os
+$(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os
+
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)
+# Sources that only hold QSTRs after pre-processing.
+SRC_QSTR_PREPROCESSOR +=
+
+
+all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2
+
+$(BUILD)/firmware.elf: $(OBJ)
+ $(STEPECHO) "LINK $@"
+ $(Q)$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group
+ $(Q)$(SIZE) $@ | $(PYTHON3) $(TOP)/tools/build_memory_info.py $(LD_FILE)
+
+$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
+ $(STEPECHO) "Create $@"
+ $(Q)$(OBJCOPY) -O binary $^ $@
+# $(Q)$(OBJCOPY) -O binary -j .vectors -j .text -j .data $^ $@
+
+$(BUILD)/firmware.hex: $(BUILD)/firmware.elf
+ $(STEPECHO) "Create $@"
+ $(Q)$(OBJCOPY) -O ihex $^ $@
+# $(Q)$(OBJCOPY) -O ihex -j .vectors -j .text -j .data $^ $@
+
+$(BUILD)/firmware.uf2: $(BUILD)/firmware.hex
+ $(ECHO) "Create $@"
+ $(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xADA52840 -c -o "$(BUILD)/firmware.uf2" $^
+
+include $(TOP)/py/mkrules.mk
+
+# Print out the value of a make variable.
+# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile
+print-%:
+ @echo $* = $($*)
diff --git a/ports/stm32f4/README.md b/ports/stm32f4/README.md
new file mode 100644
index 000000000..a860c01ce
--- /dev/null
+++ b/ports/stm32f4/README.md
@@ -0,0 +1,3 @@
+# CircuitPython Port To The ST Microelectronics STM32F4 Series
+
+This is a port of CircuitPython to the STM32F4 series of chips.
diff --git a/ports/stm32f4/background.c b/ports/stm32f4/background.c
new file mode 100644
index 000000000..8c1897043
--- /dev/null
+++ b/ports/stm32f4/background.c
@@ -0,0 +1,60 @@
+/*
+ * 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 "py/runtime.h"
+#include "supervisor/filesystem.h"
+#include "supervisor/usb.h"
+#include "supervisor/shared/stack.h"
+
+#if CIRCUITPY_DISPLAYIO
+#include "shared-module/displayio/__init__.h"
+#endif
+
+static bool running_background_tasks = false;
+
+void background_tasks_reset(void) {
+ running_background_tasks = false;
+}
+
+void run_background_tasks(void) {
+ // Don't call ourselves recursively.
+ if (running_background_tasks) {
+ return;
+ }
+ running_background_tasks = true;
+ filesystem_background();
+
+ #if USB_AVAILABLE
+ usb_background();
+ #endif
+
+ #if CIRCUITPY_DISPLAYIO
+ displayio_background();
+ #endif
+ running_background_tasks = false;
+
+ assert_heap_ok();
+}
diff --git a/shared-bindings/bleio/__init__.h b/ports/stm32f4/background.h
index 4aa6dd45b..05a4f894a 100644
--- a/shared-bindings/bleio/__init__.h
+++ b/ports/stm32f4/background.h
@@ -4,8 +4,6 @@
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,11 +24,12 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
+#ifndef MICROPY_INCLUDED_STM32F4_BACKGROUND_H
+#define MICROPY_INCLUDED_STM32F4_BACKGROUND_H
-#include "common-hal/bleio/Adapter.h"
+#include <stdbool.h>
-extern const super_adapter_obj_t common_hal_bleio_adapter_obj;
+void background_tasks_reset(void);
+void run_background_tasks(void);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
+#endif // MICROPY_INCLUDED_STM32F4_BACKGROUND_H
diff --git a/ports/stm32f4/boards/STM32F405.ld b/ports/stm32f4/boards/STM32F405.ld
new file mode 100644
index 000000000..7f7c91784
--- /dev/null
+++ b/ports/stm32f4/boards/STM32F405.ld
@@ -0,0 +1,108 @@
+/*
+ GNU linker script for STM32F405 via Micropython
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */
+ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */
+ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 48K /* sectors 1,2,3 are 16K */
+ FLASH_TEXT (rx) : ORIGIN = 0x08010000, LENGTH = 960K /* sector 4 is 64K, sectors 5,6,7 are 128K */
+ CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define tho top end of the stack. The stack is full descending so begins just
+ above last byte of RAM. Note that EABI requires the stack to be 8-byte
+ aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM);
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+
+ENTRY(Reset_Handler)
+
+/* define output sections */
+SECTIONS
+{
+ /* The startup code goes first into FLASH */
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+
+ /* This first flash block is 16K annd the isr vectors only take up
+ about 400 bytes. Micropython pads this with files, but this didn't
+ work with the size of Circuitpython's ff object. */
+
+ . = ALIGN(4);
+ } >FLASH_ISR
+
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text*) /* .text* sections (code) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+ /* *(.glue_7) */ /* glue arm to thumb code */
+ /* *(.glue_7t) */ /* glue thumb to arm code */
+
+ . = ALIGN(4);
+ _etext = .; /* define a global symbol at end of code */
+ } >FLASH_TEXT
+
+ /* used by the startup to initialize data */
+ _sidata = LOADADDR(.data);
+
+ /* This is the initialized data section
+ The program executes knowing that the data is in the RAM
+ but the loader puts the initial values in the FLASH (inidata).
+ It is one task of the startup to copy the initial values from FLASH to RAM. */
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
+ *(.data*) /* .data* sections */
+
+ . = ALIGN(4);
+ _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
+ } >RAM AT> FLASH_TEXT
+
+ /* Uninitialized data section */
+ .bss :
+ {
+ . = ALIGN(4);
+ _sbss = .; /* define a global symbol at bss start; used by startup code */
+ *(.bss*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .; /* define a global symbol at bss end; used by startup code and GC */
+ } >RAM
+
+ /* this is to define the start of the heap, and make sure we have a minimum size */
+ .heap :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_heap_size;
+ . = ALIGN(4);
+ } >RAM
+
+ /* this just checks there is enough RAM for the stack */
+ .stack :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_stack_size;
+ . = ALIGN(4);
+ } >RAM
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
+
+
diff --git a/ports/stm32f4/boards/STM32F411VETx_FLASH.ld b/ports/stm32f4/boards/STM32F411VETx_FLASH.ld
new file mode 100644
index 000000000..ac1ba3240
--- /dev/null
+++ b/ports/stm32f4/boards/STM32F411VETx_FLASH.ld
@@ -0,0 +1,109 @@
+/*
+ GNU linker script for STM32F411 via Micropython
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
+ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */
+ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 48K /* sectors 1,2,3 are 16K */
+ FLASH_TEXT (rx) : ORIGIN = 0x08010000, LENGTH = 448K /* sector 4 is 64K, sectors 5,6,7 are 128K */
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define tho top end of the stack. The stack is full descending so begins just
+ above last byte of RAM. Note that EABI requires the stack to be 8-byte
+ aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM);
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_start = _ebss; /* heap starts just after statically allocated memory */
+_heap_end = 0x2001c000; /* tunable */
+
+ENTRY(Reset_Handler)
+
+/* define output sections */
+SECTIONS
+{
+ /* The startup code goes first into FLASH */
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+
+ /* This first flash block is 16K annd the isr vectors only take up
+ about 400 bytes. Micropython pads this with files, but this didn't
+ work with the size of Circuitpython's ff object. */
+
+ . = ALIGN(4);
+ } >FLASH_ISR
+
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text*) /* .text* sections (code) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+ /* *(.glue_7) */ /* glue arm to thumb code */
+ /* *(.glue_7t) */ /* glue thumb to arm code */
+
+ . = ALIGN(4);
+ _etext = .; /* define a global symbol at end of code */
+ } >FLASH_TEXT
+
+ /* used by the startup to initialize data */
+ _sidata = LOADADDR(.data);
+
+ /* This is the initialized data section
+ The program executes knowing that the data is in the RAM
+ but the loader puts the initial values in the FLASH (inidata).
+ It is one task of the startup to copy the initial values from FLASH to RAM. */
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
+ *(.data*) /* .data* sections */
+
+ . = ALIGN(4);
+ _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
+ } >RAM AT> FLASH_TEXT
+
+ /* Uninitialized data section */
+ .bss :
+ {
+ . = ALIGN(4);
+ _sbss = .; /* define a global symbol at bss start; used by startup code */
+ *(.bss*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .; /* define a global symbol at bss end; used by startup code and GC */
+ } >RAM
+
+ /* this is to define the start of the heap, and make sure we have a minimum size */
+ .heap :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_heap_size;
+ . = ALIGN(4);
+ } >RAM
+
+ /* this just checks there is enough RAM for the stack */
+ .stack :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_stack_size;
+ . = ALIGN(4);
+ } >RAM
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
+
+
diff --git a/ports/stm32f4/boards/STM32F412ZGTx_FLASH.ld b/ports/stm32f4/boards/STM32F412ZGTx_FLASH.ld
new file mode 100644
index 000000000..e0586709e
--- /dev/null
+++ b/ports/stm32f4/boards/STM32F412ZGTx_FLASH.ld
@@ -0,0 +1,105 @@
+/*
+ GNU linker script for STM32F412
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */
+ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */
+ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 48K /* sectors 1,2,3 are 16K */
+ FLASH_TEXT (rx) : ORIGIN = 0x08010000, LENGTH = 960K /* sector 4 is 64K, sectors 5,6,7 are 128K */
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
+}
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define tho top end of the stack. The stack is full descending so begins just
+ above last byte of RAM. Note that EABI requires the stack to be 8-byte
+ aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM);
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_start = _ebss; /* heap starts just after statically allocated memory */
+_heap_end = 0x20020000; /* tunable */
+
+ENTRY(Reset_Handler)
+
+/* define output sections */
+SECTIONS
+{
+ /* The startup code goes first into FLASH */
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+
+ /* This first flash block is 16K annd the isr vectors only take up
+ about 400 bytes. Micropython pads this with files, but this didn't
+ work with the size of Circuitpython's ff object. */
+
+ . = ALIGN(4);
+ } >FLASH_ISR
+
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text*) /* .text* sections (code) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+
+ . = ALIGN(4);
+ _etext = .; /* define a global symbol at end of code */
+ } >FLASH_TEXT
+
+ /* used by the startup to initialize data */
+ _sidata = LOADADDR(.data);
+
+ /* This is the initialized data section
+ The program executes knowing that the data is in the RAM
+ but the loader puts the initial values in the FLASH (inidata).
+ It is one task of the startup to copy the initial values from FLASH to RAM. */
+ .data :
+ {
+ . = ALIGN(4);
+ _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
+ *(.data*) /* .data* sections */
+
+ . = ALIGN(4);
+ _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
+ } >RAM AT> FLASH_TEXT
+
+ /* Uninitialized data section */
+ .bss :
+ {
+ . = ALIGN(4);
+ _sbss = .; /* define a global symbol at bss start; used by startup code */
+ *(.bss*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .; /* define a global symbol at bss end; used by startup code and GC */
+ } >RAM
+
+ /* this is to define the start of the heap, and make sure we have a minimum size */
+ .heap :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_heap_size;
+ . = ALIGN(4);
+ } >RAM
+
+ /* this just checks there is enough RAM for the stack */
+ .stack :
+ {
+ . = ALIGN(4);
+ . = . + _minimum_stack_size;
+ . = ALIGN(4);
+ } >RAM
+
+ .ARM.attributes 0 : { *(.ARM.attributes) }
+}
diff --git a/ports/stm32f4/boards/board.h b/ports/stm32f4/boards/board.h
new file mode 100644
index 000000000..22d9e99be
--- /dev/null
+++ b/ports/stm32f4/boards/board.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+// This file defines board specific functions.
+
+#ifndef MICROPY_INCLUDED_STM32F4_BOARDS_BOARD_H
+#define MICROPY_INCLUDED_STM32F4_BOARDS_BOARD_H
+
+#include <stdbool.h>
+
+// Initializes board related state once on start up.
+void board_init(void);
+
+// Returns true if the user initiates safe mode in a board specific way.
+// Also add BOARD_USER_SAFE_MODE in mpconfigboard.h to explain the board specific
+// way.
+bool board_requests_safe_mode(void);
+
+// Reset the state of off MCU components such as neopixels.
+void reset_board(void);
+
+#endif // MICROPY_INCLUDED_STM32F4_BOARDS_BOARD_H
diff --git a/ports/stm32f4/boards/feather_f405/board.c b/ports/stm32f4/boards/feather_f405/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/stm32f4/boards/feather_f405/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/stm32f4/boards/feather_f405/mpconfigboard.h b/ports/stm32f4/boards/feather_f405/mpconfigboard.h
new file mode 100644
index 000000000..831a17573
--- /dev/null
+++ b/ports/stm32f4/boards/feather_f405/mpconfigboard.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "Feather F405"
+#define MICROPY_HW_MCU_NAME "STM32F405RG"
+
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (0x4000)
+
+#define AUTORESET_DELAY_MS 500
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000)
+
+// On-board flash
+#define SPI_FLASH_MOSI_PIN &pin_PB05
+#define SPI_FLASH_MISO_PIN &pin_PB04
+#define SPI_FLASH_SCK_PIN &pin_PB03
+#define SPI_FLASH_CS_PIN &pin_PA15
diff --git a/ports/stm32f4/boards/feather_f405/mpconfigboard.mk b/ports/stm32f4/boards/feather_f405/mpconfigboard.mk
new file mode 100644
index 000000000..789dc0f05
--- /dev/null
+++ b/ports/stm32f4/boards/feather_f405/mpconfigboard.mk
@@ -0,0 +1,19 @@
+USB_VID = 0x239A
+USB_PID = 0x805A
+USB_PRODUCT = "Feather F405"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+USB_DEVICES = "CDC,MSC"
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = GD25Q16C
+LONGINT_IMPL = MPZ
+
+MCU_SERIES = m4
+MCU_VARIANT = stm32f4
+MCU_SUB_VARIANT = stm32f405xx
+MCU_PACKAGE = 64
+CMSIS_MCU = STM32F405xx
+LD_FILE = boards/STM32F405.ld
+TEXT0_ADDR = 0x08000000
+TEXT1_ADDR = 0x08010000 \ No newline at end of file
diff --git a/ports/stm32f4/boards/feather_f405/pins.c b/ports/stm32f4/boards/feather_f405/pins.c
new file mode 100644
index 000000000..518ab6d2a
--- /dev/null
+++ b/ports/stm32f4/boards/feather_f405/pins.c
@@ -0,0 +1,29 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PC04) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PC05) },
+
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PC07) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PC06) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PC03) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PC02) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PC01) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB06) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB15) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB11) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h
new file mode 100644
index 000000000..019b03ca7
--- /dev/null
+++ b/ports/stm32f4/boards/feather_f405/stm32f4xx_hal_conf.h
@@ -0,0 +1,440 @@
+/**
+ ******************************************************************************
+ * @file stm32f4xx_hal_conf_template.h
+ * @author MCD Application Team
+ * @brief HAL configuration template file.
+ * This file should be copied to the application folder and renamed
+ * to stm32f4xx_hal_conf.h.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_HAL_CONF_H
+#define __STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+
+#define HAL_ADC_MODULE_ENABLED
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_CAN_MODULE_ENABLED */
+/* #define HAL_CRC_MODULE_ENABLED */
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_DAC_MODULE_ENABLED */
+/* #define HAL_DCMI_MODULE_ENABLED */
+/* #define HAL_DMA2D_MODULE_ENABLED */
+/* #define HAL_ETH_MODULE_ENABLED */
+/* #define HAL_NAND_MODULE_ENABLED */
+/* #define HAL_NOR_MODULE_ENABLED */
+/* #define HAL_PCCARD_MODULE_ENABLED */
+/* #define HAL_SRAM_MODULE_ENABLED */
+/* #define HAL_SDRAM_MODULE_ENABLED */
+/* #define HAL_HASH_MODULE_ENABLED */
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_I2S_MODULE_ENABLED
+/* #define HAL_IWDG_MODULE_ENABLED */
+/* #define HAL_LTDC_MODULE_ENABLED */
+/* #define HAL_RNG_MODULE_ENABLED */
+/* #define HAL_RTC_MODULE_ENABLED */
+/* #define HAL_SAI_MODULE_ENABLED */
+/* #define HAL_SD_MODULE_ENABLED */
+/* #define HAL_MMC_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
+/* #define HAL_TIM_MODULE_ENABLED */
+#define HAL_UART_MODULE_ENABLED
+/* #define HAL_USART_MODULE_ENABLED */
+/* #define HAL_IRDA_MODULE_ENABLED */
+/* #define HAL_SMARTCARD_MODULE_ENABLED */
+/* #define HAL_WWDG_MODULE_ENABLED */
+#define HAL_PCD_MODULE_ENABLED
+/* #define HAL_HCD_MODULE_ENABLED */
+/* #define HAL_DSI_MODULE_ENABLED */
+/* #define HAL_QSPI_MODULE_ENABLED */
+/* #define HAL_QSPI_MODULE_ENABLED */
+/* #define HAL_CEC_MODULE_ENABLED */
+/* #define HAL_FMPI2C_MODULE_ENABLED */
+/* #define HAL_SPDIFRX_MODULE_ENABLED */
+/* #define HAL_DFSDM_MODULE_ENABLED */
+/* #define HAL_LPTIM_MODULE_ENABLED */
+/* #define HAL_EXTI_MODULE_ENABLED */
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+
+/* ########################## HSE/HSI Values adaptation ##################### */
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief Internal Low Speed oscillator (LSI) value.
+ */
+#if !defined (LSI_VALUE)
+ #define LSI_VALUE ((uint32_t)40000)
+#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature. */
+/**
+ * @brief External Low Speed oscillator (LSE) value.
+ */
+#if !defined (LSE_VALUE)
+ #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */
+#endif /* LSE_VALUE */
+
+#if !defined (LSE_STARTUP_TIMEOUT)
+ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+
+/**
+ * @brief External clock source for I2S peripheral
+ * This value is used by the I2S HAL module to compute the I2S clock source
+ * frequency, this source is inserted directly through I2S_CKIN pad.
+ */
+#if !defined (EXTERNAL_CLOCK_VALUE)
+ #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
+#endif /* EXTERNAL_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
+#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
+#define USE_RTOS 0U
+#define PREFETCH_ENABLE 1U
+#define INSTRUCTION_CACHE_ENABLE 1U
+#define DATA_CACHE_ENABLE 1U
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1U */
+
+/* ################## Ethernet peripheral configuration ##################### */
+
+/* Section 1 : Ethernet peripheral configuration */
+
+/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0 2U
+#define MAC_ADDR1 0U
+#define MAC_ADDR2 0U
+#define MAC_ADDR3 0U
+#define MAC_ADDR4 0U
+#define MAC_ADDR5 0U
+
+/* Definition of the Ethernet driver buffers size and count */
+#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
+#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
+#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
+#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
+
+/* Section 2: PHY configuration section */
+
+/* DP83848_PHY_ADDRESS Address*/
+#define DP83848_PHY_ADDRESS 0x01U
+/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
+#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
+/* PHY Configuration delay */
+#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
+
+#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
+#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
+
+/* Section 3: Common PHY Registers */
+
+#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
+#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
+
+#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
+#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
+#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
+#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
+#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
+#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
+
+#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
+#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
+#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
+
+/* Section 4: Extended PHY Registers */
+#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
+
+#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
+#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+* Activated: CRC code is present inside driver
+* Deactivated: CRC code cleaned from driver
+*/
+
+#define USE_SPI_CRC 0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+ #include "stm32f4xx_hal_exti.h"
+#endif /* HAL_EXTI_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32f4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32f4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32f4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+ #include "stm32f4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32f4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32f4xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma2d.h"
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+ #include "stm32f4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dcmi.h"
+#endif /* HAL_DCMI_MODULE_ENABLED */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+ #include "stm32f4xx_hal_eth.h"
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+ #include "stm32f4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+ #include "stm32f4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_PCCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pccard.h"
+#endif /* HAL_PCCARD_MODULE_ENABLED */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sdram.h"
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_hash.h"
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+ #include "stm32f4xx_hal_ltdc.h"
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32f4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32f4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32f4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32f4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_MMC_MODULE_ENABLED
+ #include "stm32f4xx_hal_mmc.h"
+#endif /* HAL_MMC_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32f4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32f4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32f4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+#ifdef HAL_DSI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dsi.h"
+#endif /* HAL_DSI_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_CEC_MODULE_ENABLED
+ #include "stm32f4xx_hal_cec.h"
+#endif /* HAL_CEC_MODULE_ENABLED */
+
+#ifdef HAL_FMPI2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_fmpi2c.h"
+#endif /* HAL_FMPI2C_MODULE_ENABLED */
+
+#ifdef HAL_SPDIFRX_MODULE_ENABLED
+ #include "stm32f4xx_hal_spdifrx.h"
+#endif /* HAL_SPDIFRX_MODULE_ENABLED */
+
+#ifdef HAL_DFSDM_MODULE_ENABLED
+ #include "stm32f4xx_hal_dfsdm.h"
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_HAL_CONF_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32f4/boards/pyboard_v11/board.c b/ports/stm32f4/boards/pyboard_v11/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/stm32f4/boards/pyboard_v11/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/stm32f4/boards/pyboard_v11/mpconfigboard.h
index 005af6eaa..e8441d665 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.c
+++ b/ports/stm32f4/boards/pyboard_v11/mpconfigboard.h
@@ -3,9 +3,8 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,17 +25,13 @@
* THE SOFTWARE.
*/
-#include "common-hal/bleio/Descriptor.h"
-#include "shared-bindings/bleio/UUID.h"
+//Micropython setup
-void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) {
- self->uuid = uuid;
-}
+#define MICROPY_HW_BOARD_NAME "PyboardV1_1"
+#define MICROPY_HW_MCU_NAME "STM32F405RG"
-mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) {
- return self->handle;
-}
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (0x4000)
-bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
- return self->uuid;
-}
+#define AUTORESET_DELAY_MS 500
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000) \ No newline at end of file
diff --git a/ports/stm32f4/boards/pyboard_v11/mpconfigboard.mk b/ports/stm32f4/boards/pyboard_v11/mpconfigboard.mk
new file mode 100644
index 000000000..a01ff7923
--- /dev/null
+++ b/ports/stm32f4/boards/pyboard_v11/mpconfigboard.mk
@@ -0,0 +1,17 @@
+USB_VID = 0x239A
+USB_PID = 0x805C
+USB_PRODUCT = "Pyboard Version 1.1"
+USB_MANUFACTURER = "George Robotic"
+USB_DEVICES = "CDC,MSC"
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+
+MCU_SERIES = m4
+MCU_VARIANT = stm32f4
+MCU_SUB_VARIANT = stm32f405xx
+MCU_PACKAGE = 64
+CMSIS_MCU = STM32F405xx
+LD_FILE = boards/STM32F405.ld
+TEXT0_ADDR = 0x08000000
+TEXT1_ADDR = 0x08010000
diff --git a/ports/stm32f4/boards/pyboard_v11/pins.c b/ports/stm32f4/boards/pyboard_v11/pins.c
new file mode 100644
index 000000000..ccbb58ab9
--- /dev/null
+++ b/ports/stm32f4/boards/pyboard_v11/pins.c
@@ -0,0 +1,50 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_Y1), MP_ROM_PTR(&pin_PC06) },
+ { MP_ROM_QSTR(MP_QSTR_Y2), MP_ROM_PTR(&pin_PC07) },
+ { MP_ROM_QSTR(MP_QSTR_Y3), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_Y4), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_Y5), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_Y6), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_Y7), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_Y8), MP_ROM_PTR(&pin_PB15) },
+ { MP_ROM_QSTR(MP_QSTR_Y9), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_Y10), MP_ROM_PTR(&pin_PB11) },
+ { MP_ROM_QSTR(MP_QSTR_Y11), MP_ROM_PTR(&pin_PB00) },
+ { MP_ROM_QSTR(MP_QSTR_Y12), MP_ROM_PTR(&pin_PB01) },
+
+ { MP_ROM_QSTR(MP_QSTR_X1), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_X2), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_X3), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_X4), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_X5), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_X6), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_X7), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_X8), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_X9), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_X10), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_X11), MP_ROM_PTR(&pin_PC04) },
+ { MP_ROM_QSTR(MP_QSTR_X12), MP_ROM_PTR(&pin_PC05) },
+
+ { MP_ROM_QSTR(MP_QSTR_X17), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_X18), MP_ROM_PTR(&pin_PC13) },
+ { MP_ROM_QSTR(MP_QSTR_X19), MP_ROM_PTR(&pin_PC00) },
+ { MP_ROM_QSTR(MP_QSTR_X20), MP_ROM_PTR(&pin_PC01) },
+ { MP_ROM_QSTR(MP_QSTR_X21), MP_ROM_PTR(&pin_PC02) },
+ { MP_ROM_QSTR(MP_QSTR_X22), MP_ROM_PTR(&pin_PC03) },
+
+ { MP_ROM_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_PA13) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_LED4), MP_ROM_PTR(&pin_PA13) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB07) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h
new file mode 100644
index 000000000..019b03ca7
--- /dev/null
+++ b/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h
@@ -0,0 +1,440 @@
+/**
+ ******************************************************************************
+ * @file stm32f4xx_hal_conf_template.h
+ * @author MCD Application Team
+ * @brief HAL configuration template file.
+ * This file should be copied to the application folder and renamed
+ * to stm32f4xx_hal_conf.h.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_HAL_CONF_H
+#define __STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+
+#define HAL_ADC_MODULE_ENABLED
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_CAN_MODULE_ENABLED */
+/* #define HAL_CRC_MODULE_ENABLED */
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_DAC_MODULE_ENABLED */
+/* #define HAL_DCMI_MODULE_ENABLED */
+/* #define HAL_DMA2D_MODULE_ENABLED */
+/* #define HAL_ETH_MODULE_ENABLED */
+/* #define HAL_NAND_MODULE_ENABLED */
+/* #define HAL_NOR_MODULE_ENABLED */
+/* #define HAL_PCCARD_MODULE_ENABLED */
+/* #define HAL_SRAM_MODULE_ENABLED */
+/* #define HAL_SDRAM_MODULE_ENABLED */
+/* #define HAL_HASH_MODULE_ENABLED */
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_I2S_MODULE_ENABLED
+/* #define HAL_IWDG_MODULE_ENABLED */
+/* #define HAL_LTDC_MODULE_ENABLED */
+/* #define HAL_RNG_MODULE_ENABLED */
+/* #define HAL_RTC_MODULE_ENABLED */
+/* #define HAL_SAI_MODULE_ENABLED */
+/* #define HAL_SD_MODULE_ENABLED */
+/* #define HAL_MMC_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
+/* #define HAL_TIM_MODULE_ENABLED */
+#define HAL_UART_MODULE_ENABLED
+/* #define HAL_USART_MODULE_ENABLED */
+/* #define HAL_IRDA_MODULE_ENABLED */
+/* #define HAL_SMARTCARD_MODULE_ENABLED */
+/* #define HAL_WWDG_MODULE_ENABLED */
+#define HAL_PCD_MODULE_ENABLED
+/* #define HAL_HCD_MODULE_ENABLED */
+/* #define HAL_DSI_MODULE_ENABLED */
+/* #define HAL_QSPI_MODULE_ENABLED */
+/* #define HAL_QSPI_MODULE_ENABLED */
+/* #define HAL_CEC_MODULE_ENABLED */
+/* #define HAL_FMPI2C_MODULE_ENABLED */
+/* #define HAL_SPDIFRX_MODULE_ENABLED */
+/* #define HAL_DFSDM_MODULE_ENABLED */
+/* #define HAL_LPTIM_MODULE_ENABLED */
+/* #define HAL_EXTI_MODULE_ENABLED */
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+
+/* ########################## HSE/HSI Values adaptation ##################### */
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief Internal Low Speed oscillator (LSI) value.
+ */
+#if !defined (LSI_VALUE)
+ #define LSI_VALUE ((uint32_t)40000)
+#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature. */
+/**
+ * @brief External Low Speed oscillator (LSE) value.
+ */
+#if !defined (LSE_VALUE)
+ #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */
+#endif /* LSE_VALUE */
+
+#if !defined (LSE_STARTUP_TIMEOUT)
+ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+
+/**
+ * @brief External clock source for I2S peripheral
+ * This value is used by the I2S HAL module to compute the I2S clock source
+ * frequency, this source is inserted directly through I2S_CKIN pad.
+ */
+#if !defined (EXTERNAL_CLOCK_VALUE)
+ #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
+#endif /* EXTERNAL_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
+#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
+#define USE_RTOS 0U
+#define PREFETCH_ENABLE 1U
+#define INSTRUCTION_CACHE_ENABLE 1U
+#define DATA_CACHE_ENABLE 1U
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1U */
+
+/* ################## Ethernet peripheral configuration ##################### */
+
+/* Section 1 : Ethernet peripheral configuration */
+
+/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0 2U
+#define MAC_ADDR1 0U
+#define MAC_ADDR2 0U
+#define MAC_ADDR3 0U
+#define MAC_ADDR4 0U
+#define MAC_ADDR5 0U
+
+/* Definition of the Ethernet driver buffers size and count */
+#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
+#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
+#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
+#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
+
+/* Section 2: PHY configuration section */
+
+/* DP83848_PHY_ADDRESS Address*/
+#define DP83848_PHY_ADDRESS 0x01U
+/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
+#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
+/* PHY Configuration delay */
+#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
+
+#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
+#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
+
+/* Section 3: Common PHY Registers */
+
+#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
+#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
+
+#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
+#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
+#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
+#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
+#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
+#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
+
+#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
+#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
+#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
+
+/* Section 4: Extended PHY Registers */
+#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
+
+#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
+#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+* Activated: CRC code is present inside driver
+* Deactivated: CRC code cleaned from driver
+*/
+
+#define USE_SPI_CRC 0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+ #include "stm32f4xx_hal_exti.h"
+#endif /* HAL_EXTI_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32f4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32f4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32f4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+ #include "stm32f4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32f4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32f4xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma2d.h"
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+ #include "stm32f4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dcmi.h"
+#endif /* HAL_DCMI_MODULE_ENABLED */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+ #include "stm32f4xx_hal_eth.h"
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+ #include "stm32f4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+ #include "stm32f4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_PCCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pccard.h"
+#endif /* HAL_PCCARD_MODULE_ENABLED */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sdram.h"
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_hash.h"
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+ #include "stm32f4xx_hal_ltdc.h"
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32f4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32f4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32f4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32f4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_MMC_MODULE_ENABLED
+ #include "stm32f4xx_hal_mmc.h"
+#endif /* HAL_MMC_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32f4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32f4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32f4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+#ifdef HAL_DSI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dsi.h"
+#endif /* HAL_DSI_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_CEC_MODULE_ENABLED
+ #include "stm32f4xx_hal_cec.h"
+#endif /* HAL_CEC_MODULE_ENABLED */
+
+#ifdef HAL_FMPI2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_fmpi2c.h"
+#endif /* HAL_FMPI2C_MODULE_ENABLED */
+
+#ifdef HAL_SPDIFRX_MODULE_ENABLED
+ #include "stm32f4xx_hal_spdifrx.h"
+#endif /* HAL_SPDIFRX_MODULE_ENABLED */
+
+#ifdef HAL_DFSDM_MODULE_ENABLED
+ #include "stm32f4xx_hal_dfsdm.h"
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_HAL_CONF_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32f4/boards/startup_stm32f405xx.s b/ports/stm32f4/boards/startup_stm32f405xx.s
new file mode 100644
index 000000000..6b77655ca
--- /dev/null
+++ b/ports/stm32f4/boards/startup_stm32f405xx.s
@@ -0,0 +1,516 @@
+/**
+ ******************************************************************************
+ * @file startup_stm32f405xx.s
+ * @author MCD Application Team
+ * @brief STM32F405xx Devices vector table for GCC based toolchains.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M4 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2017 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+ .syntax unified
+ .cpu cortex-m4
+ .fpu softvfp
+ .thumb
+
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
+
+/**
+ * @brief This is the code that gets called when the processor first
+ * starts execution following a reset event. Only the absolutely
+ * necessary set is performed, after which the application
+ * supplied main() routine is called.
+ * @param None
+ * @retval : None
+*/
+
+ .section .text.Reset_Handler
+ .weak Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ ldr sp, =_estack /* set stack pointer */
+
+/* Copy the data segment initializers from flash to SRAM */
+ movs r1, #0
+ b LoopCopyDataInit
+
+CopyDataInit:
+ ldr r3, =_sidata
+ ldr r3, [r3, r1]
+ str r3, [r0, r1]
+ adds r1, r1, #4
+
+LoopCopyDataInit:
+ ldr r0, =_sdata
+ ldr r3, =_edata
+ adds r2, r0, r1
+ cmp r2, r3
+ bcc CopyDataInit
+ ldr r2, =_sbss
+ b LoopFillZerobss
+/* Zero fill the bss segment. */
+FillZerobss:
+ movs r3, #0
+ str r3, [r2], #4
+
+LoopFillZerobss:
+ ldr r3, = _ebss
+ cmp r2, r3
+ bcc FillZerobss
+
+/* Call the clock system intitialization function.*/
+ bl SystemInit
+/* Call static constructors */
+/* bl __libc_init_array */
+/* Call the application's entry point.*/
+ bl main
+ bx lr
+.size Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief This is the code that gets called when the processor receives an
+ * unexpected interrupt. This simply enters an infinite loop, preserving
+ * the system state for examination by a debugger.
+ * @param None
+ * @retval None
+*/
+ .section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+*******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+ .size g_pfnVectors, .-g_pfnVectors
+
+
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word MemManage_Handler
+ .word BusFault_Handler
+ .word UsageFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word DebugMon_Handler
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+
+ /* External Interrupts */
+ .word WWDG_IRQHandler /* Window WatchDog */
+ .word PVD_IRQHandler /* PVD through EXTI Line detection */
+ .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
+ .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
+ .word FLASH_IRQHandler /* FLASH */
+ .word RCC_IRQHandler /* RCC */
+ .word EXTI0_IRQHandler /* EXTI Line0 */
+ .word EXTI1_IRQHandler /* EXTI Line1 */
+ .word EXTI2_IRQHandler /* EXTI Line2 */
+ .word EXTI3_IRQHandler /* EXTI Line3 */
+ .word EXTI4_IRQHandler /* EXTI Line4 */
+ .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
+ .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
+ .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
+ .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
+ .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
+ .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
+ .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
+ .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
+ .word CAN1_TX_IRQHandler /* CAN1 TX */
+ .word CAN1_RX0_IRQHandler /* CAN1 RX0 */
+ .word CAN1_RX1_IRQHandler /* CAN1 RX1 */
+ .word CAN1_SCE_IRQHandler /* CAN1 SCE */
+ .word EXTI9_5_IRQHandler /* External Line[9:5]s */
+ .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
+ .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
+ .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
+ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
+ .word TIM2_IRQHandler /* TIM2 */
+ .word TIM3_IRQHandler /* TIM3 */
+ .word TIM4_IRQHandler /* TIM4 */
+ .word I2C1_EV_IRQHandler /* I2C1 Event */
+ .word I2C1_ER_IRQHandler /* I2C1 Error */
+ .word I2C2_EV_IRQHandler /* I2C2 Event */
+ .word I2C2_ER_IRQHandler /* I2C2 Error */
+ .word SPI1_IRQHandler /* SPI1 */
+ .word SPI2_IRQHandler /* SPI2 */
+ .word USART1_IRQHandler /* USART1 */
+ .word USART2_IRQHandler /* USART2 */
+ .word USART3_IRQHandler /* USART3 */
+ .word EXTI15_10_IRQHandler /* External Line[15:10]s */
+ .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
+ .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
+ .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
+ .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
+ .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
+ .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
+ .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
+ .word FSMC_IRQHandler /* FSMC */
+ .word SDIO_IRQHandler /* SDIO */
+ .word TIM5_IRQHandler /* TIM5 */
+ .word SPI3_IRQHandler /* SPI3 */
+ .word UART4_IRQHandler /* UART4 */
+ .word UART5_IRQHandler /* UART5 */
+ .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
+ .word TIM7_IRQHandler /* TIM7 */
+ .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
+ .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
+ .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
+ .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
+ .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word CAN2_TX_IRQHandler /* CAN2 TX */
+ .word CAN2_RX0_IRQHandler /* CAN2 RX0 */
+ .word CAN2_RX1_IRQHandler /* CAN2 RX1 */
+ .word CAN2_SCE_IRQHandler /* CAN2 SCE */
+ .word OTG_FS_IRQHandler /* USB OTG FS */
+ .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
+ .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
+ .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
+ .word USART6_IRQHandler /* USART6 */
+ .word I2C3_EV_IRQHandler /* I2C3 event */
+ .word I2C3_ER_IRQHandler /* I2C3 error */
+ .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
+ .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
+ .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
+ .word OTG_HS_IRQHandler /* USB OTG HS */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word HASH_RNG_IRQHandler /* Hash and Rng */
+ .word FPU_IRQHandler /* FPU */
+
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+ .weak NMI_Handler
+ .thumb_set NMI_Handler,Default_Handler
+
+ .weak HardFault_Handler
+ .thumb_set HardFault_Handler,Default_Handler
+
+ .weak MemManage_Handler
+ .thumb_set MemManage_Handler,Default_Handler
+
+ .weak BusFault_Handler
+ .thumb_set BusFault_Handler,Default_Handler
+
+ .weak UsageFault_Handler
+ .thumb_set UsageFault_Handler,Default_Handler
+
+ .weak SVC_Handler
+ .thumb_set SVC_Handler,Default_Handler
+
+ .weak DebugMon_Handler
+ .thumb_set DebugMon_Handler,Default_Handler
+
+ .weak PendSV_Handler
+ .thumb_set PendSV_Handler,Default_Handler
+
+ .weak SysTick_Handler
+ .thumb_set SysTick_Handler,Default_Handler
+
+ .weak WWDG_IRQHandler
+ .thumb_set WWDG_IRQHandler,Default_Handler
+
+ .weak PVD_IRQHandler
+ .thumb_set PVD_IRQHandler,Default_Handler
+
+ .weak TAMP_STAMP_IRQHandler
+ .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
+
+ .weak RTC_WKUP_IRQHandler
+ .thumb_set RTC_WKUP_IRQHandler,Default_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Default_Handler
+
+ .weak RCC_IRQHandler
+ .thumb_set RCC_IRQHandler,Default_Handler
+
+ .weak EXTI0_IRQHandler
+ .thumb_set EXTI0_IRQHandler,Default_Handler
+
+ .weak EXTI1_IRQHandler
+ .thumb_set EXTI1_IRQHandler,Default_Handler
+
+ .weak EXTI2_IRQHandler
+ .thumb_set EXTI2_IRQHandler,Default_Handler
+
+ .weak EXTI3_IRQHandler
+ .thumb_set EXTI3_IRQHandler,Default_Handler
+
+ .weak EXTI4_IRQHandler
+ .thumb_set EXTI4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream0_IRQHandler
+ .thumb_set DMA1_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream1_IRQHandler
+ .thumb_set DMA1_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream2_IRQHandler
+ .thumb_set DMA1_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream3_IRQHandler
+ .thumb_set DMA1_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream4_IRQHandler
+ .thumb_set DMA1_Stream4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream5_IRQHandler
+ .thumb_set DMA1_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream6_IRQHandler
+ .thumb_set DMA1_Stream6_IRQHandler,Default_Handler
+
+ .weak ADC_IRQHandler
+ .thumb_set ADC_IRQHandler,Default_Handler
+
+ .weak CAN1_TX_IRQHandler
+ .thumb_set CAN1_TX_IRQHandler,Default_Handler
+
+ .weak CAN1_RX0_IRQHandler
+ .thumb_set CAN1_RX0_IRQHandler,Default_Handler
+
+ .weak CAN1_RX1_IRQHandler
+ .thumb_set CAN1_RX1_IRQHandler,Default_Handler
+
+ .weak CAN1_SCE_IRQHandler
+ .thumb_set CAN1_SCE_IRQHandler,Default_Handler
+
+ .weak EXTI9_5_IRQHandler
+ .thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+ .weak TIM1_BRK_TIM9_IRQHandler
+ .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
+
+ .weak TIM1_UP_TIM10_IRQHandler
+ .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
+
+ .weak TIM1_TRG_COM_TIM11_IRQHandler
+ .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
+
+ .weak TIM1_CC_IRQHandler
+ .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+ .weak TIM2_IRQHandler
+ .thumb_set TIM2_IRQHandler,Default_Handler
+
+ .weak TIM3_IRQHandler
+ .thumb_set TIM3_IRQHandler,Default_Handler
+
+ .weak TIM4_IRQHandler
+ .thumb_set TIM4_IRQHandler,Default_Handler
+
+ .weak I2C1_EV_IRQHandler
+ .thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+ .weak I2C1_ER_IRQHandler
+ .thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+ .weak I2C2_EV_IRQHandler
+ .thumb_set I2C2_EV_IRQHandler,Default_Handler
+
+ .weak I2C2_ER_IRQHandler
+ .thumb_set I2C2_ER_IRQHandler,Default_Handler
+
+ .weak SPI1_IRQHandler
+ .thumb_set SPI1_IRQHandler,Default_Handler
+
+ .weak SPI2_IRQHandler
+ .thumb_set SPI2_IRQHandler,Default_Handler
+
+ .weak USART1_IRQHandler
+ .thumb_set USART1_IRQHandler,Default_Handler
+
+ .weak USART2_IRQHandler
+ .thumb_set USART2_IRQHandler,Default_Handler
+
+ .weak USART3_IRQHandler
+ .thumb_set USART3_IRQHandler,Default_Handler
+
+ .weak EXTI15_10_IRQHandler
+ .thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+ .weak RTC_Alarm_IRQHandler
+ .thumb_set RTC_Alarm_IRQHandler,Default_Handler
+
+ .weak OTG_FS_WKUP_IRQHandler
+ .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
+
+ .weak TIM8_BRK_TIM12_IRQHandler
+ .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
+
+ .weak TIM8_UP_TIM13_IRQHandler
+ .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
+
+ .weak TIM8_TRG_COM_TIM14_IRQHandler
+ .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
+
+ .weak TIM8_CC_IRQHandler
+ .thumb_set TIM8_CC_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream7_IRQHandler
+ .thumb_set DMA1_Stream7_IRQHandler,Default_Handler
+
+ .weak FSMC_IRQHandler
+ .thumb_set FSMC_IRQHandler,Default_Handler
+
+ .weak SDIO_IRQHandler
+ .thumb_set SDIO_IRQHandler,Default_Handler
+
+ .weak TIM5_IRQHandler
+ .thumb_set TIM5_IRQHandler,Default_Handler
+
+ .weak SPI3_IRQHandler
+ .thumb_set SPI3_IRQHandler,Default_Handler
+
+ .weak UART4_IRQHandler
+ .thumb_set UART4_IRQHandler,Default_Handler
+
+ .weak UART5_IRQHandler
+ .thumb_set UART5_IRQHandler,Default_Handler
+
+ .weak TIM6_DAC_IRQHandler
+ .thumb_set TIM6_DAC_IRQHandler,Default_Handler
+
+ .weak TIM7_IRQHandler
+ .thumb_set TIM7_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream0_IRQHandler
+ .thumb_set DMA2_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream1_IRQHandler
+ .thumb_set DMA2_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream2_IRQHandler
+ .thumb_set DMA2_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream3_IRQHandler
+ .thumb_set DMA2_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream4_IRQHandler
+ .thumb_set DMA2_Stream4_IRQHandler,Default_Handler
+
+ .weak CAN2_TX_IRQHandler
+ .thumb_set CAN2_TX_IRQHandler,Default_Handler
+
+ .weak CAN2_RX0_IRQHandler
+ .thumb_set CAN2_RX0_IRQHandler,Default_Handler
+
+ .weak CAN2_RX1_IRQHandler
+ .thumb_set CAN2_RX1_IRQHandler,Default_Handler
+
+ .weak CAN2_SCE_IRQHandler
+ .thumb_set CAN2_SCE_IRQHandler,Default_Handler
+
+ .weak OTG_FS_IRQHandler
+ .thumb_set OTG_FS_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream5_IRQHandler
+ .thumb_set DMA2_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream6_IRQHandler
+ .thumb_set DMA2_Stream6_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream7_IRQHandler
+ .thumb_set DMA2_Stream7_IRQHandler,Default_Handler
+
+ .weak USART6_IRQHandler
+ .thumb_set USART6_IRQHandler,Default_Handler
+
+ .weak I2C3_EV_IRQHandler
+ .thumb_set I2C3_EV_IRQHandler,Default_Handler
+
+ .weak I2C3_ER_IRQHandler
+ .thumb_set I2C3_ER_IRQHandler,Default_Handler
+
+ .weak OTG_HS_EP1_OUT_IRQHandler
+ .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
+
+ .weak OTG_HS_EP1_IN_IRQHandler
+ .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
+
+ .weak OTG_HS_WKUP_IRQHandler
+ .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
+
+ .weak OTG_HS_IRQHandler
+ .thumb_set OTG_HS_IRQHandler,Default_Handler
+
+ .weak HASH_RNG_IRQHandler
+ .thumb_set HASH_RNG_IRQHandler,Default_Handler
+
+ .weak FPU_IRQHandler
+ .thumb_set FPU_IRQHandler,Default_Handler
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
diff --git a/ports/stm32f4/boards/startup_stm32f411xe.s b/ports/stm32f4/boards/startup_stm32f411xe.s
new file mode 100644
index 000000000..3aac640cb
--- /dev/null
+++ b/ports/stm32f4/boards/startup_stm32f411xe.s
@@ -0,0 +1,452 @@
+/**
+ ******************************************************************************
+ * @file startup_stm32f411xe.s
+ * @author MCD Application Team
+ * @brief STM32F411xExx Devices vector table for GCC based toolchains.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M4 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2017 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+ .syntax unified
+ .cpu cortex-m4
+ .fpu softvfp
+ .thumb
+
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
+
+/**
+ * @brief This is the code that gets called when the processor first
+ * starts execution following a reset event. Only the absolutely
+ * necessary set is performed, after which the application
+ * supplied main() routine is called.
+ * @param None
+ * @retval : None
+*/
+
+ .section .text.Reset_Handler
+ .weak Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ ldr sp, =_estack /* set stack pointer */
+
+/* Copy the data segment initializers from flash to SRAM */
+ movs r1, #0
+ b LoopCopyDataInit
+
+CopyDataInit:
+ ldr r3, =_sidata
+ ldr r3, [r3, r1]
+ str r3, [r0, r1]
+ adds r1, r1, #4
+
+LoopCopyDataInit:
+ ldr r0, =_sdata
+ ldr r3, =_edata
+ adds r2, r0, r1
+ cmp r2, r3
+ bcc CopyDataInit
+ ldr r2, =_sbss
+ b LoopFillZerobss
+/* Zero fill the bss segment. */
+FillZerobss:
+ movs r3, #0
+ str r3, [r2], #4
+
+LoopFillZerobss:
+ ldr r3, = _ebss
+ cmp r2, r3
+ bcc FillZerobss
+
+/* Call the clock system intitialization function.*/
+ bl SystemInit
+/* Call static constructors */
+/* bl __libc_init_array */
+/* Call the application's entry point.*/
+ bl main
+ bx lr
+.size Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief This is the code that gets called when the processor receives an
+ * unexpected interrupt. This simply enters an infinite loop, preserving
+ * the system state for examination by a debugger.
+ * @param None
+ * @retval None
+*/
+ .section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+*******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+ .size g_pfnVectors, .-g_pfnVectors
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word MemManage_Handler
+ .word BusFault_Handler
+ .word UsageFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word DebugMon_Handler
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+
+ /* External Interrupts */
+ .word WWDG_IRQHandler /* Window WatchDog */
+ .word PVD_IRQHandler /* PVD through EXTI Line detection */
+ .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
+ .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
+ .word FLASH_IRQHandler /* FLASH */
+ .word RCC_IRQHandler /* RCC */
+ .word EXTI0_IRQHandler /* EXTI Line0 */
+ .word EXTI1_IRQHandler /* EXTI Line1 */
+ .word EXTI2_IRQHandler /* EXTI Line2 */
+ .word EXTI3_IRQHandler /* EXTI Line3 */
+ .word EXTI4_IRQHandler /* EXTI Line4 */
+ .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
+ .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
+ .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
+ .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
+ .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
+ .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
+ .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
+ .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word EXTI9_5_IRQHandler /* External Line[9:5]s */
+ .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
+ .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
+ .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
+ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
+ .word TIM2_IRQHandler /* TIM2 */
+ .word TIM3_IRQHandler /* TIM3 */
+ .word TIM4_IRQHandler /* TIM4 */
+ .word I2C1_EV_IRQHandler /* I2C1 Event */
+ .word I2C1_ER_IRQHandler /* I2C1 Error */
+ .word I2C2_EV_IRQHandler /* I2C2 Event */
+ .word I2C2_ER_IRQHandler /* I2C2 Error */
+ .word SPI1_IRQHandler /* SPI1 */
+ .word SPI2_IRQHandler /* SPI2 */
+ .word USART1_IRQHandler /* USART1 */
+ .word USART2_IRQHandler /* USART2 */
+ .word 0 /* Reserved */
+ .word EXTI15_10_IRQHandler /* External Line[15:10]s */
+ .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
+ .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
+ .word 0 /* Reserved */
+ .word SDIO_IRQHandler /* SDIO */
+ .word TIM5_IRQHandler /* TIM5 */
+ .word SPI3_IRQHandler /* SPI3 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
+ .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
+ .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
+ .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
+ .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word OTG_FS_IRQHandler /* USB OTG FS */
+ .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
+ .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
+ .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
+ .word USART6_IRQHandler /* USART6 */
+ .word I2C3_EV_IRQHandler /* I2C3 event */
+ .word I2C3_ER_IRQHandler /* I2C3 error */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word FPU_IRQHandler /* FPU */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word SPI4_IRQHandler /* SPI4 */
+ .word SPI5_IRQHandler /* SPI5 */
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+ .weak NMI_Handler
+ .thumb_set NMI_Handler,Default_Handler
+
+ .weak HardFault_Handler
+ .thumb_set HardFault_Handler,Default_Handler
+
+ .weak MemManage_Handler
+ .thumb_set MemManage_Handler,Default_Handler
+
+ .weak BusFault_Handler
+ .thumb_set BusFault_Handler,Default_Handler
+
+ .weak UsageFault_Handler
+ .thumb_set UsageFault_Handler,Default_Handler
+
+ .weak SVC_Handler
+ .thumb_set SVC_Handler,Default_Handler
+
+ .weak DebugMon_Handler
+ .thumb_set DebugMon_Handler,Default_Handler
+
+ .weak PendSV_Handler
+ .thumb_set PendSV_Handler,Default_Handler
+
+ .weak SysTick_Handler
+ .thumb_set SysTick_Handler,Default_Handler
+
+ .weak WWDG_IRQHandler
+ .thumb_set WWDG_IRQHandler,Default_Handler
+
+ .weak PVD_IRQHandler
+ .thumb_set PVD_IRQHandler,Default_Handler
+
+ .weak TAMP_STAMP_IRQHandler
+ .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
+
+ .weak RTC_WKUP_IRQHandler
+ .thumb_set RTC_WKUP_IRQHandler,Default_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Default_Handler
+
+ .weak RCC_IRQHandler
+ .thumb_set RCC_IRQHandler,Default_Handler
+
+ .weak EXTI0_IRQHandler
+ .thumb_set EXTI0_IRQHandler,Default_Handler
+
+ .weak EXTI1_IRQHandler
+ .thumb_set EXTI1_IRQHandler,Default_Handler
+
+ .weak EXTI2_IRQHandler
+ .thumb_set EXTI2_IRQHandler,Default_Handler
+
+ .weak EXTI3_IRQHandler
+ .thumb_set EXTI3_IRQHandler,Default_Handler
+
+ .weak EXTI4_IRQHandler
+ .thumb_set EXTI4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream0_IRQHandler
+ .thumb_set DMA1_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream1_IRQHandler
+ .thumb_set DMA1_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream2_IRQHandler
+ .thumb_set DMA1_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream3_IRQHandler
+ .thumb_set DMA1_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream4_IRQHandler
+ .thumb_set DMA1_Stream4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream5_IRQHandler
+ .thumb_set DMA1_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream6_IRQHandler
+ .thumb_set DMA1_Stream6_IRQHandler,Default_Handler
+
+ .weak ADC_IRQHandler
+ .thumb_set ADC_IRQHandler,Default_Handler
+
+ .weak EXTI9_5_IRQHandler
+ .thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+ .weak TIM1_BRK_TIM9_IRQHandler
+ .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
+
+ .weak TIM1_UP_TIM10_IRQHandler
+ .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
+
+ .weak TIM1_TRG_COM_TIM11_IRQHandler
+ .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
+
+ .weak TIM1_CC_IRQHandler
+ .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+ .weak TIM2_IRQHandler
+ .thumb_set TIM2_IRQHandler,Default_Handler
+
+ .weak TIM3_IRQHandler
+ .thumb_set TIM3_IRQHandler,Default_Handler
+
+ .weak TIM4_IRQHandler
+ .thumb_set TIM4_IRQHandler,Default_Handler
+
+ .weak I2C1_EV_IRQHandler
+ .thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+ .weak I2C1_ER_IRQHandler
+ .thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+ .weak I2C2_EV_IRQHandler
+ .thumb_set I2C2_EV_IRQHandler,Default_Handler
+
+ .weak I2C2_ER_IRQHandler
+ .thumb_set I2C2_ER_IRQHandler,Default_Handler
+
+ .weak SPI1_IRQHandler
+ .thumb_set SPI1_IRQHandler,Default_Handler
+
+ .weak SPI2_IRQHandler
+ .thumb_set SPI2_IRQHandler,Default_Handler
+
+ .weak USART1_IRQHandler
+ .thumb_set USART1_IRQHandler,Default_Handler
+
+ .weak USART2_IRQHandler
+ .thumb_set USART2_IRQHandler,Default_Handler
+
+ .weak EXTI15_10_IRQHandler
+ .thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+ .weak RTC_Alarm_IRQHandler
+ .thumb_set RTC_Alarm_IRQHandler,Default_Handler
+
+ .weak OTG_FS_WKUP_IRQHandler
+ .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream7_IRQHandler
+ .thumb_set DMA1_Stream7_IRQHandler,Default_Handler
+
+ .weak SDIO_IRQHandler
+ .thumb_set SDIO_IRQHandler,Default_Handler
+
+ .weak TIM5_IRQHandler
+ .thumb_set TIM5_IRQHandler,Default_Handler
+
+ .weak SPI3_IRQHandler
+ .thumb_set SPI3_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream0_IRQHandler
+ .thumb_set DMA2_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream1_IRQHandler
+ .thumb_set DMA2_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream2_IRQHandler
+ .thumb_set DMA2_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream3_IRQHandler
+ .thumb_set DMA2_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream4_IRQHandler
+ .thumb_set DMA2_Stream4_IRQHandler,Default_Handler
+
+ .weak OTG_FS_IRQHandler
+ .thumb_set OTG_FS_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream5_IRQHandler
+ .thumb_set DMA2_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream6_IRQHandler
+ .thumb_set DMA2_Stream6_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream7_IRQHandler
+ .thumb_set DMA2_Stream7_IRQHandler,Default_Handler
+
+ .weak USART6_IRQHandler
+ .thumb_set USART6_IRQHandler,Default_Handler
+
+ .weak I2C3_EV_IRQHandler
+ .thumb_set I2C3_EV_IRQHandler,Default_Handler
+
+ .weak I2C3_ER_IRQHandler
+ .thumb_set I2C3_ER_IRQHandler,Default_Handler
+
+ .weak FPU_IRQHandler
+ .thumb_set FPU_IRQHandler,Default_Handler
+
+ .weak SPI4_IRQHandler
+ .thumb_set SPI4_IRQHandler,Default_Handler
+
+ .weak SPI5_IRQHandler
+ .thumb_set SPI5_IRQHandler,Default_Handler
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/ports/stm32f4/boards/startup_stm32f412zx.s b/ports/stm32f4/boards/startup_stm32f412zx.s
new file mode 100644
index 000000000..801220795
--- /dev/null
+++ b/ports/stm32f4/boards/startup_stm32f412zx.s
@@ -0,0 +1,524 @@
+/**
+ ******************************************************************************
+ * @file startup_stm32f412zx.s
+ * @author MCD Application Team
+ * @brief STM32F412Zx Devices vector table for GCC based toolchains.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M4 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2017 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+ .syntax unified
+ .cpu cortex-m4
+ .fpu softvfp
+ .thumb
+
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
+
+/**
+ * @brief This is the code that gets called when the processor first
+ * starts execution following a reset event. Only the absolutely
+ * necessary set is performed, after which the application
+ * supplied main() routine is called.
+ * @param None
+ * @retval : None
+*/
+
+ .section .text.Reset_Handler
+ .weak Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ ldr sp, =_estack /* set stack pointer */
+
+/* Copy the data segment initializers from flash to SRAM */
+ movs r1, #0
+ b LoopCopyDataInit
+
+CopyDataInit:
+ ldr r3, =_sidata
+ ldr r3, [r3, r1]
+ str r3, [r0, r1]
+ adds r1, r1, #4
+
+LoopCopyDataInit:
+ ldr r0, =_sdata
+ ldr r3, =_edata
+ adds r2, r0, r1
+ cmp r2, r3
+ bcc CopyDataInit
+ ldr r2, =_sbss
+ b LoopFillZerobss
+/* Zero fill the bss segment. */
+FillZerobss:
+ movs r3, #0
+ str r3, [r2], #4
+
+LoopFillZerobss:
+ ldr r3, = _ebss
+ cmp r2, r3
+ bcc FillZerobss
+
+/* Call the clock system intitialization function.*/
+ bl SystemInit
+/* Call static constructors */
+/* bl __libc_init_array */
+/* Call the application's entry point.*/
+ bl main
+ bx lr
+.size Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief This is the code that gets called when the processor receives an
+ * unexpected interrupt. This simply enters an infinite loop, preserving
+ * the system state for examination by a debugger.
+ * @param None
+ * @retval None
+*/
+ .section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M3. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+*******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+ .size g_pfnVectors, .-g_pfnVectors
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word MemManage_Handler
+ .word BusFault_Handler
+ .word UsageFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word DebugMon_Handler
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+
+ /* External Interrupts */
+ .word WWDG_IRQHandler /* Window WatchDog */
+ .word PVD_IRQHandler /* PVD through EXTI Line detection */
+ .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
+ .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
+ .word FLASH_IRQHandler /* FLASH */
+ .word RCC_IRQHandler /* RCC */
+ .word EXTI0_IRQHandler /* EXTI Line0 */
+ .word EXTI1_IRQHandler /* EXTI Line1 */
+ .word EXTI2_IRQHandler /* EXTI Line2 */
+ .word EXTI3_IRQHandler /* EXTI Line3 */
+ .word EXTI4_IRQHandler /* EXTI Line4 */
+ .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
+ .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
+ .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
+ .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
+ .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
+ .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
+ .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
+ .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
+ .word CAN1_TX_IRQHandler /* CAN1 TX */
+ .word CAN1_RX0_IRQHandler /* CAN1 RX0 */
+ .word CAN1_RX1_IRQHandler /* CAN1 RX1 */
+ .word CAN1_SCE_IRQHandler /* CAN1 SCE */
+ .word EXTI9_5_IRQHandler /* External Line[9:5]s */
+ .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
+ .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
+ .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
+ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
+ .word TIM2_IRQHandler /* TIM2 */
+ .word TIM3_IRQHandler /* TIM3 */
+ .word TIM4_IRQHandler /* TIM4 */
+ .word I2C1_EV_IRQHandler /* I2C1 Event */
+ .word I2C1_ER_IRQHandler /* I2C1 Error */
+ .word I2C2_EV_IRQHandler /* I2C2 Event */
+ .word I2C2_ER_IRQHandler /* I2C2 Error */
+ .word SPI1_IRQHandler /* SPI1 */
+ .word SPI2_IRQHandler /* SPI2 */
+ .word USART1_IRQHandler /* USART1 */
+ .word USART2_IRQHandler /* USART2 */
+ .word USART3_IRQHandler /* USART3 */
+ .word EXTI15_10_IRQHandler /* External Line[15:10]s */
+ .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
+ .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
+ .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
+ .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
+ .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
+ .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
+ .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
+ .word 0 /* Reserved */
+ .word SDIO_IRQHandler /* SDIO */
+ .word TIM5_IRQHandler /* TIM5 */
+ .word SPI3_IRQHandler /* SPI3 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word TIM6_IRQHandler /* TIM6 */
+ .word TIM7_IRQHandler /* TIM7 */
+ .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
+ .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
+ .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
+ .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
+ .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
+ .word DFSDM1_FLT0_IRQHandler /* DFSDM1 Filter0 */
+ .word DFSDM1_FLT1_IRQHandler /* DFSDM1 Filter1 */
+ .word CAN2_TX_IRQHandler /* CAN2 TX */
+ .word CAN2_RX0_IRQHandler /* CAN2 RX0 */
+ .word CAN2_RX1_IRQHandler /* CAN2 RX1 */
+ .word CAN2_SCE_IRQHandler /* CAN2 SCE */
+ .word OTG_FS_IRQHandler /* USB OTG FS */
+ .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
+ .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
+ .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
+ .word USART6_IRQHandler /* USART6 */
+ .word I2C3_EV_IRQHandler /* I2C3 event */
+ .word I2C3_ER_IRQHandler /* I2C3 error */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word RNG_IRQHandler /* RNG */
+ .word FPU_IRQHandler /* FPU */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word SPI4_IRQHandler /* SPI4 */
+ .word SPI5_IRQHandler /* SPI5 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word QUADSPI_IRQHandler /* QuadSPI */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word FMPI2C1_EV_IRQHandler /* FMPI2C1 Event */
+ .word FMPI2C1_ER_IRQHandler /* FMPI2C1 Error */
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+ .weak NMI_Handler
+ .thumb_set NMI_Handler,Default_Handler
+
+ .weak HardFault_Handler
+ .thumb_set HardFault_Handler,Default_Handler
+
+ .weak MemManage_Handler
+ .thumb_set MemManage_Handler,Default_Handler
+
+ .weak BusFault_Handler
+ .thumb_set BusFault_Handler,Default_Handler
+
+ .weak UsageFault_Handler
+ .thumb_set UsageFault_Handler,Default_Handler
+
+ .weak SVC_Handler
+ .thumb_set SVC_Handler,Default_Handler
+
+ .weak DebugMon_Handler
+ .thumb_set DebugMon_Handler,Default_Handler
+
+ .weak PendSV_Handler
+ .thumb_set PendSV_Handler,Default_Handler
+
+ .weak SysTick_Handler
+ .thumb_set SysTick_Handler,Default_Handler
+
+ .weak WWDG_IRQHandler
+ .thumb_set WWDG_IRQHandler,Default_Handler
+
+ .weak PVD_IRQHandler
+ .thumb_set PVD_IRQHandler,Default_Handler
+
+ .weak TAMP_STAMP_IRQHandler
+ .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
+
+ .weak RTC_WKUP_IRQHandler
+ .thumb_set RTC_WKUP_IRQHandler,Default_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Default_Handler
+
+ .weak RCC_IRQHandler
+ .thumb_set RCC_IRQHandler,Default_Handler
+
+ .weak EXTI0_IRQHandler
+ .thumb_set EXTI0_IRQHandler,Default_Handler
+
+ .weak EXTI1_IRQHandler
+ .thumb_set EXTI1_IRQHandler,Default_Handler
+
+ .weak EXTI2_IRQHandler
+ .thumb_set EXTI2_IRQHandler,Default_Handler
+
+ .weak EXTI3_IRQHandler
+ .thumb_set EXTI3_IRQHandler,Default_Handler
+
+ .weak EXTI4_IRQHandler
+ .thumb_set EXTI4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream0_IRQHandler
+ .thumb_set DMA1_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream1_IRQHandler
+ .thumb_set DMA1_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream2_IRQHandler
+ .thumb_set DMA1_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream3_IRQHandler
+ .thumb_set DMA1_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream4_IRQHandler
+ .thumb_set DMA1_Stream4_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream5_IRQHandler
+ .thumb_set DMA1_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream6_IRQHandler
+ .thumb_set DMA1_Stream6_IRQHandler,Default_Handler
+
+ .weak ADC_IRQHandler
+ .thumb_set ADC_IRQHandler,Default_Handler
+
+ .weak CAN1_TX_IRQHandler
+ .thumb_set CAN1_TX_IRQHandler,Default_Handler
+
+ .weak CAN1_RX0_IRQHandler
+ .thumb_set CAN1_RX0_IRQHandler,Default_Handler
+
+ .weak CAN1_RX1_IRQHandler
+ .thumb_set CAN1_RX1_IRQHandler,Default_Handler
+
+ .weak CAN1_SCE_IRQHandler
+ .thumb_set CAN1_SCE_IRQHandler,Default_Handler
+
+ .weak EXTI9_5_IRQHandler
+ .thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+ .weak TIM1_BRK_TIM9_IRQHandler
+ .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
+
+ .weak TIM1_UP_TIM10_IRQHandler
+ .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
+
+ .weak TIM1_TRG_COM_TIM11_IRQHandler
+ .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
+
+ .weak TIM1_CC_IRQHandler
+ .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+ .weak TIM2_IRQHandler
+ .thumb_set TIM2_IRQHandler,Default_Handler
+
+ .weak TIM3_IRQHandler
+ .thumb_set TIM3_IRQHandler,Default_Handler
+
+ .weak TIM4_IRQHandler
+ .thumb_set TIM4_IRQHandler,Default_Handler
+
+ .weak I2C1_EV_IRQHandler
+ .thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+ .weak I2C1_ER_IRQHandler
+ .thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+ .weak I2C2_EV_IRQHandler
+ .thumb_set I2C2_EV_IRQHandler,Default_Handler
+
+ .weak I2C2_ER_IRQHandler
+ .thumb_set I2C2_ER_IRQHandler,Default_Handler
+
+ .weak SPI1_IRQHandler
+ .thumb_set SPI1_IRQHandler,Default_Handler
+
+ .weak SPI2_IRQHandler
+ .thumb_set SPI2_IRQHandler,Default_Handler
+
+ .weak USART1_IRQHandler
+ .thumb_set USART1_IRQHandler,Default_Handler
+
+ .weak USART2_IRQHandler
+ .thumb_set USART2_IRQHandler,Default_Handler
+
+ .weak USART3_IRQHandler
+ .thumb_set USART3_IRQHandler,Default_Handler
+
+ .weak EXTI15_10_IRQHandler
+ .thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+ .weak RTC_Alarm_IRQHandler
+ .thumb_set RTC_Alarm_IRQHandler,Default_Handler
+
+ .weak OTG_FS_WKUP_IRQHandler
+ .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
+
+ .weak TIM8_BRK_TIM12_IRQHandler
+ .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
+
+ .weak TIM8_UP_TIM13_IRQHandler
+ .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
+
+ .weak TIM8_TRG_COM_TIM14_IRQHandler
+ .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
+
+ .weak TIM8_CC_IRQHandler
+ .thumb_set TIM8_CC_IRQHandler,Default_Handler
+
+ .weak DMA1_Stream7_IRQHandler
+ .thumb_set DMA1_Stream7_IRQHandler,Default_Handler
+
+ .weak SDIO_IRQHandler
+ .thumb_set SDIO_IRQHandler,Default_Handler
+
+ .weak TIM5_IRQHandler
+ .thumb_set TIM5_IRQHandler,Default_Handler
+
+ .weak SPI3_IRQHandler
+ .thumb_set SPI3_IRQHandler,Default_Handler
+
+ .weak TIM6_IRQHandler
+ .thumb_set TIM6_IRQHandler,Default_Handler
+
+ .weak TIM7_IRQHandler
+ .thumb_set TIM7_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream0_IRQHandler
+ .thumb_set DMA2_Stream0_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream1_IRQHandler
+ .thumb_set DMA2_Stream1_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream2_IRQHandler
+ .thumb_set DMA2_Stream2_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream3_IRQHandler
+ .thumb_set DMA2_Stream3_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream4_IRQHandler
+ .thumb_set DMA2_Stream4_IRQHandler,Default_Handler
+
+ .weak DFSDM1_FLT0_IRQHandler
+ .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler
+
+ .weak DFSDM1_FLT1_IRQHandler
+ .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler
+
+ .weak CAN2_TX_IRQHandler
+ .thumb_set CAN2_TX_IRQHandler,Default_Handler
+
+ .weak CAN2_RX0_IRQHandler
+ .thumb_set CAN2_RX0_IRQHandler,Default_Handler
+
+ .weak CAN2_RX1_IRQHandler
+ .thumb_set CAN2_RX1_IRQHandler,Default_Handler
+
+ .weak CAN2_SCE_IRQHandler
+ .thumb_set CAN2_SCE_IRQHandler,Default_Handler
+
+ .weak OTG_FS_IRQHandler
+ .thumb_set OTG_FS_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream5_IRQHandler
+ .thumb_set DMA2_Stream5_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream6_IRQHandler
+ .thumb_set DMA2_Stream6_IRQHandler,Default_Handler
+
+ .weak DMA2_Stream7_IRQHandler
+ .thumb_set DMA2_Stream7_IRQHandler,Default_Handler
+
+ .weak USART6_IRQHandler
+ .thumb_set USART6_IRQHandler,Default_Handler
+
+ .weak I2C3_EV_IRQHandler
+ .thumb_set I2C3_EV_IRQHandler,Default_Handler
+
+ .weak I2C3_ER_IRQHandler
+ .thumb_set I2C3_ER_IRQHandler,Default_Handler
+
+ .weak RNG_IRQHandler
+ .thumb_set RNG_IRQHandler,Default_Handler
+
+ .weak FPU_IRQHandler
+ .thumb_set FPU_IRQHandler,Default_Handler
+
+ .weak SPI4_IRQHandler
+ .thumb_set SPI4_IRQHandler,Default_Handler
+
+ .weak SPI5_IRQHandler
+ .thumb_set SPI5_IRQHandler,Default_Handler
+
+ .weak QUADSPI_IRQHandler
+ .thumb_set QUADSPI_IRQHandler,Default_Handler
+
+ .weak FMPI2C1_EV_IRQHandler
+ .thumb_set FMPI2C1_EV_IRQHandler,Default_Handler
+
+ .weak FMPI2C1_ER_IRQHandler
+ .thumb_set FMPI2C1_ER_IRQHandler,Default_Handler
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/board.c b/ports/stm32f4/boards/stm32f411ve_discovery/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f411ve_discovery/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h
new file mode 100644
index 000000000..d5491fe36
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "STM32F411E_DISCO"
+#define MICROPY_HW_MCU_NAME "STM32F411xE"
+
+#define FLASH_SIZE (0x80000) //512K
+#define FLASH_PAGE_SIZE (0x4000) //16K
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x2000 - 0xC000)
+
+#define AUTORESET_DELAY_MS 500
diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.mk b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.mk
new file mode 100644
index 000000000..d6f369b6e
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.mk
@@ -0,0 +1,17 @@
+USB_VID = 0x239A
+USB_PID = 0x805E
+USB_PRODUCT = "STM32F411VE Discovery Board - CPy"
+USB_MANUFACTURER = "STMicroelectronics"
+USB_DEVICES = "CDC,MSC"
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+
+MCU_SERIES = m4
+MCU_VARIANT = stm32f4
+MCU_SUB_VARIANT = stm32f411xe
+MCU_PACKAGE = 100
+CMSIS_MCU = STM32F411xE
+LD_FILE = boards/STM32F411VETx_FLASH.ld
+TEXT0_ADDR = 0x08000000
+TEXT1_ADDR = 0x08020000 \ No newline at end of file
diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/pins.c b/ports/stm32f4/boards/stm32f411ve_discovery/pins.c
new file mode 100644
index 000000000..673c412d5
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f411ve_discovery/pins.c
@@ -0,0 +1,106 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ //P1
+ { MP_ROM_QSTR(MP_QSTR_PC00), MP_ROM_PTR(&pin_PC00) },
+ { MP_ROM_QSTR(MP_QSTR_PC01), MP_ROM_PTR(&pin_PC01) },
+ { MP_ROM_QSTR(MP_QSTR_PC02), MP_ROM_PTR(&pin_PC02) },
+ { MP_ROM_QSTR(MP_QSTR_PC03), MP_ROM_PTR(&pin_PC03) },
+ { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_PC04), MP_ROM_PTR(&pin_PC04) },
+ { MP_ROM_QSTR(MP_QSTR_PC05), MP_ROM_PTR(&pin_PC05) },
+ { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) },
+ { MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_PB02), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_PE07), MP_ROM_PTR(&pin_PE07) },
+ { MP_ROM_QSTR(MP_QSTR_PE08), MP_ROM_PTR(&pin_PE08) },
+ { MP_ROM_QSTR(MP_QSTR_PE09), MP_ROM_PTR(&pin_PE09) },
+ { MP_ROM_QSTR(MP_QSTR_PE10), MP_ROM_PTR(&pin_PE10) },
+ { MP_ROM_QSTR(MP_QSTR_PE11), MP_ROM_PTR(&pin_PE11) },
+ { MP_ROM_QSTR(MP_QSTR_PE12), MP_ROM_PTR(&pin_PE12) },
+ { MP_ROM_QSTR(MP_QSTR_PE13), MP_ROM_PTR(&pin_PE13) },
+ { MP_ROM_QSTR(MP_QSTR_PE14), MP_ROM_PTR(&pin_PE14) },
+ { MP_ROM_QSTR(MP_QSTR_PE15), MP_ROM_PTR(&pin_PE15) },
+ { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) },
+ { MP_ROM_QSTR(MP_QSTR_PD08), MP_ROM_PTR(&pin_PD08) },
+ { MP_ROM_QSTR(MP_QSTR_PD09), MP_ROM_PTR(&pin_PD09) },
+ { MP_ROM_QSTR(MP_QSTR_PD10), MP_ROM_PTR(&pin_PD10) },
+ { MP_ROM_QSTR(MP_QSTR_PD11), MP_ROM_PTR(&pin_PD11) },
+ { MP_ROM_QSTR(MP_QSTR_PD12), MP_ROM_PTR(&pin_PD12) },
+ { MP_ROM_QSTR(MP_QSTR_PD13), MP_ROM_PTR(&pin_PD13) },
+ { MP_ROM_QSTR(MP_QSTR_PD14), MP_ROM_PTR(&pin_PD14) },
+ { MP_ROM_QSTR(MP_QSTR_PD15), MP_ROM_PTR(&pin_PD15) },
+ //P2
+ { MP_ROM_QSTR(MP_QSTR_PC14), MP_ROM_PTR(&pin_PC14) },
+ { MP_ROM_QSTR(MP_QSTR_PC15), MP_ROM_PTR(&pin_PC15) },
+ { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) },
+ { MP_ROM_QSTR(MP_QSTR_PE06), MP_ROM_PTR(&pin_PE06) },
+ { MP_ROM_QSTR(MP_QSTR_PE05), MP_ROM_PTR(&pin_PE05) },
+ { MP_ROM_QSTR(MP_QSTR_PE04), MP_ROM_PTR(&pin_PE04) },
+ { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) },
+ { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) },
+ { MP_ROM_QSTR(MP_QSTR_PE01), MP_ROM_PTR(&pin_PE01) },
+ { MP_ROM_QSTR(MP_QSTR_PE00), MP_ROM_PTR(&pin_PE00) },
+ { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_PD07), MP_ROM_PTR(&pin_PD07) },
+ { MP_ROM_QSTR(MP_QSTR_PD06), MP_ROM_PTR(&pin_PD06) },
+ { MP_ROM_QSTR(MP_QSTR_PD05), MP_ROM_PTR(&pin_PD05) },
+ { MP_ROM_QSTR(MP_QSTR_PD04), MP_ROM_PTR(&pin_PD04) },
+ { MP_ROM_QSTR(MP_QSTR_PD03), MP_ROM_PTR(&pin_PD03) },
+ { MP_ROM_QSTR(MP_QSTR_PD02), MP_ROM_PTR(&pin_PD02) },
+ { MP_ROM_QSTR(MP_QSTR_PD01), MP_ROM_PTR(&pin_PD01) },
+ { MP_ROM_QSTR(MP_QSTR_PD00), MP_ROM_PTR(&pin_PD00) },
+ { MP_ROM_QSTR(MP_QSTR_PC12), MP_ROM_PTR(&pin_PC12) },
+ { MP_ROM_QSTR(MP_QSTR_PC11), MP_ROM_PTR(&pin_PC11) },
+ { MP_ROM_QSTR(MP_QSTR_PC10), MP_ROM_PTR(&pin_PC10) },
+ { MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_PA09), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_PC09), MP_ROM_PTR(&pin_PC09) },
+ { MP_ROM_QSTR(MP_QSTR_PC08), MP_ROM_PTR(&pin_PC08) },
+ { MP_ROM_QSTR(MP_QSTR_PC07), MP_ROM_PTR(&pin_PC07) },
+ { MP_ROM_QSTR(MP_QSTR_PC06), MP_ROM_PTR(&pin_PC06) },
+ //ST LED names
+ { MP_ROM_QSTR(MP_QSTR_LD3), MP_ROM_PTR(&pin_PD13) },
+ { MP_ROM_QSTR(MP_QSTR_LD4), MP_ROM_PTR(&pin_PD12) },
+ { MP_ROM_QSTR(MP_QSTR_LD5), MP_ROM_PTR(&pin_PD14) },
+ { MP_ROM_QSTR(MP_QSTR_LD6), MP_ROM_PTR(&pin_PD15) },
+ //more useful LED names
+ { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_PD13) },
+ { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_PD12) },
+ { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_PD14) },
+ { MP_ROM_QSTR(MP_QSTR_LED4), MP_ROM_PTR(&pin_PD15) },
+ //AnalogIO names
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA05) },
+ //actual LED names
+ { MP_ROM_QSTR(MP_QSTR_LED_ORANGE), MP_ROM_PTR(&pin_PD13) },
+ { MP_ROM_QSTR(MP_QSTR_LED_GREEN), MP_ROM_PTR(&pin_PD12) },
+ { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_PD14) },
+ { MP_ROM_QSTR(MP_QSTR_LED_BLUE), MP_ROM_PTR(&pin_PD15) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h
new file mode 100644
index 000000000..b244a69b5
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h
@@ -0,0 +1,439 @@
+/**
+ ******************************************************************************
+ * @file stm32f4xx_hal_conf_template.h
+ * @author MCD Application Team
+ * @brief HAL configuration template file.
+ * This file should be copied to the application folder and renamed
+ * to stm32f4xx_hal_conf.h.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_HAL_CONF_H
+#define __STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+
+#define HAL_ADC_MODULE_ENABLED
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_CAN_MODULE_ENABLED */
+/* #define HAL_CRC_MODULE_ENABLED */
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_DAC_MODULE_ENABLED */
+/* #define HAL_DCMI_MODULE_ENABLED */
+/* #define HAL_DMA2D_MODULE_ENABLED */
+/* #define HAL_ETH_MODULE_ENABLED */
+/* #define HAL_NAND_MODULE_ENABLED */
+/* #define HAL_NOR_MODULE_ENABLED */
+/* #define HAL_PCCARD_MODULE_ENABLED */
+/* #define HAL_SRAM_MODULE_ENABLED */
+/* #define HAL_SDRAM_MODULE_ENABLED */
+/* #define HAL_HASH_MODULE_ENABLED */
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_I2S_MODULE_ENABLED
+/* #define HAL_IWDG_MODULE_ENABLED */
+/* #define HAL_LTDC_MODULE_ENABLED */
+/* #define HAL_RNG_MODULE_ENABLED */
+/* #define HAL_RTC_MODULE_ENABLED */
+/* #define HAL_SAI_MODULE_ENABLED */
+/* #define HAL_SD_MODULE_ENABLED */
+/* #define HAL_MMC_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
+/* #define HAL_TIM_MODULE_ENABLED */
+#define HAL_UART_MODULE_ENABLED
+/* #define HAL_USART_MODULE_ENABLED */
+/* #define HAL_IRDA_MODULE_ENABLED */
+/* #define HAL_SMARTCARD_MODULE_ENABLED */
+/* #define HAL_WWDG_MODULE_ENABLED */
+#define HAL_PCD_MODULE_ENABLED
+/* #define HAL_HCD_MODULE_ENABLED */
+/* #define HAL_DSI_MODULE_ENABLED */
+/* #define HAL_QSPI_MODULE_ENABLED */
+/* #define HAL_QSPI_MODULE_ENABLED */
+/* #define HAL_CEC_MODULE_ENABLED */
+/* #define HAL_FMPI2C_MODULE_ENABLED */
+/* #define HAL_SPDIFRX_MODULE_ENABLED */
+/* #define HAL_DFSDM_MODULE_ENABLED */
+/* #define HAL_LPTIM_MODULE_ENABLED */
+/* #define HAL_EXTI_MODULE_ENABLED */
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+
+/* ########################## HSE/HSI Values adaptation ##################### */
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief Internal Low Speed oscillator (LSI) value.
+ */
+#if !defined (LSI_VALUE)
+ #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
+#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature.*/
+/**
+ * @brief External Low Speed oscillator (LSE) value.
+ */
+#if !defined (LSE_VALUE)
+ #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */
+#endif /* LSE_VALUE */
+
+#if !defined (LSE_STARTUP_TIMEOUT)
+ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief External clock source for I2S peripheral
+ * This value is used by the I2S HAL module to compute the I2S clock source
+ * frequency, this source is inserted directly through I2S_CKIN pad.
+ */
+#if !defined (EXTERNAL_CLOCK_VALUE)
+ #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
+#endif /* EXTERNAL_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
+#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
+#define USE_RTOS 0U
+#define PREFETCH_ENABLE 1U
+#define INSTRUCTION_CACHE_ENABLE 1U
+#define DATA_CACHE_ENABLE 1U
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1U */
+
+/* ################## Ethernet peripheral configuration ##################### */
+
+/* Section 1 : Ethernet peripheral configuration */
+
+/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0 2U
+#define MAC_ADDR1 0U
+#define MAC_ADDR2 0U
+#define MAC_ADDR3 0U
+#define MAC_ADDR4 0U
+#define MAC_ADDR5 0U
+
+/* Definition of the Ethernet driver buffers size and count */
+#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
+#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
+#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
+#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
+
+/* Section 2: PHY configuration section */
+
+/* DP83848_PHY_ADDRESS Address*/
+#define DP83848_PHY_ADDRESS 0x01U
+/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
+#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
+/* PHY Configuration delay */
+#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
+
+#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
+#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
+
+/* Section 3: Common PHY Registers */
+
+#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
+#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
+
+#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
+#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
+#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
+#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
+#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
+#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
+
+#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
+#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
+#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
+
+/* Section 4: Extended PHY Registers */
+#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
+
+#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
+#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+* Activated: CRC code is present inside driver
+* Deactivated: CRC code cleaned from driver
+*/
+
+#define USE_SPI_CRC 0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+ #include "stm32f4xx_hal_exti.h"
+#endif /* HAL_EXTI_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32f4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32f4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32f4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+ #include "stm32f4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32f4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32f4xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma2d.h"
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+ #include "stm32f4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dcmi.h"
+#endif /* HAL_DCMI_MODULE_ENABLED */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+ #include "stm32f4xx_hal_eth.h"
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+ #include "stm32f4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+ #include "stm32f4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_PCCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pccard.h"
+#endif /* HAL_PCCARD_MODULE_ENABLED */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sdram.h"
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_hash.h"
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+ #include "stm32f4xx_hal_ltdc.h"
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32f4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32f4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32f4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32f4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_MMC_MODULE_ENABLED
+ #include "stm32f4xx_hal_mmc.h"
+#endif /* HAL_MMC_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32f4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32f4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32f4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+#ifdef HAL_DSI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dsi.h"
+#endif /* HAL_DSI_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_CEC_MODULE_ENABLED
+ #include "stm32f4xx_hal_cec.h"
+#endif /* HAL_CEC_MODULE_ENABLED */
+
+#ifdef HAL_FMPI2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_fmpi2c.h"
+#endif /* HAL_FMPI2C_MODULE_ENABLED */
+
+#ifdef HAL_SPDIFRX_MODULE_ENABLED
+ #include "stm32f4xx_hal_spdifrx.h"
+#endif /* HAL_SPDIFRX_MODULE_ENABLED */
+
+#ifdef HAL_DFSDM_MODULE_ENABLED
+ #include "stm32f4xx_hal_dfsdm.h"
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_HAL_CONF_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/board.c b/ports/stm32f4/boards/stm32f412zg_discovery/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f412zg_discovery/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h b/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h
new file mode 100644
index 000000000..ebee98f89
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "STM32F412G_DISCO"
+#define MICROPY_HW_MCU_NAME "STM32F412xGS"
+
+#define FLASH_SIZE (0x100000)
+#define FLASH_PAGE_SIZE (0x4000)
+
+#define AUTORESET_DELAY_MS 500
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000)
+
diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.mk b/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.mk
new file mode 100644
index 000000000..509a24410
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.mk
@@ -0,0 +1,22 @@
+USB_VID = 0x239A
+USB_PID = 0x8056
+USB_PRODUCT = "STM32F412ZG Discovery Board - CPy"
+USB_MANUFACTURER = "STMicroelectronics"
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+
+# QSPI_FLASH_FILESYSTEM = 1
+# EXTERNAL_FLASH_DEVICE_COUNT = 1
+# EXTERNAL_FLASH_DEVICES = N25Q128A
+# LONGINT_IMPL = MPZ
+
+MCU_SERIES = m4
+MCU_VARIANT = stm32f4
+MCU_SUB_VARIANT = stm32f412zx
+MCU_PACKAGE = 144
+CMSIS_MCU = STM32F412Zx
+LD_FILE = boards/STM32F412ZGTx_FLASH.ld
+TEXT0_ADDR = 0x08000000
+TEXT1_ADDR = 0x08020000
+
diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/pins.c b/ports/stm32f4/boards/stm32f412zg_discovery/pins.c
new file mode 100644
index 000000000..a0b477a47
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f412zg_discovery/pins.c
@@ -0,0 +1,92 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) },
+ { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) },
+ { MP_ROM_QSTR(MP_QSTR_PE04), MP_ROM_PTR(&pin_PE04) },
+ { MP_ROM_QSTR(MP_QSTR_PE05), MP_ROM_PTR(&pin_PE05) },
+ { MP_ROM_QSTR(MP_QSTR_PE06), MP_ROM_PTR(&pin_PE06) },
+ { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) },
+ { MP_ROM_QSTR(MP_QSTR_PF02), MP_ROM_PTR(&pin_PF02) },
+ { MP_ROM_QSTR(MP_QSTR_PF03), MP_ROM_PTR(&pin_PF03) },
+ { MP_ROM_QSTR(MP_QSTR_PF10), MP_ROM_PTR(&pin_PF10) },
+ { MP_ROM_QSTR(MP_QSTR_PC00), MP_ROM_PTR(&pin_PC00) },
+ { MP_ROM_QSTR(MP_QSTR_PC01), MP_ROM_PTR(&pin_PC01) },
+ { MP_ROM_QSTR(MP_QSTR_PC02), MP_ROM_PTR(&pin_PC02) },
+ { MP_ROM_QSTR(MP_QSTR_PC03), MP_ROM_PTR(&pin_PC03) },
+ { MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_PC04), MP_ROM_PTR(&pin_PC04) },
+ { MP_ROM_QSTR(MP_QSTR_PC05), MP_ROM_PTR(&pin_PC05) },
+ { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) },
+ { MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_PF11), MP_ROM_PTR(&pin_PF11) },
+ { MP_ROM_QSTR(MP_QSTR_PF13), MP_ROM_PTR(&pin_PF13) },
+ { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) },
+ { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) },
+ { MP_ROM_QSTR(MP_QSTR_PD12), MP_ROM_PTR(&pin_PD12) },
+ { MP_ROM_QSTR(MP_QSTR_PD13), MP_ROM_PTR(&pin_PD13) },
+ { MP_ROM_QSTR(MP_QSTR_PG02), MP_ROM_PTR(&pin_PG02) },
+ { MP_ROM_QSTR(MP_QSTR_PC06), MP_ROM_PTR(&pin_PC06) },
+ { MP_ROM_QSTR(MP_QSTR_PC07), MP_ROM_PTR(&pin_PC07) },
+ { MP_ROM_QSTR(MP_QSTR_PC09), MP_ROM_PTR(&pin_PC09) },
+ { MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_PD06), MP_ROM_PTR(&pin_PD06) },
+ { MP_ROM_QSTR(MP_QSTR_PG09), MP_ROM_PTR(&pin_PG09) },
+ { MP_ROM_QSTR(MP_QSTR_PG10), MP_ROM_PTR(&pin_PG10) },
+ { MP_ROM_QSTR(MP_QSTR_PG11), MP_ROM_PTR(&pin_PG11) },
+ { MP_ROM_QSTR(MP_QSTR_PG12), MP_ROM_PTR(&pin_PG12) },
+ { MP_ROM_QSTR(MP_QSTR_PG13), MP_ROM_PTR(&pin_PG13) },
+ { MP_ROM_QSTR(MP_QSTR_PG14), MP_ROM_PTR(&pin_PG14) },
+ { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_PE00), MP_ROM_PTR(&pin_PE00) },
+ { MP_ROM_QSTR(MP_QSTR_PE01), MP_ROM_PTR(&pin_PE01) },
+ { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PG10) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PG11) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PF03) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PF10) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PG12) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PF04) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PG13) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PG14) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PG09) },
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PC01) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PC03) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PC04) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PC05) }, //alt PB09, see F401ZG-DISCO manual
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB00) }, //alt PB10, see F401ZG-DISCO manual
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_PE00) },
+ { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_PE01) },
+ { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_PE02) },
+ { MP_ROM_QSTR(MP_QSTR_LED4), MP_ROM_PTR(&pin_PE03) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h
new file mode 100644
index 000000000..2ad0fee20
--- /dev/null
+++ b/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h
@@ -0,0 +1,438 @@
+/**
+ ******************************************************************************
+ * @file stm32f4xx_hal_conf_template.h
+ * @author MCD Application Team
+ * @brief HAL configuration template file.
+ * This file should be copied to the application folder and renamed
+ * to stm32f4xx_hal_conf.h.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_HAL_CONF_H
+#define __STM32F4xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+
+#define HAL_ADC_MODULE_ENABLED
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_CAN_MODULE_ENABLED */
+/* #define HAL_CRC_MODULE_ENABLED */
+/* #define HAL_CRYP_MODULE_ENABLED */
+/* #define HAL_DAC_MODULE_ENABLED */
+/* #define HAL_DCMI_MODULE_ENABLED */
+/* #define HAL_DMA2D_MODULE_ENABLED */
+/* #define HAL_ETH_MODULE_ENABLED */
+/* #define HAL_NAND_MODULE_ENABLED */
+/* #define HAL_NOR_MODULE_ENABLED */
+/* #define HAL_PCCARD_MODULE_ENABLED */
+#define HAL_SRAM_MODULE_ENABLED
+/* #define HAL_SDRAM_MODULE_ENABLED */
+/* #define HAL_HASH_MODULE_ENABLED */
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_I2S_MODULE_ENABLED
+/* #define HAL_IWDG_MODULE_ENABLED */
+/* #define HAL_LTDC_MODULE_ENABLED */
+/* #define HAL_RNG_MODULE_ENABLED */
+/* #define HAL_RTC_MODULE_ENABLED */
+/* #define HAL_SAI_MODULE_ENABLED */
+#define HAL_SD_MODULE_ENABLED
+/* #define HAL_MMC_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
+/* #define HAL_TIM_MODULE_ENABLED */
+#define HAL_UART_MODULE_ENABLED
+/* #define HAL_USART_MODULE_ENABLED */
+/* #define HAL_IRDA_MODULE_ENABLED */
+/* #define HAL_SMARTCARD_MODULE_ENABLED */
+/* #define HAL_WWDG_MODULE_ENABLED */
+#define HAL_PCD_MODULE_ENABLED
+/* #define HAL_HCD_MODULE_ENABLED */
+/* #define HAL_DSI_MODULE_ENABLED */
+#define HAL_QSPI_MODULE_ENABLED
+/* #define HAL_CEC_MODULE_ENABLED */
+/* #define HAL_FMPI2C_MODULE_ENABLED */
+/* #define HAL_SPDIFRX_MODULE_ENABLED */
+/* #define HAL_DFSDM_MODULE_ENABLED */
+/* #define HAL_LPTIM_MODULE_ENABLED */
+/* #define HAL_EXTI_MODULE_ENABLED */
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+
+/* ########################## HSE/HSI Values adaptation ##################### */
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief Internal Low Speed oscillator (LSI) value.
+ */
+#if !defined (LSI_VALUE)
+ #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
+#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature.*/
+/**
+ * @brief External Low Speed oscillator (LSE) value.
+ */
+#if !defined (LSE_VALUE)
+ #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */
+#endif /* LSE_VALUE */
+
+#if !defined (LSE_STARTUP_TIMEOUT)
+ #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief External clock source for I2S peripheral
+ * This value is used by the I2S HAL module to compute the I2S clock source
+ * frequency, this source is inserted directly through I2S_CKIN pad.
+ */
+#if !defined (EXTERNAL_CLOCK_VALUE)
+ #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
+#endif /* EXTERNAL_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
+#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
+#define USE_RTOS 0U
+#define PREFETCH_ENABLE 1U
+#define INSTRUCTION_CACHE_ENABLE 1U
+#define DATA_CACHE_ENABLE 1U
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1U */
+
+/* ################## Ethernet peripheral configuration ##################### */
+
+/* Section 1 : Ethernet peripheral configuration */
+
+/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
+#define MAC_ADDR0 2U
+#define MAC_ADDR1 0U
+#define MAC_ADDR2 0U
+#define MAC_ADDR3 0U
+#define MAC_ADDR4 0U
+#define MAC_ADDR5 0U
+
+/* Definition of the Ethernet driver buffers size and count */
+#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
+#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
+#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
+#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
+
+/* Section 2: PHY configuration section */
+
+/* DP83848_PHY_ADDRESS Address*/
+#define DP83848_PHY_ADDRESS 0x01U
+/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
+#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
+/* PHY Configuration delay */
+#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
+
+#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
+#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
+
+/* Section 3: Common PHY Registers */
+
+#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
+#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
+
+#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
+#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
+#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
+#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
+#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
+#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
+
+#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
+#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
+#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
+
+/* Section 4: Extended PHY Registers */
+#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
+
+#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
+#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+* Activated: CRC code is present inside driver
+* Deactivated: CRC code cleaned from driver
+*/
+
+#define USE_SPI_CRC 0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+ #include "stm32f4xx_hal_exti.h"
+#endif /* HAL_EXTI_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32f4xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32f4xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32f4xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_CAN_MODULE_ENABLED
+ #include "stm32f4xx_hal_can.h"
+#endif /* HAL_CAN_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32f4xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32f4xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DMA2D_MODULE_ENABLED
+ #include "stm32f4xx_hal_dma2d.h"
+#endif /* HAL_DMA2D_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+ #include "stm32f4xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_DCMI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dcmi.h"
+#endif /* HAL_DCMI_MODULE_ENABLED */
+
+#ifdef HAL_ETH_MODULE_ENABLED
+ #include "stm32f4xx_hal_eth.h"
+#endif /* HAL_ETH_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sram.h"
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+ #include "stm32f4xx_hal_nor.h"
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+ #include "stm32f4xx_hal_nand.h"
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+#ifdef HAL_PCCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pccard.h"
+#endif /* HAL_PCCARD_MODULE_ENABLED */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+ #include "stm32f4xx_hal_sdram.h"
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+#ifdef HAL_HASH_MODULE_ENABLED
+ #include "stm32f4xx_hal_hash.h"
+#endif /* HAL_HASH_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32f4xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LTDC_MODULE_ENABLED
+ #include "stm32f4xx_hal_ltdc.h"
+#endif /* HAL_LTDC_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32f4xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32f4xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32f4xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32f4xx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SD_MODULE_ENABLED
+ #include "stm32f4xx_hal_sd.h"
+#endif /* HAL_SD_MODULE_ENABLED */
+
+#ifdef HAL_MMC_MODULE_ENABLED
+ #include "stm32f4xx_hal_mmc.h"
+#endif /* HAL_MMC_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32f4xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32f4xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32f4xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32f4xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32f4xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_HCD_MODULE_ENABLED
+ #include "stm32f4xx_hal_hcd.h"
+#endif /* HAL_HCD_MODULE_ENABLED */
+
+#ifdef HAL_DSI_MODULE_ENABLED
+ #include "stm32f4xx_hal_dsi.h"
+#endif /* HAL_DSI_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32f4xx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_CEC_MODULE_ENABLED
+ #include "stm32f4xx_hal_cec.h"
+#endif /* HAL_CEC_MODULE_ENABLED */
+
+#ifdef HAL_FMPI2C_MODULE_ENABLED
+ #include "stm32f4xx_hal_fmpi2c.h"
+#endif /* HAL_FMPI2C_MODULE_ENABLED */
+
+#ifdef HAL_SPDIFRX_MODULE_ENABLED
+ #include "stm32f4xx_hal_spdifrx.h"
+#endif /* HAL_SPDIFRX_MODULE_ENABLED */
+
+#ifdef HAL_DFSDM_MODULE_ENABLED
+ #include "stm32f4xx_hal_dfsdm.h"
+#endif /* HAL_DFSDM_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+ #include "stm32f4xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_HAL_CONF_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32f4/common-hal/analogio/AnalogIn.c b/ports/stm32f4/common-hal/analogio/AnalogIn.c
new file mode 100644
index 000000000..3ee3c4dbb
--- /dev/null
+++ b/ports/stm32f4/common-hal/analogio/AnalogIn.c
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/analogio/AnalogIn.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4xx_ll_gpio.h"
+#include "stm32f4xx_ll_adc.h"
+#include "stm32f4xx_ll_bus.h"
+
+void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self,
+ const mcu_pin_obj_t *pin) {
+
+ // No ADC function on pin
+ if (pin->adc_unit == 0x00) {
+ mp_raise_ValueError(translate("Pin does not have ADC capabilities"));
+ }
+ // TODO: add ADC traits to structure?
+
+ // Note that ADC2 is always bundled pin-to-pin with ADC1 if it exists, and used only
+ // for dual conversion. For this basic application it is never used.
+ LL_GPIO_SetPinMode(pin_port(pin->port), (uint32_t)pin_mask(pin->number), LL_GPIO_MODE_ANALOG);
+ if (pin->adc_unit & 0x01) {
+ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);
+ } else if (pin->adc_unit == 0x04) {
+ #ifdef LL_APB2_GRP1_PERIPH_ADC3
+ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC3);
+ #endif
+ } else {
+ mp_raise_ValueError(translate("Invalid ADC Unit value"));
+ }
+ claim_pin(pin);
+ self->pin = pin;
+}
+
+bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self) {
+ return self->pin == mp_const_none;
+}
+
+void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
+ if (common_hal_analogio_analogin_deinited(self)) {
+ return;
+ }
+ reset_pin_number(self->pin->port,self->pin->number);
+ self->pin = mp_const_none;
+}
+
+uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
+ // Something else might have used the ADC in a different way,
+ // so we completely re-initialize it.
+ ADC_TypeDef * ADCx;
+
+ if(self->pin->adc_unit & 0x01) {
+ ADCx = ADC1;
+ } else if (self->pin->adc_unit == 0x04) {
+ #ifdef ADC3
+ ADCx = ADC3;
+ #endif
+ } else {
+ mp_raise_ValueError(translate("Invalid ADC Unit value"));
+ }
+
+ LL_GPIO_SetPinMode(pin_port(self->pin->port), (uint32_t)pin_mask(self->pin->number), LL_GPIO_MODE_ANALOG);
+ //LL_GPIO_PIN_0
+
+ //HAL Implementation
+ ADC_HandleTypeDef AdcHandle;
+ ADC_ChannelConfTypeDef sConfig;
+
+ AdcHandle.Instance = ADCx;
+ AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
+ AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;
+ AdcHandle.Init.ScanConvMode = DISABLE;
+ AdcHandle.Init.ContinuousConvMode = DISABLE;
+ AdcHandle.Init.DiscontinuousConvMode = DISABLE;
+ AdcHandle.Init.NbrOfDiscConversion = 0;
+ AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
+ AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
+ AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
+ AdcHandle.Init.NbrOfConversion = 1;
+ AdcHandle.Init.DMAContinuousRequests = DISABLE;
+ AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
+ HAL_ADC_Init(&AdcHandle);
+
+ sConfig.Channel = (uint32_t)self->pin->adc_channel; //ADC_CHANNEL_0 <-normal iteration, not mask
+ sConfig.Rank = 1;
+ sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; //Taken from micropython
+ HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
+
+ HAL_ADC_Start(&AdcHandle);
+ HAL_ADC_PollForConversion(&AdcHandle,1);
+ uint16_t value = (uint16_t)HAL_ADC_GetValue(&AdcHandle);
+ HAL_ADC_Stop(&AdcHandle);
+
+ // // Shift the value to be 16 bit.
+ return value << 4;
+}
+
+float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) {
+ return 3.3f;
+}
diff --git a/ports/stm32f4/common-hal/analogio/AnalogIn.h b/ports/stm32f4/common-hal/analogio/AnalogIn.h
new file mode 100644
index 000000000..910092897
--- /dev/null
+++ b/ports/stm32f4/common-hal/analogio/AnalogIn.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_COMMON_HAL_ANALOGIO_ANALOGIN_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_ANALOGIO_ANALOGIN_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ const mcu_pin_obj_t * pin;
+} analogio_analogin_obj_t;
+
+static inline uint8_t stm32_adc_units(uint8_t adc_packed) {
+ return adc_packed >> 5;
+}
+
+static inline uint8_t stm32_adc_channel(uint8_t adc_packed) {
+ return adc_packed & 0x1f;
+}
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_ANALOGIO_ANALOGIN_H
diff --git a/ports/stm32f4/common-hal/analogio/AnalogOut.c b/ports/stm32f4/common-hal/analogio/AnalogOut.c
new file mode 100644
index 000000000..a59a8b190
--- /dev/null
+++ b/ports/stm32f4/common-hal/analogio/AnalogOut.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "py/mperrno.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/analogio/AnalogOut.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "supervisor/shared/translate.h"
+
+void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self,
+ const mcu_pin_obj_t *pin) {
+ mp_raise_ValueError(translate("DAC not supported"));
+}
+
+bool common_hal_analogio_analogout_deinited(analogio_analogout_obj_t *self) {
+ return self->deinited;
+}
+
+void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) {
+
+}
+
+void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self,
+ uint16_t value) {
+}
+
+void analogout_reset(void) {
+ // audioout_reset also resets the DAC, and does a smooth ramp down to avoid clicks
+ // if it was enabled, so do that instead if AudioOut is enabled.
+}
diff --git a/ports/stm32f4/common-hal/analogio/AnalogOut.h b/ports/stm32f4/common-hal/analogio/AnalogOut.h
new file mode 100644
index 000000000..f2952e9f9
--- /dev/null
+++ b/ports/stm32f4/common-hal/analogio/AnalogOut.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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_ATMEL_SAMD_COMMON_HAL_ANALOGIO_ANALOGOUT_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ANALOGIO_ANALOGOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t channel;
+ bool deinited;
+} analogio_analogout_obj_t;
+
+void analogout_reset(void);
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ANALOGIO_ANALOGOUT_H
diff --git a/ports/stm32f4/common-hal/analogio/__init__.c b/ports/stm32f4/common-hal/analogio/__init__.c
new file mode 100644
index 000000000..eea58c77d
--- /dev/null
+++ b/ports/stm32f4/common-hal/analogio/__init__.c
@@ -0,0 +1 @@
+// No analogio module functions.
diff --git a/ports/stm32f4/common-hal/board/__init__.c b/ports/stm32f4/common-hal/board/__init__.c
new file mode 100644
index 000000000..880033ed6
--- /dev/null
+++ b/ports/stm32f4/common-hal/board/__init__.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
diff --git a/ports/stm32f4/common-hal/busio/I2C.c b/ports/stm32f4/common-hal/busio/I2C.c
new file mode 100644
index 000000000..c2f5dbe0a
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/I2C.c
@@ -0,0 +1,231 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Lucian Copeland 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 <stdbool.h>
+
+#include "shared-bindings/busio/I2C.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "stm32f4xx_hal.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "supervisor/shared/translate.h"
+#include "common-hal/microcontroller/Pin.h"
+
+STATIC bool reserved_i2c[3];
+
+void i2c_reset(void) {
+ //Note: I2Cs are also forcibly reset in construct, due to silicon error
+ #ifdef I2C1
+ reserved_i2c[0] = false;
+ __HAL_RCC_I2C1_CLK_DISABLE();
+ #endif
+ #ifdef I2C2
+ reserved_i2c[1] = false;
+ __HAL_RCC_I2C2_CLK_DISABLE();
+ #endif
+ #ifdef I2C3
+ reserved_i2c[3] = false;
+ __HAL_RCC_I2C3_CLK_DISABLE();
+ #endif
+}
+
+void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
+ const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) {
+
+ //match pins to I2C objects
+ I2C_TypeDef * I2Cx;
+
+ uint8_t sda_len = sizeof(mcu_i2c_sda_list)/sizeof(*mcu_i2c_sda_list);
+ uint8_t scl_len = sizeof(mcu_i2c_scl_list)/sizeof(*mcu_i2c_scl_list);
+ for(uint i=0; i<sda_len;i++) {
+ if (mcu_i2c_sda_list[i].pin == sda) {
+ for(uint j=0; j<scl_len;j++) {
+ if ((mcu_i2c_scl_list[j].pin == scl)
+ && (mcu_i2c_scl_list[j].i2c_index == mcu_i2c_sda_list[i].i2c_index)) {
+ self->scl = &mcu_i2c_scl_list[j];
+ self->sda = &mcu_i2c_sda_list[i];
+ break;
+ }
+ }
+ }
+ }
+
+ //handle typedef selection, errors
+ if(self->sda!=NULL && self->scl!=NULL ) {
+ I2Cx = mcu_i2c_banks[self->sda->i2c_index-1];
+ } else {
+ mp_raise_RuntimeError(translate("Invalid I2C pin selection"));
+ }
+
+ if(reserved_i2c[self->sda->i2c_index-1]) {
+ mp_raise_RuntimeError(translate("Hardware busy, try alternative pins"));
+ }
+
+ //Start GPIO for each pin
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ GPIO_InitStruct.Pin = pin_mask(sda->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Alternate = self->sda->altfn_index;
+ HAL_GPIO_Init(pin_port(sda->port), &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = pin_mask(scl->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Alternate = self->scl->altfn_index;
+ HAL_GPIO_Init(pin_port(scl->port), &GPIO_InitStruct);
+
+ //Fix for HAL error caused by soft reboot GPIO init SDA pin voltage drop. See Eratta.
+ //Must be in this exact spot or I2C will get stuck in infinite loop.
+ //TODO: See git issue #2172
+ #ifdef I2C1
+ __HAL_RCC_I2C1_FORCE_RESET();
+ HAL_Delay(2);
+ __HAL_RCC_I2C1_RELEASE_RESET();
+ #endif
+ #ifdef I2C2
+ __HAL_RCC_I2C2_FORCE_RESET();
+ HAL_Delay(2);
+ __HAL_RCC_I2C2_RELEASE_RESET();
+ #endif
+ #ifdef I2C3
+ __HAL_RCC_I2C3_FORCE_RESET();
+ HAL_Delay(2);
+ __HAL_RCC_I2C3_RELEASE_RESET();
+ #endif
+
+ //Keep separate so above hack can be cleanly replaced
+ #ifdef I2C1
+ if(I2Cx==I2C1) {
+ reserved_i2c[0] = true;
+ __HAL_RCC_I2C1_CLK_ENABLE();
+ }
+ #endif
+ #ifdef I2C2
+ if(I2Cx==I2C2) {
+ reserved_i2c[1] = true;
+ __HAL_RCC_I2C2_CLK_ENABLE();
+ }
+ #endif
+ #ifdef I2C3
+ if(I2Cx==I2C3) {
+ reserved_i2c[2] = true;
+ __HAL_RCC_I2C3_CLK_ENABLE();
+ }
+ #endif
+
+ self->handle.Instance = I2Cx;
+ self->handle.Init.ClockSpeed = 100000;
+ self->handle.Init.DutyCycle = I2C_DUTYCYCLE_2;
+ self->handle.Init.OwnAddress1 = 0;
+ self->handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ self->handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ self->handle.Init.OwnAddress2 = 0;
+ self->handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ self->handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ if(HAL_I2C_Init(&(self->handle)) != HAL_OK) {
+ mp_raise_RuntimeError(translate("I2C Init Error"));
+ }
+ claim_pin(sda);
+ claim_pin(scl);
+}
+
+bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
+ return self->sda->pin == mp_const_none;
+}
+
+void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
+ if (common_hal_busio_i2c_deinited(self)) {
+ return;
+ }
+ #ifdef I2C1
+ if(self->handle.Instance==I2C1) {
+ reserved_i2c[0] = 0;
+ __HAL_RCC_I2C1_CLK_DISABLE();
+ }
+ #endif
+ #ifdef I2C2
+ if(self->handle.Instance==I2C2) {
+ reserved_i2c[1] = 0;
+ __HAL_RCC_I2C2_CLK_DISABLE();
+ }
+ #endif
+ #ifdef I2C3
+ if(self->handle.Instance==I2C3) {
+ reserved_i2c[3] = 0;
+ __HAL_RCC_I2C3_CLK_DISABLE();
+ }
+ #endif
+ reset_pin_number(self->sda->pin->port,self->sda->pin->number);
+ reset_pin_number(self->scl->pin->port,self->scl->pin->number);
+ self->sda = mp_const_none;
+ self->scl = mp_const_none;
+}
+
+bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
+ return HAL_I2C_IsDeviceReady(&(self->handle), (uint16_t)(addr<<1),2,2) == HAL_OK;
+}
+
+bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
+ bool grabbed_lock = false;
+
+ //Critical section code that may be required at some point.
+ // uint32_t store_primask = __get_PRIMASK();
+ // __disable_irq();
+ // __DMB();
+
+ if (!self->has_lock) {
+ grabbed_lock = true;
+ self->has_lock = true;
+ }
+
+ // __DMB();
+ // __set_PRIMASK(store_primask);
+
+ return grabbed_lock;
+}
+
+bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
+ return self->has_lock;
+}
+
+void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
+ self->has_lock = false;
+}
+
+uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
+ const uint8_t *data, size_t len, bool transmit_stop_bit) {
+ HAL_StatusTypeDef result = HAL_I2C_Master_Transmit(&(self->handle), (uint16_t)(addr<<1), (uint8_t *)data, (uint16_t)len, 500);
+ return result == HAL_OK ? 0 : MP_EIO;
+}
+
+uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
+ uint8_t *data, size_t len) {
+ return HAL_I2C_Master_Receive(&(self->handle), (uint16_t)(addr<<1), data, (uint16_t)len, 500) == HAL_OK ? 0 : MP_EIO;
+}
diff --git a/ports/stm32f4/common-hal/busio/I2C.h b/ports/stm32f4/common-hal/busio/I2C.h
new file mode 100644
index 000000000..b5c891a98
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/I2C.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_COMMON_HAL_BUSIO_I2C_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_I2C_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4/periph.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ I2C_HandleTypeDef handle;
+ bool has_lock;
+ const mcu_i2c_scl_obj_t *scl;
+ const mcu_i2c_sda_obj_t *sda;
+} busio_i2c_obj_t;
+
+void i2c_reset(void);
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_I2C_H
diff --git a/ports/stm32f4/common-hal/busio/OneWire.h b/ports/stm32f4/common-hal/busio/OneWire.h
new file mode 100644
index 000000000..6e8c82979
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/OneWire.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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_STM32F4_COMMON_HAL_BUSIO_ONEWIRE_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_ONEWIRE_H
+
+// Use bitbangio.
+#include "shared-module/busio/OneWire.h"
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_ONEWIRE_H
diff --git a/ports/stm32f4/common-hal/busio/SPI.c b/ports/stm32f4/common-hal/busio/SPI.c
new file mode 100644
index 000000000..e20bd7a94
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/SPI.c
@@ -0,0 +1,415 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Lucian Copeland 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 <stdbool.h>
+
+#include "shared-bindings/busio/SPI.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "stm32f4xx_hal.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "boards/board.h"
+#include "supervisor/shared/translate.h"
+#include "common-hal/microcontroller/Pin.h"
+
+STATIC bool reserved_spi[6];
+STATIC bool never_reset_spi[6];
+
+void spi_reset(void) {
+ #ifdef SPI1
+ if(!never_reset_spi[0]) {
+ reserved_spi[0] = false;
+ __HAL_RCC_SPI1_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI2
+ if(!never_reset_spi[1]) {
+ reserved_spi[1] = false;
+ __HAL_RCC_SPI2_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI3
+ if(!never_reset_spi[2]) {
+ reserved_spi[2] = false;
+ __HAL_RCC_SPI3_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI4
+ if(!never_reset_spi[3]) {
+ reserved_spi[3] = false;
+ __HAL_RCC_SPI4_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI5
+ if(!never_reset_spi[4]) {
+ reserved_spi[4] = false;
+ __HAL_RCC_SPI5_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI6
+ if(!never_reset_spi[5]) {
+ reserved_spi[5] = false;
+ __HAL_RCC_SPI6_CLK_DISABLE();
+ }
+ #endif
+}
+
+void common_hal_busio_spi_construct(busio_spi_obj_t *self,
+ const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi,
+ const mcu_pin_obj_t * miso) {
+
+ //match pins to SPI objects
+ SPI_TypeDef * SPIx;
+
+ uint8_t sck_len = sizeof(mcu_spi_sck_list)/sizeof(*mcu_spi_sck_list);
+ uint8_t mosi_len = sizeof(mcu_spi_mosi_list)/sizeof(*mcu_spi_mosi_list);
+ uint8_t miso_len = sizeof(mcu_spi_miso_list)/sizeof(*mcu_spi_miso_list);
+
+ bool spi_taken = false;
+ //sck
+ for(uint i=0; i<sck_len;i++) {
+ if (mcu_spi_sck_list[i].pin == sck) {
+ //mosi
+ for(uint j=0; j<mosi_len;j++) {
+ if (mcu_spi_mosi_list[j].pin == mosi) {
+ //miso
+ for(uint k=0; k<miso_len;k++) {
+ if ((mcu_spi_miso_list[k].pin == miso) //everything needs the same index
+ && (mcu_spi_sck_list[i].spi_index == mcu_spi_mosi_list[j].spi_index)
+ && (mcu_spi_sck_list[i].spi_index == mcu_spi_miso_list[k].spi_index)) {
+ //keep looking if the SPI is taken, edge case
+ if(reserved_spi[mcu_spi_sck_list[i].spi_index-1]) {
+ spi_taken = true;
+ continue;
+ }
+ //store pins if not
+ self->sck = &mcu_spi_sck_list[i];
+ self->mosi = &mcu_spi_mosi_list[j];
+ self->miso = &mcu_spi_miso_list[k];
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //handle typedef selection, errors
+ if(self->sck!=NULL && self->mosi!=NULL && self->miso!=NULL ) {
+ SPIx = mcu_spi_banks[self->sck->spi_index-1];
+ } else {
+ if (spi_taken) {
+ mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
+ } else {
+ mp_raise_ValueError(translate("Invalid SPI pin selection"));
+ }
+ }
+
+ //Start GPIO for each pin
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ GPIO_InitStruct.Pin = pin_mask(sck->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = self->sck->altfn_index;
+ HAL_GPIO_Init(pin_port(sck->port), &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = pin_mask(mosi->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = self->mosi->altfn_index;
+ HAL_GPIO_Init(pin_port(mosi->port), &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = pin_mask(miso->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = self->miso->altfn_index;
+ HAL_GPIO_Init(pin_port(miso->port), &GPIO_InitStruct);
+
+ #ifdef SPI1
+ if(SPIx==SPI1) {
+ reserved_spi[0] = true;
+ __HAL_RCC_SPI1_CLK_ENABLE();
+ }
+ #endif
+ #ifdef SPI2
+ if(SPIx==SPI2) {
+ reserved_spi[1] = true;
+ __HAL_RCC_SPI2_CLK_ENABLE();
+ }
+ #endif
+ #ifdef SPI3
+ if(SPIx==SPI3) {
+ reserved_spi[2] = true;
+ __HAL_RCC_SPI3_CLK_ENABLE();
+ }
+ #endif
+ #ifdef SPI4
+ if(SPIx==SPI4) {
+ reserved_spi[3] = true;
+ __HAL_RCC_SPI4_CLK_ENABLE();
+ }
+ #endif
+ #ifdef SPI5
+ if(SPIx==SPI5) {
+ reserved_spi[4] = true;
+ __HAL_RCC_SPI5_CLK_ENABLE();
+ }
+ #endif
+ #ifdef SPI6
+ if(SPIx==SPI6) {
+ reserved_spi[5] = true;
+ __HAL_RCC_SPI6_CLK_ENABLE();
+ }
+ #endif
+
+ self->handle.Instance = SPIx;
+ self->handle.Init.Mode = SPI_MODE_MASTER;
+ self->handle.Init.Direction = SPI_DIRECTION_2LINES;
+ self->handle.Init.DataSize = SPI_DATASIZE_8BIT;
+ self->handle.Init.CLKPolarity = SPI_POLARITY_LOW;
+ self->handle.Init.CLKPhase = SPI_PHASE_1EDGE;
+ self->handle.Init.NSS = SPI_NSS_SOFT;
+ self->handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
+ self->handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ self->handle.Init.TIMode = SPI_TIMODE_DISABLE;
+ self->handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ self->handle.Init.CRCPolynomial = 10;
+ if (HAL_SPI_Init(&self->handle) != HAL_OK)
+ {
+ mp_raise_ValueError(translate("SPI Init Error"));
+ }
+ self->baudrate = (HAL_RCC_GetPCLK2Freq()/16);
+ self->prescaler = 16;
+ self->polarity = 0;
+ self->phase = 1;
+ self->bits = 8;
+
+ claim_pin(sck);
+ claim_pin(mosi);
+ claim_pin(miso);
+}
+
+void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
+ for(size_t i = 0 ; i < MP_ARRAY_SIZE(mcu_spi_banks); i++) {
+ if (mcu_spi_banks[i] == self->handle.Instance) {
+ never_reset_spi[i] = true;
+ never_reset_pin_number(self->sck->pin->port, self->sck->pin->number);
+ never_reset_pin_number(self->mosi->pin->port, self->mosi->pin->number);
+ never_reset_pin_number(self->miso->pin->port, self->miso->pin->number);
+ break;
+ }
+ }
+}
+
+bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
+ return self->sck->pin == mp_const_none;
+}
+
+void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
+ #ifdef SPI1
+ if(self->handle.Instance==SPI1) {
+ reserved_spi[0] = false;
+ __HAL_RCC_SPI1_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI2
+ if(self->handle.Instance==SPI2) {
+ reserved_spi[1] = false;
+ __HAL_RCC_SPI2_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI3
+ if(self->handle.Instance==SPI3) {
+ reserved_spi[2] = false;
+ __HAL_RCC_SPI3_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI4
+ if(self->handle.Instance==SPI4) {
+ reserved_spi[3] = false;
+ __HAL_RCC_SPI4_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI5
+ if(self->handle.Instance==SPI5) {
+ reserved_spi[4] = false;
+ __HAL_RCC_SPI5_CLK_DISABLE();
+ }
+ #endif
+ #ifdef SPI6
+ if(self->handle.Instance==SPI6) {
+ reserved_spi[5] = false;
+ __HAL_RCC_SPI6_CLK_DISABLE();
+ }
+ #endif
+ reset_pin_number(self->sck->pin->port,self->sck->pin->number);
+ reset_pin_number(self->mosi->pin->port,self->mosi->pin->number);
+ reset_pin_number(self->miso->pin->port,self->miso->pin->number);
+ self->sck = mp_const_none;
+ self->mosi = mp_const_none;
+ self->miso = mp_const_none;
+}
+
+static uint32_t stm32_baud_to_spi_div(uint32_t baudrate, uint16_t * prescaler) {
+ static const uint32_t baud_map[8][2] = {
+ {2,SPI_BAUDRATEPRESCALER_2},
+ {4,SPI_BAUDRATEPRESCALER_4},
+ {8,SPI_BAUDRATEPRESCALER_8},
+ {16,SPI_BAUDRATEPRESCALER_16},
+ {32,SPI_BAUDRATEPRESCALER_32},
+ {64,SPI_BAUDRATEPRESCALER_64},
+ {128,SPI_BAUDRATEPRESCALER_128},
+ {256,SPI_BAUDRATEPRESCALER_256}
+ };
+ size_t i = 0;
+ uint16_t divisor;
+ do {
+ divisor = baud_map[i][0];
+ if (baudrate >= (HAL_RCC_GetPCLK2Freq()/divisor)) {
+ *prescaler = divisor;
+ return baud_map[i][1];
+ }
+ i++;
+ } while (divisor != 256);
+ //only gets here if requested baud is lower than minimum
+ *prescaler = 256;
+ return SPI_BAUDRATEPRESCALER_256;
+}
+
+bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
+ uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
+ //This resets the SPI, so check before updating it redundantly
+ if (baudrate == self->baudrate && polarity== self->polarity
+ && phase == self->phase && bits == self->bits) return true;
+
+ //Deinit SPI
+ HAL_SPI_DeInit(&self->handle);
+
+ if (bits == 8) {
+ self->handle.Init.DataSize = SPI_DATASIZE_8BIT;
+ } else if (bits == 16) {
+ self->handle.Init.DataSize = SPI_DATASIZE_16BIT;
+ } else {
+ return false;
+ }
+
+ if (polarity) {
+ self->handle.Init.CLKPolarity = SPI_POLARITY_HIGH;
+ } else {
+ self->handle.Init.CLKPolarity = SPI_POLARITY_LOW;
+ }
+
+ if (phase) {
+ self->handle.Init.CLKPhase = SPI_PHASE_2EDGE;
+ } else {
+ self->handle.Init.CLKPhase = SPI_PHASE_1EDGE;
+ }
+
+ self->handle.Init.BaudRatePrescaler = stm32_baud_to_spi_div(baudrate, &self->prescaler);
+
+ self->handle.Init.Mode = SPI_MODE_MASTER;
+ self->handle.Init.Direction = SPI_DIRECTION_2LINES;
+ self->handle.Init.NSS = SPI_NSS_SOFT;
+ self->handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ self->handle.Init.TIMode = SPI_TIMODE_DISABLE;
+ self->handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ self->handle.Init.CRCPolynomial = 10;
+
+ if (HAL_SPI_Init(&self->handle) != HAL_OK)
+ {
+ mp_raise_ValueError(translate("SPI Re-initialization error"));
+ }
+
+ self->baudrate = baudrate;
+ self->polarity = polarity;
+ self->phase = phase;
+ self->bits = bits;
+ return true;
+}
+
+bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
+ bool grabbed_lock = false;
+
+ //Critical section code that may be required at some point.
+ // uint32_t store_primask = __get_PRIMASK();
+ // __disable_irq();
+ // __DMB();
+
+ if (!self->has_lock) {
+ grabbed_lock = true;
+ self->has_lock = true;
+ }
+
+ // __DMB();
+ // __set_PRIMASK(store_primask);
+
+ return grabbed_lock;
+}
+
+bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
+ return self->has_lock;
+}
+
+void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
+ self->has_lock = false;
+}
+
+bool common_hal_busio_spi_write(busio_spi_obj_t *self,
+ const uint8_t *data, size_t len) {
+ HAL_StatusTypeDef result = HAL_SPI_Transmit (&self->handle, (uint8_t *)data, (uint16_t)len, HAL_MAX_DELAY);
+ return result == HAL_OK;
+}
+
+bool common_hal_busio_spi_read(busio_spi_obj_t *self,
+ uint8_t *data, size_t len, uint8_t write_value) {
+ HAL_StatusTypeDef result = HAL_SPI_Receive (&self->handle, data, (uint16_t)len, HAL_MAX_DELAY);
+ return result == HAL_OK;
+}
+
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self,
+ uint8_t *data_out, uint8_t *data_in, size_t len) {
+ HAL_StatusTypeDef result = HAL_SPI_TransmitReceive (&self->handle,
+ data_out, data_in, (uint16_t)len,HAL_MAX_DELAY);
+ return result == HAL_OK;
+}
+
+uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
+ //returns actual frequency
+ uint32_t result = HAL_RCC_GetPCLK2Freq()/self->prescaler;
+ return result;
+}
+
+uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t* self) {
+ return self->phase;
+}
+
+uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self) {
+ return self->polarity;
+} \ No newline at end of file
diff --git a/ports/stm32f4/common-hal/busio/SPI.h b/ports/stm32f4/common-hal/busio/SPI.h
new file mode 100644
index 000000000..067d2fcb6
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/SPI.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_COMMON_HAL_BUSIO_SPI_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_SPI_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4/periph.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ SPI_HandleTypeDef handle;
+ bool has_lock;
+ const mcu_spi_sck_obj_t *sck;
+ const mcu_spi_mosi_obj_t *mosi;
+ const mcu_spi_miso_obj_t *miso;
+ const mcu_spi_nss_obj_t *nss;
+ uint32_t baudrate;
+ uint16_t prescaler;
+ uint8_t polarity;
+ uint8_t phase;
+ uint8_t bits;
+} busio_spi_obj_t;
+
+void spi_reset(void);
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_SPI_H
diff --git a/ports/stm32f4/common-hal/busio/UART.c b/ports/stm32f4/common-hal/busio/UART.c
new file mode 100644
index 000000000..e1810b131
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/UART.c
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * 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/microcontroller/__init__.h"
+#include "shared-bindings/busio/UART.h"
+
+#include "mpconfigport.h"
+#include "lib/utils/interrupt_char.h"
+#include "py/gc.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+
+#include "tick.h"
+
+void common_hal_busio_uart_construct(busio_uart_obj_t *self,
+ const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate,
+ uint8_t bits, uart_parity_t parity, uint8_t stop, mp_float_t timeout,
+ uint16_t receiver_buffer_size) {
+ mp_raise_NotImplementedError(translate("UART not yet supported"));
+}
+
+bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
+ return 0;
+}
+
+void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
+}
+
+// Read characters.
+size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) {
+ return 0;
+}
+
+// Write characters.
+size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
+ return 0;
+}
+
+uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) {
+ return 0;
+}
+
+void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) {
+}
+
+uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
+ return 0;
+}
+
+void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
+}
+
+bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
+ return 0;
+}
diff --git a/ports/stm32f4/common-hal/busio/UART.h b/ports/stm32f4/common-hal/busio/UART.h
new file mode 100644
index 000000000..699233934
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/UART.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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_STM32F4_COMMON_HAL_BUSIO_UART_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_UART_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t rx_pin;
+ uint8_t tx_pin;
+ uint8_t character_bits;
+ bool rx_error;
+ uint32_t baudrate;
+ uint32_t timeout_ms;
+ uint32_t buffer_length;
+ uint8_t* buffer;
+} busio_uart_obj_t;
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_BUSIO_UART_H
diff --git a/ports/stm32f4/common-hal/busio/__init__.c b/ports/stm32f4/common-hal/busio/__init__.c
new file mode 100644
index 000000000..41761b674
--- /dev/null
+++ b/ports/stm32f4/common-hal/busio/__init__.c
@@ -0,0 +1 @@
+// No busio module functions.
diff --git a/ports/stm32f4/common-hal/digitalio/DigitalInOut.c b/ports/stm32f4/common-hal/digitalio/DigitalInOut.c
new file mode 100644
index 000000000..51b1fde73
--- /dev/null
+++ b/ports/stm32f4/common-hal/digitalio/DigitalInOut.c
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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/digitalio/DigitalInOut.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4xx_ll_gpio.h"
+
+void common_hal_digitalio_digitalinout_never_reset(
+ digitalio_digitalinout_obj_t *self) {
+ never_reset_pin_number(self->pin->port, self->pin->number);
+}
+
+digitalinout_result_t common_hal_digitalio_digitalinout_construct(
+ digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) {
+
+ claim_pin(pin);
+ self->pin = pin;
+
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ GPIO_InitStruct.Pin = pin_mask(self->pin->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(pin_port(self->pin->port), &GPIO_InitStruct);
+
+ return DIGITALINOUT_OK;
+}
+
+bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self) {
+ return self->pin == mp_const_none;
+}
+
+void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self) {
+ if (common_hal_digitalio_digitalinout_deinited(self)) {
+ return;
+ }
+
+ reset_pin_number(self->pin->port, self->pin->number);
+ self->pin = mp_const_none;
+}
+
+void common_hal_digitalio_digitalinout_switch_to_input(
+ digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
+
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ GPIO_InitStruct.Pin = pin_mask(self->pin->number);
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(pin_port(self->pin->port), &GPIO_InitStruct);
+
+ common_hal_digitalio_digitalinout_set_pull(self, pull);
+}
+
+void common_hal_digitalio_digitalinout_switch_to_output(
+ digitalio_digitalinout_obj_t *self, bool value,
+ digitalio_drive_mode_t drive_mode) {
+
+ common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode);
+ common_hal_digitalio_digitalinout_set_value(self, value);
+}
+
+digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
+ digitalio_digitalinout_obj_t *self) {
+
+ return (LL_GPIO_GetPinMode(pin_port(self->pin->port), pin_mask(self->pin->number))
+ == LL_GPIO_MODE_INPUT) ? DIRECTION_INPUT : DIRECTION_OUTPUT;
+}
+
+void common_hal_digitalio_digitalinout_set_value(
+ digitalio_digitalinout_obj_t *self, bool value) {
+ HAL_GPIO_WritePin(pin_port(self->pin->port), pin_mask(self->pin->number), value);
+}
+
+bool common_hal_digitalio_digitalinout_get_value(
+ digitalio_digitalinout_obj_t *self) {
+ return (LL_GPIO_GetPinMode(pin_port(self->pin->port), pin_mask(self->pin->number)) == LL_GPIO_MODE_INPUT)
+ ? HAL_GPIO_ReadPin(pin_port(self->pin->port), pin_mask(self->pin->number))
+ : LL_GPIO_IsOutputPinSet(pin_port(self->pin->port), pin_mask(self->pin->number));
+}
+
+void common_hal_digitalio_digitalinout_set_drive_mode(
+ digitalio_digitalinout_obj_t *self,
+ digitalio_drive_mode_t drive_mode) {
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ GPIO_InitStruct.Pin = pin_mask(self->pin->number);
+ GPIO_InitStruct.Mode = (drive_mode == DRIVE_MODE_OPEN_DRAIN ?
+ GPIO_MODE_OUTPUT_OD : GPIO_MODE_OUTPUT_PP);
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(pin_port(self->pin->port), &GPIO_InitStruct);
+}
+
+digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
+ digitalio_digitalinout_obj_t *self) {
+
+ return LL_GPIO_GetPinOutputType(pin_port(self->pin->port), pin_mask(self->pin->number))
+ == LL_GPIO_OUTPUT_OPENDRAIN ? DRIVE_MODE_OPEN_DRAIN : DRIVE_MODE_PUSH_PULL;
+}
+
+void common_hal_digitalio_digitalinout_set_pull(
+ digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
+
+ switch (pull) {
+ case PULL_UP:
+ LL_GPIO_SetPinPull(pin_port(self->pin->port), pin_mask(self->pin->number),LL_GPIO_PULL_UP);
+ break;
+ case PULL_DOWN:
+ LL_GPIO_SetPinPull(pin_port(self->pin->port), pin_mask(self->pin->number),LL_GPIO_PULL_DOWN);
+ break;
+ case PULL_NONE:
+ LL_GPIO_SetPinPull(pin_port(self->pin->port), pin_mask(self->pin->number),LL_GPIO_PULL_NO);
+ break;
+ default:
+ break;
+ }
+}
+
+digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
+ digitalio_digitalinout_obj_t *self) {
+
+
+ switch (LL_GPIO_GetPinPull(pin_port(self->pin->port), pin_mask(self->pin->number))) {
+ case LL_GPIO_PULL_UP:
+ return PULL_UP;
+ case LL_GPIO_PULL_DOWN:
+ return PULL_DOWN;
+ case LL_GPIO_PULL_NO:
+ return PULL_NONE;
+ default:
+ return PULL_NONE;
+ }
+}
diff --git a/ports/stm32f4/common-hal/digitalio/DigitalInOut.h b/ports/stm32f4/common-hal/digitalio/DigitalInOut.h
new file mode 100644
index 000000000..76aa2c855
--- /dev/null
+++ b/ports/stm32f4/common-hal/digitalio/DigitalInOut.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ const mcu_pin_obj_t *pin;
+} digitalio_digitalinout_obj_t;
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
diff --git a/ports/stm32f4/common-hal/digitalio/__init__.c b/ports/stm32f4/common-hal/digitalio/__init__.c
new file mode 100644
index 000000000..20fad4595
--- /dev/null
+++ b/ports/stm32f4/common-hal/digitalio/__init__.c
@@ -0,0 +1 @@
+// No digitalio module functions.
diff --git a/ports/stm32f4/common-hal/microcontroller/Pin.c b/ports/stm32f4/common-hal/microcontroller/Pin.c
new file mode 100644
index 000000000..5761d7fb1
--- /dev/null
+++ b/ports/stm32f4/common-hal/microcontroller/Pin.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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/microcontroller/Pin.h"
+
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+#include "stm32f4xx_hal.h"
+
+#if MCU_PACKAGE == 144
+ #define GPIO_PORT_COUNT 7
+ GPIO_TypeDef * ports[GPIO_PORT_COUNT] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG};
+#elif MCU_PACKAGE == 100
+ #define GPIO_PORT_COUNT 5
+ GPIO_TypeDef * ports[GPIO_PORT_COUNT] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE};
+#elif MCU_PACKAGE == 64
+ #define GPIO_PORT_COUNT 3
+ GPIO_TypeDef * ports[GPIO_PORT_COUNT] = {GPIOA, GPIOB, GPIOC};
+#endif
+
+STATIC uint16_t claimed_pins[GPIO_PORT_COUNT];
+STATIC uint16_t never_reset_pins[GPIO_PORT_COUNT];
+
+void reset_all_pins(void) {
+ // Reset claimed pins
+ for (uint8_t i = 0; i < GPIO_PORT_COUNT; i++) {
+ claimed_pins[i] = never_reset_pins[i];
+ }
+ for (uint8_t i = 0; i < GPIO_PORT_COUNT; i++) {
+ HAL_GPIO_DeInit(ports[i], ~never_reset_pins[i]);
+ }
+}
+
+// Mark pin as free and return it to a quiescent state.
+void reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
+ if (pin_port == 0x0F) {
+ return;
+ }
+
+ // Clear claimed bit.
+ claimed_pins[pin_port] &= ~(1<<pin_number);
+ // Reset the pin
+ HAL_GPIO_DeInit(ports[pin_port], 1<<pin_number);
+}
+
+
+void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
+ never_reset_pins[pin_port] |= 1<<pin_number;
+}
+
+void claim_pin(const mcu_pin_obj_t* pin) {
+ // Set bit in claimed_pins bitmask.
+ claimed_pins[pin->port] |= 1<<pin->number;
+}
+
+bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) {
+ return !(claimed_pins[pin_port] & 1<<pin_number);
+}
+
+bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
+ return pin_number_is_free(pin->port, pin->number);
+}
+
+GPIO_TypeDef * pin_port(uint8_t pin_port) {
+ return ports[pin_port];
+}
+
+uint16_t pin_mask(uint8_t pin_number) {
+ return 1<<pin_number;
+}
diff --git a/ports/stm32f4/common-hal/microcontroller/Pin.h b/ports/stm32f4/common-hal/microcontroller/Pin.h
new file mode 100644
index 000000000..0c3fb375f
--- /dev/null
+++ b/ports/stm32f4/common-hal/microcontroller/Pin.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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_STM34F4_COMMON_HAL_MICROCONTROLLER_PIN_H
+#define MICROPY_INCLUDED_STM34F4_COMMON_HAL_MICROCONTROLLER_PIN_H
+
+#include "py/mphal.h"
+
+#include "peripherals/stm32f4/pins.h"
+
+void reset_all_pins(void);
+// reset_pin_number takes the pin number instead of the pointer so that objects don't
+// need to store a full pointer.
+void reset_pin_number(uint8_t pin_port, uint8_t pin_number);
+void claim_pin(const mcu_pin_obj_t* pin);
+bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number);
+void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number);
+GPIO_TypeDef * pin_port(uint8_t pin_port);
+uint16_t pin_mask(uint8_t pin_number);
+
+#endif // MICROPY_INCLUDED_STM34F4_COMMON_HAL_MICROCONTROLLER_PIN_H
diff --git a/ports/stm32f4/common-hal/microcontroller/Processor.c b/ports/stm32f4/common-hal/microcontroller/Processor.c
new file mode 100644
index 000000000..c16bd3125
--- /dev/null
+++ b/ports/stm32f4/common-hal/microcontroller/Processor.c
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/microcontroller/Processor.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+#include "stm32f4xx_hal.h"
+
+#define STM32_UUID ((uint32_t *)0x1FFF7A10)
+
+float common_hal_mcu_processor_get_temperature(void) {
+ return 0;
+}
+
+uint32_t common_hal_mcu_processor_get_frequency(void) {
+ return SystemCoreClock;
+}
+
+void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
+ for (int i=0; i<3; i++) {
+ ((uint32_t*) raw_id)[i] = STM32_UUID[i];
+ }
+}
diff --git a/ports/stm32f4/common-hal/microcontroller/Processor.h b/ports/stm32f4/common-hal/microcontroller/Processor.h
new file mode 100644
index 000000000..311333e7d
--- /dev/null
+++ b/ports/stm32f4/common-hal/microcontroller/Processor.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
+
+#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 12
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ // Stores no state currently.
+} mcu_processor_obj_t;
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
diff --git a/ports/stm32f4/common-hal/microcontroller/__init__.c b/ports/stm32f4/common-hal/microcontroller/__init__.c
new file mode 100644
index 000000000..4a6fdc388
--- /dev/null
+++ b/ports/stm32f4/common-hal/microcontroller/__init__.c
@@ -0,0 +1,205 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mphal.h"
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/microcontroller/Processor.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Processor.h"
+
+#include "supervisor/filesystem.h"
+#include "supervisor/shared/safe_mode.h"
+
+// This routine should work even when interrupts are disabled. Used by OneWire
+// for precise timing.
+void common_hal_mcu_delay_us(uint32_t delay) {
+ //TODO: implement equivalent of mp_hal_delay_us(delay);
+ //this is fairly annoying in the STM32 HAL
+}
+
+void common_hal_mcu_disable_interrupts() {
+}
+
+void common_hal_mcu_enable_interrupts() {
+}
+
+void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
+ if(runmode == RUNMODE_SAFE_MODE)
+ safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE);
+}
+
+void common_hal_mcu_reset(void) {
+ filesystem_flush();
+ NVIC_SystemReset();
+}
+
+// The singleton microcontroller.Processor object, bound to microcontroller.cpu
+// It currently only has properties, and no state.
+const mcu_processor_obj_t common_hal_mcu_processor_obj = {
+ .base = {
+ .type = &mcu_processor_type,
+ },
+};
+
+STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = {
+#if MCU_PACKAGE >= 100
+ { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) },
+ { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) },
+ { MP_ROM_QSTR(MP_QSTR_PE04), MP_ROM_PTR(&pin_PE04) },
+ { MP_ROM_QSTR(MP_QSTR_PE05), MP_ROM_PTR(&pin_PE05) },
+ { MP_ROM_QSTR(MP_QSTR_PE06), MP_ROM_PTR(&pin_PE06) },
+#endif
+ { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) },
+#if MCU_PACKAGE == 144
+ { MP_ROM_QSTR(MP_QSTR_PF00), MP_ROM_PTR(&pin_PF00) },
+ { MP_ROM_QSTR(MP_QSTR_PF01), MP_ROM_PTR(&pin_PF01) },
+ { MP_ROM_QSTR(MP_QSTR_PF02), MP_ROM_PTR(&pin_PF02) },
+ { MP_ROM_QSTR(MP_QSTR_PF03), MP_ROM_PTR(&pin_PF03) },
+ { MP_ROM_QSTR(MP_QSTR_PF04), MP_ROM_PTR(&pin_PF04) },
+ { MP_ROM_QSTR(MP_QSTR_PF05), MP_ROM_PTR(&pin_PF05) },
+ { MP_ROM_QSTR(MP_QSTR_PF06), MP_ROM_PTR(&pin_PF06) },
+ { MP_ROM_QSTR(MP_QSTR_PF07), MP_ROM_PTR(&pin_PF07) },
+ { MP_ROM_QSTR(MP_QSTR_PF08), MP_ROM_PTR(&pin_PF08) },
+ { MP_ROM_QSTR(MP_QSTR_PF09), MP_ROM_PTR(&pin_PF09) },
+ { MP_ROM_QSTR(MP_QSTR_PF10), MP_ROM_PTR(&pin_PF10) },
+#endif
+ { MP_ROM_QSTR(MP_QSTR_PC00), MP_ROM_PTR(&pin_PC00) },
+ { MP_ROM_QSTR(MP_QSTR_PC01), MP_ROM_PTR(&pin_PC01) },
+ { MP_ROM_QSTR(MP_QSTR_PC02), MP_ROM_PTR(&pin_PC02) },
+ { MP_ROM_QSTR(MP_QSTR_PC03), MP_ROM_PTR(&pin_PC03) },
+ { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_PC04), MP_ROM_PTR(&pin_PC04) },
+ { MP_ROM_QSTR(MP_QSTR_PC05), MP_ROM_PTR(&pin_PC05) },
+ { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) },
+ { MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_PB02), MP_ROM_PTR(&pin_PB02) },
+#if MCU_PACKAGE == 144
+ { MP_ROM_QSTR(MP_QSTR_PF11), MP_ROM_PTR(&pin_PF11) },
+ { MP_ROM_QSTR(MP_QSTR_PF12), MP_ROM_PTR(&pin_PF12) },
+ { MP_ROM_QSTR(MP_QSTR_PF13), MP_ROM_PTR(&pin_PF13) },
+ { MP_ROM_QSTR(MP_QSTR_PF14), MP_ROM_PTR(&pin_PF14) },
+ { MP_ROM_QSTR(MP_QSTR_PF15), MP_ROM_PTR(&pin_PF15) },
+ { MP_ROM_QSTR(MP_QSTR_PG00), MP_ROM_PTR(&pin_PG00) },
+ { MP_ROM_QSTR(MP_QSTR_PG01), MP_ROM_PTR(&pin_PG01) },
+#endif
+#if MCU_PACKAGE >= 100
+ { MP_ROM_QSTR(MP_QSTR_PE07), MP_ROM_PTR(&pin_PE07) },
+ { MP_ROM_QSTR(MP_QSTR_PE08), MP_ROM_PTR(&pin_PE08) },
+ { MP_ROM_QSTR(MP_QSTR_PE09), MP_ROM_PTR(&pin_PE09) },
+ { MP_ROM_QSTR(MP_QSTR_PE10), MP_ROM_PTR(&pin_PE10) },
+ { MP_ROM_QSTR(MP_QSTR_PE11), MP_ROM_PTR(&pin_PE11) },
+ { MP_ROM_QSTR(MP_QSTR_PE12), MP_ROM_PTR(&pin_PE12) },
+ { MP_ROM_QSTR(MP_QSTR_PE13), MP_ROM_PTR(&pin_PE13) },
+ { MP_ROM_QSTR(MP_QSTR_PE14), MP_ROM_PTR(&pin_PE14) },
+ { MP_ROM_QSTR(MP_QSTR_PE15), MP_ROM_PTR(&pin_PE15) },
+#endif
+ { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) },
+#if MCU_PACKAGE != 100
+ { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) },
+#endif
+ { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) },
+#if MCU_PACKAGE >= 100
+ { MP_ROM_QSTR(MP_QSTR_PD08), MP_ROM_PTR(&pin_PD08) },
+ { MP_ROM_QSTR(MP_QSTR_PD09), MP_ROM_PTR(&pin_PD09) },
+ { MP_ROM_QSTR(MP_QSTR_PD10), MP_ROM_PTR(&pin_PD10) },
+ { MP_ROM_QSTR(MP_QSTR_PD11), MP_ROM_PTR(&pin_PD11) },
+ { MP_ROM_QSTR(MP_QSTR_PD12), MP_ROM_PTR(&pin_PD12) },
+ { MP_ROM_QSTR(MP_QSTR_PD13), MP_ROM_PTR(&pin_PD13) },
+ { MP_ROM_QSTR(MP_QSTR_PD14), MP_ROM_PTR(&pin_PD14) },
+ { MP_ROM_QSTR(MP_QSTR_PD15), MP_ROM_PTR(&pin_PD15) },
+#endif
+#if MCU_PACKAGE == 144
+ { MP_ROM_QSTR(MP_QSTR_PG02), MP_ROM_PTR(&pin_PG02) },
+ { MP_ROM_QSTR(MP_QSTR_PG03), MP_ROM_PTR(&pin_PG03) },
+ { MP_ROM_QSTR(MP_QSTR_PG04), MP_ROM_PTR(&pin_PG04) },
+ { MP_ROM_QSTR(MP_QSTR_PG05), MP_ROM_PTR(&pin_PG05) },
+ { MP_ROM_QSTR(MP_QSTR_PG06), MP_ROM_PTR(&pin_PG06) },
+ { MP_ROM_QSTR(MP_QSTR_PG07), MP_ROM_PTR(&pin_PG07) },
+ { MP_ROM_QSTR(MP_QSTR_PG08), MP_ROM_PTR(&pin_PG08) },
+#endif
+ { MP_ROM_QSTR(MP_QSTR_PC06), MP_ROM_PTR(&pin_PC06) },
+ { MP_ROM_QSTR(MP_QSTR_PC07), MP_ROM_PTR(&pin_PC07) },
+ { MP_ROM_QSTR(MP_QSTR_PC08), MP_ROM_PTR(&pin_PC08) },
+ { MP_ROM_QSTR(MP_QSTR_PC09), MP_ROM_PTR(&pin_PC09) },
+ { MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_PA09), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_PC10), MP_ROM_PTR(&pin_PC10) },
+ { MP_ROM_QSTR(MP_QSTR_PC11), MP_ROM_PTR(&pin_PC11) },
+ { MP_ROM_QSTR(MP_QSTR_PC12), MP_ROM_PTR(&pin_PC12) },
+#if MCU_PACKAGE >= 100
+ { MP_ROM_QSTR(MP_QSTR_PD00), MP_ROM_PTR(&pin_PD00) },
+ { MP_ROM_QSTR(MP_QSTR_PD01), MP_ROM_PTR(&pin_PD01) },
+ { MP_ROM_QSTR(MP_QSTR_PD02), MP_ROM_PTR(&pin_PD02) },
+ { MP_ROM_QSTR(MP_QSTR_PD03), MP_ROM_PTR(&pin_PD03) },
+ { MP_ROM_QSTR(MP_QSTR_PD04), MP_ROM_PTR(&pin_PD04) },
+ { MP_ROM_QSTR(MP_QSTR_PD05), MP_ROM_PTR(&pin_PD05) },
+ { MP_ROM_QSTR(MP_QSTR_PD06), MP_ROM_PTR(&pin_PD06) },
+ { MP_ROM_QSTR(MP_QSTR_PD07), MP_ROM_PTR(&pin_PD07) },
+#endif
+#if MCU_PACKAGE == 144
+ { MP_ROM_QSTR(MP_QSTR_PG09), MP_ROM_PTR(&pin_PG09) },
+ { MP_ROM_QSTR(MP_QSTR_PG10), MP_ROM_PTR(&pin_PG10) },
+ { MP_ROM_QSTR(MP_QSTR_PG11), MP_ROM_PTR(&pin_PG11) },
+ { MP_ROM_QSTR(MP_QSTR_PG12), MP_ROM_PTR(&pin_PG12) },
+ { MP_ROM_QSTR(MP_QSTR_PG13), MP_ROM_PTR(&pin_PG13) },
+ { MP_ROM_QSTR(MP_QSTR_PG14), MP_ROM_PTR(&pin_PG14) },
+ { MP_ROM_QSTR(MP_QSTR_PG15), MP_ROM_PTR(&pin_PG15) },
+#endif
+ { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) },
+#if MCU_PACKAGE >= 100
+ { MP_ROM_QSTR(MP_QSTR_PE00), MP_ROM_PTR(&pin_PE00) },
+ { MP_ROM_QSTR(MP_QSTR_PE01), MP_ROM_PTR(&pin_PE01) },
+#endif
+};
+MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_globals_table);
diff --git a/ports/stm32f4/common-hal/os/__init__.c b/ports/stm32f4/common-hal/os/__init__.c
new file mode 100644
index 000000000..aa80a02f5
--- /dev/null
+++ b/ports/stm32f4/common-hal/os/__init__.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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 "genhdr/mpversion.h"
+#include "py/mpconfig.h"
+#include "py/objstr.h"
+#include "py/objtuple.h"
+
+STATIC const qstr os_uname_info_fields[] = {
+ MP_QSTR_sysname, MP_QSTR_nodename,
+ MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
+};
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "stm32f4");
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "stm32f4");
+
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
+
+STATIC MP_DEFINE_ATTRTUPLE(
+ os_uname_info_obj,
+ os_uname_info_fields,
+ 5,
+ (mp_obj_t)&os_uname_info_sysname_obj,
+ (mp_obj_t)&os_uname_info_nodename_obj,
+ (mp_obj_t)&os_uname_info_release_obj,
+ (mp_obj_t)&os_uname_info_version_obj,
+ (mp_obj_t)&os_uname_info_machine_obj
+);
+
+mp_obj_t common_hal_os_uname(void) {
+ return (mp_obj_t)&os_uname_info_obj;
+}
+
+bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) {
+
+ for (uint32_t i = 0; i < length; i++) {
+ buffer[i] = 4; //read in my coffee dregs; the truest random number, chosen by Nrthalotep
+ //todo: spurn the gods, replace with actual code.
+ }
+ return true;
+} \ No newline at end of file
diff --git a/ports/stm32f4/common-hal/supervisor/Runtime.c b/ports/stm32f4/common-hal/supervisor/Runtime.c
new file mode 100755
index 000000000..feab6987d
--- /dev/null
+++ b/ports/stm32f4/common-hal/supervisor/Runtime.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * 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 <stdbool.h>
+#include "shared-bindings/supervisor/Runtime.h"
+#include "supervisor/serial.h"
+
+bool common_hal_get_serial_connected(void) {
+ return (bool) serial_connected();
+}
+
+bool common_hal_get_serial_bytes_available(void) {
+ return (bool) serial_bytes_available();
+}
+
diff --git a/ports/stm32f4/common-hal/supervisor/Runtime.h b/ports/stm32f4/common-hal/supervisor/Runtime.h
new file mode 100755
index 000000000..9a798e056
--- /dev/null
+++ b/ports/stm32f4/common-hal/supervisor/Runtime.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * 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_STM32F4_COMMON_HAL_SUPERVISOR_RUNTIME_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_SUPERVISOR_RUNTIME_H
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ // Stores no state currently.
+} super_runtime_obj_t;
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_SUPERVISOR_RUNTIME_H
diff --git a/ports/stm32f4/common-hal/supervisor/__init__.c b/ports/stm32f4/common-hal/supervisor/__init__.c
new file mode 100755
index 000000000..ac88556b4
--- /dev/null
+++ b/ports/stm32f4/common-hal/supervisor/__init__.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+#include "py/obj.h"
+
+#include "shared-bindings/supervisor/__init__.h"
+#include "shared-bindings/supervisor/Runtime.h"
+
+
+// The singleton supervisor.Runtime object, bound to supervisor.runtime
+// It currently only has properties, and no state.
+const super_runtime_obj_t common_hal_supervisor_runtime_obj = {
+ .base = {
+ .type = &supervisor_runtime_type,
+ },
+}; \ No newline at end of file
diff --git a/ports/stm32f4/common-hal/time/__init__.c b/ports/stm32f4/common-hal/time/__init__.c
new file mode 100644
index 000000000..e3cb481ef
--- /dev/null
+++ b/ports/stm32f4/common-hal/time/__init__.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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 "py/mphal.h"
+
+#include "tick.h"
+
+uint64_t common_hal_time_monotonic(void) {
+ return ticks_ms;
+}
+
+void common_hal_time_delay_ms(uint32_t delay) {
+ mp_hal_delay_ms(delay);
+}
diff --git a/ports/stm32f4/fatfs_port.c b/ports/stm32f4/fatfs_port.c
new file mode 100644
index 000000000..13ac21fb1
--- /dev/null
+++ b/ports/stm32f4/fatfs_port.c
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "lib/oofatfs/ff.h"
+
+DWORD get_fattime(void) {
+ // TODO: Implement this function. For now, fake it.
+ return ((2016 - 1980) << 25) | ((12) << 21) | ((4) << 16) | ((00) << 11) | ((18) << 5) | (23 / 2);
+}
diff --git a/ports/stm32f4/mpconfigport.h b/ports/stm32f4/mpconfigport.h
new file mode 100644
index 000000000..543a55942
--- /dev/null
+++ b/ports/stm32f4/mpconfigport.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Glenn Ruben Bakke
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef STM32F4_MPCONFIGPORT_H__
+#define STM32F4_MPCONFIGPORT_H__
+
+#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
+#define MICROPY_PY_FUNCTION_ATTRS (1)
+#define MICROPY_PY_IO (1)
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
+#define MICROPY_PY_UJSON (1)
+
+// 24kiB stack
+#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000
+
+#include "py/circuitpy_mpconfig.h"
+
+#define MICROPY_PORT_ROOT_POINTERS \
+ CIRCUITPY_COMMON_ROOT_POINTERS
+
+#endif // __INCLUDED_MPCONFIGPORT_H
diff --git a/ports/stm32f4/mpconfigport.mk b/ports/stm32f4/mpconfigport.mk
new file mode 100644
index 000000000..0dd4862ec
--- /dev/null
+++ b/ports/stm32f4/mpconfigport.mk
@@ -0,0 +1,29 @@
+# Define an equivalent for MICROPY_LONGINT_IMPL, to pass to $(MPY-TOOL) in py/mkrules.mk
+# $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers.
+# This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h.
+MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
+
+# Internal math library is substantially smaller than toolchain one
+INTERNAL_LIBM = 1
+
+# Chip supplied serial number, in bytes
+USB_SERIAL_NUMBER_LENGTH = 24
+
+# Longints can be implemented as mpz, as longlong, or not
+LONGINT_IMPL = MPZ
+
+#Reduced feature set for early port
+CIRCUITPY_MINIMAL_BUILD = 1
+
+CIRCUITPY_BOARD = 1
+CIRCUITPY_DIGITALIO = 1
+CIRCUITPY_ANALOGIO = 1
+CIRCUITPY_MICROCONTROLLER = 1
+CIRCUITPY_BUSIO = 1
+CIRCUITPY_TIME = 1
+CIRCUITPY_OS = 1
+CIRCUITPY_STRUCT = 1
+CIRCUITPY_MATH = 1
+
+#ifeq ($(MCU_SUB_VARIANT), stm32f412zx)
+#endif
diff --git a/ports/stm32f4/mphalport.c b/ports/stm32f4/mphalport.c
new file mode 100644
index 000000000..ea864e7ce
--- /dev/null
+++ b/ports/stm32f4/mphalport.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "py/mphal.h"
+#include "py/mpstate.h"
+#include "py/gc.h"
+
+/*------------------------------------------------------------------*/
+/* delay
+ *------------------------------------------------------------------*/
+void mp_hal_delay_ms(mp_uint_t delay) {
+ uint64_t start_tick = ticks_ms;
+ uint64_t duration = 0;
+ while (duration < delay) {
+ #ifdef MICROPY_VM_HOOK_LOOP
+ MICROPY_VM_HOOK_LOOP
+ #endif
+ // Check to see if we've been CTRL-Ced by autoreload or the user.
+ if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) ||
+ MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
+ break;
+ }
+ duration = (ticks_ms - start_tick);
+ // TODO(tannewt): Go to sleep for a little while while we wait.
+ }
+}
diff --git a/ports/stm32f4/mphalport.h b/ports/stm32f4/mphalport.h
new file mode 100644
index 000000000..131f2751d
--- /dev/null
+++ b/ports/stm32f4/mphalport.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef __STM32F4_HAL
+#define __STM32F4_HAL
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "lib/utils/interrupt_char.h"
+#include "py/mpconfig.h"
+
+//extern nrfx_uarte_t serial_instance;
+
+extern volatile uint64_t ticks_ms;
+
+#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms)
+//#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us))
+
+bool mp_hal_stdin_any(void);
+
+#endif
diff --git a/ports/stm32f4/peripherals/stm32f4/clocks.h b/ports/stm32f4/peripherals/stm32f4/clocks.h
new file mode 100644
index 000000000..c7ba84662
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/clocks.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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.
+ */
+
+void stm32f4_peripherals_clocks_init(void);
diff --git a/ports/stm32f4/peripherals/stm32f4/gpio.h b/ports/stm32f4/peripherals/stm32f4/gpio.h
new file mode 100644
index 000000000..34f89e792
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/gpio.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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.
+ */
+
+void stm32f4_peripherals_gpio_init(void);
+void stm32f4_peripherals_status_led(uint8_t led, uint8_t state);
diff --git a/ports/stm32f4/peripherals/stm32f4/periph.h b/ports/stm32f4/peripherals/stm32f4/periph.h
new file mode 100644
index 000000000..06ab2d3e4
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/periph.h
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_PERIPH_H__
+#define __MICROPY_INCLUDED_STM32F4_PERIPHERALS_PERIPH_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4/pins.h"
+
+// I2C
+//TODO: these objects should be condensed into a single 'periph_pin' unless we
+//find a compelling reason to store more unique data in them.
+
+typedef struct {
+ uint8_t i2c_index:4; // Index of the I2C unit (1 to 3)
+ uint8_t altfn_index:4; //Index of the altfn for this pin (0 to 15)
+ const mcu_pin_obj_t * pin;
+} mcu_i2c_sda_obj_t;
+
+typedef struct {
+ uint8_t i2c_index:4;
+ uint8_t altfn_index:4;
+ const mcu_pin_obj_t * pin;
+} mcu_i2c_scl_obj_t;
+
+
+#define I2C_SDA(index, alt, sda_pin) \
+{ \
+ .i2c_index = index, \
+ .altfn_index = alt, \
+ .pin = sda_pin, \
+}
+
+#define I2C_SCL(index, alt, scl_pin) \
+{ \
+ .i2c_index = index, \
+ .altfn_index = alt, \
+ .pin = scl_pin, \
+}
+
+// SPI
+//TODO: these objects should be condensed into a single 'periph_pin' unless we
+//find a compelling reason to store more unique data in them.
+
+typedef struct {
+ uint8_t spi_index:4; //Up to 6 SPI units
+ uint8_t altfn_index:4; //Up to 15 alt channels
+ const mcu_pin_obj_t * pin;
+} mcu_spi_sck_obj_t;
+
+typedef struct {
+ uint8_t spi_index:4;
+ uint8_t altfn_index:4;
+ const mcu_pin_obj_t * pin;
+} mcu_spi_mosi_obj_t;
+
+typedef struct {
+ uint8_t spi_index:4;
+ uint8_t altfn_index:4;
+ const mcu_pin_obj_t * pin;
+} mcu_spi_miso_obj_t;
+
+typedef struct {
+ uint8_t spi_index:4;
+ uint8_t altfn_index:4;
+ const mcu_pin_obj_t * pin;
+} mcu_spi_nss_obj_t;
+
+#define SPI(index, alt, spi_pin) \
+{ \
+ .spi_index = index, \
+ .altfn_index = alt, \
+ .pin = spi_pin, \
+}
+
+// TODO: SPI, UART, etc
+
+// Choose based on chip
+#ifdef STM32F412Zx
+#include "stm32f412zx/periph.h"
+#endif
+#ifdef STM32F411xE
+#include "stm32f411xe/periph.h"
+#endif
+#ifdef STM32F405xx
+#include "stm32f405xx/periph.h"
+#endif
+#endif // __MICROPY_INCLUDED_STM32F4_PERIPHERALS_PERIPH_H__
diff --git a/ports/stm32f4/peripherals/stm32f4/pins.h b/ports/stm32f4/peripherals/stm32f4/pins.h
new file mode 100644
index 000000000..ced83562e
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/pins.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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.
+ */
+
+// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure
+// that all necessary includes are already included.
+
+#ifndef __MICROPY_INCLUDED_STM32F4_PERIPHERALS_PINS_H__
+#define __MICROPY_INCLUDED_STM32F4_PERIPHERALS_PINS_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "stm32f4xx_hal.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t port:4;
+ uint8_t number:4;
+ uint8_t adc_unit:3;
+ uint8_t adc_channel:5;
+} mcu_pin_obj_t;
+
+//Standard stm32 adc unit combinations
+#define ADC_1 1
+#define ADC_12 3
+#define ADC_123 7
+#define ADC_3 4
+
+//STM32 ADC pins can have a combination of 1, 2 or all 3 ADCs on a single pin,
+//but all 3 ADCs will share the same input number per pin.
+//F4 family has 3 ADC max, 24 channels max.
+#define ADC_INPUT(mask, number) \
+ .adc_unit = mask, \
+ .adc_channel = number,
+
+#define NO_ADC \
+ .adc_unit = 0x00, \
+ .adc_channel = 0x1f
+
+extern const mp_obj_type_t mcu_pin_type;
+
+// STM32 can have up to 9 ports, each restricted to 16 pins
+// We split the pin/port evenly, in contrast to nrf.
+#define PIN(p_port, p_number, p_adc) \
+{ \
+ { &mcu_pin_type }, \
+ .port = p_port, \
+ .number = p_number, \
+ p_adc \
+}
+
+// Use illegal pin value to mark unassigned pins.
+#define NO_PIN 0xff
+
+// Choose based on chip
+#ifdef STM32F412Zx
+#include "stm32f412zx/pins.h"
+#endif
+#ifdef STM32F411xE
+#include "stm32f411xe/pins.h"
+#endif
+#ifdef STM32F405xx
+#include "stm32f405xx/pins.h"
+#endif
+#endif // __MICROPY_INCLUDED_STM32F4_PERIPHERALS_PINS_H__
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/clocks.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/clocks.c
new file mode 100644
index 000000000..74eeb4b24
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/clocks.c
@@ -0,0 +1,63 @@
+
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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 "stm32f4xx_hal.h"
+
+void stm32f4_peripherals_clocks_init(void) {
+ //TODO: All parameters must be moved to board level, due to relationship with HSE Osc.
+
+ //System clock init
+ RCC_ClkInitTypeDef RCC_ClkInitStruct;
+ RCC_OscInitTypeDef RCC_OscInitStruct;
+
+ /* Enable Power Control clock */
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* The voltage scaling allows optimizing the power consumption when the device is
+ clocked below the maximum system frequency, to update the voltage scaling value
+ regarding system frequency refer to product datasheet. */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /* Enable HSE Oscillator and activate PLL with HSE as source */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLM = 12;
+ RCC_OscInitStruct.PLL.PLLN = 336;
+ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
+ RCC_OscInitStruct.PLL.PLLQ = 7;
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+ /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
+ clocks dividers */
+ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
+}
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/gpio.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/gpio.c
new file mode 100644
index 000000000..f9be3b4ec
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/gpio.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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 "stm32f4xx_hal.h"
+#include "stm32f4/gpio.h"
+#include "common-hal/microcontroller/Pin.h"
+
+void stm32f4_peripherals_gpio_init(void) {
+ //Enable all GPIO for now
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+
+ //Never reset pins
+ never_reset_pin_number(2,13); //PC13 anti tamp
+ never_reset_pin_number(2,14); //PC14 OSC32_IN
+ never_reset_pin_number(2,15); //PC15 OSC32_OUT
+ never_reset_pin_number(0,13); //PA13 SWDIO
+ never_reset_pin_number(0,14); //PA14 SWCLK
+ // never_reset_pin_number(0,15); //PA15 JTDI
+ // never_reset_pin_number(1,3); //PB3 JTDO
+ // never_reset_pin_number(1,4); //PB4 JTRST
+
+ // Port H is not included in GPIO port array
+ // never_reset_pin_number(5,0); //PH0 JTDO
+ // never_reset_pin_number(5,1); //PH1 JTRST
+}
+
+void stm32f4_peripherals_status_led(uint8_t led, uint8_t state) {
+
+}
+
+
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c
new file mode 100644
index 000000000..7b0a54e55
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c
@@ -0,0 +1,88 @@
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+#include "stm32f4/periph.h"
+
+// I2C
+
+I2C_TypeDef * mcu_i2c_banks[3] = {I2C1, I2C2, I2C3};
+
+const mcu_i2c_sda_obj_t mcu_i2c_sda_list[4] = {
+ I2C_SDA(1, 4, &pin_PB07),
+ I2C_SDA(1, 4, &pin_PB09),
+ I2C_SDA(2, 4, &pin_PB11),
+ I2C_SDA(3, 4, &pin_PC09),
+};
+
+const mcu_i2c_scl_obj_t mcu_i2c_scl_list[4] = {
+ I2C_SCL(1, 4, &pin_PB06),
+ I2C_SCL(1, 4, &pin_PB08),
+ I2C_SCL(2, 4, &pin_PB10),
+ I2C_SCL(3, 4, &pin_PA08)
+};
+
+SPI_TypeDef * mcu_spi_banks[3] = {SPI1, SPI2, SPI3};
+
+const mcu_spi_sck_obj_t mcu_spi_sck_list[7] = {
+ SPI(1, 5, &pin_PA05),
+ SPI(1, 5, &pin_PB03),
+ SPI(2, 5, &pin_PB10),
+ SPI(2, 5, &pin_PB13),
+ SPI(2, 5, &pin_PC07),
+ SPI(3, 6, &pin_PB03),
+ SPI(3, 6, &pin_PC10),
+};
+
+const mcu_spi_mosi_obj_t mcu_spi_mosi_list[6] = {
+ SPI(1, 5, &pin_PA07),
+ SPI(1, 5, &pin_PB05),
+ SPI(2, 5, &pin_PB15),
+ SPI(2, 5, &pin_PC03),
+ SPI(3, 6, &pin_PB05),
+ SPI(3, 6, &pin_PC12),
+};
+
+const mcu_spi_miso_obj_t mcu_spi_miso_list[6] = {
+ SPI(1, 5, &pin_PA06),
+ SPI(1, 5, &pin_PB04),
+ SPI(2, 5, &pin_PB14),
+ SPI(2, 5, &pin_PC02),
+ SPI(3, 6, &pin_PB04),
+ SPI(3, 6, &pin_PC11),
+};
+
+const mcu_spi_nss_obj_t mcu_spi_nss_list[6] = {
+ SPI(1, 5, &pin_PA04),
+ SPI(1, 5, &pin_PA15),
+ SPI(2, 5, &pin_PB09),
+ SPI(2, 5, &pin_PB12),
+ SPI(3, 6, &pin_PA04),
+ SPI(3, 6, &pin_PA15),
+};
+//UART, Etc
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h
new file mode 100644
index 000000000..cb9b33f6e
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H
+#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H
+
+//I2C
+extern I2C_TypeDef * mcu_i2c_banks[3];
+
+extern const mcu_i2c_sda_obj_t mcu_i2c_sda_list[4];
+extern const mcu_i2c_scl_obj_t mcu_i2c_scl_list[4];
+
+//SPI
+extern SPI_TypeDef * mcu_spi_banks[3];
+
+extern const mcu_spi_sck_obj_t mcu_spi_sck_list[7];
+extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[6];
+extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6];
+extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6];
+
+
+#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.c
new file mode 100644
index 000000000..86445fe14
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.c
@@ -0,0 +1,161 @@
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+
+const mcu_pin_obj_t pin_PE02 = PIN(4, 2, NO_ADC);
+const mcu_pin_obj_t pin_PE03 = PIN(4, 3, NO_ADC);
+const mcu_pin_obj_t pin_PE04 = PIN(4, 4, NO_ADC);
+const mcu_pin_obj_t pin_PE05 = PIN(4, 5, NO_ADC);
+const mcu_pin_obj_t pin_PE06 = PIN(4, 6, NO_ADC);
+
+const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC); //anti-tamp
+const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC); //OSC32_IN
+const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC); //OSC32_OUT
+
+const mcu_pin_obj_t pin_PF00 = PIN(5, 0, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF01 = PIN(5, 1, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF02 = PIN(5, 2, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF03 = PIN(5, 3, ADC_INPUT(ADC_3,9)); // 144 only
+const mcu_pin_obj_t pin_PF04 = PIN(5, 4, ADC_INPUT(ADC_3,14)); // 144 only
+const mcu_pin_obj_t pin_PF05 = PIN(5, 5, ADC_INPUT(ADC_3,15)); // 144 only
+const mcu_pin_obj_t pin_PF06 = PIN(5, 6, ADC_INPUT(ADC_3,4)); // 144 only
+const mcu_pin_obj_t pin_PF07 = PIN(5, 7, ADC_INPUT(ADC_3,5)); // 144 only
+const mcu_pin_obj_t pin_PF08 = PIN(5, 8, ADC_INPUT(ADC_3,6)); // 144 only
+const mcu_pin_obj_t pin_PF09 = PIN(5, 9, ADC_INPUT(ADC_3,7)); // 144 only
+const mcu_pin_obj_t pin_PF10 = PIN(5, 10, ADC_INPUT(ADC_3,8)); // 144 only
+
+const mcu_pin_obj_t pin_PC00 = PIN(2, 0, ADC_INPUT(ADC_123,10));
+const mcu_pin_obj_t pin_PC01 = PIN(2, 1, ADC_INPUT(ADC_123,11));
+const mcu_pin_obj_t pin_PC02 = PIN(2, 2, ADC_INPUT(ADC_123,12));
+const mcu_pin_obj_t pin_PC03 = PIN(2, 3, ADC_INPUT(ADC_123,13));
+
+const mcu_pin_obj_t pin_PA00 = PIN(0, 0, ADC_INPUT(ADC_123,0));
+const mcu_pin_obj_t pin_PA01 = PIN(0, 1, ADC_INPUT(ADC_123,1));
+const mcu_pin_obj_t pin_PA02 = PIN(0, 2, ADC_INPUT(ADC_123,2));
+const mcu_pin_obj_t pin_PA03 = PIN(0, 3, ADC_INPUT(ADC_123,3));
+const mcu_pin_obj_t pin_PA04 = PIN(0, 4, ADC_INPUT(ADC_12,4));
+const mcu_pin_obj_t pin_PA05 = PIN(0, 5, ADC_INPUT(ADC_12,5));
+const mcu_pin_obj_t pin_PA06 = PIN(0, 6, ADC_INPUT(ADC_12,6));
+const mcu_pin_obj_t pin_PA07 = PIN(0, 7, ADC_INPUT(ADC_12,7));
+
+const mcu_pin_obj_t pin_PC04 = PIN(2, 4, ADC_INPUT(ADC_12,14));
+const mcu_pin_obj_t pin_PC05 = PIN(2, 5, ADC_INPUT(ADC_12,15));
+
+const mcu_pin_obj_t pin_PB00 = PIN(1, 0, ADC_INPUT(ADC_12,8));
+const mcu_pin_obj_t pin_PB01 = PIN(1, 1, ADC_INPUT(ADC_12,9));
+const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC); //BOOT1
+
+const mcu_pin_obj_t pin_PF11 = PIN(5, 11, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF12 = PIN(5, 12, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF13 = PIN(5, 13, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF14 = PIN(5, 14, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF15 = PIN(5, 15, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PG00 = PIN(6, 0, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG01 = PIN(6, 1, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PE07 = PIN(4, 7, NO_ADC);
+const mcu_pin_obj_t pin_PE08 = PIN(4, 8, NO_ADC);
+const mcu_pin_obj_t pin_PE09 = PIN(4, 9, NO_ADC);
+const mcu_pin_obj_t pin_PE10 = PIN(4, 10, NO_ADC);
+const mcu_pin_obj_t pin_PE11 = PIN(4, 11, NO_ADC);
+const mcu_pin_obj_t pin_PE12 = PIN(4, 12, NO_ADC);
+const mcu_pin_obj_t pin_PE13 = PIN(4, 13, NO_ADC);
+const mcu_pin_obj_t pin_PE14 = PIN(4, 14, NO_ADC);
+const mcu_pin_obj_t pin_PE15 = PIN(4, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PB10 = PIN(1, 10, NO_ADC);
+const mcu_pin_obj_t pin_PB11 = PIN(1, 11, NO_ADC);
+const mcu_pin_obj_t pin_PB12 = PIN(1, 12, NO_ADC);
+const mcu_pin_obj_t pin_PB13 = PIN(1, 13, NO_ADC);
+const mcu_pin_obj_t pin_PB14 = PIN(1, 14, NO_ADC);
+const mcu_pin_obj_t pin_PB15 = PIN(1, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PD08 = PIN(3, 8, NO_ADC);
+const mcu_pin_obj_t pin_PD09 = PIN(3, 9, NO_ADC);
+const mcu_pin_obj_t pin_PD10 = PIN(3, 10, NO_ADC);
+const mcu_pin_obj_t pin_PD11 = PIN(3, 11, NO_ADC);
+const mcu_pin_obj_t pin_PD12 = PIN(3, 12, NO_ADC);
+const mcu_pin_obj_t pin_PD13 = PIN(3, 13, NO_ADC);
+const mcu_pin_obj_t pin_PD14 = PIN(3, 14, NO_ADC);
+const mcu_pin_obj_t pin_PD15 = PIN(3, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PG02 = PIN(6, 2, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG03 = PIN(6, 3, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG04 = PIN(6, 4, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG05 = PIN(6, 5, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG06 = PIN(6, 6, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG07 = PIN(6, 7, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG08 = PIN(6, 8, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PC06 = PIN(2, 6, NO_ADC);
+const mcu_pin_obj_t pin_PC07 = PIN(2, 7, NO_ADC);
+const mcu_pin_obj_t pin_PC08 = PIN(2, 8, NO_ADC);
+const mcu_pin_obj_t pin_PC09 = PIN(2, 9, NO_ADC);
+
+const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC);
+const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC);
+const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC);
+const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC);
+const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC);
+const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC);
+const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC);
+const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PC10 = PIN(2, 10, NO_ADC);
+const mcu_pin_obj_t pin_PC11 = PIN(2, 11, NO_ADC);
+const mcu_pin_obj_t pin_PC12 = PIN(2, 12, NO_ADC);
+
+const mcu_pin_obj_t pin_PD00 = PIN(3, 0, NO_ADC);
+const mcu_pin_obj_t pin_PD01 = PIN(3, 1, NO_ADC);
+const mcu_pin_obj_t pin_PD02 = PIN(3, 2, NO_ADC);
+const mcu_pin_obj_t pin_PD03 = PIN(3, 3, NO_ADC);
+const mcu_pin_obj_t pin_PD04 = PIN(3, 4, NO_ADC);
+const mcu_pin_obj_t pin_PD05 = PIN(3, 5, NO_ADC);
+const mcu_pin_obj_t pin_PD06 = PIN(3, 6, NO_ADC);
+const mcu_pin_obj_t pin_PD07 = PIN(3, 7, NO_ADC);
+
+const mcu_pin_obj_t pin_PG09 = PIN(6, 9, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG10 = PIN(6, 10, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG11 = PIN(6, 11, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG12 = PIN(6, 12, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG13 = PIN(6, 13, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG14 = PIN(6, 14, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG15 = PIN(6, 15, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC);
+const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC);
+const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC);
+const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC);
+const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC);
+const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC);
+const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC);
+
+const mcu_pin_obj_t pin_PE00 = PIN(4, 0, NO_ADC);
+const mcu_pin_obj_t pin_PE01 = PIN(4, 1, NO_ADC);
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.h
new file mode 100644
index 000000000..180f5c316
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/pins.h
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_STM32F412ZG_PINS_H
+#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F412ZG_PINS_H
+
+//Pins in datasheet order: DocID028087 Rev 7 page 50. LQFP100 only
+//pg 50
+extern const mcu_pin_obj_t pin_PE02;
+extern const mcu_pin_obj_t pin_PE03;
+extern const mcu_pin_obj_t pin_PE04;
+extern const mcu_pin_obj_t pin_PE05;
+extern const mcu_pin_obj_t pin_PE06;
+extern const mcu_pin_obj_t pin_PC13;
+extern const mcu_pin_obj_t pin_PC14;
+//pg 51
+extern const mcu_pin_obj_t pin_PC15;
+extern const mcu_pin_obj_t pin_PF00; // 144 only
+extern const mcu_pin_obj_t pin_PF01; // 144 only
+extern const mcu_pin_obj_t pin_PF02; // 144 only
+extern const mcu_pin_obj_t pin_PF03; // 144 only
+extern const mcu_pin_obj_t pin_PF04; // 144 only
+extern const mcu_pin_obj_t pin_PF05; // 144 only
+extern const mcu_pin_obj_t pin_PF06; // 144 only
+extern const mcu_pin_obj_t pin_PF07; // 144 only
+extern const mcu_pin_obj_t pin_PF08; // 144 only
+extern const mcu_pin_obj_t pin_PF09; // 144 only
+extern const mcu_pin_obj_t pin_PF10; // 144 only
+//pg 52
+extern const mcu_pin_obj_t pin_PC00;
+extern const mcu_pin_obj_t pin_PC01;
+extern const mcu_pin_obj_t pin_PC02;
+extern const mcu_pin_obj_t pin_PC03;
+extern const mcu_pin_obj_t pin_PA00;
+extern const mcu_pin_obj_t pin_PA01;
+extern const mcu_pin_obj_t pin_PA02;
+//pg 53
+extern const mcu_pin_obj_t pin_PA03;
+extern const mcu_pin_obj_t pin_PA04;
+extern const mcu_pin_obj_t pin_PA05;
+extern const mcu_pin_obj_t pin_PA06;
+extern const mcu_pin_obj_t pin_PA07;
+extern const mcu_pin_obj_t pin_PC04;
+//pg 54
+extern const mcu_pin_obj_t pin_PC05;
+extern const mcu_pin_obj_t pin_PB00;
+extern const mcu_pin_obj_t pin_PB01;
+extern const mcu_pin_obj_t pin_PB02;
+extern const mcu_pin_obj_t pin_PF11; // 144 only
+extern const mcu_pin_obj_t pin_PF12; // 144 only
+extern const mcu_pin_obj_t pin_PF13; // 144 only
+extern const mcu_pin_obj_t pin_PF14; // 144 only
+extern const mcu_pin_obj_t pin_PF15; // 144 only
+extern const mcu_pin_obj_t pin_PG00; // 144 only
+extern const mcu_pin_obj_t pin_PG01; // 144 only
+//pg 55
+extern const mcu_pin_obj_t pin_PE07;
+extern const mcu_pin_obj_t pin_PE08;
+extern const mcu_pin_obj_t pin_PE09;
+extern const mcu_pin_obj_t pin_PE10;
+extern const mcu_pin_obj_t pin_PE11;
+extern const mcu_pin_obj_t pin_PE12;
+extern const mcu_pin_obj_t pin_PE13;
+extern const mcu_pin_obj_t pin_PE14;
+//pg 56
+extern const mcu_pin_obj_t pin_PE15;
+extern const mcu_pin_obj_t pin_PB10;
+extern const mcu_pin_obj_t pin_PB11; // 144 only
+extern const mcu_pin_obj_t pin_PB12;
+extern const mcu_pin_obj_t pin_PB13;
+//pg 57
+extern const mcu_pin_obj_t pin_PB14;
+extern const mcu_pin_obj_t pin_PB15;
+extern const mcu_pin_obj_t pin_PD08;
+extern const mcu_pin_obj_t pin_PD09;
+extern const mcu_pin_obj_t pin_PD10;
+extern const mcu_pin_obj_t pin_PD11;
+extern const mcu_pin_obj_t pin_PD12;
+//pg 58
+extern const mcu_pin_obj_t pin_PD13;
+extern const mcu_pin_obj_t pin_PD14;
+extern const mcu_pin_obj_t pin_PD15;
+extern const mcu_pin_obj_t pin_PG02; // 144 only
+extern const mcu_pin_obj_t pin_PG03; // 144 only
+extern const mcu_pin_obj_t pin_PG04; // 144 only
+extern const mcu_pin_obj_t pin_PG05; // 144 only
+extern const mcu_pin_obj_t pin_PG06; // 144 only
+extern const mcu_pin_obj_t pin_PG07; // 144 only
+extern const mcu_pin_obj_t pin_PG08; // 144 only
+//pg 59
+extern const mcu_pin_obj_t pin_PC06;
+extern const mcu_pin_obj_t pin_PC07;
+extern const mcu_pin_obj_t pin_PC08;
+extern const mcu_pin_obj_t pin_PC09;
+extern const mcu_pin_obj_t pin_PA08;
+extern const mcu_pin_obj_t pin_PA09;
+extern const mcu_pin_obj_t pin_PA10;
+//pg 60
+extern const mcu_pin_obj_t pin_PA11;
+extern const mcu_pin_obj_t pin_PA12;
+extern const mcu_pin_obj_t pin_PA13;
+extern const mcu_pin_obj_t pin_PA14;
+extern const mcu_pin_obj_t pin_PA15;
+extern const mcu_pin_obj_t pin_PC10;
+extern const mcu_pin_obj_t pin_PC11;
+//pg 61
+extern const mcu_pin_obj_t pin_PC12;
+extern const mcu_pin_obj_t pin_PD00;
+extern const mcu_pin_obj_t pin_PD01;
+extern const mcu_pin_obj_t pin_PD02;
+extern const mcu_pin_obj_t pin_PD03;
+extern const mcu_pin_obj_t pin_PD04;
+extern const mcu_pin_obj_t pin_PD05;
+extern const mcu_pin_obj_t pin_PD06;
+extern const mcu_pin_obj_t pin_PD07;
+//pg 62
+extern const mcu_pin_obj_t pin_PG09; // 144 only
+extern const mcu_pin_obj_t pin_PG10; // 144 only
+extern const mcu_pin_obj_t pin_PG11; // 144 only
+extern const mcu_pin_obj_t pin_PG12; // 144 only
+extern const mcu_pin_obj_t pin_PG13; // 144 only
+extern const mcu_pin_obj_t pin_PG14; // 144 only
+extern const mcu_pin_obj_t pin_PG15; // 144 only
+extern const mcu_pin_obj_t pin_PB03;
+extern const mcu_pin_obj_t pin_PB04;
+//pg 63
+extern const mcu_pin_obj_t pin_PB05;
+extern const mcu_pin_obj_t pin_PB06;
+extern const mcu_pin_obj_t pin_PB07;
+extern const mcu_pin_obj_t pin_PB08;
+extern const mcu_pin_obj_t pin_PB09;
+extern const mcu_pin_obj_t pin_PE00;
+extern const mcu_pin_obj_t pin_PE01;
+
+#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F412ZG_PINS_H
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
new file mode 100644
index 000000000..883c252d5
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
@@ -0,0 +1,61 @@
+
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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 "stm32f4xx_hal.h"
+
+void stm32f4_peripherals_clocks_init(void) {
+ //System clock init
+ RCC_ClkInitTypeDef RCC_ClkInitStruct;
+ RCC_OscInitTypeDef RCC_OscInitStruct;
+
+ /* Enable Power Control clock */
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* The voltage scaling allows optimizing the power consumption when the device is
+ clocked below the maximum system frequency, to update the voltage scaling value
+ regarding system frequency refer to product datasheet. */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
+
+ /* Enable HSE Oscillator and activate PLL with HSE as source */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLM = 8;
+ RCC_OscInitStruct.PLL.PLLN = 336;
+ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
+ RCC_OscInitStruct.PLL.PLLQ = 7;
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+ /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
+ clocks dividers */
+ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
+}
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
new file mode 100644
index 000000000..2b80647c0
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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.
+ */
+
+/* GPIO PIN REFERENCE
+#define DATA_Ready_Pin GPIO_PIN_2
+#define DATA_Ready_GPIO_Port GPIOE
+#define CS_I2C_SPI_Pin GPIO_PIN_3
+#define CS_I2C_SPI_GPIO_Port GPIOE
+#define INT1_Pin GPIO_PIN_4
+#define INT1_GPIO_Port GPIOE
+#define INT2_Pin GPIO_PIN_5
+#define INT2_GPIO_Port GPIOE
+#define PC14_OSC32_IN_Pin GPIO_PIN_14
+#define PC14_OSC32_IN_GPIO_Port GPIOC
+#define PC15_OSC32_OUT_Pin GPIO_PIN_15
+#define PC15_OSC32_OUT_GPIO_Port GPIOC
+#define PH0_OSC_IN_Pin GPIO_PIN_0
+#define PH0_OSC_IN_GPIO_Port GPIOH
+#define PH1_OSC_OUT_Pin GPIO_PIN_1
+#define PH1_OSC_OUT_GPIO_Port GPIOH
+#define OTG_FS_PowerSwitchOn_Pin GPIO_PIN_0
+#define OTG_FS_PowerSwitchOn_GPIO_Port GPIOC
+#define PDM_OUT_Pin GPIO_PIN_3
+#define PDM_OUT_GPIO_Port GPIOC
+#define I2S3_WS_Pin GPIO_PIN_4
+#define I2S3_WS_GPIO_Port GPIOA
+#define SPI1_SCK_Pin GPIO_PIN_5
+#define SPI1_SCK_GPIO_Port GPIOA
+#define SPI1_MISO_Pin GPIO_PIN_6
+#define SPI1_MISO_GPIO_Port GPIOA
+#define SPI1_MOSI_Pin GPIO_PIN_7
+#define SPI1_MOSI_GPIO_Port GPIOA
+#define CLK_IN_Pin GPIO_PIN_10
+#define CLK_IN_GPIO_Port GPIOB
+#define LD4_Pin GPIO_PIN_12
+#define LD4_GPIO_Port GPIOD
+#define LD3_Pin GPIO_PIN_13
+#define LD3_GPIO_Port GPIOD
+#define LD5_Pin GPIO_PIN_14
+#define LD5_GPIO_Port GPIOD
+#define LD6_Pin GPIO_PIN_15
+#define LD6_GPIO_Port GPIOD
+#define I2S3_MCK_Pin GPIO_PIN_7
+#define I2S3_MCK_GPIO_Port GPIOC
+#define VBUS_FS_Pin GPIO_PIN_9
+#define VBUS_FS_GPIO_Port GPIOA
+#define OTG_FS_ID_Pin GPIO_PIN_10
+#define OTG_FS_ID_GPIO_Port GPIOA
+#define OTG_FS_DM_Pin GPIO_PIN_11
+#define OTG_FS_DM_GPIO_Port GPIOA
+#define OTG_FS_DP_Pin GPIO_PIN_12
+#define OTG_FS_DP_GPIO_Port GPIOA
+#define SWDIO_Pin GPIO_PIN_13
+#define SWDIO_GPIO_Port GPIOA
+#define SWCLK_Pin GPIO_PIN_14
+#define SWCLK_GPIO_Port GPIOA
+#define I2S3_SCK_Pin GPIO_PIN_10
+#define I2S3_SCK_GPIO_Port GPIOC
+#define I2S3_SD_Pin GPIO_PIN_12
+#define I2S3_SD_GPIO_Port GPIOC
+#define Audio_RST_Pin GPIO_PIN_4
+#define Audio_RST_GPIO_Port GPIOD
+#define OTG_FS_OverCurrent_Pin GPIO_PIN_5
+#define OTG_FS_OverCurrent_GPIO_Port GPIOD
+#define SWO_Pin GPIO_PIN_3
+#define SWO_GPIO_Port GPIOB
+#define Audio_SCL_Pin GPIO_PIN_6
+#define Audio_SCL_GPIO_Port GPIOB
+#define Audio_SDA_Pin GPIO_PIN_9
+#define Audio_SDA_GPIO_Port GPIOB
+#define MEMS_INT2_Pin GPIO_PIN_1
+#define MEMS_INT2_GPIO_Port GPIOE
+*/
+
+#define LD4_Pin GPIO_PIN_12
+#define LD4_GPIO_Port GPIOD
+#define LD3_Pin GPIO_PIN_13
+#define LD3_GPIO_Port GPIOD
+#define LD5_Pin GPIO_PIN_14
+#define LD5_GPIO_Port GPIOD
+#define LD6_Pin GPIO_PIN_15
+#define LD6_GPIO_Port GPIOD
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4/gpio.h"
+#include "common-hal/microcontroller/Pin.h"
+
+void stm32f4_peripherals_gpio_init(void) {
+ //Enable all GPIO for now
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ /* GPIO Ports Clock Enable */
+ __HAL_RCC_GPIOE_CLK_ENABLE();
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ __HAL_RCC_GPIOH_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(GPIOD, LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin, GPIO_PIN_RESET);
+
+ /*Configure GPIO pins : LD4_Pin LD3_Pin LD5_Pin LD6_Pin */
+ GPIO_InitStruct.Pin = LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+ //Status LED chain
+ stm32f4_peripherals_status_led(0,1);
+ stm32f4_peripherals_status_led(1,0);
+ stm32f4_peripherals_status_led(2,0);
+ stm32f4_peripherals_status_led(3,0);
+
+ //Never reset pins
+ never_reset_pin_number(2,13); //PC13 anti tamp
+ never_reset_pin_number(2,14); //PC14 OSC32_IN
+ never_reset_pin_number(2,15); //PC15 OSC32_OUT
+ never_reset_pin_number(0,13); //PA13 SWDIO
+ never_reset_pin_number(0,14); //PA14 SWCLK
+ never_reset_pin_number(0,15); //PA15 JTDI
+ never_reset_pin_number(1,3); //PB3 JTDO
+ never_reset_pin_number(1,4); //PB4 JTRST
+
+ // Port H is not included in GPIO port array
+ // never_reset_pin_number(5,0); //PH0 JTDO
+ // never_reset_pin_number(5,1); //PH1 JTRST
+}
+
+//LEDs are inverted on F411 DISCO
+void stm32f4_peripherals_status_led(uint8_t led, uint8_t state) {
+ switch(led)
+ {
+ case 0: HAL_GPIO_WritePin(GPIOD, LD4_Pin, (state ^ 1));
+ break;
+ case 1: HAL_GPIO_WritePin(GPIOD, LD3_Pin, (state ^ 1));
+ break;
+ case 2: HAL_GPIO_WritePin(GPIOD, LD5_Pin, (state ^ 1));
+ break;
+ case 3: HAL_GPIO_WritePin(GPIOD, LD6_Pin, (state ^ 1));
+ break;
+ default: break;
+ }
+}
+
+
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c
new file mode 100644
index 000000000..f0966f785
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c
@@ -0,0 +1,122 @@
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+#include "stm32f4/periph.h"
+
+// I2C
+
+I2C_TypeDef * mcu_i2c_banks[3] = {I2C1, I2C2, I2C3};
+
+const mcu_i2c_sda_obj_t mcu_i2c_sda_list[7] = {
+ I2C_SDA(1, 4, &pin_PB07),
+ I2C_SDA(1, 4, &pin_PB09),
+ I2C_SDA(2, 9, &pin_PB09),
+ I2C_SDA(2, 9, &pin_PB03),
+ I2C_SDA(3, 4, &pin_PC09),
+ I2C_SDA(3, 9, &pin_PB04),
+ I2C_SDA(3, 9, &pin_PB08)
+};
+
+const mcu_i2c_scl_obj_t mcu_i2c_scl_list[4] = {
+ I2C_SCL(1, 4, &pin_PB06),
+ I2C_SCL(1, 4, &pin_PB08),
+ I2C_SCL(2, 4, &pin_PB10),
+ I2C_SCL(3, 4, &pin_PA08)
+};
+
+// SPI
+
+SPI_TypeDef * mcu_spi_banks[5] = {SPI1, SPI2, SPI3, SPI4, SPI5};
+
+const mcu_spi_sck_obj_t mcu_spi_sck_list[15] = {
+ SPI(1, 5, &pin_PA05),
+ SPI(1, 5, &pin_PB03),
+ SPI(2, 5, &pin_PB10),
+ SPI(2, 5, &pin_PB13),
+ SPI(2, 5, &pin_PC07),
+ SPI(2, 5, &pin_PD03),
+ SPI(3, 6, &pin_PB03),
+ SPI(3, 7, &pin_PB12),
+ SPI(3, 6, &pin_PC10),
+ SPI(4, 6, &pin_PB13),
+ SPI(4, 5, &pin_PE02),
+ SPI(4, 5, &pin_PE12),
+ SPI(5, 6, &pin_PB00),
+ SPI(5, 6, &pin_PE02),
+ SPI(5, 6, &pin_PE12)
+};
+
+const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14] = {
+ SPI(1, 5, &pin_PA07),
+ SPI(1, 5, &pin_PB05),
+ SPI(2, 5, &pin_PB15),
+ SPI(2, 5, &pin_PC03),
+ SPI(3, 6, &pin_PB05),
+ SPI(3, 6, &pin_PC12),
+ SPI(3, 5, &pin_PD06),
+ SPI(4, 5, &pin_PA01),
+ SPI(4, 5, &pin_PE06),
+ SPI(4, 5, &pin_PE14),
+ SPI(5, 6, &pin_PA10),
+ SPI(5, 6, &pin_PB08),
+ SPI(5, 6, &pin_PE06),
+ SPI(5, 6, &pin_PE14)
+};
+
+const mcu_spi_miso_obj_t mcu_spi_miso_list[12] = {
+ SPI(1, 5, &pin_PA06),
+ SPI(1, 5, &pin_PB04),
+ SPI(2, 5, &pin_PB14),
+ SPI(2, 5, &pin_PC02),
+ SPI(3, 6, &pin_PB04),
+ SPI(3, 6, &pin_PC11),
+ SPI(4, 6, &pin_PA11),
+ SPI(4, 5, &pin_PE05),
+ SPI(4, 5, &pin_PE13),
+ SPI(5, 6, &pin_PA12),
+ SPI(5, 6, &pin_PE05),
+ SPI(5, 6, &pin_PE13)
+};
+
+const mcu_spi_nss_obj_t mcu_spi_nss_list[12] = {
+ SPI(1, 5, &pin_PA04),
+ SPI(1, 5, &pin_PA15),
+ SPI(2, 5, &pin_PB09),
+ SPI(2, 5, &pin_PB12),
+ SPI(3, 6, &pin_PA04),
+ SPI(3, 6, &pin_PA15),
+ SPI(4, 6, &pin_PB12),
+ SPI(4, 5, &pin_PE04),
+ SPI(4, 5, &pin_PE11),
+ SPI(5, 6, &pin_PB01),
+ SPI(5, 6, &pin_PE04),
+ SPI(5, 6, &pin_PE11)
+};
+
+//UART, Etc
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h
new file mode 100644
index 000000000..08efa14ca
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H
+#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H
+
+//I2C
+extern I2C_TypeDef * mcu_i2c_banks[3];
+
+extern const mcu_i2c_sda_obj_t mcu_i2c_sda_list[7];
+extern const mcu_i2c_scl_obj_t mcu_i2c_scl_list[4];
+
+//SPI
+extern SPI_TypeDef * mcu_spi_banks[5];
+
+extern const mcu_spi_sck_obj_t mcu_spi_sck_list[15];
+extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14];
+extern const mcu_spi_miso_obj_t mcu_spi_miso_list[12];
+extern const mcu_spi_nss_obj_t mcu_spi_nss_list[12];
+
+#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H \ No newline at end of file
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.c
new file mode 100644
index 000000000..7e88c3dcb
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.c
@@ -0,0 +1,123 @@
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+
+const mcu_pin_obj_t pin_PE02 = PIN(4, 2, NO_ADC);
+const mcu_pin_obj_t pin_PE03 = PIN(4, 3, NO_ADC);
+const mcu_pin_obj_t pin_PE04 = PIN(4, 4, NO_ADC);
+const mcu_pin_obj_t pin_PE05 = PIN(4, 5, NO_ADC);
+const mcu_pin_obj_t pin_PE06 = PIN(4, 6, NO_ADC);
+
+const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC); //anti-tamp
+const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC); //OSC32_IN
+const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC); //OSC32_OUT
+
+const mcu_pin_obj_t pin_PC00 = PIN(2, 0, ADC_INPUT(ADC_1,10));
+const mcu_pin_obj_t pin_PC01 = PIN(2, 1, ADC_INPUT(ADC_1,11));
+const mcu_pin_obj_t pin_PC02 = PIN(2, 2, ADC_INPUT(ADC_1,12));
+const mcu_pin_obj_t pin_PC03 = PIN(2, 3, ADC_INPUT(ADC_1,13));
+
+const mcu_pin_obj_t pin_PA00 = PIN(0, 0, ADC_INPUT(ADC_1,0));
+const mcu_pin_obj_t pin_PA01 = PIN(0, 1, ADC_INPUT(ADC_1,1));
+const mcu_pin_obj_t pin_PA02 = PIN(0, 2, ADC_INPUT(ADC_1,2));
+const mcu_pin_obj_t pin_PA03 = PIN(0, 3, ADC_INPUT(ADC_1,3));
+const mcu_pin_obj_t pin_PA04 = PIN(0, 4, ADC_INPUT(ADC_1,4));
+const mcu_pin_obj_t pin_PA05 = PIN(0, 5, ADC_INPUT(ADC_1,5));
+const mcu_pin_obj_t pin_PA06 = PIN(0, 6, ADC_INPUT(ADC_1,6));
+const mcu_pin_obj_t pin_PA07 = PIN(0, 7, ADC_INPUT(ADC_1,7));
+
+const mcu_pin_obj_t pin_PC04 = PIN(2, 4, ADC_INPUT(ADC_1,14));
+const mcu_pin_obj_t pin_PC05 = PIN(2, 5, ADC_INPUT(ADC_1,15));
+
+const mcu_pin_obj_t pin_PB00 = PIN(1, 0, ADC_INPUT(ADC_1,8));
+const mcu_pin_obj_t pin_PB01 = PIN(1, 1, ADC_INPUT(ADC_1,9));
+const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC);
+
+const mcu_pin_obj_t pin_PE07 = PIN(4, 7, NO_ADC);
+const mcu_pin_obj_t pin_PE08 = PIN(4, 8, NO_ADC);
+const mcu_pin_obj_t pin_PE09 = PIN(4, 9, NO_ADC);
+const mcu_pin_obj_t pin_PE10 = PIN(4, 10, NO_ADC);
+const mcu_pin_obj_t pin_PE11 = PIN(4, 11, NO_ADC);
+const mcu_pin_obj_t pin_PE12 = PIN(4, 12, NO_ADC);
+const mcu_pin_obj_t pin_PE13 = PIN(4, 13, NO_ADC);
+const mcu_pin_obj_t pin_PE14 = PIN(4, 14, NO_ADC);
+const mcu_pin_obj_t pin_PE15 = PIN(4, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PB10 = PIN(1, 10, NO_ADC);
+const mcu_pin_obj_t pin_PB12 = PIN(1, 12, NO_ADC);
+const mcu_pin_obj_t pin_PB13 = PIN(1, 13, NO_ADC);
+const mcu_pin_obj_t pin_PB14 = PIN(1, 14, NO_ADC);
+const mcu_pin_obj_t pin_PB15 = PIN(1, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PD08 = PIN(3, 8, NO_ADC);
+const mcu_pin_obj_t pin_PD09 = PIN(3, 9, NO_ADC);
+const mcu_pin_obj_t pin_PD10 = PIN(3, 10, NO_ADC);
+const mcu_pin_obj_t pin_PD11 = PIN(3, 11, NO_ADC);
+const mcu_pin_obj_t pin_PD12 = PIN(3, 12, NO_ADC);
+const mcu_pin_obj_t pin_PD13 = PIN(3, 13, NO_ADC);
+const mcu_pin_obj_t pin_PD14 = PIN(3, 14, NO_ADC);
+const mcu_pin_obj_t pin_PD15 = PIN(3, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PC06 = PIN(2, 6, NO_ADC);
+const mcu_pin_obj_t pin_PC07 = PIN(2, 7, NO_ADC);
+const mcu_pin_obj_t pin_PC08 = PIN(2, 8, NO_ADC);
+const mcu_pin_obj_t pin_PC09 = PIN(2, 9, NO_ADC);
+
+const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC);
+const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC);
+const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC);
+const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC);
+const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC);
+const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC); //SWDIO
+const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC); //SWCLK
+const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC); //JTDI
+
+const mcu_pin_obj_t pin_PC10 = PIN(2, 10, NO_ADC);
+const mcu_pin_obj_t pin_PC11 = PIN(2, 11, NO_ADC);
+const mcu_pin_obj_t pin_PC12 = PIN(2, 12, NO_ADC);
+
+const mcu_pin_obj_t pin_PD00 = PIN(3, 0, NO_ADC);
+const mcu_pin_obj_t pin_PD01 = PIN(3, 1, NO_ADC);
+const mcu_pin_obj_t pin_PD02 = PIN(3, 2, NO_ADC);
+const mcu_pin_obj_t pin_PD03 = PIN(3, 3, NO_ADC);
+const mcu_pin_obj_t pin_PD04 = PIN(3, 4, NO_ADC);
+const mcu_pin_obj_t pin_PD05 = PIN(3, 5, NO_ADC);
+const mcu_pin_obj_t pin_PD06 = PIN(3, 6, NO_ADC);
+const mcu_pin_obj_t pin_PD07 = PIN(3, 7, NO_ADC);
+
+const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC);
+const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC);
+const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC);
+const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC);
+const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC);
+const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC);
+const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC);
+
+const mcu_pin_obj_t pin_PE00 = PIN(4, 0, NO_ADC);
+const mcu_pin_obj_t pin_PE01 = PIN(4, 1, NO_ADC); \ No newline at end of file
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.h b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.h
new file mode 100644
index 000000000..37d3a5cf1
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/pins.h
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_STM32F411VE_PINS_H
+#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PINS_H
+
+//Pins in datasheet order: DocID026289 Rev 7 page 38. LQFP100 only
+//pg 38
+extern const mcu_pin_obj_t pin_PE02;
+extern const mcu_pin_obj_t pin_PE03;
+extern const mcu_pin_obj_t pin_PE04;
+extern const mcu_pin_obj_t pin_PE05;
+//pg 39
+extern const mcu_pin_obj_t pin_PE06;
+extern const mcu_pin_obj_t pin_PC13;
+extern const mcu_pin_obj_t pin_PC14;
+extern const mcu_pin_obj_t pin_PC15;
+extern const mcu_pin_obj_t pin_PC00;
+extern const mcu_pin_obj_t pin_PC01;
+extern const mcu_pin_obj_t pin_PC02;
+extern const mcu_pin_obj_t pin_PC03;
+//pg 40
+extern const mcu_pin_obj_t pin_PA00;
+extern const mcu_pin_obj_t pin_PA01;
+extern const mcu_pin_obj_t pin_PA02;
+extern const mcu_pin_obj_t pin_PA03;
+extern const mcu_pin_obj_t pin_PA04;
+extern const mcu_pin_obj_t pin_PA05;
+extern const mcu_pin_obj_t pin_PA06;
+extern const mcu_pin_obj_t pin_PA07;
+//pg 41
+extern const mcu_pin_obj_t pin_PC04;
+extern const mcu_pin_obj_t pin_PC05;
+extern const mcu_pin_obj_t pin_PB00;
+extern const mcu_pin_obj_t pin_PB01;
+extern const mcu_pin_obj_t pin_PB02;
+extern const mcu_pin_obj_t pin_PE07;
+extern const mcu_pin_obj_t pin_PE08;
+extern const mcu_pin_obj_t pin_PE09;
+extern const mcu_pin_obj_t pin_PE10;
+extern const mcu_pin_obj_t pin_PE11;
+extern const mcu_pin_obj_t pin_PE12;
+extern const mcu_pin_obj_t pin_PE13;
+extern const mcu_pin_obj_t pin_PE14;
+extern const mcu_pin_obj_t pin_PE15;
+//pg 42
+extern const mcu_pin_obj_t pin_PB10;
+extern const mcu_pin_obj_t pin_PB12;
+extern const mcu_pin_obj_t pin_PB13;
+extern const mcu_pin_obj_t pin_PB14;
+extern const mcu_pin_obj_t pin_PB15;
+extern const mcu_pin_obj_t pin_PD08;
+extern const mcu_pin_obj_t pin_PD09;
+extern const mcu_pin_obj_t pin_PD10;
+extern const mcu_pin_obj_t pin_PD11;
+extern const mcu_pin_obj_t pin_PD12;
+//pg 43
+extern const mcu_pin_obj_t pin_PD13;
+extern const mcu_pin_obj_t pin_PD14;
+extern const mcu_pin_obj_t pin_PD15;
+extern const mcu_pin_obj_t pin_PC06;
+extern const mcu_pin_obj_t pin_PC07;
+extern const mcu_pin_obj_t pin_PC08;
+extern const mcu_pin_obj_t pin_PC09;
+extern const mcu_pin_obj_t pin_PA08;
+extern const mcu_pin_obj_t pin_PA09;
+//pg 44
+extern const mcu_pin_obj_t pin_PA10;
+extern const mcu_pin_obj_t pin_PA11;
+extern const mcu_pin_obj_t pin_PA12;
+extern const mcu_pin_obj_t pin_PA13;
+extern const mcu_pin_obj_t pin_PA14;
+extern const mcu_pin_obj_t pin_PA15;
+extern const mcu_pin_obj_t pin_PC10;
+extern const mcu_pin_obj_t pin_PC11;
+extern const mcu_pin_obj_t pin_PC12;
+//pg 45
+extern const mcu_pin_obj_t pin_PD00;
+extern const mcu_pin_obj_t pin_PD01;
+extern const mcu_pin_obj_t pin_PD02;
+extern const mcu_pin_obj_t pin_PD03;
+extern const mcu_pin_obj_t pin_PD04;
+extern const mcu_pin_obj_t pin_PD05;
+extern const mcu_pin_obj_t pin_PD06;
+extern const mcu_pin_obj_t pin_PD07;
+extern const mcu_pin_obj_t pin_PB03;
+extern const mcu_pin_obj_t pin_PB04;
+extern const mcu_pin_obj_t pin_PB05;
+extern const mcu_pin_obj_t pin_PB06;
+//pg 46
+extern const mcu_pin_obj_t pin_PB07;
+extern const mcu_pin_obj_t pin_PB08;
+extern const mcu_pin_obj_t pin_PB09;
+extern const mcu_pin_obj_t pin_PE00;
+extern const mcu_pin_obj_t pin_PE01;
+
+
+#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PINS_H
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/clocks.c b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/clocks.c
new file mode 100644
index 000000000..107056550
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/clocks.c
@@ -0,0 +1,74 @@
+
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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 "stm32f4xx_hal.h"
+
+void stm32f4_peripherals_clocks_init(void) {
+ //System clock init
+ RCC_ClkInitTypeDef RCC_ClkInitStruct;
+ RCC_OscInitTypeDef RCC_OscInitStruct;
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
+
+ /* Enable Power Control clock */
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /* The voltage scaling allows optimizing the power consumption when the
+ * device is clocked below the maximum system frequency, to update the
+ * voltage scaling value regarding system frequency refer to product
+ * datasheet. */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /* Enable HSE Oscillator and activate PLL with HSE as source */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLM = 8;
+ RCC_OscInitStruct.PLL.PLLN = 200;
+ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
+ RCC_OscInitStruct.PLL.PLLQ = 7;
+ RCC_OscInitStruct.PLL.PLLR = 2;
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+ /* Select PLLSAI output as USB clock source */
+ PeriphClkInitStruct.PLLI2S.PLLI2SM = 8;
+ PeriphClkInitStruct.PLLI2S.PLLI2SQ = 4;
+ PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CK48;
+ PeriphClkInitStruct.Clk48ClockSelection = RCC_CK48CLKSOURCE_PLLI2SQ;
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+
+ /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
+ * clocks dividers */
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
+ RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
+
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
+}
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/gpio.c b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/gpio.c
new file mode 100644
index 000000000..d17ab4e01
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/gpio.c
@@ -0,0 +1,243 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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.
+ */
+
+/* GPIO PIN REFERENCE
+#define LED3_Pin GPIO_PIN_2
+#define LED3_GPIO_Port GPIOE
+#define LED4_Pin GPIO_PIN_3
+#define LED4_GPIO_Port GPIOE
+#define DFSDM_DATIN3_Pin GPIO_PIN_4
+#define DFSDM_DATIN3_GPIO_Port GPIOE
+#define A0_Pin GPIO_PIN_0
+#define A0_GPIO_Port GPIOF
+#define LCD_BLCTRL_Pin GPIO_PIN_5
+#define LCD_BLCTRL_GPIO_Port GPIOF
+#define QSPI_BK1_IO3_Pin GPIO_PIN_6
+#define QSPI_BK1_IO3_GPIO_Port GPIOF
+#define QSPI_BK1_IO2_Pin GPIO_PIN_7
+#define QSPI_BK1_IO2_GPIO_Port GPIOF
+#define QSPI_BK1_IO0_Pin GPIO_PIN_8
+#define QSPI_BK1_IO0_GPIO_Port GPIOF
+#define QSPI_BK1_IO1_Pin GPIO_PIN_9
+#define QSPI_BK1_IO1_GPIO_Port GPIOF
+#define STLK_MCO_Pin GPIO_PIN_0
+#define STLK_MCO_GPIO_Port GPIOH
+#define DFSDM_CKOUT_Pin GPIO_PIN_2
+#define DFSDM_CKOUT_GPIO_Port GPIOC
+#define JOY_SEL_Pin GPIO_PIN_0
+#define JOY_SEL_GPIO_Port GPIOA
+#define STLINK_RX_Pin GPIO_PIN_2
+#define STLINK_RX_GPIO_Port GPIOA
+#define STLINK_TX_Pin GPIO_PIN_3
+#define STLINK_TX_GPIO_Port GPIOA
+#define CODEC_I2S3_WS_Pin GPIO_PIN_4
+#define CODEC_I2S3_WS_GPIO_Port GPIOA
+#define DFSDM_DATIN0_Pin GPIO_PIN_1
+#define DFSDM_DATIN0_GPIO_Port GPIOB
+#define QSPI_CLK_Pin GPIO_PIN_2
+#define QSPI_CLK_GPIO_Port GPIOB
+#define EXT_RESET_Pin GPIO_PIN_11
+#define EXT_RESET_GPIO_Port GPIOF
+#define CTP_RST_Pin GPIO_PIN_12
+#define CTP_RST_GPIO_Port GPIOF
+#define JOY_RIGHT_Pin GPIO_PIN_14
+#define JOY_RIGHT_GPIO_Port GPIOF
+#define JOY_LEFT_Pin GPIO_PIN_15
+#define JOY_LEFT_GPIO_Port GPIOF
+#define JOY_UP_Pin GPIO_PIN_0
+#define JOY_UP_GPIO_Port GPIOG
+#define JOY_DOWN_Pin GPIO_PIN_1
+#define JOY_DOWN_GPIO_Port GPIOG
+#define D4_Pin GPIO_PIN_7
+#define D4_GPIO_Port GPIOE
+#define D5_Pin GPIO_PIN_8
+#define D5_GPIO_Port GPIOE
+#define D6_Pin GPIO_PIN_9
+#define D6_GPIO_Port GPIOE
+#define D7_Pin GPIO_PIN_10
+#define D7_GPIO_Port GPIOE
+#define D8_Pin GPIO_PIN_11
+#define D8_GPIO_Port GPIOE
+#define D9_Pin GPIO_PIN_12
+#define D9_GPIO_Port GPIOE
+#define D10_Pin GPIO_PIN_13
+#define D10_GPIO_Port GPIOE
+#define D11_Pin GPIO_PIN_14
+#define D11_GPIO_Port GPIOE
+#define D12_Pin GPIO_PIN_15
+#define D12_GPIO_Port GPIOE
+#define I2C2_SCL_Pin GPIO_PIN_10
+#define I2C2_SCL_GPIO_Port GPIOB
+#define M2_CKIN_Pin GPIO_PIN_11
+#define M2_CKIN_GPIO_Port GPIOB
+#define CODEC_I2S3_SCK_Pin GPIO_PIN_12
+#define CODEC_I2S3_SCK_GPIO_Port GPIOB
+#define D13_Pin GPIO_PIN_8
+#define D13_GPIO_Port GPIOD
+#define D14_Pin GPIO_PIN_9
+#define D14_GPIO_Port GPIOD
+#define D15_Pin GPIO_PIN_10
+#define D15_GPIO_Port GPIOD
+#define LCD_RESET_Pin GPIO_PIN_11
+#define LCD_RESET_GPIO_Port GPIOD
+#define D0_Pin GPIO_PIN_14
+#define D0_GPIO_Port GPIOD
+#define D1_Pin GPIO_PIN_15
+#define D1_GPIO_Port GPIOD
+#define CODEC_INT_Pin GPIO_PIN_2
+#define CODEC_INT_GPIO_Port GPIOG
+#define LCD_TE_Pin GPIO_PIN_4
+#define LCD_TE_GPIO_Port GPIOG
+#define CTP_INT_Pin GPIO_PIN_5
+#define CTP_INT_GPIO_Port GPIOG
+#define QSPI_BK1_NCS_Pin GPIO_PIN_6
+#define QSPI_BK1_NCS_GPIO_Port GPIOG
+#define USB_OTGFS_OVRCR_Pin GPIO_PIN_7
+#define USB_OTGFS_OVRCR_GPIO_Port GPIOG
+#define USB_OTGFS_PPWR_EN_Pin GPIO_PIN_8
+#define USB_OTGFS_PPWR_EN_GPIO_Port GPIOG
+#define CODEC_I2S3_MCK_Pin GPIO_PIN_7
+#define CODEC_I2S3_MCK_GPIO_Port GPIOC
+#define uSD_D0_Pin GPIO_PIN_8
+#define uSD_D0_GPIO_Port GPIOC
+#define uSD_D1_Pin GPIO_PIN_9
+#define uSD_D1_GPIO_Port GPIOC
+#define M2_CKINA8_Pin GPIO_PIN_8
+#define M2_CKINA8_GPIO_Port GPIOA
+#define USB_OTGFS_VBUS_Pin GPIO_PIN_9
+#define USB_OTGFS_VBUS_GPIO_Port GPIOA
+#define USB_OTGFS_ID_Pin GPIO_PIN_10
+#define USB_OTGFS_ID_GPIO_Port GPIOA
+#define USB_OTGFS_DM_Pin GPIO_PIN_11
+#define USB_OTGFS_DM_GPIO_Port GPIOA
+#define USB_OTGFS_DP_Pin GPIO_PIN_12
+#define USB_OTGFS_DP_GPIO_Port GPIOA
+#define SWDIO_Pin GPIO_PIN_13
+#define SWDIO_GPIO_Port GPIOA
+#define SWCLK_Pin GPIO_PIN_14
+#define SWCLK_GPIO_Port GPIOA
+#define uSD_D2_Pin GPIO_PIN_10
+#define uSD_D2_GPIO_Port GPIOC
+#define uSD_D3_Pin GPIO_PIN_11
+#define uSD_D3_GPIO_Port GPIOC
+#define uSD_CLK_Pin GPIO_PIN_12
+#define uSD_CLK_GPIO_Port GPIOC
+#define D2_Pin GPIO_PIN_0
+#define D2_GPIO_Port GPIOD
+#define D3_Pin GPIO_PIN_1
+#define D3_GPIO_Port GPIOD
+#define uSD_CMD_Pin GPIO_PIN_2
+#define uSD_CMD_GPIO_Port GPIOD
+#define uSD_DETECT_Pin GPIO_PIN_3
+#define uSD_DETECT_GPIO_Port GPIOD
+#define FMC_NOE_Pin GPIO_PIN_4
+#define FMC_NOE_GPIO_Port GPIOD
+#define FMC_NWE_Pin GPIO_PIN_5
+#define FMC_NWE_GPIO_Port GPIOD
+#define FMC_NE1_Pin GPIO_PIN_7
+#define FMC_NE1_GPIO_Port GPIOD
+#define SWO_Pin GPIO_PIN_3
+#define SWO_GPIO_Port GPIOB
+#define CODEC_I2S3ext_SD_Pin GPIO_PIN_4
+#define CODEC_I2S3ext_SD_GPIO_Port GPIOB
+#define CODEC_I2S3_SD_Pin GPIO_PIN_5
+#define CODEC_I2S3_SD_GPIO_Port GPIOB
+#define I2C1_SCL_Pin GPIO_PIN_6
+#define I2C1_SCL_GPIO_Port GPIOB
+#define I2C1_SDA_Pin GPIO_PIN_7
+#define I2C1_SDA_GPIO_Port GPIOB
+#define I2C2_SDA_Pin GPIO_PIN_9
+#define I2C2_SDA_GPIO_Port GPIOB
+#define LED1_Pin GPIO_PIN_0
+#define LED1_GPIO_Port GPIOE
+#define LED2_Pin GPIO_PIN_1
+#define LED2_GPIO_Port GPIOE
+*/
+
+#include "stm32f4xx_hal.h"
+#include "stm32f4/gpio.h"
+#include "common-hal/microcontroller/Pin.h"
+
+void stm32f4_peripherals_gpio_init(void) {
+ //Enable all GPIO for now
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ __HAL_RCC_GPIOE_CLK_ENABLE();
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ __HAL_RCC_GPIOF_CLK_ENABLE();
+ __HAL_RCC_GPIOH_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_GPIOG_CLK_ENABLE();
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+
+ HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
+ //HAL_GPIO_WritePin(USB_OTGFS_PPWR_EN_GPIO_Port, USB_OTGFS_PPWR_EN_Pin, GPIO_PIN_SET);
+
+ //Configure LED pins
+ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
+
+ //Status LED chain
+ stm32f4_peripherals_status_led(0,1);
+ stm32f4_peripherals_status_led(1,0);
+ stm32f4_peripherals_status_led(2,0);
+ stm32f4_peripherals_status_led(3,0);
+
+ //Never reset pins
+ never_reset_pin_number(2,13); //PC13 anti tamp
+ never_reset_pin_number(2,14); //PC14 OSC32_IN
+ never_reset_pin_number(2,15); //PC15 OSC32_OUT
+ never_reset_pin_number(0,13); //PA13 SWDIO
+ never_reset_pin_number(0,14); //PA14 SWCLK
+ //never_reset_pin_number(0,15); //PA15 JTDI
+ //never_reset_pin_number(1,3); //PB3 JTDO
+ //never_reset_pin_number(1,4); //PB4 JTRST
+
+ // Port H is not included in GPIO port array
+ // never_reset_pin_number(5,0); //PH0 JTDO
+ // never_reset_pin_number(5,1); //PH1 JTRST
+}
+
+//LEDs are inverted on F411 DISCO
+void stm32f4_peripherals_status_led(uint8_t led, uint8_t state) {
+ switch(led)
+ {
+ case 0: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, (state ^ 1));
+ break;
+ case 1: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, (state ^ 1));
+ break;
+ case 2: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, (state ^ 1));
+ break;
+ case 3: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, (state ^ 1));
+ break;
+ default: break;
+ }
+}
+
+
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c
new file mode 100644
index 000000000..ea94719ec
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c
@@ -0,0 +1,123 @@
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+#include "stm32f4/periph.h"
+
+// I2C
+
+I2C_TypeDef * mcu_i2c_banks[3] = {I2C1, I2C2, I2C3};
+
+const mcu_i2c_sda_obj_t mcu_i2c_sda_list[8] = {
+ I2C_SDA(1, 4, &pin_PB07),
+ I2C_SDA(1, 4, &pin_PB09),
+ I2C_SDA(2, 4, &pin_PB11), //not on LQFP100
+ I2C_SDA(2, 9, &pin_PB09),
+ I2C_SDA(2, 9, &pin_PB03),
+ I2C_SDA(3, 4, &pin_PC09),
+ I2C_SDA(3, 9, &pin_PB04),
+ I2C_SDA(3, 9, &pin_PB08)
+};
+
+const mcu_i2c_scl_obj_t mcu_i2c_scl_list[4] = {
+ I2C_SCL(1, 4, &pin_PB06),
+ I2C_SCL(1, 4, &pin_PB08),
+ I2C_SCL(2, 4, &pin_PB10),
+ I2C_SCL(3, 4, &pin_PA08)
+};
+
+// SPI
+
+SPI_TypeDef * mcu_spi_banks[5] = {SPI1, SPI2, SPI3, SPI4, SPI5};
+
+const mcu_spi_sck_obj_t mcu_spi_sck_list[15] = {
+ SPI(1, 5, &pin_PA05),
+ SPI(1, 5, &pin_PB03),
+ SPI(2, 5, &pin_PB10),
+ SPI(2, 5, &pin_PB13),
+ SPI(2, 5, &pin_PC07),
+ SPI(2, 5, &pin_PD03),
+ SPI(3, 6, &pin_PB03),
+ SPI(3, 7, &pin_PB12),
+ SPI(3, 6, &pin_PC10),
+ SPI(4, 6, &pin_PB13),
+ SPI(4, 5, &pin_PE02),
+ SPI(4, 5, &pin_PE12),
+ SPI(5, 6, &pin_PB00),
+ SPI(5, 6, &pin_PE02),
+ SPI(5, 6, &pin_PE12)
+};
+
+const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14] = {
+ SPI(1, 5, &pin_PA07),
+ SPI(1, 5, &pin_PB05),
+ SPI(2, 5, &pin_PB15),
+ SPI(2, 5, &pin_PC03),
+ SPI(3, 6, &pin_PB05),
+ SPI(3, 6, &pin_PC12),
+ SPI(3, 5, &pin_PD06),
+ SPI(4, 5, &pin_PA01),
+ SPI(4, 5, &pin_PE06),
+ SPI(4, 5, &pin_PE14),
+ SPI(5, 6, &pin_PA10),
+ SPI(5, 6, &pin_PB08),
+ SPI(5, 6, &pin_PE06),
+ SPI(5, 6, &pin_PE14)
+};
+
+const mcu_spi_miso_obj_t mcu_spi_miso_list[12] = {
+ SPI(1, 5, &pin_PA06),
+ SPI(1, 5, &pin_PB04),
+ SPI(2, 5, &pin_PB14),
+ SPI(2, 5, &pin_PC02),
+ SPI(3, 6, &pin_PB04),
+ SPI(3, 6, &pin_PC11),
+ SPI(4, 6, &pin_PA11),
+ SPI(4, 5, &pin_PE05),
+ SPI(4, 5, &pin_PE13),
+ SPI(5, 6, &pin_PA12),
+ SPI(5, 6, &pin_PE05),
+ SPI(5, 6, &pin_PE13)
+};
+
+const mcu_spi_nss_obj_t mcu_spi_nss_list[12] = {
+ SPI(1, 5, &pin_PA04),
+ SPI(1, 5, &pin_PA15),
+ SPI(2, 5, &pin_PB09),
+ SPI(2, 5, &pin_PB12),
+ SPI(3, 6, &pin_PA04),
+ SPI(3, 6, &pin_PA15),
+ SPI(4, 6, &pin_PB12),
+ SPI(4, 5, &pin_PE04),
+ SPI(4, 5, &pin_PE11),
+ SPI(5, 6, &pin_PB01),
+ SPI(5, 6, &pin_PE04),
+ SPI(5, 6, &pin_PE11)
+};
+
+//UART, Etc
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h
new file mode 100644
index 000000000..d12bbba93
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H
+#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H
+
+//I2C
+extern I2C_TypeDef * mcu_i2c_banks[3];
+
+extern const mcu_i2c_sda_obj_t mcu_i2c_sda_list[8];
+extern const mcu_i2c_scl_obj_t mcu_i2c_scl_list[4];
+
+
+//SPI
+extern SPI_TypeDef * mcu_spi_banks[5];
+
+extern const mcu_spi_sck_obj_t mcu_spi_sck_list[15];
+extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14];
+extern const mcu_spi_miso_obj_t mcu_spi_miso_list[12];
+extern const mcu_spi_nss_obj_t mcu_spi_nss_list[12];
+
+#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H \ No newline at end of file
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.c b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.c
new file mode 100644
index 000000000..c56de5a29
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.c
@@ -0,0 +1,161 @@
+ /*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "stm32f4/pins.h"
+
+const mcu_pin_obj_t pin_PE02 = PIN(4, 2, NO_ADC);
+const mcu_pin_obj_t pin_PE03 = PIN(4, 3, NO_ADC);
+const mcu_pin_obj_t pin_PE04 = PIN(4, 4, NO_ADC);
+const mcu_pin_obj_t pin_PE05 = PIN(4, 5, NO_ADC);
+const mcu_pin_obj_t pin_PE06 = PIN(4, 6, NO_ADC);
+
+const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC); //anti-tamp
+const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC); //OSC32_IN
+const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC); //OSC32_OUT
+
+const mcu_pin_obj_t pin_PF00 = PIN(5, 0, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF01 = PIN(5, 1, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF02 = PIN(5, 2, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF03 = PIN(5, 3, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF04 = PIN(5, 4, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF05 = PIN(5, 5, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF06 = PIN(5, 6, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF07 = PIN(5, 7, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF08 = PIN(5, 8, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF09 = PIN(5, 9, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF10 = PIN(5, 10, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PC00 = PIN(2, 0, ADC_INPUT(ADC_1,10));
+const mcu_pin_obj_t pin_PC01 = PIN(2, 1, ADC_INPUT(ADC_1,11));
+const mcu_pin_obj_t pin_PC02 = PIN(2, 2, ADC_INPUT(ADC_1,12));
+const mcu_pin_obj_t pin_PC03 = PIN(2, 3, ADC_INPUT(ADC_1,13));
+
+const mcu_pin_obj_t pin_PA00 = PIN(0, 0, ADC_INPUT(ADC_1,0));
+const mcu_pin_obj_t pin_PA01 = PIN(0, 1, ADC_INPUT(ADC_1,1));
+const mcu_pin_obj_t pin_PA02 = PIN(0, 2, ADC_INPUT(ADC_1,2));
+const mcu_pin_obj_t pin_PA03 = PIN(0, 3, ADC_INPUT(ADC_1,3));
+const mcu_pin_obj_t pin_PA04 = PIN(0, 4, ADC_INPUT(ADC_1,4));
+const mcu_pin_obj_t pin_PA05 = PIN(0, 5, ADC_INPUT(ADC_1,5));
+const mcu_pin_obj_t pin_PA06 = PIN(0, 6, ADC_INPUT(ADC_1,6));
+const mcu_pin_obj_t pin_PA07 = PIN(0, 7, ADC_INPUT(ADC_1,7));
+
+const mcu_pin_obj_t pin_PC04 = PIN(2, 4, ADC_INPUT(ADC_1,14));
+const mcu_pin_obj_t pin_PC05 = PIN(2, 5, ADC_INPUT(ADC_1,15));
+
+const mcu_pin_obj_t pin_PB00 = PIN(1, 0, ADC_INPUT(ADC_1,8));
+const mcu_pin_obj_t pin_PB01 = PIN(1, 1, ADC_INPUT(ADC_1,9));
+const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC);
+
+const mcu_pin_obj_t pin_PF11 = PIN(5, 11, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF12 = PIN(5, 12, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF13 = PIN(5, 13, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF14 = PIN(5, 14, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PF15 = PIN(5, 15, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PG00 = PIN(6, 0, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG01 = PIN(6, 1, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PE07 = PIN(4, 7, NO_ADC);
+const mcu_pin_obj_t pin_PE08 = PIN(4, 8, NO_ADC);
+const mcu_pin_obj_t pin_PE09 = PIN(4, 9, NO_ADC);
+const mcu_pin_obj_t pin_PE10 = PIN(4, 10, NO_ADC);
+const mcu_pin_obj_t pin_PE11 = PIN(4, 11, NO_ADC);
+const mcu_pin_obj_t pin_PE12 = PIN(4, 12, NO_ADC);
+const mcu_pin_obj_t pin_PE13 = PIN(4, 13, NO_ADC);
+const mcu_pin_obj_t pin_PE14 = PIN(4, 14, NO_ADC);
+const mcu_pin_obj_t pin_PE15 = PIN(4, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PB10 = PIN(1, 10, NO_ADC);
+const mcu_pin_obj_t pin_PB11 = PIN(1, 11, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PB12 = PIN(1, 12, NO_ADC);
+const mcu_pin_obj_t pin_PB13 = PIN(1, 13, NO_ADC);
+const mcu_pin_obj_t pin_PB14 = PIN(1, 14, NO_ADC);
+const mcu_pin_obj_t pin_PB15 = PIN(1, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PD08 = PIN(3, 8, NO_ADC);
+const mcu_pin_obj_t pin_PD09 = PIN(3, 9, NO_ADC);
+const mcu_pin_obj_t pin_PD10 = PIN(3, 10, NO_ADC);
+const mcu_pin_obj_t pin_PD11 = PIN(3, 11, NO_ADC);
+const mcu_pin_obj_t pin_PD12 = PIN(3, 12, NO_ADC);
+const mcu_pin_obj_t pin_PD13 = PIN(3, 13, NO_ADC);
+const mcu_pin_obj_t pin_PD14 = PIN(3, 14, NO_ADC);
+const mcu_pin_obj_t pin_PD15 = PIN(3, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PG02 = PIN(6, 2, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG03 = PIN(6, 3, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG04 = PIN(6, 4, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG05 = PIN(6, 5, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG06 = PIN(6, 6, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG07 = PIN(6, 7, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG08 = PIN(6, 8, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PC06 = PIN(2, 6, NO_ADC);
+const mcu_pin_obj_t pin_PC07 = PIN(2, 7, NO_ADC);
+const mcu_pin_obj_t pin_PC08 = PIN(2, 8, NO_ADC);
+const mcu_pin_obj_t pin_PC09 = PIN(2, 9, NO_ADC);
+
+const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC);
+const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC);
+const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC);
+const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC);
+const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC);
+const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC);
+const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC);
+const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC);
+
+const mcu_pin_obj_t pin_PC10 = PIN(2, 10, NO_ADC);
+const mcu_pin_obj_t pin_PC11 = PIN(2, 11, NO_ADC);
+const mcu_pin_obj_t pin_PC12 = PIN(2, 12, NO_ADC);
+
+const mcu_pin_obj_t pin_PD00 = PIN(3, 0, NO_ADC);
+const mcu_pin_obj_t pin_PD01 = PIN(3, 1, NO_ADC);
+const mcu_pin_obj_t pin_PD02 = PIN(3, 2, NO_ADC);
+const mcu_pin_obj_t pin_PD03 = PIN(3, 3, NO_ADC);
+const mcu_pin_obj_t pin_PD04 = PIN(3, 4, NO_ADC);
+const mcu_pin_obj_t pin_PD05 = PIN(3, 5, NO_ADC);
+const mcu_pin_obj_t pin_PD06 = PIN(3, 6, NO_ADC);
+const mcu_pin_obj_t pin_PD07 = PIN(3, 7, NO_ADC);
+
+const mcu_pin_obj_t pin_PG09 = PIN(6, 9, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG10 = PIN(6, 10, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG11 = PIN(6, 11, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG12 = PIN(6, 12, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG13 = PIN(6, 13, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG14 = PIN(6, 14, NO_ADC); // 144 only
+const mcu_pin_obj_t pin_PG15 = PIN(6, 15, NO_ADC); // 144 only
+
+const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC);
+const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC);
+const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC);
+const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC);
+const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC);
+const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC);
+const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC);
+
+const mcu_pin_obj_t pin_PE00 = PIN(4, 0, NO_ADC);
+const mcu_pin_obj_t pin_PE01 = PIN(4, 1, NO_ADC);
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.h b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.h
new file mode 100644
index 000000000..180f5c316
--- /dev/null
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/pins.h
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_PERIPHERALS_STM32F412ZG_PINS_H
+#define MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F412ZG_PINS_H
+
+//Pins in datasheet order: DocID028087 Rev 7 page 50. LQFP100 only
+//pg 50
+extern const mcu_pin_obj_t pin_PE02;
+extern const mcu_pin_obj_t pin_PE03;
+extern const mcu_pin_obj_t pin_PE04;
+extern const mcu_pin_obj_t pin_PE05;
+extern const mcu_pin_obj_t pin_PE06;
+extern const mcu_pin_obj_t pin_PC13;
+extern const mcu_pin_obj_t pin_PC14;
+//pg 51
+extern const mcu_pin_obj_t pin_PC15;
+extern const mcu_pin_obj_t pin_PF00; // 144 only
+extern const mcu_pin_obj_t pin_PF01; // 144 only
+extern const mcu_pin_obj_t pin_PF02; // 144 only
+extern const mcu_pin_obj_t pin_PF03; // 144 only
+extern const mcu_pin_obj_t pin_PF04; // 144 only
+extern const mcu_pin_obj_t pin_PF05; // 144 only
+extern const mcu_pin_obj_t pin_PF06; // 144 only
+extern const mcu_pin_obj_t pin_PF07; // 144 only
+extern const mcu_pin_obj_t pin_PF08; // 144 only
+extern const mcu_pin_obj_t pin_PF09; // 144 only
+extern const mcu_pin_obj_t pin_PF10; // 144 only
+//pg 52
+extern const mcu_pin_obj_t pin_PC00;
+extern const mcu_pin_obj_t pin_PC01;
+extern const mcu_pin_obj_t pin_PC02;
+extern const mcu_pin_obj_t pin_PC03;
+extern const mcu_pin_obj_t pin_PA00;
+extern const mcu_pin_obj_t pin_PA01;
+extern const mcu_pin_obj_t pin_PA02;
+//pg 53
+extern const mcu_pin_obj_t pin_PA03;
+extern const mcu_pin_obj_t pin_PA04;
+extern const mcu_pin_obj_t pin_PA05;
+extern const mcu_pin_obj_t pin_PA06;
+extern const mcu_pin_obj_t pin_PA07;
+extern const mcu_pin_obj_t pin_PC04;
+//pg 54
+extern const mcu_pin_obj_t pin_PC05;
+extern const mcu_pin_obj_t pin_PB00;
+extern const mcu_pin_obj_t pin_PB01;
+extern const mcu_pin_obj_t pin_PB02;
+extern const mcu_pin_obj_t pin_PF11; // 144 only
+extern const mcu_pin_obj_t pin_PF12; // 144 only
+extern const mcu_pin_obj_t pin_PF13; // 144 only
+extern const mcu_pin_obj_t pin_PF14; // 144 only
+extern const mcu_pin_obj_t pin_PF15; // 144 only
+extern const mcu_pin_obj_t pin_PG00; // 144 only
+extern const mcu_pin_obj_t pin_PG01; // 144 only
+//pg 55
+extern const mcu_pin_obj_t pin_PE07;
+extern const mcu_pin_obj_t pin_PE08;
+extern const mcu_pin_obj_t pin_PE09;
+extern const mcu_pin_obj_t pin_PE10;
+extern const mcu_pin_obj_t pin_PE11;
+extern const mcu_pin_obj_t pin_PE12;
+extern const mcu_pin_obj_t pin_PE13;
+extern const mcu_pin_obj_t pin_PE14;
+//pg 56
+extern const mcu_pin_obj_t pin_PE15;
+extern const mcu_pin_obj_t pin_PB10;
+extern const mcu_pin_obj_t pin_PB11; // 144 only
+extern const mcu_pin_obj_t pin_PB12;
+extern const mcu_pin_obj_t pin_PB13;
+//pg 57
+extern const mcu_pin_obj_t pin_PB14;
+extern const mcu_pin_obj_t pin_PB15;
+extern const mcu_pin_obj_t pin_PD08;
+extern const mcu_pin_obj_t pin_PD09;
+extern const mcu_pin_obj_t pin_PD10;
+extern const mcu_pin_obj_t pin_PD11;
+extern const mcu_pin_obj_t pin_PD12;
+//pg 58
+extern const mcu_pin_obj_t pin_PD13;
+extern const mcu_pin_obj_t pin_PD14;
+extern const mcu_pin_obj_t pin_PD15;
+extern const mcu_pin_obj_t pin_PG02; // 144 only
+extern const mcu_pin_obj_t pin_PG03; // 144 only
+extern const mcu_pin_obj_t pin_PG04; // 144 only
+extern const mcu_pin_obj_t pin_PG05; // 144 only
+extern const mcu_pin_obj_t pin_PG06; // 144 only
+extern const mcu_pin_obj_t pin_PG07; // 144 only
+extern const mcu_pin_obj_t pin_PG08; // 144 only
+//pg 59
+extern const mcu_pin_obj_t pin_PC06;
+extern const mcu_pin_obj_t pin_PC07;
+extern const mcu_pin_obj_t pin_PC08;
+extern const mcu_pin_obj_t pin_PC09;
+extern const mcu_pin_obj_t pin_PA08;
+extern const mcu_pin_obj_t pin_PA09;
+extern const mcu_pin_obj_t pin_PA10;
+//pg 60
+extern const mcu_pin_obj_t pin_PA11;
+extern const mcu_pin_obj_t pin_PA12;
+extern const mcu_pin_obj_t pin_PA13;
+extern const mcu_pin_obj_t pin_PA14;
+extern const mcu_pin_obj_t pin_PA15;
+extern const mcu_pin_obj_t pin_PC10;
+extern const mcu_pin_obj_t pin_PC11;
+//pg 61
+extern const mcu_pin_obj_t pin_PC12;
+extern const mcu_pin_obj_t pin_PD00;
+extern const mcu_pin_obj_t pin_PD01;
+extern const mcu_pin_obj_t pin_PD02;
+extern const mcu_pin_obj_t pin_PD03;
+extern const mcu_pin_obj_t pin_PD04;
+extern const mcu_pin_obj_t pin_PD05;
+extern const mcu_pin_obj_t pin_PD06;
+extern const mcu_pin_obj_t pin_PD07;
+//pg 62
+extern const mcu_pin_obj_t pin_PG09; // 144 only
+extern const mcu_pin_obj_t pin_PG10; // 144 only
+extern const mcu_pin_obj_t pin_PG11; // 144 only
+extern const mcu_pin_obj_t pin_PG12; // 144 only
+extern const mcu_pin_obj_t pin_PG13; // 144 only
+extern const mcu_pin_obj_t pin_PG14; // 144 only
+extern const mcu_pin_obj_t pin_PG15; // 144 only
+extern const mcu_pin_obj_t pin_PB03;
+extern const mcu_pin_obj_t pin_PB04;
+//pg 63
+extern const mcu_pin_obj_t pin_PB05;
+extern const mcu_pin_obj_t pin_PB06;
+extern const mcu_pin_obj_t pin_PB07;
+extern const mcu_pin_obj_t pin_PB08;
+extern const mcu_pin_obj_t pin_PB09;
+extern const mcu_pin_obj_t pin_PE00;
+extern const mcu_pin_obj_t pin_PE01;
+
+#endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F412ZG_PINS_H
diff --git a/ports/stm32f4/qstrdefsport.h b/ports/stm32f4/qstrdefsport.h
new file mode 100644
index 000000000..3ba897069
--- /dev/null
+++ b/ports/stm32f4/qstrdefsport.h
@@ -0,0 +1 @@
+// qstrs specific to this port
diff --git a/ports/stm32f4/stm32f4 b/ports/stm32f4/stm32f4
new file mode 160000
+Subproject 89a356f0b44883d55c45a5d22940777a44a2b88
diff --git a/ports/stm32f4/supervisor/cpu.s b/ports/stm32f4/supervisor/cpu.s
new file mode 100755
index 000000000..9e6807a5e
--- /dev/null
+++ b/ports/stm32f4/supervisor/cpu.s
@@ -0,0 +1,27 @@
+.syntax unified
+.cpu cortex-m4
+.thumb
+.text
+.align 2
+
+@ uint cpu_get_regs_and_sp(r0=uint regs[10])
+.global cpu_get_regs_and_sp
+.thumb
+.thumb_func
+.type cpu_get_regs_and_sp, %function
+cpu_get_regs_and_sp:
+@ store registers into given array
+str r4, [r0], #4
+str r5, [r0], #4
+str r6, [r0], #4
+str r7, [r0], #4
+str r8, [r0], #4
+str r9, [r0], #4
+str r10, [r0], #4
+str r11, [r0], #4
+str r12, [r0], #4
+str r13, [r0], #4
+
+@ return the sp
+mov r0, sp
+bx lr
diff --git a/ports/stm32f4/supervisor/internal_flash.c b/ports/stm32f4/supervisor/internal_flash.c
new file mode 100644
index 000000000..046b26baf
--- /dev/null
+++ b/ports/stm32f4/supervisor/internal_flash.c
@@ -0,0 +1,204 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "supervisor/internal_flash.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat.h"
+#include "py/mphal.h"
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "lib/oofatfs/ff.h"
+
+#include "stm32f4xx_hal.h"
+
+typedef struct {
+ uint32_t base_address;
+ uint32_t sector_size;
+ uint32_t sector_count;
+} flash_layout_t;
+
+/*------------------------------------------------------------------*/
+/* Internal Flash API
+ *------------------------------------------------------------------*/
+
+static const flash_layout_t flash_layout[] = {
+ { 0x08000000, 0x04000, 4 },
+ { 0x08010000, 0x10000, 1 },
+ { 0x08020000, 0x20000, 3 },
+ #if defined(FLASH_SECTOR_8)
+ { 0x08080000, 0x20000, 4 },
+ #endif
+ #if defined(FLASH_SECTOR_12)
+ { 0x08100000, 0x04000, 4 },
+ { 0x08110000, 0x10000, 1 },
+ { 0x08120000, 0x20000, 7 },
+ #endif
+};
+
+static uint8_t sector_copy[0x4000] __attribute__((aligned(4)));
+
+//Return the sector of a given flash address.
+uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) {
+ if (addr >= flash_layout[0].base_address) {
+ uint32_t sector_index = 0;
+ for (uint8_t i = 0; i < MP_ARRAY_SIZE(flash_layout); ++i) {
+ for (uint8_t j = 0; j < flash_layout[i].sector_count; ++j) {
+ uint32_t sector_start_next = flash_layout[i].base_address
+ + (j + 1) * flash_layout[i].sector_size;
+ if (addr < sector_start_next) {
+ if (start_addr != NULL) {
+ *start_addr = flash_layout[i].base_address
+ + j * flash_layout[i].sector_size;
+ }
+ if (size != NULL) {
+ *size = flash_layout[i].sector_size;
+ }
+ return sector_index;
+ }
+ ++sector_index;
+ }
+ }
+ }
+ return 0;
+}
+
+void supervisor_flash_init(void) {
+}
+
+uint32_t supervisor_flash_get_block_size(void) {
+ return FILESYSTEM_BLOCK_SIZE;
+}
+
+uint32_t supervisor_flash_get_block_count(void) {
+ return INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS;
+}
+
+void supervisor_flash_flush(void) {
+}
+
+static int32_t convert_block_to_flash_addr(uint32_t block) {
+ if (0 <= block && block < INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS) {
+ // a block in partition 1
+ return INTERNAL_FLASH_FILESYSTEM_START_ADDR + block * FILESYSTEM_BLOCK_SIZE;
+ }
+ // bad block
+ return -1;
+}
+
+mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
+ int32_t src = convert_block_to_flash_addr(block);
+ if (src == -1) {
+ // bad block number
+ return false;
+ }
+ memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks);
+ return 0; // success
+}
+
+bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
+ int32_t dest = convert_block_to_flash_addr(block);
+ if (dest == -1) {
+ // bad block number
+ mp_printf(&mp_plat_print, "BAD FLASH BLOCK ERROR");
+ return false;
+ }
+
+ // unlock flash
+ HAL_FLASH_Unlock();
+
+ // set up for erase
+ FLASH_EraseInitTypeDef EraseInitStruct;
+ EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
+ EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
+ // get the sector information
+ uint32_t sector_size;
+ uint32_t sector_start_addr;
+ EraseInitStruct.Sector = flash_get_sector_info(dest, &sector_start_addr, &sector_size);
+ EraseInitStruct.NbSectors = 1;
+ if (sector_size>0x4000) return false;
+
+ // copy the sector
+ memcpy(sector_copy,(void *)sector_start_addr,sector_size);
+
+ // // overwrite sector data
+ memcpy(sector_copy+(dest-sector_start_addr),src,FILESYSTEM_BLOCK_SIZE);
+
+ // find end address, subtract for number of sectors
+ // Shouldn't be required since blocks will always fit in a single sector, they should never overlap
+ //EraseInitStruct.NbSectors = flash_get_sector_info(dest + FILESYSTEM_BLOCK_SIZE - 1, NULL, NULL) - EraseInitStruct.Sector + 1;
+
+ // erase the sector
+ uint32_t SectorError = 0;
+ if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
+ // error occurred during sector erase
+ HAL_FLASH_Lock(); // lock the flash
+ mp_printf(&mp_plat_print, "FLASH SECTOR ERASE ERROR");
+ return false;
+ }
+
+ __HAL_FLASH_DATA_CACHE_DISABLE();
+ __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+
+ __HAL_FLASH_DATA_CACHE_RESET();
+ __HAL_FLASH_INSTRUCTION_CACHE_RESET();
+
+ __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+ __HAL_FLASH_DATA_CACHE_ENABLE();
+
+ // reprogram the sector
+ for (uint32_t i = 0; i < sector_size; i++) {
+ if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, sector_start_addr, (uint64_t)sector_copy[i]) != HAL_OK) {
+ // error occurred during flash write
+ HAL_FLASH_Lock(); // lock the flash
+ mp_printf(&mp_plat_print, "FLASH WRITE ERROR");
+ return false;
+ }
+ sector_start_addr += 1;
+ }
+
+ // lock the flash
+ HAL_FLASH_Lock();
+
+ return true;
+}
+
+mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
+
+ for (size_t i = 0; i < num_blocks; i++) {
+ if (!supervisor_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) {
+ return 1; // error
+ }
+ }
+ return 0; // success
+}
+
+void supervisor_flash_release_cache(void) {
+}
+
diff --git a/ports/stm32f4/supervisor/internal_flash.h b/ports/stm32f4/supervisor/internal_flash.h
new file mode 100644
index 000000000..b6d26a07f
--- /dev/null
+++ b/ports/stm32f4/supervisor/internal_flash.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2019 Lucian Copeland 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_STM32F4_INTERNAL_FLASH_H
+#define MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/mpconfig.h"
+
+#ifdef STM32F411xE
+#define STM32_FLASH_SIZE 0x80000 //512KiB
+#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#endif
+
+#ifdef STM32F412Zx
+#define STM32_FLASH_SIZE 0x100000 //1MB
+#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#endif
+
+#ifdef STM32F405xx
+#define STM32_FLASH_SIZE 0x100000 //1MB
+#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#endif
+
+#define STM32_FLASH_OFFSET 0x8000000 //All STM32 chips map to this flash location
+
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
+
+#define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms
+#define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2)
+
+#endif // MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_H
diff --git a/ports/stm32f4/supervisor/internal_flash_root_pointers.h b/ports/stm32f4/supervisor/internal_flash_root_pointers.h
new file mode 100644
index 000000000..7a8681bd9
--- /dev/null
+++ b/ports/stm32f4/supervisor/internal_flash_root_pointers.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
+ *
+ * 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_STM32F4_INTERNAL_FLASH_ROOT_POINTERS_H
+#define MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_ROOT_POINTERS_H
+
+#define FLASH_ROOT_POINTERS
+
+#endif // MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_ROOT_POINTERS_H
diff --git a/ports/stm32f4/supervisor/port.c b/ports/stm32f4/supervisor/port.c
new file mode 100644
index 000000000..df7a6ca42
--- /dev/null
+++ b/ports/stm32f4/supervisor/port.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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 "supervisor/port.h"
+#include "boards/board.h"
+#include "tick.h"
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/busio/I2C.h"
+#include "common-hal/busio/SPI.h"
+
+#include "stm32f4/clocks.h"
+#include "stm32f4/gpio.h"
+
+#include "stm32f4xx_hal.h"
+
+safe_mode_t port_init(void) {
+ HAL_Init();
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ stm32f4_peripherals_clocks_init();
+ stm32f4_peripherals_gpio_init();
+
+ tick_init();
+ board_init();
+
+ return NO_SAFE_MODE;
+}
+
+void reset_port(void) {
+ reset_all_pins();
+ i2c_reset();
+ spi_reset();
+}
+
+void reset_to_bootloader(void) {
+
+}
+
+void reset_cpu(void) {
+ NVIC_SystemReset();
+}
+
+extern uint32_t _ebss;
+// Place the word to save just after our BSS section that gets blanked.
+void port_set_saved_word(uint32_t value) {
+ _ebss = value;
+}
+
+uint32_t port_get_saved_word(void) {
+ return _ebss;
+}
+
+void HardFault_Handler(void) {
+ reset_into_safe_mode(HARD_CRASH);
+ while (true) {
+ asm("nop;");
+ }
+}
diff --git a/ports/stm32f4/supervisor/qspi_flash.c b/ports/stm32f4/supervisor/qspi_flash.c
new file mode 100644
index 000000000..f3915273b
--- /dev/null
+++ b/ports/stm32f4/supervisor/qspi_flash.c
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ * 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 "supervisor/spi_flash_api.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "py/mpconfig.h" // for EXTERNAL_FLASH_QSPI_DUAL
+//#include "nrfx_qspi.h"
+
+//#include "shared-bindings/microcontroller/__init__.h"
+
+#include "supervisor/shared/external_flash/common_commands.h"
+#include "supervisor/shared/external_flash/qspi_flash.h"
+
+bool spi_flash_command(uint8_t command) {
+ // nrf_qspi_cinstr_conf_t cinstr_cfg = {
+ // .opcode = command,
+ // .length = 1,
+ // .io2_level = true,
+ // .io3_level = true,
+ // .wipwait = false,
+ // .wren = false
+ // };
+ return false; //nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL) == NRFX_SUCCESS;
+}
+
+bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) {
+ // nrf_qspi_cinstr_conf_t cinstr_cfg = {
+ // .opcode = command,
+ // .length = length + 1,
+ // .io2_level = true,
+ // .io3_level = true,
+ // .wipwait = false,
+ // .wren = false
+ // };
+ // return nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, response) == NRFX_SUCCESS;
+ return false;
+
+}
+
+bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) {
+ // nrf_qspi_cinstr_conf_t cinstr_cfg = {
+ // .opcode = command,
+ // .length = length + 1,
+ // .io2_level = true,
+ // .io3_level = true,
+ // .wipwait = false,
+ // .wren = false // We do this manually.
+ // };
+ // return nrfx_qspi_cinstr_xfer(&cinstr_cfg, data, NULL) == NRFX_SUCCESS;
+ return false;
+}
+
+bool spi_flash_sector_command(uint8_t command, uint32_t address) {
+ // if (command != CMD_SECTOR_ERASE) {
+ // return false;
+ // }
+ // return nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, address) == NRFX_SUCCESS;
+ return false;
+}
+
+bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
+ // return nrfx_qspi_write(data, length, address) == NRFX_SUCCESS;
+ return false;
+}
+
+bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
+ // return nrfx_qspi_read(data, length, address) == NRFX_SUCCESS;
+ return false;
+}
+
+void spi_flash_init(void) {
+ // Init QSPI flash
+// nrfx_qspi_config_t qspi_cfg = {
+// .xip_offset = 0,
+// .pins = {
+// .sck_pin = MICROPY_QSPI_SCK,
+// .csn_pin = MICROPY_QSPI_CS,
+// .io0_pin = MICROPY_QSPI_DATA0,
+// .io1_pin = NRF_QSPI_PIN_NOT_CONNECTED,
+// .io2_pin = NRF_QSPI_PIN_NOT_CONNECTED,
+// .io3_pin = NRF_QSPI_PIN_NOT_CONNECTED,
+
+// },
+// .prot_if = {
+// .readoc = NRF_QSPI_READOC_FASTREAD,
+// .writeoc = NRF_QSPI_WRITEOC_PP,
+// .addrmode = NRF_QSPI_ADDRMODE_24BIT,
+// .dpmconfig = false
+// },
+// .phy_if = {
+// .sck_freq = NRF_QSPI_FREQ_32MDIV16, // Start at a slow 2MHz and speed up once we know what we're talking to.
+// .sck_delay = 10, // min time CS must stay high before going low again. in unit of 62.5 ns
+// .spi_mode = NRF_QSPI_MODE_0,
+// .dpmen = false
+// },
+// .irq_priority = 7,
+// };
+
+// #if EXTERNAL_FLASH_QSPI_DUAL
+// qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1;
+// qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ2O;
+// qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O;
+// #else
+// qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1;
+// qspi_cfg.pins.io2_pin = MICROPY_QSPI_DATA2;
+// qspi_cfg.pins.io3_pin = MICROPY_QSPI_DATA3;
+// qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ4IO;
+// qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4O;
+// #endif
+
+// // No callback for blocking API
+// nrfx_qspi_init(&qspi_cfg, NULL, NULL);
+}
+
+void spi_flash_init_device(const external_flash_device* device) {
+ // check_quad_enable(device);
+
+ // // Switch to single output line if the device doesn't support quad programs.
+ // if (!device->supports_qspi_writes) {
+ // NRF_QSPI->IFCONFIG0 &= ~QSPI_IFCONFIG0_WRITEOC_Msk;
+ // NRF_QSPI->IFCONFIG0 |= QSPI_IFCONFIG0_WRITEOC_PP << QSPI_IFCONFIG0_WRITEOC_Pos;
+ // }
+
+ // // Speed up as much as we can.
+ // // Start at 16 MHz and go down.
+ // // At 32 MHz GD25Q16C doesn't work reliably on Feather 52840, even though it should work up to 104 MHz.
+ // // sckfreq = 0 is 32 Mhz
+ // // sckfreq = 1 is 16 MHz, etc.
+ // uint8_t sckfreq = 1;
+ // while (32000000 / (sckfreq + 1) > device->max_clock_speed_mhz * 1000000 && sckfreq < 16) {
+ // sckfreq += 1;
+ // }
+ // NRF_QSPI->IFCONFIG1 &= ~QSPI_IFCONFIG1_SCKFREQ_Msk;
+ // NRF_QSPI->IFCONFIG1 |= sckfreq << QSPI_IFCONFIG1_SCKFREQ_Pos;
+}
diff --git a/ports/stm32f4/supervisor/serial.c b/ports/stm32f4/supervisor/serial.c
new file mode 100644
index 000000000..ce1366000
--- /dev/null
+++ b/ports/stm32f4/supervisor/serial.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mphal.h"
+#include <string.h>
+#include "supervisor/serial.h"
+#include "stm32f4xx_hal.h"
+#include "stm32f4/gpio.h"
+
+UART_HandleTypeDef huart2;
+
+void serial_init(void) {
+ huart2.Instance = USART2;
+ huart2.Init.BaudRate = 115200;
+ huart2.Init.WordLength = UART_WORDLENGTH_8B;
+ huart2.Init.StopBits = UART_STOPBITS_1;
+ huart2.Init.Parity = UART_PARITY_NONE;
+ huart2.Init.Mode = UART_MODE_TX_RX;
+ huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart2.Init.OverSampling = UART_OVERSAMPLING_16;
+ if (HAL_UART_Init(&huart2) == HAL_OK)
+ {
+ stm32f4_peripherals_status_led(1,1);
+ }
+}
+
+bool serial_connected(void) {
+ return true;
+}
+
+char serial_read(void) {
+ uint8_t data;
+ HAL_UART_Receive(&huart2, &data, 1,500);
+ return data;
+}
+
+bool serial_bytes_available(void) {
+ return __HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE);
+}
+
+void serial_write(const char* text) {
+ serial_write_substring(text, strlen(text));
+}
+
+void serial_write_substring(const char *text, uint32_t len) {
+ if (len == 0) {
+ return;
+ }
+ HAL_UART_Transmit(&huart2, (uint8_t*)text, len, 5000);
+}
+
diff --git a/ports/stm32f4/supervisor/usb.c b/ports/stm32f4/supervisor/usb.c
new file mode 100644
index 000000000..f327050f5
--- /dev/null
+++ b/ports/stm32f4/supervisor/usb.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 hathach for Adafruit Industries
+ * Copyright (c) 2019 Lucian Copeland 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 "tick.h"
+#include "supervisor/usb.h"
+#include "lib/utils/interrupt_char.h"
+#include "lib/mp-readline/readline.h"
+#include "stm32f4xx_hal.h"
+
+#include "common-hal/microcontroller/Pin.h"
+
+void init_usb_hardware(void) {
+ //TODO: if future chips overload this with options, move to peripherals management.
+
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ /**USB_OTG_FS GPIO Configuration
+ PA10 ------> USB_OTG_FS_ID
+ PA11 ------> USB_OTG_FS_DM
+ PA12 ------> USB_OTG_FS_DP
+ */
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+
+ /* Configure DM DP Pins */
+ GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ never_reset_pin_number(0, 11);
+ never_reset_pin_number(0, 12);
+
+ /* Configure VBUS Pin */
+ GPIO_InitStruct.Pin = GPIO_PIN_9;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ never_reset_pin_number(0, 9);
+
+ /* This for ID line debug */
+ GPIO_InitStruct.Pin = GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ never_reset_pin_number(0, 10);
+
+#ifdef STM32F412Zx
+ /* Configure POWER_SWITCH IO pin (F412 ONLY)*/
+ GPIO_InitStruct.Pin = GPIO_PIN_8;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+ never_reset_pin_number(0, 8);
+#endif
+
+ /* Peripheral clock enable */
+ __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
+}
diff --git a/ports/stm32f4/system_stm32f4xx.c b/ports/stm32f4/system_stm32f4xx.c
new file mode 100644
index 000000000..3303f969d
--- /dev/null
+++ b/ports/stm32f4/system_stm32f4xx.c
@@ -0,0 +1,761 @@
+/**
+ ******************************************************************************
+ * @file system_stm32f4xx.c
+ * @author MCD Application Team
+ * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
+ *
+ * This file provides two functions and one global variable to be called from
+ * user application:
+ * - SystemInit(): This function is called at startup just after reset and
+ * before branch to main program. This call is made inside
+ * the "startup_stm32f4xx.s" file.
+ *
+ * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+ * by the user application to setup the SysTick
+ * timer or configure other parameters.
+ *
+ * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+ * be called whenever the core clock is changed
+ * during program execution.
+ *
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2017 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32f4xx_system
+ * @{
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Includes
+ * @{
+ */
+
+
+#include "stm32f4xx.h"
+
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Defines
+ * @{
+ */
+
+/************************* Miscellaneous Configuration ************************/
+/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
+#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
+ || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
+ || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
+/* #define DATA_IN_ExtSRAM */
+#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
+ STM32F412Zx || STM32F412Vx */
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
+ || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
+/* #define DATA_IN_ExtSDRAM */
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
+ STM32F479xx */
+
+/*!< Uncomment the following line if you need to relocate your vector Table in
+ Internal SRAM. */
+/* #define VECT_TAB_SRAM */
+#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
+ This value must be a multiple of 0x200. */
+/******************************************************************************/
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Variables
+ * @{
+ */
+ /* This variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock; then there
+ is no need to call the 2 first functions listed above, since SystemCoreClock
+ variable is updated automatically.
+ */
+uint32_t SystemCoreClock = 16000000;
+const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
+ * @{
+ */
+
+#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
+ static void SystemInit_ExtMemCtl(void);
+#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Setup the microcontroller system
+ * Initialize the FPU setting, vector table location and External memory
+ * configuration.
+ * @param None
+ * @retval None
+ */
+void SystemInit(void)
+{
+ /* FPU settings ------------------------------------------------------------*/
+ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
+ #endif
+ /* Reset the RCC clock configuration to the default reset state ------------*/
+ /* Set HSION bit */
+ RCC->CR |= (uint32_t)0x00000001;
+
+ /* Reset CFGR register */
+ RCC->CFGR = 0x00000000;
+
+ /* Reset HSEON, CSSON and PLLON bits */
+ RCC->CR &= (uint32_t)0xFEF6FFFF;
+
+ /* Reset PLLCFGR register */
+ RCC->PLLCFGR = 0x24003010;
+
+ /* Reset HSEBYP bit */
+ RCC->CR &= (uint32_t)0xFFFBFFFF;
+
+ /* Disable all interrupts */
+ RCC->CIR = 0x00000000;
+
+#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
+ SystemInit_ExtMemCtl();
+#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
+
+ /* Configure the Vector Table location add offset address ------------------*/
+#ifdef VECT_TAB_SRAM
+ SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+#else
+ SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
+#endif
+}
+
+/**
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ * The SystemCoreClock variable contains the core clock (HCLK), it can
+ * be used by the user application to setup the SysTick timer or configure
+ * other parameters.
+ *
+ * @note Each time the core clock (HCLK) changes, this function must be called
+ * to update SystemCoreClock variable value. Otherwise, any configuration
+ * based on this variable will be incorrect.
+ *
+ * @note - The system frequency computed by this function is not the real
+ * frequency in the chip. It is calculated based on the predefined
+ * constant and the selected clock source:
+ *
+ * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
+ *
+ * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
+ *
+ * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.
+ *
+ * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
+ * 16 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ *
+ * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
+ * depends on the application requirements), user has to ensure that HSE_VALUE
+ * is same as the real frequency of the crystal used. Otherwise, this function
+ * may have wrong result.
+ *
+ * - The result of this function could be not correct when using fractional
+ * value for HSE crystal.
+ *
+ * @param None
+ * @retval None
+ */
+void SystemCoreClockUpdate(void)
+{
+ uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ tmp = RCC->CFGR & RCC_CFGR_SWS;
+
+ switch (tmp)
+ {
+ case 0x00: /* HSI used as system clock source */
+ SystemCoreClock = HSI_VALUE;
+ break;
+ case 0x04: /* HSE used as system clock source */
+ SystemCoreClock = HSE_VALUE;
+ break;
+ case 0x08: /* PLL used as system clock source */
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
+ SYSCLK = PLL_VCO / PLL_P
+ */
+ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+ pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+
+ if (pllsource != 0)
+ {
+ /* HSE used as PLL clock source */
+ pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+ }
+ else
+ {
+ /* HSI used as PLL clock source */
+ pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+ }
+
+ pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
+ SystemCoreClock = pllvco/pllp;
+ break;
+ default:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ }
+ /* Compute HCLK frequency --------------------------------------------------*/
+ /* Get HCLK prescaler */
+ tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
+ /* HCLK frequency */
+ SystemCoreClock >>= tmp;
+}
+
+#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
+ || defined(STM32F469xx) || defined(STM32F479xx)
+/**
+ * @brief Setup the external memory controller.
+ * Called in startup_stm32f4xx.s before jump to main.
+ * This function configures the external memories (SRAM/SDRAM)
+ * This SRAM/SDRAM will be used as program data memory (including heap and stack).
+ * @param None
+ * @retval None
+ */
+void SystemInit_ExtMemCtl(void)
+{
+ __IO uint32_t tmp = 0x00;
+
+ register uint32_t tmpreg = 0, timeout = 0xFFFF;
+ register __IO uint32_t index;
+
+ /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
+ RCC->AHB1ENR |= 0x000001F8;
+
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
+
+ /* Connect PDx pins to FMC Alternate function */
+ GPIOD->AFR[0] = 0x00CCC0CC;
+ GPIOD->AFR[1] = 0xCCCCCCCC;
+ /* Configure PDx pins in Alternate function mode */
+ GPIOD->MODER = 0xAAAA0A8A;
+ /* Configure PDx pins speed to 100 MHz */
+ GPIOD->OSPEEDR = 0xFFFF0FCF;
+ /* Configure PDx pins Output type to push-pull */
+ GPIOD->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PDx pins */
+ GPIOD->PUPDR = 0x00000000;
+
+ /* Connect PEx pins to FMC Alternate function */
+ GPIOE->AFR[0] = 0xC00CC0CC;
+ GPIOE->AFR[1] = 0xCCCCCCCC;
+ /* Configure PEx pins in Alternate function mode */
+ GPIOE->MODER = 0xAAAA828A;
+ /* Configure PEx pins speed to 100 MHz */
+ GPIOE->OSPEEDR = 0xFFFFC3CF;
+ /* Configure PEx pins Output type to push-pull */
+ GPIOE->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PEx pins */
+ GPIOE->PUPDR = 0x00000000;
+
+ /* Connect PFx pins to FMC Alternate function */
+ GPIOF->AFR[0] = 0xCCCCCCCC;
+ GPIOF->AFR[1] = 0xCCCCCCCC;
+ /* Configure PFx pins in Alternate function mode */
+ GPIOF->MODER = 0xAA800AAA;
+ /* Configure PFx pins speed to 50 MHz */
+ GPIOF->OSPEEDR = 0xAA800AAA;
+ /* Configure PFx pins Output type to push-pull */
+ GPIOF->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PFx pins */
+ GPIOF->PUPDR = 0x00000000;
+
+ /* Connect PGx pins to FMC Alternate function */
+ GPIOG->AFR[0] = 0xCCCCCCCC;
+ GPIOG->AFR[1] = 0xCCCCCCCC;
+ /* Configure PGx pins in Alternate function mode */
+ GPIOG->MODER = 0xAAAAAAAA;
+ /* Configure PGx pins speed to 50 MHz */
+ GPIOG->OSPEEDR = 0xAAAAAAAA;
+ /* Configure PGx pins Output type to push-pull */
+ GPIOG->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PGx pins */
+ GPIOG->PUPDR = 0x00000000;
+
+ /* Connect PHx pins to FMC Alternate function */
+ GPIOH->AFR[0] = 0x00C0CC00;
+ GPIOH->AFR[1] = 0xCCCCCCCC;
+ /* Configure PHx pins in Alternate function mode */
+ GPIOH->MODER = 0xAAAA08A0;
+ /* Configure PHx pins speed to 50 MHz */
+ GPIOH->OSPEEDR = 0xAAAA08A0;
+ /* Configure PHx pins Output type to push-pull */
+ GPIOH->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PHx pins */
+ GPIOH->PUPDR = 0x00000000;
+
+ /* Connect PIx pins to FMC Alternate function */
+ GPIOI->AFR[0] = 0xCCCCCCCC;
+ GPIOI->AFR[1] = 0x00000CC0;
+ /* Configure PIx pins in Alternate function mode */
+ GPIOI->MODER = 0x0028AAAA;
+ /* Configure PIx pins speed to 50 MHz */
+ GPIOI->OSPEEDR = 0x0028AAAA;
+ /* Configure PIx pins Output type to push-pull */
+ GPIOI->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PIx pins */
+ GPIOI->PUPDR = 0x00000000;
+
+/*-- FMC Configuration -------------------------------------------------------*/
+ /* Enable the FMC interface clock */
+ RCC->AHB3ENR |= 0x00000001;
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
+
+ FMC_Bank5_6->SDCR[0] = 0x000019E4;
+ FMC_Bank5_6->SDTR[0] = 0x01115351;
+
+ /* SDRAM initialization sequence */
+ /* Clock enable command */
+ FMC_Bank5_6->SDCMR = 0x00000011;
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* Delay */
+ for (index = 0; index<1000; index++);
+
+ /* PALL command */
+ FMC_Bank5_6->SDCMR = 0x00000012;
+ timeout = 0xFFFF;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* Auto refresh command */
+ FMC_Bank5_6->SDCMR = 0x00000073;
+ timeout = 0xFFFF;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* MRD register program */
+ FMC_Bank5_6->SDCMR = 0x00046014;
+ timeout = 0xFFFF;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* Set refresh count */
+ tmpreg = FMC_Bank5_6->SDRTR;
+ FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
+
+ /* Disable write protection */
+ tmpreg = FMC_Bank5_6->SDCR[0];
+ FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
+ /* Configure and enable Bank1_SRAM2 */
+ FMC_Bank1->BTCR[2] = 0x00001011;
+ FMC_Bank1->BTCR[3] = 0x00000201;
+ FMC_Bank1E->BWTR[2] = 0x0fffffff;
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
+#if defined(STM32F469xx) || defined(STM32F479xx)
+ /* Configure and enable Bank1_SRAM2 */
+ FMC_Bank1->BTCR[2] = 0x00001091;
+ FMC_Bank1->BTCR[3] = 0x00110212;
+ FMC_Bank1E->BWTR[2] = 0x0fffffff;
+#endif /* STM32F469xx || STM32F479xx */
+
+ (void)(tmp);
+}
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
+#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
+/**
+ * @brief Setup the external memory controller.
+ * Called in startup_stm32f4xx.s before jump to main.
+ * This function configures the external memories (SRAM/SDRAM)
+ * This SRAM/SDRAM will be used as program data memory (including heap and stack).
+ * @param None
+ * @retval None
+ */
+void SystemInit_ExtMemCtl(void)
+{
+ __IO uint32_t tmp = 0x00;
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
+ || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
+#if defined (DATA_IN_ExtSDRAM)
+ register uint32_t tmpreg = 0, timeout = 0xFFFF;
+ register __IO uint32_t index;
+
+#if defined(STM32F446xx)
+ /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
+ clock */
+ RCC->AHB1ENR |= 0x0000007D;
+#else
+ /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
+ clock */
+ RCC->AHB1ENR |= 0x000001F8;
+#endif /* STM32F446xx */
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
+
+#if defined(STM32F446xx)
+ /* Connect PAx pins to FMC Alternate function */
+ GPIOA->AFR[0] |= 0xC0000000;
+ GPIOA->AFR[1] |= 0x00000000;
+ /* Configure PDx pins in Alternate function mode */
+ GPIOA->MODER |= 0x00008000;
+ /* Configure PDx pins speed to 50 MHz */
+ GPIOA->OSPEEDR |= 0x00008000;
+ /* Configure PDx pins Output type to push-pull */
+ GPIOA->OTYPER |= 0x00000000;
+ /* No pull-up, pull-down for PDx pins */
+ GPIOA->PUPDR |= 0x00000000;
+
+ /* Connect PCx pins to FMC Alternate function */
+ GPIOC->AFR[0] |= 0x00CC0000;
+ GPIOC->AFR[1] |= 0x00000000;
+ /* Configure PDx pins in Alternate function mode */
+ GPIOC->MODER |= 0x00000A00;
+ /* Configure PDx pins speed to 50 MHz */
+ GPIOC->OSPEEDR |= 0x00000A00;
+ /* Configure PDx pins Output type to push-pull */
+ GPIOC->OTYPER |= 0x00000000;
+ /* No pull-up, pull-down for PDx pins */
+ GPIOC->PUPDR |= 0x00000000;
+#endif /* STM32F446xx */
+
+ /* Connect PDx pins to FMC Alternate function */
+ GPIOD->AFR[0] = 0x000000CC;
+ GPIOD->AFR[1] = 0xCC000CCC;
+ /* Configure PDx pins in Alternate function mode */
+ GPIOD->MODER = 0xA02A000A;
+ /* Configure PDx pins speed to 50 MHz */
+ GPIOD->OSPEEDR = 0xA02A000A;
+ /* Configure PDx pins Output type to push-pull */
+ GPIOD->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PDx pins */
+ GPIOD->PUPDR = 0x00000000;
+
+ /* Connect PEx pins to FMC Alternate function */
+ GPIOE->AFR[0] = 0xC00000CC;
+ GPIOE->AFR[1] = 0xCCCCCCCC;
+ /* Configure PEx pins in Alternate function mode */
+ GPIOE->MODER = 0xAAAA800A;
+ /* Configure PEx pins speed to 50 MHz */
+ GPIOE->OSPEEDR = 0xAAAA800A;
+ /* Configure PEx pins Output type to push-pull */
+ GPIOE->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PEx pins */
+ GPIOE->PUPDR = 0x00000000;
+
+ /* Connect PFx pins to FMC Alternate function */
+ GPIOF->AFR[0] = 0xCCCCCCCC;
+ GPIOF->AFR[1] = 0xCCCCCCCC;
+ /* Configure PFx pins in Alternate function mode */
+ GPIOF->MODER = 0xAA800AAA;
+ /* Configure PFx pins speed to 50 MHz */
+ GPIOF->OSPEEDR = 0xAA800AAA;
+ /* Configure PFx pins Output type to push-pull */
+ GPIOF->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PFx pins */
+ GPIOF->PUPDR = 0x00000000;
+
+ /* Connect PGx pins to FMC Alternate function */
+ GPIOG->AFR[0] = 0xCCCCCCCC;
+ GPIOG->AFR[1] = 0xCCCCCCCC;
+ /* Configure PGx pins in Alternate function mode */
+ GPIOG->MODER = 0xAAAAAAAA;
+ /* Configure PGx pins speed to 50 MHz */
+ GPIOG->OSPEEDR = 0xAAAAAAAA;
+ /* Configure PGx pins Output type to push-pull */
+ GPIOG->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PGx pins */
+ GPIOG->PUPDR = 0x00000000;
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
+ || defined(STM32F469xx) || defined(STM32F479xx)
+ /* Connect PHx pins to FMC Alternate function */
+ GPIOH->AFR[0] = 0x00C0CC00;
+ GPIOH->AFR[1] = 0xCCCCCCCC;
+ /* Configure PHx pins in Alternate function mode */
+ GPIOH->MODER = 0xAAAA08A0;
+ /* Configure PHx pins speed to 50 MHz */
+ GPIOH->OSPEEDR = 0xAAAA08A0;
+ /* Configure PHx pins Output type to push-pull */
+ GPIOH->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PHx pins */
+ GPIOH->PUPDR = 0x00000000;
+
+ /* Connect PIx pins to FMC Alternate function */
+ GPIOI->AFR[0] = 0xCCCCCCCC;
+ GPIOI->AFR[1] = 0x00000CC0;
+ /* Configure PIx pins in Alternate function mode */
+ GPIOI->MODER = 0x0028AAAA;
+ /* Configure PIx pins speed to 50 MHz */
+ GPIOI->OSPEEDR = 0x0028AAAA;
+ /* Configure PIx pins Output type to push-pull */
+ GPIOI->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PIx pins */
+ GPIOI->PUPDR = 0x00000000;
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
+
+/*-- FMC Configuration -------------------------------------------------------*/
+ /* Enable the FMC interface clock */
+ RCC->AHB3ENR |= 0x00000001;
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
+
+ /* Configure and enable SDRAM bank1 */
+#if defined(STM32F446xx)
+ FMC_Bank5_6->SDCR[0] = 0x00001954;
+#else
+ FMC_Bank5_6->SDCR[0] = 0x000019E4;
+#endif /* STM32F446xx */
+ FMC_Bank5_6->SDTR[0] = 0x01115351;
+
+ /* SDRAM initialization sequence */
+ /* Clock enable command */
+ FMC_Bank5_6->SDCMR = 0x00000011;
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* Delay */
+ for (index = 0; index<1000; index++);
+
+ /* PALL command */
+ FMC_Bank5_6->SDCMR = 0x00000012;
+ timeout = 0xFFFF;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* Auto refresh command */
+#if defined(STM32F446xx)
+ FMC_Bank5_6->SDCMR = 0x000000F3;
+#else
+ FMC_Bank5_6->SDCMR = 0x00000073;
+#endif /* STM32F446xx */
+ timeout = 0xFFFF;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* MRD register program */
+#if defined(STM32F446xx)
+ FMC_Bank5_6->SDCMR = 0x00044014;
+#else
+ FMC_Bank5_6->SDCMR = 0x00046014;
+#endif /* STM32F446xx */
+ timeout = 0xFFFF;
+ while((tmpreg != 0) && (timeout-- > 0))
+ {
+ tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
+ }
+
+ /* Set refresh count */
+ tmpreg = FMC_Bank5_6->SDRTR;
+#if defined(STM32F446xx)
+ FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
+#else
+ FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
+#endif /* STM32F446xx */
+
+ /* Disable write protection */
+ tmpreg = FMC_Bank5_6->SDCR[0];
+ FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
+#endif /* DATA_IN_ExtSDRAM */
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
+
+#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
+ || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
+ || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
+
+#if defined(DATA_IN_ExtSRAM)
+/*-- GPIOs Configuration -----------------------------------------------------*/
+ /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
+ RCC->AHB1ENR |= 0x00000078;
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
+
+ /* Connect PDx pins to FMC Alternate function */
+ GPIOD->AFR[0] = 0x00CCC0CC;
+ GPIOD->AFR[1] = 0xCCCCCCCC;
+ /* Configure PDx pins in Alternate function mode */
+ GPIOD->MODER = 0xAAAA0A8A;
+ /* Configure PDx pins speed to 100 MHz */
+ GPIOD->OSPEEDR = 0xFFFF0FCF;
+ /* Configure PDx pins Output type to push-pull */
+ GPIOD->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PDx pins */
+ GPIOD->PUPDR = 0x00000000;
+
+ /* Connect PEx pins to FMC Alternate function */
+ GPIOE->AFR[0] = 0xC00CC0CC;
+ GPIOE->AFR[1] = 0xCCCCCCCC;
+ /* Configure PEx pins in Alternate function mode */
+ GPIOE->MODER = 0xAAAA828A;
+ /* Configure PEx pins speed to 100 MHz */
+ GPIOE->OSPEEDR = 0xFFFFC3CF;
+ /* Configure PEx pins Output type to push-pull */
+ GPIOE->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PEx pins */
+ GPIOE->PUPDR = 0x00000000;
+
+ /* Connect PFx pins to FMC Alternate function */
+ GPIOF->AFR[0] = 0x00CCCCCC;
+ GPIOF->AFR[1] = 0xCCCC0000;
+ /* Configure PFx pins in Alternate function mode */
+ GPIOF->MODER = 0xAA000AAA;
+ /* Configure PFx pins speed to 100 MHz */
+ GPIOF->OSPEEDR = 0xFF000FFF;
+ /* Configure PFx pins Output type to push-pull */
+ GPIOF->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PFx pins */
+ GPIOF->PUPDR = 0x00000000;
+
+ /* Connect PGx pins to FMC Alternate function */
+ GPIOG->AFR[0] = 0x00CCCCCC;
+ GPIOG->AFR[1] = 0x000000C0;
+ /* Configure PGx pins in Alternate function mode */
+ GPIOG->MODER = 0x00085AAA;
+ /* Configure PGx pins speed to 100 MHz */
+ GPIOG->OSPEEDR = 0x000CAFFF;
+ /* Configure PGx pins Output type to push-pull */
+ GPIOG->OTYPER = 0x00000000;
+ /* No pull-up, pull-down for PGx pins */
+ GPIOG->PUPDR = 0x00000000;
+
+/*-- FMC/FSMC Configuration --------------------------------------------------*/
+ /* Enable the FMC/FSMC interface clock */
+ RCC->AHB3ENR |= 0x00000001;
+
+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
+ /* Configure and enable Bank1_SRAM2 */
+ FMC_Bank1->BTCR[2] = 0x00001011;
+ FMC_Bank1->BTCR[3] = 0x00000201;
+ FMC_Bank1E->BWTR[2] = 0x0fffffff;
+#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
+#if defined(STM32F469xx) || defined(STM32F479xx)
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
+ /* Configure and enable Bank1_SRAM2 */
+ FMC_Bank1->BTCR[2] = 0x00001091;
+ FMC_Bank1->BTCR[3] = 0x00110212;
+ FMC_Bank1E->BWTR[2] = 0x0fffffff;
+#endif /* STM32F469xx || STM32F479xx */
+#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
+ || defined(STM32F412Zx) || defined(STM32F412Vx)
+ /* Delay after an RCC peripheral clock enabling */
+ tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
+ /* Configure and enable Bank1_SRAM2 */
+ FSMC_Bank1->BTCR[2] = 0x00001011;
+ FSMC_Bank1->BTCR[3] = 0x00000201;
+ FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
+#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
+
+#endif /* DATA_IN_ExtSRAM */
+#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
+ STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
+ (void)(tmp);
+}
+#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32f4/tick.c b/ports/stm32f4/tick.c
new file mode 100644
index 000000000..43521fb51
--- /dev/null
+++ b/ports/stm32f4/tick.c
@@ -0,0 +1,90 @@
+/*
+ * 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 "tick.h"
+
+#include "supervisor/shared/autoreload.h"
+#include "supervisor/filesystem.h"
+#include "shared-module/gamepad/__init__.h"
+#include "shared-bindings/microcontroller/Processor.h"
+
+#include "stm32f4xx.h"
+
+// Global millisecond tick count
+volatile uint64_t ticks_ms = 0;
+
+void SysTick_Handler(void) {
+ // SysTick interrupt handler called when the SysTick timer reaches zero
+ // (every millisecond).
+ ticks_ms += 1;
+
+#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
+ filesystem_tick();
+#endif
+#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
+ autoreload_tick();
+#endif
+#ifdef CIRCUITPY_GAMEPAD_TICKS
+ if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
+ gamepad_tick();
+ }
+#endif
+}
+
+uint32_t HAL_GetTick(void) //override ST HAL
+{
+ return (uint32_t)ticks_ms;
+}
+
+void tick_init() {
+ uint32_t ticks_per_ms = SystemCoreClock/ 1000;
+ SysTick_Config(ticks_per_ms); // interrupt is enabled
+}
+
+void tick_delay(uint32_t us) {
+ uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000;
+ uint32_t us_between_ticks = SysTick->VAL / ticks_per_us;
+ uint64_t start_ms = ticks_ms;
+ while (us > 1000) {
+ while (ticks_ms == start_ms) {}
+ us -= us_between_ticks;
+ start_ms = ticks_ms;
+ us_between_ticks = 1000;
+ }
+ while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
+}
+
+// us counts down!
+void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
+ uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000;
+ *ms = ticks_ms;
+ *us_until_ms = SysTick->VAL / ticks_per_us;
+}
+
+void wait_until(uint64_t ms, uint32_t us_until_ms) {
+ uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000;
+ while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
+}
diff --git a/ports/stm32f4/tick.h b/ports/stm32f4/tick.h
new file mode 100644
index 000000000..e4772fa2c
--- /dev/null
+++ b/ports/stm32f4/tick.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_STM32F4_TICK_H
+#define MICROPY_INCLUDED_STM32F4_TICK_H
+
+#include "py/mpconfig.h"
+
+#include <stdint.h>
+
+extern volatile uint64_t ticks_ms;
+
+extern struct timer_descriptor ms_timer;
+
+void tick_init(void);
+
+void tick_delay(uint32_t us);
+
+void current_tick(uint64_t* ms, uint32_t* us_until_ms);
+// Do not call this with interrupts disabled because it may be waiting for
+// ticks_ms to increment.
+void wait_until(uint64_t ms, uint32_t us_until_ms);
+
+#endif // MICROPY_INCLUDED_STM32F4_TICK_H
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 782314fc7..b72d75390 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -108,11 +108,24 @@ endif
ifeq ($(CIRCUITPY_AUDIOIO),1)
SRC_PATTERNS += audioio/%
endif
+ifeq ($(CIRCUITPY_AUDIOPWMIO),1)
+SRC_PATTERNS += audiopwmio/%
+endif
+ifeq ($(CIRCUITPY_AUDIOCORE),1)
+SRC_PATTERNS += audiocore/%
+endif
+ifeq ($(CIRCUITPY_AUDIOMIXER),1)
+SRC_PATTERNS += audiomixer/%
+endif
ifeq ($(CIRCUITPY_BITBANGIO),1)
SRC_PATTERNS += bitbangio/%
endif
+# Some builds need bitbang SPI for the dotstar but don't make bitbangio available so include it separately.
+ifeq ($(CIRCUITPY_BITBANG_APA102),1)
+SRC_PATTERNS += bitbangio/SPI%
+endif
ifeq ($(CIRCUITPY_BLEIO),1)
-SRC_PATTERNS += bleio/%
+SRC_PATTERNS += _bleio/%
endif
ifeq ($(CIRCUITPY_BOARD),1)
SRC_PATTERNS += board/%
@@ -211,27 +224,29 @@ ifeq ($(CIRCUITPY_PEW),1)
SRC_PATTERNS += _pew/%
endif
-# All possible sources are listed here, and are filtered by SRC_PATTERNS.
-SRC_COMMON_HAL = \
-$(filter $(SRC_PATTERNS), \
+# All possible sources are listed here, and are filtered by SRC_PATTERNS in SRC_COMMON_HAL
+SRC_COMMON_HAL_ALL = \
+ _bleio/__init__.c \
+ _bleio/Adapter.c \
+ _bleio/Attribute.c \
+ _bleio/Central.c \
+ _bleio/Characteristic.c \
+ _bleio/CharacteristicBuffer.c \
+ _bleio/Descriptor.c \
+ _bleio/Peripheral.c \
+ _bleio/Scanner.c \
+ _bleio/Service.c \
+ _bleio/UUID.c \
analogio/AnalogIn.c \
analogio/AnalogOut.c \
analogio/__init__.c \
audiobusio/__init__.c \
audiobusio/I2SOut.c \
audiobusio/PDMIn.c \
+ audiopwmio/__init__.c \
+ audiopwmio/PWMAudioOut.c \
audioio/__init__.c \
audioio/AudioOut.c \
- bleio/__init__.c \
- bleio/Adapter.c \
- bleio/Central.c \
- bleio/Characteristic.c \
- bleio/CharacteristicBuffer.c \
- bleio/Descriptor.c \
- bleio/Peripheral.c \
- bleio/Scanner.c \
- bleio/Service.c \
- bleio/UUID.c \
board/__init__.c \
busio/I2C.c \
busio/SPI.c \
@@ -263,16 +278,18 @@ $(filter $(SRC_PATTERNS), \
rtc/__init__.c \
supervisor/Runtime.c \
supervisor/__init__.c \
- time/__init__.c \
- touchio/TouchIn.c \
- touchio/__init__.c \
-)
+ time/__init__.c
+
+SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL))
# These don't have corresponding files in each port but are still located in
# shared-bindings to make it clear what the contents of the modules are.
# All possible sources are listed here, and are filtered by SRC_PATTERNS.
SRC_BINDINGS_ENUMS = \
$(filter $(SRC_PATTERNS), \
+ _bleio/Address.c \
+ _bleio/Attribute.c \
+ _bleio/ScanEntry.c \
digitalio/Direction.c \
digitalio/DriveMode.c \
digitalio/Pull.c \
@@ -286,37 +303,36 @@ SRC_BINDINGS_ENUMS += \
help.c \
util.c
-SRC_BINDINGS_ENUMS += \
-$(filter $(SRC_PATTERNS), \
- bleio/Address.c \
- bleio/ScanEntry.c \
-)
-
-# All possible sources are listed here, and are filtered by SRC_PATTERNS.
-SRC_SHARED_MODULE = \
-$(filter $(SRC_PATTERNS), \
+SRC_SHARED_MODULE_ALL = \
+ _bleio/Address.c \
+ _bleio/Attribute.c \
+ _bleio/ScanEntry.c \
_pixelbuf/PixelBuf.c \
_pixelbuf/__init__.c \
_stage/Layer.c \
_stage/Text.c \
_stage/__init__.c \
+ audiopwmio/__init__.c \
audioio/__init__.c \
- audioio/Mixer.c \
- audioio/RawSample.c \
- audioio/WaveFile.c \
+ audiocore/__init__.c \
+ audiocore/RawSample.c \
+ audiocore/WaveFile.c \
+ audiomixer/__init__.c \
+ audiomixer/Mixer.c \
+ audiomixer/MixerVoice.c \
bitbangio/I2C.c \
bitbangio/OneWire.c \
bitbangio/SPI.c \
bitbangio/__init__.c \
board/__init__.c \
- bleio/Address.c \
- bleio/ScanEntry.c \
busio/OneWire.c \
displayio/Bitmap.c \
displayio/ColorConverter.c \
displayio/Display.c \
+ displayio/EPaperDisplay.c \
displayio/FourWire.c \
displayio/Group.c \
+ displayio/I2CDisplay.c \
displayio/OnDiskBitmap.c \
displayio/Palette.c \
displayio/Shape.c \
@@ -339,7 +355,28 @@ $(filter $(SRC_PATTERNS), \
uheap/__init__.c \
ustack/__init__.c \
_pew/__init__.c \
- _pew/PewPew.c \
+ _pew/PewPew.c
+
+# All possible sources are listed here, and are filtered by SRC_PATTERNS.
+SRC_SHARED_MODULE = $(filter $(SRC_PATTERNS), $(SRC_SHARED_MODULE_ALL))
+
+# Use the native touchio if requested. This flag is set conditionally in, say, mpconfigport.h.
+# The presence of common-hal/touchio/* # does not imply it's available for all chips in a port,
+# so there is an explicit flag. For example, SAMD21 touchio is native, but SAMD51 is not.
+ifeq ($(CIRCUITPY_TOUCHIO_USE_NATIVE),1)
+SRC_COMMON_HAL_ALL += \
+ touchio/TouchIn.c \
+ touchio/__init__.c
+else
+SRC_SHARED_MODULE_ALL += \
+ touchio/TouchIn.c \
+ touchio/__init__.c
+endif
+
+# All possible sources are listed here, and are filtered by SRC_PATTERNS.
+SRC_SHARED_MODULE_INTERNAL = \
+$(filter $(SRC_PATTERNS), \
+ displayio/display_core.c \
)
ifeq ($(INTERNAL_LIBM),1)
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index 2026185ef..2cb617819 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -230,6 +230,13 @@ extern const struct _mp_obj_module_t audiobusio_module;
#define AUDIOBUSIO_MODULE
#endif
+#if CIRCUITPY_AUDIOCORE
+#define AUDIOCORE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiocore), (mp_obj_t)&audiocore_module },
+extern const struct _mp_obj_module_t audiocore_module;
+#else
+#define AUDIOCORE_MODULE
+#endif
+
#if CIRCUITPY_AUDIOIO
#define AUDIOIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module },
extern const struct _mp_obj_module_t audioio_module;
@@ -237,6 +244,20 @@ extern const struct _mp_obj_module_t audioio_module;
#define AUDIOIO_MODULE
#endif
+#if CIRCUITPY_AUDIOMIXER
+#define AUDIOMIXER_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiomixer), (mp_obj_t)&audiomixer_module },
+extern const struct _mp_obj_module_t audiomixer_module;
+#else
+#define AUDIOMIXER_MODULE
+#endif
+
+#if CIRCUITPY_AUDIOPWMIO
+#define AUDIOPWMIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiopwmio), (mp_obj_t)&audiopwmio_module },
+extern const struct _mp_obj_module_t audiopwmio_module;
+#else
+#define AUDIOPWMIO_MODULE
+#endif
+
#if CIRCUITPY_BITBANGIO
#define BITBANGIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module },
extern const struct _mp_obj_module_t bitbangio_module;
@@ -245,7 +266,7 @@ extern const struct _mp_obj_module_t bitbangio_module;
#endif
#if CIRCUITPY_BLEIO
-#define BLEIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_bleio), (mp_obj_t)&bleio_module },
+#define BLEIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__bleio), (mp_obj_t)&bleio_module },
extern const struct _mp_obj_module_t bleio_module;
#else
#define BLEIO_MODULE
@@ -259,13 +280,7 @@ extern const struct _mp_obj_module_t board_module;
#define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI))
#define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX))
-#if BOARD_I2C
-#define BOARD_I2C_ROOT_POINTER mp_obj_t shared_i2c_bus;
-#else
-#define BOARD_I2C_ROOT_POINTER
-#endif
-
-// SPI is always allocated off the heap.
+// I2C and SPI are always allocated off the heap.
#if BOARD_UART
#define BOARD_UART_ROOT_POINTER mp_obj_t shared_uart_bus;
@@ -275,7 +290,6 @@ extern const struct _mp_obj_module_t board_module;
#else
#define BOARD_MODULE
-#define BOARD_I2C_ROOT_POINTER
#define BOARD_UART_ROOT_POINTER
#endif
@@ -300,7 +314,7 @@ extern const struct _mp_obj_module_t terminalio_module;
#define DISPLAYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module },
#define FONTIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_fontio), (mp_obj_t)&fontio_module },
#define TERMINALIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_terminalio), (mp_obj_t)&terminalio_module },
-#define CIRCUITPY_DISPLAY_LIMIT (3)
+#define CIRCUITPY_DISPLAY_LIMIT (1)
#else
#define DISPLAYIO_MODULE
#define FONTIO_MODULE
@@ -564,7 +578,10 @@ extern const struct _mp_obj_module_t ustack_module;
#define MICROPY_PORT_BUILTIN_MODULES_STRONG_LINKS \
ANALOGIO_MODULE \
AUDIOBUSIO_MODULE \
+ AUDIOCORE_MODULE \
AUDIOIO_MODULE \
+ AUDIOMIXER_MODULE \
+ AUDIOPWMIO_MODULE \
BITBANGIO_MODULE \
BLEIO_MODULE \
BOARD_MODULE \
@@ -587,8 +604,8 @@ extern const struct _mp_obj_module_t ustack_module;
WIZNET_MODULE \
PEW_MODULE \
PIXELBUF_MODULE \
- PULSEIO_MODULE \
PS2IO_MODULE \
+ PULSEIO_MODULE \
RANDOM_MODULE \
RE_MODULE \
ROTARYIO_MODULE \
@@ -631,12 +648,12 @@ extern const struct _mp_obj_module_t ustack_module;
GAMEPAD_ROOT_POINTERS \
mp_obj_t pew_singleton; \
mp_obj_t terminal_tilegrid_tiles; \
- BOARD_I2C_ROOT_POINTER \
BOARD_UART_ROOT_POINTER \
FLASH_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \
void run_background_tasks(void);
+#define RUN_BACKGROUND_TASKS (run_background_tasks())
// TODO: Used in wiznet5k driver, but may not be needed in the long run.
#define MICROPY_THREAD_YIELD()
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index 47303a73a..c5756f488 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -41,13 +41,26 @@ ifndef CIRCUITPY_FULL_BUILD
endif
endif
+# Setting CIRCUITPY_MINIMAL_BUILD = 1 will disable all features
+# Use for for early stage or highly restricted ports
+ifndef CIRCUITPY_DEFAULT_BUILD
+ ifeq ($(CIRCUITPY_MINIMAL_BUILD),1)
+ CIRCUITPY_FULL_BUILD = 0
+ CIRCUITPY_DEFAULT_BUILD = 0
+ else
+ CIRCUITPY_DEFAULT_BUILD = 1
+ endif
+endif
+
+
+
# All builtin modules are listed below, with default values (0 for off, 1 for on)
# Some are always on, some are always off, and some depend on CIRCUITPY_FULL_BUILD.
#
# *** You can override any of the defaults by defining them in your mpconfigboard.mk.
ifndef CIRCUITPY_ANALOGIO
-CIRCUITPY_ANALOGIO = 1
+CIRCUITPY_ANALOGIO = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_ANALOGIO=$(CIRCUITPY_ANALOGIO)
@@ -61,29 +74,54 @@ CIRCUITPY_AUDIOIO = $(CIRCUITPY_FULL_BUILD)
endif
CFLAGS += -DCIRCUITPY_AUDIOIO=$(CIRCUITPY_AUDIOIO)
+ifndef CIRCUITPY_AUDIOIO_COMPAT
+CIRCUITPY_AUDIOIO_COMPAT = $(CIRCUITPY_AUDIOIO)
+endif
+CFLAGS += -DCIRCUITPY_AUDIOIO_COMPAT=$(CIRCUITPY_AUDIOIO_COMPAT)
+
+
+ifndef CIRCUITPY_AUDIOPWMIO
+CIRCUITPY_AUDIOPWMIO = 0
+endif
+CFLAGS += -DCIRCUITPY_AUDIOPWMIO=$(CIRCUITPY_AUDIOPWMIO)
+
+ifndef CIRCUITPY_AUDIOCORE
+ifeq ($(CIRCUITPY_AUDIOPWMIO),1)
+CIRCUITPY_AUDIOCORE = $(CIRCUITPY_AUDIOPWMIO)
+else
+CIRCUITPY_AUDIOCORE = $(CIRCUITPY_AUDIOIO)
+endif
+endif
+CFLAGS += -DCIRCUITPY_AUDIOCORE=$(CIRCUITPY_AUDIOCORE)
+
+ifndef CIRCUITPY_AUDIOMIXER
+CIRCUITPY_AUDIOMIXER = $(CIRCUITPY_AUDIOIO)
+endif
+CFLAGS += -DCIRCUITPY_AUDIOMIXER=$(CIRCUITPY_AUDIOMIXER)
+
ifndef CIRCUITPY_BITBANGIO
CIRCUITPY_BITBANGIO = $(CIRCUITPY_FULL_BUILD)
endif
CFLAGS += -DCIRCUITPY_BITBANGIO=$(CIRCUITPY_BITBANGIO)
-# Explicitly enabled for boards that support bleio.
+# Explicitly enabled for boards that support _bleio.
ifndef CIRCUITPY_BLEIO
CIRCUITPY_BLEIO = 0
endif
CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO)
ifndef CIRCUITPY_BOARD
-CIRCUITPY_BOARD = 1
+CIRCUITPY_BOARD = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_BOARD=$(CIRCUITPY_BOARD)
ifndef CIRCUITPY_BUSIO
-CIRCUITPY_BUSIO = 1
+CIRCUITPY_BUSIO = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_BUSIO=$(CIRCUITPY_BUSIO)
ifndef CIRCUITPY_DIGITALIO
-CIRCUITPY_DIGITALIO = 1
+CIRCUITPY_DIGITALIO = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_DIGITALIO=$(CIRCUITPY_DIGITALIO)
@@ -113,17 +151,17 @@ endif
CFLAGS += -DCIRCUITPY_I2CSLAVE=$(CIRCUITPY_I2CSLAVE)
ifndef CIRCUITPY_MATH
-CIRCUITPY_MATH = 1
+CIRCUITPY_MATH = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH)
ifndef CIRCUITPY_MICROCONTROLLER
-CIRCUITPY_MICROCONTROLLER = 1
+CIRCUITPY_MICROCONTROLLER = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_MICROCONTROLLER=$(CIRCUITPY_MICROCONTROLLER)
ifndef CIRCUITPY_NEOPIXEL_WRITE
-CIRCUITPY_NEOPIXEL_WRITE = 1
+CIRCUITPY_NEOPIXEL_WRITE = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_NEOPIXEL_WRITE=$(CIRCUITPY_NEOPIXEL_WRITE)
@@ -134,12 +172,12 @@ endif
CFLAGS += -DCIRCUITPY_NETWORK=$(CIRCUITPY_NETWORK)
ifndef CIRCUITPY_NVM
-CIRCUITPY_NVM = 1
+CIRCUITPY_NVM = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_NVM=$(CIRCUITPY_NVM)
ifndef CIRCUITPY_OS
-CIRCUITPY_OS = 1
+CIRCUITPY_OS = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_OS=$(CIRCUITPY_OS)
@@ -149,7 +187,7 @@ endif
CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF)
ifndef CIRCUITPY_PULSEIO
-CIRCUITPY_PULSEIO = 1
+CIRCUITPY_PULSEIO = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_PULSEIO=$(CIRCUITPY_PULSEIO)
@@ -160,17 +198,17 @@ endif
CFLAGS += -DCIRCUITPY_PS2IO=$(CIRCUITPY_PS2IO)
ifndef CIRCUITPY_RANDOM
-CIRCUITPY_RANDOM = 1
+CIRCUITPY_RANDOM = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_RANDOM=$(CIRCUITPY_RANDOM)
ifndef CIRCUITPY_ROTARYIO
-CIRCUITPY_ROTARYIO = 1
+CIRCUITPY_ROTARYIO = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_ROTARYIO=$(CIRCUITPY_ROTARYIO)
ifndef CIRCUITPY_RTC
-CIRCUITPY_RTC = 1
+CIRCUITPY_RTC = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC)
@@ -189,27 +227,33 @@ endif
CFLAGS += -DCIRCUITPY_STAGE=$(CIRCUITPY_STAGE)
ifndef CIRCUITPY_STORAGE
-CIRCUITPY_STORAGE = 1
+CIRCUITPY_STORAGE = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_STORAGE=$(CIRCUITPY_STORAGE)
ifndef CIRCUITPY_STRUCT
-CIRCUITPY_STRUCT = 1
+CIRCUITPY_STRUCT = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_STRUCT=$(CIRCUITPY_STRUCT)
ifndef CIRCUITPY_SUPERVISOR
-CIRCUITPY_SUPERVISOR = 1
+CIRCUITPY_SUPERVISOR = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_SUPERVISOR=$(CIRCUITPY_SUPERVISOR)
ifndef CIRCUITPY_TIME
-CIRCUITPY_TIME = 1
+CIRCUITPY_TIME = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_TIME=$(CIRCUITPY_TIME)
+# touchio might be native or generic. See circuitpy_defns.mk.
+ifndef CIRCUITPY_TOUCHIO_USE_NATIVE
+CIRCUITPY_TOUCHIO_USE_NATIVE = 0
+endif
+CFLAGS += -DCIRCUITPY_TOUCHIO_USE_NATIVE=$(CIRCUITPY_TOUCHIO_USE_NATIVE)
+
ifndef CIRCUITPY_TOUCHIO
-CIRCUITPY_TOUCHIO = 1
+CIRCUITPY_TOUCHIO = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_TOUCHIO=$(CIRCUITPY_TOUCHIO)
@@ -220,12 +264,12 @@ endif
CFLAGS += -DCIRCUITPY_UHEAP=$(CIRCUITPY_UHEAP)
ifndef CIRCUITPY_USB_HID
-CIRCUITPY_USB_HID = 1
+CIRCUITPY_USB_HID = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_USB_HID=$(CIRCUITPY_USB_HID)
ifndef CIRCUITPY_USB_MIDI
-CIRCUITPY_USB_MIDI = 1
+CIRCUITPY_USB_MIDI = $(CIRCUITPY_DEFAULT_BUILD)
endif
CFLAGS += -DCIRCUITPY_USB_MIDI=$(CIRCUITPY_USB_MIDI)
@@ -239,3 +283,9 @@ ifndef CIRCUITPY_USTACK
CIRCUITPY_USTACK = 0
endif
CFLAGS += -DCIRCUITPY_USTACK=$(CIRCUITPY_USTACK)
+
+
+ifndef CIRCUITPY_BITBANG_APA102
+CIRCUITPY_BITBANG_APA102 = 0
+endif
+CFLAGS += -DCIRCUITPY_BITBANG_APA102=$(CIRCUITPY_BITBANG_APA102)
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 5b5ec1c37..8e3835d86 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -180,7 +180,7 @@ def compress(encoding_table, decompressed):
if not isinstance(decompressed, bytes):
raise TypeError()
values, lengths = encoding_table
- enc = bytearray(len(decompressed))
+ enc = bytearray(len(decompressed) * 2)
#print(decompressed)
#print(lengths)
current_bit = 7
@@ -227,6 +227,8 @@ def compress(encoding_table, decompressed):
current_bit -= 1
if current_bit != 7:
current_byte += 1
+ if current_byte > len(decompressed):
+ print("Note: compression increased length", repr(decompressed.decode('utf-8')), len(decompressed), current_byte, file=sys.stderr)
return enc[:current_byte]
def qstr_escape(qst):
diff --git a/py/obj.c b/py/obj.c
index 322a302f9..bd2aaf9d2 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -63,6 +63,9 @@ const char *mp_obj_get_type_str(mp_const_obj_t o_in) {
void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
// There can be data structures nested too deep, or just recursive
MP_STACK_CHECK();
+ #ifdef RUN_BACKGROUND_TASKS
+ RUN_BACKGROUND_TASKS;
+ #endif
#ifndef NDEBUG
if (o_in == MP_OBJ_NULL) {
mp_print_str(print, "(nil)");
diff --git a/py/obj.h b/py/obj.h
index 6eead377d..cf4216d02 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -647,6 +647,7 @@ mp_obj_t mp_obj_new_str(const char* data, size_t len);
mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len);
mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr);
mp_obj_t mp_obj_new_bytes(const byte* data, size_t len);
+mp_obj_t mp_obj_new_bytes_of_zeros(size_t len);
mp_obj_t mp_obj_new_bytearray(size_t n, void *items);
mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n);
mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items);
@@ -668,6 +669,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed);
mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items);
mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items);
+mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable);
mp_obj_t mp_obj_new_dict(size_t n_args);
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
diff --git a/py/objlist.c b/py/objlist.c
index 558c4c611..ea38e64e5 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -68,6 +68,11 @@ STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
return list;
}
+mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable) {
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+ return list_extend_from_iter(list, iterable);
+}
+
STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
(void)type_in;
mp_arg_check_num(n_args, kw_args, 0, 1, false);
diff --git a/py/objstr.c b/py/objstr.c
index ebd11d5cc..6ef9a15b5 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -41,6 +41,12 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
+const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'};
+
+const char nibble_to_hex_lower[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'};
+
/******************************************************************************/
/* str */
@@ -2088,6 +2094,14 @@ mp_obj_t mp_obj_new_bytes(const byte* data, size_t len) {
return mp_obj_new_str_copy(&mp_type_bytes, data, len);
}
+mp_obj_t mp_obj_new_bytes_of_zeros(size_t len) {
+ vstr_t vstr;
+ vstr_init_len(&vstr, len);
+ memset(vstr.buf, 0, len);
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+
+
bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {
if (MP_OBJ_IS_QSTR(s1) && MP_OBJ_IS_QSTR(s2)) {
return s1 == s2;
diff --git a/py/objstr.h b/py/objstr.h
index 0efe62a80..61a11d0bd 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -77,6 +77,9 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s
mp_obj_t index, bool is_slice);
const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction);
+const char nibble_to_hex_upper[16];
+const char nibble_to_hex_lower[16];
+
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj);
diff --git a/py/objtuple.c b/py/objtuple.c
index 474f81c1a..ed13cdcef 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -251,7 +251,8 @@ mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) {
}
void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {
- assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
+ // type check is done on getiter method to allow tuple, namedtuple, attrtuple
+ mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter);
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
*len = self->len;
*items = &self->items[0];
diff --git a/py/stream.c b/py/stream.c
index 08c749cc3..1d25f6470 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -341,6 +341,9 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
p = vstr_extend(&vstr, DEFAULT_BUFFER_SIZE);
current_read = DEFAULT_BUFFER_SIZE;
}
+ #ifdef RUN_BACKGROUND_TASKS
+ RUN_BACKGROUND_TASKS;
+ #endif
}
vstr.len = total_size;
diff --git a/shared-bindings/bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c
index 7b8df5103..0caca96b8 100644
--- a/shared-bindings/bleio/Adapter.c
+++ b/shared-bindings/_bleio/Adapter.c
@@ -26,10 +26,10 @@
*/
#include "py/objproperty.h"
-#include "shared-bindings/bleio/Address.h"
-#include "shared-bindings/bleio/Adapter.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-bindings/_bleio/Adapter.h"
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`Adapter` --- BLE adapter information
//| ----------------------------------------------------
@@ -38,27 +38,21 @@
//|
//| Usage::
//|
-//| import bleio
-//| bleio.adapter.enabled = True
-//| print(bleio.adapter.address)
+//| import _bleio
+//| _bleio.adapter.enabled = True
+//| print(_bleio.adapter.address)
//|
//| .. class:: Adapter()
//|
-//| You cannot create an instance of `bleio.Adapter`.
-//| Use `bleio.adapter` to access the sole instance available.
+//| You cannot create an instance of `_bleio.Adapter`.
+//| Use `_bleio.adapter` to access the sole instance available.
//|
//| .. attribute:: adapter.enabled
//|
//| State of the BLE adapter.
//|
-
-//| .. attribute:: adapter.address
-//|
-//| MAC address of the BLE adapter. (read-only)
-//|
-
STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) {
return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled());
}
@@ -80,13 +74,13 @@ const mp_obj_property_t bleio_adapter_enabled_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: adapter.address
+//|
+//| MAC address of the BLE adapter. (read-only)
+//|
STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
- mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, mp_const_none);
- bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj);
-
- common_hal_bleio_adapter_get_address(address);
+ return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address());
- return obj;
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address);
@@ -97,9 +91,29 @@ const mp_obj_property_t bleio_adapter_address_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: adapter.default_name
+//|
+//| default_name of the BLE adapter. (read-only)
+//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``,
+//| to make it easy to distinguish multiple CircuitPython boards.
+//|
+STATIC mp_obj_t bleio_adapter_get_default_name(mp_obj_t self) {
+ return common_hal_bleio_adapter_get_default_name();
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_default_name_obj, bleio_adapter_get_default_name);
+
+const mp_obj_property_t bleio_adapter_default_name_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_adapter_get_default_name_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&bleio_adapter_enabled_obj) },
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_adapter_address_obj) },
+ { MP_ROM_QSTR(MP_QSTR_default_name), MP_ROM_PTR(&bleio_adapter_default_name_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table);
diff --git a/shared-bindings/bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h
index de9d1d6db..932fc9c95 100644
--- a/shared-bindings/bleio/Adapter.h
+++ b/shared-bindings/_bleio/Adapter.h
@@ -28,12 +28,13 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
-#include "shared-module/bleio/Address.h"
+#include "shared-module/_bleio/Address.h"
const mp_obj_type_t bleio_adapter_type;
extern bool common_hal_bleio_adapter_get_enabled(void);
extern void common_hal_bleio_adapter_set_enabled(bool enabled);
-extern void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address);
+extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(void);
+extern mp_obj_t common_hal_bleio_adapter_get_default_name(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/_bleio/Address.c
index 37f01042c..cdee02b5d 100644
--- a/shared-bindings/bleio/Address.c
+++ b/shared-bindings/_bleio/Address.c
@@ -31,10 +31,10 @@
#include "py/objproperty.h"
#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Address.h"
-#include "shared-module/bleio/Address.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-module/_bleio/Address.h"
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`Address` -- BLE address
//| =========================================================
@@ -83,7 +83,21 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args,
//| .. attribute:: address_bytes
//|
-//| The bytes that make up the device address (read-only)
+//| The bytes that make up the device address (read-only).
+//|
+//| Note that the ``bytes`` object returned is in little-endian order:
+//| The least significant byte is ``address_bytes[0]``. So the address will
+//| appear to be reversed if you print the raw ``bytes`` object. If you print
+//| or use `str()` on the :py:class:`~_bleio.Attribute` object itself, the address will be printed
+//| in the expected order. For example:
+//|
+//| .. code-block:: pycon
+//|
+//| >>> import _bleio
+//| >>> _bleio.adapter.address
+//| <Address c8:1d:f5:ed:a8:35>
+//| >>> _bleio.adapter.address.address_bytes
+//| b'5\xa8\xed\xf5\x1d\xc8'
//|
STATIC mp_obj_t bleio_address_get_address_bytes(mp_obj_t self_in) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -147,18 +161,13 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o
STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (kind == PRINT_STR) {
- mp_buffer_info_t buf_info;
- mp_obj_t address_bytes = common_hal_bleio_address_get_address_bytes(self);
- mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ);
-
- const uint8_t *buf = (uint8_t *) buf_info.buf;
- mp_printf(print,
- "%02x:%02x:%02x:%02x:%02x:%02x",
- buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
- } else {
- mp_printf(print, "<Address>");
- }
+ mp_buffer_info_t buf_info;
+ mp_obj_t address_bytes = common_hal_bleio_address_get_address_bytes(self);
+ mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ);
+
+ const uint8_t *buf = (uint8_t *) buf_info.buf;
+ mp_printf(print, "<Address %02x:%02x:%02x:%02x:%02x:%02x>",
+ buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
}
//| .. data:: PUBLIC
@@ -179,13 +188,13 @@ STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
//| A randomly generated address that changes on every connection.
//|
STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) },
- { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) },
+ { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) },
+ { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) },
// These match the BLE_GAP_ADDR_TYPES values used by the nRF library.
- { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_OBJ_NEW_SMALL_INT(0) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_OBJ_NEW_SMALL_INT(1) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(2) },
- { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(3) },
+ { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_INT(0) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_INT(1) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_INT(2) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_INT(3) },
};
diff --git a/shared-bindings/bleio/Address.h b/shared-bindings/_bleio/Address.h
index 5e02ee210..98b6f80e0 100644
--- a/shared-bindings/bleio/Address.h
+++ b/shared-bindings/_bleio/Address.h
@@ -29,7 +29,7 @@
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H
#include "py/objtype.h"
-#include "shared-module/bleio/Address.h"
+#include "shared-module/_bleio/Address.h"
#define BLEIO_ADDRESS_TYPE_PUBLIC (0)
#define BLEIO_ADDRESS_TYPE_RANDOM_STATIC (1)
diff --git a/shared-bindings/_bleio/Attribute.c b/shared-bindings/_bleio/Attribute.c
new file mode 100644
index 000000000..2d8b15b9f
--- /dev/null
+++ b/shared-bindings/_bleio/Attribute.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/UUID.h"
+
+//
+
+//| .. currentmodule:: _bleio
+//|
+//| :class:`Attribute` -- BLE Attribute
+//| =========================================================
+//|
+//| Definitions associated with all BLE attributes: characteristics, descriptors, etc.
+//| :py:class:`~_bleio.Attribute` is, notionally, a superclass of
+//| :py:class:`~Characteristic` and :py:class:`~Descriptor`,
+//| but is not defined as a Python superclass of those classes.
+//|
+//| .. class:: Attribute()
+//|
+//| You cannot create an instance of :py:class:`~_bleio.Attribute`.
+//|
+
+STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = {
+
+//| .. data:: NO_ACCESS
+//|
+//| security mode: access not allowed
+//|
+//| .. data:: OPEN
+//|
+//| security_mode: no security (link is not encrypted)
+//|
+//| .. data:: ENCRYPT_NO_MITM
+//|
+//| security_mode: unauthenticated encryption, without man-in-the-middle protection
+//|
+//| .. data:: ENCRYPT_WITH_MITM
+//|
+//| security_mode: authenticated encryption, with man-in-the-middle protection
+//|
+//| .. data:: LESC_ENCRYPT_WITH_MITM
+//|
+//| security_mode: LESC encryption, with man-in-the-middle protection
+//|
+//| .. data:: SIGNED_NO_MITM
+//|
+//| security_mode: unauthenticated data signing, without man-in-the-middle protection
+//|
+//| .. data:: SIGNED_WITH_MITM
+//|
+//| security_mode: authenticated data signing, without man-in-the-middle protection
+//|
+ { MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SECURITY_MODE_NO_ACCESS) },
+ { MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SECURITY_MODE_OPEN) },
+ { MP_ROM_QSTR(MP_QSTR_ENCRYPT_NO_MITM), MP_ROM_INT(SECURITY_MODE_ENC_NO_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_ENCRYPT_WITH_MITM), MP_ROM_INT(SECURITY_MODE_ENC_WITH_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_LESC_ENCRYPT_WITH_MITM), MP_ROM_INT(SECURITY_MODE_LESC_ENC_WITH_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_SIGNED_NO_MITM), MP_ROM_INT(SECURITY_MODE_SIGNED_NO_MITM) },
+ { MP_ROM_QSTR(MP_QSTR_SIGNED_WITH_MITM), MP_ROM_INT(SECURITY_MODE_SIGNED_WITH_MITM) },
+
+};
+STATIC MP_DEFINE_CONST_DICT(bleio_attribute_locals_dict, bleio_attribute_locals_dict_table);
+
+const mp_obj_type_t bleio_attribute_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Attribute,
+ .locals_dict = (mp_obj_dict_t*)&bleio_attribute_locals_dict,
+};
diff --git a/shared-module/bleio/Characteristic.h b/shared-bindings/_bleio/Attribute.h
index 27b43588f..a0ce04500 100644
--- a/shared-module/bleio/Characteristic.h
+++ b/shared-bindings/_bleio/Attribute.h
@@ -24,17 +24,16 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
-#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H
-// Flags for each characteristic property. Common across ports.
-typedef struct {
- bool broadcast : 1;
- bool read : 1;
- bool write_no_response : 1;
- bool write : 1;
- bool notify : 1;
- bool indicate : 1;
-} bleio_characteristic_properties_t;
+#include "py/obj.h"
-#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+#include "common-hal/_bleio/Attribute.h"
+#include "shared-module/_bleio/Attribute.h"
+
+extern const mp_obj_type_t bleio_attribute_type;
+
+extern void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H
diff --git a/shared-bindings/bleio/Central.c b/shared-bindings/_bleio/Central.c
index fc00bce5c..084f40cd6 100644
--- a/shared-bindings/bleio/Central.c
+++ b/shared-bindings/_bleio/Central.c
@@ -34,13 +34,13 @@
#include "py/objproperty.h"
#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Address.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Central.h"
-#include "shared-bindings/bleio/Service.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Central.h"
+#include "shared-bindings/_bleio/Service.h"
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`Central` -- A BLE central device
//| =========================================================
@@ -49,19 +49,23 @@
//|
//| Usage::
//|
-//| import bleio
+//| import _bleio
//|
-//| scanner = bleio.Scanner()
+//| scanner = _bleio.Scanner()
//| entries = scanner.scan(2.5)
//|
//| my_entry = None
//| for entry in entries:
-//| if entry.name is not None and entry.name == 'MyPeripheral':
+//| if entry.name is not None and entry.name == 'InterestingPeripheral':
//| my_entry = entry
//| break
//|
-//| central = bleio.Central(my_entry.address)
-//| central.connect(10.0) # timeout after 10 seconds
+//| if not my_entry:
+//| raise Exception("'InterestingPeripheral' not found")
+//|
+//| central = _bleio.Central()
+//| central.connect(my_entry.address, 10) # timeout after 10 seconds
+//| remote_services = central.discover_remote_services()
//|
//| .. class:: Central()
@@ -79,24 +83,11 @@ STATIC mp_obj_t bleio_central_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-//| .. method:: connect(address, timeout, *, service_uuids=None)
-//| Attempts a connection to the remote peripheral. If the connection is successful,
-//| Do BLE discovery for the listed services, to find their handles and characteristics.
-//| The attribute `remote_services` will contain a list of all discovered services.
+//| .. method:: connect(address, timeout, *, service_uuids_whitelist=None)
+//| Attempts a connection to the remote peripheral.
//|
-//| :param bleio.Address address: The address of the peripheral to connect to
+//| :param Address address: The address of the peripheral to connect to
//| :param float/int timeout: Try to connect for timeout seconds.
-//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services
-//| provided by the peripheral that you want to use.
-//| The peripheral may provide more services, but services not listed are ignored.
-//| If a service in service_uuids is not found during discovery, it will not
-//| appear in `remote_services`.
-//|
-//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
-//|
-//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
-//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
-//| service or characteristic to be discovered. (This restriction may be lifted in the future.)
//|
STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -105,7 +96,6 @@ STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_service_uuids_whitelist, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -119,7 +109,7 @@ STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args
mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj);
// common_hal_bleio_central_connect() will validate that services is an iterable or None.
- common_hal_bleio_central_connect(self, address, timeout, args[ARG_service_uuids_whitelist].u_obj);
+ common_hal_bleio_central_connect(self, address, timeout);
return mp_const_none;
}
@@ -139,6 +129,46 @@ STATIC mp_obj_t bleio_central_disconnect(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_disconnect);
+//| .. method:: discover_remote_services(service_uuids_whitelist=None)
+//| Do BLE discovery for all services or for the given service UUIDS,
+//| to find their handles and characteristics, and return the discovered services.
+//| `Peripheral.connected` must be True.
+//|
+//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services
+//| provided by the peripheral that you want to use.
+//| The peripheral may provide more services, but services not listed are ignored
+//| and will not be returned.
+//|
+//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
+//|
+//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
+//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
+//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered
+//| for use. (This restriction may be lifted in the future.)
+//|
+//| :return: A tuple of services provided by the remote peripheral.
+//|
+STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_service_uuids_whitelist };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ if (!common_hal_bleio_central_get_connected(self)) {
+ mp_raise_ValueError(translate("Not connected"));
+ }
+
+ return MP_OBJ_FROM_PTR(common_hal_bleio_central_discover_remote_services(
+ MP_OBJ_FROM_PTR(self),
+ args[ARG_service_uuids_whitelist].u_obj));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services);
+
//| .. attribute:: connected
//|
//| True if connected to a remove peripheral.
@@ -157,36 +187,14 @@ const mp_obj_property_t bleio_central_connected_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-
-//| .. attribute:: remote_services (read-only)
-//|
-//| A tuple of services provided by the remote peripheral.
-//| If the Central is not connected, an empty tuple will be returned.
-//|
-STATIC mp_obj_t bleio_central_get_remote_services(mp_obj_t self_in) {
- bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- // Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *service_list = common_hal_bleio_central_get_remote_services(self);
- return mp_obj_new_tuple(service_list->len, service_list->items);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_get_remote_services_obj, bleio_central_get_remote_services);
-
-const mp_obj_property_t bleio_central_remote_services_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_central_get_remote_services_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = {
// Methods
- { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_central_discover_remote_services_obj) },
// Properties
{ MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_remote_services), MP_ROM_PTR(&bleio_central_remote_services_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_central_locals_dict, bleio_central_locals_dict_table);
diff --git a/shared-bindings/bleio/Central.h b/shared-bindings/_bleio/Central.h
index 0e84037f9..85d788654 100644
--- a/shared-bindings/bleio/Central.h
+++ b/shared-bindings/_bleio/Central.h
@@ -28,15 +28,16 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
-#include "common-hal/bleio/Central.h"
-#include "common-hal/bleio/Service.h"
+#include "py/objtuple.h"
+#include "common-hal/_bleio/Central.h"
+#include "common-hal/_bleio/Service.h"
extern const mp_obj_type_t bleio_central_type;
extern void common_hal_bleio_central_construct(bleio_central_obj_t *self);
-extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids);
+extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout);
extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self);
extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self);
-extern mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self);
+extern mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H
diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c
new file mode 100644
index 000000000..198155589
--- /dev/null
+++ b/shared-bindings/_bleio/Characteristic.c
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/Attribute.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
+
+//| .. currentmodule:: _bleio
+//|
+//| :class:`Characteristic` -- BLE service characteristic
+//| =========================================================
+//|
+//| Stores information about a BLE service characteristic and allows reading
+//| and writing of the characteristic's value.
+//|
+//| .. class:: Characteristic
+//|
+//| There is no regular constructor for a Characteristic. A new local Characteristic can be created
+//| and attached to a Service by calling `add_to_service()`.
+//| Remote Characteristic objects are created by `Central.discover_remote_services()`
+//| or `Peripheral.discover_remote_services()` as part of remote Services.
+//|
+
+//| .. method:: add_to_service(service, uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=None)
+//|
+//| Create a new Characteristic object, and add it to this Service.
+//|
+//| :param Service service: The service that will provide this characteristic
+//| :param UUID uuid: The uuid of the characteristic
+//| :param int properties: The properties of the characteristic,
+//| specified as a bitmask of these values bitwise-or'd together:
+//| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.
+//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which
+//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
+//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
+//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
+//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which
+//| security mode is required. Values allowed are the same as ``read_perm``.
+//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is
+//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
+//| number of data bytes that fit in a single BLE 4.x ATT packet.
+//| :param bool fixed_length: True if the characteristic value is of fixed length.
+//| :param buf initial_value: The initial value for this characteristic. If not given, will be
+//| filled with zeros.
+//|
+//| :return: the new Characteristic.
+//|
+STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ // class is arg[0], which we can ignore.
+
+ enum { ARG_service, ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm,
+ ARG_max_length, ARG_fixed_length, ARG_initial_value };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_service, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
+ { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
+ { MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} },
+ { MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_initial_value, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t service_obj = args[ARG_service].u_obj;
+ if (!MP_OBJ_IS_TYPE(service_obj, &bleio_service_type)) {
+ mp_raise_ValueError(translate("Expected a Service"));
+ }
+
+ const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
+ if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
+ mp_raise_ValueError(translate("Expected a UUID"));
+ }
+
+ const bleio_characteristic_properties_t properties = args[ARG_properties].u_int;
+ if (properties & ~CHAR_PROP_ALL) {
+ mp_raise_ValueError(translate("Invalid properties"));
+ }
+
+ const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(read_perm);
+
+ const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(write_perm);
+
+ const mp_int_t max_length = args[ARG_max_length].u_int;
+ const bool fixed_length = args[ARG_fixed_length].u_bool;
+ mp_obj_t initial_value = args[ARG_initial_value].u_obj;
+
+ // Length will be validated in common_hal.
+ mp_buffer_info_t initial_value_bufinfo;
+ if (initial_value == mp_const_none) {
+ if (fixed_length && max_length > 0) {
+ initial_value = mp_obj_new_bytes_of_zeros(max_length);
+ } else {
+ initial_value = mp_const_empty_bytes;
+ }
+ }
+ mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
+
+ bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
+ characteristic->base.type = &bleio_characteristic_type;
+
+ // Range checking on max_length arg is done by the common_hal layer, because
+ // it may vary depending on underlying BLE implementation.
+ common_hal_bleio_characteristic_construct(
+ characteristic, MP_OBJ_TO_PTR(service_obj), MP_OBJ_TO_PTR(uuid_obj),
+ properties, read_perm, write_perm,
+ max_length, fixed_length, &initial_value_bufinfo);
+
+ common_hal_bleio_service_add_characteristic(service_obj, characteristic);
+
+ return MP_OBJ_FROM_PTR(characteristic);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_to_service_fun_obj, 3, bleio_characteristic_add_to_service);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj, MP_ROM_PTR(&bleio_characteristic_add_to_service_fun_obj));
+
+
+
+//| .. attribute:: properties
+//|
+//| An int bitmask representing which properties are set, specified as bitwise or'ing of
+//| of these possible values.
+//| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.
+//|
+STATIC mp_obj_t bleio_characteristic_get_properties(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_properties(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_properties_obj, bleio_characteristic_get_properties);
+
+const mp_obj_property_t bleio_characteristic_properties_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_properties_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. attribute:: uuid
+//|
+//| The UUID of this characteristic. (read-only)
+//| Will be ``None`` if the 128-bit UUID for this characteristic is not known.
+//|
+STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ bleio_uuid_obj_t *uuid = common_hal_bleio_characteristic_get_uuid(self);
+ return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_uuid_obj, bleio_characteristic_get_uuid);
+
+const mp_obj_property_t bleio_characteristic_uuid_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_uuid_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. attribute:: value
+//|
+//| The value of this characteristic.
+//|
+STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_bleio_characteristic_get_value(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value);
+
+STATIC mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ);
+
+ common_hal_bleio_characteristic_set_value(self, &bufinfo);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_value_obj, bleio_characteristic_set_value);
+
+const mp_obj_property_t bleio_characteristic_value_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_value_obj,
+ (mp_obj_t)&bleio_characteristic_set_value_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. attribute:: descriptors
+//|
+//| A tuple of :py:class:`Descriptor` that describe this characteristic. (read-only)
+//|
+STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ // Return list as a tuple so user won't be able to change it.
+ mp_obj_list_t *char_list = common_hal_bleio_characteristic_get_descriptor_list(self);
+ return mp_obj_new_tuple(char_list->len, char_list->items);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors);
+
+const mp_obj_property_t bleio_characteristic_descriptors_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_descriptors_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. attribute:: service (read-only)
+//|
+//| The Service this Characteristic is a part of.
+//|
+STATIC mp_obj_t bleio_characteristic_get_service(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_bleio_characteristic_get_service(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_service_obj, bleio_characteristic_get_service);
+
+const mp_obj_property_t bleio_characteristic_service_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_service_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. method:: set_cccd(*, notify=False, indicate=False)
+//|
+//| Set the remote characteristic's CCCD to enable or disable notification and indication.
+//|
+//| :param bool notify: True if Characteristic should receive notifications of remote writes
+//| :param float indicate: True if Characteristic should receive indications of remote writes
+//|
+STATIC mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_notify, ARG_indicate };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_notify, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_indicate, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ common_hal_bleio_characteristic_set_cccd(self, args[ARG_notify].u_bool, args[ARG_indicate].u_bool);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_characteristic_set_cccd);
+
+
+STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) },
+ { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) },
+ { MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
+
+ // Bitmask constants to represent properties
+//| .. data:: BROADCAST
+//|
+//| property: allowed in advertising packets
+//|
+//| .. data:: INDICATE
+//|
+//| property: server will indicate to the client when the value is set and wait for a response
+//|
+//| .. data:: NOTIFY
+//|
+//| property: server will notify the client when the value is set
+//|
+//| .. data:: READ
+//|
+//| property: clients may read this characteristic
+//|
+//| .. data:: WRITE
+//|
+//| property: clients may write this characteristic; a response will be sent back
+//|
+//| .. data:: WRITE_NO_RESPONSE
+//|
+//| property: clients may write this characteristic; no response will be sent back
+//|
+ { MP_ROM_QSTR(MP_QSTR_BROADCAST), MP_ROM_INT(CHAR_PROP_BROADCAST) },
+ { MP_ROM_QSTR(MP_QSTR_INDICATE), MP_ROM_INT(CHAR_PROP_INDICATE) },
+ { MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(CHAR_PROP_NOTIFY) },
+ { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(CHAR_PROP_READ) },
+ { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(CHAR_PROP_WRITE) },
+ { MP_ROM_QSTR(MP_QSTR_WRITE_NO_RESPONSE), MP_ROM_INT(CHAR_PROP_WRITE_NO_RESPONSE) },
+
+};
+STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table);
+
+STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->uuid) {
+ mp_printf(print, "Characteristic(");
+ bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind);
+ mp_printf(print, ")");
+ } else {
+ mp_printf(print, "<Characteristic with Unregistered UUID>");
+ }
+}
+
+const mp_obj_type_t bleio_characteristic_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Characteristic,
+ .print = bleio_characteristic_print,
+ .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict,
+};
diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h
index d450c42b4..a816c6050 100644
--- a/shared-bindings/bleio/Characteristic.h
+++ b/shared-bindings/_bleio/Characteristic.h
@@ -28,17 +28,22 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
-#include "shared-module/bleio/Characteristic.h"
-#include "common-hal/bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Attribute.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-module/_bleio/Characteristic.h"
+#include "common-hal/_bleio/Characteristic.h"
+#include "common-hal/_bleio/Service.h"
extern const mp_obj_type_t bleio_characteristic_type;
-extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list);
+extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self);
extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self);
extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self);
extern mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self);
+extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self);
+extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor);
extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
diff --git a/shared-bindings/bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c
index 26f9e012b..9cc708eb7 100644
--- a/shared-bindings/bleio/CharacteristicBuffer.c
+++ b/shared-bindings/_bleio/CharacteristicBuffer.c
@@ -30,8 +30,8 @@
#include "py/runtime.h"
#include "py/stream.h"
-#include "shared-bindings/bleio/CharacteristicBuffer.h"
-#include "shared-bindings/bleio/UUID.h"
+#include "shared-bindings/_bleio/CharacteristicBuffer.h"
+#include "shared-bindings/_bleio/UUID.h"
#include "shared-bindings/util.h"
STATIC void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self) {
@@ -40,7 +40,7 @@ STATIC void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self
}
}
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`CharacteristicBuffer` -- BLE Service incoming values buffer.
//| =====================================================================
@@ -52,7 +52,7 @@ STATIC void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self
//| Monitor the given Characteristic. Each time a new value is written to the Characteristic
//| add the newly-written bytes to a FIFO buffer.
//|
-//| :param bleio.Characteristic characteristic: The Characteristic to monitor.
+//| :param Characteristic characteristic: The Characteristic to monitor.
//| It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic
//| in a remote Service that a Central has connected to.
//| :param int timeout: the timeout in seconds to wait for the first character and between subsequent characters.
diff --git a/shared-bindings/bleio/CharacteristicBuffer.h b/shared-bindings/_bleio/CharacteristicBuffer.h
index b45835ff3..83e6fef02 100644
--- a/shared-bindings/bleio/CharacteristicBuffer.h
+++ b/shared-bindings/_bleio/CharacteristicBuffer.h
@@ -27,7 +27,7 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTICBUFFER_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTICBUFFER_H
-#include "common-hal/bleio/CharacteristicBuffer.h"
+#include "common-hal/_bleio/CharacteristicBuffer.h"
extern const mp_obj_type_t bleio_characteristic_buffer_type;
diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c
new file mode 100644
index 000000000..0ab9fe8e9
--- /dev/null
+++ b/shared-bindings/_bleio/Descriptor.c
@@ -0,0 +1,231 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/Attribute.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-bindings/_bleio/UUID.h"
+
+//| .. currentmodule:: _bleio
+//|
+//| :class:`Descriptor` -- BLE descriptor
+//| =========================================================
+//|
+//| Stores information about a BLE descriptor.
+//| Descriptors are attached to BLE characteristics and provide contextual
+//| information about the characteristic.
+//|
+//| .. class:: Descriptor
+//|
+//| There is no regular constructor for a Descriptor. A new local Descriptor can be created
+//| and attached to a Characteristic by calling `add_to_characteristic()`.
+//| Remote Descriptor objects are created by `Central.discover_remote_services()`
+//| or `Peripheral.discover_remote_services()` as part of remote Characteristics
+//| in the remote Services that are discovered.
+//|
+//| .. classmethod:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'')
+//|
+//| Create a new Descriptor object, and add it to this Service.
+//|
+//| :param Characteristic characteristic: The characteristic that will hold this descriptor
+//| :param UUID uuid: The uuid of the descriptor
+//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which
+//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
+//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`,
+//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
+//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which
+//| security mode is required. Values allowed are the same as ``read_perm``.
+//| :param int max_length: Maximum length in bytes of the descriptor value. The maximum allowed is
+//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum
+//| number of data bytes that fit in a single BLE 4.x ATT packet.
+//| :param bool fixed_length: True if the descriptor value is of fixed length.
+//| :param buf initial_value: The initial value for this descriptor.
+//|
+//| :return: the new Descriptor.
+//|
+STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ // class is arg[0], which we can ignore.
+
+ enum { ARG_characteristic, ARG_uuid, ARG_read_perm, ARG_write_perm,
+ ARG_max_length, ARG_fixed_length, ARG_initial_value };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_characteristic, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
+ { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} },
+ { MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} },
+ { MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_initial_value, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t characteristic_obj = args[ARG_characteristic].u_obj;
+ if (!MP_OBJ_IS_TYPE(characteristic_obj, &bleio_characteristic_type)) {
+ mp_raise_ValueError(translate("Expected a Characteristic"));
+ }
+
+ const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
+ if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
+ mp_raise_ValueError(translate("Expected a UUID"));
+ }
+
+ const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(read_perm);
+
+ const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int;
+ common_hal_bleio_attribute_security_mode_check_valid(write_perm);
+
+ const mp_int_t max_length = args[ARG_max_length].u_int;
+ const bool fixed_length = args[ARG_fixed_length].u_bool;
+ mp_obj_t initial_value = args[ARG_initial_value].u_obj;
+
+ // Length will be validated in common_hal.
+ mp_buffer_info_t initial_value_bufinfo;
+ if (initial_value == mp_const_none) {
+ if (fixed_length && max_length > 0) {
+ initial_value = mp_obj_new_bytes_of_zeros(max_length);
+ } else {
+ initial_value = mp_const_empty_bytes;
+ }
+ }
+ mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ);
+
+ bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
+ descriptor->base.type = &bleio_descriptor_type;
+
+ // Range checking on max_length arg is done by the common_hal layer, because
+ // it may vary depending on underlying BLE implementation.
+ common_hal_bleio_descriptor_construct(
+ descriptor, MP_OBJ_TO_PTR(characteristic_obj), MP_OBJ_TO_PTR(uuid_obj),
+ read_perm, write_perm,
+ max_length, fixed_length, &initial_value_bufinfo);
+
+ common_hal_bleio_characteristic_add_descriptor(characteristic_obj, descriptor);
+
+ return MP_OBJ_FROM_PTR(descriptor);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_descriptor_add_to_characteristic_fun_obj, 3, bleio_descriptor_add_to_characteristic);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_descriptor_add_to_characteristic_obj, MP_ROM_PTR(&bleio_descriptor_add_to_characteristic_fun_obj));
+
+//| .. attribute:: uuid
+//|
+//| The descriptor uuid. (read-only)
+//|
+STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ bleio_uuid_obj_t *uuid = common_hal_bleio_descriptor_get_uuid(self);
+ return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_uuid_obj, bleio_descriptor_get_uuid);
+
+const mp_obj_property_t bleio_descriptor_uuid_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&bleio_descriptor_get_uuid_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: characteristic (read-only)
+//|
+//| The Characteristic this Descriptor is a part of.
+//|
+STATIC mp_obj_t bleio_descriptor_get_characteristic(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_bleio_descriptor_get_characteristic(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_characteristic_obj, bleio_descriptor_get_characteristic);
+
+const mp_obj_property_t bleio_descriptor_characteristic_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_descriptor_get_characteristic_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+//| .. attribute:: value
+//|
+//| The value of this descriptor.
+//|
+STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return common_hal_bleio_descriptor_get_value(self);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_value_obj, bleio_descriptor_get_value);
+
+STATIC mp_obj_t bleio_descriptor_set_value(mp_obj_t self_in, mp_obj_t value_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ);
+
+ common_hal_bleio_descriptor_set_value(self, &bufinfo);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_descriptor_set_value_obj, bleio_descriptor_set_value);
+
+const mp_obj_property_t bleio_descriptor_value_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_descriptor_get_value_obj,
+ (mp_obj_t)&bleio_descriptor_set_value_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_add_to_characteristic), MP_ROM_PTR(&bleio_descriptor_add_to_characteristic_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_characteristic), MP_ROM_PTR(&bleio_descriptor_characteristic_obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_descriptor_value_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table);
+
+STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->uuid) {
+ mp_printf(print, "Descriptor(");
+ bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind);
+ mp_printf(print, ")");
+ } else {
+ mp_printf(print, "<Descriptor with Unregistered UUID>");
+ }
+}
+
+const mp_obj_type_t bleio_descriptor_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Descriptor,
+ .print = bleio_descriptor_print,
+ .locals_dict = (mp_obj_dict_t*)&bleio_descriptor_locals_dict
+};
diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/_bleio/Descriptor.h
index fd11ea08c..7544bdb17 100644
--- a/shared-bindings/bleio/Descriptor.h
+++ b/shared-bindings/_bleio/Descriptor.h
@@ -28,31 +28,17 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
-#include "common-hal/bleio/Descriptor.h"
-#include "common-hal/bleio/UUID.h"
-
-enum {
- DESCRIPTOR_UUID_CHARACTERISTIC_EXTENDED_PROPERTIES = 0x2900,
- DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION = 0x2901,
- DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION = 0x2902,
- DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION = 0x2903,
- DESCRIPTOR_UUID_CHARACTERISTIC_PRESENTATION_FORMAT = 0x2904,
- DESCRIPTOR_UUID_CHARACTERISTIC_AGGREGATE_FORMAT = 0x2905,
- DESCRIPTOR_UUID_VALID_RANGE = 0x2906,
- DESCRIPTOR_UUID_EXTERNAL_REPORT_REFERENCE = 0x2907,
- DESCRIPTOR_UUID_REPORT_REFERENCE = 0x2908,
- DESCRIPTOR_UUID_NUMBER_OF_DIGITALS = 0x2909,
- DESCRIPTOR_UUID_VALUE_TRIGGER_SETTING = 0x290A,
- DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_CONFIGURATION = 0x290B,
- DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_MEASUREMENT = 0x290C,
- DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_TRIGGER_SETTING = 0x290D,
- DESCRIPTOR_UUID_TIME_TRIGGER_SETTING = 0x290E,
-};
+#include "shared-module/_bleio/Attribute.h"
+#include "common-hal/_bleio/Characteristic.h"
+#include "common-hal/_bleio/Descriptor.h"
+#include "common-hal/_bleio/UUID.h"
extern const mp_obj_type_t bleio_descriptor_type;
-extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid);
-extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self);
-extern mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
+extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo);
+extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
+extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self);
+extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self);
+extern void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/_bleio/Peripheral.c
index 1302c9652..0bf292744 100644
--- a/shared-bindings/bleio/Peripheral.c
+++ b/shared-bindings/_bleio/Peripheral.c
@@ -35,24 +35,23 @@
#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Peripheral.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
-#include "shared-module/bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Adapter.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Peripheral.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
+#include "shared-module/_bleio/ScanEntry.h"
-#include "common-hal/bleio/Peripheral.h"
+#include "common-hal/_bleio/Peripheral.h"
-static const char default_name[] = "CIRCUITPY";
-
-#define ADV_INTERVAL_DEFAULT (1.0f)
#define ADV_INTERVAL_MIN (0.0020f)
#define ADV_INTERVAL_MIN_STRING "0.0020"
#define ADV_INTERVAL_MAX (10.24f)
#define ADV_INTERVAL_MAX_STRING "10.24"
+// 20ms is recommended by Apple
+#define ADV_INTERVAL_DEFAULT (0.1f)
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`Peripheral` -- A BLE peripheral device
//| =========================================================
@@ -62,78 +61,58 @@ static const char default_name[] = "CIRCUITPY";
//|
//| Usage::
//|
-//| import bleio
+//| from _bleio import Characteristic, Peripheral, Service
//| from adafruit_ble.advertising import ServerAdvertisement
//|
-//| # Create a Characteristic.
-//| chara = bleio.Characteristic(bleio.UUID(0x2919), read=True, notify=True)
+//| # Create a peripheral and start it up.
+//| peripheral = _bleio.Peripheral()
//|
-//| # Create a Service providing that one Characteristic.
-//| serv = bleio.Service(bleio.UUID(0x180f), [chara])
+//| # Create a Service and add it to this Peripheral.
+//| service = Service.add_to_peripheral(peripheral, _bleio.UUID(0x180f))
//|
-//| # Create a peripheral and start it up.
-//| periph = bleio.Peripheral([service])
-//| adv = ServerAdvertisement(periph)
-//| periph.start_advertising(adv.advertising_data_bytes, adv.scan_response_bytes)
+//| # Create a Characteristic and add it to the Service.
+//| characteristic = Characteristic.add_to_service(service,
+//| _bleio.UUID(0x2919), properties=Characteristic.READ | Characteristic.NOTIFY)
//|
-//| while not periph.connected:
+//| adv = ServerAdvertisement(peripheral)
+//| peripheral.start_advertising(adv.advertising_data_bytes, scan_response=adv.scan_response_bytes)
+//|
+//| while not peripheral.connected:
//| # Wait for connection.
//| pass
//|
-//| .. class:: Peripheral(services=(), \*, name='CIRCUITPY')
+//| .. class:: Peripheral(name=None)
//|
//| Create a new Peripheral object.
//|
-//| :param iterable services: the Service objects representing services available from this peripheral, if any.
-//| A non-connectable peripheral will have no services.
-//| :param str name: The name used when advertising this peripheral. Use ``None`` when a name is not needed,
-//| such as when the peripheral is a beacon
+//| :param str name: The name used when advertising this peripheral. If name is None,
+//| _bleio.adapter.default_name will be used.
//|
STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_services, ARG_name };
+ enum { ARG_name };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_services, MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple} },
- { MP_QSTR_name, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_name, MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- // If services is not an iterable, an exception will be thrown.
- mp_obj_iter_buf_t iter_buf;
- mp_obj_t iterable = mp_getiter(args[ARG_services].u_obj, &iter_buf);
-
bleio_peripheral_obj_t *self = m_new_obj(bleio_peripheral_obj_t);
self->base.type = &bleio_peripheral_type;
- // Copy the services list and validate its items.
- mp_obj_t service_list_obj = mp_obj_new_list(0, NULL);
- mp_obj_list_t *service_list = MP_OBJ_FROM_PTR(service_list_obj);
-
- mp_obj_t service;
- while ((service = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
- if (!MP_OBJ_IS_TYPE(service, &bleio_service_type)) {
- mp_raise_ValueError(translate("non-Service found in services"));
- }
- mp_obj_list_append(service_list, service);
- }
-
- const mp_obj_t name = args[ARG_name].u_obj;
- mp_obj_t name_str;
- if (name == MP_OBJ_NULL || name == mp_const_none) {
- name_str = mp_obj_new_str(default_name, strlen(default_name));
- } else if (MP_OBJ_IS_STR(name)) {
- name_str = name;
- } else {
+ mp_obj_t name = args[ARG_name].u_obj;
+ if (name == mp_const_none) {
+ name = common_hal_bleio_adapter_get_default_name();
+ } else if (!MP_OBJ_IS_STR(name)) {
mp_raise_ValueError(translate("name must be a string"));
}
- common_hal_bleio_peripheral_construct(self, service_list, name_str);
+ common_hal_bleio_peripheral_construct(self, name);
return MP_OBJ_FROM_PTR(self);
}
-//| .. attribute:: connected
+//| .. attribute:: connected (read-only)
//|
//| True if connected to a BLE Central device.
//|
@@ -153,13 +132,13 @@ const mp_obj_property_t bleio_peripheral_connected_obj = {
//| .. attribute:: services
//|
-//| A `tuple` of `bleio.Service` that are offered by this peripheral. (read-only)
+//| A tuple of :py:class:`Service` objects offered by this peripheral. (read-only)
//|
STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) {
bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *service_list = common_hal_bleio_peripheral_get_service_list(self);
- return mp_obj_new_tuple(service_list->len, service_list->items);
+ mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services(self);
+ return mp_obj_new_tuple(services_list->len, services_list->items);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services);
@@ -188,7 +167,7 @@ const mp_obj_property_t bleio_peripheral_name_obj = {
(mp_obj_t)&mp_const_none_obj },
};
-//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=1)
+//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1)
//|
//| Starts advertising the peripheral. The peripheral's name and
//| services are included in the advertisement packets.
@@ -222,7 +201,7 @@ STATIC mp_obj_t bleio_peripheral_start_advertising(mp_uint_t n_args, const mp_ob
}
if (args[ARG_interval].u_obj == MP_OBJ_NULL) {
- args[ARG_interval].u_obj = mp_obj_new_float(1.0F);
+ args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT);
}
const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj);
@@ -265,16 +244,75 @@ STATIC mp_obj_t bleio_peripheral_disconnect(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripheral_disconnect);
+//| .. method:: discover_remote_services(service_uuids_whitelist=None)
+//| Do BLE discovery for all services or for the given service UUIDS,
+//| to find their handles and characteristics, and return the discovered services.
+//| `Peripheral.connected` must be True.
+//|
+//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services
+//| provided by the peripheral that you want to use.
+//| The peripheral may provide more services, but services not listed are ignored
+//| and will not be returned.
+//|
+//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
+//|
+//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you
+//| you must have already created a :py:class:~`UUID` object for that UUID in order for the
+//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered
+//| for use. (This restriction may be lifted in the future.)
+//|
+//| Thought it is unusual for a peripheral to act as a BLE client, it can do so, and
+//| needs to be able to do discovery on its peer (a central).
+//| Examples include a peripheral accessing a central that provides Current Time Service,
+//| Apple Notification Center Service, or Battery Service.
+//|
+//| :return: A tuple of services provided by the remote central.
+//|
+STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ enum { ARG_service_uuids_whitelist };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ if (!common_hal_bleio_peripheral_get_connected(self)) {
+ mp_raise_ValueError(translate("Not connected"));
+ }
+
+ return MP_OBJ_FROM_PTR(common_hal_bleio_peripheral_discover_remote_services(
+ MP_OBJ_FROM_PTR(self),
+ args[ARG_service_uuids_whitelist].u_obj));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services);
+
+//| .. method:: pair()
+//|
+//| Request pairing with connected central.
+STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) {
+ bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_peripheral_pair(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair);
+
STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = {
// Methods
- { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) },
- { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_peripheral_pair_obj) },
// Properties
- { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) },
- { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table);
diff --git a/shared-bindings/bleio/Peripheral.h b/shared-bindings/_bleio/Peripheral.h
index 846250a5f..bc56a9338 100644
--- a/shared-bindings/bleio/Peripheral.h
+++ b/shared-bindings/_bleio/Peripheral.h
@@ -28,16 +28,21 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
-#include "common-hal/bleio/Peripheral.h"
+#include "py/objtuple.h"
+#include "common-hal/_bleio/Peripheral.h"
+#include "common-hal/_bleio/Service.h"
extern const mp_obj_type_t bleio_peripheral_type;
-extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name);
-extern mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self);
+extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name);
+extern void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service);
+extern mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self);
extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self);
extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self);
extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo);
extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device);
extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device);
+extern mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist);
+extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H
diff --git a/shared-bindings/bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c
index 6eb02c716..bec380d03 100644
--- a/shared-bindings/bleio/ScanEntry.c
+++ b/shared-bindings/_bleio/ScanEntry.c
@@ -29,24 +29,24 @@
#include <string.h>
#include "py/objproperty.h"
-#include "shared-bindings/bleio/Address.h"
-#include "shared-bindings/bleio/ScanEntry.h"
-#include "shared-bindings/bleio/UUID.h"
-#include "shared-module/bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-bindings/_bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/UUID.h"
+#include "shared-module/_bleio/ScanEntry.h"
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`ScanEntry` -- BLE scan response entry
//| =========================================================
//|
//| Encapsulates information about a device that was received as a
//| response to a BLE scan request. This object may only be created
-//| by a `bleio.Scanner`: it has no user-visible constructor.
+//| by a `_bleio.Scanner`: it has no user-visible constructor.
//|
//| .. attribute:: address
//|
-//| The address of the device (read-only), of type `bleio.Address`.
+//| The address of the device (read-only), of type `_bleio.Address`.
//|
STATIC mp_obj_t bleio_scanentry_get_address(mp_obj_t self_in) {
bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
diff --git a/shared-bindings/bleio/ScanEntry.h b/shared-bindings/_bleio/ScanEntry.h
index 77e93175f..8af1f050a 100644
--- a/shared-bindings/bleio/ScanEntry.h
+++ b/shared-bindings/_bleio/ScanEntry.h
@@ -30,7 +30,7 @@
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H
#include "py/obj.h"
-#include "shared-module/bleio/ScanEntry.h"
+#include "shared-module/_bleio/ScanEntry.h"
extern const mp_obj_type_t bleio_scanentry_type;
diff --git a/shared-bindings/bleio/Scanner.c b/shared-bindings/_bleio/Scanner.c
index 269c42591..94cec9752 100644
--- a/shared-bindings/bleio/Scanner.c
+++ b/shared-bindings/_bleio/Scanner.c
@@ -27,8 +27,8 @@
#include "py/objproperty.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/ScanEntry.h"
-#include "shared-bindings/bleio/Scanner.h"
+#include "shared-bindings/_bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Scanner.h"
#define INTERVAL_DEFAULT (0.1f)
#define INTERVAL_MIN (0.0025f)
@@ -37,7 +37,7 @@
#define INTERVAL_MAX_STRING "40.959375"
#define WINDOW_DEFAULT (0.1f)
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`Scanner` -- scan for nearby BLE devices
//| =========================================================
@@ -46,8 +46,8 @@
//|
//| Usage::
//|
-//| import bleio
-//| scanner = bleio.Scanner()
+//| import _bleio
+//| scanner = _bleio.Scanner()
//| entries = scanner.scan(2.5) # Scan for 2.5 seconds
//|
diff --git a/shared-bindings/bleio/Scanner.h b/shared-bindings/_bleio/Scanner.h
index 3a0ce7eae..cbaa77866 100644
--- a/shared-bindings/bleio/Scanner.h
+++ b/shared-bindings/_bleio/Scanner.h
@@ -29,7 +29,7 @@
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
#include "py/objtype.h"
-#include "common-hal/bleio/Scanner.h"
+#include "common-hal/_bleio/Scanner.h"
extern const mp_obj_type_t bleio_scanner_type;
diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/_bleio/Service.c
index db0606991..da5633f2a 100644
--- a/shared-bindings/bleio/Service.c
+++ b/shared-bindings/_bleio/Service.c
@@ -28,81 +28,79 @@
#include "py/objproperty.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/Peripheral.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`Service` -- BLE service
//| =========================================================
//|
//| Stores information about a BLE service and its characteristics.
//|
-
-//| .. class:: Service(uuid, characteristics, *, secondary=False)
+//| .. class:: Service
+//|
+//| There is no regular constructor for a Service. A new local Service can be created
+//| and attached to a Peripheral by calling `add_to_peripheral()`.
+//| Remote Service objects are created by `Central.discover_remote_services()`
+//| or `Peripheral.discover_remote_services()`.
+//|
+//| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False)
//|
-//| Create a new Service object identified by the specified UUID.
-//| To mark the service as secondary, pass `True` as :py:data:`secondary`.
+//| Create a new Service object, identitied by the specified UUID, and add it
+//| to the given Peripheral.
//|
-//| :param bleio.UUID uuid: The uuid of the service
-//| :param iterable characteristics: the Characteristic objects for this service
-//| :param bool secondary: If the service is a secondary one
+//| To mark the service as secondary, pass `True` as :py:data:`secondary`.
//|
+//| :param Peripheral peripheral: The peripheral that will provide this service
+//| :param UUID uuid: The uuid of the service
+//| :param bool secondary: If the service is a secondary one
+//
+//| :return: the new Service
+//|
+STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ // class is arg[0], which we can ignore.
-STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_uuid, ARG_characteristics, ARG_secondary };
+ enum { ARG_peripheral, ARG_uuid, ARG_secondary };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_characteristics, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_peripheral, MP_ARG_REQUIRED | MP_ARG_OBJ,},
+ { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
+ const mp_obj_t peripheral_obj = args[ARG_peripheral].u_obj;
+ if (!MP_OBJ_IS_TYPE(peripheral_obj, &bleio_peripheral_type)) {
+ mp_raise_ValueError(translate("Expected a Peripheral"));
+ }
+ const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
mp_raise_ValueError(translate("Expected a UUID"));
}
- bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t);
- self->base.type = &bleio_service_type;
-
const bool is_secondary = args[ARG_secondary].u_bool;
- bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
-
- // If characteristics is not an iterable, an exception will be thrown.
- mp_obj_iter_buf_t iter_buf;
- mp_obj_t iterable = mp_getiter(args[ARG_characteristics].u_obj, &iter_buf);
- mp_obj_t characteristic_obj;
-
- // Copy the characteristics list and validate its items.
- mp_obj_t char_list_obj = mp_obj_new_list(0, NULL);
- mp_obj_list_t *char_list = MP_OBJ_TO_PTR(char_list_obj);
-
- while ((characteristic_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
- if (!MP_OBJ_IS_TYPE(characteristic_obj, &bleio_characteristic_type)) {
- mp_raise_ValueError(translate("characteristics includes an object that is not a Characteristic"));
- }
- bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_obj);
- if (common_hal_bleio_uuid_get_uuid128_reference(uuid) !=
- common_hal_bleio_uuid_get_uuid128_reference(characteristic->uuid)) {
- // The descriptor base UUID doesn't match the characteristic base UUID.
- mp_raise_ValueError(translate("Characteristic UUID doesn't match Service UUID"));
- }
- mp_obj_list_append(char_list_obj, characteristic_obj);
- }
- common_hal_bleio_service_construct(self, uuid, char_list, is_secondary);
+ bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
+ service->base.type = &bleio_service_type;
- return MP_OBJ_FROM_PTR(self);
+ common_hal_bleio_service_construct(
+ service, MP_OBJ_TO_PTR(peripheral_obj), MP_OBJ_TO_PTR(uuid_obj), is_secondary);
+
+ common_hal_bleio_peripheral_add_service(peripheral_obj, service);
+
+ return MP_OBJ_FROM_PTR(service);
}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_service_add_to_peripheral_fun_obj, 3, bleio_service_add_to_peripheral);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_service_add_to_peripheral_obj, MP_ROM_PTR(&bleio_service_add_to_peripheral_fun_obj));
//| .. attribute:: characteristics
//|
-//| A tuple of `bleio.Characteristic` that are offered by this service. (read-only)
+//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by this service. (read-only)
//|
STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) {
bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -119,6 +117,24 @@ const mp_obj_property_t bleio_service_characteristics_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+//| .. attribute:: remote
+//|
+//| True if this is a service provided by a remote device. (read-only)
+//|
+STATIC mp_obj_t bleio_service_get_remote(mp_obj_t self_in) {
+ bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(common_hal_bleio_service_get_is_remote(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_remote_obj, bleio_service_get_remote);
+
+const mp_obj_property_t bleio_service_remote_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_service_get_remote_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
//| .. attribute:: secondary
//|
//| True if this is a secondary service. (read-only)
@@ -157,10 +173,12 @@ const mp_obj_property_t bleio_service_uuid_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+
STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) },
- { MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) },
- { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_add_to_peripheral), MP_ROM_PTR(&bleio_service_add_to_peripheral_obj) },
+ { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) },
+ { MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table);
@@ -178,7 +196,6 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
const mp_obj_type_t bleio_service_type = {
{ &mp_type_type },
.name = MP_QSTR_Service,
- .make_new = bleio_service_make_new,
.print = bleio_service_print,
.locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict
};
diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/_bleio/Service.h
index f646c81a9..e061bcffc 100644
--- a/shared-bindings/bleio/Service.h
+++ b/shared-bindings/_bleio/Service.h
@@ -28,14 +28,16 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
-#include "common-hal/bleio/Service.h"
+#include "common-hal/_bleio/Peripheral.h"
+#include "common-hal/_bleio/Service.h"
const mp_obj_type_t bleio_service_type;
-extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, mp_obj_list_t *characteristic_list, bool is_secondary);
+extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary);
extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self);
extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self);
+extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self);
extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self);
-extern void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self);
+extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
diff --git a/shared-bindings/bleio/UUID.c b/shared-bindings/_bleio/UUID.c
index dca7ea010..3c0889aad 100644
--- a/shared-bindings/bleio/UUID.c
+++ b/shared-bindings/_bleio/UUID.c
@@ -31,9 +31,9 @@
#include "py/objproperty.h"
#include "py/objstr.h"
#include "py/runtime.h"
-#include "shared-bindings/bleio/UUID.h"
+#include "shared-bindings/_bleio/UUID.h"
-//| .. currentmodule:: bleio
+//| .. currentmodule:: _bleio
//|
//| :class:`UUID` -- BLE UUID
//| =========================================================
diff --git a/shared-bindings/bleio/UUID.h b/shared-bindings/_bleio/UUID.h
index caf039aec..46ac54ff3 100644
--- a/shared-bindings/bleio/UUID.h
+++ b/shared-bindings/_bleio/UUID.h
@@ -28,7 +28,7 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H
-#include "common-hal/bleio/UUID.h"
+#include "common-hal/_bleio/UUID.h"
void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c
new file mode 100644
index 000000000..f207be8cf
--- /dev/null
+++ b/shared-bindings/_bleio/__init__.c
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/_bleio/__init__.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-bindings/_bleio/Attribute.h"
+#include "shared-bindings/_bleio/Central.h"
+#include "shared-bindings/_bleio/Characteristic.h"
+#include "shared-bindings/_bleio/CharacteristicBuffer.h"
+#include "shared-bindings/_bleio/Descriptor.h"
+#include "shared-bindings/_bleio/Peripheral.h"
+#include "shared-bindings/_bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Scanner.h"
+#include "shared-bindings/_bleio/Service.h"
+#include "shared-bindings/_bleio/UUID.h"
+
+//| :mod:`_bleio` --- Bluetooth Low Energy (BLE) communication
+//| ================================================================
+//|
+//| .. module:: _bleio
+//| :synopsis: Bluetooth Low Energy functionality
+//| :platform: nRF
+//|
+//| The `_bleio` module provides necessary low-level functionality for communicating
+//| using Bluetooth Low Energy (BLE). The '_' prefix indicates this module is meant
+//| for internal use by libraries but not by the end user. Its API may change incompatibly
+//| between minor versions of CircuitPython.
+//| Please use the
+//| `adafruit_ble <https://circuitpython.readthedocs.io/projects/ble/en/latest/>`_
+//| CircuitPython library instead, which builds on `_bleio`, and
+//| provides higher-level convenience functionality, including predefined beacons, clients,
+//| servers.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| Address
+//| Adapter
+//| Attribute
+//| Central
+//| Characteristic
+//| CharacteristicBuffer
+//| Descriptor
+//| Peripheral
+//| ScanEntry
+//| Scanner
+//| Service
+//| UUID
+//|
+//| .. attribute:: adapter
+//|
+//| BLE Adapter information, such as enabled state as well as MAC
+//| address.
+//| This object is the sole instance of `_bleio.Adapter`.
+//|
+
+STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__bleio) },
+ { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
+ { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) },
+ { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) },
+ { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
+ { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) },
+ { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
+ { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) },
+ { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
+ { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
+ { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
+ { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table);
+
+const mp_obj_module_t bleio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&bleio_module_globals,
+};
diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h
new file mode 100644
index 000000000..67379ae2e
--- /dev/null
+++ b/shared-bindings/_bleio/__init__.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
+
+#include "py/objlist.h"
+
+#include "shared-bindings/_bleio/Adapter.h"
+
+#include "common-hal/_bleio/__init__.h"
+#include "common-hal/_bleio/Adapter.h"
+
+extern const super_adapter_obj_t common_hal_bleio_adapter_obj;
+
+extern void common_hal_bleio_check_connected(uint16_t conn_handle);
+
+extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
+extern mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device);
+extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist);
+
+extern mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle);
+extern void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo);
+extern void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response);
+
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H
diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c
index 03775b1de..1154bbbf1 100644
--- a/shared-bindings/_stage/__init__.c
+++ b/shared-bindings/_stage/__init__.c
@@ -30,6 +30,7 @@
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/displayio/Display.h"
#include "shared-module/_stage/__init__.h"
+#include "shared-module/displayio/display_core.h"
#include "Layer.h"
#include "Text.h"
@@ -50,7 +51,7 @@
//| Layer
//| Text
//|
-//| .. function:: render(x0, y0, x1, y1, layers, buffer, display)
+//| .. function:: render(x0, y0, x1, y1, layers, buffer, display[, scale])
//|
//| Render and send to the display a fragment of the screen.
//|
@@ -61,6 +62,7 @@
//| :param list layers: A list of the :py:class:`~_stage.Layer` objects.
//| :param bytearray buffer: A buffer to use for rendering.
//| :param ~displayio.Display display: The display to use.
+//| :param int scale: How many times should the image be scaled up.
//|
//| There are also no sanity checks, outside of the basic overflow
//| checking. The caller is responsible for making the passed parameters
@@ -89,19 +91,17 @@ STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) {
mp_raise_TypeError(translate("argument num/types mismatch"));
}
displayio_display_obj_t *display = MP_OBJ_TO_PTR(native_display);
-
- while (!displayio_display_begin_transaction(display)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ uint8_t scale = 1;
+ if (n_args >= 8) {
+ scale = mp_obj_get_int(args[7]);
}
- displayio_display_set_region_to_update(display, x0, y0, x1, y1);
- render_stage(x0, y0, x1, y1, layers, layers_size, buffer, buffer_size, display);
- displayio_display_end_transaction(display);
+
+ render_stage(x0, y0, x1, y1, layers, layers_size, buffer, buffer_size,
+ display, scale);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 7, stage_render);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 8, stage_render);
STATIC const mp_rom_map_elem_t stage_module_globals_table[] = {
diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c
index 980f11392..2cd2b6728 100644
--- a/shared-bindings/audiobusio/I2SOut.c
+++ b/shared-bindings/audiobusio/I2SOut.c
@@ -56,7 +56,7 @@
//| using `UDA1334 Breakout <https://www.adafruit.com/product/3678>`_::
//|
//| import audiobusio
-//| import audioio
+//| import audiocore
//| import board
//| import array
//| import time
@@ -68,7 +68,7 @@
//| for i in range(length):
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
//|
-//| sine_wave = audiobusio.RawSample(sine_wave, sample_rate=8000)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
//| i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9)
//| i2s.play(sine_wave, loop=True)
//| time.sleep(1)
@@ -78,12 +78,13 @@
//|
//| import board
//| import audioio
+//| import audiocore
//| import audiobusio
//| import digitalio
//|
//|
//| f = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audioio.WaveFile(f)
+//| wav = audiocore.WaveFile(f)
//|
//| a = audiobusio.I2SOut(board.D1, board.D0, board.D9)
//|
@@ -163,7 +164,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_i2sout___exit___obj, 4, 4,
//| Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audioio.WaveFile` or `audioio.RawSample`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
//|
//| The sample itself should consist of 8 bit or 16 bit samples.
//|
diff --git a/shared-bindings/audioio/RawSample.c b/shared-bindings/audiocore/RawSample.c
index 62998f580..07f8c683f 100644
--- a/shared-bindings/audioio/RawSample.c
+++ b/shared-bindings/audiocore/RawSample.c
@@ -31,11 +31,11 @@
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
-#include "shared-bindings/audioio/AudioOut.h"
#include "shared-bindings/util.h"
+#include "shared-bindings/audiocore/RawSample.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
+//| .. currentmodule:: audiocore
//|
//| :class:`RawSample` -- A raw audio sample buffer
//| ========================================================
@@ -55,6 +55,7 @@
//|
//| Simple 8ksps 440 Hz sin wave::
//|
+//| import audiocore
//| import audioio
//| import board
//| import array
@@ -68,7 +69,7 @@
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15))
//|
//| dac = audioio.AudioOut(board.SPEAKER)
-//| sine_wave = audioio.RawSample(sine_wave)
+//| sine_wave = audiocore.RawSample(sine_wave)
//| dac.play(sine_wave, loop=True)
//| time.sleep(1)
//| dac.stop()
diff --git a/shared-bindings/audioio/RawSample.h b/shared-bindings/audiocore/RawSample.h
index 0d764b77c..b02778cad 100644
--- a/shared-bindings/audioio/RawSample.h
+++ b/shared-bindings/audiocore/RawSample.h
@@ -27,9 +27,8 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_RAWSAMPLE_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_RAWSAMPLE_H
-#include "common-hal/audioio/AudioOut.h"
#include "common-hal/microcontroller/Pin.h"
-#include "shared-module/audioio/RawSample.h"
+#include "shared-module/audiocore/RawSample.h"
extern const mp_obj_type_t audioio_rawsample_type;
diff --git a/shared-bindings/audioio/WaveFile.c b/shared-bindings/audiocore/WaveFile.c
index 242c915d3..1b3a94ff3 100644
--- a/shared-bindings/audioio/WaveFile.c
+++ b/shared-bindings/audiocore/WaveFile.c
@@ -29,27 +29,31 @@
#include "lib/utils/context_manager_helpers.h"
#include "py/objproperty.h"
#include "py/runtime.h"
-#include "shared-bindings/audioio/WaveFile.h"
+#include "shared-bindings/audiocore/WaveFile.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
+//| .. currentmodule:: audiocore
//|
//| :class:`WaveFile` -- Load a wave file for audio playback
//| ========================================================
//|
//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
-//| be 8 bit unsigned or 16 bit signed.
+//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
+//| an internal buffer.
//|
-//| .. class:: WaveFile(file)
+//| .. class:: WaveFile(file[, buffer])
//|
//| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
//|
//| :param typing.BinaryIO file: Already opened wave file
+//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally.
+//|
//|
//| Playing a wave file from flash::
//|
//| import board
+//| import audiocore
//| import audioio
//| import digitalio
//|
@@ -58,7 +62,7 @@
//| speaker_enable.switch_to_output(value=True)
//|
//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audioio.WaveFile(data)
+//| wav = audiocore.WaveFile(data)
//| a = audioio.AudioOut(board.A0)
//|
//| print("playing")
@@ -68,15 +72,23 @@
//| print("stopped")
//|
STATIC mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- mp_arg_check_num(n_args, kw_args, 1, 1, false);
+ mp_arg_check_num(n_args, kw_args, 1, 2, false);
audioio_wavefile_obj_t *self = m_new_obj(audioio_wavefile_obj_t);
self->base.type = &audioio_wavefile_type;
- if (MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) {
- common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]));
- } else {
+ if (!MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) {
mp_raise_TypeError(translate("file must be a file opened in byte mode"));
}
+ uint8_t *buffer = NULL;
+ size_t buffer_size = 0;
+ if (n_args >= 2) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
+ buffer = bufinfo.buf;
+ buffer_size = bufinfo.len;
+ }
+ common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]),
+ buffer, buffer_size);
return MP_OBJ_FROM_PTR(self);
}
diff --git a/shared-bindings/audioio/WaveFile.h b/shared-bindings/audiocore/WaveFile.h
index 62a4200dc..f4a172319 100644
--- a/shared-bindings/audioio/WaveFile.h
+++ b/shared-bindings/audiocore/WaveFile.h
@@ -27,14 +27,15 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_WAVEFILE_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_WAVEFILE_H
-#include "common-hal/audioio/AudioOut.h"
-#include "common-hal/microcontroller/Pin.h"
+#include "py/obj.h"
#include "extmod/vfs_fat.h"
+#include "shared-module/audiocore/WaveFile.h"
+
extern const mp_obj_type_t audioio_wavefile_type;
void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
- pyb_file_obj_t* file);
+ pyb_file_obj_t* file, uint8_t *buffer, size_t buffer_size);
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self);
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self);
diff --git a/shared-bindings/audiocore/__init__.c b/shared-bindings/audiocore/__init__.c
new file mode 100644
index 000000000..cf05112cb
--- /dev/null
+++ b/shared-bindings/audiocore/__init__.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiocore/__init__.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/audiocore/WaveFile.h"
+//#include "shared-bindings/audiomixer/Mixer.h"
+
+//| :mod:`audiocore` --- Support for audio samples and mixer
+//| ========================================================
+//|
+//| .. module:: audiocore
+//| :synopsis: Support for audio samples and mixer
+//| :platform: SAMD21
+//|
+//| The `audiocore` module contains core classes for audio IO
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| RawSample
+//| WaveFile
+//|
+
+STATIC const mp_rom_map_elem_t audiocore_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiocore) },
+ { MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) },
+ { MP_ROM_QSTR(MP_QSTR_WaveFile), MP_ROM_PTR(&audioio_wavefile_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(audiocore_module_globals, audiocore_module_globals_table);
+
+const mp_obj_module_t audiocore_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&audiocore_module_globals,
+};
diff --git a/shared-bindings/audiocore/__init__.h b/shared-bindings/audiocore/__init__.h
new file mode 100644
index 000000000..02437cd13
--- /dev/null
+++ b/shared-bindings/audiocore/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOCORE___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOCORE___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOCORE___INIT___H
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index 571dcdaca..eb4ef1fc6 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -32,7 +32,7 @@
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/audioio/AudioOut.h"
-#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audiocore/RawSample.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
@@ -55,6 +55,7 @@
//|
//| Simple 8ksps 440 Hz sin wave::
//|
+//| import audiocore
//| import audioio
//| import board
//| import array
@@ -68,7 +69,7 @@
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
//|
//| dac = audioio.AudioOut(board.SPEAKER)
-//| sine_wave = audioio.RawSample(sine_wave, sample_rate=8000)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
//| dac.play(sine_wave, loop=True)
//| time.sleep(1)
//| dac.stop()
@@ -84,7 +85,7 @@
//| speaker_enable.switch_to_output(value=True)
//|
//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
-//| wav = audioio.WaveFile(data)
+//| wav = audiocore.WaveFile(data)
//| a = audioio.AudioOut(board.A0)
//|
//| print("playing")
@@ -162,7 +163,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_audioout___exit___obj, 4, 4,
//| Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audioio.WaveFile` or `audioio.RawSample`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
//|
//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output
//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit
diff --git a/shared-bindings/audioio/AudioOut.h b/shared-bindings/audioio/AudioOut.h
index d09a5c9ca..1076ac5cc 100644
--- a/shared-bindings/audioio/AudioOut.h
+++ b/shared-bindings/audioio/AudioOut.h
@@ -29,7 +29,7 @@
#include "common-hal/audioio/AudioOut.h"
#include "common-hal/microcontroller/Pin.h"
-#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audiocore/RawSample.h"
extern const mp_obj_type_t audioio_audioout_type;
diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c
index 4786b6425..7fa37d5c5 100644
--- a/shared-bindings/audioio/__init__.c
+++ b/shared-bindings/audioio/__init__.c
@@ -32,9 +32,15 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/audioio/__init__.h"
#include "shared-bindings/audioio/AudioOut.h"
-#include "shared-bindings/audioio/Mixer.h"
-#include "shared-bindings/audioio/RawSample.h"
-#include "shared-bindings/audioio/WaveFile.h"
+
+#if CIRCUITPY_AUDIOIO_COMPAT
+#include "shared-bindings/audiomixer/Mixer.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/audiocore/WaveFile.h"
+#endif
+#if CIRCUITPY_AUDIOMIXER
+#include "shared-bindings/audiomixer/Mixer.h"
+#endif
//| :mod:`audioio` --- Support for audio input and output
//| ======================================================
@@ -51,22 +57,30 @@
//| :maxdepth: 3
//|
//| AudioOut
-//| Mixer
-//| RawSample
-//| WaveFile
//|
//| All classes change hardware state and should be deinitialized when they
//| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See
//| :ref:`lifetime-and-contextmanagers` for more info.
//|
+//| Since CircuitPython 5, `RawSample` and `WaveFile` are moved
+//| to :mod:`audiocore`, and `Mixer` is moved to :mod:`audiomixer`.
+//|
+//| For compatibility with CircuitPython 4.x, some builds allow the items in
+//| `audiocore` to be imported from `audioio`. This will be removed for all
+//| boards in a future build of CicuitPython.
+//|
STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioio) },
{ MP_ROM_QSTR(MP_QSTR_AudioOut), MP_ROM_PTR(&audioio_audioout_type) },
- { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audioio_mixer_type) },
+#if CIRCUITPY_AUDIOIO_COMPAT
+ #if CIRCUITPY_AUDIOMIXER
+ { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audiomixer_mixer_type) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) },
{ MP_ROM_QSTR(MP_QSTR_WaveFile), MP_ROM_PTR(&audioio_wavefile_type) },
+#endif
};
STATIC MP_DEFINE_CONST_DICT(audioio_module_globals, audioio_module_globals_table);
diff --git a/shared-bindings/audioio/Mixer.c b/shared-bindings/audiomixer/Mixer.c
index dce4b3955..ed7b95d9e 100644
--- a/shared-bindings/audioio/Mixer.c
+++ b/shared-bindings/audiomixer/Mixer.c
@@ -23,7 +23,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "shared-bindings/audioio/Mixer.h"
+#include "shared-bindings/audiomixer/Mixer.h"
+#include "shared-bindings/audiomixer/MixerVoice.h"
+#include "shared-module/audiomixer/MixerVoice.h"
#include <stdint.h>
@@ -32,48 +34,55 @@
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
-#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audiocore/RawSample.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
-//| .. currentmodule:: audioio
+//| .. currentmodule:: audiomixer
//|
//| :class:`Mixer` -- Mixes one or more audio samples together
//| ===========================================================
//|
//| Mixer mixes multiple samples into one sample.
//|
-//| .. class:: Mixer(channel_count=2, buffer_size=1024)
+//| .. class:: Mixer(voice_count=2, buffer_size=1024, channel_count=2, bits_per_sample=16, samples_signed=True, sample_rate=8000)
//|
//| Create a Mixer object that can mix multiple channels with the same sample rate.
+//| Samples are accessed and controlled with the mixer's `audiomixer.MixerVoice` objects.
//|
-//| :param int channel_count: The maximum number of samples to mix at once
+//| :param int voice_count: The maximum number of voices to mix
//| :param int buffer_size: The total size in bytes of the buffers to mix into
+//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo.
+//| :param int bits_per_sample: The bits per sample of the samples being played
+//| :param bool samples_signed: Samples are signed (True) or unsigned (False)
+//| :param int sample_rate: The sample rate to be used for all samples
//|
//| Playing a wave file from flash::
//|
//| import board
//| import audioio
+//| import audiocore
+//| import audiomixer
//| import digitalio
//|
-//| # Required for CircuitPlayground Express
-//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
-//| speaker_enable.switch_to_output(value=True)
-//|
-//| music = audioio.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb"))
-//| drum = audioio.WaveFile(open("drum.wav", "rb"))
-//| mixer = audioio.Mixer(voice_count=2, sample_rate=16000, channel_count=1, bits_per_sample=16, samples_signed=True)
//| a = audioio.AudioOut(board.A0)
+//| music = audiocore.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb"))
+//| drum = audiocore.WaveFile(open("drum.wav", "rb"))
+//| mixer = audiomixer.Mixer(voice_count=2, sample_rate=16000, channel_count=1,
+//| bits_per_sample=16, samples_signed=True)
//|
//| print("playing")
+//| # Have AudioOut play our Mixer source
//| a.play(mixer)
-//| mixer.play(music, voice=0)
+//| # Play the first sample voice
+//| mixer.voice[0].play(music)
//| while mixer.playing:
-//| mixer.play(drum, voice=1)
+//| # Play the second sample voice
+//| mixer.voice[1].play(drum)
//| time.sleep(1)
//| print("stopped")
//|
-STATIC mp_obj_t audioio_mixer_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+STATIC mp_obj_t audiomixer_mixer_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_voice_count, ARG_buffer_size, ARG_channel_count, ARG_bits_per_sample, ARG_samples_signed, ARG_sample_rate };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_voice_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} },
@@ -103,9 +112,15 @@ STATIC mp_obj_t audioio_mixer_make_new(const mp_obj_type_t *type, size_t n_args,
if (bits_per_sample != 8 && bits_per_sample != 16) {
mp_raise_ValueError(translate("bits_per_sample must be 8 or 16"));
}
- audioio_mixer_obj_t *self = m_new_obj_var(audioio_mixer_obj_t, audioio_mixer_voice_t, voice_count);
- self->base.type = &audioio_mixer_type;
- common_hal_audioio_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
+ audiomixer_mixer_obj_t *self = m_new_obj_var(audiomixer_mixer_obj_t, mp_obj_t, voice_count);
+ self->base.type = &audiomixer_mixer_type;
+ common_hal_audiomixer_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
+
+ for(int v=0; v<voice_count; v++){
+ self->voice[v] = audiomixer_mixervoice_type.make_new(&audiomixer_mixervoice_type, 0, 0, NULL);
+ common_hal_audiomixer_mixervoice_set_parent(self->voice[v], self);
+ }
+ self->voice_tuple = mp_obj_new_tuple(self->voice_count, self->voice);
return MP_OBJ_FROM_PTR(self);
}
@@ -114,15 +129,15 @@ STATIC mp_obj_t audioio_mixer_make_new(const mp_obj_type_t *type, size_t n_args,
//|
//| Deinitialises the Mixer and releases any hardware resources for reuse.
//|
-STATIC mp_obj_t audioio_mixer_deinit(mp_obj_t self_in) {
- audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- common_hal_audioio_mixer_deinit(self);
+STATIC mp_obj_t audiomixer_mixer_deinit(mp_obj_t self_in) {
+ audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_audiomixer_mixer_deinit(self);
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_deinit_obj, audioio_mixer_deinit);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_deinit_obj, audiomixer_mixer_deinit);
-STATIC void check_for_deinit(audioio_mixer_obj_t *self) {
- if (common_hal_audioio_mixer_deinited(self)) {
+STATIC void check_for_deinit(audiomixer_mixer_obj_t *self) {
+ if (common_hal_audiomixer_mixer_deinited(self)) {
raise_deinited_error();
}
}
@@ -138,115 +153,147 @@ STATIC void check_for_deinit(audioio_mixer_obj_t *self) {
//| Automatically deinitializes the hardware when exiting a context. See
//| :ref:`lifetime-and-contextmanagers` for more info.
//|
-STATIC mp_obj_t audioio_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t audiomixer_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
- common_hal_audioio_mixer_deinit(args[0]);
+ common_hal_audiomixer_mixer_deinit(args[0]);
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_mixer___exit___obj, 4, 4, audioio_mixer_obj___exit__);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomixer_mixer___exit___obj, 4, 4, audiomixer_mixer_obj___exit__);
+
+//| .. attribute:: playing
+//|
+//| True when any voice is being output. (read-only)
+//|
+STATIC mp_obj_t audiomixer_mixer_obj_get_playing(mp_obj_t self_in) {
+ audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_bool(common_hal_audiomixer_mixer_get_playing(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_get_playing_obj, audiomixer_mixer_obj_get_playing);
+
+const mp_obj_property_t audiomixer_mixer_playing_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomixer_mixer_get_playing_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: sample_rate
+//|
+//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
+//|
+STATIC mp_obj_t audiomixer_mixer_obj_get_sample_rate(mp_obj_t self_in) {
+ audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audiomixer_mixer_get_sample_rate(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_get_sample_rate_obj, audiomixer_mixer_obj_get_sample_rate);
+
+const mp_obj_property_t audiomixer_mixer_sample_rate_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomixer_mixer_get_sample_rate_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+//| .. attribute:: voice
+//|
+//| A tuple of the mixer's `audiomixer.MixerVoice` object(s).
+//|
+//| .. code-block:: python
+//|
+//| >>> mixer.voice
+//| (<MixerVoice>,)
+STATIC mp_obj_t audiomixer_mixer_obj_get_voice(mp_obj_t self_in) {
+ audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return self->voice_tuple;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_get_voice_obj, audiomixer_mixer_obj_get_voice);
+
+const mp_obj_property_t audiomixer_mixer_voice_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomixer_mixer_get_voice_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
//| .. method:: play(sample, *, voice=0, loop=False)
//|
//| Plays the sample once when loop=False and continuously when loop=True.
//| Does not block. Use `playing` to block.
//|
-//| Sample must be an `audioio.WaveFile`, `audioio.Mixer` or `audioio.RawSample`.
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
//|
//| The sample must match the Mixer's encoding settings given in the constructor.
//|
-STATIC mp_obj_t audioio_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+STATIC mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_sample, ARG_voice, ARG_loop };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_voice, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
{ MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
};
- audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ uint8_t v = args[ARG_voice].u_int;
+ if (v > (self->voice_count - 1)) {
+ mp_raise_ValueError(translate("Invalid voice"));
+ }
+ audiomixer_mixervoice_obj_t *voice = MP_OBJ_TO_PTR(self->voice[v]);
mp_obj_t sample = args[ARG_sample].u_obj;
- common_hal_audioio_mixer_play(self, sample, args[ARG_voice].u_int, args[ARG_loop].u_bool);
+ common_hal_audiomixer_mixervoice_play(voice, sample, args[ARG_loop].u_bool);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_play_obj, 1, audioio_mixer_obj_play);
+MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixer_play_obj, 1, audiomixer_mixer_obj_play);
//| .. method:: stop_voice(voice=0)
//|
//| Stops playback of the sample on the given voice.
//|
-STATIC mp_obj_t audioio_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+STATIC mp_obj_t audiomixer_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_voice };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_voice, MP_ARG_INT, {.u_int = 0} },
};
- audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- common_hal_audioio_mixer_stop_voice(self, args[ARG_voice].u_int);
+ uint8_t v = args[ARG_voice].u_int;
+ if (v > (self->voice_count - 1)) {
+ mp_raise_ValueError(translate("Invalid voice"));
+ }
+ audiomixer_mixervoice_obj_t *voice = MP_OBJ_TO_PTR(self->voice[v]);
+ common_hal_audiomixer_mixervoice_stop(voice);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_stop_voice_obj, 1, audioio_mixer_obj_stop_voice);
-
-//| .. attribute:: playing
-//|
-//| True when any voice is being output. (read-only)
-//|
-STATIC mp_obj_t audioio_mixer_obj_get_playing(mp_obj_t self_in) {
- audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- check_for_deinit(self);
- return mp_obj_new_bool(common_hal_audioio_mixer_get_playing(self));
-}
-MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_playing_obj, audioio_mixer_obj_get_playing);
+MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixer_stop_voice_obj, 1, audiomixer_mixer_obj_stop_voice);
-const mp_obj_property_t audioio_mixer_playing_obj = {
- .base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&audioio_mixer_get_playing_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj},
-};
-
-//| .. attribute:: sample_rate
-//|
-//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
-//|
-STATIC mp_obj_t audioio_mixer_obj_get_sample_rate(mp_obj_t self_in) {
- audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- check_for_deinit(self);
- return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_mixer_get_sample_rate(self));
-}
-MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_sample_rate_obj, audioio_mixer_obj_get_sample_rate);
-
-
-const mp_obj_property_t audioio_mixer_sample_rate_obj = {
- .base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&audioio_mixer_get_sample_rate_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj},
-};
-STATIC const mp_rom_map_elem_t audioio_mixer_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t audiomixer_mixer_locals_dict_table[] = {
// Methods
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_mixer_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiomixer_mixer_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
- { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_mixer___exit___obj) },
- { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audioio_mixer_play_obj) },
- { MP_ROM_QSTR(MP_QSTR_stop_voice), MP_ROM_PTR(&audioio_mixer_stop_voice_obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiomixer_mixer___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiomixer_mixer_play_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_voice), MP_ROM_PTR(&audiomixer_mixer_stop_voice_obj) },
// Properties
- { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audioio_mixer_playing_obj) },
- { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_mixer_sample_rate_obj) },
+ { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiomixer_mixer_playing_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiomixer_mixer_sample_rate_obj) },
+ { MP_ROM_QSTR(MP_QSTR_voice), MP_ROM_PTR(&audiomixer_mixer_voice_obj) }
};
-STATIC MP_DEFINE_CONST_DICT(audioio_mixer_locals_dict, audioio_mixer_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(audiomixer_mixer_locals_dict, audiomixer_mixer_locals_dict_table);
-const mp_obj_type_t audioio_mixer_type = {
+const mp_obj_type_t audiomixer_mixer_type = {
{ &mp_type_type },
.name = MP_QSTR_Mixer,
- .make_new = audioio_mixer_make_new,
- .locals_dict = (mp_obj_dict_t*)&audioio_mixer_locals_dict,
+ .make_new = audiomixer_mixer_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audiomixer_mixer_locals_dict,
};
diff --git a/shared-bindings/audioio/Mixer.h b/shared-bindings/audiomixer/Mixer.h
index 832072b8f..9eabbf61d 100644
--- a/shared-bindings/audioio/Mixer.h
+++ b/shared-bindings/audiomixer/Mixer.h
@@ -24,29 +24,28 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER_MIXER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER_MIXER_H
#include "common-hal/microcontroller/Pin.h"
-#include "shared-module/audioio/Mixer.h"
-#include "shared-bindings/audioio/RawSample.h"
+#include "shared-module/audiomixer/Mixer.h"
+#include "shared-bindings/audiocore/RawSample.h"
-extern const mp_obj_type_t audioio_mixer_type;
+extern const mp_obj_type_t audiomixer_mixer_type;
+extern const mp_obj_type_t audiomixer_mixervoice_type;
-void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
- uint8_t voice_count,
- uint32_t buffer_size,
- uint8_t bits_per_sample,
- bool samples_signed,
- uint8_t channel_count,
- uint32_t sample_rate);
+void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t* self,
+ uint8_t voice_count,
+ uint32_t buffer_size,
+ uint8_t bits_per_sample,
+ bool samples_signed,
+ uint8_t channel_count,
+ uint32_t sample_rate);
-void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self);
-bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self);
-void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t voice, bool loop);
-void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice);
+void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t* self);
+bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t* self);
-bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self);
-uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self);
+bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t* self);
+uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t* self);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER_MIXER_H
diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c
new file mode 100644
index 000000000..188f76f57
--- /dev/null
+++ b/shared-bindings/audiomixer/MixerVoice.c
@@ -0,0 +1,178 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 DeanM 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/audiomixer/Mixer.h"
+#include "shared-bindings/audiomixer/MixerVoice.h"
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: audiomixer
+//|
+//| :class:`MixerVoice` -- Voice objects used with Mixer
+//| =====================================================
+//|
+//| Used to access and control samples with `audiomixer.Mixer`.
+//|
+//| .. class:: MixerVoice()
+//|
+//| MixerVoice instance object(s) created by `audiomixer.Mixer`.
+//|
+// TODO: support mono or stereo voices
+STATIC mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ audiomixer_mixervoice_obj_t *self = m_new_obj(audiomixer_mixervoice_obj_t);
+ self->base.type = &audiomixer_mixervoice_type;
+
+ common_hal_audiomixer_mixervoice_construct(self);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: play(sample, *, loop=False)
+//|
+//| Plays the sample once when ``loop=False``, and continuously when ``loop=True``.
+//| Does not block. Use `playing` to block.
+//|
+//| Sample must be an `audiocore.WaveFile`, `audiomixer.Mixer` or `audiocore.RawSample`.
+//|
+//| The sample must match the `audiomixer.Mixer`'s encoding settings given in the constructor.
+//|
+STATIC mp_obj_t audiomixer_mixervoice_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sample, ARG_loop };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t sample = args[ARG_sample].u_obj;
+ common_hal_audiomixer_mixervoice_play(self, sample, args[ARG_loop].u_bool);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_play_obj, 1, audiomixer_mixervoice_obj_play);
+
+//| .. method:: stop()
+//|
+//| Stops playback of the sample on this voice.
+//|
+STATIC mp_obj_t audiomixer_mixervoice_obj_stop(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_voice };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_voice, MP_ARG_INT, {.u_int = 0} },
+ };
+ audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ common_hal_audiomixer_mixervoice_stop(self);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_stop_obj, 1, audiomixer_mixervoice_obj_stop);
+
+//| .. attribute:: level()
+//|
+//| The volume level of a voice, as a floating point number between 0 and 1.
+//|
+STATIC mp_obj_t audiomixer_mixervoice_obj_get_level(mp_obj_t self_in) {
+ return mp_obj_new_float(common_hal_audiomixer_mixervoice_get_level(self_in));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_level_obj, audiomixer_mixervoice_obj_get_level);
+
+STATIC mp_obj_t audiomixer_mixervoice_obj_set_level(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_level };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_level, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ };
+ audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ float level = mp_obj_get_float(args[ARG_level].u_obj);
+
+ if (level > 1 || level < 0) {
+ mp_raise_ValueError(translate("level must be between 0 and 1"));
+ }
+
+ common_hal_audiomixer_mixervoice_set_level(self, level);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_set_level_obj, 1, audiomixer_mixervoice_obj_set_level);
+
+const mp_obj_property_t audiomixer_mixervoice_level_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomixer_mixervoice_get_level_obj,
+ (mp_obj_t)&audiomixer_mixervoice_set_level_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: playing
+//|
+//| True when this voice is being output. (read-only)
+//|
+
+STATIC mp_obj_t audiomixer_mixervoice_obj_get_playing(mp_obj_t self_in) {
+ audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(common_hal_audiomixer_mixervoice_get_playing(self));
+
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_playing_obj, audiomixer_mixervoice_obj_get_playing);
+
+const mp_obj_property_t audiomixer_mixervoice_playing_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomixer_mixervoice_get_playing_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t audiomixer_mixervoice_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiomixer_mixervoice_play_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiomixer_mixervoice_stop_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiomixer_mixervoice_playing_obj) },
+ { MP_ROM_QSTR(MP_QSTR_level), MP_ROM_PTR(&audiomixer_mixervoice_level_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(audiomixer_mixervoice_locals_dict, audiomixer_mixervoice_locals_dict_table);
+
+const mp_obj_type_t audiomixer_mixervoice_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_MixerVoice,
+ .make_new = audiomixer_mixervoice_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audiomixer_mixervoice_locals_dict,
+};
diff --git a/shared-bindings/audiomixer/MixerVoice.h b/shared-bindings/audiomixer/MixerVoice.h
new file mode 100644
index 000000000..83098bc9d
--- /dev/null
+++ b/shared-bindings/audiomixer/MixerVoice.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 DeanM 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_BINDINGS_AUDIOMIXER_MIXERVOICE_H_
+#define SHARED_BINDINGS_AUDIOMIXER_MIXERVOICE_H_
+
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/audiocore/RawSample.h"
+
+#include "shared-module/audiomixer/MixerVoice.h"
+#include "shared-module/audiomixer/Mixer.h"
+
+extern const mp_obj_type_t audiomixer_mixer_type;
+extern const mp_obj_type_t audiomixer_mixervoice_type;
+
+void common_hal_audiomixer_mixervoice_construct(audiomixer_mixervoice_obj_t *self);
+void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t* self, audiomixer_mixer_obj_t *parent);
+void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t* self, mp_obj_t sample, bool loop);
+void common_hal_audiomixer_mixervoice_stop(audiomixer_mixervoice_obj_t* self);
+float common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t* self);
+void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t* self, float gain);
+
+bool common_hal_audiomixer_mixervoice_get_playing(audiomixer_mixervoice_obj_t* self);
+
+#endif /* SHARED_BINDINGS_AUDIOMIXER_MIXERVOICE_H_ */
diff --git a/shared-bindings/audiomixer/__init__.c b/shared-bindings/audiomixer/__init__.c
new file mode 100644
index 000000000..79bab440e
--- /dev/null
+++ b/shared-bindings/audiomixer/__init__.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Michael Schroeder
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiomixer/Mixer.h"
+
+//| :mod:`audiomixer` --- Support for audio mixer
+//| ========================================================
+//|
+//| .. module:: audiomixer
+//| :synopsis: Support for audio mixer
+//|
+//| The `audiomixer` module contains core classes for mixing audio sources
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| Mixer
+//| MixerVoice
+//|
+
+STATIC const mp_rom_map_elem_t audiomixer_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiomixer) },
+ { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audiomixer_mixer_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(audiomixer_module_globals, audiomixer_module_globals_table);
+
+const mp_obj_module_t audiomixer_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&audiomixer_module_globals,
+};
diff --git a/shared-bindings/audiomixer/__init__.h b/shared-bindings/audiomixer/__init__.h
new file mode 100644
index 000000000..35a90441c
--- /dev/null
+++ b/shared-bindings/audiomixer/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Michael Schroeder
+ *
+ * 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_AUDIOMIXER___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER___INIT___H
diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c
new file mode 100644
index 000000000..60bf08500
--- /dev/null
+++ b/shared-bindings/audiopwmio/PWMAudioOut.c
@@ -0,0 +1,294 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: audiopwmio
+//|
+//| :class:`PWMAudioOut` -- Output an analog audio signal
+//| ========================================================
+//|
+//| AudioOut can be used to output an analog audio signal on a given pin.
+//|
+//| .. class:: PWMAudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000)
+//|
+//| Create a PWMAudioOut object associated with the given pin(s). This allows you to
+//| play audio signals out on the given pin(s). In contrast to mod:`audioio`,
+//| the pin(s) specified are digital pins, and are driven with a device-dependent PWM
+//| signal.
+//|
+//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
+//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
+//| :param int quiescent_value: The output value when no signal is present. Samples should start
+//| and end with this value to prevent audible popping.
+//|
+//| Simple 8ksps 440 Hz sin wave::
+//|
+//| import audiocore
+//| import audiopwmio
+//| import board
+//| import array
+//| import time
+//| import math
+//|
+//| # Generate one period of sine wav.
+//| length = 8000 // 440
+//| sine_wave = array.array("H", [0] * length)
+//| for i in range(length):
+//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
+//|
+//| dac = audiopwmio.PWMAudioOut(board.SPEAKER)
+//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000)
+//| dac.play(sine_wave, loop=True)
+//| time.sleep(1)
+//| dac.stop()
+//|
+//| Playing a wave file from flash::
+//|
+//| import board
+//| import audiocore
+//| import audiopwmio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audiocore.WaveFile(data)
+//| a = audiopwmio.PWMAudioOut(board.SPEAKER)
+//|
+//| print("playing")
+//| a.play(wav)
+//| while a.playing:
+//| pass
+//| print("stopped")
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_left_channel, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_right_channel, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = mp_const_none} },
+ { MP_QSTR_quiescent_value, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x8000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t left_channel_obj = args[ARG_left_channel].u_obj;
+ assert_pin(left_channel_obj, false);
+ const mcu_pin_obj_t *left_channel_pin = MP_OBJ_TO_PTR(left_channel_obj);
+
+ mp_obj_t right_channel_obj = args[ARG_right_channel].u_obj;
+ const mcu_pin_obj_t *right_channel_pin = NULL;
+ if (right_channel_obj != mp_const_none) {
+ assert_pin(right_channel_obj, false);
+ right_channel_pin = MP_OBJ_TO_PTR(right_channel_obj);
+ }
+
+ // create AudioOut object from the given pin
+ audiopwmio_pwmaudioout_obj_t *self = m_new_obj(audiopwmio_pwmaudioout_obj_t);
+ self->base.type = &audiopwmio_pwmaudioout_type;
+ common_hal_audiopwmio_pwmaudioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the PWMAudioOut and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_deinit(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_audiopwmio_pwmaudioout_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_deinit_obj, audiopwmio_pwmaudioout_deinit);
+
+STATIC void check_for_deinit(audiopwmio_pwmaudioout_obj_t *self) {
+ if (common_hal_audiopwmio_pwmaudioout_deinited(self)) {
+ raise_deinited_error();
+ }
+}
+//| .. method:: __enter__()
+//|
+//| No-op used by Context Managers.
+//|
+// Provided by context manager helper.
+
+//| .. method:: __exit__()
+//|
+//| Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_audiopwmio_pwmaudioout_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiopwmio_pwmaudioout___exit___obj, 4, 4, audiopwmio_pwmaudioout_obj___exit__);
+
+
+//| .. method:: play(sample, *, loop=False)
+//|
+//| Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
+//|
+//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, or `audiomixer.Mixer`.
+//|
+//| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output
+//| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit
+//| DAC that ignores the lowest 6 bits when playing 16 bit samples.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sample, ARG_loop };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ check_for_deinit(self);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t sample = args[ARG_sample].u_obj;
+ common_hal_audiopwmio_pwmaudioout_play(self, sample, args[ARG_loop].u_bool);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audiopwmio_pwmaudioout_play_obj, 1, audiopwmio_pwmaudioout_obj_play);
+
+//| .. method:: stop()
+//|
+//| Stops playback and resets to the start of the sample.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_stop(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ common_hal_audiopwmio_pwmaudioout_stop(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_stop_obj, audiopwmio_pwmaudioout_obj_stop);
+
+//| .. attribute:: playing
+//|
+//| True when an audio sample is being output even if `paused`. (read-only)
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_playing(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_bool(common_hal_audiopwmio_pwmaudioout_get_playing(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_get_playing_obj, audiopwmio_pwmaudioout_obj_get_playing);
+
+const mp_obj_property_t audiopwmio_pwmaudioout_playing_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiopwmio_pwmaudioout_get_playing_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. method:: pause()
+//|
+//| Stops playback temporarily while remembering the position. Use `resume` to resume playback.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_pause(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ if (!common_hal_audiopwmio_pwmaudioout_get_playing(self)) {
+ mp_raise_RuntimeError(translate("Not playing"));
+ }
+ common_hal_audiopwmio_pwmaudioout_pause(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_pause_obj, audiopwmio_pwmaudioout_obj_pause);
+
+//| .. method:: resume()
+//|
+//| Resumes sample playback after :py:func:`pause`.
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_resume(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+
+ if (common_hal_audiopwmio_pwmaudioout_get_paused(self)) {
+ common_hal_audiopwmio_pwmaudioout_resume(self);
+ }
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_resume_obj, audiopwmio_pwmaudioout_obj_resume);
+
+//| .. attribute:: paused
+//|
+//| True when playback is paused. (read-only)
+//|
+STATIC mp_obj_t audiopwmio_pwmaudioout_obj_get_paused(mp_obj_t self_in) {
+ audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return mp_obj_new_bool(common_hal_audiopwmio_pwmaudioout_get_paused(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_get_paused_obj, audiopwmio_pwmaudioout_obj_get_paused);
+
+const mp_obj_property_t audiopwmio_pwmaudioout_paused_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiopwmio_pwmaudioout_get_paused_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t audiopwmio_pwmaudioout_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiopwmio_pwmaudioout_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiopwmio_pwmaudioout___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiopwmio_pwmaudioout_play_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiopwmio_pwmaudioout_stop_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&audiopwmio_pwmaudioout_pause_obj) },
+ { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&audiopwmio_pwmaudioout_resume_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiopwmio_pwmaudioout_playing_obj) },
+ { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&audiopwmio_pwmaudioout_paused_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(audiopwmio_pwmaudioout_locals_dict, audiopwmio_pwmaudioout_locals_dict_table);
+
+const mp_obj_type_t audiopwmio_pwmaudioout_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PWMAudioOut,
+ .make_new = audiopwmio_pwmaudioout_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audiopwmio_pwmaudioout_locals_dict,
+};
diff --git a/shared-bindings/audiopwmio/PWMAudioOut.h b/shared-bindings/audiopwmio/PWMAudioOut.h
new file mode 100644
index 000000000..22afc70d3
--- /dev/null
+++ b/shared-bindings/audiopwmio/PWMAudioOut.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H
+
+#include "common-hal/audiopwmio/PWMAudioOut.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/audiocore/RawSample.h"
+
+extern const mp_obj_type_t audiopwmio_pwmaudioout_type;
+
+// left_channel will always be non-NULL but right_channel may be for mono output.
+void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t* self,
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t default_value);
+
+void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t* self);
+bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t* self);
+void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self, mp_obj_t sample, bool loop);
+void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t* self);
+bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t* self);
+void common_hal_audiopwmio_pwmaudioout_pause(audiopwmio_pwmaudioout_obj_t* self);
+void common_hal_audiopwmio_pwmaudioout_resume(audiopwmio_pwmaudioout_obj_t* self);
+bool common_hal_audiopwmio_pwmaudioout_get_paused(audiopwmio_pwmaudioout_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO_AUDIOOUT_H
diff --git a/shared-bindings/audiopwmio/__init__.c b/shared-bindings/audiopwmio/__init__.c
new file mode 100644
index 000000000..8a2b202b3
--- /dev/null
+++ b/shared-bindings/audiopwmio/__init__.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audiopwmio/__init__.h"
+#include "shared-bindings/audiopwmio/PWMAudioOut.h"
+
+//| :mod:`audiopwmio` --- Support for audio input and output
+//| ========================================================
+//|
+//| .. module:: audiopwmio
+//| :synopsis: Support for audio output via digital PWM
+//| :platform: NRF52
+//|
+//| The `audiopwmio` module contains classes to provide access to audio IO.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| PWMAudioOut
+//|
+//| All classes change hardware state and should be deinitialized when they
+//| are no longer needed if the program continues after use. To do so, either
+//| call :py:meth:`!deinit` or use a context manager. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+//| Since CircuitPython 5, `Mixer`, `RawSample` and `WaveFile` are moved
+//| to :mod:`audiocore`.
+//|
+
+STATIC const mp_rom_map_elem_t audiopwmio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiopwmio) },
+ { MP_ROM_QSTR(MP_QSTR_PWMAudioOut), MP_ROM_PTR(&audiopwmio_pwmaudioout_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(audiopwmio_module_globals, audiopwmio_module_globals_table);
+
+const mp_obj_module_t audiopwmio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&audiopwmio_module_globals,
+};
diff --git a/shared-bindings/audiopwmio/__init__.h b/shared-bindings/audiopwmio/__init__.h
new file mode 100644
index 000000000..e4b7067d1
--- /dev/null
+++ b/shared-bindings/audiopwmio/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H
diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c
index 0a3b03f51..01a128393 100644
--- a/shared-bindings/bitbangio/I2C.c
+++ b/shared-bindings/bitbangio/I2C.c
@@ -175,6 +175,23 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
//| :param int start: Index to start writing at
//| :param int end: Index to write up to but not include
//|
+// Shared arg parsing for readfrom_into and writeto_then_readfrom.
+STATIC void readfrom(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
+
+ size_t length = bufinfo.len;
+ normalize_buffer_bounds(&start, end, &length);
+ if (length == 0) {
+ mp_raise_ValueError(translate("Buffer must be at least length 1"));
+ }
+
+ uint8_t status = shared_module_bitbangio_i2c_read(self, address, ((uint8_t*)bufinfo.buf) + start, length);
+ if (status != 0) {
+ mp_raise_OSError(status);
+ }
+}
+
STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
static const mp_arg_t allowed_args[] = {
@@ -185,33 +202,21 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
};
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
+ check_lock(self);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- check_lock(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
- int32_t start = args[ARG_start].u_int;
- uint32_t length = bufinfo.len;
- normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
- if (length == 0) {
- mp_raise_ValueError(translate("Buffer must be at least length 1"));
- }
- uint8_t status = shared_module_bitbangio_i2c_read(self,
- args[ARG_address].u_int,
- ((uint8_t*)bufinfo.buf) + start,
- length);
- if (status != 0) {
- mp_raise_OSError(status);
- }
+ readfrom(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
+ args[ARG_end].u_int);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_readfrom_into);
//| .. method:: writeto(address, buffer, *, start=0, end=None, stop=True)
//|
-//| Write the bytes from ``buffer`` to the slave specified by ``address``.
-//| Transmits a stop bit if ``stop`` is set.
+//| Write the bytes from ``buffer`` to the slave specified by ``address`` and then transmits a
+//| stop bit. Use `writeto_then_readfrom` when needing a write, no stop and repeated start
+//| before a read.
//|
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
//| as if ``buffer[start:end]``. This will not cause an allocation like
@@ -224,9 +229,27 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea
//| :param bytearray buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
//| :param int end: Index to read up to but not include
-//| :param bool stop: If true, output an I2C stop condition after the
-//| buffer is written
+//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
+//| Deprecated. Will be removed in 6.x and act as stop=True.
//|
+// Shared arg parsing for writeto and writeto_then_readfrom.
+STATIC void writeto(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) {
+ // get the buffer to write the data from
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
+
+ size_t length = bufinfo.len;
+ normalize_buffer_bounds(&start, end, &length);
+
+ // do the transfer
+ uint8_t status = shared_module_bitbangio_i2c_write(self, address,
+ ((uint8_t*) bufinfo.buf) + start, length,
+ stop);
+ if (status != 0) {
+ mp_raise_OSError(status);
+ }
+}
+
STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end, ARG_stop };
static const mp_arg_t allowed_args[] = {
@@ -242,23 +265,56 @@ STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, m
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- // get the buffer to write the data from
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
+ writeto(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
+ args[ARG_end].u_int, args[ARG_stop].u_bool);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);
- int32_t start = args[ARG_start].u_int;
- uint32_t length = bufinfo.len;
- normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
- // do the transfer
- uint8_t status = shared_module_bitbangio_i2c_write(self, args[ARG_address].u_int,
- ((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool);
- if (status != 0) {
- mp_raise_OSError(status);
- }
+//| .. method:: writeto_then_readfrom(address, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None)
+//|
+//| Write the bytes from ``out_buffer`` to the slave specified by ``address``, generate no stop
+//| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and
+//| ``in_buffer`` can be the same buffer because they are used sequentially.
+//|
+//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
+//| will so it saves memory.
+//|
+//| :param int address: 7-bit device address
+//| :param bytearray out_buffer: buffer containing the bytes to write
+//| :param bytearray in_buffer: buffer to write into
+//| :param int out_start: Index to start writing from
+//| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)``
+//| :param int in_start: Index to start writing at
+//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``
+//|
+STATIC mp_obj_t bitbangio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
+ { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
+ };
+ bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ check_for_deinit(self);
+ check_lock(self);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ writeto(self, args[ARG_address].u_int, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int,
+ args[ARG_out_end].u_int, false);
+ readfrom(self, args[ARG_address].u_int, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int,
+ args[ARG_in_end].u_int);
+
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);
+MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_then_readfrom_obj, 3, bitbangio_i2c_writeto_then_readfrom);
STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_i2c_deinit_obj) },
@@ -271,6 +327,7 @@ STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&bitbangio_i2c_writeto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&bitbangio_i2c_readfrom_into_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeto_then_readfrom), MP_ROM_PTR(&bitbangio_i2c_writeto_then_readfrom_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table);
diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c
index 88bd3d6cb..9a51bde66 100644
--- a/shared-bindings/bitbangio/SPI.c
+++ b/shared-bindings/bitbangio/SPI.c
@@ -275,13 +275,13 @@ STATIC mp_obj_t bitbangio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_
mp_buffer_info_t buf_out_info;
mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
int32_t out_start = args[ARG_out_start].u_int;
- uint32_t out_length = buf_out_info.len;
+ size_t out_length = buf_out_info.len;
normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
mp_buffer_info_t buf_in_info;
mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
int32_t in_start = args[ARG_in_start].u_int;
- uint32_t in_length = buf_in_info.len;
+ size_t in_length = buf_in_info.len;
normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
if (out_length != in_length) {
diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c
deleted file mode 100644
index 3bf0476ab..000000000
--- a/shared-bindings/bleio/Characteristic.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2017 Glenn Ruben Bakke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "py/objproperty.h"
-#include "py/runtime.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/UUID.h"
-
-//| .. currentmodule:: bleio
-//|
-//| :class:`Characteristic` -- BLE service characteristic
-//| =========================================================
-//|
-//| Stores information about a BLE service characteristic and allows reading
-//| and writing of the characteristic's value.
-//|
-//|
-//| .. class:: Characteristic(uuid, *, broadcast=False, indicate=False, notify=False, read=False, write=False, write_no_response=False)
-//|
-//| Create a new Characteristic object identified by the specified UUID.
-//|
-//| :param bleio.UUID uuid: The uuid of the characteristic
-//| :param bool broadcast: Allowed in advertising packets
-//| :param bool indicate: Server will indicate to the client when the value is set and wait for a response
-//| :param bool notify: Server will notify the client when the value is set
-//| :param bool read: Clients may read this characteristic
-//| :param bool write: Clients may write this characteristic; a response will be sent back
-//| :param bool write_no_response: Clients may write this characteristic; no response will be sent back
-//|
-STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum {
- ARG_uuid, ARG_broadcast, ARG_indicate, ARG_notify, ARG_read, ARG_write, ARG_write_no_response,
- };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_broadcast, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_indicate, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_notify, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_read, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_write, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_write_no_response, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} },
- };
-
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- const mp_obj_t uuid_obj = args[ARG_uuid].u_obj;
-
- if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
- mp_raise_ValueError(translate("Expected a UUID"));
- }
- bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
-
- bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t);
- self->base.type = &bleio_characteristic_type;
-
- bleio_characteristic_properties_t properties;
-
- properties.broadcast = args[ARG_broadcast].u_bool;
- properties.indicate = args[ARG_indicate].u_bool;
- properties.notify = args[ARG_notify].u_bool;
- properties.read = args[ARG_read].u_bool;
- properties.write = args[ARG_write].u_bool;
- properties.write_no_response = args[ARG_write_no_response].u_bool;
-
- // Initialize, with an empty descriptor list.
- common_hal_bleio_characteristic_construct(self, uuid, properties, mp_obj_new_list(0, NULL));
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-//| .. attribute:: broadcast
-//|
-//| A `bool` specifying if the characteristic allows broadcasting its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).broadcast);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast);
-
-const mp_obj_property_t bleio_characteristic_broadcast_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: indicate
-//|
-//| A `bool` specifying if the characteristic allows indicating its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).indicate);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate);
-
-
-const mp_obj_property_t bleio_characteristic_indicate_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: notify
-//|
-//| A `bool` specifying if the characteristic allows notifying its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).notify);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify);
-
-const mp_obj_property_t bleio_characteristic_notify_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: read
-//|
-//| A `bool` specifying if the characteristic allows reading its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).read);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read);
-
-const mp_obj_property_t bleio_characteristic_read_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: write
-//|
-//| A `bool` specifying if the characteristic allows writing to its value. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).write);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write);
-
-const mp_obj_property_t bleio_characteristic_write_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: write_no_response
-//|
-//| A `bool` specifying if the characteristic allows writing to its value without response. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_write_no_response(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).write_no_response);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_no_response_obj, bleio_characteristic_get_write_no_response);
-
-const mp_obj_property_t bleio_characteristic_write_no_response_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_write_no_response_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: uuid
-//|
-//| The UUID of this characteristic. (read-only)
-//| Will be ``None`` if the 128-bit UUID for this characteristic is not known.
-//|
-STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- bleio_uuid_obj_t *uuid = common_hal_bleio_characteristic_get_uuid(self);
- return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_uuid_obj, bleio_characteristic_get_uuid);
-
-const mp_obj_property_t bleio_characteristic_uuid_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_uuid_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: value
-//|
-//| The value of this characteristic. The value can be written to if the `write` property allows it.
-//| If the `read` property allows it, the value can be read. If the `notify` property is set, writing
-//| to the value will generate a BLE notification.
-//|
-STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return common_hal_bleio_characteristic_get_value(self);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value);
-
-STATIC mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ);
-
- common_hal_bleio_characteristic_set_value(self, &bufinfo);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_value_obj, bleio_characteristic_set_value);
-
-const mp_obj_property_t bleio_characteristic_value_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_value_obj,
- (mp_obj_t)&bleio_characteristic_set_value_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. attribute:: descriptors
-//|
-//| A tuple of `bleio.Descriptor` that describe this characteristic. (read-only)
-//|
-STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
- // Return list as a tuple so user won't be able to change it.
- mp_obj_list_t *char_list = common_hal_bleio_characteristic_get_descriptor_list(self);
- return mp_obj_new_tuple(char_list->len, char_list->items);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors);
-
-const mp_obj_property_t bleio_characteristic_descriptors_obj = {
- .base.type = &mp_type_property,
- .proxy = { (mp_obj_t)&bleio_characteristic_get_descriptors_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj },
-};
-
-//| .. method:: set_cccd(*, notify=False, indicate=False)
-//|
-//| Set the remote characteristic's CCCD to enable or disable notification and indication.
-//|
-//| :param bool notify: True if Characteristic should receive notifications of remote writes
-//| :param float indicate: True if Characteristic should receive indications of remote writes
-//|
-STATIC mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
-
- enum { ARG_notify, ARG_indicate };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_notify, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_indicate, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- };
-
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- common_hal_bleio_characteristic_set_cccd(self, args[ARG_notify].u_bool, args[ARG_indicate].u_bool);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_characteristic_set_cccd);
-
-
-STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&bleio_characteristic_broadcast_obj) },
- { MP_ROM_QSTR(MP_QSTR_descriptors), MP_ROM_PTR(&bleio_characteristic_descriptors_obj) },
- { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&bleio_characteristic_indicate_obj) },
- { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&bleio_characteristic_notify_obj) },
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&bleio_characteristic_read_obj) },
- { MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) },
- { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
- { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) },
- { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_obj) },
- { MP_ROM_QSTR(MP_QSTR_write_no_response), MP_ROM_PTR(&bleio_characteristic_write_no_response_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table);
-
-STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->uuid) {
- mp_printf(print, "Characteristic(");
- bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind);
- mp_printf(print, ")");
- } else {
- mp_printf(print, "<Characteristic with Unregistered UUID>");
- }
-}
-
-const mp_obj_type_t bleio_characteristic_type = {
- { &mp_type_type },
- .name = MP_QSTR_Characteristic,
- .make_new = bleio_characteristic_make_new,
- .print = bleio_characteristic_print,
- .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict
-};
diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c
deleted file mode 100644
index f2e5aa01d..000000000
--- a/shared-bindings/bleio/Descriptor.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2017 Glenn Ruben Bakke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "py/objproperty.h"
-#include "py/runtime.h"
-#include "shared-bindings/bleio/Descriptor.h"
-#include "shared-bindings/bleio/UUID.h"
-
-//| .. currentmodule:: bleio
-//|
-//| :class:`Descriptor` -- BLE descriptor
-//| =========================================================
-//|
-//| Stores information about a BLE descriptor.
-//| Descriptors are encapsulated by BLE characteristics and provide contextual
-//| information about the characteristic.
-//|
-
-//| .. class:: Descriptor(uuid)
-//|
-//| Create a new descriptor object with the UUID uuid.
-
-//| .. attribute:: handle
-//|
-//| The descriptor handle. (read-only)
-//|
-
-//| .. attribute:: uuid
-//|
-//| The descriptor uuid. (read-only)
-//|
-STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_uuid };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- };
-
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- const mp_obj_t uuid_arg = args[ARG_uuid].u_obj;
-
- if (!MP_OBJ_IS_TYPE(uuid_arg, &bleio_uuid_type)) {
- mp_raise_ValueError(translate("Expected a UUID"));
- }
-
- bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t);
- self->base.type = type;
- bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_arg);
- common_hal_bleio_descriptor_construct(self, uuid);
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-STATIC mp_obj_t bleio_descriptor_get_handle(mp_obj_t self_in) {
- bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- return mp_obj_new_int(common_hal_bleio_descriptor_get_handle(self));
-}
-MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_handle_obj, bleio_descriptor_get_handle);
-
-const mp_obj_property_t bleio_descriptor_handle_obj = {
- .base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&bleio_descriptor_get_handle_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj},
-};
-
-STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) {
- bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
-
- bleio_uuid_obj_t *uuid = common_hal_bleio_descriptor_get_uuid(self);
- return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_uuid_obj, bleio_descriptor_get_uuid);
-
-const mp_obj_property_t bleio_descriptor_uuid_obj = {
- .base.type = &mp_type_property,
- .proxy = {(mp_obj_t)&bleio_descriptor_get_uuid_obj,
- (mp_obj_t)&mp_const_none_obj,
- (mp_obj_t)&mp_const_none_obj},
-};
-
-STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
- // Properties
- { MP_ROM_QSTR(MP_QSTR_handle), MP_ROM_PTR(&bleio_descriptor_handle_obj) },
- { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
-
- // Static variables
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_EXTENDED_PROPERTIES) },
-
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION) },
-
- { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION),
- MP_ROM_INT(DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION) },
-
- { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION),
- MP_ROM_INT(DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION) },
-
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_PRESENTATION_FORMAT) },
-
- { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT),
- MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_AGGREGATE_FORMAT) },
-
- { MP_ROM_QSTR(MP_QSTR_VALID_RANGE),
- MP_ROM_INT(DESCRIPTOR_UUID_VALID_RANGE) },
-
- { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE),
- MP_ROM_INT(DESCRIPTOR_UUID_EXTERNAL_REPORT_REFERENCE) },
-
- { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE),
- MP_ROM_INT(DESCRIPTOR_UUID_REPORT_REFERENCE) },
-
- { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS),
- MP_ROM_INT(DESCRIPTOR_UUID_NUMBER_OF_DIGITALS) },
-
- { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING),
- MP_ROM_INT(DESCRIPTOR_UUID_VALUE_TRIGGER_SETTING) },
-
- { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION),
- MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_CONFIGURATION) },
-
- { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ),
- MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_MEASUREMENT) },
-
- { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING),
- MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_TRIGGER_SETTING) },
-
- { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING),
- MP_ROM_INT(DESCRIPTOR_UUID_TIME_TRIGGER_SETTING) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table);
-
-STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->uuid) {
- mp_printf(print, "Descriptor(");
- bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind);
- mp_printf(print, ")");
- } else {
- mp_printf(print, "<Descriptor with Unregistered UUID>");
- }
-}
-
-const mp_obj_type_t bleio_descriptor_type = {
- { &mp_type_type },
- .name = MP_QSTR_Descriptor,
- .make_new = bleio_descriptor_make_new,
- .print = bleio_descriptor_print,
- .locals_dict = (mp_obj_dict_t*)&bleio_descriptor_locals_dict
-};
diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c
deleted file mode 100644
index ba3bae6c7..000000000
--- a/shared-bindings/bleio/__init__.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Dan Halbert for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2016 Glenn Ruben Bakke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "shared-bindings/bleio/__init__.h"
-#include "shared-bindings/bleio/Address.h"
-#include "shared-bindings/bleio/Central.h"
-#include "shared-bindings/bleio/Characteristic.h"
-#include "shared-bindings/bleio/CharacteristicBuffer.h"
-// #include "shared-bindings/bleio/Descriptor.h"
-#include "shared-bindings/bleio/Peripheral.h"
-#include "shared-bindings/bleio/ScanEntry.h"
-#include "shared-bindings/bleio/Scanner.h"
-#include "shared-bindings/bleio/Service.h"
-#include "shared-bindings/bleio/UUID.h"
-
-//| :mod:`bleio` --- Bluetooth Low Energy functionality
-//| ================================================================
-//|
-//| .. module:: bleio
-//| :synopsis: Bluetooth Low Energy functionality
-//| :platform: nRF
-//|
-//| The `bleio` module contains methods for managing the BLE adapter.
-//|
-//| Libraries
-//|
-//| .. toctree::
-//| :maxdepth: 3
-//|
-//| Address
-//| Adapter
-//| Central
-//| Characteristic
-//| CharacteristicBuffer
-//| Descriptor
-//| Peripheral
-//| ScanEntry
-//| Scanner
-//| Service
-//| UUID
-//|
-//| .. attribute:: adapter
-//|
-//| BLE Adapter information, such as enabled state as well as MAC
-//| address.
-//| This object is the sole instance of `bleio.Adapter`.
-//|
-
-STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) },
- { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
- { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) },
- { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
- { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) },
-// { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
- { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) },
- { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
- { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
- { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
- { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
-
- // Properties
- { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table);
-
-const mp_obj_module_t bleio_module = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&bleio_module_globals,
-};
diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c
index 0e639f0b5..3bd89e2e2 100644
--- a/shared-bindings/busio/I2C.c
+++ b/shared-bindings/busio/I2C.c
@@ -189,6 +189,23 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
//| :param int start: Index to start writing at
//| :param int end: Index to write up to but not include. Defaults to ``len(buffer)``
//|
+// Shared arg parsing for readfrom_into and writeto_then_readfrom.
+STATIC void readfrom(busio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
+
+ size_t length = bufinfo.len;
+ normalize_buffer_bounds(&start, end, &length);
+ if (length == 0) {
+ mp_raise_ValueError(translate("Buffer must be at least length 1"));
+ }
+
+ uint8_t status = common_hal_busio_i2c_read(self, address, ((uint8_t*)bufinfo.buf) + start, length);
+ if (status != 0) {
+ mp_raise_OSError(status);
+ }
+}
+
STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
static const mp_arg_t allowed_args[] = {
@@ -203,21 +220,8 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args,
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
-
- int32_t start = args[ARG_start].u_int;
- uint32_t length = bufinfo.len;
- normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
- if (length == 0) {
- mp_raise_ValueError(translate("Buffer must be at least length 1"));
- }
-
- uint8_t status = common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, length);
- if (status != 0) {
- mp_raise_OSError(status);
- }
-
+ readfrom(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
+ args[ARG_end].u_int);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_into);
@@ -225,7 +229,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in
//| .. method:: writeto(address, buffer, *, start=0, end=None, stop=True)
//|
//| Write the bytes from ``buffer`` to the slave specified by ``address``.
-//| Transmits a stop bit if ``stop`` is set.
+//| Transmits a stop bit when stop is True. Setting stop=False is deprecated and stop will be
+//| removed in CircuitPython 6.x. Use `writeto_then_readfrom` when needing a write, no stop and
+//| repeated start before a read.
//|
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
//| as if ``buffer[start:end]``. This will not cause an allocation like
@@ -238,9 +244,26 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in
//| :param bytearray buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
//| :param int end: Index to read up to but not include. Defaults to ``len(buffer)``
-//| :param bool stop: If true, output an I2C stop condition after the
-//| buffer is written
+//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
+//| Deprecated. Will be removed in 6.x and act as stop=True.
//|
+// Shared arg parsing for writeto and writeto_then_readfrom.
+STATIC void writeto(busio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) {
+ // get the buffer to write the data from
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
+
+ size_t length = bufinfo.len;
+ normalize_buffer_bounds(&start, end, &length);
+
+ // do the transfer
+ uint8_t status = common_hal_busio_i2c_write(self, address, ((uint8_t*) bufinfo.buf) + start,
+ length, stop);
+ if (status != 0) {
+ mp_raise_OSError(status);
+ }
+}
+
STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end, ARG_stop };
static const mp_arg_t allowed_args[] = {
@@ -256,24 +279,55 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- // get the buffer to write the data from
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
+ writeto(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
+ args[ARG_end].u_int, args[ARG_stop].u_bool);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto);
+//| .. method:: writeto_then_readfrom(address, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None)
+//|
+//| Write the bytes from ``out_buffer`` to the slave specified by ``address``, generate no stop
+//| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and
+//| ``in_buffer`` can be the same buffer because they are used sequentially.
+//|
+//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
+//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
+//| will so it saves memory.
+//|
+//| :param int address: 7-bit device address
+//| :param bytearray out_buffer: buffer containing the bytes to write
+//| :param bytearray in_buffer: buffer to write into
+//| :param int out_start: Index to start writing from
+//| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)``
+//| :param int in_start: Index to start writing at
+//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``
+//|
+STATIC mp_obj_t busio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
+ { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
+ };
+ busio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ check_for_deinit(self);
+ check_lock(self);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- int32_t start = args[ARG_start].u_int;
- uint32_t length = bufinfo.len;
- normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
+ writeto(self, args[ARG_address].u_int, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int,
+ args[ARG_out_end].u_int, false);
+ readfrom(self, args[ARG_address].u_int, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int,
+ args[ARG_in_end].u_int);
- // do the transfer
- uint8_t status = common_hal_busio_i2c_write(self, args[ARG_address].u_int,
- ((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool);
- if (status != 0) {
- mp_raise_OSError(status);
- }
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto);
+MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_then_readfrom_obj, 3, busio_i2c_writeto_then_readfrom);
STATIC const mp_rom_map_elem_t busio_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_i2c_deinit_obj) },
@@ -286,6 +340,7 @@ STATIC const mp_rom_map_elem_t busio_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&busio_i2c_readfrom_into_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&busio_i2c_writeto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeto_then_readfrom), MP_ROM_PTR(&busio_i2c_writeto_then_readfrom_obj) },
};
STATIC MP_DEFINE_CONST_DICT(busio_i2c_locals_dict, busio_i2c_locals_dict_table);
diff --git a/shared-bindings/busio/I2C.h b/shared-bindings/busio/I2C.h
index 739732e97..a2d5dbf50 100644
--- a/shared-bindings/busio/I2C.h
+++ b/shared-bindings/busio/I2C.h
@@ -69,4 +69,7 @@ extern uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addres
extern uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address,
uint8_t * data, size_t len);
+// This is used by the supervisor to claim I2C devices indefinitely.
+extern void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_I2C_H
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index a7d7d515c..d47bf499a 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -244,7 +244,7 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
int32_t start = args[ARG_start].u_int;
- uint32_t length = bufinfo.len;
+ size_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
if (length == 0) {
@@ -288,7 +288,7 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
int32_t start = args[ARG_start].u_int;
- uint32_t length = bufinfo.len;
+ size_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
if (length == 0) {
@@ -337,13 +337,13 @@ STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args
mp_buffer_info_t buf_out_info;
mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
int32_t out_start = args[ARG_out_start].u_int;
- uint32_t out_length = buf_out_info.len;
+ size_t out_length = buf_out_info.len;
normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
mp_buffer_info_t buf_in_info;
mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
int32_t in_start = args[ARG_in_start].u_int;
- uint32_t in_length = buf_in_info.len;
+ size_t in_length = buf_in_info.len;
normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
if (out_length != in_length) {
diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c
index 561883810..db2d1b6e2 100644
--- a/shared-bindings/displayio/ColorConverter.c
+++ b/shared-bindings/displayio/ColorConverter.c
@@ -43,25 +43,35 @@
//|
//| Converts one color format to another.
//|
-//| .. class:: ColorConverter()
+//| .. class:: ColorConverter(*, dither=False)
//|
//| Create a ColorConverter object to convert color formats. Only supports RGB888 to RGB565
//| currently.
-//|
+//| :param bool dither: Adds random noise to dither the output image
+
// TODO(tannewt): Add support for other color formats.
//|
STATIC mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_check_num(n_args, kw_args, 0, 0, false);
+ enum { ARG_dither};
+
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_dither, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
displayio_colorconverter_t *self = m_new_obj(displayio_colorconverter_t);
self->base.type = &displayio_colorconverter_type;
- common_hal_displayio_colorconverter_construct(self);
+
+ common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool);
return MP_OBJ_FROM_PTR(self);
}
//| .. method:: convert(color)
//|
+//| Converts the given RGB888 color to RGB565
+//|
STATIC mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t color_obj) {
displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in);
@@ -69,14 +79,44 @@ STATIC mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t
if (!mp_obj_get_int_maybe(color_obj, &color)) {
mp_raise_ValueError(translate("color should be an int"));
}
- uint16_t output_color;
- common_hal_displayio_colorconverter_convert(self, color, &output_color);
+ _displayio_colorspace_t colorspace;
+ colorspace.depth = 16;
+ uint32_t output_color;
+ common_hal_displayio_colorconverter_convert(self, &colorspace, color, &output_color);
return MP_OBJ_NEW_SMALL_INT(output_color);
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_colorconverter_convert_obj, displayio_colorconverter_obj_convert);
+//| .. attribute:: dither
+//|
+//| When true the color converter dithers the output by adding random noise when
+//| truncating to display bitdepth
+//|
+STATIC mp_obj_t displayio_colorconverter_obj_get_dither(mp_obj_t self_in) {
+ displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(common_hal_displayio_colorconverter_get_dither(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_colorconverter_get_dither_obj, displayio_colorconverter_obj_get_dither);
+
+STATIC mp_obj_t displayio_colorconverter_obj_set_dither(mp_obj_t self_in, mp_obj_t dither) {
+ displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_displayio_colorconverter_set_dither(self, mp_obj_is_true(dither));
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_colorconverter_set_dither_obj, displayio_colorconverter_obj_set_dither);
+
+const mp_obj_property_t displayio_colorconverter_dither_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_colorconverter_get_dither_obj,
+ (mp_obj_t)&displayio_colorconverter_set_dither_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
STATIC const mp_rom_map_elem_t displayio_colorconverter_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_convert), MP_ROM_PTR(&displayio_colorconverter_convert_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&displayio_colorconverter_dither_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_colorconverter_locals_dict, displayio_colorconverter_locals_dict_table);
@@ -86,3 +126,4 @@ const mp_obj_type_t displayio_colorconverter_type = {
.make_new = displayio_colorconverter_make_new,
.locals_dict = (mp_obj_dict_t*)&displayio_colorconverter_locals_dict,
};
+
diff --git a/shared-bindings/displayio/ColorConverter.h b/shared-bindings/displayio/ColorConverter.h
index 71be7f543..d550d81be 100644
--- a/shared-bindings/displayio/ColorConverter.h
+++ b/shared-bindings/displayio/ColorConverter.h
@@ -29,9 +29,14 @@
#include "shared-module/displayio/ColorConverter.h"
+#include "shared-module/displayio/Palette.h"
+
extern const mp_obj_type_t displayio_colorconverter_type;
-void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t* self);
-bool common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *colorconverter, uint32_t input_color, uint16_t* output_color);
+void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t* self, bool dither);
+void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *colorconverter, const _displayio_colorspace_t* colorspace, uint32_t input_color, uint32_t* output_color);
+
+void common_hal_displayio_colorconverter_set_dither(displayio_colorconverter_t* self, bool dither);
+bool common_hal_displayio_colorconverter_get_dither(displayio_colorconverter_t* self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_COLORCONVERTER_H
diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c
index 1a36872a6..5ce7b3581 100644
--- a/shared-bindings/displayio/Display.c
+++ b/shared-bindings/displayio/Display.c
@@ -51,7 +51,7 @@
//| Most people should not use this class directly. Use a specific display driver instead that will
//| contain the initialization sequence at minimum.
//|
-//| .. class:: Display(display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False)
+//| .. class:: Display(display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, grayscale=False, pixels_in_byte_share_row=True, bytes_per_cell=1, reverse_pixels_in_byte=False, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness_command=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False, auto_refresh=True, native_frames_per_second=60)
//|
//| Create a Display object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
//|
@@ -88,18 +88,25 @@
//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)
//| :param int color_depth: The number of bits of color per pixel transmitted. (Some displays
//| support 18 bit but 16 is easier to transmit. The last bit is extrapolated.)
+//| :param bool grayscale: True if the display only shows a single color.
+//| :param bool pixels_in_byte_share_row: True when pixels are less than a byte and a byte includes pixels from the same row of the display. When False, pixels share a column.
+//| :param int bytes_per_cell: Number of bytes per addressable memory location when color_depth < 8. When greater than one, bytes share a row or column according to pixels_in_byte_share_row.
+//| :param bool reverse_pixels_in_byte: Reverses the pixel order within each byte when color_depth < 8. Does not apply across multiple bytes even if there is more than one byte per cell (bytes_per_cell.)
//| :param int set_column_command: Command used to set the start and end columns to update
//| :param int set_row_command: Command used so set the start and end rows to update
-//| :param int write_ram_command: Command used to write pixels values into the update region
+//| :param int write_ram_command: Command used to write pixels values into the update region. Ignored if data_as_commands is set.
//| :param int set_vertical_scroll: Command used to set the first row to show
//| :param microcontroller.Pin backlight_pin: Pin connected to the display's backlight
+//| :param int brightness_command: Command to set display brightness. Usually available in OLED controllers.
//| :param bool brightness: Initial display brightness. This value is ignored if auto_brightness is True.
//| :param bool auto_brightness: If True, brightness is controlled via an ambient light sensor or other mechanism.
//| :param bool single_byte_bounds: Display column and row commands use single bytes
//| :param bool data_as_commands: Treat all init and boundary data as SPI commands. Certain displays require this.
+//| :param bool auto_refresh: Automatically refresh the screen
+//| :param int native_frames_per_second: Number of display refreshes per second that occur with the given init_sequence.
//|
STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness, ARG_auto_brightness, ARG_single_byte_bounds, ARG_data_as_commands };
+ enum { ARG_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_bytes_per_cell, ARG_reverse_pixels_in_byte, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_auto_brightness, ARG_single_byte_bounds, ARG_data_as_commands, ARG_auto_refresh, ARG_native_frames_per_second };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_init_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ },
@@ -109,15 +116,22 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
{ MP_QSTR_rowstart, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
{ MP_QSTR_rotation, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
{ MP_QSTR_color_depth, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} },
+ { MP_QSTR_grayscale, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ { MP_QSTR_pixels_in_byte_share_row, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ { MP_QSTR_bytes_per_cell, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1} },
+ { MP_QSTR_reverse_pixels_in_byte, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_set_column_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2a} },
{ MP_QSTR_set_row_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2b} },
{ MP_QSTR_write_ram_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2c} },
{ MP_QSTR_set_vertical_scroll, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x0} },
{ MP_QSTR_backlight_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ { MP_QSTR_brightness_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_BRIGHTNESS_COMMAND} },
{ MP_QSTR_brightness, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(1)} },
{ MP_QSTR_auto_brightness, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_single_byte_bounds, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_data_as_commands, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ { MP_QSTR_auto_refresh, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ { MP_QSTR_native_frames_per_second, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 60} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -157,15 +171,20 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
common_hal_displayio_display_construct(
self,
display_bus, args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation,
- args[ARG_color_depth].u_int, args[ARG_set_column_command].u_int, args[ARG_set_row_command].u_int,
+ args[ARG_color_depth].u_int, args[ARG_grayscale].u_bool,
+ args[ARG_pixels_in_byte_share_row].u_bool, args[ARG_bytes_per_cell].u_bool, args[ARG_reverse_pixels_in_byte].u_bool,
+ args[ARG_set_column_command].u_int, args[ARG_set_row_command].u_int,
args[ARG_write_ram_command].u_int,
args[ARG_set_vertical_scroll].u_int,
bufinfo.buf, bufinfo.len,
MP_OBJ_TO_PTR(backlight_pin),
+ args[ARG_brightness_command].u_int,
brightness,
args[ARG_auto_brightness].u_bool,
args[ARG_single_byte_bounds].u_bool,
- args[ARG_data_as_commands].u_bool
+ args[ARG_data_as_commands].u_bool,
+ args[ARG_auto_refresh].u_bool,
+ args[ARG_native_frames_per_second].u_int
);
return self;
@@ -191,32 +210,74 @@ STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in)
group = MP_OBJ_TO_PTR(native_group(group_in));
}
- common_hal_displayio_display_show(self, group);
+ bool ok = common_hal_displayio_display_show(self, group);
+ if (!ok) {
+ mp_raise_ValueError(translate("Group already used"));
+ }
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_show_obj, displayio_display_obj_show);
-//| .. method:: refresh_soon()
+//| .. method:: refresh(*, target_frames_per_second=60, minimum_frames_per_second=1)
//|
-//| Queues up a display refresh that happens in the background.
+//| When auto refresh is off, waits for the target frame rate and then refreshes the display,
+//| returning True. If the call has taken too long since the last refresh call for the given
+//| target frame rate, then the refresh returns False immediately without updating the screen to
+//| hopefully help getting caught up.
//|
-STATIC mp_obj_t displayio_display_obj_refresh_soon(mp_obj_t self_in) {
- displayio_display_obj_t *self = native_display(self_in);
- common_hal_displayio_display_refresh_soon(self);
- return mp_const_none;
+//| If the time since the last successful refresh is below the minimum frame rate, then an
+//| exception will be raised. Set minimum_frames_per_second to 0 to disable.
+//|
+//| When auto refresh is on, updates the display immediately. (The display will also update
+//| without calls to this.)
+//|
+//| :param int target_frames_per_second: How many times a second `refresh` should be called and the screen updated.
+//| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second.
+//|
+STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_target_frames_per_second, ARG_minimum_frames_per_second };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_target_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 60} },
+ { MP_QSTR_minimum_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ displayio_display_obj_t *self = native_display(pos_args[0]);
+ uint32_t maximum_ms_per_real_frame = 0xffffffff;
+ mp_int_t minimum_frames_per_second = args[ARG_minimum_frames_per_second].u_int;
+ if (minimum_frames_per_second > 0) {
+ maximum_ms_per_real_frame = 1000 / minimum_frames_per_second;
+ }
+ return mp_obj_new_bool(common_hal_displayio_display_refresh(self, 1000 / args[ARG_target_frames_per_second].u_int, maximum_ms_per_real_frame));
}
-MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_refresh_soon_obj, displayio_display_obj_refresh_soon);
+MP_DEFINE_CONST_FUN_OBJ_KW(displayio_display_refresh_obj, 1, displayio_display_obj_refresh);
-//| .. method:: wait_for_frame()
+//| .. attribute:: auto_refresh
//|
-//| Waits until the next frame has been transmitted to the display unless the wait count is
-//| behind the rendered frames. In that case, this will return immediately with the wait count.
+//| True when the display is refreshed automatically.
//|
-STATIC mp_obj_t displayio_display_obj_wait_for_frame(mp_obj_t self_in) {
+STATIC mp_obj_t displayio_display_obj_get_auto_refresh(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
- return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_display_wait_for_frame(self));
+ return mp_obj_new_bool(common_hal_displayio_display_get_auto_refresh(self));
}
-MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_wait_for_frame_obj, displayio_display_obj_wait_for_frame);
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_auto_refresh_obj, displayio_display_obj_get_auto_refresh);
+
+STATIC mp_obj_t displayio_display_obj_set_auto_refresh(mp_obj_t self_in, mp_obj_t auto_refresh) {
+ displayio_display_obj_t *self = native_display(self_in);
+
+ common_hal_displayio_display_set_auto_refresh(self, mp_obj_is_true(auto_refresh));
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_set_auto_refresh_obj, displayio_display_obj_set_auto_refresh);
+
+const mp_obj_property_t displayio_display_auto_refresh_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_display_get_auto_refresh_obj,
+ (mp_obj_t)&displayio_display_set_auto_refresh_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
//| .. attribute:: brightness
//|
@@ -234,10 +295,14 @@ STATIC mp_obj_t displayio_display_obj_get_brightness(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_brightness_obj, displayio_display_obj_get_brightness);
-STATIC mp_obj_t displayio_display_obj_set_brightness(mp_obj_t self_in, mp_obj_t brightness) {
+STATIC mp_obj_t displayio_display_obj_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) {
displayio_display_obj_t *self = native_display(self_in);
common_hal_displayio_display_set_auto_brightness(self, false);
- bool ok = common_hal_displayio_display_set_brightness(self, mp_obj_get_float(brightness));
+ mp_float_t brightness = mp_obj_get_float(brightness_obj);
+ if (brightness < 0 || brightness > 1.0) {
+ mp_raise_ValueError(translate("Brightness must be 0-1.0"));
+ }
+ bool ok = common_hal_displayio_display_set_brightness(self, brightness);
if (!ok) {
mp_raise_RuntimeError(translate("Brightness not adjustable"));
}
@@ -281,6 +346,9 @@ const mp_obj_property_t displayio_display_auto_brightness_obj = {
(mp_obj_t)&mp_const_none_obj},
};
+
+
+
//| .. attribute:: width
//|
//| Gets the width of the board
@@ -317,6 +385,23 @@ const mp_obj_property_t displayio_display_height_obj = {
(mp_obj_t)&mp_const_none_obj},
};
+//| .. attribute:: rotation
+//|
+//| The rotation of the display as an int in degrees.
+//|
+STATIC mp_obj_t displayio_display_obj_get_rotation(mp_obj_t self_in) {
+ displayio_display_obj_t *self = native_display(self_in);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_display_get_rotation(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_rotation_obj, displayio_display_obj_get_rotation);
+
+const mp_obj_property_t displayio_display_rotation_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_display_get_rotation_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
//| .. attribute:: bus
//|
//| The bus being used by the display
@@ -324,7 +409,7 @@ const mp_obj_property_t displayio_display_height_obj = {
//|
STATIC mp_obj_t displayio_display_obj_get_bus(mp_obj_t self_in) {
displayio_display_obj_t *self = native_display(self_in);
- return self->bus;
+ return common_hal_displayio_display_get_bus(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_bus_obj, displayio_display_obj_get_bus);
@@ -336,16 +421,79 @@ const mp_obj_property_t displayio_display_bus_obj = {
};
+//| .. method:: fill_row(y, buffer)
+//|
+//| Extract the pixels from a single row
+//|
+//| :param int y: The top edge of the area
+//| :param bytearray buffer: The buffer in which to place the pixel data
+STATIC mp_obj_t displayio_display_obj_fill_row(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_y, ARG_buffer };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_y, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = -1} },
+ { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ displayio_display_obj_t *self = native_display(pos_args[0]);
+ mp_int_t y = args[ARG_y].u_int;
+ mp_obj_t *result = args[ARG_buffer].u_obj;
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(result, &bufinfo, MP_BUFFER_WRITE);
+
+ if (bufinfo.typecode != BYTEARRAY_TYPECODE) {
+ mp_raise_ValueError(translate("Buffer is not a bytearray."));
+ }
+ if (self->core.colorspace.depth != 16) {
+ mp_raise_ValueError(translate("Display must have a 16 bit colorspace."));
+ }
+
+ displayio_area_t area = {
+ .x1 = 0,
+ .y1 = y,
+ .x2 = self->core.width,
+ .y2 = y + 1
+ };
+ uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth;
+ uint16_t buffer_size = self->core.width / pixels_per_word;
+ uint16_t pixels_per_buffer = displayio_area_size(&area);
+ if (pixels_per_buffer % pixels_per_word) {
+ buffer_size += 1;
+ }
+
+ uint32_t *result_buffer = bufinfo.buf;
+ size_t result_buffer_size = bufinfo.len;
+
+ if (result_buffer_size >= (buffer_size * 4)) {
+ volatile uint32_t mask_length = (pixels_per_buffer / 32) + 1;
+ uint32_t mask[mask_length];
+
+ for (uint16_t k = 0; k < mask_length; k++) {
+ mask[k] = 0x00000000;
+ }
+
+ displayio_display_core_fill_area(&self->core, &area, mask, result_buffer);
+ return result;
+ } else {
+ mp_raise_ValueError(translate("Buffer is too small"));
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(displayio_display_fill_row_obj, 1, displayio_display_obj_fill_row);
+
STATIC const mp_rom_map_elem_t displayio_display_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&displayio_display_show_obj) },
- { MP_ROM_QSTR(MP_QSTR_refresh_soon), MP_ROM_PTR(&displayio_display_refresh_soon_obj) },
- { MP_ROM_QSTR(MP_QSTR_wait_for_frame), MP_ROM_PTR(&displayio_display_wait_for_frame_obj) },
+ { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&displayio_display_refresh_obj) },
+ { MP_ROM_QSTR(MP_QSTR_fill_row), MP_ROM_PTR(&displayio_display_fill_row_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_auto_refresh), MP_ROM_PTR(&displayio_display_auto_refresh_obj) },
{ MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&displayio_display_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_auto_brightness), MP_ROM_PTR(&displayio_display_auto_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_display_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_display_height_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&displayio_display_rotation_obj) },
{ MP_ROM_QSTR(MP_QSTR_bus), MP_ROM_PTR(&displayio_display_bus_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_display_locals_dict, displayio_display_locals_dict_table);
diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h
index 5a027561b..ca2b2d476 100644
--- a/shared-bindings/displayio/Display.h
+++ b/shared-bindings/displayio/Display.h
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_DISPLAY_H
-#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_DISPLAY_H
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_DISPLAY_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_DISPLAY_H
#include "common-hal/microcontroller/Pin.h"
@@ -36,38 +36,39 @@ extern const mp_obj_type_t displayio_display_type;
#define DELAY 0x80
+#define NO_BRIGHTNESS_COMMAND 0x100
+
void common_hal_displayio_display_construct(displayio_display_obj_t* self,
mp_obj_t bus, uint16_t width, uint16_t height,
- int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t color_depth,
+ int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t color_depth, bool grayscale,
+ bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte,
uint8_t set_column_command, uint8_t set_row_command, uint8_t write_ram_command, uint8_t set_vertical_scroll,
- uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin,
+ uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin, uint16_t brightness_command,
mp_float_t brightness, bool auto_brightness,
- bool single_byte_bounds, bool data_as_commands);
-
-int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self);
-
-void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group);
+ bool single_byte_bounds, bool data_as_commands, bool auto_refresh, uint16_t native_frames_per_second);
-void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self);
+bool common_hal_displayio_display_show(displayio_display_obj_t* self,
+ displayio_group_t* root_group);
-bool displayio_display_begin_transaction(displayio_display_obj_t* self);
-void displayio_display_end_transaction(displayio_display_obj_t* self);
+bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame);
-// The second point of the region is exclusive.
-void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
-bool displayio_display_frame_queued(displayio_display_obj_t* self);
+bool common_hal_displayio_display_get_auto_refresh(displayio_display_obj_t* self);
+void common_hal_displayio_display_set_auto_refresh(displayio_display_obj_t* self, bool auto_refresh);
-bool displayio_display_refresh_queued(displayio_display_obj_t* self);
-void displayio_display_finish_refresh(displayio_display_obj_t* self);
-void displayio_display_send_pixels(displayio_display_obj_t* self, uint8_t* pixels, uint32_t length);
+uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self);
+uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self);
+uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self);
bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self);
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness);
-uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self);
-uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self);
+bool common_hal_displayio_display_get_dither(displayio_display_obj_t* self);
+void common_hal_displayio_display_set_dither(displayio_display_obj_t* self, bool dither);
mp_float_t common_hal_displayio_display_get_brightness(displayio_display_obj_t* self);
bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self, mp_float_t brightness);
-#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_DISPLAY_H
+mp_obj_t common_hal_displayio_display_get_bus(displayio_display_obj_t* self);
+
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_DISPLAY_H
diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c
new file mode 100644
index 000000000..81e06f82f
--- /dev/null
+++ b/shared-bindings/displayio/EPaperDisplay.c
@@ -0,0 +1,313 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/EPaperDisplay.h"
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/objtype.h"
+#include "py/runtime.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/util.h"
+#include "shared-module/displayio/__init__.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: displayio
+//|
+//| :class:`EPaperDisplay` -- Manage updating an epaper display over a display bus
+//| ==============================================================================
+//|
+//| This initializes an epaper display and connects it into CircuitPython. Unlike other
+//| objects in CircuitPython, EPaperDisplay objects live until `displayio.release_displays()`
+//| is called. This is done so that CircuitPython can use the display itself.
+//|
+//| Most people should not use this class directly. Use a specific display driver instead that will
+//| contain the startup and shutdown sequences at minimum.
+//|
+//| .. class:: EPaperDisplay(display_bus, start_sequence, stop_sequence, *, width, height, ram_width, ram_height, colstart=0, rowstart=0, rotation=0, set_column_window_command=None, set_row_window_command=None, single_byte_bounds=False, write_black_ram_command, black_bits_inverted=False, write_color_ram_command=None, color_bits_inverted=False, highlight_color=0x000000, refresh_display_command, refresh_time=40, busy_pin=None, busy_state=True, seconds_per_frame=180, always_toggle_chip_select=False)
+//|
+//| Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
+//|
+//| The ``start_sequence`` and ``stop_sequence`` are bitpacked to minimize the ram impact. Every
+//| command begins with a command byte followed by a byte to determine the parameter count and if
+//| a delay is need after. When the top bit of the second byte is 1, the next byte will be the
+//| delay time in milliseconds. The remaining 7 bits are the parameter count excluding any delay
+//| byte. The third through final bytes are the remaining command parameters. The next byte will
+//| begin a new command definition.
+//|
+//| :param display_bus: The bus that the display is connected to
+//| :type display_bus: displayio.FourWire or displayio.ParallelBus
+//| :param buffer start_sequence: Byte-packed initialization sequence.
+//| :param buffer stop_sequence: Byte-packed initialization sequence.
+//| :param int width: Width in pixels
+//| :param int height: Height in pixels
+//| :param int ram_width: RAM width in pixels
+//| :param int ram_height: RAM height in pixels
+//| :param int colstart: The index if the first visible column
+//| :param int rowstart: The index if the first visible row
+//| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270)
+//| :param int set_column_window_command: Command used to set the start and end columns to update
+//| :param int set_row_window_command: Command used so set the start and end rows to update
+//| :param int set_current_column_command: Command used to set the current column location
+//| :param int set_current_row_command: Command used to set the current row location
+//| :param int write_black_ram_command: Command used to write pixels values into the update region
+//| :param bool black_bits_inverted: True if 0 bits are used to show black pixels. Otherwise, 1 means to show black.
+//| :param int write_color_ram_command: Command used to write pixels values into the update region
+//| :param bool color_bits_inverted: True if 0 bits are used to show the color. Otherwise, 1 means to show color.
+//| :param int highlight_color: RGB888 of source color to highlight with third ePaper color.
+//| :param int refresh_display_command: Command used to start a display refresh
+//| :param float refresh_time: Time it takes to refresh the display before the stop_sequence should be sent. Ignored when busy_pin is provided.
+//| :param microcontroller.Pin busy_pin: Pin used to signify the display is busy
+//| :param bool busy_state: State of the busy pin when the display is busy
+//| :param float seconds_per_frame: Minimum number of seconds between screen refreshes
+//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte
+//|
+STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_display_bus, ARG_start_sequence, ARG_stop_sequence, ARG_width, ARG_height, ARG_ram_width, ARG_ram_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_set_column_window_command, ARG_set_row_window_command, ARG_set_current_column_command, ARG_set_current_row_command, ARG_write_black_ram_command, ARG_black_bits_inverted, ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color, ARG_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state, ARG_seconds_per_frame, ARG_always_toggle_chip_select };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_start_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_stop_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_width, MP_ARG_INT | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, },
+ { MP_QSTR_height, MP_ARG_INT | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, },
+ { MP_QSTR_ram_width, MP_ARG_INT | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, },
+ { MP_QSTR_ram_height, MP_ARG_INT | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, },
+ { MP_QSTR_colstart, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_rowstart, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_rotation, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_set_column_window_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_COMMAND} },
+ { MP_QSTR_set_row_window_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_COMMAND} },
+ { MP_QSTR_set_current_column_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_COMMAND} },
+ { MP_QSTR_set_current_row_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_COMMAND} },
+ { MP_QSTR_write_black_ram_command, MP_ARG_INT | MP_ARG_REQUIRED },
+ { MP_QSTR_black_bits_inverted, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ { MP_QSTR_write_color_ram_command, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ { MP_QSTR_color_bits_inverted, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ { MP_QSTR_highlight_color, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x000000} },
+ { MP_QSTR_refresh_display_command, MP_ARG_INT | MP_ARG_REQUIRED },
+ { MP_QSTR_refresh_time, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(40)} },
+ { MP_QSTR_busy_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ { MP_QSTR_busy_state, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ { MP_QSTR_seconds_per_frame, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(180)} },
+ { MP_QSTR_always_toggle_chip_select, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t display_bus = args[ARG_display_bus].u_obj;
+
+ mp_buffer_info_t start_bufinfo;
+ mp_get_buffer_raise(args[ARG_start_sequence].u_obj, &start_bufinfo, MP_BUFFER_READ);
+ mp_buffer_info_t stop_bufinfo;
+ mp_get_buffer_raise(args[ARG_stop_sequence].u_obj, &stop_bufinfo, MP_BUFFER_READ);
+
+
+ mp_obj_t busy_pin_obj = args[ARG_busy_pin].u_obj;
+ assert_pin(busy_pin_obj, true);
+ const mcu_pin_obj_t* busy_pin = NULL;
+ if (busy_pin_obj != NULL && busy_pin_obj != mp_const_none) {
+ busy_pin = MP_OBJ_TO_PTR(busy_pin_obj);
+ assert_pin_free(busy_pin);
+ }
+
+ mp_int_t rotation = args[ARG_rotation].u_int;
+ if (rotation % 90 != 0) {
+ mp_raise_ValueError(translate("Display rotation must be in 90 degree increments"));
+ }
+
+ displayio_epaperdisplay_obj_t *self = NULL;
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].display.base.type == NULL ||
+ displays[i].display.base.type == &mp_type_NoneType) {
+ self = &displays[i].epaper_display;
+ break;
+ }
+ }
+ if (self == NULL) {
+ mp_raise_RuntimeError(translate("Too many displays"));
+ }
+
+ mp_float_t refresh_time = mp_obj_get_float(args[ARG_refresh_time].u_obj);
+ mp_float_t seconds_per_frame = mp_obj_get_float(args[ARG_seconds_per_frame].u_obj);
+
+ mp_int_t write_color_ram_command = NO_COMMAND;
+ mp_int_t highlight_color = args[ARG_highlight_color].u_int;
+ if (args[ARG_write_color_ram_command].u_obj != mp_const_none) {
+ write_color_ram_command = mp_obj_get_int(args[ARG_write_color_ram_command].u_obj);
+ }
+
+ self->base.type = &displayio_epaperdisplay_type;
+ common_hal_displayio_epaperdisplay_construct(
+ self,
+ display_bus,
+ start_bufinfo.buf, start_bufinfo.len, stop_bufinfo.buf, stop_bufinfo.len,
+ args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_ram_width].u_int, args[ARG_ram_height].u_int, args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation,
+ args[ARG_set_column_window_command].u_int, args[ARG_set_row_window_command].u_int,
+ args[ARG_set_current_column_command].u_int, args[ARG_set_current_row_command].u_int,
+ args[ARG_write_black_ram_command].u_int, args[ARG_black_bits_inverted].u_bool, write_color_ram_command, args[ARG_color_bits_inverted].u_bool, highlight_color, args[ARG_refresh_display_command].u_int, refresh_time,
+ busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame, args[ARG_always_toggle_chip_select].u_bool
+ );
+
+ return self;
+}
+
+// Helper to ensure we have the native super class instead of a subclass.
+static displayio_epaperdisplay_obj_t* native_display(mp_obj_t display_obj) {
+ mp_obj_t native_display = mp_instance_cast_to_native_base(display_obj, &displayio_epaperdisplay_type);
+ mp_obj_assert_native_inited(native_display);
+ return MP_OBJ_TO_PTR(native_display);
+}
+
+//| .. method:: show(group)
+//|
+//| Switches to displaying the given group of layers. When group is None, the default
+//| CircuitPython terminal will be shown.
+//|
+//| :param Group group: The group to show.
+STATIC mp_obj_t displayio_epaperdisplay_obj_show(mp_obj_t self_in, mp_obj_t group_in) {
+ displayio_epaperdisplay_obj_t *self = native_display(self_in);
+ displayio_group_t* group = NULL;
+ if (group_in != mp_const_none) {
+ group = MP_OBJ_TO_PTR(native_group(group_in));
+ }
+
+ bool ok = common_hal_displayio_epaperdisplay_show(self, group);
+ if (!ok) {
+ mp_raise_ValueError(translate("Group already used"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_epaperdisplay_show_obj, displayio_epaperdisplay_obj_show);
+
+//| .. method:: refresh()
+//|
+//| Refreshes the display immediately or raises an exception if too soon. Use
+//| ``time.sleep(display.time_to_refresh)`` to sleep until a refresh can occur.
+//|
+STATIC mp_obj_t displayio_epaperdisplay_obj_refresh(mp_obj_t self_in) {
+ displayio_epaperdisplay_obj_t *self = native_display(self_in);
+ bool ok = common_hal_displayio_epaperdisplay_refresh(self);
+ if (!ok) {
+ mp_raise_RuntimeError(translate("Refresh too soon"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_refresh_obj, displayio_epaperdisplay_obj_refresh);
+
+//| .. attribute:: time_to_refresh
+//|
+//| Time, in fractional seconds, until the ePaper display can be refreshed.
+//|
+//|
+STATIC mp_obj_t displayio_epaperdisplay_obj_get_time_to_refresh(mp_obj_t self_in) {
+ displayio_epaperdisplay_obj_t *self = native_display(self_in);
+ return mp_obj_new_float(common_hal_displayio_epaperdisplay_get_time_to_refresh(self) / 1000.0);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_get_time_to_refresh_obj, displayio_epaperdisplay_obj_get_time_to_refresh);
+
+const mp_obj_property_t displayio_epaperdisplay_time_to_refresh_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_epaperdisplay_get_time_to_refresh_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: width
+//|
+//| Gets the width of the display in pixels
+//|
+//|
+STATIC mp_obj_t displayio_epaperdisplay_obj_get_width(mp_obj_t self_in) {
+ displayio_epaperdisplay_obj_t *self = native_display(self_in);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_epaperdisplay_get_width(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_get_width_obj, displayio_epaperdisplay_obj_get_width);
+
+const mp_obj_property_t displayio_epaperdisplay_width_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_epaperdisplay_get_width_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: height
+//|
+//| Gets the height of the display in pixels
+//|
+//|
+STATIC mp_obj_t displayio_epaperdisplay_obj_get_height(mp_obj_t self_in) {
+ displayio_epaperdisplay_obj_t *self = native_display(self_in);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_epaperdisplay_get_height(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_get_height_obj, displayio_epaperdisplay_obj_get_height);
+
+const mp_obj_property_t displayio_epaperdisplay_height_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_epaperdisplay_get_height_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: bus
+//|
+//| The bus being used by the display
+//|
+//|
+STATIC mp_obj_t displayio_epaperdisplay_obj_get_bus(mp_obj_t self_in) {
+ displayio_epaperdisplay_obj_t *self = native_display(self_in);
+ return common_hal_displayio_epaperdisplay_get_bus(self);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_get_bus_obj, displayio_epaperdisplay_obj_get_bus);
+
+const mp_obj_property_t displayio_epaperdisplay_bus_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_epaperdisplay_get_bus_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+STATIC const mp_rom_map_elem_t displayio_epaperdisplay_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&displayio_epaperdisplay_show_obj) },
+ { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&displayio_epaperdisplay_refresh_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_epaperdisplay_width_obj) },
+ { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_epaperdisplay_height_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bus), MP_ROM_PTR(&displayio_epaperdisplay_bus_obj) },
+ { MP_ROM_QSTR(MP_QSTR_time_to_refresh), MP_ROM_PTR(&displayio_epaperdisplay_time_to_refresh_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(displayio_epaperdisplay_locals_dict, displayio_epaperdisplay_locals_dict_table);
+
+const mp_obj_type_t displayio_epaperdisplay_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_EPaperDisplay,
+ .make_new = displayio_epaperdisplay_make_new,
+ .locals_dict = (mp_obj_dict_t*)&displayio_epaperdisplay_locals_dict,
+};
diff --git a/shared-bindings/displayio/EPaperDisplay.h b/shared-bindings/displayio/EPaperDisplay.h
new file mode 100644
index 000000000..e4b81c883
--- /dev/null
+++ b/shared-bindings/displayio/EPaperDisplay.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_EPAPERDISPLAY_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_EPAPERDISPLAY_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "shared-module/displayio/EPaperDisplay.h"
+#include "shared-module/displayio/Group.h"
+
+extern const mp_obj_type_t displayio_epaperdisplay_type;
+
+#define DELAY 0x80
+
+#define NO_COMMAND 0x100
+
+void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self,
+ mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len,
+ uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, int16_t colstart, int16_t rowstart, uint16_t rotation,
+ uint16_t set_column_window_command, uint16_t set_row_window_command,
+ uint16_t set_current_column_command, uint16_t set_current_row_command,
+ uint16_t write_black_ram_command, bool black_bits_inverted, uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint16_t refresh_display_command, mp_float_t refresh_time,
+ const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool always_toggle_chip_select);
+
+bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* self);
+
+bool common_hal_displayio_epaperdisplay_show(displayio_epaperdisplay_obj_t* self, displayio_group_t* root_group);
+
+// Returns time in milliseconds.
+uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaperdisplay_obj_t* self);
+
+uint16_t common_hal_displayio_epaperdisplay_get_width(displayio_epaperdisplay_obj_t* self);
+uint16_t common_hal_displayio_epaperdisplay_get_height(displayio_epaperdisplay_obj_t* self);
+
+mp_obj_t common_hal_displayio_epaperdisplay_get_bus(displayio_epaperdisplay_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_EPAPERDISPLAY_H
diff --git a/shared-bindings/displayio/FourWire.c b/shared-bindings/displayio/FourWire.c
index af64a2028..51203d460 100644
--- a/shared-bindings/displayio/FourWire.c
+++ b/shared-bindings/displayio/FourWire.c
@@ -103,35 +103,63 @@ STATIC mp_obj_t displayio_fourwire_make_new(const mp_obj_type_t *type, size_t n_
return self;
}
-//| .. method:: send(command, data)
+//| .. method:: reset()
+//|
+//| Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
+//| is available.
+//|
+STATIC mp_obj_t displayio_fourwire_obj_reset(mp_obj_t self_in) {
+ displayio_fourwire_obj_t *self = self_in;
+
+ if (!common_hal_displayio_fourwire_reset(self)) {
+ mp_raise_RuntimeError(translate("no reset pin available"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_fourwire_reset_obj, displayio_fourwire_obj_reset);
+
+//| .. method:: send(command, data, *, toggle_every_byte=False)
//|
//| Sends the given command value followed by the full set of data. Display state, such as
//| vertical scroll, set via ``send`` may or may not be reset once the code is done.
//|
-STATIC mp_obj_t displayio_fourwire_obj_send(mp_obj_t self, mp_obj_t command_obj, mp_obj_t data_obj) {
- mp_int_t command_int = MP_OBJ_SMALL_INT_VALUE(command_obj);
- if (!MP_OBJ_IS_SMALL_INT(command_obj) || command_int > 255 || command_int < 0) {
+STATIC mp_obj_t displayio_fourwire_obj_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_command, ARG_data, ARG_toggle_every_byte };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_command, MP_ARG_INT | MP_ARG_REQUIRED },
+ { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_toggle_every_byte, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t command_int = args[ARG_command].u_int;
+ if (command_int > 255 || command_int < 0) {
mp_raise_ValueError(translate("Command must be an int between 0 and 255"));
}
+ displayio_fourwire_obj_t *self = pos_args[0];
uint8_t command = command_int;
mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
+ mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ);
// Wait for display bus to be available.
while (!common_hal_displayio_fourwire_begin_transaction(self)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
+ }
+ display_chip_select_behavior_t chip_select = CHIP_SELECT_UNTOUCHED;
+ if (args[ARG_toggle_every_byte].u_bool) {
+ chip_select = CHIP_SELECT_TOGGLE_EVERY_BYTE;
}
- common_hal_displayio_fourwire_send(self, true, &command, 1);
- common_hal_displayio_fourwire_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
+ common_hal_displayio_fourwire_send(self, DISPLAY_COMMAND, chip_select, &command, 1);
+ common_hal_displayio_fourwire_send(self, DISPLAY_DATA, chip_select, ((uint8_t*) bufinfo.buf), bufinfo.len);
common_hal_displayio_fourwire_end_transaction(self);
return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_3(displayio_fourwire_send_obj, displayio_fourwire_obj_send);
+MP_DEFINE_CONST_FUN_OBJ_KW(displayio_fourwire_send_obj, 3, displayio_fourwire_obj_send);
STATIC const mp_rom_map_elem_t displayio_fourwire_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&displayio_fourwire_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&displayio_fourwire_send_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_fourwire_locals_dict, displayio_fourwire_locals_dict_table);
diff --git a/shared-bindings/displayio/FourWire.h b/shared-bindings/displayio/FourWire.h
index 5dbd60764..d0935f063 100644
--- a/shared-bindings/displayio/FourWire.h
+++ b/shared-bindings/displayio/FourWire.h
@@ -28,6 +28,8 @@
#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_FOURWIRE_H
#include "shared-module/displayio/FourWire.h"
+
+#include "shared-bindings/displayio/__init__.h"
#include "common-hal/microcontroller/Pin.h"
#include "shared-module/displayio/Group.h"
@@ -40,9 +42,12 @@ void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self,
void common_hal_displayio_fourwire_deinit(displayio_fourwire_obj_t* self);
+bool common_hal_displayio_fourwire_reset(mp_obj_t self);
+bool common_hal_displayio_fourwire_bus_free(mp_obj_t self);
+
bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t self);
-void common_hal_displayio_fourwire_send(mp_obj_t self, bool command, uint8_t *data, uint32_t data_length);
+void common_hal_displayio_fourwire_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
void common_hal_displayio_fourwire_end_transaction(mp_obj_t self);
diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c
index 5a35424ce..dd7600eb9 100644
--- a/shared-bindings/displayio/Group.c
+++ b/shared-bindings/displayio/Group.c
@@ -90,6 +90,32 @@ displayio_group_t* native_group(mp_obj_t group_obj) {
return MP_OBJ_TO_PTR(native_group);
}
+//| .. attribute:: hidden
+//|
+//| True when the Group and all of it's layers are not visible. When False, the Group's layers
+//| are visible if they haven't been hidden.
+//|
+STATIC mp_obj_t displayio_group_obj_get_hidden(mp_obj_t self_in) {
+ displayio_group_t *self = native_group(self_in);
+ return mp_obj_new_bool(common_hal_displayio_group_get_hidden(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_group_get_hidden_obj, displayio_group_obj_get_hidden);
+
+STATIC mp_obj_t displayio_group_obj_set_hidden(mp_obj_t self_in, mp_obj_t hidden_obj) {
+ displayio_group_t *self = native_group(self_in);
+
+ common_hal_displayio_group_set_hidden(self, mp_obj_is_true(hidden_obj));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_set_hidden_obj, displayio_group_obj_set_hidden);
+
+const mp_obj_property_t displayio_group_hidden_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_group_get_hidden_obj,
+ (mp_obj_t)&displayio_group_set_hidden_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
//| .. attribute:: scale
//|
//| Scales each pixel within the Group in both directions. For example, when scale=2 each pixel
@@ -305,6 +331,7 @@ STATIC mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t valu
}
STATIC const mp_rom_map_elem_t displayio_group_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_hidden), MP_ROM_PTR(&displayio_group_hidden_obj) },
{ MP_ROM_QSTR(MP_QSTR_scale), MP_ROM_PTR(&displayio_group_scale_obj) },
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&displayio_group_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&displayio_group_y_obj) },
diff --git a/shared-bindings/displayio/Group.h b/shared-bindings/displayio/Group.h
index dc9616f2e..942a207f2 100644
--- a/shared-bindings/displayio/Group.h
+++ b/shared-bindings/displayio/Group.h
@@ -36,6 +36,8 @@ displayio_group_t* native_group(mp_obj_t group_obj);
void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y);
uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self);
void common_hal_displayio_group_set_scale(displayio_group_t* self, uint32_t scale);
+bool common_hal_displayio_group_get_hidden(displayio_group_t* self);
+void common_hal_displayio_group_set_hidden(displayio_group_t* self, bool hidden);
mp_int_t common_hal_displayio_group_get_x(displayio_group_t* self);
void common_hal_displayio_group_set_x(displayio_group_t* self, mp_int_t x);
mp_int_t common_hal_displayio_group_get_y(displayio_group_t* self);
diff --git a/shared-bindings/displayio/I2CDisplay.c b/shared-bindings/displayio/I2CDisplay.c
new file mode 100644
index 000000000..4339d182f
--- /dev/null
+++ b/shared-bindings/displayio/I2CDisplay.c
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/I2CDisplay.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/util.h"
+#include "shared-module/displayio/__init__.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: displayio
+//|
+//| :class:`I2CDisplay` -- Manage updating a display over I2C
+//| ==========================================================================
+//|
+//| Manage updating a display over I2C in the background while Python code runs.
+//| It doesn't handle display initialization.
+//|
+//| .. class:: I2CDisplay(i2c_bus, *, device_address, reset=None)
+//|
+//| Create a I2CDisplay object associated with the given I2C bus and reset pin.
+//|
+//| The I2C bus and pins are then in use by the display until `displayio.release_displays()` is
+//| called even after a reload. (It does this so CircuitPython can use the display after your code
+//| is done.) So, the first time you initialize a display bus in code.py you should call
+//| :py:func`displayio.release_displays` first, otherwise it will error after the first code.py run.
+//|
+//| :param busio.I2C i2c_bus: The I2C bus that make up the clock and data lines
+//| :param int device_address: The I2C address of the device
+//| :param microcontroller.Pin reset: Reset pin. When None only software reset can be used
+//|
+STATIC mp_obj_t displayio_i2cdisplay_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_i2c_bus, ARG_device_address, ARG_reset };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_i2c_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_device_address, MP_ARG_INT | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
+ { MP_QSTR_reset, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t reset = args[ARG_reset].u_obj;
+ if (reset != mp_const_none) {
+ assert_pin_free(reset);
+ } else {
+ reset = NULL;
+ }
+
+ displayio_i2cdisplay_obj_t* self = NULL;
+ mp_obj_t i2c = args[ARG_i2c_bus].u_obj;
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].i2cdisplay_bus.base.type == NULL ||
+ displays[i].i2cdisplay_bus.base.type == &mp_type_NoneType) {
+ self = &displays[i].i2cdisplay_bus;
+ self->base.type = &displayio_i2cdisplay_type;
+ break;
+ }
+ }
+ if (self == NULL) {
+ mp_raise_RuntimeError(translate("Too many display busses"));
+ }
+
+ common_hal_displayio_i2cdisplay_construct(self,
+ MP_OBJ_TO_PTR(i2c), args[ARG_device_address].u_int, reset);
+ return self;
+}
+
+//| .. method:: reset()
+//|
+//| Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
+//| is available.
+//|
+STATIC mp_obj_t displayio_i2cdisplay_obj_reset(mp_obj_t self_in) {
+ displayio_i2cdisplay_obj_t *self = self_in;
+
+ if (!common_hal_displayio_i2cdisplay_reset(self)) {
+ mp_raise_RuntimeError(translate("no reset pin available"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_i2cdisplay_reset_obj, displayio_i2cdisplay_obj_reset);
+
+//| .. method:: send(command, data)
+//|
+//| Sends the given command value followed by the full set of data. Display state, such as
+//| vertical scroll, set via ``send`` may or may not be reset once the code is done.
+//|
+STATIC mp_obj_t displayio_i2cdisplay_obj_send(mp_obj_t self, mp_obj_t command_obj, mp_obj_t data_obj) {
+ mp_int_t command_int = MP_OBJ_SMALL_INT_VALUE(command_obj);
+ if (!MP_OBJ_IS_SMALL_INT(command_obj) || command_int > 255 || command_int < 0) {
+ mp_raise_ValueError(translate("Command must be 0-255"));
+ }
+ uint8_t command = command_int;
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
+
+ // Wait for display bus to be available.
+ while (!common_hal_displayio_i2cdisplay_begin_transaction(self)) {
+ RUN_BACKGROUND_TASKS;
+ }
+ uint8_t full_command[bufinfo.len + 1];
+ full_command[0] = command;
+ memcpy(full_command + 1, ((uint8_t*) bufinfo.buf), bufinfo.len);
+ common_hal_displayio_i2cdisplay_send(self, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, full_command, bufinfo.len + 1);
+ common_hal_displayio_i2cdisplay_end_transaction(self);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_3(displayio_i2cdisplay_send_obj, displayio_i2cdisplay_obj_send);
+
+STATIC const mp_rom_map_elem_t displayio_i2cdisplay_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&displayio_i2cdisplay_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&displayio_i2cdisplay_send_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(displayio_i2cdisplay_locals_dict, displayio_i2cdisplay_locals_dict_table);
+
+const mp_obj_type_t displayio_i2cdisplay_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_I2CDisplay,
+ .make_new = displayio_i2cdisplay_make_new,
+ .locals_dict = (mp_obj_dict_t*)&displayio_i2cdisplay_locals_dict,
+};
diff --git a/shared-bindings/displayio/I2CDisplay.h b/shared-bindings/displayio/I2CDisplay.h
new file mode 100644
index 000000000..bae53c491
--- /dev/null
+++ b/shared-bindings/displayio/I2CDisplay.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017, 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_DISPLAYBUSIO_I2CDISPLAY_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_I2CDISPLAY_H
+
+#include "shared-module/displayio/I2CDisplay.h"
+
+#include "shared-bindings/displayio/__init__.h"
+#include "common-hal/microcontroller/Pin.h"
+
+extern const mp_obj_type_t displayio_i2cdisplay_type;
+
+void common_hal_displayio_i2cdisplay_construct(displayio_i2cdisplay_obj_t* self,
+ busio_i2c_obj_t* i2c, uint16_t device_address, const mcu_pin_obj_t* reset);
+
+void common_hal_displayio_i2cdisplay_deinit(displayio_i2cdisplay_obj_t* self);
+
+bool common_hal_displayio_i2cdisplay_reset(mp_obj_t self);
+bool common_hal_displayio_i2cdisplay_bus_free(mp_obj_t self);
+
+bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t self);
+
+void common_hal_displayio_i2cdisplay_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
+
+void common_hal_displayio_i2cdisplay_end_transaction(mp_obj_t self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_I2CDISPLAY_H
diff --git a/shared-bindings/displayio/Palette.c b/shared-bindings/displayio/Palette.c
index 11c2f677c..dda58e3c5 100644
--- a/shared-bindings/displayio/Palette.c
+++ b/shared-bindings/displayio/Palette.c
@@ -66,11 +66,26 @@ STATIC mp_obj_t displayio_palette_make_new(const mp_obj_type_t *type, size_t n_a
return MP_OBJ_FROM_PTR(self);
}
+
+//| .. method:: __len__()
+//|
+//| Returns the number of colors in a Palette
+//|
+STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ displayio_palette_t *self = MP_OBJ_TO_PTR(self_in);
+ switch (op) {
+ case MP_UNARY_OP_BOOL: return mp_const_true;
+ case MP_UNARY_OP_LEN:
+ return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_palette_get_len(self));
+ default: return MP_OBJ_NULL; // op not supported
+ }
+}
+
//| .. method:: __setitem__(index, value)
//|
//| Sets the pixel color at the given index. The index should be an integer in the range 0 to color_count-1.
//|
-//| The value argument represents a color, and can be from 0x000000 to 0xFFFFFF (to represent an RGB value).
+//| The value argument represents a color, and can be from 0x000000 to 0xFFFFFF (to represent an RGB value).
//| Value can be an int, bytes (3 bytes (RGB) or 4 bytes (RGB + pad byte)), or bytearray.
//|
//| This allows you to::
@@ -89,12 +104,12 @@ STATIC mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val
if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
return MP_OBJ_NULL;
}
- // index read is not supported
- if (value == MP_OBJ_SENTINEL) {
- return MP_OBJ_NULL;
- }
displayio_palette_t *self = MP_OBJ_TO_PTR(self_in);
size_t index = mp_get_index(&displayio_palette_type, self->color_count, index_in, false);
+ // index read
+ if (value == MP_OBJ_SENTINEL) {
+ return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_palette_get_color(self, index));
+ }
uint32_t color;
mp_int_t int_value;
@@ -160,5 +175,7 @@ const mp_obj_type_t displayio_palette_type = {
.name = MP_QSTR_Palette,
.make_new = displayio_palette_make_new,
.subscr = palette_subscr,
+ .unary_op = group_unary_op,
+ .getiter = mp_obj_new_generic_iterator,
.locals_dict = (mp_obj_dict_t*)&displayio_palette_locals_dict,
};
diff --git a/shared-bindings/displayio/Palette.h b/shared-bindings/displayio/Palette.h
index 767fc7b63..8c9fe11e3 100644
--- a/shared-bindings/displayio/Palette.h
+++ b/shared-bindings/displayio/Palette.h
@@ -33,6 +33,8 @@ extern const mp_obj_type_t displayio_palette_type;
void common_hal_displayio_palette_construct(displayio_palette_t* self, uint16_t color_count);
void common_hal_displayio_palette_set_color(displayio_palette_t* self, uint32_t palette_index, uint32_t color);
+uint32_t common_hal_displayio_palette_get_color(displayio_palette_t* self, uint32_t palette_index);
+uint32_t common_hal_displayio_palette_get_len(displayio_palette_t* self);
void common_hal_displayio_palette_make_opaque(displayio_palette_t* self, uint32_t palette_index);
void common_hal_displayio_palette_make_transparent(displayio_palette_t* self, uint32_t palette_index);
diff --git a/shared-bindings/displayio/ParallelBus.c b/shared-bindings/displayio/ParallelBus.c
index 00a96d230..f7195b9cc 100644
--- a/shared-bindings/displayio/ParallelBus.c
+++ b/shared-bindings/displayio/ParallelBus.c
@@ -106,6 +106,21 @@ STATIC mp_obj_t displayio_parallelbus_make_new(const mp_obj_type_t *type, size_t
return self;
}
+//| .. method:: reset()
+//|
+//| Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin
+//| is available.
+//|
+STATIC mp_obj_t displayio_parallelbus_obj_reset(mp_obj_t self_in) {
+ displayio_parallelbus_obj_t *self = self_in;
+
+ if (!common_hal_displayio_parallelbus_reset(self)) {
+ mp_raise_RuntimeError(translate("no reset pin available"));
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_parallelbus_reset_obj, displayio_parallelbus_obj_reset);
+
//| .. method:: send(command, data)
//|
//| Sends the given command value followed by the full set of data. Display state, such as
@@ -122,12 +137,10 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o
// Wait for display bus to be available.
while (!common_hal_displayio_parallelbus_begin_transaction(self)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
+ RUN_BACKGROUND_TASKS;
}
- common_hal_displayio_parallelbus_send(self, true, &command, 1);
- common_hal_displayio_parallelbus_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
+ common_hal_displayio_parallelbus_send(self, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, &command, 1);
+ common_hal_displayio_parallelbus_send(self, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, ((uint8_t*) bufinfo.buf), bufinfo.len);
common_hal_displayio_parallelbus_end_transaction(self);
return mp_const_none;
@@ -135,6 +148,7 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o
MP_DEFINE_CONST_FUN_OBJ_3(displayio_parallelbus_send_obj, displayio_parallelbus_obj_send);
STATIC const mp_rom_map_elem_t displayio_parallelbus_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&displayio_parallelbus_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&displayio_parallelbus_send_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_parallelbus_locals_dict, displayio_parallelbus_locals_dict_table);
diff --git a/shared-bindings/displayio/ParallelBus.h b/shared-bindings/displayio/ParallelBus.h
index c4cde5ff5..be2aef7d4 100644
--- a/shared-bindings/displayio/ParallelBus.h
+++ b/shared-bindings/displayio/ParallelBus.h
@@ -28,8 +28,9 @@
#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_PARALLELBUS_H
#include "common-hal/displayio/ParallelBus.h"
-#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/displayio/__init__.h"
#include "shared-module/displayio/Group.h"
extern const mp_obj_type_t displayio_parallelbus_type;
@@ -40,9 +41,12 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self);
+bool common_hal_displayio_parallelbus_reset(mp_obj_t self);
+bool common_hal_displayio_parallelbus_bus_free(mp_obj_t self);
+
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t self);
-void common_hal_displayio_parallelbus_send(mp_obj_t self, bool command, uint8_t *data, uint32_t data_length);
+void common_hal_displayio_parallelbus_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
void common_hal_displayio_parallelbus_end_transaction(mp_obj_t self);
diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c
index 6ba4914a0..288eb4b23 100644
--- a/shared-bindings/displayio/TileGrid.c
+++ b/shared-bindings/displayio/TileGrid.c
@@ -131,7 +131,8 @@ STATIC mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_
displayio_tilegrid_t *self = m_new_obj(displayio_tilegrid_t);
self->base.type = &displayio_tilegrid_type;
- common_hal_displayio_tilegrid_construct(self, native, bitmap_width / tile_width,
+ common_hal_displayio_tilegrid_construct(self, native,
+ bitmap_width / tile_width, bitmap_height / tile_height,
pixel_shader, args[ARG_width].u_int, args[ARG_height].u_int,
tile_width, tile_height, x, y, args[ARG_default_tile].u_int);
return MP_OBJ_FROM_PTR(self);
@@ -143,6 +144,30 @@ static displayio_tilegrid_t* native_tilegrid(mp_obj_t tilegrid_obj) {
mp_obj_assert_native_inited(native_tilegrid);
return MP_OBJ_TO_PTR(native_tilegrid);
}
+//| .. attribute:: hidden
+//|
+//| True when the TileGrid is hidden. This may be False even when a part of a hidden Group.
+//|
+STATIC mp_obj_t displayio_tilegrid_obj_get_hidden(mp_obj_t self_in) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+ return mp_obj_new_bool(common_hal_displayio_tilegrid_get_hidden(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(displayio_tilegrid_get_hidden_obj, displayio_tilegrid_obj_get_hidden);
+
+STATIC mp_obj_t displayio_tilegrid_obj_set_hidden(mp_obj_t self_in, mp_obj_t hidden_obj) {
+ displayio_tilegrid_t *self = native_tilegrid(self_in);
+
+ common_hal_displayio_tilegrid_set_hidden(self, mp_obj_is_true(hidden_obj));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_set_hidden_obj, displayio_tilegrid_obj_set_hidden);
+
+const mp_obj_property_t displayio_tilegrid_hidden_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&displayio_tilegrid_get_hidden_obj,
+ (mp_obj_t)&displayio_tilegrid_set_hidden_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
//| .. attribute:: x
//|
@@ -346,7 +371,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v
}
if (x >= common_hal_displayio_tilegrid_get_width(self) ||
y >= common_hal_displayio_tilegrid_get_height(self)) {
- mp_raise_IndexError(translate("tile index out of bounds"));
+ mp_raise_IndexError(translate("Tile index out of bounds"));
}
if (value_obj == MP_OBJ_SENTINEL) {
@@ -357,7 +382,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v
} else {
mp_int_t value = mp_obj_get_int(value_obj);
if (value < 0 || value > 255) {
- mp_raise_ValueError(translate("Tile indices must be 0 - 255"));
+ mp_raise_ValueError(translate("Tile value out of bounds"));
}
common_hal_displayio_tilegrid_set_tile(self, x, y, value);
}
@@ -367,6 +392,7 @@ STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v
STATIC const mp_rom_map_elem_t displayio_tilegrid_locals_dict_table[] = {
// Properties
+ { MP_ROM_QSTR(MP_QSTR_hidden), MP_ROM_PTR(&displayio_tilegrid_hidden_obj) },
{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&displayio_tilegrid_x_obj) },
{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&displayio_tilegrid_y_obj) },
{ MP_ROM_QSTR(MP_QSTR_flip_x), MP_ROM_PTR(&displayio_tilegrid_flip_x_obj) },
diff --git a/shared-bindings/displayio/TileGrid.h b/shared-bindings/displayio/TileGrid.h
index 1f9995a94..0ee1c7883 100644
--- a/shared-bindings/displayio/TileGrid.h
+++ b/shared-bindings/displayio/TileGrid.h
@@ -32,9 +32,12 @@
extern const mp_obj_type_t displayio_tilegrid_type;
void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap,
- uint16_t bitmap_width_in_tiles, mp_obj_t pixel_shader, uint16_t width, uint16_t height,
+ uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles,
+ mp_obj_t pixel_shader, uint16_t width, uint16_t height,
uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile);
+bool common_hal_displayio_tilegrid_get_hidden(displayio_tilegrid_t* self);
+void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t* self, bool hidden);
mp_int_t common_hal_displayio_tilegrid_get_x(displayio_tilegrid_t *self);
void common_hal_displayio_tilegrid_set_x(displayio_tilegrid_t *self, mp_int_t x);
mp_int_t common_hal_displayio_tilegrid_get_y(displayio_tilegrid_t *self);
diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c
index 9dc17103b..f78325593 100644
--- a/shared-bindings/displayio/__init__.c
+++ b/shared-bindings/displayio/__init__.c
@@ -33,8 +33,10 @@
#include "shared-bindings/displayio/Bitmap.h"
#include "shared-bindings/displayio/ColorConverter.h"
#include "shared-bindings/displayio/Display.h"
+#include "shared-bindings/displayio/EPaperDisplay.h"
#include "shared-bindings/displayio/FourWire.h"
#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/displayio/I2CDisplay.h"
#include "shared-bindings/displayio/OnDiskBitmap.h"
#include "shared-bindings/displayio/Palette.h"
#include "shared-bindings/displayio/ParallelBus.h"
@@ -59,8 +61,10 @@
//| Bitmap
//| ColorConverter
//| Display
+//| EPaperDisplay
//| FourWire
//| Group
+//| I2CDisplay
//| OnDiskBitmap
//| Palette
//| ParallelBus
@@ -73,7 +77,7 @@
//|
//| Releases any actively used displays so their busses and pins can be used again. This will also
//| release the builtin display on boards that have one. You will need to reinitialize it yourself
-//| afterwards.
+//| afterwards. This may take seconds to complete if an active EPaperDisplay is refreshing.
//|
//| Use this once in your code.py if you initialize a display. Place it right before the
//| initialization so the display is active as long as possible.
@@ -89,6 +93,7 @@ STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_Bitmap), MP_ROM_PTR(&displayio_bitmap_type) },
{ MP_ROM_QSTR(MP_QSTR_ColorConverter), MP_ROM_PTR(&displayio_colorconverter_type) },
{ MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&displayio_display_type) },
+ { MP_ROM_QSTR(MP_QSTR_EPaperDisplay), MP_ROM_PTR(&displayio_epaperdisplay_type) },
{ MP_ROM_QSTR(MP_QSTR_Group), MP_ROM_PTR(&displayio_group_type) },
{ MP_ROM_QSTR(MP_QSTR_OnDiskBitmap), MP_ROM_PTR(&displayio_ondiskbitmap_type) },
{ MP_ROM_QSTR(MP_QSTR_Palette), MP_ROM_PTR(&displayio_palette_type) },
@@ -96,6 +101,7 @@ STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_TileGrid), MP_ROM_PTR(&displayio_tilegrid_type) },
{ MP_ROM_QSTR(MP_QSTR_FourWire), MP_ROM_PTR(&displayio_fourwire_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2CDisplay), MP_ROM_PTR(&displayio_i2cdisplay_type) },
{ MP_ROM_QSTR(MP_QSTR_ParallelBus), MP_ROM_PTR(&displayio_parallelbus_type) },
{ MP_ROM_QSTR(MP_QSTR_release_displays), MP_ROM_PTR(&displayio_release_displays_obj) },
diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h
index 427ddb47d..a7748d029 100644
--- a/shared-bindings/displayio/__init__.h
+++ b/shared-bindings/displayio/__init__.h
@@ -27,6 +27,24 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
+#include "py/obj.h"
+
+typedef enum {
+ DISPLAY_COMMAND,
+ DISPLAY_DATA
+} display_byte_type_t;
+
+typedef enum {
+ CHIP_SELECT_UNTOUCHED,
+ CHIP_SELECT_TOGGLE_EVERY_BYTE
+} display_chip_select_behavior_t;
+
+typedef bool (*display_bus_bus_reset)(mp_obj_t bus);
+typedef bool (*display_bus_bus_free)(mp_obj_t bus);
+typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
+typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
+typedef void (*display_bus_end_transaction)(mp_obj_t bus);
+
void common_hal_displayio_release_displays(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
diff --git a/shared-bindings/i2cslave/I2CSlave.c b/shared-bindings/i2cslave/I2CSlave.c
index 2598accbb..c98ea52e0 100644
--- a/shared-bindings/i2cslave/I2CSlave.c
+++ b/shared-bindings/i2cslave/I2CSlave.c
@@ -182,7 +182,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request(size_t n_args, const mp_obj_t *pos_ar
bool is_read;
bool is_restart;
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
return mp_const_none;
}
@@ -337,7 +337,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request_read(size_t n_args, const mp_obj_t *p
uint8_t *buffer = NULL;
uint64_t timeout_end = common_hal_time_monotonic() + 10 * 1000;
while (common_hal_time_monotonic() < timeout_end) {
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
@@ -382,7 +382,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request_write(mp_obj_t self_in, mp_obj_t buf_
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
for (size_t i = 0; i < bufinfo.len; i++) {
- MICROPY_VM_HOOK_LOOP
+ RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index 8f9bbbb31..cbffdb614 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -1,11 +1,11 @@
Core Modules
========================================
-These core modules are intended on being consistent across ports. Currently
-they are only implemented in the SAMD21 and ESP8266 ports. A module may not exist
-in a port if no underlying hardware support is present or if flash space is
-limited. For example, a microcontroller without analog features will not have
-`analogio`.
+These core modules are intended on being consistent across ports and boards.
+A module may not exist on a port/board if no underlying hardware support is
+present or if flash space is limited. For example, a microcontroller without
+analog features will not have `analogio`. See the `support_matrix` page for
+a list of modules supported on each board.
Modules
---------
@@ -14,55 +14,6 @@ Modules
:glob:
:maxdepth: 3
+ support_matrix
*/__init__
help
-
-.. _module-support-matrix:
-
-Support Matrix
----------------
-NOTE 1: **All Supported** means the following ports are supported: SAMD21, SAMD21 Express,
-SAMD51, SAMD51 Express, and ESP8266.
-
-NOTE 2: **SAMD** and/or **SAMD Express** without additional numbers, means both SAMD21 & SAMD51 versions
-are supported.
-
-NOTE 3: The `pIRkey SAMD21 board <https://www.adafruit.com/product/3364>`_ is specialized and may not
-have modules as listed below.
-
-================= ==============================
-Module Supported Ports
-================= ==============================
-`analogio` **All Supported**
-`audiobusio` **SAMD/SAMD Express**
-`audioio` **SAMD Express**
-`binascii` **ESP8266**
-`bitbangio` **SAMD Express, ESP8266**
-`board` **All Supported**
-`bleio` **nRF**
-`busio` **All Supported**
-`digitalio` **All Supported**
-`frequencyio` **SAMD51**
-`gamepad` **SAMD Express, nRF**
-`hashlib` **ESP8266**
-`i2cslave` **SAMD Express**
-`math` **All Supported**
-`microcontroller` **All Supported**
-`multiterminal` **ESP8266**
-`neopixel_write` **All Supported**
-`nvm` **SAMD Express**
-`os` **All Supported**
-`pulseio` **SAMD/SAMD Express**
-`ps2io` **SAMD/SAMD Express**
-`random` **All Supported**
-`rotaryio` **SAMD51, SAMD Express**
-`storage` **All Supported**
-`struct` **All Supported**
-`supervisor` **SAMD/SAMD Express**
-`time` **All Supported**
-`touchio` **SAMD/SAMD Express**
-`uheap` **Debug (All)**
-`usb_hid` **SAMD/SAMD Express**
-`_pixelbuf` **SAMD Express**
-`_stage` **SAMD/SAMD Express**
-================= ==============================
diff --git a/shared-bindings/support_matrix.rst b/shared-bindings/support_matrix.rst
new file mode 100644
index 000000000..124f3a810
--- /dev/null
+++ b/shared-bindings/support_matrix.rst
@@ -0,0 +1,16 @@
+.. _module-support-matrix:
+
+Support Matrix
+===============
+
+The following table lists the available built-in modules for each CircuitPython
+capable board.
+
+.. csv-table::
+ :header-rows: 1
+ :widths: 7, 50
+
+ "Board", "Modules Available"
+ {% for key, value in support_matrix|dictsort -%}
+ "{{ key }}", "{{ '`' ~ value|join("`, `") ~ '`' }}"
+ {% endfor -%}
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index 70c01c2d8..2654de09a 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -99,16 +99,17 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp
//|
//| Structure used to capture a date and time. Note that it takes a tuple!
//|
-//| :param Tuple[tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst] time_tuple: Tuple of time info.
-//| * the year, 2017 for example
-//| * the month, range [1, 12]
-//| * the day of the month, range [1, 31]
-//| * the hour, range [0, 23]
-//| * the minute, range [0, 59]
-//| * the second, range [0, 61]
-//| * the day of the week, range [0, 6], Monday is 0
-//| * the day of the year, range [1, 366], -1 indicates not known
-//| * 1 when in daylight savings, 0 when not, -1 if unknown.
+//| :param tuple time_tuple: Tuple of time info: ``(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)``
+//|
+//| * ``tm_year``: the year, 2017 for example
+//| * ``tm_month``: the month, range [1, 12]
+//| * ``tm_mday``: the day of the month, range [1, 31]
+//| * ``tm_hour``: the hour, range [0, 23]
+//| * ``tm_minute``: the minute, range [0, 59]
+//| * ``tm_sec``: the second, range [0, 61]
+//| * ``tm_wday``: the day of the week, range [0, 6], Monday is 0
+//| * ``tm_yday``: the day of the year, range [1, 366], -1 indicates not known
+//| * ``tm_isdst``: 1 when in daylight savings, 0 when not, -1 if unknown.
//|
const mp_obj_namedtuple_type_t struct_time_type_obj = {
.base = {
@@ -235,9 +236,16 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
return rtc_get_time_source_time();
}
- mp_int_t secs = mp_obj_int_get_checked(args[0]);
- if (secs < EPOCH1970_EPOCH2000_DIFF_SECS)
+ mp_obj_t arg = args[0];
+ if (mp_obj_is_float(arg)) {
+ arg = mp_obj_new_int_from_float(mp_obj_get_float(arg));
+ }
+
+ mp_int_t secs = mp_obj_get_int(arg);
+
+ if (secs < EPOCH1970_EPOCH2000_DIFF_SECS) {
mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t"));
+ }
timeutils_struct_time_t tm;
timeutils_seconds_since_epoch_to_struct_time(secs, &tm);
@@ -269,8 +277,9 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_raise_TypeError(translate("function takes exactly 9 arguments"));
}
- if (mp_obj_get_int(elem[0]) < 2000)
+ if (mp_obj_get_int(elem[0]) < 2000) {
mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t"));
+ }
mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]));
diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c
index 78fceef41..33d369c74 100644
--- a/shared-bindings/touchio/TouchIn.c
+++ b/shared-bindings/touchio/TouchIn.c
@@ -68,10 +68,11 @@ STATIC mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type,
// 1st argument is the pin
mp_obj_t pin_obj = args[0];
assert_pin(pin_obj, false);
+ const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj);
+ assert_pin_free(pin);
touchio_touchin_obj_t *self = m_new_obj(touchio_touchin_obj_t);
self->base.type = &touchio_touchin_type;
- const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj);
common_hal_touchio_touchin_construct(self, pin);
return (mp_obj_t) self;
diff --git a/shared-bindings/touchio/TouchIn.h b/shared-bindings/touchio/TouchIn.h
index 2e5c51607..e04e79c0b 100644
--- a/shared-bindings/touchio/TouchIn.h
+++ b/shared-bindings/touchio/TouchIn.h
@@ -28,7 +28,12 @@
#define MICROPY_INCLUDED_SHARED_BINDINGS_TOUCHIO_TOUCHIN_H
#include "common-hal/microcontroller/Pin.h"
+
+#if CIRCUITPY_TOUCHIO_USE_NATIVE
#include "common-hal/touchio/TouchIn.h"
+#else
+#include "shared-module/touchio/TouchIn.h"
+#endif
extern const mp_obj_type_t touchio_touchin_type;
diff --git a/shared-module/bleio/Address.c b/shared-module/_bleio/Address.c
index 6bc458b7c..8c8b043fe 100644
--- a/shared-module/bleio/Address.c
+++ b/shared-module/_bleio/Address.c
@@ -28,8 +28,8 @@
#include <string.h>
#include "py/objstr.h"
-#include "shared-bindings/bleio/Address.h"
-#include "shared-module/bleio/Address.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-module/_bleio/Address.h"
void common_hal_bleio_address_construct(bleio_address_obj_t *self, uint8_t *bytes, uint8_t address_type) {
self->bytes = mp_obj_new_bytes(bytes, NUM_BLEIO_ADDRESS_BYTES);
diff --git a/shared-module/bleio/Address.h b/shared-module/_bleio/Address.h
index 39789842f..39789842f 100644
--- a/shared-module/bleio/Address.h
+++ b/shared-module/_bleio/Address.h
diff --git a/shared-module/_bleio/Attribute.c b/shared-module/_bleio/Attribute.c
new file mode 100644
index 000000000..3acfcf1f5
--- /dev/null
+++ b/shared-module/_bleio/Attribute.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "py/runtime.h"
+#include "shared-bindings/_bleio/Attribute.h"
+
+void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode) {
+ switch (security_mode) {
+ case SECURITY_MODE_NO_ACCESS:
+ case SECURITY_MODE_OPEN:
+ case SECURITY_MODE_ENC_NO_MITM:
+ case SECURITY_MODE_ENC_WITH_MITM:
+ case SECURITY_MODE_LESC_ENC_WITH_MITM:
+ case SECURITY_MODE_SIGNED_NO_MITM:
+ case SECURITY_MODE_SIGNED_WITH_MITM:
+ break;
+ default:
+ mp_raise_ValueError(translate("Invalid security_mode"));
+ break;
+ }
+}
diff --git a/shared-module/_bleio/Attribute.h b/shared-module/_bleio/Attribute.h
new file mode 100644
index 000000000..a498a14a5
--- /dev/null
+++ b/shared-module/_bleio/Attribute.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H
+
+// BLE security modes: 0x<level><mode>
+typedef enum {
+ SECURITY_MODE_NO_ACCESS = 0x00,
+ SECURITY_MODE_OPEN = 0x11,
+ SECURITY_MODE_ENC_NO_MITM = 0x21,
+ SECURITY_MODE_ENC_WITH_MITM = 0x31,
+ SECURITY_MODE_LESC_ENC_WITH_MITM = 0x41,
+ SECURITY_MODE_SIGNED_NO_MITM = 0x12,
+ SECURITY_MODE_SIGNED_WITH_MITM = 0x22,
+} bleio_attribute_security_mode_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H
diff --git a/shared-module/_bleio/Characteristic.h b/shared-module/_bleio/Characteristic.h
new file mode 100644
index 000000000..409a57c76
--- /dev/null
+++ b/shared-module/_bleio/Characteristic.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
+
+typedef enum {
+ CHAR_PROP_NONE = 0,
+ CHAR_PROP_BROADCAST = 1u << 0,
+ CHAR_PROP_INDICATE = 1u << 1,
+ CHAR_PROP_NOTIFY = 1u << 2,
+ CHAR_PROP_READ = 1u << 3,
+ CHAR_PROP_WRITE = 1u << 4,
+ CHAR_PROP_WRITE_NO_RESPONSE = 1u << 5,
+ CHAR_PROP_ALL = (CHAR_PROP_BROADCAST | CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY |
+ CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE)
+} bleio_characteristic_properties_enum_t;
+typedef uint8_t bleio_characteristic_properties_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H
diff --git a/shared-module/bleio/ScanEntry.c b/shared-module/_bleio/ScanEntry.c
index 306ac33c5..8dfa17f31 100644
--- a/shared-module/bleio/ScanEntry.c
+++ b/shared-module/_bleio/ScanEntry.c
@@ -28,9 +28,9 @@
#include <string.h>
-#include "shared-bindings/bleio/Address.h"
-#include "shared-module/bleio/Address.h"
-#include "shared-module/bleio/ScanEntry.h"
+#include "shared-bindings/_bleio/Address.h"
+#include "shared-module/_bleio/Address.h"
+#include "shared-module/_bleio/ScanEntry.h"
mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self) {
return MP_OBJ_FROM_PTR(self->address);
diff --git a/shared-module/bleio/ScanEntry.h b/shared-module/_bleio/ScanEntry.h
index b302460e6..1e798d78f 100644
--- a/shared-module/bleio/ScanEntry.h
+++ b/shared-module/_bleio/ScanEntry.h
@@ -29,7 +29,7 @@
#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H
#include "py/obj.h"
-#include "shared-bindings/bleio/Address.h"
+#include "shared-bindings/_bleio/Address.h"
typedef struct {
mp_obj_base_t base;
diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c
index 1af279e92..d5da74272 100644
--- a/shared-module/_stage/__init__.c
+++ b/shared-module/_stage/__init__.c
@@ -34,34 +34,60 @@
void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
mp_obj_t *layers, size_t layers_size,
uint16_t *buffer, size_t buffer_size,
- displayio_display_obj_t *display) {
+ displayio_display_obj_t *display, uint8_t scale) {
+
+ displayio_area_t area;
+ area.x1 = x0;
+ area.y1 = y0;
+ area.x2 = x1;
+ area.y2 = y1;
+ displayio_display_core_set_region_to_update(
+ &display->core, display->set_column_command, display->set_row_command,
+ NO_COMMAND, NO_COMMAND, display->data_as_commands, false, &area);
+
+ while (!displayio_display_core_begin_transaction(&display->core)) {
+ RUN_BACKGROUND_TASKS;
+ }
+ display->core.send(display->core.bus, DISPLAY_COMMAND,
+ CHIP_SELECT_TOGGLE_EVERY_BYTE,
+ &display->write_ram_command, 1);
size_t index = 0;
for (uint16_t y = y0; y < y1; ++y) {
- for (uint16_t x = x0; x < x1; ++x) {
- for (size_t layer = 0; layer < layers_size; ++layer) {
+ for (uint8_t yscale = 0; yscale < scale; ++yscale) {
+ for (uint16_t x = x0; x < x1; ++x) {
uint16_t c = TRANSPARENT;
- layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]);
- if (obj->base.type == &mp_type_layer) {
- c = get_layer_pixel(obj, x, y);
- } else if (obj->base.type == &mp_type_text) {
- c = get_text_pixel((text_obj_t *)obj, x, y);
+ for (size_t layer = 0; layer < layers_size; ++layer) {
+ layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]);
+ if (obj->base.type == &mp_type_layer) {
+ c = get_layer_pixel(obj, x, y);
+ } else if (obj->base.type == &mp_type_text) {
+ c = get_text_pixel((text_obj_t *)obj, x, y);
+ }
+ if (c != TRANSPARENT) {
+ break;
+ }
}
- if (c != TRANSPARENT) {
+ for (uint8_t xscale = 0; xscale < scale; ++xscale) {
buffer[index] = c;
- break;
+ index += 1;
+ // The buffer is full, send it.
+ if (index >= buffer_size) {
+ display->core.send(display->core.bus, DISPLAY_DATA,
+ CHIP_SELECT_UNTOUCHED,
+ ((uint8_t*)buffer), buffer_size * 2);
+ index = 0;
+ }
}
}
- index += 1;
- // The buffer is full, send it.
- if (index >= buffer_size) {
- display->send(display->bus, false, ((uint8_t*)buffer), buffer_size * 2);
- index = 0;
- }
}
}
// Send the remaining data.
if (index) {
- display->send(display->bus, false, ((uint8_t*)buffer), index * 2);
+ display->core.send(display->core.bus, DISPLAY_DATA,
+ CHIP_SELECT_UNTOUCHED,
+ ((uint8_t*)buffer), index * 2);
}
+
+ displayio_display_core_end_transaction(&display->core);
}
diff --git a/shared-module/_stage/__init__.h b/shared-module/_stage/__init__.h
index d263302b4..5af2124ae 100644
--- a/shared-module/_stage/__init__.h
+++ b/shared-module/_stage/__init__.h
@@ -37,6 +37,6 @@
void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
mp_obj_t *layers, size_t layers_size,
uint16_t *buffer, size_t buffer_size,
- displayio_display_obj_t *display);
+ displayio_display_obj_t *display, uint8_t scale);
#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE
diff --git a/shared-module/audioio/RawSample.c b/shared-module/audiocore/RawSample.c
index 6422e346b..d6bf3a567 100644
--- a/shared-module/audioio/RawSample.c
+++ b/shared-module/audiocore/RawSample.c
@@ -24,11 +24,11 @@
* THE SOFTWARE.
*/
-#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/audiocore/RawSample.h"
#include <stdint.h>
-#include "shared-module/audioio/RawSample.h"
+#include "shared-module/audiocore/RawSample.h"
void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t* self,
uint8_t* buffer,
diff --git a/shared-module/audioio/RawSample.h b/shared-module/audiocore/RawSample.h
index fe5283db4..6c2c19c9b 100644
--- a/shared-module/audioio/RawSample.h
+++ b/shared-module/audiocore/RawSample.h
@@ -29,7 +29,7 @@
#include "py/obj.h"
-#include "shared-module/audioio/__init__.h"
+#include "shared-module/audiocore/__init__.h"
typedef struct {
mp_obj_base_t base;
diff --git a/shared-module/audioio/WaveFile.c b/shared-module/audiocore/WaveFile.c
index d5dd9419c..0248d42e2 100644
--- a/shared-module/audioio/WaveFile.c
+++ b/shared-module/audiocore/WaveFile.c
@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
-#include "shared-bindings/audioio/WaveFile.h"
+#include "shared-bindings/audiocore/WaveFile.h"
#include <stdint.h>
#include <string.h>
@@ -32,7 +32,7 @@
#include "py/mperrno.h"
#include "py/runtime.h"
-#include "shared-module/audioio/WaveFile.h"
+#include "shared-module/audiocore/WaveFile.h"
#include "supervisor/shared/translate.h"
struct wave_format_chunk {
@@ -46,7 +46,9 @@ struct wave_format_chunk {
};
void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
- pyb_file_obj_t* file) {
+ pyb_file_obj_t* file,
+ uint8_t *buffer,
+ size_t buffer_size) {
// Load the wave
self->file = file;
uint8_t chunk_header[16];
@@ -84,7 +86,6 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
}
// Get the sample_rate
self->sample_rate = format.sample_rate;
- self->len = 256;
self->channel_count = format.num_channels;
self->bits_per_sample = format.bits_per_sample;
@@ -111,21 +112,31 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
// Try to allocate two buffers, one will be loaded from file and the other
// DMAed to DAC.
- self->buffer = m_malloc(self->len, false);
- if (self->buffer == NULL) {
- common_hal_audioio_wavefile_deinit(self);
- mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer"));
- }
+ if (buffer_size) {
+ self->len = buffer_size / 2;
+ self->buffer = buffer;
+ self->second_buffer = buffer + self->len;
+ } else {
+ self->len = 256;
+ self->buffer = m_malloc(self->len, false);
+ if (self->buffer == NULL) {
+ common_hal_audioio_wavefile_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate first buffer"));
+ }
- self->second_buffer = m_malloc(self->len, false);
- if (self->second_buffer == NULL) {
- common_hal_audioio_wavefile_deinit(self);
- mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer"));
+ self->second_buffer = m_malloc(self->len, false);
+ if (self->second_buffer == NULL) {
+ common_hal_audioio_wavefile_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate second buffer"));
+ }
}
}
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self) {
self->buffer = NULL;
+ self->second_buffer = NULL;
}
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self) {
@@ -205,7 +216,7 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t*
} else {
*buffer = self->buffer;
}
- if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK) {
+ if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK || length_read != num_bytes_to_load) {
return GET_BUFFER_ERROR;
}
self->bytes_remaining -= length_read;
diff --git a/shared-module/audioio/WaveFile.h b/shared-module/audiocore/WaveFile.h
index 2cee2b1d2..3eecbf15c 100644
--- a/shared-module/audioio/WaveFile.h
+++ b/shared-module/audiocore/WaveFile.h
@@ -27,9 +27,10 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_WAVEFILE_H
#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_WAVEFILE_H
+#include "extmod/vfs_fat.h"
#include "py/obj.h"
-#include "shared-module/audioio/__init__.h"
+#include "shared-module/audiocore/__init__.h"
typedef struct {
mp_obj_base_t base;
diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c
new file mode 100644
index 000000000..f9762676f
--- /dev/null
+++ b/shared-module/audiocore/__init__.c
@@ -0,0 +1,138 @@
+/*
+ * 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/audioio/__init__.h"
+
+#include "py/obj.h"
+#include "shared-bindings/audiocore/RawSample.h"
+#include "shared-bindings/audiocore/WaveFile.h"
+#include "shared-module/audiocore/RawSample.h"
+#include "shared-module/audiocore/WaveFile.h"
+
+#include "shared-bindings/audiomixer/Mixer.h"
+#include "shared-module/audiomixer/Mixer.h"
+
+uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->sample_rate;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->sample_rate;
+ #if CIRCUITPY_AUDIOMIXER
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) {
+ audiomixer_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->sample_rate;
+ #endif
+ }
+ return 16000;
+}
+
+uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->bits_per_sample;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->bits_per_sample;
+ #if CIRCUITPY_AUDIOMIXER
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) {
+ audiomixer_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->bits_per_sample;
+ #endif
+ }
+ return 8;
+}
+
+uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return sample->channel_count;
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return file->channel_count;
+ #if CIRCUITPY_AUDIOMIXER
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) {
+ audiomixer_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
+ return mixer->channel_count;
+ #endif
+ }
+ return 1;
+}
+
+void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ audioio_rawsample_reset_buffer(sample, single_channel, audio_channel);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_wavefile_reset_buffer(file, single_channel, audio_channel);
+ #if CIRCUITPY_AUDIOMIXER
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) {
+ audiomixer_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audiomixer_mixer_reset_buffer(file, single_channel, audio_channel);
+ #endif
+ }
+}
+
+audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer, uint32_t* buffer_length) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length);
+ #if CIRCUITPY_AUDIOMIXER
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) {
+ audiomixer_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ return audiomixer_mixer_get_buffer(file, single_channel, channel, buffer, buffer_length);
+ #endif
+ }
+ return GET_BUFFER_DONE;
+}
+
+void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing) {
+ if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
+ audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
+ audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer,
+ samples_signed, max_buffer_length, spacing);
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
+ audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
+ max_buffer_length, spacing);
+ #if CIRCUITPY_AUDIOMIXER
+ } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) {
+ audiomixer_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
+ audiomixer_mixer_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
+ max_buffer_length, spacing);
+ #endif
+ }
+}
diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h
new file mode 100644
index 000000000..7aa0c1824
--- /dev/null
+++ b/shared-module/audiocore/__init__.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOCORE__INIT__H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOCORE__INIT__H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "py/obj.h"
+
+typedef enum {
+ GET_BUFFER_DONE, // No more data to read
+ GET_BUFFER_MORE_DATA, // More data to read.
+ GET_BUFFER_ERROR, // Error while reading data.
+} audioio_get_buffer_result_t;
+
+uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
+uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
+uint8_t audiosample_channel_count(mp_obj_t sample_obj);
+void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel);
+audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer, uint32_t* buffer_length);
+void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOCORE__INIT__H
diff --git a/shared-module/audioio/__init__.c b/shared-module/audioio/__init__.c
index b87b06a83..e69de29bb 100644
--- a/shared-module/audioio/__init__.c
+++ b/shared-module/audioio/__init__.c
@@ -1,125 +0,0 @@
-/*
- * 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/audioio/__init__.h"
-
-#include "py/obj.h"
-#include "shared-bindings/audioio/Mixer.h"
-#include "shared-bindings/audioio/RawSample.h"
-#include "shared-bindings/audioio/WaveFile.h"
-#include "shared-module/audioio/Mixer.h"
-#include "shared-module/audioio/RawSample.h"
-#include "shared-module/audioio/WaveFile.h"
-
-uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return sample->sample_rate;
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return file->sample_rate;
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
- audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
- return mixer->sample_rate;
- }
- return 16000;
-}
-
-uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return sample->bits_per_sample;
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return file->bits_per_sample;
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
- audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
- return mixer->bits_per_sample;
- }
- return 8;
-}
-
-uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return sample->channel_count;
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return file->channel_count;
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
- audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj);
- return mixer->channel_count;
- }
- return 1;
-}
-
-void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- audioio_rawsample_reset_buffer(sample, single_channel, audio_channel);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- audioio_wavefile_reset_buffer(file, single_channel, audio_channel);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
- audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- audioio_mixer_reset_buffer(file, single_channel, audio_channel);
- }
-}
-
-audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
- bool single_channel,
- uint8_t channel,
- uint8_t** buffer, uint32_t* buffer_length) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
- audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- return audioio_mixer_get_buffer(file, single_channel, channel, buffer, buffer_length);
- }
- return GET_BUFFER_DONE;
-}
-
-void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
- bool* single_buffer, bool* samples_signed,
- uint32_t* max_buffer_length, uint8_t* spacing) {
- if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
- audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
- audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer,
- samples_signed, max_buffer_length, spacing);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) {
- audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
- max_buffer_length, spacing);
- } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) {
- audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
- audioio_mixer_get_buffer_structure(file, single_channel, single_buffer, samples_signed,
- max_buffer_length, spacing);
- }
-}
diff --git a/shared-module/audioio/__init__.h b/shared-module/audioio/__init__.h
index c805f3116..53b2d4a16 100644
--- a/shared-module/audioio/__init__.h
+++ b/shared-module/audioio/__init__.h
@@ -27,27 +27,6 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "py/obj.h"
-
-typedef enum {
- GET_BUFFER_DONE, // No more data to read
- GET_BUFFER_MORE_DATA, // More data to read.
- GET_BUFFER_ERROR, // Error while reading data.
-} audioio_get_buffer_result_t;
-
-uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
-uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
-uint8_t audiosample_channel_count(mp_obj_t sample_obj);
-void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel);
-audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
- bool single_channel,
- uint8_t channel,
- uint8_t** buffer, uint32_t* buffer_length);
-void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
- bool* single_buffer, bool* samples_signed,
- uint32_t* max_buffer_length, uint8_t* spacing);
+#include "shared-module/audiocore/__init__.h"
#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H
diff --git a/shared-module/audioio/Mixer.c b/shared-module/audiomixer/Mixer.c
index 8020a621e..a52489f85 100644
--- a/shared-module/audioio/Mixer.c
+++ b/shared-module/audiomixer/Mixer.c
@@ -4,6 +4,8 @@
* The MIT License (MIT)
*
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ * 2018 DeanM for Adafruit Industries
+ * 2019 Michael Schroeder
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,32 +26,33 @@
* THE SOFTWARE.
*/
-#include "shared-bindings/audioio/Mixer.h"
+#include "shared-bindings/audiomixer/Mixer.h"
+#include "shared-bindings/audiomixer/MixerVoice.h"
#include <stdint.h>
#include "py/runtime.h"
-#include "shared-module/audioio/__init__.h"
-#include "shared-module/audioio/RawSample.h"
-
-void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
- uint8_t voice_count,
- uint32_t buffer_size,
- uint8_t bits_per_sample,
- bool samples_signed,
- uint8_t channel_count,
- uint32_t sample_rate) {
+#include "shared-module/audiocore/__init__.h"
+#include "shared-module/audiocore/RawSample.h"
+
+void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t* self,
+ uint8_t voice_count,
+ uint32_t buffer_size,
+ uint8_t bits_per_sample,
+ bool samples_signed,
+ uint8_t channel_count,
+ uint32_t sample_rate) {
self->len = buffer_size / 2 / sizeof(uint32_t) * sizeof(uint32_t);
self->first_buffer = m_malloc(self->len, false);
if (self->first_buffer == NULL) {
- common_hal_audioio_mixer_deinit(self);
+ common_hal_audiomixer_mixer_deinit(self);
mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer"));
}
self->second_buffer = m_malloc(self->len, false);
if (self->second_buffer == NULL) {
- common_hal_audioio_mixer_deinit(self);
+ common_hal_audiomixer_mixer_deinit(self);
mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer"));
}
@@ -58,130 +61,85 @@ void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
self->channel_count = channel_count;
self->sample_rate = sample_rate;
self->voice_count = voice_count;
-
- for (uint8_t i = 0; i < self->voice_count; i++) {
- self->voice[i].sample = NULL;
- }
}
-void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self) {
+void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t* self) {
self->first_buffer = NULL;
self->second_buffer = NULL;
}
-bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self) {
+bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t* self) {
return self->first_buffer == NULL;
}
-uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self) {
+uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t* self) {
return self->sample_rate;
}
-void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t v, bool loop) {
- if (v >= self->voice_count) {
- mp_raise_ValueError(translate("Voice index too high"));
- }
- if (audiosample_sample_rate(sample) != self->sample_rate) {
- mp_raise_ValueError(translate("The sample's sample rate does not match the mixer's"));
- }
- if (audiosample_channel_count(sample) != self->channel_count) {
- mp_raise_ValueError(translate("The sample's channel count does not match the mixer's"));
- }
- if (audiosample_bits_per_sample(sample) != self->bits_per_sample) {
- mp_raise_ValueError(translate("The sample's bits_per_sample does not match the mixer's"));
- }
- bool single_buffer;
- bool samples_signed;
- uint32_t max_buffer_length;
- uint8_t spacing;
- audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed,
- &max_buffer_length, &spacing);
- if (samples_signed != self->samples_signed) {
- mp_raise_ValueError(translate("The sample's signedness does not match the mixer's"));
- }
- audioio_mixer_voice_t* voice = &self->voice[v];
- voice->sample = sample;
- voice->loop = loop;
-
- audiosample_reset_buffer(sample, false, 0);
- audioio_get_buffer_result_t result = audiosample_get_buffer(sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length);
- // Track length in terms of words.
- voice->buffer_length /= sizeof(uint32_t);
- voice->more_data = result == GET_BUFFER_MORE_DATA;
-}
-
-void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice) {
- self->voice[voice].sample = NULL;
-}
-
-bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self) {
- for (int32_t v = 0; v < self->voice_count; v++) {
- if (self->voice[v].sample != NULL) {
+bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t* self) {
+ for (uint8_t v = 0; v < self->voice_count; v++) {
+ if (common_hal_audiomixer_mixervoice_get_playing(MP_OBJ_TO_PTR(self->voice[v]))) {
return true;
}
}
return false;
}
-void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
- bool single_channel,
- uint8_t channel) {
- for (int32_t i = 0; i < self->voice_count; i++) {
- self->voice[i].sample = NULL;
+void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel) {
+ for (uint8_t i = 0; i < self->voice_count; i++) {
+ common_hal_audiomixer_mixervoice_stop(self->voice[i]);
}
}
uint32_t add8signed(uint32_t a, uint32_t b) {
- #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
- return __QADD8(a, b);
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ return __SHADD8(a, b);
#else
uint32_t result = 0;
for (int8_t i = 0; i < 4; i++) {
int8_t ai = a >> (sizeof(int8_t) * 8 * i);
int8_t bi = b >> (sizeof(int8_t) * 8 * i);
- int32_t intermediate = (int32_t) ai + bi;
+ int32_t intermediate = (int32_t) ai + bi / 2;
if (intermediate > CHAR_MAX) {
intermediate = CHAR_MAX;
} else if (intermediate < CHAR_MIN) {
- //intermediate = CHAR_MIN;
+ intermediate = CHAR_MIN;
}
- result |= (((uint32_t) intermediate) & 0xff) << (sizeof(int8_t) * 8 * i);
+ result |= ((uint32_t) intermediate & 0xff) << (sizeof(int8_t) * 8 * i);
}
return result;
#endif
}
uint32_t add8unsigned(uint32_t a, uint32_t b) {
- #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
- // Subtract out the DC offset, add and then shift back.
- a = __USUB8(a, 0x80808080);
- b = __USUB8(b, 0x80808080);
- uint32_t sum = __QADD8(a, b);
- return __UADD8(sum, 0x80808080);
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ return __UHADD8(a, b);
#else
uint32_t result = 0;
for (int8_t i = 0; i < 4; i++) {
- int8_t ai = (a >> (sizeof(uint8_t) * 8 * i)) - 128;
- int8_t bi = (b >> (sizeof(uint8_t) * 8 * i)) - 128;
- int32_t intermediate = (int32_t) ai + bi;
+ uint8_t ai = (a >> (sizeof(uint8_t) * 8 * i));
+ uint8_t bi = (b >> (sizeof(uint8_t) * 8 * i));
+ int32_t intermediate = (int32_t) (ai + bi) / 2;
if (intermediate > UCHAR_MAX) {
intermediate = UCHAR_MAX;
}
- result |= ((uint8_t) intermediate + 128) << (sizeof(uint8_t) * 8 * i);
+ result |= ((uint32_t) intermediate & 0xff) << (sizeof(uint8_t) * 8 * i);
}
return result;
#endif
}
uint32_t add16signed(uint32_t a, uint32_t b) {
- #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
- return __QADD16(a, b);
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ return __SHADD16(a, b);
#else
uint32_t result = 0;
for (int8_t i = 0; i < 2; i++) {
int16_t ai = a >> (sizeof(int16_t) * 8 * i);
int16_t bi = b >> (sizeof(int16_t) * 8 * i);
- int32_t intermediate = (int32_t) ai + bi;
+ int32_t intermediate = (int32_t) ai + bi / 2;
if (intermediate > SHRT_MAX) {
intermediate = SHRT_MAX;
} else if (intermediate < SHRT_MIN) {
@@ -194,32 +152,146 @@ uint32_t add16signed(uint32_t a, uint32_t b) {
}
uint32_t add16unsigned(uint32_t a, uint32_t b) {
- #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
- // Subtract out the DC offset, add and then shift back.
- a = __USUB16(a, 0x80008000);
- b = __USUB16(b, 0x80008000);
- uint32_t sum = __QADD16(a, b);
- return __UADD16(sum, 0x80008000);
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ return __UHADD16(a, b);
#else
uint32_t result = 0;
for (int8_t i = 0; i < 2; i++) {
int16_t ai = (a >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
int16_t bi = (b >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
- int32_t intermediate = (int32_t) ai + bi;
+ int32_t intermediate = (int32_t) ai + bi / 2;
if (intermediate > USHRT_MAX) {
intermediate = USHRT_MAX;
}
- result |= ((uint16_t) intermediate + 0x8000) << (sizeof(int16_t) * 8 * i);
+ result |= ((uint32_t) intermediate & 0xffff) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ #endif
+}
+
+static inline uint32_t mult8unsigned(uint32_t val, int32_t mul) {
+ // if mul == 0, no need in wasting cycles
+ if (mul == 0) {
+ return 0;
+ }
+ /* TODO: workout ARMv7 instructions
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ return val;
+ #else*/
+ uint32_t result = 0;
+ float mod_mul = (float) mul / (float) ((1<<15)-1);
+ for (int8_t i = 0; i < 4; i++) {
+ uint8_t ai = val >> (sizeof(uint8_t) * 8 * i);
+ int32_t intermediate = ai * mod_mul;
+ if (intermediate > SHRT_MAX) {
+ intermediate = SHRT_MAX;
+ }
+ result |= ((uint32_t) intermediate & 0xff) << (sizeof(uint8_t) * 8 * i);
+ }
+
+ return result;
+ //#endif
+}
+
+static inline uint32_t mult8signed(uint32_t val, int32_t mul) {
+ // if mul == 0, no need in wasting cycles
+ if (mul == 0) {
+ return 0;
+ }
+ /* TODO: workout ARMv7 instructions
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ return val;
+ #else
+ */
+ uint32_t result = 0;
+ float mod_mul = (float)mul / (float)((1<<15)-1);
+ for (int8_t i = 0; i < 4; i++) {
+ int16_t ai = val >> (sizeof(int8_t) * 8 * i);
+ int32_t intermediate = ai * mod_mul;
+ if (intermediate > CHAR_MAX) {
+ intermediate = CHAR_MAX;
+ } else if (intermediate < CHAR_MIN) {
+ intermediate = CHAR_MIN;
+ }
+ result |= (((uint32_t) intermediate) & 0xff) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ //#endif
+}
+
+//TODO:
+static inline uint32_t mult16unsigned(uint32_t val, int32_t mul) {
+ // if mul == 0, no need in wasting cycles
+ if (mul == 0) {
+ return 0;
+ }
+ /* TODO: the below ARMv7m instructions "work", but the amplitude is much higher/louder
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ // there is no unsigned equivalent to the 'SMULWx' ARMv7 Thumb function,
+ // so we have to do it by hand.
+ uint32_t lo = val & 0xffff;
+ uint32_t hi = val >> 16;
+ //mp_printf(&mp_plat_print, "pre-asm: (mul: %d)\n\tval: %x\tlo: %x\thi: %x\n", mul, val, lo, hi);
+ uint32_t val_lo;
+ asm volatile("mul %0, %1, %2" : "=r" (val_lo) : "r" (mul), "r" (lo));
+ asm volatile("mla %0, %1, %2, %3" : "=r" (val) : "r" (mul), "r" (hi), "r" (val_lo));
+ //mp_printf(&mp_plat_print, "post-asm:\n\tval: %x\tlo: %x\n\n", val, val_lo);
+ return val;
+ #else
+ */
+ uint32_t result = 0;
+ float mod_mul = (float)mul / (float)((1<<15)-1);
+ for (int8_t i = 0; i < 2; i++) {
+ int16_t ai = (val >> (sizeof(uint16_t) * 8 * i)) - 0x8000;
+ int32_t intermediate = ai * mod_mul;
+ if (intermediate > SHRT_MAX) {
+ intermediate = SHRT_MAX;
+ } else if (intermediate < SHRT_MIN) {
+ intermediate = SHRT_MIN;
+ }
+ result |= (((uint32_t) intermediate) + 0x8000) << (sizeof(int16_t) * 8 * i);
+ }
+ return result;
+ //#endif
+}
+
+static inline uint32_t mult16signed(uint32_t val, int32_t mul) {
+ // if mul == 0, no need in wasting cycles
+ if (mul == 0) {
+ return 0;
+ }
+ #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU
+ int32_t hi, lo;
+ enum { bits = 16 }; // saturate to 16 bits
+ enum { shift = 0 }; // shift is done automatically
+ asm volatile("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul), "r" (val));
+ asm volatile("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul), "r" (val));
+ asm volatile("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift));
+ asm volatile("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift));
+ asm volatile("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack
+ return val;
+ #else
+ uint32_t result = 0;
+ float mod_mul = (float)mul / (float)((1<<15)-1);
+ for (int8_t i = 0; i < 2; i++) {
+ int16_t ai = val >> (sizeof(int16_t) * 8 * i);
+ int32_t intermediate = ai * mod_mul;
+ if (intermediate > SHRT_MAX) {
+ intermediate = SHRT_MAX;
+ } else if (intermediate < SHRT_MIN) {
+ intermediate = SHRT_MIN;
+ }
+ result |= (((uint32_t) intermediate) & 0xffff) << (sizeof(int16_t) * 8 * i);
}
return result;
#endif
}
-audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
- bool single_channel,
- uint8_t channel,
- uint8_t** buffer,
- uint32_t* buffer_length) {
+audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer,
+ uint32_t* buffer_length) {
if (!single_channel) {
channel = 0;
}
@@ -243,7 +315,7 @@ audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
self->use_first_buffer = !self->use_first_buffer;
bool voices_active = false;
for (int32_t v = 0; v < self->voice_count; v++) {
- audioio_mixer_voice_t* voice = &self->voice[v];
+ audiomixer_mixervoice_obj_t* voice = MP_OBJ_TO_PTR(self->voice[v]);
uint32_t j = 0;
bool voice_done = voice->sample == NULL;
@@ -285,6 +357,21 @@ audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
sample_value = voice->remaining_buffer[j];
}
+ // apply the mixer level
+ if (!self->samples_signed) {
+ if (self->bits_per_sample == 8) {
+ sample_value = mult8unsigned(sample_value, voice->level);
+ } else {
+ sample_value = mult16unsigned(sample_value, voice->level);
+ }
+ } else {
+ if (self->bits_per_sample == 8) {
+ sample_value = mult8signed(sample_value, voice->level);
+ } else {
+ sample_value = mult16signed(sample_value, voice->level);
+ }
+ }
+
if (!voices_active) {
word_buffer[i] = sample_value;
} else {
@@ -327,7 +414,7 @@ audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
return GET_BUFFER_MORE_DATA;
}
-void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel,
+void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t* self, bool single_channel,
bool* single_buffer, bool* samples_signed,
uint32_t* max_buffer_length, uint8_t* spacing) {
*single_buffer = false;
diff --git a/shared-module/audioio/Mixer.h b/shared-module/audiomixer/Mixer.h
index 6a88fe0bd..ab4780efc 100644
--- a/shared-module/audioio/Mixer.h
+++ b/shared-module/audiomixer/Mixer.h
@@ -24,20 +24,13 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
-#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOMIXER_MIXER_H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOMIXER_MIXER_H
#include "py/obj.h"
+#include "py/objtuple.h"
-#include "shared-module/audioio/__init__.h"
-
-typedef struct {
- mp_obj_t sample;
- bool loop;
- bool more_data;
- uint32_t* remaining_buffer;
- uint32_t buffer_length;
-} audioio_mixer_voice_t;
+#include "shared-module/audiocore/__init__.h"
typedef struct {
mp_obj_base_t base;
@@ -55,21 +48,22 @@ typedef struct {
uint32_t right_read_count;
uint8_t voice_count;
- audioio_mixer_voice_t voice[];
-} audioio_mixer_obj_t;
+ mp_obj_tuple_t *voice_tuple;
+ mp_obj_t voice[];
+} audiomixer_mixer_obj_t;
// These are not available from Python because it may be called in an interrupt.
-void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
+void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t* self,
bool single_channel,
uint8_t channel);
-audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
+audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* self,
bool single_channel,
uint8_t channel,
uint8_t** buffer,
uint32_t* buffer_length); // length in bytes
-void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel,
+void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t* self, bool single_channel,
bool* single_buffer, bool* samples_signed,
uint32_t* max_buffer_length, uint8_t* spacing);
-#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOMIXER_MIXER_H
diff --git a/shared-module/audiomixer/MixerVoice.c b/shared-module/audiomixer/MixerVoice.c
new file mode 100644
index 000000000..ff05dc93e
--- /dev/null
+++ b/shared-module/audiomixer/MixerVoice.c
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 DeanM 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/audiomixer/Mixer.h"
+#include "shared-module/audiomixer/MixerVoice.h"
+
+#include <stdint.h>
+
+#include "py/runtime.h"
+#include "shared-module/audiomixer/__init__.h"
+#include "shared-module/audiocore/RawSample.h"
+
+void common_hal_audiomixer_mixervoice_construct(audiomixer_mixervoice_obj_t *self) {
+ self->sample = NULL;
+ self->level = ((1 << 15) - 1);
+}
+
+void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t* self, audiomixer_mixer_obj_t *parent) {
+ self->parent = parent;
+}
+
+float common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t* self) {
+ return ((float) self->level / ((1 << 15) - 1));
+}
+
+void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t* self, float level) {
+ self->level = level * ((1 << 15)-1);
+}
+
+void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t* self, mp_obj_t sample, bool loop) {
+ if (audiosample_sample_rate(sample) != self->parent->sample_rate) {
+ mp_raise_ValueError(translate("The sample's sample rate does not match the mixer's"));
+ }
+ if (audiosample_channel_count(sample) != self->parent->channel_count) {
+ mp_raise_ValueError(translate("The sample's channel count does not match the mixer's"));
+ }
+ if (audiosample_bits_per_sample(sample) != self->parent->bits_per_sample) {
+ mp_raise_ValueError(translate("The sample's bits_per_sample does not match the mixer's"));
+ }
+ bool single_buffer;
+ bool samples_signed;
+ uint32_t max_buffer_length;
+ uint8_t spacing;
+ audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed,
+ &max_buffer_length, &spacing);
+ if (samples_signed != self->parent->samples_signed) {
+ mp_raise_ValueError(translate("The sample's signedness does not match the mixer's"));
+ }
+ self->sample = sample;
+ self->loop = loop;
+
+ audiosample_reset_buffer(sample, false, 0);
+ audioio_get_buffer_result_t result = audiosample_get_buffer(sample, false, 0, (uint8_t**) &self->remaining_buffer, &self->buffer_length);
+ // Track length in terms of words.
+ self->buffer_length /= sizeof(uint32_t);
+ self->more_data = result == GET_BUFFER_MORE_DATA;
+}
+
+bool common_hal_audiomixer_mixervoice_get_playing(audiomixer_mixervoice_obj_t* self) {
+ return self->sample != NULL;
+}
+
+void common_hal_audiomixer_mixervoice_stop(audiomixer_mixervoice_obj_t* self) {
+ self->sample = NULL;
+}
diff --git a/shared-module/audiomixer/MixerVoice.h b/shared-module/audiomixer/MixerVoice.h
new file mode 100644
index 000000000..efac19156
--- /dev/null
+++ b/shared-module/audiomixer/MixerVoice.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 DeanM 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_AUDIOMIXER_MIXERVOICE_H_
+#define SHARED_MODULE_AUDIOMIXER_MIXERVOICE_H_
+
+#include "py/obj.h"
+
+#include "shared-module/audiomixer/__init__.h"
+#include "shared-module/audiomixer/Mixer.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ audiomixer_mixer_obj_t *parent;
+ mp_obj_t sample;
+ bool loop;
+ bool more_data;
+ uint32_t* remaining_buffer;
+ uint32_t buffer_length;
+ int16_t level;
+} audiomixer_mixervoice_obj_t;
+
+
+#endif /* SHARED_MODULE_AUDIOMIXER_MIXERVOICE_H_ */
diff --git a/shared-module/audiomixer/__init__.c b/shared-module/audiomixer/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/audiomixer/__init__.c
diff --git a/shared-module/bleio/__init__.h b/shared-module/audiomixer/__init__.h
index 07d148594..35b731558 100644
--- a/shared-module/bleio/__init__.h
+++ b/shared-module/audiomixer/__init__.h
@@ -24,15 +24,9 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
-#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOMIXER__INIT__H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOMIXER__INIT__H
-typedef enum {
- GATT_ROLE_NONE,
- GATT_ROLE_SERVER,
- GATT_ROLE_CLIENT,
-} gatt_role_t;
+#include "shared-module/audiocore/__init__.h"
-extern void bleio_reset(void);
-
-#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOMIXER__INIT__H
diff --git a/shared-module/audiopwmio/__init__.c b/shared-module/audiopwmio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/audiopwmio/__init__.c
diff --git a/shared-module/audiopwmio/__init__.h b/shared-module/audiopwmio/__init__.h
new file mode 100644
index 000000000..964e4aafe
--- /dev/null
+++ b/shared-module/audiopwmio/__init__.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H
+
+#include "shared-module/audiocore/__init__.h"
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOPWMIO__INIT__H
diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c
index be8502bc0..dd07d7190 100644
--- a/shared-module/board/__init__.c
+++ b/shared-module/board/__init__.c
@@ -24,31 +24,41 @@
* THE SOFTWARE.
*/
-#include "shared-bindings/busio/I2C.h"
-#include "shared-bindings/busio/SPI.h"
-#include "shared-bindings/busio/UART.h"
-
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/translate.h"
#include "mpconfigboard.h"
#include "py/runtime.h"
-#ifdef CIRCUITPY_DISPLAYIO
+#if CIRCUITPY_BUSIO
+#include "shared-bindings/busio/I2C.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/busio/UART.h"
+#endif
+
+#if CIRCUITPY_DISPLAYIO
#include "shared-module/displayio/__init__.h"
#endif
#if BOARD_I2C
+// Statically allocate the I2C object so it can live past the end of the heap and into the next VM.
+// That way it can be used by built-in I2CDisplay displays and be accessible through board.I2C().
+STATIC busio_i2c_obj_t i2c_obj;
+STATIC mp_obj_t i2c_singleton = NULL;
+
mp_obj_t common_hal_board_get_i2c(void) {
- return MP_STATE_VM(shared_i2c_bus);
+ return i2c_singleton;
}
mp_obj_t common_hal_board_create_i2c(void) {
- busio_i2c_obj_t *self = m_new_ll_obj(busio_i2c_obj_t);
+ if (i2c_singleton != NULL) {
+ return i2c_singleton;
+ }
+ busio_i2c_obj_t *self = &i2c_obj;
self->base.type = &busio_i2c_type;
common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 0);
- MP_STATE_VM(shared_i2c_bus) = MP_OBJ_FROM_PTR(self);
- return MP_STATE_VM(shared_i2c_bus);
+ i2c_singleton = (mp_obj_t)self;
+ return i2c_singleton;
}
#endif
@@ -99,7 +109,18 @@ mp_obj_t common_hal_board_create_uart(void) {
void reset_board_busses(void) {
#if BOARD_I2C
- MP_STATE_VM(shared_i2c_bus) = NULL;
+ bool display_using_i2c = false;
+ #if CIRCUITPY_DISPLAYIO
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].i2cdisplay_bus.bus == i2c_singleton) {
+ display_using_i2c = true;
+ break;
+ }
+ }
+ #endif
+ if (!display_using_i2c) {
+ i2c_singleton = NULL;
+ }
#endif
#if BOARD_SPI
bool display_using_spi = false;
diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c
index f8dc24c15..59971d25c 100644
--- a/shared-module/displayio/Bitmap.c
+++ b/shared-module/displayio/Bitmap.c
@@ -63,6 +63,11 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi
}
self->x_mask = (1 << self->x_shift) - 1; // Used as a modulus on the x value
self->bitmask = (1 << bits_per_value) - 1;
+
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = width;
+ self->dirty_area.y1 = 0;
+ self->dirty_area.y2 = height;
}
uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self) {
@@ -104,6 +109,26 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x,
if (self->read_only) {
mp_raise_RuntimeError(translate("Read-only object"));
}
+ // Update the dirty area.
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ self->dirty_area.x1 = x;
+ self->dirty_area.x2 = x + 1;
+ self->dirty_area.y1 = y;
+ self->dirty_area.y2 = y + 1;
+ } else {
+ if (x < self->dirty_area.x1) {
+ self->dirty_area.x1 = x;
+ } else if (x >= self->dirty_area.x2) {
+ self->dirty_area.x2 = x + 1;
+ }
+ if (y < self->dirty_area.y1) {
+ self->dirty_area.y1 = y;
+ } else if (y >= self->dirty_area.y2) {
+ self->dirty_area.y2 = y + 1;
+ }
+ }
+
+ // Update our data
int32_t row_start = y * self->stride;
uint32_t bytes_per_value = self->bits_per_value / 8;
if (bytes_per_value < 1) {
@@ -124,3 +149,16 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x,
}
}
}
+
+displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail) {
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ return tail;
+ }
+ self->dirty_area.next = tail;
+ return &self->dirty_area;
+}
+
+void displayio_bitmap_finish_refresh(displayio_bitmap_t *self) {
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = 0;
+}
diff --git a/shared-module/displayio/Bitmap.h b/shared-module/displayio/Bitmap.h
index 48ca9e2cf..f4bd7ce4d 100644
--- a/shared-module/displayio/Bitmap.h
+++ b/shared-module/displayio/Bitmap.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include "py/obj.h"
+#include "shared-module/displayio/area.h"
typedef struct {
mp_obj_base_t base;
@@ -41,8 +42,12 @@ typedef struct {
uint8_t bits_per_value;
uint8_t x_shift;
size_t x_mask;
+ displayio_area_t dirty_area;
uint16_t bitmask;
bool read_only;
} displayio_bitmap_t;
+void displayio_bitmap_finish_refresh(displayio_bitmap_t *self);
+displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H
diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c
index 3928e115a..a5d7f0b05 100644
--- a/shared-module/displayio/ColorConverter.c
+++ b/shared-module/displayio/ColorConverter.c
@@ -26,20 +26,163 @@
#include "shared-bindings/displayio/ColorConverter.h"
-void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t* self) {
+#include "py/misc.h"
+
+uint32_t displayio_colorconverter_dither_noise_1 (uint32_t n)
+{
+ n = (n >> 13) ^ n;
+ int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+ return (uint32_t) (((float)nn / (1073741824.0f*2)) * 255);
+}
+
+uint32_t displayio_colorconverter_dither_noise_2(uint32_t x, uint32_t y) {
+ return displayio_colorconverter_dither_noise_1(x + y * 0xFFFF);
+}
+
+void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t* self, bool dither) {
+ self->dither = dither;
}
-bool common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *self, uint32_t input_color, uint16_t* output_color) {
- // TODO(tannewt): Validate the color input against the input format.
- uint32_t r5 = (input_color >> 19);
- uint32_t g6 = (input_color >> 10) & 0x3f;
- uint32_t b5 = (input_color >> 3) & 0x1f;
+uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888) {
+ uint32_t r5 = (color_rgb888 >> 19);
+ uint32_t g6 = (color_rgb888 >> 10) & 0x3f;
+ uint32_t b5 = (color_rgb888 >> 3) & 0x1f;
uint32_t packed = r5 << 11 | g6 << 5 | b5;
// swap bytes
- *output_color = __builtin_bswap16(packed);
- return true;
+ return __builtin_bswap16(packed);
+}
+
+uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888) {
+ uint32_t r8 = (color_rgb888 >> 16);
+ uint32_t g8 = (color_rgb888 >> 8) & 0xff;
+ uint32_t b8 = color_rgb888 & 0xff;
+ return (r8 * 19) / 255 + (g8 * 182) / 255 + (b8 + 54) / 255;
+}
+
+uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888) {
+ uint32_t r8 = (color_rgb888 >> 16);
+ uint32_t g8 = (color_rgb888 >> 8) & 0xff;
+ uint32_t b8 = color_rgb888 & 0xff;
+ uint8_t max = MAX(r8, MAX(g8, b8));
+ uint8_t min = MIN(r8, MIN(g8, b8));
+ return max - min;
+}
+
+uint8_t displayio_colorconverter_compute_hue(uint32_t color_rgb888) {
+ uint32_t r8 = (color_rgb888 >> 16);
+ uint32_t g8 = (color_rgb888 >> 8) & 0xff;
+ uint32_t b8 = color_rgb888 & 0xff;
+ uint8_t max = MAX(r8, MAX(g8, b8));
+ uint8_t min = MIN(r8, MIN(g8, b8));
+ uint8_t c = max - min;
+ if (c == 0) {
+ return 0;
+ }
+
+ int32_t hue = 0;
+ if (max == r8) {
+ hue = (((int32_t) (g8 - b8) * 40) / c) % 240;
+ } else if (max == g8) {
+ hue = (((int32_t) (b8 - r8) + (2 * c)) * 40) / c;
+ } else if (max == b8) {
+ hue = (((int32_t) (r8 - g8) + (4 * c)) * 40) / c;
+ }
+ if (hue < 0) {
+ hue += 240;
+ }
+
+ return hue;
+}
+
+void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t* colorspace, uint8_t pixel_hue, uint8_t pixel_luma, uint32_t* color) {
+
+ int16_t hue_diff = colorspace->tricolor_hue - pixel_hue;
+ if ((-10 <= hue_diff && hue_diff <= 10) || hue_diff <= -220 || hue_diff >= 220) {
+ if (colorspace->grayscale) {
+ *color = 0;
+ } else {
+ *color = 1;
+ }
+ } else if (!colorspace->grayscale) {
+ *color = 0;
+ }
}
+void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t* colorspace, uint32_t input_color, uint32_t* output_color) {
+ displayio_input_pixel_t input_pixel;
+ input_pixel.pixel = input_color;
+ input_pixel.x = input_pixel.y = input_pixel.tile = input_pixel.tile_x = input_pixel.tile_y = 0;
+
+ displayio_output_pixel_t output_pixel;
+ output_pixel.pixel = 0;
+ output_pixel.opaque = false;
+
+ displayio_colorconverter_convert(self, colorspace, &input_pixel, &output_pixel);
+
+ (*output_color) = output_pixel.pixel;
+}
+
+void common_hal_displayio_colorconverter_set_dither(displayio_colorconverter_t* self, bool dither) {
+ self->dither = dither;
+}
+
+bool common_hal_displayio_colorconverter_get_dither(displayio_colorconverter_t* self) {
+ return self->dither;
+}
+
+void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t* colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) {
+ uint32_t pixel = input_pixel->pixel;
+
+ if (self->dither){
+ uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y));
+ uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x+33,input_pixel->tile_y));
+ uint8_t randb = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y+33));
+
+ uint32_t r8 = (pixel >> 16);
+ uint32_t g8 = (pixel >> 8) & 0xff;
+ uint32_t b8 = pixel & 0xff;
+
+ if (colorspace->depth == 16) {
+ b8 = MIN(255,b8 + (randb&0x07));
+ r8 = MIN(255,r8 + (randr&0x07));
+ g8 = MIN(255,g8 + (randg&0x03));
+ } else {
+ int bitmask = 0xFF >> colorspace->depth;
+ b8 = MIN(255,b8 + (randb&bitmask));
+ r8 = MIN(255,r8 + (randr&bitmask));
+ g8 = MIN(255,g8 + (randg&bitmask));
+ }
+ pixel = r8 << 16 | g8 << 8 | b8;
+ }
+
+ if (colorspace->depth == 16) {
+ output_color->pixel = displayio_colorconverter_compute_rgb565(pixel);
+ output_color->opaque = true;
+ return;
+ } else if (colorspace->tricolor) {
+ uint8_t luma = displayio_colorconverter_compute_luma(pixel);
+ output_color->pixel = luma >> (8 - colorspace->depth);
+ if (displayio_colorconverter_compute_chroma(pixel) <= 16) {
+ if (!colorspace->grayscale) {
+ output_color->pixel = 0;
+ }
+ output_color->opaque = true;
+ return;
+ }
+ uint8_t pixel_hue = displayio_colorconverter_compute_hue(pixel);
+ displayio_colorconverter_compute_tricolor(colorspace, pixel_hue, luma, &output_color->pixel);
+ return;
+ } else if (colorspace->grayscale && colorspace->depth <= 8) {
+ uint8_t luma = displayio_colorconverter_compute_luma(pixel);
+ output_color->pixel = luma >> (8 - colorspace->depth);
+ output_color->opaque = true;
+ return;
+ }
+ output_color->opaque = false;
+}
+
+
+
// Currently no refresh logic is needed for a ColorConverter.
bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self) {
return false;
@@ -47,3 +190,4 @@ bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self) {
void displayio_colorconverter_finish_refresh(displayio_colorconverter_t *self) {
}
+
diff --git a/shared-module/displayio/ColorConverter.h b/shared-module/displayio/ColorConverter.h
index 7f3c1a0a0..10b1604a4 100644
--- a/shared-module/displayio/ColorConverter.h
+++ b/shared-module/displayio/ColorConverter.h
@@ -31,12 +31,24 @@
#include <stdint.h>
#include "py/obj.h"
+#include "shared-module/displayio/Palette.h"
typedef struct {
mp_obj_base_t base;
+ bool dither;
} displayio_colorconverter_t;
bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self);
void displayio_colorconverter_finish_refresh(displayio_colorconverter_t *self);
+void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t* colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color);
+
+uint32_t displayio_colorconverter_dither_noise_1 (uint32_t n);
+uint32_t displayio_colorconverter_dither_noise_2(uint32_t x, uint32_t y);
+
+uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888);
+uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888);
+uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888);
+uint8_t displayio_colorconverter_compute_hue(uint32_t color_rgb888);
+void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t* colorspace, uint8_t pixel_hue, uint8_t pixel_luma, uint32_t* color);
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_COLORCONVERTER_H
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index 0ae88300a..06b81f2f8 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -28,70 +28,70 @@
#include "py/runtime.h"
#include "shared-bindings/displayio/FourWire.h"
+#include "shared-bindings/displayio/I2CDisplay.h"
#include "shared-bindings/displayio/ParallelBus.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/time/__init__.h"
#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/display_core.h"
#include "supervisor/shared/display.h"
+#include "supervisor/usb.h"
#include <stdint.h>
+#include <string.h>
#include "tick.h"
-#define DELAY 0x80
-
void common_hal_displayio_display_construct(displayio_display_obj_t* self,
- mp_obj_t bus, uint16_t width, uint16_t height, int16_t colstart, int16_t rowstart, uint16_t rotation,
- uint16_t color_depth, uint8_t set_column_command, uint8_t set_row_command,
- uint8_t write_ram_command, uint8_t set_vertical_scroll, uint8_t* init_sequence, uint16_t init_sequence_len,
- const mcu_pin_obj_t* backlight_pin, mp_float_t brightness, bool auto_brightness,
- bool single_byte_bounds, bool data_as_commands) {
- self->color_depth = color_depth;
+ mp_obj_t bus, uint16_t width, uint16_t height, int16_t colstart, int16_t rowstart,
+ uint16_t rotation, uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row,
+ uint8_t bytes_per_cell, bool reverse_pixels_in_byte, uint8_t set_column_command,
+ uint8_t set_row_command, uint8_t write_ram_command, uint8_t set_vertical_scroll,
+ uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin,
+ uint16_t brightness_command, mp_float_t brightness, bool auto_brightness,
+ bool single_byte_bounds, bool data_as_commands, bool auto_refresh, uint16_t native_frames_per_second) {
+ // Turn off auto-refresh as we init.
+ self->auto_refresh = false;
+ uint16_t ram_width = 0x100;
+ uint16_t ram_height = 0x100;
+ if (single_byte_bounds) {
+ ram_width = 0xff;
+ ram_height = 0xff;
+ }
+ displayio_display_core_construct(&self->core, bus, width, height, ram_width, ram_height, colstart, rowstart, rotation,
+ color_depth, grayscale, pixels_in_byte_share_row, bytes_per_cell, reverse_pixels_in_byte);
+
self->set_column_command = set_column_command;
self->set_row_command = set_row_command;
self->write_ram_command = write_ram_command;
- self->refresh = false;
- self->current_group = NULL;
- self->colstart = colstart;
- self->rowstart = rowstart;
+ self->brightness_command = brightness_command;
self->auto_brightness = auto_brightness;
+ self->first_manual_refresh = !auto_refresh;
self->data_as_commands = data_as_commands;
- self->single_byte_bounds = single_byte_bounds;
-
- if (MP_OBJ_IS_TYPE(bus, &displayio_parallelbus_type)) {
- self->begin_transaction = common_hal_displayio_parallelbus_begin_transaction;
- self->send = common_hal_displayio_parallelbus_send;
- self->end_transaction = common_hal_displayio_parallelbus_end_transaction;
- } else if (MP_OBJ_IS_TYPE(bus, &displayio_fourwire_type)) {
- self->begin_transaction = common_hal_displayio_fourwire_begin_transaction;
- self->send = common_hal_displayio_fourwire_send;
- self->end_transaction = common_hal_displayio_fourwire_end_transaction;
- } else {
- mp_raise_ValueError(translate("Unsupported display bus type"));
- }
- self->bus = bus;
+
+ self->native_frames_per_second = native_frames_per_second;
+ self->native_ms_per_frame = 1000 / native_frames_per_second;
uint32_t i = 0;
- while (!self->begin_transaction(self->bus)) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
-#endif
- }
while (i < init_sequence_len) {
uint8_t *cmd = init_sequence + i;
uint8_t data_size = *(cmd + 1);
bool delay = (data_size & DELAY) != 0;
data_size &= ~DELAY;
uint8_t *data = cmd + 2;
- self->send(self->bus, true, cmd, 1);
+ while (!displayio_display_core_begin_transaction(&self->core)) {
+ RUN_BACKGROUND_TASKS;
+ }
if (self->data_as_commands) {
- // Loop through each parameter to force a CS toggle
- for (uint32_t j=0; j < data_size; j++) {
- self->send(self->bus, true, data + j, 1);
- }
+ uint8_t full_command[data_size + 1];
+ full_command[0] = cmd[0];
+ memcpy(full_command + 1, data, data_size);
+ self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, full_command, data_size + 1);
} else {
- self->send(self->bus, false, data, data_size);
+ self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, cmd, 1);
+ self->core.send(self->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, data, data_size);
}
+ displayio_display_core_end_transaction(&self->core);
uint16_t delay_length_ms = 10;
if (delay) {
data_size++;
@@ -103,33 +103,9 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
common_hal_time_delay_ms(delay_length_ms);
i += 2 + data_size;
}
- self->end_transaction(self->bus);
supervisor_start_terminal(width, height);
- self->width = width;
- self->height = height;
- rotation = rotation % 360;
- self->transform.x = 0;
- self->transform.y = 0;
- self->transform.scale = 1;
- self->transform.mirror_x = false;
- self->transform.mirror_y = false;
- self->transform.transpose_xy = false;
- if (rotation == 0 || rotation == 180) {
- if (rotation == 180) {
- self->transform.mirror_x = true;
- self->transform.mirror_y = true;
- }
- } else {
- self->transform.transpose_xy = true;
- if (rotation == 270) {
- self->transform.mirror_y = true;
- } else {
- self->transform.mirror_x = true;
- }
- }
-
// Always set the backlight type in case we're reusing memory.
self->backlight_inout.base.type = &mp_type_NoneType;
if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) {
@@ -141,110 +117,43 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
} else {
self->backlight_pwm.base.type = &pulseio_pwmout_type;
common_hal_pulseio_pwmout_never_reset(&self->backlight_pwm);
- if (!self->auto_brightness) {
- common_hal_displayio_display_set_brightness(self, brightness);
- }
}
}
-
- self->area.x1 = 0;
- self->area.y1 = 0;
- self->area.next = NULL;
-
- self->transform.dx = 1;
- self->transform.dy = 1;
- if (self->transform.transpose_xy) {
- self->area.x2 = height;
- self->area.y2 = width;
- if (self->transform.mirror_x) {
- self->transform.x = height;
- self->transform.dx = -1;
- }
- if (self->transform.mirror_y) {
- self->transform.y = width;
- self->transform.dy = -1;
- }
+ if (!self->auto_brightness && (self->backlight_inout.base.type != &mp_type_NoneType ||
+ brightness_command != NO_BRIGHTNESS_COMMAND)) {
+ common_hal_displayio_display_set_brightness(self, brightness);
} else {
- self->area.x2 = width;
- self->area.y2 = height;
- if (self->transform.mirror_x) {
- self->transform.x = width;
- self->transform.dx = -1;
- }
- if (self->transform.mirror_y) {
- self->transform.y = height;
- self->transform.dy = -1;
- }
+ self->current_brightness = -1.0;
}
// Set the group after initialization otherwise we may send pixels while we delay in
// initialization.
common_hal_displayio_display_show(self, &circuitpython_splash);
+ self->auto_refresh = auto_refresh;
}
-void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
- if (root_group == NULL) {
- root_group = &circuitpython_splash;
- }
- if (root_group == self->current_group) {
- return;
- }
- displayio_group_update_transform(root_group, &self->transform);
- self->current_group = root_group;
- self->full_refresh = true;
- common_hal_displayio_display_refresh_soon(self);
-}
-
-void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self) {
- self->refresh = true;
+bool common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
+ return displayio_display_core_show(&self->core, root_group);
}
-const displayio_area_t* displayio_display_get_refresh_areas(displayio_display_obj_t *self) {
- if (self->full_refresh) {
- self->area.next = NULL;
- return &self->area;
- } else {
- return displayio_group_get_refresh_areas(self->current_group, NULL);
- }
+uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self){
+ return displayio_display_core_get_width(&self->core);
}
-int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self) {
- uint64_t last_refresh = self->last_refresh;
- // Don't try to refresh if we got an exception.
- while (last_refresh == self->last_refresh && MP_STATE_VM(mp_pending_exception) == NULL) {
- MICROPY_VM_HOOK_LOOP
- }
- return 0;
+uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self){
+ return displayio_display_core_get_height(&self->core);
}
bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self) {
return self->auto_brightness;
}
-uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self){
- return self->width;
-}
-
-uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self){
- return self->height;
-}
-
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness) {
self->auto_brightness = auto_brightness;
}
mp_float_t common_hal_displayio_display_get_brightness(displayio_display_obj_t* self) {
- if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
- uint16_t duty_cycle = common_hal_pulseio_pwmout_get_duty_cycle(&self->backlight_pwm);
- return duty_cycle / ((mp_float_t) 0xffff);
- } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
- if (common_hal_digitalio_digitalinout_get_value(&self->backlight_inout)) {
- return 1.0;
- } else {
- return 0.0;
- }
- }
- return -1.0;
+ return self->current_brightness;
}
bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self, mp_float_t brightness) {
@@ -256,76 +165,188 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self,
} else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
common_hal_digitalio_digitalinout_set_value(&self->backlight_inout, brightness > 0.99);
ok = true;
+ } else if (self->brightness_command != NO_BRIGHTNESS_COMMAND) {
+ ok = displayio_display_core_begin_transaction(&self->core);
+ if (ok) {
+ if (self->data_as_commands) {
+ uint8_t set_brightness[2] = {self->brightness_command, (uint8_t) (0xff * brightness)};
+ self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, set_brightness, 2);
+ } else {
+ uint8_t command = self->brightness_command;
+ uint8_t hex_brightness = 0xff * brightness;
+ self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, &command, 1);
+ self->core.send(self->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, &hex_brightness, 1);
+ }
+ displayio_display_core_end_transaction(&self->core);
+ }
+
}
self->updating_backlight = false;
+ if (ok) {
+ self->current_brightness = brightness;
+ }
return ok;
}
-bool displayio_display_begin_transaction(displayio_display_obj_t* self) {
- return self->begin_transaction(self->bus);
+mp_obj_t common_hal_displayio_display_get_bus(displayio_display_obj_t* self) {
+ return self->core.bus;
}
-void displayio_display_end_transaction(displayio_display_obj_t* self) {
- self->end_transaction(self->bus);
+STATIC const displayio_area_t* _get_refresh_areas(displayio_display_obj_t *self) {
+ if (self->core.full_refresh) {
+ self->core.area.next = NULL;
+ return &self->core.area;
+ } else if (self->core.current_group != NULL) {
+ return displayio_group_get_refresh_areas(self->core.current_group, NULL);
+ }
+ return NULL;
}
-void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
- self->send(self->bus, true, &self->set_column_command, 1);
- bool isCommand = self->data_as_commands;
- if (self->single_byte_bounds) {
- uint8_t data[2];
- data[0] = x0 + self->colstart;
- data[1] = x1 - 1 + self->colstart;
- self->send(self->bus, isCommand, (uint8_t*) data, 2);
- } else {
- uint16_t data[2];
- data[0] = __builtin_bswap16(x0 + self->colstart);
- data[1] = __builtin_bswap16(x1 - 1 + self->colstart);
- self->send(self->bus, isCommand, (uint8_t*) data, 4);
- }
- self->send(self->bus, true, &self->set_row_command, 1);
- if (self->single_byte_bounds) {
- uint8_t data[2];
- data[0] = y0 + self->rowstart;
- data[1] = y1 - 1 + self->rowstart;
- self->send(self->bus, isCommand, (uint8_t*) data, 2);
- } else {
- uint16_t data[2];
- data[0] = __builtin_bswap16(y0 + self->rowstart);
- data[1] = __builtin_bswap16(y1 - 1 + self->rowstart);
- self->send(self->bus, isCommand, (uint8_t*) data, 4);
- }
+STATIC void _send_pixels(displayio_display_obj_t* self, uint8_t* pixels, uint32_t length) {
if (!self->data_as_commands) {
- self->send(self->bus, true, &self->write_ram_command, 1);
+ self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, &self->write_ram_command, 1);
}
+ self->core.send(self->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, pixels, length);
}
-void displayio_display_start_refresh(displayio_display_obj_t* self) {
- self->last_refresh = ticks_ms;
+STATIC bool _refresh_area(displayio_display_obj_t* self, const displayio_area_t* area) {
+ uint16_t buffer_size = 128; // In uint32_ts
+
+ displayio_area_t clipped;
+ // Clip the area to the display by overlapping the areas. If there is no overlap then we're done.
+ if (!displayio_display_core_clip_area(&self->core, area, &clipped)) {
+ return true;
+ }
+ uint16_t subrectangles = 1;
+ uint16_t rows_per_buffer = displayio_area_height(&clipped);
+ uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth;
+ uint16_t pixels_per_buffer = displayio_area_size(&clipped);
+ if (displayio_area_size(&clipped) > buffer_size * pixels_per_word) {
+ rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width(&clipped);
+ if (rows_per_buffer == 0) {
+ rows_per_buffer = 1;
+ }
+ // If pixels are packed by column then ensure rows_per_buffer is on a byte boundary.
+ if (self->core.colorspace.depth < 8 && !self->core.colorspace.pixels_in_byte_share_row) {
+ uint8_t pixels_per_byte = 8 / self->core.colorspace.depth;
+ if (rows_per_buffer % pixels_per_byte != 0) {
+ rows_per_buffer -= rows_per_buffer % pixels_per_byte;
+ }
+ }
+ subrectangles = displayio_area_height(&clipped) / rows_per_buffer;
+ if (displayio_area_height(&clipped) % rows_per_buffer != 0) {
+ subrectangles++;
+ }
+ pixels_per_buffer = rows_per_buffer * displayio_area_width(&clipped);
+ buffer_size = pixels_per_buffer / pixels_per_word;
+ if (pixels_per_buffer % pixels_per_word) {
+ buffer_size += 1;
+ }
+ }
+
+ // Allocated and shared as a uint32_t array so the compiler knows the
+ // alignment everywhere.
+ uint32_t buffer[buffer_size];
+ uint32_t mask_length = (pixels_per_buffer / 32) + 1;
+ uint32_t mask[mask_length];
+ uint16_t remaining_rows = displayio_area_height(&clipped);
+
+ for (uint16_t j = 0; j < subrectangles; j++) {
+ displayio_area_t subrectangle = {
+ .x1 = clipped.x1,
+ .y1 = clipped.y1 + rows_per_buffer * j,
+ .x2 = clipped.x2,
+ .y2 = clipped.y1 + rows_per_buffer * (j + 1)
+ };
+ if (remaining_rows < rows_per_buffer) {
+ subrectangle.y2 = subrectangle.y1 + remaining_rows;
+ }
+ remaining_rows -= rows_per_buffer;
+
+ displayio_display_core_set_region_to_update(&self->core, self->set_column_command, self->set_row_command, NO_COMMAND, NO_COMMAND, self->data_as_commands, false, &subrectangle);
+
+ uint16_t subrectangle_size_bytes;
+ if (self->core.colorspace.depth >= 8) {
+ subrectangle_size_bytes = displayio_area_size(&subrectangle) * (self->core.colorspace.depth / 8);
+ } else {
+ subrectangle_size_bytes = displayio_area_size(&subrectangle) / (8 / self->core.colorspace.depth);
+ }
+
+ memset(mask, 0, mask_length * sizeof(mask[0]));
+ memset(buffer, 0, buffer_size * sizeof(buffer[0]));
+
+ displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer);
+
+ // Can't acquire display bus; skip the rest of the data.
+ if (!displayio_display_core_bus_free(&self->core)) {
+ return false;
+ }
+
+ displayio_display_core_begin_transaction(&self->core);
+ _send_pixels(self, (uint8_t*) buffer, subrectangle_size_bytes);
+ displayio_display_core_end_transaction(&self->core);
+
+ // TODO(tannewt): Make refresh displays faster so we don't starve other
+ // background tasks.
+ usb_background();
+ }
+ return true;
}
-bool displayio_display_frame_queued(displayio_display_obj_t* self) {
- if (self->current_group == NULL) {
- return false;
+STATIC void _refresh_display(displayio_display_obj_t* self) {
+ if (!displayio_display_core_bus_free(&self->core)) {
+ // Can't acquire display bus; skip updating this display. Try next display.
+ return;
}
- // Refresh at ~60 fps.
- return (ticks_ms - self->last_refresh) > 16;
+ displayio_display_core_start_refresh(&self->core);
+ const displayio_area_t* current_area = _get_refresh_areas(self);
+ while (current_area != NULL) {
+ _refresh_area(self, current_area);
+ current_area = current_area->next;
+ }
+ displayio_display_core_finish_refresh(&self->core);
}
-void displayio_display_finish_refresh(displayio_display_obj_t* self) {
- if (self->current_group != NULL) {
- displayio_group_finish_refresh(self->current_group);
+uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self){
+ return self->core.rotation;
+}
+
+bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) {
+ if (!self->auto_refresh && !self->first_manual_refresh) {
+ uint64_t current_time = ticks_ms;
+ uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh;
+ // Test to see if the real frame time is below our minimum.
+ if (current_ms_since_real_refresh > maximum_ms_per_real_frame) {
+ mp_raise_RuntimeError(translate("Below minimum frame rate"));
+ }
+ uint32_t current_ms_since_last_call = current_time - self->last_refresh_call;
+ self->last_refresh_call = current_time;
+ // Skip the actual refresh to help catch up.
+ if (current_ms_since_last_call > target_ms_per_frame) {
+ return false;
+ }
+ uint32_t remaining_time = target_ms_per_frame - (current_ms_since_real_refresh % target_ms_per_frame);
+ // We're ahead of the game so wait until we align with the frame rate.
+ while (ticks_ms - self->last_refresh_call < remaining_time) {
+ RUN_BACKGROUND_TASKS;
+ }
}
- self->refresh = false;
- self->full_refresh = false;
- self->last_refresh = ticks_ms;
+ self->first_manual_refresh = false;
+ _refresh_display(self);
+ return true;
+}
+
+bool common_hal_displayio_display_get_auto_refresh(displayio_display_obj_t* self) {
+ return self->auto_refresh;
}
-void displayio_display_send_pixels(displayio_display_obj_t* self, uint8_t* pixels, uint32_t length) {
- self->send(self->bus, false, pixels, length);
+void common_hal_displayio_display_set_auto_refresh(displayio_display_obj_t* self,
+ bool auto_refresh) {
+ self->first_manual_refresh = !auto_refresh;
+ self->auto_refresh = auto_refresh;
}
-void displayio_display_update_backlight(displayio_display_obj_t* self) {
+STATIC void _update_backlight(displayio_display_obj_t* self) {
if (!self->auto_brightness || self->updating_backlight) {
return;
}
@@ -339,7 +360,16 @@ void displayio_display_update_backlight(displayio_display_obj_t* self) {
self->last_backlight_refresh = ticks_ms;
}
+void displayio_display_background(displayio_display_obj_t* self) {
+ _update_backlight(self);
+
+ if (self->auto_refresh && (ticks_ms - self->core.last_refresh) > self->native_ms_per_frame) {
+ _refresh_display(self);
+ }
+}
+
void release_display(displayio_display_obj_t* self) {
+ release_display_core(&self->core);
if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
common_hal_pulseio_pwmout_reset_ok(&self->backlight_pwm);
common_hal_pulseio_pwmout_deinit(&self->backlight_pwm);
@@ -348,10 +378,12 @@ void release_display(displayio_display_obj_t* self) {
}
}
-bool displayio_display_fill_area(displayio_display_obj_t *self, displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
- return displayio_group_fill_area(self->current_group, area, mask, buffer);
+void reset_display(displayio_display_obj_t* self) {
+ self->auto_refresh = true;
+ self->auto_brightness = true;
+ common_hal_displayio_display_show(self, NULL);
}
-bool displayio_display_clip_area(displayio_display_obj_t *self, const displayio_area_t* area, displayio_area_t* clipped) {
- return displayio_area_compute_overlap(&self->area, area, clipped);
+void displayio_display_collect_ptrs(displayio_display_obj_t* self) {
+ displayio_display_core_collect_ptrs(&self->core);
}
diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h
index fa8902ced..e5fe0a708 100644
--- a/shared-module/displayio/Display.h
+++ b/shared-module/displayio/Display.h
@@ -32,47 +32,35 @@
#include "shared-bindings/pulseio/PWMOut.h"
#include "shared-module/displayio/area.h"
-
-typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
-typedef void (*display_bus_send)(mp_obj_t bus, bool command, uint8_t *data, uint32_t data_length);
-typedef void (*display_bus_end_transaction)(mp_obj_t bus);
+#include "shared-module/displayio/display_core.h"
typedef struct {
mp_obj_base_t base;
- mp_obj_t bus;
- displayio_group_t *current_group;
- uint64_t last_refresh;
- display_bus_begin_transaction begin_transaction;
- display_bus_send send;
- display_bus_end_transaction end_transaction;
+ displayio_display_core_t core;
union {
digitalio_digitalinout_obj_t backlight_inout;
pulseio_pwmout_obj_t backlight_pwm;
};
uint64_t last_backlight_refresh;
- displayio_buffer_transform_t transform;
- displayio_area_t area;
- uint16_t width;
- uint16_t height;
- uint16_t color_depth;
- int16_t colstart;
- int16_t rowstart;
+ uint64_t last_refresh_call;
+ mp_float_t current_brightness;
+ uint16_t brightness_command;
+ uint16_t native_frames_per_second;
+ uint16_t native_ms_per_frame;
uint8_t set_column_command;
uint8_t set_row_command;
uint8_t write_ram_command;
- bool refresh;
- bool single_byte_bounds;
+ bool auto_refresh;
+ bool first_manual_refresh;
bool data_as_commands;
bool auto_brightness;
bool updating_backlight;
- bool full_refresh; // New group means we need to refresh the whole display.
} displayio_display_obj_t;
-void displayio_display_start_refresh(displayio_display_obj_t* self);
-const displayio_area_t* displayio_display_get_refresh_areas(displayio_display_obj_t *self);
-bool displayio_display_fill_area(displayio_display_obj_t *self, displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
-void displayio_display_update_backlight(displayio_display_obj_t* self);
-bool displayio_display_clip_area(displayio_display_obj_t *self, const displayio_area_t* area, displayio_area_t* clipped);
+void displayio_display_background(displayio_display_obj_t* self);
void release_display(displayio_display_obj_t* self);
+void reset_display(displayio_display_obj_t* self);
+
+void displayio_display_collect_ptrs(displayio_display_obj_t* self);
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c
new file mode 100644
index 000000000..efbd9f3dd
--- /dev/null
+++ b/shared-module/displayio/EPaperDisplay.c
@@ -0,0 +1,385 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/displayio/EPaperDisplay.h"
+
+#include "py/runtime.h"
+#include "shared-bindings/displayio/ColorConverter.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-bindings/displayio/I2CDisplay.h"
+#include "shared-bindings/displayio/ParallelBus.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-module/displayio/__init__.h"
+#include "supervisor/shared/display.h"
+#include "supervisor/usb.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "tick.h"
+
+void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self,
+ mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len,
+ uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height,
+ int16_t colstart, int16_t rowstart, uint16_t rotation,
+ uint16_t set_column_window_command, uint16_t set_row_window_command,
+ uint16_t set_current_column_command, uint16_t set_current_row_command,
+ uint16_t write_black_ram_command, bool black_bits_inverted, uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint16_t refresh_display_command, mp_float_t refresh_time,
+ const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select) {
+ if (highlight_color != 0x000000) {
+ self->core.colorspace.tricolor = true;
+ self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(highlight_color);
+ self->core.colorspace.tricolor_luma = displayio_colorconverter_compute_luma(highlight_color);
+ }
+
+ displayio_display_core_construct(&self->core, bus, width, height, ram_width, ram_height, colstart, rowstart, rotation, 1, true, true, 1, true);
+
+ self->set_column_window_command = set_column_window_command;
+ self->set_row_window_command = set_row_window_command;
+ self->set_current_column_command = set_current_column_command;
+ self->set_current_row_command = set_current_row_command;
+ self->write_black_ram_command = write_black_ram_command;
+ self->black_bits_inverted = black_bits_inverted;
+ self->write_color_ram_command = write_color_ram_command;
+ self->color_bits_inverted = color_bits_inverted;
+ self->refresh_display_command = refresh_display_command;
+ self->refresh_time = refresh_time * 1000;
+ self->busy_state = busy_state;
+ self->refreshing = false;
+ self->milliseconds_per_frame = seconds_per_frame * 1000;
+ self->chip_select = chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED;
+
+ self->start_sequence = start_sequence;
+ self->start_sequence_len = start_sequence_len;
+ self->stop_sequence = stop_sequence;
+ self->stop_sequence_len = stop_sequence_len;
+
+ self->busy.base.type = &mp_type_NoneType;
+ if (busy_pin != NULL) {
+ self->busy.base.type = &digitalio_digitalinout_type;
+ common_hal_digitalio_digitalinout_construct(&self->busy, busy_pin);
+ never_reset_pin_number(busy_pin->number);
+ }
+
+ // Clear the color memory if it isn't in use.
+ if (highlight_color == 0x00 && write_color_ram_command != NO_COMMAND) {
+ // TODO: Clear
+ }
+
+ supervisor_start_terminal(width, height);
+
+ // Set the group after initialization otherwise we may send pixels while we delay in
+ // initialization.
+ common_hal_displayio_epaperdisplay_show(self, &circuitpython_splash);
+}
+
+bool common_hal_displayio_epaperdisplay_show(displayio_epaperdisplay_obj_t* self, displayio_group_t* root_group) {
+ return displayio_display_core_show(&self->core, root_group);
+}
+
+const displayio_area_t* displayio_epaperdisplay_get_refresh_areas(displayio_epaperdisplay_obj_t *self) {
+ if (self->core.full_refresh) {
+ self->core.area.next = NULL;
+ return &self->core.area;
+ }
+ const displayio_area_t* first_area = NULL;
+ if (self->core.current_group != NULL) {
+ first_area = displayio_group_get_refresh_areas(self->core.current_group, NULL);
+ }
+ if (first_area != NULL && self->set_row_window_command == NO_COMMAND) {
+ self->core.area.next = NULL;
+ return &self->core.area;
+ }
+ return first_area;
+}
+
+uint16_t common_hal_displayio_epaperdisplay_get_width(displayio_epaperdisplay_obj_t* self){
+ return displayio_display_core_get_width(&self->core);
+}
+
+uint16_t common_hal_displayio_epaperdisplay_get_height(displayio_epaperdisplay_obj_t* self){
+ return displayio_display_core_get_height(&self->core);
+}
+
+STATIC void wait_for_busy(displayio_epaperdisplay_obj_t* self) {
+ if (self->busy.base.type == &mp_type_NoneType) {
+ return;
+ }
+ while (common_hal_digitalio_digitalinout_get_value(&self->busy) == self->busy_state) {
+ RUN_BACKGROUND_TASKS;
+ }
+}
+
+STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self, bool should_wait_for_busy, uint8_t* sequence, uint32_t sequence_len) {
+ uint32_t i = 0;
+ while (i < sequence_len) {
+ uint8_t *cmd = sequence + i;
+ uint8_t data_size = *(cmd + 1);
+ bool delay = (data_size & DELAY) != 0;
+ data_size &= ~DELAY;
+ uint8_t *data = cmd + 2;
+ displayio_display_core_begin_transaction(&self->core);
+ self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1);
+ self->core.send(self->core.bus, DISPLAY_DATA, self->chip_select, data, data_size);
+ displayio_display_core_end_transaction(&self->core);
+ uint16_t delay_length_ms = 0;
+ if (delay) {
+ data_size++;
+ delay_length_ms = *(cmd + 1 + data_size);
+ if (delay_length_ms == 255) {
+ delay_length_ms = 500;
+ }
+ }
+ common_hal_time_delay_ms(delay_length_ms);
+ if (should_wait_for_busy) {
+ wait_for_busy(self);
+ }
+ i += 2 + data_size;
+ }
+}
+
+void displayio_epaperdisplay_start_refresh(displayio_epaperdisplay_obj_t* self) {
+ // run start sequence
+ self->core.bus_reset(self->core.bus);
+
+ send_command_sequence(self, true, self->start_sequence, self->start_sequence_len);
+ displayio_display_core_start_refresh(&self->core);
+}
+
+uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaperdisplay_obj_t* self) {
+ if (self->core.last_refresh == 0) {
+ return 0;
+ }
+ // Refresh at seconds per frame rate.
+ uint32_t elapsed_time = ticks_ms - self->core.last_refresh;
+ if (elapsed_time > self->milliseconds_per_frame) {
+ return 0;
+ }
+ return self->milliseconds_per_frame - elapsed_time;
+}
+
+void displayio_epaperdisplay_finish_refresh(displayio_epaperdisplay_obj_t* self) {
+ // Actually refresh the display now that all pixel RAM has been updated.
+ displayio_display_core_begin_transaction(&self->core);
+ self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, &self->refresh_display_command, 1);
+ displayio_display_core_end_transaction(&self->core);
+ self->refreshing = true;
+
+ displayio_display_core_finish_refresh(&self->core);
+}
+
+mp_obj_t common_hal_displayio_epaperdisplay_get_bus(displayio_epaperdisplay_obj_t* self) {
+ return self->core.bus;
+}
+
+bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, const displayio_area_t* area) {
+ uint16_t buffer_size = 128; // In uint32_ts
+
+ displayio_area_t clipped;
+ // Clip the area to the display by overlapping the areas. If there is no overlap then we're done.
+ if (!displayio_display_core_clip_area(&self->core, area, &clipped)) {
+ return true;
+ }
+ uint16_t subrectangles = 1;
+ uint16_t rows_per_buffer = displayio_area_height(&clipped);
+ uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth;
+ uint16_t pixels_per_buffer = displayio_area_size(&clipped);
+ if (displayio_area_size(&clipped) > buffer_size * pixels_per_word) {
+ rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width(&clipped);
+ if (rows_per_buffer == 0) {
+ rows_per_buffer = 1;
+ }
+ subrectangles = displayio_area_height(&clipped) / rows_per_buffer;
+ if (displayio_area_height(&clipped) % rows_per_buffer != 0) {
+ subrectangles++;
+ }
+ pixels_per_buffer = rows_per_buffer * displayio_area_width(&clipped);
+ buffer_size = pixels_per_buffer / pixels_per_word;
+ if (pixels_per_buffer % pixels_per_word) {
+ buffer_size += 1;
+ }
+ }
+
+ // Allocated and shared as a uint32_t array so the compiler knows the
+ // alignment everywhere.
+ uint32_t buffer[buffer_size];
+ volatile uint32_t mask_length = (pixels_per_buffer / 32) + 1;
+ uint32_t mask[mask_length];
+
+ uint8_t passes = 1;
+ if (self->core.colorspace.tricolor) {
+ passes = 2;
+ }
+ for (uint8_t pass = 0; pass < passes; pass++) {
+ uint16_t remaining_rows = displayio_area_height(&clipped);
+
+ if (self->set_row_window_command != NO_COMMAND) {
+ displayio_display_core_set_region_to_update(&self->core, self->set_column_window_command, self->set_row_window_command, self->set_current_column_command, self->set_current_row_command, false, self->chip_select, &clipped);
+ }
+
+ uint8_t write_command = self->write_black_ram_command;
+ if (pass == 1) {
+ write_command = self->write_color_ram_command;
+ }
+ displayio_display_core_begin_transaction(&self->core);
+ self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1);
+ displayio_display_core_end_transaction(&self->core);
+
+ for (uint16_t j = 0; j < subrectangles; j++) {
+ displayio_area_t subrectangle = {
+ .x1 = clipped.x1,
+ .y1 = clipped.y1 + rows_per_buffer * j,
+ .x2 = clipped.x2,
+ .y2 = clipped.y1 + rows_per_buffer * (j + 1)
+ };
+ if (remaining_rows < rows_per_buffer) {
+ subrectangle.y2 = subrectangle.y1 + remaining_rows;
+ }
+ remaining_rows -= rows_per_buffer;
+
+
+ uint16_t subrectangle_size_bytes = displayio_area_size(&subrectangle) / (8 / self->core.colorspace.depth);
+
+ memset(mask, 0, mask_length * sizeof(mask[0]));
+ memset(buffer, 0, buffer_size * sizeof(buffer[0]));
+
+ self->core.colorspace.grayscale = true;
+ if (pass == 1) {
+ self->core.colorspace.grayscale = false;
+ }
+ displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer);
+
+ // Invert it all.
+ if ((pass == 1 && self->color_bits_inverted) ||
+ (pass == 0 && self->black_bits_inverted)) {
+ for (uint16_t k = 0; k < buffer_size; k++) {
+ buffer[k] = ~buffer[k];
+ }
+ }
+
+ if (!displayio_display_core_begin_transaction(&self->core)) {
+ // Can't acquire display bus; skip the rest of the data. Try next display.
+ return false;
+ }
+ self->core.send(self->core.bus, DISPLAY_DATA, self->chip_select, (uint8_t*) buffer, subrectangle_size_bytes);
+ displayio_display_core_end_transaction(&self->core);
+
+ // TODO(tannewt): Make refresh displays faster so we don't starve other
+ // background tasks.
+ usb_background();
+ }
+ }
+
+ return true;
+}
+
+bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* self) {
+
+ if (self->refreshing && self->busy.base.type == &digitalio_digitalinout_type) {
+ if (common_hal_digitalio_digitalinout_get_value(&self->busy) != self->busy_state) {
+ self->refreshing = false;
+ // Run stop sequence but don't wait for busy because busy is set when sleeping.
+ send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len);
+ } else {
+ return false;
+ }
+ }
+ if (self->core.current_group == NULL) {
+ return true;
+ }
+ // Refresh at seconds per frame rate.
+ if (common_hal_displayio_epaperdisplay_get_time_to_refresh(self) > 0) {
+ return false;
+ }
+ if (!displayio_display_core_bus_free(&self->core)) {
+ // Can't acquire display bus; skip updating this display. Try next display.
+ return false;
+ }
+ const displayio_area_t* current_area = displayio_epaperdisplay_get_refresh_areas(self);
+ if (current_area == NULL) {
+ return true;
+ }
+ displayio_epaperdisplay_start_refresh(self);
+ while (current_area != NULL) {
+ displayio_epaperdisplay_refresh_area(self, current_area);
+ current_area = current_area->next;
+ }
+ displayio_epaperdisplay_finish_refresh(self);
+ return true;
+}
+
+void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) {
+ if (self->refreshing) {
+ bool refresh_done = false;
+ if (self->busy.base.type == &digitalio_digitalinout_type) {
+ bool busy = common_hal_digitalio_digitalinout_get_value(&self->busy);
+ refresh_done = busy != self->busy_state;
+ } else {
+ refresh_done = ticks_ms - self->core.last_refresh > self->refresh_time;
+ }
+ if (refresh_done) {
+ self->refreshing = false;
+ // Run stop sequence but don't wait for busy because busy is set when sleeping.
+ send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len);
+ }
+ }
+}
+
+void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) {
+ if (self->refreshing) {
+ wait_for_busy(self);
+ self->refreshing = false;
+ // Run stop sequence but don't wait for busy because busy is set when sleeping.
+ send_command_sequence(self, false, self->stop_sequence, self->stop_sequence_len);
+ }
+
+ release_display_core(&self->core);
+ if (self->busy.base.type == &digitalio_digitalinout_type) {
+ common_hal_digitalio_digitalinout_deinit(&self->busy);
+ }
+}
+
+void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self) {
+ displayio_display_core_collect_ptrs(&self->core);
+}
+
+bool maybe_refresh_epaperdisplay(void) {
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ if (displays[i].epaper_display.base.type != &displayio_epaperdisplay_type ||
+ displays[i].epaper_display.core.current_group != &circuitpython_splash) {
+ // Skip regular displays and those not showing the splash.
+ continue;
+ }
+ displayio_epaperdisplay_obj_t* display = &displays[i].epaper_display;
+ if (common_hal_displayio_epaperdisplay_get_time_to_refresh(display) != 0) {
+ return false;
+ }
+ return common_hal_displayio_epaperdisplay_refresh(display);
+ }
+ // Return true if no ePaper displays are available to pretend it was updated.
+ return true;
+}
diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h
new file mode 100644
index 000000000..d08bed546
--- /dev/null
+++ b/shared-module/displayio/EPaperDisplay.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_EPAPERDISPLAY_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_EPAPERDISPLAY_H
+
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/pulseio/PWMOut.h"
+
+#include "shared-module/displayio/area.h"
+#include "shared-module/displayio/display_core.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ displayio_display_core_t core;
+ digitalio_digitalinout_obj_t busy;
+ uint32_t milliseconds_per_frame;
+ uint8_t* start_sequence;
+ uint32_t start_sequence_len;
+ uint8_t* stop_sequence;
+ uint32_t stop_sequence_len;
+ uint16_t refresh_time;
+ uint16_t set_column_window_command;
+ uint16_t set_row_window_command;
+ uint16_t set_current_column_command;
+ uint16_t set_current_row_command;
+ uint16_t write_black_ram_command;
+ uint16_t write_color_ram_command;
+ uint8_t refresh_display_command;
+ uint8_t hue;
+ bool busy_state;
+ bool black_bits_inverted;
+ bool color_bits_inverted;
+ bool refreshing;
+ display_chip_select_behavior_t chip_select;
+} displayio_epaperdisplay_obj_t;
+
+void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self);
+void release_epaperdisplay(displayio_epaperdisplay_obj_t* self);
+bool maybe_refresh_epaperdisplay(void);
+
+void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_EPAPERDISPLAY_H
diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c
index d38da56fc..fcc4c1a20 100644
--- a/shared-module/displayio/FourWire.c
+++ b/shared-module/displayio/FourWire.c
@@ -33,6 +33,7 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/time/__init__.h"
+#include "shared-module/displayio/display_core.h"
#include "tick.h"
@@ -55,10 +56,13 @@ void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self,
common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
+ self->reset.base.type = &mp_type_NoneType;
if (reset != NULL) {
+ self->reset.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->reset, reset);
common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
never_reset_pin_number(reset->number);
+ common_hal_displayio_fourwire_reset(self);
}
never_reset_pin_number(command->number);
@@ -75,6 +79,27 @@ void common_hal_displayio_fourwire_deinit(displayio_fourwire_obj_t* self) {
reset_pin_number(self->reset.pin->number);
}
+bool common_hal_displayio_fourwire_reset(mp_obj_t obj) {
+ displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (self->reset.base.type == &mp_type_NoneType) {
+ return false;
+ }
+ common_hal_digitalio_digitalinout_set_value(&self->reset, false);
+ common_hal_time_delay_ms(1);
+ common_hal_digitalio_digitalinout_set_value(&self->reset, true);
+ common_hal_time_delay_ms(1);
+ return true;
+}
+
+bool common_hal_displayio_fourwire_bus_free(mp_obj_t obj) {
+ displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (!common_hal_busio_spi_try_lock(self->bus)) {
+ return false;
+ }
+ common_hal_busio_spi_unlock(self->bus);
+ return true;
+}
+
bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) {
displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
if (!common_hal_busio_spi_try_lock(self->bus)) {
@@ -86,15 +111,21 @@ bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) {
return true;
}
-void common_hal_displayio_fourwire_send(mp_obj_t obj, bool command, uint8_t *data, uint32_t data_length) {
+void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
- if (command) {
- common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
- common_hal_mcu_delay_us(1);
- common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
+ common_hal_digitalio_digitalinout_set_value(&self->command, data_type == DISPLAY_DATA);
+ if (chip_select == CHIP_SELECT_TOGGLE_EVERY_BYTE) {
+ // Toggle chip select after each command byte in case the display driver
+ // IC latches commands based on it.
+ for (size_t i = 0; i < data_length; i++) {
+ common_hal_busio_spi_write(self->bus, &data[i], 1);
+ common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
+ common_hal_mcu_delay_us(1);
+ common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
+ }
+ } else {
+ common_hal_busio_spi_write(self->bus, data, data_length);
}
- common_hal_digitalio_digitalinout_set_value(&self->command, !command);
- common_hal_busio_spi_write(self->bus, data, data_length);
}
void common_hal_displayio_fourwire_end_transaction(mp_obj_t obj) {
diff --git a/shared-module/displayio/FourWire.h b/shared-module/displayio/FourWire.h
index 743139e62..a4260a3ac 100644
--- a/shared-module/displayio/FourWire.h
+++ b/shared-module/displayio/FourWire.h
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H
-#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_FOURWIRE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_FOURWIRE_H
#include "common-hal/busio/SPI.h"
#include "common-hal/digitalio/DigitalInOut.h"
@@ -43,4 +43,4 @@ typedef struct {
uint8_t phase;
} displayio_fourwire_obj_t;
-#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_FOURWIRE_H
diff --git a/shared-module/displayio/Group.c b/shared-module/displayio/Group.c
index 15060e87b..d69e9f585 100644
--- a/shared-module/displayio/Group.c
+++ b/shared-module/displayio/Group.c
@@ -34,6 +34,47 @@ void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_
displayio_group_construct(self, children, max_size, scale, x, y);
}
+bool common_hal_displayio_group_get_hidden(displayio_group_t* self) {
+ return self->hidden;
+}
+
+void common_hal_displayio_group_set_hidden(displayio_group_t* self, bool hidden) {
+ if (self->hidden == hidden) {
+ return;
+ }
+ self->hidden = hidden;
+ if (self->hidden_by_parent) {
+ return;
+ }
+ for (size_t i = 0; i < self->size; i++) {
+ mp_obj_t layer = self->children[i].native;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ displayio_tilegrid_set_hidden_by_parent(layer, hidden);
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ displayio_group_set_hidden_by_parent(layer, hidden);
+ }
+ }
+}
+
+void displayio_group_set_hidden_by_parent(displayio_group_t *self, bool hidden) {
+ if (self->hidden_by_parent == hidden) {
+ return;
+ }
+ self->hidden_by_parent = hidden;
+ // If we're already hidden, then we're done.
+ if (self->hidden) {
+ return;
+ }
+ for (size_t i = 0; i < self->size; i++) {
+ mp_obj_t layer = self->children[i].native;
+ if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
+ displayio_tilegrid_set_hidden_by_parent(layer, hidden);
+ } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
+ displayio_group_set_hidden_by_parent(layer, hidden);
+ }
+ }
+}
+
uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self) {
return self->scale;
}
@@ -270,19 +311,19 @@ void displayio_group_construct(displayio_group_t* self, displayio_group_child_t*
self->in_group = false;
}
-bool displayio_group_fill_area(displayio_group_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t* buffer) {
+bool displayio_group_fill_area(displayio_group_t *self, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t* buffer) {
// Track if any of the layers finishes filling in the given area. We can ignore any remaining
// layers at that point.
bool full_coverage = false;
for (int32_t i = self->size - 1; i >= 0 ; i--) {
mp_obj_t layer = self->children[i].native;
if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) {
- if (displayio_tilegrid_fill_area(layer, area, mask, buffer)) {
+ if (displayio_tilegrid_fill_area(layer, colorspace, area, mask, buffer)) {
full_coverage = true;
break;
}
} else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) {
- if (displayio_group_fill_area(layer, area, mask, buffer)) {
+ if (displayio_group_fill_area(layer, colorspace, area, mask, buffer)) {
full_coverage = true;
break;
}
diff --git a/shared-module/displayio/Group.h b/shared-module/displayio/Group.h
index 7ce19a4cd..5afaac1ba 100644
--- a/shared-module/displayio/Group.h
+++ b/shared-module/displayio/Group.h
@@ -32,6 +32,7 @@
#include "py/obj.h"
#include "shared-module/displayio/area.h"
+#include "shared-module/displayio/Palette.h"
typedef struct {
mp_obj_t native;
@@ -41,20 +42,24 @@ typedef struct {
typedef struct {
mp_obj_base_t base;
displayio_group_child_t* children;
+ displayio_buffer_transform_t absolute_transform;
+ displayio_area_t dirty_area; // Catch all for changed area
int16_t x;
int16_t y;
uint16_t scale;
uint16_t size;
uint16_t max_size;
- bool item_removed;
- bool in_group;
- displayio_buffer_transform_t absolute_transform;
- displayio_area_t dirty_area; // Catch all for changed area
+ bool item_removed :1;
+ bool in_group :1;
+ bool hidden :1;
+ bool hidden_by_parent :1;
+ uint8_t padding :4;
} displayio_group_t;
void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y);
+void displayio_group_set_hidden_by_parent(displayio_group_t *self, bool hidden);
bool displayio_group_get_previous_area(displayio_group_t *group, displayio_area_t* area);
-bool displayio_group_fill_area(displayio_group_t *group, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
+bool displayio_group_fill_area(displayio_group_t *group, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
void displayio_group_update_transform(displayio_group_t *group, const displayio_buffer_transform_t* parent_transform);
void displayio_group_finish_refresh(displayio_group_t *self);
displayio_area_t* displayio_group_get_refresh_areas(displayio_group_t *self, displayio_area_t* tail);
diff --git a/shared-module/displayio/I2CDisplay.c b/shared-module/displayio/I2CDisplay.c
new file mode 100644
index 000000000..d9452dc50
--- /dev/null
+++ b/shared-module/displayio/I2CDisplay.c
@@ -0,0 +1,123 @@
+/*
+ * 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-bindings/displayio/I2CDisplay.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "py/gc.h"
+#include "py/runtime.h"
+#include "shared-bindings/busio/I2C.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-module/displayio/display_core.h"
+
+#include "tick.h"
+
+void common_hal_displayio_i2cdisplay_construct(displayio_i2cdisplay_obj_t* self,
+ busio_i2c_obj_t* i2c, uint16_t device_address, const mcu_pin_obj_t* reset) {
+
+ // Probe the bus to see if a device acknowledges the given address.
+ if (!common_hal_busio_i2c_probe(i2c, device_address)) {
+ mp_raise_ValueError_varg(translate("Unable to find I2C Display at %x"), device_address);
+ }
+
+ // Write to the device and return 0 on success or an appropriate error code from mperrno.h
+ self->bus = i2c;
+ common_hal_busio_i2c_never_reset(self->bus);
+ // Our object is statically allocated off the heap so make sure the bus object lives to the end
+ // of the heap as well.
+ gc_never_free(self->bus);
+
+ self->address = device_address;
+
+ self->reset.base.type = &mp_type_NoneType;
+ if (reset != NULL) {
+ self->reset.base.type = &digitalio_digitalinout_type;
+ common_hal_digitalio_digitalinout_construct(&self->reset, reset);
+ common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
+ never_reset_pin_number(reset->number);
+ common_hal_displayio_i2cdisplay_reset(self);
+ }
+}
+
+void common_hal_displayio_i2cdisplay_deinit(displayio_i2cdisplay_obj_t* self) {
+ if (self->bus == &self->inline_bus) {
+ common_hal_busio_i2c_deinit(self->bus);
+ }
+
+ reset_pin_number(self->reset.pin->number);
+}
+
+bool common_hal_displayio_i2cdisplay_reset(mp_obj_t obj) {
+ displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (self->reset.base.type == &mp_type_NoneType) {
+ return false;
+ }
+
+ common_hal_digitalio_digitalinout_set_value(&self->reset, false);
+ common_hal_mcu_delay_us(4);
+ common_hal_digitalio_digitalinout_set_value(&self->reset, true);
+ return true;
+}
+
+bool common_hal_displayio_i2cdisplay_bus_free(mp_obj_t obj) {
+ displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (!common_hal_busio_i2c_try_lock(self->bus)) {
+ return false;
+ }
+ common_hal_busio_i2c_unlock(self->bus);
+ return true;
+}
+
+bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t obj) {
+ displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
+ return common_hal_busio_i2c_try_lock(self->bus);
+}
+
+void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
+ displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
+ if (data_type == DISPLAY_COMMAND) {
+ uint8_t command_bytes[2 * data_length];
+ for (uint32_t i = 0; i < data_length; i++) {
+ command_bytes[2 * i] = 0x80;
+ command_bytes[2 * i + 1] = data[i];
+ }
+ common_hal_busio_i2c_write(self->bus, self->address, command_bytes, 2 * data_length, true);
+ } else {
+ uint8_t data_bytes[data_length + 1];
+ data_bytes[0] = 0x40;
+ memcpy(data_bytes + 1, data, data_length);
+ common_hal_busio_i2c_write(self->bus, self->address, data_bytes, data_length + 1, true);
+ }
+}
+
+void common_hal_displayio_i2cdisplay_end_transaction(mp_obj_t obj) {
+ displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
+ common_hal_busio_i2c_unlock(self->bus);
+}
diff --git a/shared-module/displayio/I2CDisplay.h b/shared-module/displayio/I2CDisplay.h
new file mode 100644
index 000000000..4636c3f73
--- /dev/null
+++ b/shared-module/displayio/I2CDisplay.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_I2CDISPLAY_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_I2CDISPLAY_H
+
+#include "common-hal/busio/I2C.h"
+#include "common-hal/digitalio/DigitalInOut.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ busio_i2c_obj_t* bus;
+ busio_i2c_obj_t inline_bus;
+ digitalio_digitalinout_obj_t reset;
+ uint16_t address;
+} displayio_i2cdisplay_obj_t;
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_I2CDISPLAY_H
diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c
index 2b5642437..993fc03de 100644
--- a/shared-module/displayio/OnDiskBitmap.c
+++ b/shared-module/displayio/OnDiskBitmap.c
@@ -74,7 +74,7 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
self->g_bitmask = 0x3e0;
self->b_bitmask = 0x1f;
}
- } else if ((indexed) && (self->bits_per_pixel != 1)) {
+ } else if (indexed && self->bits_per_pixel != 1) {
uint16_t palette_size = number_of_colors * sizeof(uint32_t);
uint16_t palette_offset = 0xe + header_size;
@@ -90,25 +90,24 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
if (palette_bytes_read != palette_size) {
mp_raise_ValueError(translate("Unable to read color palette data"));
}
-
-
} else if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124)) {
mp_raise_ValueError_varg(translate("Only Windows format, uncompressed BMP supported: given header size is %d"), header_size);
}
- if ((bits_per_pixel == 4 ) || (( bits_per_pixel == 8) && (number_of_colors == 0))) {
- mp_raise_ValueError_varg(translate("Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp given"), bits_per_pixel);
+ if (bits_per_pixel == 8 && number_of_colors == 0) {
+ mp_raise_ValueError_varg(translate("Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: %d bpp given"), bits_per_pixel);
}
- if (self->bits_per_pixel >=8){
- self->stride = (self->width * (bits_per_pixel / 8));
+ uint8_t bytes_per_pixel = (self->bits_per_pixel / 8) ? (self->bits_per_pixel /8) : 1;
+ uint8_t pixels_per_byte = 8 / self->bits_per_pixel;
+ if (pixels_per_byte == 0){
+ self->stride = (self->width * bytes_per_pixel);
// Rows are word aligned.
if (self->stride % 4 != 0) {
self->stride += 4 - self->stride % 4;
}
-
} else {
- uint32_t bit_stride = self->width;
+ uint32_t bit_stride = self->width * self->bits_per_pixel;
if (bit_stride % 32 != 0) {
bit_stride += 32 - bit_stride % 32;
}
@@ -126,10 +125,11 @@ uint32_t common_hal_displayio_ondiskbitmap_get_pixel(displayio_ondiskbitmap_t *s
uint32_t location;
uint8_t bytes_per_pixel = (self->bits_per_pixel / 8) ? (self->bits_per_pixel /8) : 1;
- if (self->bits_per_pixel >= 8){
+ uint8_t pixels_per_byte = 8 / self->bits_per_pixel;
+ if (pixels_per_byte == 0){
location = self->data_offset + (self->height - y - 1) * self->stride + x * bytes_per_pixel;
} else {
- location = self->data_offset + (self->height - y - 1) * self->stride + x / 8;
+ location = self->data_offset + (self->height - y - 1) * self->stride + x / pixels_per_byte;
}
// We don't cache here because the underlying FS caches sectors.
f_lseek(&self->file->fp, location);
@@ -141,20 +141,19 @@ uint32_t common_hal_displayio_ondiskbitmap_get_pixel(displayio_ondiskbitmap_t *s
uint8_t red;
uint8_t green;
uint8_t blue;
- if (self->bits_per_pixel == 1) {
- uint8_t bit_offset = x%8;
- tmp = ( pixel_data & (0x80 >> (bit_offset))) >> (7 - bit_offset);
- if (tmp == 1) {
- return 0x00FFFFFF;
- } else {
- return 0x00000000;
+ if (bytes_per_pixel == 1) {
+ uint8_t offset = (x % pixels_per_byte) * self->bits_per_pixel;
+ uint8_t mask = (1 << self->bits_per_pixel) - 1;
+
+ uint8_t index = (pixel_data >> ((8 - self->bits_per_pixel) - offset)) & mask;
+ if (self->bits_per_pixel == 1) {
+ if (index == 1) {
+ return 0xFFFFFF;
+ } else {
+ return 0x000000;
+ }
}
- } else if (bytes_per_pixel == 1) {
- blue = ((self->palette_data[pixel_data] & 0xFF) >> 0);
- red = ((self->palette_data[pixel_data] & 0xFF0000) >> 16);
- green = ((self->palette_data[pixel_data] & 0xFF00) >> 8);
- tmp = (red << 16 | green << 8 | blue );
- return tmp;
+ return self->palette_data[index];
} else if (bytes_per_pixel == 2) {
if (self->g_bitmask == 0x07e0) { // 565
red =((pixel_data & self->r_bitmask) >>11);
diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c
index 8dc6e766b..3bce86f48 100644
--- a/shared-module/displayio/Palette.c
+++ b/shared-module/displayio/Palette.c
@@ -26,49 +26,65 @@
#include "shared-bindings/displayio/Palette.h"
+#include "shared-module/displayio/ColorConverter.h"
+
void common_hal_displayio_palette_construct(displayio_palette_t* self, uint16_t color_count) {
self->color_count = color_count;
- self->colors = (uint32_t *) m_malloc(color_count * sizeof(uint16_t), false);
- uint32_t opaque_byte_count = color_count / 8;
- if (color_count % 8 > 0) {
- opaque_byte_count += 1;
- }
- self->opaque = (uint32_t *) m_malloc(opaque_byte_count, false);
+ self->colors = (_displayio_color_t *) m_malloc(color_count * sizeof(_displayio_color_t), false);
}
void common_hal_displayio_palette_make_opaque(displayio_palette_t* self, uint32_t palette_index) {
- self->opaque[palette_index / 32] &= ~(0x1 << (palette_index % 32));
+ self->colors[palette_index].transparent = false;
}
void common_hal_displayio_palette_make_transparent(displayio_palette_t* self, uint32_t palette_index) {
- self->opaque[palette_index / 32] |= (0x1 << (palette_index % 32));
+ self->colors[palette_index].transparent = true;
+}
+
+uint32_t common_hal_displayio_palette_get_len(displayio_palette_t* self) {
+ return self->color_count;
}
void common_hal_displayio_palette_set_color(displayio_palette_t* self, uint32_t palette_index, uint32_t color) {
- uint32_t shift = (palette_index % 2) * 16;
- uint32_t masked = self->colors[palette_index / 2] & ~(0xffff << shift);
- uint32_t r5 = (color >> 19);
- uint32_t g6 = (color >> 10) & 0x3f;
- uint32_t b5 = (color >> 3) & 0x1f;
- uint32_t packed = r5 << 11 | g6 << 5 | b5;
- // swap bytes
- packed = __builtin_bswap16(packed);
- uint32_t final_color = masked | packed << shift;
- if (self->colors[palette_index / 2] == final_color) {
+ if (self->colors[palette_index].rgb888 == color) {
return;
}
- self->colors[palette_index / 2] = final_color;
+ self->colors[palette_index].rgb888 = color;
+ self->colors[palette_index].luma = displayio_colorconverter_compute_luma(color);
+ self->colors[palette_index].rgb565 = displayio_colorconverter_compute_rgb565(color);
+
+ uint8_t chroma = displayio_colorconverter_compute_chroma(color);
+ self->colors[palette_index].chroma = chroma;
+ self->colors[palette_index].hue = displayio_colorconverter_compute_hue(color);
self->needs_refresh = true;
}
-bool displayio_palette_get_color(displayio_palette_t *self, uint32_t palette_index, uint16_t* color) {
- if (palette_index > self->color_count) {
- return false;
+uint32_t common_hal_displayio_palette_get_color(displayio_palette_t* self, uint32_t palette_index) {
+ return self->colors[palette_index].rgb888;
+}
+
+bool displayio_palette_get_color(displayio_palette_t *self, const _displayio_colorspace_t* colorspace, uint32_t palette_index, uint32_t* color) {
+ if (palette_index > self->color_count || self->colors[palette_index].transparent) {
+ return false; // returns opaque
}
- if ((self->opaque[palette_index / 32] & (0x1 << (palette_index % 32))) != 0) {
- return false;
+
+ if (colorspace->tricolor) {
+ uint8_t luma = self->colors[palette_index].luma;
+ *color = luma >> (8 - colorspace->depth);
+ // Chroma 0 means the color is a gray and has no hue so never color based on it.
+ if (self->colors[palette_index].chroma <= 16) {
+ if (!colorspace->grayscale) {
+ *color = 0;
+ }
+ return true;
+ }
+ uint8_t pixel_hue = self->colors[palette_index].hue;
+ displayio_colorconverter_compute_tricolor(colorspace, pixel_hue, luma, color);
+ } else if (colorspace->grayscale) {
+ *color = self->colors[palette_index].luma >> (8 - colorspace->depth);
+ } else {
+ *color = self->colors[palette_index].rgb565;
}
- *color = (self->colors[palette_index / 2] >> (16 * (palette_index % 2))) & 0xffff;
return true;
}
diff --git a/shared-module/displayio/Palette.h b/shared-module/displayio/Palette.h
index 3813e8bdd..758fd43fc 100644
--- a/shared-module/displayio/Palette.h
+++ b/shared-module/displayio/Palette.h
@@ -33,14 +33,50 @@
#include "py/obj.h"
typedef struct {
+ uint8_t depth;
+ uint8_t bytes_per_cell;
+ uint8_t tricolor_hue;
+ uint8_t tricolor_luma;
+ bool grayscale;
+ bool tricolor;
+ bool pixels_in_byte_share_row;
+ bool reverse_pixels_in_byte;
+ bool dither;
+} _displayio_colorspace_t;
+
+typedef struct {
+ uint32_t rgb888;
+ uint16_t rgb565;
+ uint8_t luma;
+ uint8_t hue;
+ uint8_t chroma;
+ bool transparent; // This may have additional bits added later for blending.
+} _displayio_color_t;
+
+typedef struct {
+ uint32_t pixel;
+ uint16_t x;
+ uint16_t y;
+ uint8_t tile;
+ uint16_t tile_x;
+ uint16_t tile_y;
+} displayio_input_pixel_t;
+
+typedef struct {
+ uint32_t pixel;
+ bool opaque;
+} displayio_output_pixel_t;
+
+typedef struct {
mp_obj_base_t base;
- uint32_t* opaque;
- uint32_t* colors;
+ _displayio_color_t* colors;
uint32_t color_count;
bool needs_refresh;
} displayio_palette_t;
-bool displayio_palette_get_color(displayio_palette_t *palette, uint32_t palette_index, uint16_t* color);
+// Returns false if color fetch did not succeed (out of range or transparent).
+// Returns true if color is opaque, and sets color.
+bool displayio_palette_get_color(displayio_palette_t *palette, const _displayio_colorspace_t* colorspace, uint32_t palette_index, uint32_t* color);
bool displayio_palette_needs_refresh(displayio_palette_t *self);
void displayio_palette_finish_refresh(displayio_palette_t *self);
diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c
index 0cd00e0ce..c4855c333 100644
--- a/shared-module/displayio/TileGrid.c
+++ b/shared-module/displayio/TileGrid.c
@@ -26,6 +26,7 @@
#include "shared-bindings/displayio/TileGrid.h"
+#include "py/runtime.h"
#include "shared-bindings/displayio/Bitmap.h"
#include "shared-bindings/displayio/ColorConverter.h"
#include "shared-bindings/displayio/OnDiskBitmap.h"
@@ -33,7 +34,7 @@
#include "shared-bindings/displayio/Shape.h"
void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap,
- uint16_t bitmap_width_in_tiles,
+ uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles,
mp_obj_t pixel_shader, uint16_t width, uint16_t height,
uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) {
uint32_t total_tiles = width * height;
@@ -54,6 +55,7 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_
self->inline_tiles = false;
}
self->bitmap_width_in_tiles = bitmap_width_in_tiles;
+ self->tiles_in_bitmap = bitmap_width_in_tiles * bitmap_height_in_tiles;
self->width_in_tiles = width;
self->height_in_tiles = height;
self->x = x;
@@ -65,14 +67,30 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_
self->bitmap = bitmap;
self->pixel_shader = pixel_shader;
self->in_group = false;
- self->first_draw = true;
+ self->hidden = false;
+ self->hidden_by_parent = false;
+ self->previous_area.x1 = 0xffff;
+ self->previous_area.x2 = self->previous_area.x1;
self->flip_x = false;
self->flip_y = false;
self->transpose_xy = false;
}
+
+bool common_hal_displayio_tilegrid_get_hidden(displayio_tilegrid_t* self) {
+ return self->hidden;
+}
+
+void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t* self, bool hidden) {
+ self->hidden = hidden;
+}
+
+void displayio_tilegrid_set_hidden_by_parent(displayio_tilegrid_t *self, bool hidden) {
+ self->hidden_by_parent = hidden;
+}
+
bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_area_t* area) {
- if (self->first_draw) {
+ if (self->previous_area.x1 == self->previous_area.x2) {
return false;
}
displayio_area_copy(&self->previous_area, area);
@@ -136,12 +154,10 @@ void displayio_tilegrid_update_transform(displayio_tilegrid_t *self,
self->in_group = absolute_transform != NULL;
self->absolute_transform = absolute_transform;
if (absolute_transform != NULL) {
- self->moved = !self->first_draw;
+ self->moved = true;
_update_current_x(self);
_update_current_y(self);
- } else {
- self->first_draw = true;
}
}
@@ -153,7 +169,7 @@ void common_hal_displayio_tilegrid_set_x(displayio_tilegrid_t *self, mp_int_t x)
return;
}
- self->moved = !self->first_draw;
+ self->moved = true;
self->x = x;
if (self->absolute_transform != NULL) {
@@ -168,7 +184,7 @@ void common_hal_displayio_tilegrid_set_y(displayio_tilegrid_t *self, mp_int_t y)
if (self->y == y) {
return;
}
- self->moved = !self->first_draw;
+ self->moved = true;
self->y = y;
if (self->absolute_transform != NULL) {
_update_current_y(self);
@@ -204,6 +220,9 @@ uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint1
}
void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index) {
+ if (tile_index >= self->tiles_in_bitmap) {
+ mp_raise_ValueError(translate("Tile index out of bounds"));
+ }
uint8_t* tiles = self->tiles;
if (self->inline_tiles) {
tiles = (uint8_t*) &self->tiles;
@@ -291,7 +310,7 @@ void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint
self->full_change = true;
}
-bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
+bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
// If no tiles are present we have no impact.
uint8_t* tiles = self->tiles;
if (self->inline_tiles) {
@@ -301,6 +320,11 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_ar
return false;
}
+ bool hidden = self->hidden || self->hidden_by_parent;
+ if (hidden) {
+ return false;
+ }
+
displayio_area_t overlap;
if (!displayio_area_compute_overlap(area, &self->current_area, &overlap)) {
return false;
@@ -371,14 +395,19 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_ar
y_shift = temp_shift;
}
- for (int16_t y = start_y; y < end_y; y++) {
- int16_t row_start = start + (y - start_y + y_shift) * y_stride;
- int16_t local_y = y / self->absolute_transform->scale;
- for (int16_t x = start_x; x < end_x; x++) {
+ uint8_t pixels_per_byte = 8 / colorspace->depth;
+
+ displayio_input_pixel_t input_pixel;
+ displayio_output_pixel_t output_pixel;
+
+ for (input_pixel.y = start_y; input_pixel.y < end_y; ++input_pixel.y) {
+ int16_t row_start = start + (input_pixel.y - start_y + y_shift) * y_stride; // in pixels
+ int16_t local_y = input_pixel.y / self->absolute_transform->scale;
+ for (input_pixel.x = start_x; input_pixel.x < end_x; ++input_pixel.x) {
// Compute the destination pixel in the buffer and mask based on the transformations.
- int16_t offset = row_start + (x - start_x + x_shift) * x_stride;
+ int16_t offset = row_start + (input_pixel.x - start_x + x_shift) * x_stride; // in pixels
- // This is super useful for debugging out range accesses. Uncomment to use.
+ // This is super useful for debugging out of range accesses. Uncomment to use.
// if (offset < 0 || offset >= (int32_t) displayio_area_size(area)) {
// asm("bkpt");
// }
@@ -387,40 +416,62 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_ar
if ((mask[offset / 32] & (1 << (offset % 32))) != 0) {
continue;
}
- int16_t local_x = x / self->absolute_transform->scale;
+ int16_t local_x = input_pixel.x / self->absolute_transform->scale;
uint16_t tile_location = ((local_y / self->tile_height + self->top_left_y) % self->height_in_tiles) * self->width_in_tiles + (local_x / self->tile_width + self->top_left_x) % self->width_in_tiles;
- uint8_t tile = tiles[tile_location];
- uint16_t tile_x = (tile % self->bitmap_width_in_tiles) * self->tile_width + local_x % self->tile_width;
- uint16_t tile_y = (tile / self->bitmap_width_in_tiles) * self->tile_height + local_y % self->tile_height;
+ input_pixel.tile = tiles[tile_location];
+ input_pixel.tile_x = (input_pixel.tile % self->bitmap_width_in_tiles) * self->tile_width + local_x % self->tile_width;
+ input_pixel.tile_y = (input_pixel.tile / self->bitmap_width_in_tiles) * self->tile_height + local_y % self->tile_height;
+
+ //uint32_t value = 0;
+ output_pixel.pixel = 0;
+ input_pixel.pixel = 0;
- uint32_t value = 0;
// We always want to read bitmap pixels by row first and then transpose into the destination
// buffer because most bitmaps are row associated.
if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
- value = common_hal_displayio_bitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ input_pixel.pixel = common_hal_displayio_bitmap_get_pixel(self->bitmap, input_pixel.tile_x, input_pixel.tile_y);
} else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
- value = common_hal_displayio_shape_get_pixel(self->bitmap, tile_x, tile_y);
+ input_pixel.pixel = common_hal_displayio_shape_get_pixel(self->bitmap, input_pixel.tile_x, input_pixel.tile_y);
} else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
- value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, tile_x, tile_y);
+ input_pixel.pixel = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, input_pixel.tile_x, input_pixel.tile_y);
}
-
- uint16_t* pixel = ((uint16_t*) buffer) + offset;
+
+ output_pixel.opaque = true;
if (self->pixel_shader == mp_const_none) {
- *pixel = value;
- return true;
+ output_pixel.pixel = input_pixel.pixel;
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
- if (!displayio_palette_get_color(self->pixel_shader, value, pixel)) {
- // A pixel is transparent so we haven't fully covered the area ourselves.
- full_coverage = false;
- } else {
- mask[offset / 32] |= 1 << (offset % 32);
- }
+ output_pixel.opaque = displayio_palette_get_color(self->pixel_shader, colorspace, input_pixel.pixel, &output_pixel.pixel);
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
- if (!common_hal_displayio_colorconverter_convert(self->pixel_shader, value, pixel)) {
- // A pixel is transparent so we haven't fully covered the area ourselves.
- full_coverage = false;
- } else {
- mask[offset / 32] |= 1 << (offset % 32);
+ displayio_colorconverter_convert(self->pixel_shader, colorspace, &input_pixel, &output_pixel);
+ }
+ if (!output_pixel.opaque) {
+ // A pixel is transparent so we haven't fully covered the area ourselves.
+ full_coverage = false;
+ } else {
+ mask[offset / 32] |= 1 << (offset % 32);
+ if (colorspace->depth == 16) {
+ *(((uint16_t*) buffer) + offset) = output_pixel.pixel;
+ } else if (colorspace->depth == 8) {
+ *(((uint8_t*) buffer) + offset) = output_pixel.pixel;
+ } else if (colorspace->depth < 8) {
+ // Reorder the offsets to pack multiple rows into a byte (meaning they share a column).
+ if (!colorspace->pixels_in_byte_share_row) {
+ uint16_t width = displayio_area_width(area);
+ uint16_t row = offset / width;
+ uint16_t col = offset % width;
+ // Dividing by pixels_per_byte does truncated division even if we multiply it back out.
+ offset = col * pixels_per_byte + (row / pixels_per_byte) * pixels_per_byte * width + row % pixels_per_byte;
+ // Also useful for validating that the bitpacking worked correctly.
+ // if (offset > displayio_area_size(area)) {
+ // asm("bkpt");
+ // }
+ }
+ uint8_t shift = (offset % pixels_per_byte) * colorspace->depth;
+ if (colorspace->reverse_pixels_in_byte) {
+ // Reverse the shift by subtracting it from the leftmost shift.
+ shift = (pixels_per_byte - 1) * colorspace->depth - shift;
+ }
+ ((uint8_t*)buffer)[offset / pixels_per_byte] |= output_pixel.pixel << shift;
}
}
}
@@ -429,25 +480,46 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_ar
}
void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
- if (self->moved || self->first_draw) {
+ bool first_draw = self->previous_area.x1 == self->previous_area.x2;
+ bool hidden = self->hidden || self->hidden_by_parent;
+ if (!first_draw && hidden) {
+ self->previous_area.x2 = self->previous_area.x1;
+ } else if (self->moved || first_draw) {
displayio_area_copy(&self->current_area, &self->previous_area);
}
self->moved = false;
self->full_change = false;
self->partial_change = false;
- self->first_draw = false;
if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
displayio_palette_finish_refresh(self->pixel_shader);
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
displayio_colorconverter_finish_refresh(self->pixel_shader);
}
+ if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
+ displayio_bitmap_finish_refresh(self->bitmap);
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) {
+ // TODO: Support shape changes.
+ } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) {
+ // OnDiskBitmap changes will trigger a complete reload so no need to
+ // track changes.
+ }
// TODO(tannewt): We could double buffer changes to position and move them over here.
// That way they won't change during a refresh and tear.
}
displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *self, displayio_area_t* tail) {
- if (self->moved && !self->first_draw) {
+ bool first_draw = self->previous_area.x1 == self->previous_area.x2;
+ bool hidden = self->hidden || self->hidden_by_parent;
+ // Check hidden first because it trumps all other changes.
+ if (hidden) {
+ if (!first_draw) {
+ self->previous_area.next = tail;
+ return &self->previous_area;
+ } else {
+ return tail;
+ }
+ } else if (self->moved && !first_draw) {
displayio_area_union(&self->previous_area, &self->current_area, &self->dirty_area);
if (displayio_area_size(&self->dirty_area) <= 2U * self->pixel_width * self->pixel_height) {
self->dirty_area.next = tail;
@@ -458,14 +530,27 @@ displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *sel
return &self->current_area;
}
- // We must recheck if our sources require a refresh because needs_refresh may or may not have
- // been called.
+ // If we have an in-memory bitmap, then check it for modifications.
+ if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) {
+ displayio_area_t* refresh_area = displayio_bitmap_get_refresh_areas(self->bitmap, tail);
+ if (refresh_area != tail) {
+ // Special case a TileGrid that shows a full bitmap and use its
+ // dirty area. Copy it to ours so we can transform it.
+ if (self->tiles_in_bitmap == 1) {
+ displayio_area_copy(refresh_area, &self->dirty_area);
+ self->partial_change = true;
+ } else {
+ self->full_change = true;
+ }
+ }
+ }
+
self->full_change = self->full_change ||
(MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type) &&
displayio_palette_needs_refresh(self->pixel_shader)) ||
(MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type) &&
displayio_colorconverter_needs_refresh(self->pixel_shader));
- if (self->full_change || self->first_draw) {
+ if (self->full_change || first_draw) {
self->current_area.next = tail;
return &self->current_area;
}
diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h
index 4d97eccc2..e97d3dfd4 100644
--- a/shared-module/displayio/TileGrid.h
+++ b/shared-module/displayio/TileGrid.h
@@ -32,6 +32,7 @@
#include "py/obj.h"
#include "shared-module/displayio/area.h"
+#include "shared-module/displayio/Palette.h"
typedef struct {
mp_obj_base_t base;
@@ -41,7 +42,8 @@ typedef struct {
int16_t y;
uint16_t pixel_width;
uint16_t pixel_height;
- uint16_t bitmap_width_in_tiles;
+ uint16_t bitmap_width_in_tiles;;
+ uint16_t tiles_in_bitmap;
uint16_t width_in_tiles;
uint16_t height_in_tiles;
uint16_t tile_width;
@@ -53,17 +55,21 @@ typedef struct {
displayio_area_t dirty_area; // Stored as a relative area until the refresh area is fetched.
displayio_area_t previous_area; // Stored as an absolute area.
displayio_area_t current_area; // Stored as an absolute area so it applies across frames.
- bool partial_change;
- bool full_change;
- bool first_draw;
- bool moved;
- bool inline_tiles;
- bool in_group;
- bool flip_x;
- bool flip_y;
- bool transpose_xy;
+ bool partial_change :1;
+ bool full_change :1;
+ bool moved :1;
+ bool inline_tiles :1;
+ bool in_group :1;
+ bool flip_x :1;
+ bool flip_y :1;
+ bool transpose_xy :1;
+ bool hidden :1;
+ bool hidden_by_parent :1;
+ uint8_t padding :6;
} displayio_tilegrid_t;
+void displayio_tilegrid_set_hidden_by_parent(displayio_tilegrid_t *self, bool hidden);
+
// Updating the screen is a three stage process.
// The first stage is used to determine i
@@ -71,7 +77,7 @@ displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *sel
// Area is always in absolute screen coordinates. Update transform is used to inform TileGrids how
// they relate to it.
-bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
+bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
void displayio_tilegrid_update_transform(displayio_tilegrid_t *group, const displayio_buffer_transform_t* parent_transform);
// Fills in area with the maximum bounds of all related pixels in the last rendered frame. Returns
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index b6709e0eb..af22cb0df 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -4,7 +4,6 @@
#include "shared-module/displayio/__init__.h"
#include "lib/utils/interrupt_char.h"
-#include "py/gc.h"
#include "py/reload.h"
#include "py/runtime.h"
#include "shared-bindings/board/__init__.h"
@@ -16,89 +15,13 @@
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/display.h"
#include "supervisor/memory.h"
-#include "supervisor/usb.h"
primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
-bool refresh_area(displayio_display_obj_t* display, const displayio_area_t* area) {
- uint16_t buffer_size = 512;
+// Check for recursive calls to displayio_background.
+bool displayio_background_in_progress = false;
- displayio_area_t clipped;
- // Clip the area to the display by overlapping the areas. If there is no overlap then we're done.
- if (!displayio_display_clip_area(display, area, &clipped)) {
- return true;
- }
- uint16_t subrectangles = 1;
- uint16_t rows_per_buffer = displayio_area_height(&clipped);
- if (displayio_area_size(area) > buffer_size) {
- rows_per_buffer = buffer_size / displayio_area_width(&clipped);
- subrectangles = displayio_area_height(&clipped) / rows_per_buffer;
- if (displayio_area_height(&clipped) % rows_per_buffer != 0) {
- subrectangles++;
- }
- buffer_size = rows_per_buffer * displayio_area_width(&clipped);
- }
- uint32_t buffer[buffer_size / 2];
- uint16_t remaining_rows = displayio_area_height(&clipped);
-
- for (uint16_t j = 0; j < subrectangles; j++) {
- displayio_area_t subrectangle = {
- .x1 = clipped.x1,
- .y1 = clipped.y1 + rows_per_buffer * j,
- .x2 = clipped.x2,
- .y2 = clipped.y1 + rows_per_buffer * (j + 1)
- };
- if (remaining_rows < rows_per_buffer) {
- subrectangle.y2 = subrectangle.y1 + remaining_rows;
- }
- remaining_rows -= rows_per_buffer;
-
- displayio_display_begin_transaction(display);
- displayio_display_set_region_to_update(display, subrectangle.x1, subrectangle.y1,
- subrectangle.x2, subrectangle.y2);
- displayio_display_end_transaction(display);
-
- uint32_t mask[(buffer_size / 32) + 1];
- for (uint16_t k = 0; k < (buffer_size / 32) + 1; k++) {
- mask[k] = 0x00000000;
- }
-
- bool full_coverage = displayio_display_fill_area(display, &subrectangle, mask, buffer);
- if (!full_coverage) {
- uint32_t index = 0;
- uint32_t current_mask = 0;
- for (int16_t y = subrectangle.y1; y < subrectangle.y2; y++) {
- for (int16_t x = subrectangle.x1; x < subrectangle.x2; x++) {
- if (index % 32 == 0) {
- current_mask = mask[index / 32];
- }
- if ((current_mask & (1 << (index % 32))) == 0) {
- ((uint16_t*) buffer)[index] = 0x0000;
- }
- index++;
- }
- }
- }
-
- if (!displayio_display_begin_transaction(display)) {
- // Can't acquire display bus; skip the rest of the data. Try next display.
- return false;
- }
- displayio_display_send_pixels(display, (uint8_t*) buffer, displayio_area_size(&subrectangle) * sizeof(uint16_t));
- displayio_display_end_transaction(display);
-
- // TODO(tannewt): Make refresh displays faster so we don't starve other
- // background tasks.
- usb_background();
- }
- return true;
-}
-
-// Check for recursive calls to displayio_refresh_displays.
-bool refresh_displays_in_progress = false;
-uint32_t frame_count = 0;
-
-void displayio_refresh_displays(void) {
+void displayio_background(void) {
if (mp_hal_is_interrupted()) {
return;
}
@@ -107,61 +30,56 @@ void displayio_refresh_displays(void) {
return;
}
- if (refresh_displays_in_progress) {
+ if (displayio_background_in_progress) {
// Don't allow recursive calls to this routine.
return;
}
- refresh_displays_in_progress = true;
+ displayio_background_in_progress = true;
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) {
// Skip null display.
continue;
}
- displayio_display_obj_t* display = &displays[i].display;
- displayio_display_update_backlight(display);
-
- // Time to refresh at specified frame rate?
- if (!displayio_display_frame_queued(display)) {
- // Too soon. Try next display.
- continue;
+ if (displays[i].display.base.type == &displayio_display_type) {
+ displayio_display_background(&displays[i].display);
+ } else if (displays[i].epaper_display.base.type == &displayio_epaperdisplay_type) {
+ displayio_epaperdisplay_background(&displays[i].epaper_display);
}
- if (!displayio_display_begin_transaction(display)) {
- // Can't acquire display bus; skip updating this display. Try next display.
- continue;
- }
- displayio_display_end_transaction(display);
- displayio_display_start_refresh(display);
- const displayio_area_t* current_area = displayio_display_get_refresh_areas(display);
- while (current_area != NULL) {
- refresh_area(display, current_area);
- current_area = current_area->next;
- }
- displayio_display_finish_refresh(display);
- frame_count++;
}
// All done.
- refresh_displays_in_progress = false;
+ displayio_background_in_progress = false;
}
void common_hal_displayio_release_displays(void) {
+ // Release displays before busses so that they can send any final commands to turn the display
+ // off properly.
+ for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ mp_const_obj_t display_type = displays[i].display.base.type;
+ if (display_type == NULL || display_type == &mp_type_NoneType) {
+ continue;
+ } else if (display_type == &displayio_display_type) {
+ release_display(&displays[i].display);
+ } else if (display_type == &displayio_epaperdisplay_type) {
+ release_epaperdisplay(&displays[i].epaper_display);
+ }
+ displays[i].display.base.type = &mp_type_NoneType;
+ }
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
mp_const_obj_t bus_type = displays[i].fourwire_bus.base.type;
- if (bus_type == NULL) {
+ if (bus_type == NULL || bus_type == &mp_type_NoneType) {
continue;
} else if (bus_type == &displayio_fourwire_type) {
common_hal_displayio_fourwire_deinit(&displays[i].fourwire_bus);
+ } else if (bus_type == &displayio_i2cdisplay_type) {
+ common_hal_displayio_i2cdisplay_deinit(&displays[i].i2cdisplay_bus);
} else if (bus_type == &displayio_parallelbus_type) {
common_hal_displayio_parallelbus_deinit(&displays[i].parallel_bus);
}
displays[i].fourwire_bus.base.type = &mp_type_NoneType;
}
- for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- release_display(&displays[i].display);
- displays[i].display.base.type = &mp_type_NoneType;
- }
supervisor_stop_terminal();
}
@@ -169,39 +87,67 @@ void common_hal_displayio_release_displays(void) {
void reset_displays(void) {
// The SPI buses used by FourWires may be allocated on the heap so we need to move them inline.
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].fourwire_bus.base.type != &displayio_fourwire_type) {
- continue;
- }
- displayio_fourwire_obj_t* fourwire = &displays[i].fourwire_bus;
- if (((uint32_t) fourwire->bus) < ((uint32_t) &displays) ||
- ((uint32_t) fourwire->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
- busio_spi_obj_t* original_spi = fourwire->bus;
- #if BOARD_SPI
- // We don't need to move original_spi if it is the board.SPI object because it is
- // statically allocated already. (Doing so would also make it impossible to reference in
- // a subsequent VM run.)
- if (original_spi == common_hal_board_get_spi()) {
- continue;
+ if (displays[i].fourwire_bus.base.type == &displayio_fourwire_type) {
+ displayio_fourwire_obj_t* fourwire = &displays[i].fourwire_bus;
+ if (((uint32_t) fourwire->bus) < ((uint32_t) &displays) ||
+ ((uint32_t) fourwire->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
+ busio_spi_obj_t* original_spi = fourwire->bus;
+ #if BOARD_SPI
+ // We don't need to move original_spi if it is the board.SPI object because it is
+ // statically allocated already. (Doing so would also make it impossible to reference in
+ // a subsequent VM run.)
+ if (original_spi == common_hal_board_get_spi()) {
+ continue;
+ }
+ #endif
+ memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t));
+ fourwire->bus = &fourwire->inline_bus;
+ // Check for other displays that use the same spi bus and swap them too.
+ for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
+ if (displays[i].fourwire_bus.base.type == &displayio_fourwire_type &&
+ displays[i].fourwire_bus.bus == original_spi) {
+ displays[i].fourwire_bus.bus = &fourwire->inline_bus;
+ }
}
- #endif
- memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t));
- fourwire->bus = &fourwire->inline_bus;
- // Check for other displays that use the same spi bus and swap them too.
- for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
- if (displays[i].fourwire_bus.bus == original_spi) {
- displays[i].fourwire_bus.bus = &fourwire->inline_bus;
+ }
+ } else if (displays[i].i2cdisplay_bus.base.type == &displayio_i2cdisplay_type) {
+ displayio_i2cdisplay_obj_t* i2c = &displays[i].i2cdisplay_bus;
+ if (((uint32_t) i2c->bus) < ((uint32_t) &displays) ||
+ ((uint32_t) i2c->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
+ busio_i2c_obj_t* original_i2c = i2c->bus;
+ #if BOARD_I2C
+ // We don't need to move original_i2c if it is the board.I2C object because it is
+ // statically allocated already. (Doing so would also make it impossible to reference in
+ // a subsequent VM run.)
+ if (original_i2c == common_hal_board_get_i2c()) {
+ continue;
+ }
+ #endif
+ memcpy(&i2c->inline_bus, original_i2c, sizeof(busio_i2c_obj_t));
+ i2c->bus = &i2c->inline_bus;
+ // Check for other displays that use the same i2c bus and swap them too.
+ for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
+ if (displays[i].i2cdisplay_bus.base.type == &displayio_i2cdisplay_type &&
+ displays[i].i2cdisplay_bus.bus == original_i2c) {
+ displays[i].i2cdisplay_bus.bus = &i2c->inline_bus;
+ }
}
}
+ } else {
+ // Not an active display bus.
+ continue;
}
}
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
- if (displays[i].display.base.type == NULL) {
- continue;
+ // Reset the displayed group. Only the first will get the terminal but
+ // that's ok.
+ if (displays[i].display.base.type == &displayio_display_type) {
+ reset_display(&displays[i].display);
+ } else if (displays[i].epaper_display.base.type == &displayio_epaperdisplay_type) {
+ displayio_epaperdisplay_obj_t* display = &displays[i].epaper_display;
+ common_hal_displayio_epaperdisplay_show(display, NULL);
}
- displayio_display_obj_t* display = &displays[i].display;
- display->auto_brightness = true;
- common_hal_displayio_display_show(display, &circuitpython_splash);
}
}
@@ -213,8 +159,11 @@ void displayio_gc_collect(void) {
// Alternatively, we could use gc_collect_root over the whole object,
// but this is more precise, and is the only field that needs marking.
- gc_collect_ptr(displays[i].display.current_group);
-
+ if (displays[i].display.base.type == &displayio_display_type) {
+ displayio_display_collect_ptrs(&displays[i].display);
+ } else if (displays[i].epaper_display.base.type == &displayio_epaperdisplay_type) {
+ displayio_epaperdisplay_collect_ptrs(&displays[i].epaper_display);
+ }
}
}
diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h
index 18c1a4f4a..e78bc61ce 100644
--- a/shared-module/displayio/__init__.h
+++ b/shared-module/displayio/__init__.h
@@ -28,23 +28,29 @@
#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO___INIT___H
#include "shared-bindings/displayio/Display.h"
+#include "shared-bindings/displayio/EPaperDisplay.h"
#include "shared-bindings/displayio/FourWire.h"
#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/displayio/I2CDisplay.h"
#include "shared-bindings/displayio/ParallelBus.h"
typedef struct {
union {
displayio_fourwire_obj_t fourwire_bus;
+ displayio_i2cdisplay_obj_t i2cdisplay_bus;
displayio_parallelbus_obj_t parallel_bus;
};
- displayio_display_obj_t display;
+ union {
+ displayio_display_obj_t display;
+ displayio_epaperdisplay_obj_t epaper_display;
+ };
} primary_display_t;
extern primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
extern displayio_group_t circuitpython_splash;
-void displayio_refresh_displays(void);
+void displayio_background(void);
void reset_displays(void);
void displayio_gc_collect(void);
diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c
new file mode 100644
index 000000000..a73ea81d1
--- /dev/null
+++ b/shared-module/displayio/display_core.c
@@ -0,0 +1,335 @@
+/*
+ * 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-bindings/displayio/Display.h"
+
+#include "py/gc.h"
+#include "py/runtime.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-bindings/displayio/I2CDisplay.h"
+#include "shared-bindings/displayio/ParallelBus.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/time/__init__.h"
+#include "shared-module/displayio/__init__.h"
+#include "supervisor/shared/display.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "tick.h"
+
+void displayio_display_core_construct(displayio_display_core_t* self,
+ mp_obj_t bus, uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, int16_t colstart, int16_t rowstart, uint16_t rotation,
+ uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte) {
+ self->colorspace.depth = color_depth;
+ self->colorspace.grayscale = grayscale;
+ self->colorspace.pixels_in_byte_share_row = pixels_in_byte_share_row;
+ self->colorspace.bytes_per_cell = bytes_per_cell;
+ self->colorspace.reverse_pixels_in_byte = reverse_pixels_in_byte;
+ self->colorspace.dither = false;
+ self->current_group = NULL;
+ self->colstart = colstart;
+ self->rowstart = rowstart;
+ self->last_refresh = 0;
+
+ if (MP_OBJ_IS_TYPE(bus, &displayio_parallelbus_type)) {
+ self->bus_reset = common_hal_displayio_parallelbus_reset;
+ self->bus_free = common_hal_displayio_parallelbus_bus_free;
+ self->begin_transaction = common_hal_displayio_parallelbus_begin_transaction;
+ self->send = common_hal_displayio_parallelbus_send;
+ self->end_transaction = common_hal_displayio_parallelbus_end_transaction;
+ } else if (MP_OBJ_IS_TYPE(bus, &displayio_fourwire_type)) {
+ self->bus_reset = common_hal_displayio_fourwire_reset;
+ self->bus_free = common_hal_displayio_fourwire_bus_free;
+ self->begin_transaction = common_hal_displayio_fourwire_begin_transaction;
+ self->send = common_hal_displayio_fourwire_send;
+ self->end_transaction = common_hal_displayio_fourwire_end_transaction;
+ } else if (MP_OBJ_IS_TYPE(bus, &displayio_i2cdisplay_type)) {
+ self->bus_reset = common_hal_displayio_i2cdisplay_reset;
+ self->bus_free = common_hal_displayio_i2cdisplay_bus_free;
+ self->begin_transaction = common_hal_displayio_i2cdisplay_begin_transaction;
+ self->send = common_hal_displayio_i2cdisplay_send;
+ self->end_transaction = common_hal_displayio_i2cdisplay_end_transaction;
+ } else {
+ mp_raise_ValueError(translate("Unsupported display bus type"));
+ }
+ self->bus = bus;
+
+
+ supervisor_start_terminal(width, height);
+
+ self->width = width;
+ self->height = height;
+ self->ram_width = ram_width;
+ self->ram_height = ram_height;
+ rotation = rotation % 360;
+ self->rotation = rotation;
+ self->transform.x = 0;
+ self->transform.y = 0;
+ self->transform.scale = 1;
+ self->transform.mirror_x = false;
+ self->transform.mirror_y = false;
+ self->transform.transpose_xy = false;
+ if (rotation == 0 || rotation == 180) {
+ if (rotation == 180) {
+ self->transform.mirror_x = true;
+ self->transform.mirror_y = true;
+ }
+ } else {
+ self->transform.transpose_xy = true;
+ if (rotation == 270) {
+ self->transform.mirror_y = true;
+ } else {
+ self->transform.mirror_x = true;
+ }
+ }
+
+ self->area.x1 = 0;
+ self->area.y1 = 0;
+ self->area.next = NULL;
+
+ self->transform.dx = 1;
+ self->transform.dy = 1;
+ if (self->transform.transpose_xy) {
+ self->area.x2 = height;
+ self->area.y2 = width;
+ if (self->transform.mirror_x) {
+ self->transform.x = height;
+ self->transform.dx = -1;
+ }
+ if (self->transform.mirror_y) {
+ self->transform.y = width;
+ self->transform.dy = -1;
+ }
+ } else {
+ self->area.x2 = width;
+ self->area.y2 = height;
+ if (self->transform.mirror_x) {
+ self->transform.x = width;
+ self->transform.dx = -1;
+ }
+ if (self->transform.mirror_y) {
+ self->transform.y = height;
+ self->transform.dy = -1;
+ }
+ }
+}
+
+bool displayio_display_core_show(displayio_display_core_t* self, displayio_group_t* root_group) {
+ if (root_group == NULL) {
+ if (!circuitpython_splash.in_group) {
+ root_group = &circuitpython_splash;
+ } else if (self->current_group == &circuitpython_splash) {
+ return true;
+ }
+ }
+ if (root_group == self->current_group) {
+ return true;
+ }
+ if (root_group != NULL && root_group->in_group) {
+ return false;
+ }
+ if (self->current_group != NULL) {
+ self->current_group->in_group = false;
+ }
+
+ if (root_group != NULL) {
+ displayio_group_update_transform(root_group, &self->transform);
+ root_group->in_group = true;
+ }
+ self->current_group = root_group;
+ self->full_refresh = true;
+ return true;
+}
+
+uint16_t displayio_display_core_get_width(displayio_display_core_t* self){
+ return self->width;
+}
+
+uint16_t displayio_display_core_get_height(displayio_display_core_t* self){
+ return self->height;
+}
+
+void displayio_display_core_set_dither(displayio_display_core_t* self, bool dither){
+ self->colorspace.dither = dither;
+}
+
+bool displayio_display_core_get_dither(displayio_display_core_t* self){
+ return self->colorspace.dither;
+}
+
+bool displayio_display_core_bus_free(displayio_display_core_t *self) {
+ return self->bus_free(self->bus);
+}
+
+bool displayio_display_core_begin_transaction(displayio_display_core_t* self) {
+ return self->begin_transaction(self->bus);
+}
+
+void displayio_display_core_end_transaction(displayio_display_core_t* self) {
+ self->end_transaction(self->bus);
+}
+
+void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command, uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command, bool data_as_commands, bool always_toggle_chip_select, displayio_area_t* area) {
+ uint16_t x1 = area->x1;
+ uint16_t x2 = area->x2;
+ uint16_t y1 = area->y1;
+ uint16_t y2 = area->y2;
+ // Collapse down the dimension where multiple pixels are in a byte.
+ if (self->colorspace.depth < 8) {
+ uint8_t pixels_per_byte = 8 / self->colorspace.depth;
+ if (self->colorspace.pixels_in_byte_share_row) {
+ x1 /= pixels_per_byte * self->colorspace.bytes_per_cell;
+ x2 /= pixels_per_byte * self->colorspace.bytes_per_cell;
+ } else {
+ y1 /= pixels_per_byte * self->colorspace.bytes_per_cell;
+ y2 /= pixels_per_byte * self->colorspace.bytes_per_cell;
+ }
+ }
+
+ display_chip_select_behavior_t chip_select = CHIP_SELECT_UNTOUCHED;
+ if (always_toggle_chip_select || data_as_commands) {
+ chip_select = CHIP_SELECT_TOGGLE_EVERY_BYTE;
+ }
+
+ // Set column.
+ displayio_display_core_begin_transaction(self);
+ uint8_t data[5];
+ data[0] = column_command;
+ uint8_t data_length = 1;
+ display_byte_type_t data_type = DISPLAY_DATA;
+ if (!data_as_commands) {
+ self->send(self->bus, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, data, 1);
+ data_length = 0;
+ } else {
+ data_type = DISPLAY_COMMAND;
+ }
+ if (self->ram_width < 0x100) {
+ data[data_length++] = x1 + self->colstart;
+ data[data_length++] = x2 - 1 + self->colstart;
+ } else {
+ x1 += self->colstart;
+ x2 += self->colstart - 1;
+ data[data_length++] = x1 >> 8;
+ data[data_length++] = x1 & 0xff;
+ data[data_length++] = x2 >> 8;
+ data[data_length++] = x2 & 0xff;
+ }
+ self->send(self->bus, data_type, chip_select, data, data_length);
+ displayio_display_core_end_transaction(self);
+ if (set_current_column_command != NO_COMMAND) {
+ uint8_t command = set_current_column_command;
+ displayio_display_core_begin_transaction(self);
+ self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1);
+ self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2);
+ displayio_display_core_end_transaction(self);
+ }
+
+
+ // Set row.
+ displayio_display_core_begin_transaction(self);
+ data[0] = row_command;
+ data_length = 1;
+ if (!data_as_commands) {
+ self->send(self->bus, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, data, 1);
+ data_length = 0;
+ }
+ if (self->ram_height < 0x100) {
+ data[data_length++] = y1 + self->rowstart;
+ data[data_length++] = y2 - 1 + self->rowstart;
+ } else {
+ y1 += self->rowstart;
+ y2 += self->rowstart - 1;
+ data[data_length++] = y1 >> 8;
+ data[data_length++] = y1 & 0xff;
+ data[data_length++] = y2 >> 8;
+ data[data_length++] = y2 & 0xff;
+ }
+ self->send(self->bus, data_type, chip_select, data, data_length);
+ displayio_display_core_end_transaction(self);
+
+ if (set_current_row_command != NO_COMMAND) {
+ uint8_t command = set_current_row_command;
+ displayio_display_core_begin_transaction(self);
+ self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1);
+ self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2);
+ displayio_display_core_end_transaction(self);
+ }
+}
+
+void displayio_display_core_start_refresh(displayio_display_core_t* self) {
+ self->last_refresh = ticks_ms;
+}
+
+void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
+ if (self->current_group != NULL) {
+ displayio_group_finish_refresh(self->current_group);
+ }
+ self->full_refresh = false;
+ self->last_refresh = ticks_ms;
+}
+
+void release_display_core(displayio_display_core_t* self) {
+ if (self->current_group != NULL) {
+ self->current_group->in_group = false;
+ }
+}
+
+void displayio_display_core_collect_ptrs(displayio_display_core_t* self) {
+ gc_collect_ptr(self->current_group);
+}
+
+bool displayio_display_core_fill_area(displayio_display_core_t *self, displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
+ return displayio_group_fill_area(self->current_group, &self->colorspace, area, mask, buffer);
+}
+
+bool displayio_display_core_clip_area(displayio_display_core_t *self, const displayio_area_t* area, displayio_area_t* clipped) {
+ bool overlaps = displayio_area_compute_overlap(&self->area, area, clipped);
+ if (!overlaps) {
+ return false;
+ }
+ // Expand the area if we have multiple pixels per byte and we need to byte
+ // align the bounds.
+ if (self->colorspace.depth < 8) {
+ uint8_t pixels_per_byte = 8 / self->colorspace.depth * self->colorspace.bytes_per_cell;
+ if (self->colorspace.pixels_in_byte_share_row) {
+ if (clipped->x1 % pixels_per_byte != 0) {
+ clipped->x1 -= clipped->x1 % pixels_per_byte;
+ }
+ if (clipped->x2 % pixels_per_byte != 0) {
+ clipped->x2 += pixels_per_byte - clipped->x2 % pixels_per_byte;
+ }
+ } else {
+ if (clipped->y1 % pixels_per_byte != 0) {
+ clipped->y1 -= clipped->y1 % pixels_per_byte;
+ }
+ if (clipped->y2 % pixels_per_byte != 0) {
+ clipped->y2 += pixels_per_byte - clipped->y2 % pixels_per_byte;
+ }
+ }
+ }
+ return true;
+}
diff --git a/shared-module/displayio/display_core.h b/shared-module/displayio/display_core.h
new file mode 100644
index 000000000..3a69cd40a
--- /dev/null
+++ b/shared-module/displayio/display_core.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_CORE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_CORE_H
+
+#include "shared-bindings/displayio/__init__.h"
+#include "shared-bindings/displayio/Group.h"
+
+#include "shared-module/displayio/area.h"
+
+#define NO_COMMAND 0x100
+
+typedef struct {
+ mp_obj_t bus;
+ displayio_group_t *current_group;
+ uint64_t last_refresh;
+ display_bus_bus_reset bus_reset;
+ display_bus_bus_free bus_free;
+ display_bus_begin_transaction begin_transaction;
+ display_bus_send send;
+ display_bus_end_transaction end_transaction;
+ displayio_buffer_transform_t transform;
+ displayio_area_t area;
+ uint16_t width;
+ uint16_t height;
+ uint16_t rotation;
+ uint16_t ram_width;
+ uint16_t ram_height;
+ _displayio_colorspace_t colorspace;
+ int16_t colstart;
+ int16_t rowstart;
+ bool full_refresh; // New group means we need to refresh the whole display.
+} displayio_display_core_t;
+
+void displayio_display_core_construct(displayio_display_core_t* self,
+ mp_obj_t bus, uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, int16_t colstart, int16_t rowstart, uint16_t rotation,
+ uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte);
+
+bool displayio_display_core_show(displayio_display_core_t* self, displayio_group_t* root_group);
+
+uint16_t displayio_display_core_get_width(displayio_display_core_t* self);
+uint16_t displayio_display_core_get_height(displayio_display_core_t* self);
+
+void displayio_display_core_set_dither(displayio_display_core_t* self, bool dither);
+bool displayio_display_core_get_dither(displayio_display_core_t* self);
+
+bool displayio_display_core_bus_free(displayio_display_core_t *self);
+bool displayio_display_core_begin_transaction(displayio_display_core_t* self);
+void displayio_display_core_end_transaction(displayio_display_core_t* self);
+
+void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command, uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command, bool data_as_commands, bool always_toggle_chip_select, displayio_area_t* area);
+
+void release_display_core(displayio_display_core_t* self);
+
+void displayio_display_core_start_refresh(displayio_display_core_t* self);
+void displayio_display_core_finish_refresh(displayio_display_core_t* self);
+
+void displayio_display_core_collect_ptrs(displayio_display_core_t* self);
+
+bool displayio_display_core_fill_area(displayio_display_core_t *self, displayio_area_t* area, uint32_t* mask, uint32_t *buffer);
+
+bool displayio_display_core_clip_area(displayio_display_core_t *self, const displayio_area_t* area, displayio_area_t* clipped);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_CORE_H
diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c
index 313893d97..8060eec4f 100644
--- a/shared-module/os/__init__.c
+++ b/shared-module/os/__init__.c
@@ -128,6 +128,7 @@ mp_obj_t common_hal_os_listdir(const char* path) {
while ((next = mp_iternext(iter_obj)) != MP_OBJ_STOP_ITERATION) {
// next[0] is the filename.
mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL));
+ RUN_BACKGROUND_TASKS;
}
return dir_list;
}
diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c
index 7adf9d032..df92a5dc4 100644
--- a/shared-module/terminalio/Terminal.c
+++ b/shared-module/terminalio/Terminal.c
@@ -35,6 +35,14 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, d
self->font = font;
self->tilegrid = tilegrid;
self->first_row = 0;
+
+ for (uint16_t x = 0; x < self->tilegrid->width_in_tiles; x++) {
+ for (uint16_t y = 0; y < self->tilegrid->height_in_tiles; y++) {
+ common_hal_displayio_tilegrid_set_tile(self->tilegrid, x, y, 0);
+ }
+ }
+
+ common_hal_displayio_tilegrid_set_top_left(self->tilegrid, 0, 1);
}
size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) {
diff --git a/ports/nrf/common-hal/touchio/TouchIn.c b/shared-module/touchio/TouchIn.c
index ba50b17b0..88d12b8b8 100644
--- a/ports/nrf/common-hal/touchio/TouchIn.c
+++ b/shared-module/touchio/TouchIn.c
@@ -28,15 +28,9 @@
#include <string.h>
#include <stdio.h>
-#include "py/nlr.h"
-#include "py/mperrno.h"
#include "py/runtime.h"
-#include "py/binary.h"
#include "py/mphal.h"
#include "shared-bindings/touchio/TouchIn.h"
-#include "supervisor/shared/translate.h"
-
-#include "nrf.h"
// This is a capacitive touch sensing routine using a single digital
// pin. The pin should be connected to the sensing pad, and to ground
@@ -57,15 +51,14 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
for (uint16_t i = 0; i < N_SAMPLES; i++) {
// set pad to digital output high for 10us to charge it
- nrf_gpio_cfg_output(self->pin->number);
- nrf_gpio_pin_set(self->pin->number);
+ common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, true, DRIVE_MODE_PUSH_PULL);
mp_hal_delay_us(10);
// set pad back to an input and take some samples
- nrf_gpio_cfg_input(self->pin->number, NRF_GPIO_PIN_NOPULL);
+ common_hal_digitalio_digitalinout_switch_to_input(self->digitalinout, PULL_NONE);
- while(nrf_gpio_pin_read(self->pin->number)) {
+ while(common_hal_digitalio_digitalinout_get_value(self->digitalinout)) {
if (ticks >= TIMEOUT_TICKS) return TIMEOUT_TICKS;
ticks++;
}
@@ -73,16 +66,22 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
return ticks;
}
-void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self,
- const mcu_pin_obj_t *pin) {
- self->pin = pin;
+void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self, const mcu_pin_obj_t *pin) {
claim_pin(pin);
+ self->digitalinout = m_new_obj(digitalio_digitalinout_obj_t);
+ self->digitalinout->base.type = &digitalio_digitalinout_type;
+
+ common_hal_digitalio_digitalinout_construct(self->digitalinout, pin);
- self->threshold = get_raw_reading(self) * 1.05 + 100;
+ uint16_t raw_reading = get_raw_reading(self);
+ if (raw_reading == TIMEOUT_TICKS) {
+ mp_raise_ValueError(translate("No pulldown on pin; 1Mohm recommended"));
+ }
+ self->threshold = raw_reading * 1.05 + 100;
}
bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t* self) {
- return self->pin == NULL;
+ return self->digitalinout == MP_OBJ_NULL;
}
void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t* self) {
@@ -90,8 +89,8 @@ void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t* self) {
return;
}
- reset_pin_number(self->pin->number);
- self->pin = NULL;
+ common_hal_digitalio_digitalinout_deinit(self->digitalinout);
+ self->digitalinout = MP_OBJ_NULL;
}
void touchin_reset() {
diff --git a/ports/nrf/common-hal/touchio/TouchIn.h b/shared-module/touchio/TouchIn.h
index 121580eac..8ff6fda8f 100644
--- a/ports/nrf/common-hal/touchio/TouchIn.h
+++ b/shared-module/touchio/TouchIn.h
@@ -25,19 +25,20 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_TOUCHIO_TOUCHIN_H
-#define MICROPY_INCLUDED_NRF_COMMON_HAL_TOUCHIO_TOUCHIN_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_TOUCHIO_TOUCHIN_H
+#define MICROPY_INCLUDED_SHARED_MODULE_TOUCHIO_TOUCHIN_H
#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
- const mcu_pin_obj_t *pin;
+ digitalio_digitalinout_obj_t *digitalinout;
uint16_t threshold;
} touchio_touchin_obj_t;
void touchin_reset(void);
-#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_TOUCHIO_TOUCHIN_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_TOUCHIO_TOUCHIN_H
diff --git a/ports/nrf/common-hal/touchio/__init__.c b/shared-module/touchio/__init__.c
index d2290447c..d2290447c 100644
--- a/ports/nrf/common-hal/touchio/__init__.c
+++ b/shared-module/touchio/__init__.c
diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c
index 0e256cb5e..bed7d163f 100644
--- a/shared-module/usb_hid/Device.c
+++ b/shared-module/usb_hid/Device.c
@@ -47,15 +47,17 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t*
// Wait until interface is ready, timeout = 2 seconds
uint64_t end_ticks = ticks_ms + 2000;
- while ( (ticks_ms < end_ticks) && !tud_hid_generic_ready() ) { }
+ while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) {
+ RUN_BACKGROUND_TASKS;
+ }
- if ( !tud_hid_generic_ready() ) {
+ if ( !tud_hid_ready() ) {
mp_raise_msg(&mp_type_OSError, translate("USB Busy"));
}
memcpy(self->report_buffer, report, len);
- if ( !tud_hid_generic_report(self->report_id, self->report_buffer, len) ) {
+ if ( !tud_hid_report(self->report_id, self->report_buffer, len) ) {
mp_raise_msg(&mp_type_OSError, translate("USB Error"));
}
}
@@ -70,7 +72,7 @@ static usb_hid_device_obj_t* get_hid_device(uint8_t report_id) {
}
// Callbacks invoked when receive Get_Report request through control endpoint
-uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
+uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
// only support Input Report
if ( report_type != HID_REPORT_TYPE_INPUT ) return 0;
@@ -80,7 +82,7 @@ uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t repo
}
// Callbacks invoked when receive Set_Report request through control endpoint
-void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
+void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
usb_hid_device_obj_t* hid_device = get_hid_device(report_id);
if ( report_type == HID_REPORT_TYPE_OUTPUT ) {
diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c
index f14fdd41e..d88f9787a 100644
--- a/shared-module/usb_hid/__init__.c
+++ b/shared-module/usb_hid/__init__.c
@@ -24,131 +24,4 @@
* THE SOFTWARE.
*/
-#include "py/obj.h"
-#include "py/mphal.h"
-#include "py/runtime.h"
-
-#include "genhdr/autogen_usb_descriptor.h"
-#include "shared-module/usb_hid/Device.h"
-#include "shared-bindings/usb_hid/Device.h"
-#include "tusb.h"
-
-#ifdef USB_HID_REPORT_ID_KEYBOARD
-static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD];
-#endif
-
-#ifdef USB_HID_REPORT_ID_MOUSE
-static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE];
-#endif
-
-#ifdef USB_HID_REPORT_ID_CONSUMER
-static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER];
-#endif
-
-#ifdef USB_HID_REPORT_ID_SYS_CONTROL
-static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL];
-#endif
-
-#ifdef USB_HID_REPORT_ID_GAMEPAD
-static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD];
-#endif
-
-#ifdef USB_HID_REPORT_ID_DIGITIZER
-static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER];
-#endif
-
-usb_hid_device_obj_t usb_hid_devices[] = {
-#ifdef USB_HID_REPORT_ID_KEYBOARD
- {
- .base = { .type = &usb_hid_device_type } ,
- .report_buffer = keyboard_report_buffer ,
- .report_id = USB_HID_REPORT_ID_KEYBOARD ,
- .report_length = USB_HID_REPORT_LENGTH_KEYBOARD ,
- .usage_page = HID_USAGE_PAGE_DESKTOP ,
- .usage = HID_USAGE_DESKTOP_KEYBOARD ,
- },
-#endif
-
-#ifdef USB_HID_REPORT_ID_MOUSE
- {
- .base = { .type = &usb_hid_device_type } ,
- .report_buffer = mouse_report_buffer ,
- .report_id = USB_HID_REPORT_ID_MOUSE ,
- .report_length = USB_HID_REPORT_LENGTH_MOUSE ,
- .usage_page = HID_USAGE_PAGE_DESKTOP ,
- .usage = HID_USAGE_DESKTOP_MOUSE ,
- },
-#endif
-
-#ifdef USB_HID_REPORT_ID_CONSUMER
- {
- .base = { .type = &usb_hid_device_type } ,
- .report_buffer = consumer_report_buffer ,
- .report_id = USB_HID_REPORT_ID_CONSUMER ,
- .report_length = USB_HID_REPORT_LENGTH_CONSUMER ,
- .usage_page = HID_USAGE_PAGE_CONSUMER ,
- .usage = HID_USAGE_CONSUMER_CONTROL ,
- },
-#endif
-
-#ifdef USB_HID_REPORT_ID_SYS_CONTROL
- {
- .base = { .type = &usb_hid_device_type } ,
- .report_buffer = sys_control_report_buffer ,
- .report_id = USB_HID_REPORT_ID_SYS_CONTROL ,
- .report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL ,
- .usage_page = HID_USAGE_PAGE_DESKTOP ,
- .usage = HID_USAGE_DESKTOP_SYSTEM_CONTROL ,
- },
-#endif
-
-#ifdef USB_HID_REPORT_ID_GAMEPAD
- {
- .base = { .type = &usb_hid_device_type } ,
- .report_buffer = gamepad_report_buffer ,
- .report_id = USB_HID_REPORT_ID_GAMEPAD ,
- .report_length = USB_HID_REPORT_LENGTH_GAMEPAD ,
- .usage_page = HID_USAGE_PAGE_DESKTOP ,
- .usage = HID_USAGE_DESKTOP_GAMEPAD ,
- },
-#endif
-
-#ifdef USB_HID_REPORT_ID_DIGITIZER
- {
- .base = { .type = &usb_hid_device_type } ,
- .report_buffer = digitizer_report_buffer ,
- .report_id = USB_HID_REPORT_ID_DIGITIZER ,
- .report_length = USB_HID_REPORT_LENGTH_DIGITIZER ,
- .usage_page = 0x0D ,
- .usage = 0x02 ,
- },
-#endif
-};
-
-
-mp_obj_tuple_t common_hal_usb_hid_devices = {
- .base = {
- .type = &mp_type_tuple,
- },
- .len = USB_HID_NUM_DEVICES,
- .items = {
-#if USB_HID_NUM_DEVICES >= 1
- (mp_obj_t) &usb_hid_devices[0],
-#endif
-#if USB_HID_NUM_DEVICES >= 2
- (mp_obj_t) &usb_hid_devices[1],
-#endif
-#if USB_HID_NUM_DEVICES >= 3
- (mp_obj_t) &usb_hid_devices[2],
-#endif
-#if USB_HID_NUM_DEVICES >= 4
- (mp_obj_t) &usb_hid_devices[3],
-#endif
-#if USB_HID_NUM_DEVICES >= 5
- (mp_obj_t) &usb_hid_devices[4],
-#endif
-#if USB_HID_NUM_DEVICES >= 6
- (mp_obj_t) &usb_hid_devices[5],
-#endif
- }
-};
+// Nothing needed here. Tables of HID devices are generated in autogen_usb_descriptor.c at compile-time.
diff --git a/shared-module/usb_midi/PortOut.c b/shared-module/usb_midi/PortOut.c
index 99a4fad43..0b37dcfd4 100644
--- a/shared-module/usb_midi/PortOut.c
+++ b/shared-module/usb_midi/PortOut.c
@@ -33,5 +33,5 @@ size_t common_hal_usb_midi_portout_write(usb_midi_portout_obj_t *self, const uin
}
bool common_hal_usb_midi_portout_ready_to_tx(usb_midi_portout_obj_t *self) {
- return tud_midi_connected();
+ return tud_midi_mounted();
}
diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c
index 414f85034..c6fda0f16 100644
--- a/supervisor/shared/display.c
+++ b/supervisor/shared/display.c
@@ -82,8 +82,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) {
grid->pixel_height = height_in_tiles * grid->tile_height;
grid->tiles = tiles;
- supervisor_terminal.cursor_x = 0;
- supervisor_terminal.cursor_y = 0;
+ common_hal_terminalio_terminal_construct(&supervisor_terminal, grid, &supervisor_terminal_font);
}
void supervisor_stop_terminal(void) {
@@ -147,17 +146,61 @@ displayio_bitmap_t blinka_bitmap = {
.read_only = true
};
-uint32_t blinka_transparency[1] = {0x80000000};
-
-// These colors are RGB 565 with the bytes swapped.
-uint32_t blinka_colors[8] = {0x78890000, 0x9F86B8FC, 0xffff0D5A, 0x0000f501,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000};
+_displayio_color_t blinka_colors[7] = {
+ {
+ .rgb888 = 0x000000,
+ .rgb565 = 0x0000,
+ .luma = 0x00,
+ .chroma = 0,
+ .transparent = true
+ },
+ {
+ .rgb888 = 0x8428bc,
+ .rgb565 = 0x7889,
+ .luma = 0xff, // We cheat the luma here. It is actually 0x60
+ .hue = 184,
+ .chroma = 148
+ },
+ {
+ .rgb888 = 0xff89bc,
+ .rgb565 = 0xB8FC,
+ .luma = 0xb5,
+ .hue = 222,
+ .chroma = 118
+ },
+ {
+ .rgb888 = 0x7beffe,
+ .rgb565 = 0x9F86,
+ .luma = 0xe0,
+ .hue = 124,
+ .chroma = 131
+ },
+ {
+ .rgb888 = 0x51395f,
+ .rgb565 = 0x0D5A,
+ .luma = 0x47,
+ .hue = 185,
+ .chroma = 38
+ },
+ {
+ .rgb888 = 0xffffff,
+ .rgb565 = 0xffff,
+ .luma = 0xff,
+ .chroma = 0
+ },
+ {
+ .rgb888 = 0x0736a0,
+ .rgb565 = 0xf501,
+ .luma = 0x44,
+ .hue = 147,
+ .chroma = 153
+ },
+};
displayio_palette_t blinka_palette = {
.base = {.type = &displayio_palette_type },
- .opaque = blinka_transparency,
.colors = blinka_colors,
- .color_count = 16,
+ .color_count = 7,
.needs_refresh = false
};
@@ -179,7 +222,8 @@ displayio_tilegrid_t blinka_sprite = {
.tiles = 0,
.partial_change = false,
.full_change = false,
- .first_draw = true,
+ .hidden = false,
+ .hidden_by_parent = false,
.moved = false,
.inline_tiles = true,
.in_group = true
@@ -198,5 +242,8 @@ displayio_group_t circuitpython_splash = {
.size = 2,
.max_size = 2,
.children = splash_children,
- .item_removed = false
+ .item_removed = false,
+ .in_group = false,
+ .hidden = false,
+ .hidden_by_parent = false
};
diff --git a/supervisor/shared/display.h b/supervisor/shared/display.h
index d5faa7777..2a2ccf46d 100644
--- a/supervisor/shared/display.h
+++ b/supervisor/shared/display.h
@@ -35,11 +35,10 @@
// These are autogenerated resources.
// This is fixed so it doesn't need to be in RAM.
-extern const displayio_bitmap_t supervisor_terminal_font_bitmap;
-
extern const fontio_builtinfont_t supervisor_terminal_font;
// These will change so they must live in RAM.
+extern displayio_bitmap_t supervisor_terminal_font_bitmap;
extern displayio_tilegrid_t supervisor_terminal_text_grid;
extern terminalio_terminal_obj_t supervisor_terminal;
diff --git a/supervisor/shared/external_flash/devices.h b/supervisor/shared/external_flash/devices.h
index 5b8f9b298..4de22719a 100644
--- a/supervisor/shared/external_flash/devices.h
+++ b/supervisor/shared/external_flash/devices.h
@@ -66,7 +66,7 @@ typedef struct {
bool single_status_byte: 1;
} external_flash_device;
-// Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21
+// Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. It's on the SAMD21
// Xplained board.
// Datasheet: https://www.adestotech.com/wp-content/uploads/doc8715.pdf
#define AT25DF081A {\
@@ -103,6 +103,24 @@ typedef struct {
.single_status_byte = false, \
}
+// Settings for the Gigadevice GD25Q32C 4MiB SPI flash.
+// Datasheet: http://www.elm-tech.com/en/products/spi-flash-memory/gd25q32/gd25q32.pdf
+#define GD25Q32C {\
+ .total_size = (1 << 22), /* 4 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xc8, \
+ .memory_type = 0x40, \
+ .capacity = 0x16, \
+ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = true, \
+ .single_status_byte = false, \
+}
+
// Settings for the Gigadevice GD25Q64C 8MiB SPI flash.
// Datasheet: http://www.elm-tech.com/en/products/spi-flash-memory/gd25q64/gd25q64.pdf
#define GD25Q64C {\
@@ -424,4 +442,5 @@ typedef struct {
.write_status_register_split = false, \
.single_status_byte = false, \
}
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H
diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c
index ad10bab51..99df553e1 100644
--- a/supervisor/shared/external_flash/external_flash.c
+++ b/supervisor/shared/external_flash/external_flash.c
@@ -428,6 +428,7 @@ static bool flush_ram_cache(bool keep_cache) {
}
// Delegates to the correct flash flush method depending on the existing cache.
+// TODO Don't blink the status indicator if we don't actually do any writing (hard to tell right now).
static void spi_flash_flush_keep_cache(bool keep_cache) {
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c
index 0e69cd2e0..4d9371516 100644
--- a/supervisor/shared/rgb_led_status.c
+++ b/supervisor/shared/rgb_led_status.c
@@ -39,8 +39,11 @@ static digitalio_digitalinout_obj_t status_neopixel;
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
uint8_t rgb_status_brightness = 255;
-static uint8_t status_apa102_color[12] = {0, 0, 0, 0, 0xff, 0, 0, 0};
-#ifdef CIRCUITPY_BITBANG_APA102
+
+#define APA102_BUFFER_LENGTH 12
+static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff};
+
+#if CIRCUITPY_BITBANG_APA102
#include "shared-bindings/bitbangio/SPI.h"
#include "shared-module/bitbangio/types.h"
static bitbangio_spi_obj_t status_apa102;
@@ -81,7 +84,7 @@ void rgb_led_status_init() {
common_hal_digitalio_digitalinout_switch_to_output(&status_neopixel, false, DRIVE_MODE_PUSH_PULL);
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
- #ifdef CIRCUITPY_BITBANG_APA102
+ #if CIRCUITPY_BITBANG_APA102
shared_module_bitbangio_spi_construct(&status_apa102,
MICROPY_HW_APA102_SCK,
MICROPY_HW_APA102_MOSI,
@@ -102,12 +105,14 @@ void rgb_led_status_init() {
// mark them as used.
apa102_mosi_in_use = false;
apa102_sck_in_use = false;
- #ifdef CIRCUITPY_BITBANG_APA102
+ #if CIRCUITPY_BITBANG_APA102
shared_module_bitbangio_spi_try_lock(&status_apa102);
- shared_module_bitbangio_spi_configure(&status_apa102, 100000, 0, 1, 8);
+ // Use 1MHz for clock rate. Some APA102's are spec'd 800kHz-1200kHz,
+ // though many can run much faster. bitbang will probably run slower.
+ shared_module_bitbangio_spi_configure(&status_apa102, 1000000, 0, 0, 8);
#else
common_hal_busio_spi_try_lock(&status_apa102);
- common_hal_busio_spi_configure(&status_apa102, 100000, 0, 1, 8);
+ common_hal_busio_spi_configure(&status_apa102, 1000000, 0, 0, 8);
#endif
#endif
@@ -120,7 +125,7 @@ void rgb_led_status_init() {
common_hal_pulseio_pwmout_never_reset(&rgb_status_r);
}
}
-
+
if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_G)) {
pwmout_result_t green_result = common_hal_pulseio_pwmout_construct(&rgb_status_g, CP_RGB_STATUS_G, 0, 50000, false);
@@ -185,10 +190,10 @@ void new_status_color(uint32_t rgb) {
status_apa102_color[6] = (rgb_adjusted >> 8) & 0xff;
status_apa102_color[7] = (rgb_adjusted >> 16) & 0xff;
- #ifdef CIRCUITPY_BITBANG_APA102
- shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, 8);
+ #if CIRCUITPY_BITBANG_APA102
+ shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH);
#else
- common_hal_busio_spi_write(&status_apa102, status_apa102_color, 8);
+ common_hal_busio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH);
#endif
#endif
@@ -229,20 +234,20 @@ void temp_status_color(uint32_t rgb) {
if (apa102_mosi_in_use || apa102_sck_in_use) {
return;
}
- uint8_t colors[12] = {0, 0, 0, 0, 0xff, rgb_adjusted & 0xff, (rgb_adjusted >> 8) & 0xff, (rgb_adjusted >> 16) & 0xff, 0x0, 0x0, 0x0, 0x0};
- #ifdef CIRCUITPY_BITBANG_APA102
- shared_module_bitbangio_spi_write(&status_apa102, colors, 12);
+ uint8_t colors[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, rgb_adjusted & 0xff, (rgb_adjusted >> 8) & 0xff, (rgb_adjusted >> 16) & 0xff, 0xff, 0xff, 0xff, 0xff};
+ #if CIRCUITPY_BITBANG_APA102
+ shared_module_bitbangio_spi_write(&status_apa102, colors, APA102_BUFFER_LENGTH);
#else
- common_hal_busio_spi_write(&status_apa102, colors, 12);
+ common_hal_busio_spi_write(&status_apa102, colors, APA102_BUFFER_LENGTH);
#endif
#endif
#if defined(CP_RGB_STATUS_LED)
uint8_t red_u8 = (rgb_adjusted >> 16) & 0xFF;
uint8_t green_u8 = (rgb_adjusted >> 8) & 0xFF;
uint8_t blue_u8 = rgb_adjusted & 0xFF;
-
+
uint16_t temp_status_color_rgb[3] = {0};
-
+
#if defined(CP_RGB_STATUS_INVERTED_PWM)
temp_status_color_rgb[0] = (1 << 16) - 1 - ((uint16_t) (red_u8 << 8) + red_u8);
temp_status_color_rgb[1] = (1 << 16) - 1 - ((uint16_t) (green_u8 << 8) + green_u8);
@@ -261,13 +266,19 @@ void temp_status_color(uint32_t rgb) {
void clear_temp_status() {
#ifdef MICROPY_HW_NEOPIXEL
+ if (neopixel_in_use) {
+ return;
+ }
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3);
#endif
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
- #ifdef CIRCUITPY_BITBANG_APA102
- shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, 8);
+ if (apa102_mosi_in_use || apa102_sck_in_use) {
+ return;
+ }
+ #if CIRCUITPY_BITBANG_APA102
+ shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH);
#else
- common_hal_busio_spi_write(&status_apa102, status_apa102_color, 8);
+ common_hal_busio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH);
#endif
#endif
#if defined(CP_RGB_STATUS_LED)
diff --git a/supervisor/shared/rgb_led_status.h b/supervisor/shared/rgb_led_status.h
index 83f4822d7..e4e1981a2 100644
--- a/supervisor/shared/rgb_led_status.h
+++ b/supervisor/shared/rgb_led_status.h
@@ -44,7 +44,7 @@
// To work with a NeoPixel, one must have MICROPY_HW_NEOPIXEL defined and
// neopixel_write implemented.
-#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) && !defined(CIRCUITPY_BITBANG_APA102)
+#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) && !CIRCUITPY_BITBANG_APA102
#include "common-hal/busio/SPI.h"
extern busio_spi_obj_t status_apa102;
#endif
diff --git a/supervisor/shared/status_leds.c b/supervisor/shared/status_leds.c
index d99853ceb..672242a96 100644
--- a/supervisor/shared/status_leds.c
+++ b/supervisor/shared/status_leds.c
@@ -26,8 +26,10 @@
#include "supervisor/shared/status_leds.h"
+#if CIRCUITPY_DIGITALIO
#include "common-hal/digitalio/DigitalInOut.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
+#endif
#ifdef MICROPY_HW_LED_RX
digitalio_digitalinout_obj_t rx_led;
diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h
index 301805275..ad5825b6c 100644
--- a/supervisor/shared/usb/tusb_config.h
+++ b/supervisor/shared/usb/tusb_config.h
@@ -107,7 +107,7 @@
// USB RAM PLACEMENT
//--------------------------------------------------------------------+
#define CFG_TUSB_ATTR_USBRAM
-#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
+#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#ifdef __cplusplus
diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c
index 0678a3a3f..c1d70c5b0 100644
--- a/supervisor/shared/usb/usb.c
+++ b/supervisor/shared/usb/usb.c
@@ -25,6 +25,7 @@
*/
#include "tick.h"
+#include "py/objstr.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "shared-module/usb_midi/__init__.h"
#include "supervisor/port.h"
@@ -43,13 +44,11 @@ void load_serial_number(void) {
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
common_hal_mcu_processor_get_uid(raw_id);
- static const char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F'};
for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) {
for (int j = 0; j < 2; j++) {
uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf;
// Strings are UTF-16-LE encoded.
- usb_serial_number[1 + i * 2 + j] = nibble_to_hex[nibble];
+ usb_serial_number[1 + i * 2 + j] = nibble_to_hex_upper[nibble];
}
}
}
diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c
index 5a0de1ffc..9b333d6fe 100644
--- a/supervisor/shared/usb/usb_desc.c
+++ b/supervisor/shared/usb/usb_desc.c
@@ -24,23 +24,35 @@
* THE SOFTWARE.
*/
-#include "supervisor/shared/usb/usb_desc.h"
+#include "lib/tinyusb/src/tusb.h"
#include "shared-module/usb_hid/Device.h"
#include "genhdr/autogen_usb_descriptor.h"
-// tud_desc_set is required by tinyusb stack
-tud_desc_set_t tud_desc_set =
-{
- .device = &usb_desc_dev,
- .config = &usb_desc_cfg,
- .string_arr = (uint8_t const **) string_desc_arr,
- .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
+// Invoked when received GET DEVICE DESCRIPTOR
+// Application return pointer to descriptor
+uint8_t const * tud_descriptor_device_cb(void) {
+ return usb_desc_dev;
+}
- .hid_report =
- {
- .generic = hid_report_descriptor,
- .boot_keyboard = NULL,
- .boot_mouse = NULL
- }
-};
+// Invoked when received GET CONFIGURATION DESCRIPTOR
+// Application return pointer to descriptor
+// Descriptor contents must exist long enough for transfer to complete
+uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
+ (void) index; // for multiple configurations
+ return usb_desc_cfg;
+}
+
+// Invoked when received GET HID REPORT DESCRIPTOR
+// Application return pointer to descriptor
+// Descriptor contents must exist long enough for transfer to complete
+uint8_t const * tud_hid_descriptor_report_cb(void) {
+ return hid_report_descriptor;
+}
+
+// Invoked when received GET STRING DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+uint16_t const* tud_descriptor_string_cb(uint8_t index) {
+ uint8_t const max_index = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]);
+ return (index < max_index) ? string_desc_arr[index] : NULL;
+}
diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c
index f6f0fa9c3..205cb7b50 100644
--- a/supervisor/shared/usb/usb_msc_flash.c
+++ b/supervisor/shared/usb/usb_msc_flash.c
@@ -59,59 +59,18 @@ static fs_user_mount_t* get_vfs(int lun) {
}
// Callback invoked when received an SCSI command not in built-in list below
-// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
+// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE
// - READ10 and WRITE10 have their own callbacks
int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, uint16_t bufsize) {
const void* response = NULL;
int32_t resplen = 0;
switch ( scsi_cmd[0] ) {
- case SCSI_CMD_TEST_UNIT_READY:
- // Command that host uses to check our readiness before sending other commands
- resplen = 0;
- if (lun > 1) {
- resplen = -1;
- } else {
- fs_user_mount_t* current_mount = get_vfs(lun);
- if (current_mount == NULL) {
- resplen = -1;
- }
- if (ejected[lun]) {
- resplen = -1;
- }
- }
- break;
-
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
// Host is about to read/write etc ... better not to disconnect disk
resplen = 0;
break;
- case SCSI_CMD_START_STOP_UNIT:
- {
- // Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power
- const scsi_start_stop_unit_t* start_stop = (const scsi_start_stop_unit_t*) scsi_cmd;
- // Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well
- // Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage
- resplen = 0;
- if (start_stop->load_eject == 1) {
- if (lun > 1) {
- resplen = -1;
- } else {
- fs_user_mount_t* current_mount = get_vfs(lun);
- if (current_mount == NULL) {
- resplen = -1;
- }
- if (disk_ioctl(current_mount, CTRL_SYNC, NULL) != RES_OK) {
- resplen = -1;
- } else {
- ejected[lun] = true;
- }
- }
- }
- }
- break;
-
default:
// Set Sense = Invalid Command Operation
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
@@ -127,7 +86,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer,
}
// copy response to stack's buffer if any
- if ( response && resplen ) {
+ if ( response && (resplen > 0) ) {
memcpy(buffer, response, resplen);
}
@@ -206,3 +165,54 @@ void tud_msc_write10_complete_cb (uint8_t lun) {
// This write is complete, start the autoreload clock.
autoreload_start();
}
+
+// Invoked when received SCSI_CMD_INQUIRY
+// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
+void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
+ (void) lun;
+
+ memcpy(vendor_id , CFG_TUD_MSC_VENDOR , strlen(CFG_TUD_MSC_VENDOR));
+ memcpy(product_id , CFG_TUD_MSC_PRODUCT , strlen(CFG_TUD_MSC_PRODUCT));
+ memcpy(product_rev, CFG_TUD_MSC_PRODUCT_REV, strlen(CFG_TUD_MSC_PRODUCT_REV));
+}
+
+// Invoked when received Test Unit Ready command.
+// return true allowing host to read/write this LUN e.g SD card inserted
+bool tud_msc_test_unit_ready_cb(uint8_t lun) {
+ if (lun > 1) {
+ return false;
+ }
+
+ fs_user_mount_t* current_mount = get_vfs(lun);
+ if (current_mount == NULL) {
+ return false;
+ }
+ if (ejected[lun]) {
+ return false;
+ }
+
+ return true;
+}
+
+// Invoked when received Start Stop Unit command
+// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
+// - Start = 1 : active mode, if load_eject = 1 : load disk storage
+bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
+ if (load_eject) {
+ if (lun > 1) {
+ return false;
+ } else {
+ fs_user_mount_t* current_mount = get_vfs(lun);
+ if (current_mount == NULL) {
+ return false;
+ }
+ if (disk_ioctl(current_mount, CTRL_SYNC, NULL) != RES_OK) {
+ return false;
+ } else {
+ ejected[lun] = true;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/supervisor/stub/internal_flash.c b/supervisor/stub/internal_flash.c
new file mode 100644
index 000000000..5db6b5bc0
--- /dev/null
+++ b/supervisor/stub/internal_flash.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "supervisor/internal_flash.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat.h"
+#include "py/mphal.h"
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "lib/oofatfs/ff.h"
+
+void supervisor_flash_init(void) {
+}
+
+uint32_t supervisor_flash_get_block_size(void) {
+ return 0;
+}
+
+uint32_t supervisor_flash_get_block_count(void) {
+ return 0;
+}
+
+void supervisor_flash_flush(void) {
+}
+
+mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
+ return 0; // success
+}
+
+bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
+ return true;
+}
+
+mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
+ return 0; // success
+}
+
+void supervisor_flash_release_cache(void) {
+}
+
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index 2d50e7a8b..ee47be4b0 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -13,7 +13,7 @@ SRC_SUPERVISOR = \
supervisor/shared/translate.c
ifndef $(NO_USB)
-NO_USB = $(wildcard supervisor/usb.c)
+ NO_USB = $(wildcard supervisor/usb.c)
endif
ifneq ($(INTERNAL_FLASH_FILESYSTEM),)
@@ -44,7 +44,11 @@ ifdef EXTERNAL_FLASH_DEVICES
SRC_SUPERVISOR += supervisor/qspi_flash.c supervisor/shared/external_flash/qspi_flash.c
endif
else
- SRC_SUPERVISOR += supervisor/internal_flash.c
+ ifeq ($(DISABLE_FILESYSTEM),1)
+ SRC_SUPERVISOR += supervisor/stub/internal_flash.c
+ else
+ SRC_SUPERVISOR += supervisor/internal_flash.c
+ endif
endif
ifeq ($(USB),FALSE)
@@ -78,9 +82,23 @@ else
shared-module/usb_midi/PortIn.c \
shared-module/usb_midi/PortOut.c \
$(BUILD)/autogen_usb_descriptor.c
+
CFLAGS += -DUSB_AVAILABLE
endif
+ifndef USB_DEVICES
+USB_DEVICES = "CDC,MSC,AUDIO,HID"
+endif
+
+ifndef USB_HID_DEVICES
+USB_HID_DEVICES = "KEYBOARD,MOUSE,CONSUMER,GAMEPAD"
+endif
+
+# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
+ifndef USB_MSC_NUM_ENDPOINT_PAIRS
+USB_MSC_NUM_ENDPOINT_PAIRS = 1
+endif
+
SUPERVISOR_O = $(addprefix $(BUILD)/, $(SRC_SUPERVISOR:.c=.o)) $(BUILD)/autogen_display_resources.o
$(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h
@@ -98,6 +116,9 @@ autogen_usb_descriptor.intermediate: ../../tools/gen_usb_descriptor.py Makefile
--vid $(USB_VID)\
--pid $(USB_PID)\
--serial_number_length $(USB_SERIAL_NUMBER_LENGTH)\
+ --devices $(USB_DEVICES)\
+ --hid_devices $(USB_HID_DEVICES)\
+ --msc_num_endpoint_pairs $(USB_MSC_NUM_ENDPOINT_PAIRS)\
--output_c_file $(BUILD)/autogen_usb_descriptor.c\
--output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h
diff --git a/tools/build_board_info.py b/tools/build_board_info.py
index 8731a6feb..7d0d2996c 100644
--- a/tools/build_board_info.py
+++ b/tools/build_board_info.py
@@ -12,7 +12,7 @@ from sh.contrib import git
sys.path.append("adabot")
import adabot.github_requests as github
-SUPPORTED_PORTS = ["nrf", "atmel-samd"]
+SUPPORTED_PORTS = ["nrf", "atmel-samd", "stm32f4"]
BIN = ('bin',)
UF2 = ('uf2',)
@@ -23,6 +23,7 @@ HEX = ('hex',)
extension_by_port = {
"nrf": UF2,
"atmel-samd": UF2,
+ "stm32f4": BIN,
}
# Per board overrides
@@ -88,10 +89,8 @@ def get_version_info():
# No exact match
pass
- if "TRAVIS" in os.environ and os.environ["TRAVIS"] == "true":
- sha = os.environ["TRAVIS_COMMIT"]
- if os.environ["TRAVIS_PULL_REQUEST"] != "false":
- sha = os.environ["TRAVIS_PULL_REQUEST_SHA"]
+ if "GITHUB_SHA" in os.environ:
+ sha = os.environ["GITHUB_SHA"]
if not version:
version="{}-{}".format(date.today().strftime("%Y%m%d"), sha[:7])
@@ -119,7 +118,7 @@ def get_current_info():
current_info[info["id"]] = info
return git_info, current_info
-def create_pr(changes, updated, git_info):
+def create_pr(changes, updated, git_info, user):
commit_sha, original_blob_sha = git_info
branch_name = "new_release_" + changes["new_release"]
@@ -132,7 +131,7 @@ def create_pr(changes, updated, git_info):
updated_list.append(info)
updated = json.dumps(updated_list, sort_keys=True, indent=4).encode("utf-8") + b"\n"
- print(updated.decode("utf-8"))
+ #print(updated.decode("utf-8"))
pr_title = "Automated website update for release {}".format(changes["new_release"])
boards = ""
if changes["new_boards"]:
@@ -140,7 +139,7 @@ def create_pr(changes, updated, git_info):
languages = ""
if changes["new_languages"]:
languages = "New languages:\n* " + "\n* ".join(changes["new_languages"])
- message = "Automated website update for release {} by AdaBot.\n\n{}\n\n{}\n".format(
+ message = "Automated website update for release {} by Blinka.\n\n{}\n\n{}\n".format(
changes["new_release"],
boards,
languages
@@ -150,7 +149,7 @@ def create_pr(changes, updated, git_info):
"ref": "refs/heads/" + branch_name,
"sha": commit_sha
}
- response = github.post("/repos/adafruit-adabot/circuitpython-org/git/refs", json=create_branch)
+ response = github.post("/repos/{}/circuitpython-org/git/refs".format(user), json=create_branch)
if not response.ok and response.json()["message"] != "Reference already exists":
print("unable to create branch")
print(response.text)
@@ -163,14 +162,14 @@ def create_pr(changes, updated, git_info):
"branch": branch_name
}
- response = github.put("/repos/adafruit-adabot/circuitpython-org/contents/_data/files.json", json=update_file)
+ response = github.put("/repos/{}/circuitpython-org/contents/_data/files.json".format(user), json=update_file)
if not response.ok:
print("unable to post new file")
print(response.text)
return
pr_info = {
"title": pr_title,
- "head": "adafruit-adabot:" + branch_name,
+ "head": user + ":" + branch_name,
"base": "master",
"body": message,
"maintainer_can_modify": True
@@ -200,15 +199,18 @@ def update_downloads(boards, release):
def print_active_user():
response = github.get("/user")
if response.ok:
- print("Logged in as {}".format(response.json()["login"]))
+ user = response.json()["login"]
+ print("Logged in as {}".format(user))
+ return user
else:
print("Not logged in")
+ return None
def generate_download_info():
boards = {}
errors = []
- new_tag = os.environ["TRAVIS_TAG"]
+ new_tag = os.environ["RELEASE_TAG"]
changes = {
"new_release": new_tag,
@@ -216,7 +218,7 @@ def generate_download_info():
"new_languages": []
}
- print_active_user()
+ user = print_active_user()
sha, this_version = get_version_info()
@@ -240,7 +242,6 @@ def generate_download_info():
board_mapping = get_board_mapping()
- print(previous_releases)
for release in previous_releases:
update_downloads(board_mapping, release)
@@ -274,13 +275,13 @@ def generate_download_info():
changes["new_languages"] = set(languages) - previous_languages
- if changes["new_release"]:
- create_pr(changes, current_info, git_info)
+ if changes["new_release"] and user:
+ create_pr(changes, current_info, git_info, user)
else:
print("No new release to update")
if __name__ == "__main__":
- if "TRAVIS_TAG" in os.environ and os.environ["TRAVIS_TAG"]:
+ if "RELEASE_TAG" in os.environ and os.environ["RELEASE_TAG"]:
generate_download_info()
else:
print("skipping website update because this isn't a tag")
diff --git a/tools/build_release_files.py b/tools/build_release_files.py
index e29b098c7..09133e51f 100755
--- a/tools/build_release_files.py
+++ b/tools/build_release_files.py
@@ -10,21 +10,14 @@ import time
for port in build_info.SUPPORTED_PORTS:
result = subprocess.run("rm -rf ../ports/{port}/build*".format(port=port), shell=True)
-ROSIE_SETUPS = ["rosie-ci"]
-rosie_ok = {}
-for rosie in ROSIE_SETUPS:
- rosie_ok[rosie] = True
-
PARALLEL = "-j 5"
-travis = False
-if "TRAVIS" in os.environ and os.environ["TRAVIS"] == "true":
+if "GITHUB_ACTION" in os.environ:
PARALLEL="-j 2"
- travis = True
all_boards = build_info.get_board_mapping()
build_boards = list(all_boards.keys())
-if "TRAVIS_BOARDS" in os.environ:
- build_boards = os.environ["TRAVIS_BOARDS"].split()
+if "BOARDS" in os.environ:
+ build_boards = os.environ["BOARDS"].split()
sha, version = build_info.get_version_info()
@@ -83,25 +76,14 @@ for board in build_boards:
if exit_status == 0:
exit_status = 1
- if travis:
- print('travis_fold:start:adafruit-bins-{}-{}\\r'.format(language, board))
print("Build {board} for {language}{clean_build} took {build_duration:.2f}s and {success}".format(
board=board, language=language, clean_build=(" (clean_build)" if clean_build else ""),
build_duration=build_duration, success=success))
- if make_result.returncode != 0:
- print(make_result.stdout.decode("utf-8"))
- print(other_output)
- # Only upload to Rosie if its a pull request.
- if travis:
- for rosie in ROSIE_SETUPS:
- if not rosie_ok[rosie]:
- break
- print("Uploading to https://{rosie}.ngrok.io/upload/{sha}".format(rosie=rosie, sha=sha))
- #curl -F "file=@$final_filename" https://$rosie.ngrok.io/upload/$sha
- if travis:
- print('travis_fold:end:adafruit-bins-{}-{}\\r'.format(language, board))
-
- # Flush so travis will see something before 10 minutes has passed.
+
+ print(make_result.stdout.decode("utf-8"))
+ print(other_output)
+
+ # Flush so we will see something before 10 minutes has passed.
print(flush=True)
sys.exit(exit_status)
diff --git a/tools/check_translations.py b/tools/check_translations.py
index 4bea040bf..7c008d3da 100644
--- a/tools/check_translations.py
+++ b/tools/check_translations.py
@@ -16,8 +16,10 @@ for po_filename in po_filenames:
po_file = polib.pofile(po_filename)
po_ids = set([x.msgid for x in po_file])
- if all_ids - po_ids:
+ missing = all_ids - po_ids
+ if missing:
print("Missing message id. Please run `make translate`")
+ print(missing)
sys.exit(-1)
else:
print("ok")
diff --git a/tools/ci_new_boards_check.py b/tools/ci_new_boards_check.py
new file mode 100644
index 000000000..8bb8876fb
--- /dev/null
+++ b/tools/ci_new_boards_check.py
@@ -0,0 +1,51 @@
+#! /usr/bin/env python3
+
+import sys
+import os
+import json
+import yaml
+
+import build_board_info
+
+workflow_file = '.github/workflows/build.yml'
+
+# Get boards in json format
+boards_info_json = build_board_info.get_board_mapping()
+
+# Get all the boards out of the json format
+info_boards = [board for board in boards_info_json.keys() if not boards_info_json[board].get("alias", False)]
+
+# We need to know the path of the workflow file
+base_path = os.path.dirname(__file__)
+yml_path = os.path.abspath(os.path.join(base_path, '..', workflow_file))
+
+# Loading board list based on build jobs in the workflow file.
+ci_boards = []
+with open(yml_path, "r") as f:
+ workflow = yaml.safe_load(f)
+
+ok = True
+for job in workflow["jobs"]:
+ if not job.startswith("build"):
+ continue
+ job_boards = workflow["jobs"][job]["strategy"]["matrix"]["board"]
+ if job_boards != sorted(job_boards):
+ print("Boards for job \"{}\" not sorted. Must be:".format(job))
+ print(" - \"" + "\"\n - \"".join(sorted(job_boards)) + "\"")
+ ok = False
+ ci_boards.extend(job_boards)
+
+# All the travis_boards elements must be on info_boards
+info_boards.sort()
+ci_boards.sort()
+
+missing_boards = set(info_boards) - set(ci_boards)
+
+if missing_boards:
+ ok = False
+ print('Boards missing in {}:'.format(workflow_file))
+ for board in missing_boards:
+ print(board)
+
+if not ok:
+ sys.exit(1)
diff --git a/tools/convert_release_notes.py b/tools/convert_release_notes.py
index 4805f182a..87b7e444b 100644
--- a/tools/convert_release_notes.py
+++ b/tools/convert_release_notes.py
@@ -31,6 +31,11 @@ class AdafruitBBCodeRenderer:
def link(self, link, title, text):
return "[url={}]{}[/url]".format(link, text)
+ def autolink(self, link, is_email):
+ if not is_email:
+ return "[url={}]{}[/url]".format(link, link)
+ return link
+
def header(self, text, level, raw):
return "[b][size=150]{}[/size][/b]\n".format(text)
diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py
index 2c674c8eb..781b5e69b 100644
--- a/tools/gen_display_resources.py
+++ b/tools/gen_display_resources.py
@@ -98,14 +98,23 @@ c_file.write("""\
""")
c_file.write("""\
-uint32_t terminal_transparency[1] = {0x00000000};
-
-// These colors are RGB 565 with the bytes swapped.
-uint32_t terminal_colors[1] = {0xffff0000};
+_displayio_color_t terminal_colors[2] = {
+ {
+ .rgb888 = 0x000000,
+ .rgb565 = 0x0000,
+ .luma = 0x00,
+ .chroma = 0
+ },
+ {
+ .rgb888 = 0xffffff,
+ .rgb565 = 0xffff,
+ .luma = 0xff,
+ .chroma = 0
+ },
+};
displayio_palette_t supervisor_terminal_color = {
.base = {.type = &displayio_palette_type },
- .opaque = terminal_transparency,
.colors = terminal_colors,
.color_count = 2,
.needs_refresh = false
@@ -122,6 +131,7 @@ displayio_tilegrid_t supervisor_terminal_text_grid = {{
.pixel_width = {1},
.pixel_height = {2},
.bitmap_width_in_tiles = {0},
+ .tiles_in_bitmap = {0},
.width_in_tiles = 1,
.height_in_tiles = 1,
.tile_width = {1},
@@ -129,7 +139,8 @@ displayio_tilegrid_t supervisor_terminal_text_grid = {{
.tiles = NULL,
.partial_change = false,
.full_change = false,
- .first_draw = true,
+ .hidden = false,
+ .hidden_by_parent = false,
.moved = false,
.inline_tiles = false,
.in_group = true
@@ -150,7 +161,7 @@ c_file.write("""\
""")
c_file.write("""\
-const displayio_bitmap_t supervisor_terminal_font_bitmap = {{
+displayio_bitmap_t supervisor_terminal_font_bitmap = {{
.base = {{.type = &displayio_bitmap_type }},
.width = {},
.height = {},
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 10bbf5066..c4ff74d39 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -8,6 +8,15 @@ sys.path.append("../../tools/usb_descriptor")
from adafruit_usb_descriptor import audio, audio10, cdc, hid, midi, msc, standard, util
import hid_report_descriptors
+ALL_DEVICES='CDC,MSC,AUDIO,HID'
+ALL_DEVICES_SET=frozenset(ALL_DEVICES.split(','))
+DEFAULT_DEVICES='CDC,MSC,AUDIO,HID'
+
+ALL_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,SYS_CONTROL,GAMEPAD,DIGITIZER,XAC_COMPATIBLE_GAMEPAD,RAW'
+ALL_HID_DEVICES_SET=frozenset(ALL_HID_DEVICES.split(','))
+# Digitizer works on Linux but conflicts with mouse, so omit it.
+DEFAULT_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,GAMEPAD'
+
parser = argparse.ArgumentParser(description='Generate USB descriptors.')
parser.add_argument('--manufacturer', type=str,
help='manufacturer of the device')
@@ -19,11 +28,29 @@ parser.add_argument('--pid', type=lambda x: int(x, 16),
help='product id')
parser.add_argument('--serial_number_length', type=int, default=32,
help='length needed for the serial number in digits')
+parser.add_argument('--devices', type=lambda l: tuple(l.split(',')), default=DEFAULT_DEVICES,
+ help='devices to include in descriptor (AUDIO includes MIDI support)')
+parser.add_argument('--hid_devices', type=lambda l: tuple(l.split(',')), default=DEFAULT_HID_DEVICES,
+ help='HID devices to include in HID report descriptor')
+parser.add_argument('--msc_num_endpoint_pairs', type=int, default=1,
+ help='Use 1 or 2 endpoint pairs for MSC (1 bidirectional, or 1 input + 1 output (required by SAMD21))')
parser.add_argument('--output_c_file', type=argparse.FileType('w'), required=True)
parser.add_argument('--output_h_file', type=argparse.FileType('w'), required=True)
args = parser.parse_args()
+unknown_devices = list(frozenset(args.devices) - ALL_DEVICES_SET)
+if unknown_devices:
+ raise ValueError("Unknown device(s)", unknown_devices)
+
+unknown_hid_devices = list(frozenset(args.hid_devices) - ALL_HID_DEVICES_SET)
+if unknown_hid_devices:
+ raise ValueError("Unknown HID devices(s)", unknown_hid_devices)
+
+if args.msc_num_endpoint_pairs not in (1, 2):
+ raise ValueError("--msc_num_endpoint_pairs must be 1 or 2")
+
+
class StringIndex:
"""Assign a monotonically increasing index to each unique string. Start with 0."""
string_to_index = {}
@@ -131,25 +158,40 @@ msc_interfaces = [
bInterval=0),
standard.EndpointDescriptor(
description="MSC out",
- bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT,
+ # SAMD21 needs to use a separate pair of endpoints for MSC.
+ bEndpointAddress=((0x1 if args.msc_num_endpoint_pairs == 2 else 0x0) |
+ standard.EndpointDescriptor.DIRECTION_OUT),
bmAttributes=standard.EndpointDescriptor.TYPE_BULK,
bInterval=0)
]
)
]
-# Include only these HID devices.
-# DIGITIZER works on Linux but conflicts with MOUSE, so leave it out for now.
-hid_devices = ("KEYBOARD", "MOUSE", "CONSUMER", "GAMEPAD")
-
-combined_hid_report_descriptor = hid.ReportDescriptor(
- description="MULTIDEVICE",
- report_descriptor=b''.join(
- hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor for name in hid_devices ))
-
-hid_report_ids_dict = { name: hid_report_descriptors.REPORT_IDS[name] for name in hid_devices }
-hid_report_lengths_dict = { name: hid_report_descriptors.REPORT_LENGTHS[name] for name in hid_devices }
-hid_max_report_length = max(hid_report_lengths_dict.values())
+# When there's only one hid_device, it shouldn't have a report id.
+# Otherwise, report ids are assigned sequentially:
+# args.hid_devices[0] has report_id 1
+# args.hid_devices[1] has report_id 2
+# etc.
+
+report_ids = {}
+
+if len(args.hid_devices) == 1:
+ name = args.hid_devices[0]
+ combined_hid_report_descriptor = hid.ReportDescriptor(
+ description=name,
+ report_descriptor=bytes(hid_report_descriptors.REPORT_DESCRIPTOR_FUNCTIONS[name](0)))
+ report_ids[name] = 0
+else:
+ report_id = 1
+ concatenated_descriptors = bytearray()
+ for name in args.hid_devices:
+ concatenated_descriptors.extend(
+ bytes(hid_report_descriptors.REPORT_DESCRIPTOR_FUNCTIONS[name](report_id)))
+ report_ids[name] = report_id
+ report_id += 1
+ combined_hid_report_descriptor = hid.ReportDescriptor(
+ description="MULTIDEVICE",
+ report_descriptor=bytes(concatenated_descriptors))
# ASF4 expects keyboard and generic devices to have both in and out endpoints,
# and will fail (possibly silently) if both are not supplied.
@@ -157,7 +199,13 @@ hid_endpoint_in_descriptor = standard.EndpointDescriptor(
description="HID in",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT,
- bInterval=10)
+ bInterval=8)
+
+hid_endpoint_out_descriptor = standard.EndpointDescriptor(
+ description="HID out",
+ bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT,
+ bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT,
+ bInterval=8)
hid_interfaces = [
standard.InterfaceDescriptor(
@@ -171,6 +219,7 @@ hid_interfaces = [
description="HID",
wDescriptorLength=len(bytes(combined_hid_report_descriptor))),
hid_endpoint_in_descriptor,
+ hid_endpoint_out_descriptor,
]
),
]
@@ -250,10 +299,24 @@ 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
-# This will renumber the endpoints to make them unique across descriptors,
+interfaces_to_join = []
+
+if 'CDC' in args.devices:
+ interfaces_to_join.append(cdc_interfaces)
+
+if 'MSC' in args.devices:
+ interfaces_to_join.append(msc_interfaces)
+
+if 'HID' in args.devices:
+ interfaces_to_join.append(hid_interfaces)
+
+if 'AUDIO' in args.devices:
+ interfaces_to_join.append(audio_interfaces)
+
+# util.join_interfaces() 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, audio_interfaces)
+interfaces = util.join_interfaces(*interfaces_to_join)
# Now adjust the CDC interface cross-references.
@@ -271,19 +334,29 @@ cdc_iad = standard.InterfaceAssociationDescriptor(
bFunctionProtocol=cdc.CDC_PROTOCOL_NONE)
descriptor_list = []
-descriptor_list.append(cdc_iad)
-descriptor_list.extend(cdc_interfaces)
-descriptor_list.extend(msc_interfaces)
-# 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
-# first. However, it still fetches the descriptor anyway. We could reorder the interfaces but
-# the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it
-# there for backwards compatibility.
-descriptor_list.extend(hid_interfaces)
+
+if 'CDC' in args.devices:
+ # 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
+ # first. However, it still fetches the descriptor anyway. We could reorder the interfaces but
+ # the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it
+ # there for backwards compatibility.
+ descriptor_list.append(cdc_iad)
+ descriptor_list.extend(cdc_interfaces)
+
+if 'MSC' in args.devices:
+ descriptor_list.extend(msc_interfaces)
+
+if 'HID' in args.devices:
+ descriptor_list.extend(hid_interfaces)
+
+if 'AUDIO' in args.devices:
+ # Only add the control interface because other audio interfaces are managed by it to ensure the
+ # correct ordering.
+ descriptor_list.append(audio_control_interface)
+
+# Finally, build the composite descriptor.
configuration = standard.ConfigurationDescriptor(
description="Composite configuration",
@@ -302,6 +375,8 @@ h_file = args.output_h_file
c_file.write("""\
#include <stdint.h>
+#include "py/objtuple.h"
+#include "shared-bindings/usb_hid/Device.h"
#include "{H_FILE_NAME}"
""".format(H_FILE_NAME=h_file.name))
@@ -420,7 +495,9 @@ const uint8_t usb_desc_cfg[{configuration_length}];
uint16_t usb_serial_number[{serial_number_length}];
uint16_t const * const string_desc_arr [{string_descriptor_length}];
-const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}];
+const uint8_t hid_report_descriptor[{hid_report_descriptor_length}];
+
+#define USB_HID_NUM_DEVICES {hid_num_devices}
// Vendor name included in Inquiry response, max 8 bytes
#define CFG_TUD_MSC_VENDOR "{msc_vendor}"
@@ -434,36 +511,11 @@ const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}];
configuration_length=descriptor_length,
max_configuration_length=max(hid_descriptor_length, descriptor_length),
string_descriptor_length=len(pointers_to_strings),
- HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)),
+ hid_report_descriptor_length=len(bytes(combined_hid_report_descriptor)),
+ hid_num_devices=len(args.hid_devices),
msc_vendor=args.manufacturer[:8],
msc_product=args.product[:16]))
-# #define the report ID's used in the combined HID descriptor
-for name, id in hid_report_ids_dict.items():
- h_file.write("""\
-#define USB_HID_REPORT_ID_{name} {id}
-""".format(name=name,
- id=id))
-
-h_file.write("\n")
-
-# #define the report sizes used in the combined HID descriptor
-for name, length in hid_report_lengths_dict.items():
- h_file.write("""\
-#define USB_HID_REPORT_LENGTH_{name} {length}
-""".format(name=name,
- length=length))
-
-h_file.write("\n")
-
-h_file.write("""\
-#define USB_HID_NUM_DEVICES {num_devices}
-#define USB_HID_MAX_REPORT_LENGTH {max_length}
-""".format(num_devices=len(hid_report_lengths_dict),
- max_length=hid_max_report_length))
-
-
-
# Write out the report descriptor and info
c_file.write("""\
const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{
@@ -471,7 +523,55 @@ const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{
for b in bytes(combined_hid_report_descriptor):
c_file.write("0x{:02x}, ".format(b))
+c_file.write("""\
+};
+
+""")
+
+# Write out USB HID report buffer definitions.
+for name in args.hid_devices:
+ c_file.write("""\
+static uint8_t {name}_report_buffer[{report_length}];
+""".format(name=name.lower(), report_length=hid_report_descriptors.HID_DEVICE_DATA[name].report_length))
+
+# Write out table of device objects.
c_file.write("""
+usb_hid_device_obj_t usb_hid_devices[] = {
+""");
+for name in args.hid_devices:
+ device_data = hid_report_descriptors.HID_DEVICE_DATA[name]
+ c_file.write("""\
+ {{
+ .base = {{ .type = &usb_hid_device_type }},
+ .report_buffer = {name}_report_buffer,
+ .report_id = {report_id},
+ .report_length = {report_length},
+ .usage_page = {usage_page:#04x},
+ .usage = {usage:#04x},
+ }},
+""".format(name=name.lower(), report_id=report_ids[name],
+ report_length=device_data.report_length,
+ usage_page=device_data.usage_page,
+ usage=device_data.usage))
+c_file.write("""\
+};
+""")
+
+# Write out tuple of device objects.
+c_file.write("""
+mp_obj_tuple_t common_hal_usb_hid_devices = {{
+ .base = {{
+ .type = &mp_type_tuple,
+ }},
+ .len = {num_devices},
+ .items = {{
+""".format(num_devices=len(args.hid_devices)))
+for idx in range(len(args.hid_devices)):
+ c_file.write("""\
+ (mp_obj_t) &usb_hid_devices[{idx}],
+""".format(idx=idx))
+c_file.write("""\
+ },
};
""")
diff --git a/tools/hid_report_descriptors.py b/tools/hid_report_descriptors.py
index f3b28ebcf..92c962d59 100644
--- a/tools/hid_report_descriptors.py
+++ b/tools/hid_report_descriptors.py
@@ -29,211 +29,284 @@ HID specific descriptors
* Author(s): Dan Halbert
"""
+from collections import namedtuple
+
from adafruit_usb_descriptor import hid
-REPORT_IDS = {
- "KEYBOARD" : 1,
- "MOUSE" : 2,
- "CONSUMER" : 3,
- "SYS_CONTROL" : 4,
- "GAMEPAD" : 5,
- "DIGITIZER" : 6,
+# Information about each kind of device
+# report_length does not include report ID in first byte, if present when sent.
+DeviceData = namedtuple('DeviceData', ('report_length', 'usage_page', 'usage'))
+HID_DEVICE_DATA = {
+ "KEYBOARD" : DeviceData(report_length=8, usage_page=0x01, usage=0x06), # Generic Desktop, Keyboard
+ "MOUSE" : DeviceData(report_length=4, usage_page=0x01, usage=0x02), # Generic Desktop, Mouse
+ "CONSUMER" : DeviceData(report_length=2, usage_page=0x0C, usage=0x01), # Consumer, Consumer Control
+ "SYS_CONTROL" : DeviceData(report_length=1, usage_page=0x01, usage=0x80), # Generic Desktop, Sys Control
+ "GAMEPAD" : DeviceData(report_length=6, usage_page=0x01, usage=0x05), # Generic Desktop, Game Pad
+ "DIGITIZER" : DeviceData(report_length=5, usage_page=0x0D, usage=0x02), # Digitizers, Pen
+ "XAC_COMPATIBLE_GAMEPAD" : DeviceData(report_length=3, usage_page=0x01, usage=0x05), # Generic Desktop, Game Pad
+ "RAW" : DeviceData(report_length=64, usage_page=0xFFAF, usage=0xAF), # Vendor 0xFFAF "Adafruit", 0xAF
}
-# Byte count for each kind of report. Length does not include report ID in first byte.
-REPORT_LENGTHS = {
- "KEYBOARD" : 8,
- "MOUSE" : 4,
- "CONSUMER" : 2,
- "SYS_CONTROL" : 1,
- "GAMEPAD" : 6,
- "DIGITIZER" : 5,
- }
+def keyboard_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["KEYBOARD"]
+ return hid.ReportDescriptor(
+ description="KEYBOARD",
+ report_descriptor=bytes(
+ # Regular keyboard
+ (0x05, data.usage_page, # Usage Page (Generic Desktop)
+ 0x09, data.usage, # Usage (Keyboard)
+ 0xA1, 0x01, # Collection (Application)
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x05, 0x07, # Usage Page (Keyboard)
+ 0x19, 224, # Usage Minimum (224)
+ 0x29, 231, # Usage Maximum (231)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x25, 0x01, # Logical Maximum (1)
+ 0x75, 0x01, # Report Size (1)
+ 0x95, 0x08, # Report Count (8)
+ 0x81, 0x02, # Input (Data, Variable, Absolute)
+ 0x81, 0x01, # Input (Constant)
+ 0x19, 0x00, # Usage Minimum (0)
+ 0x29, 101, # Usage Maximum (101)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x25, 101, # Logical Maximum (101)
+ 0x75, 0x08, # Report Size (8)
+ 0x95, 0x06, # Report Count (6)
+ 0x81, 0x00, # Input (Data, Array)
+ 0x05, 0x08, # Usage Page (LED)
+ 0x19, 0x01, # Usage Minimum (1)
+ 0x29, 0x05, # Usage Maximum (5)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x25, 0x01, # Logical Maximum (1)
+ 0x75, 0x01, # Report Size (1)
+ 0x95, 0x05, # Report Count (5)
+ 0x91, 0x02, # Output (Data, Variable, Absolute)
+ 0x95, 0x03, # Report Count (3)
+ 0x91, 0x01, # Output (Constant)
+ 0xC0, # End Collection
+ )))
-KEYBOARD_WITH_ID = hid.ReportDescriptor(
- description="KEYBOARD",
- report_descriptor=bytes([
- # Regular keyboard
- 0x05, 0x01, # Usage Page (Generic Desktop)
- 0x09, 0x06, # Usage (Keyboard)
- 0xA1, 0x01, # Collection (Application)
- 0x85, REPORT_IDS["KEYBOARD"], # Report ID (1)
- 0x05, 0x07, # Usage Page (Keyboard)
- 0x19, 224, # Usage Minimum (224)
- 0x29, 231, # Usage Maximum (231)
- 0x15, 0x00, # Logical Minimum (0)
- 0x25, 0x01, # Logical Maximum (1)
- 0x75, 0x01, # Report Size (1)
- 0x95, 0x08, # Report Count (8)
- 0x81, 0x02, # Input (Data, Variable, Absolute)
- 0x81, 0x01, # Input (Constant)
- 0x19, 0x00, # Usage Minimum (0)
- 0x29, 101, # Usage Maximum (101)
- 0x15, 0x00, # Logical Minimum (0)
- 0x25, 101, # Logical Maximum (101)
- 0x75, 0x08, # Report Size (8)
- 0x95, 0x06, # Report Count (6)
- 0x81, 0x00, # Input (Data, Array)
- 0x05, 0x08, # Usage Page (LED)
- 0x19, 0x01, # Usage Minimum (1)
- 0x29, 0x05, # Usage Maximum (5)
- 0x15, 0x00, # Logical Minimum (0)
- 0x25, 0x01, # Logical Maximum (1)
- 0x75, 0x01, # Report Size (1)
- 0x95, 0x05, # Report Count (5)
- 0x91, 0x02, # Output (Data, Variable, Absolute)
- 0x95, 0x03, # Report Count (3)
- 0x91, 0x01, # Output (Constant)
- 0xC0, # End Collection
- ]))
+def mouse_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["MOUSE"]
+ return hid.ReportDescriptor(
+ description="MOUSE",
+ report_descriptor=bytes(
+ # Regular mouse
+ (0x05, data.usage_page, # Usage Page (Generic Desktop)
+ 0x09, data.usage, # Usage (Mouse)
+ 0xA1, 0x01, # Collection (Application)
+ 0x09, 0x01, # Usage (Pointer)
+ 0xA1, 0x00, # Collection (Physical)
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x05, 0x09, # Usage Page (Button)
+ 0x19, 0x01, # Usage Minimum (0x01)
+ 0x29, 0x05, # Usage Maximum (0x05)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x25, 0x01, # Logical Maximum (1)
+ 0x95, 0x05, # Report Count (5)
+ 0x75, 0x01, # Report Size (1)
+ 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0x95, 0x01, # Report Count (1)
+ 0x75, 0x03, # Report Size (3)
+ 0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
+ 0x09, 0x30, # Usage (X)
+ 0x09, 0x31, # Usage (Y)
+ 0x15, 0x81, # Logical Minimum (-127)
+ 0x25, 0x7F, # Logical Maximum (127)
+ 0x75, 0x08, # Report Size (8)
+ 0x95, 0x02, # Report Count (2)
+ 0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
+ 0x09, 0x38, # Usage (Wheel)
+ 0x15, 0x81, # Logical Minimum (-127)
+ 0x25, 0x7F, # Logical Maximum (127)
+ 0x75, 0x08, # Report Size (8)
+ 0x95, 0x01, # Report Count (1)
+ 0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
+ 0xC0, # End Collection
+ 0xC0, # End Collection
+ )))
-MOUSE_WITH_ID = hid.ReportDescriptor(
- description="MOUSE",
- report_descriptor=bytes([
- # Regular mouse
- 0x05, 0x01, # Usage Page (Generic Desktop)
- 0x09, 0x02, # Usage (Mouse)
- 0xA1, 0x01, # Collection (Application)
- 0x09, 0x01, # Usage (Pointer)
- 0xA1, 0x00, # Collection (Physical)
- 0x85, REPORT_IDS["MOUSE"], # Report ID (n)
- 0x05, 0x09, # Usage Page (Button)
- 0x19, 0x01, # Usage Minimum (0x01)
- 0x29, 0x05, # Usage Maximum (0x05)
- 0x15, 0x00, # Logical Minimum (0)
- 0x25, 0x01, # Logical Maximum (1)
- 0x95, 0x05, # Report Count (5)
- 0x75, 0x01, # Report Size (1)
- 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0x95, 0x01, # Report Count (1)
- 0x75, 0x03, # Report Size (3)
- 0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
- 0x09, 0x30, # Usage (X)
- 0x09, 0x31, # Usage (Y)
- 0x15, 0x81, # Logical Minimum (-127)
- 0x25, 0x7F, # Logical Maximum (127)
- 0x75, 0x08, # Report Size (8)
- 0x95, 0x02, # Report Count (2)
- 0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
- 0x09, 0x38, # Usage (Wheel)
- 0x15, 0x81, # Logical Minimum (-127)
- 0x25, 0x7F, # Logical Maximum (127)
- 0x75, 0x08, # Report Size (8)
- 0x95, 0x01, # Report Count (1)
- 0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
- 0xC0, # End Collection
- 0xC0, # End Collection
- ]))
+def consumer_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["CONSUMER"]
+ return hid.ReportDescriptor(
+ description="CONSUMER",
+ report_descriptor=bytes(
+ # Consumer ("multimedia") keys
+ (0x05, data.usage_page, # Usage Page (Consumer)
+ 0x09, data.usage, # Usage (Consumer Control)
+ 0xA1, 0x01, # Collection (Application)
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x75, 0x10, # Report Size (16)
+ 0x95, 0x01, # Report Count (1)
+ 0x15, 0x01, # Logical Minimum (1)
+ 0x26, 0x8C, 0x02, # Logical Maximum (652)
+ 0x19, 0x01, # Usage Minimum (Consumer Control)
+ 0x2A, 0x8C, 0x02, # Usage Maximum (AC Send)
+ 0x81, 0x00, # Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0xC0, # End Collection
+ )))
-CONSUMER_WITH_ID = hid.ReportDescriptor(
- description="CONSUMER",
- report_descriptor=bytes([
- # Consumer ("multimedia") keys
- 0x05, 0x0C, # Usage Page (Consumer)
- 0x09, 0x01, # Usage (Consumer Control)
- 0xA1, 0x01, # Collection (Application)
- 0x85, REPORT_IDS["CONSUMER"], # Report ID (n)
- 0x75, 0x10, # Report Size (16)
- 0x95, 0x01, # Report Count (1)
- 0x15, 0x01, # Logical Minimum (1)
- 0x26, 0x8C, 0x02, # Logical Maximum (652)
- 0x19, 0x01, # Usage Minimum (Consumer Control)
- 0x2A, 0x8C, 0x02, # Usage Maximum (AC Send)
- 0x81, 0x00, # Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0xC0, # End Collection
- ]))
+def sys_control_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["SYS_CONTROL"]
+ return hid.ReportDescriptor(
+ description="SYS_CONTROL",
+ report_descriptor=bytes(
+ # Power controls
+ (0x05, data.usage_page, # Usage Page (Generic Desktop Ctrls)
+ 0x09, data.usage, # Usage (Sys Control)
+ 0xA1, 0x01, # Collection (Application)
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x75, 0x02, # Report Size (2)
+ 0x95, 0x01, # Report Count (1)
+ 0x15, 0x01, # Logical Minimum (1)
+ 0x25, 0x03, # Logical Maximum (3)
+ 0x09, 0x82, # Usage (Sys Sleep)
+ 0x09, 0x81, # Usage (Sys Power Down)
+ 0x09, 0x83, # Usage (Sys Wake Up)
+ 0x81, 0x60, # Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State)
+ 0x75, 0x06, # Report Size (6)
+ 0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0xC0, # End Collection
+ )))
-SYS_CONTROL_WITH_ID = hid.ReportDescriptor(
- description="SYS_CONTROL",
- report_descriptor=bytes([
- # Power controls
- 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
- 0x09, 0x80, # Usage (Sys Control)
- 0xA1, 0x01, # Collection (Application)
- 0x85, REPORT_IDS["SYS_CONTROL"], # Report ID (n)
- 0x75, 0x02, # Report Size (2)
- 0x95, 0x01, # Report Count (1)
- 0x15, 0x01, # Logical Minimum (1)
- 0x25, 0x03, # Logical Maximum (3)
- 0x09, 0x82, # Usage (Sys Sleep)
- 0x09, 0x81, # Usage (Sys Power Down)
- 0x09, 0x83, # Usage (Sys Wake Up)
- 0x81, 0x60, # Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State)
- 0x75, 0x06, # Report Size (6)
- 0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0xC0, # End Collection
- ]))
+def gamepad_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["GAMEPAD"]
+ return hid.ReportDescriptor(
+ description="GAMEPAD",
+ report_descriptor=bytes(
+ # Gamepad with 16 buttons and two joysticks
+ (0x05, data.usage_page, # Usage Page (Generic Desktop Ctrls)
+ 0x09, data.usage, # Usage (Game Pad)
+ 0xA1, 0x01, # Collection (Application)
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x05, 0x09, # Usage Page (Button)
+ 0x19, 0x01, # Usage Minimum (Button 1)
+ 0x29, 0x10, # Usage Maximum (Button 16)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x25, 0x01, # Logical Maximum (1)
+ 0x75, 0x01, # Report Size (1)
+ 0x95, 0x10, # Report Count (16)
+ 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
+ 0x15, 0x81, # Logical Minimum (-127)
+ 0x25, 0x7F, # Logical Maximum (127)
+ 0x09, 0x30, # Usage (X)
+ 0x09, 0x31, # Usage (Y)
+ 0x09, 0x32, # Usage (Z)
+ 0x09, 0x35, # Usage (Rz)
+ 0x75, 0x08, # Report Size (8)
+ 0x95, 0x04, # Report Count (4)
+ 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0xC0, # End Collection
+ )))
-GAMEPAD_WITH_ID = hid.ReportDescriptor(
- description="GAMEPAD",
- report_descriptor=bytes([
- # Gamepad with 16 buttons and two joysticks
- 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
- 0x09, 0x05, # Usage (Game Pad)
- 0xA1, 0x01, # Collection (Application)
- 0x85, REPORT_IDS["GAMEPAD"], # Report ID (n)
- 0x05, 0x09, # Usage Page (Button)
- 0x19, 0x01, # Usage Minimum (Button 1)
- 0x29, 0x10, # Usage Maximum (Button 16)
- 0x15, 0x00, # Logical Minimum (0)
- 0x25, 0x01, # Logical Maximum (1)
- 0x75, 0x01, # Report Size (1)
- 0x95, 0x10, # Report Count (16)
- 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
- 0x15, 0x81, # Logical Minimum (-127)
- 0x25, 0x7F, # Logical Maximum (127)
- 0x09, 0x30, # Usage (X)
- 0x09, 0x31, # Usage (Y)
- 0x09, 0x32, # Usage (Z)
- 0x09, 0x35, # Usage (Rz)
- 0x75, 0x08, # Report Size (8)
- 0x95, 0x04, # Report Count (4)
- 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0xC0, # End Collection
- ]))
+def digitizer_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["DIGITIZER"]
+ return hid.ReportDescriptor(
+ description="DIGITIZER",
+ report_descriptor=bytes(
+ # Digitizer (used as an absolute pointer)
+ (0x05, data.usage_page, # Usage Page (Digitizers)
+ 0x09, data.usage, # Usage (Pen)
+ 0xA1, 0x01, # Collection (Application)
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x09, 0x01, # Usage (Stylus)
+ 0xA1, 0x00, # Collection (Physical)
+ 0x09, 0x32, # Usage (In-Range)
+ 0x09, 0x42, # Usage (Tip Switch)
+ 0x09, 0x44, # Usage (Barrel Switch)
+ 0x09, 0x45, # Usage (Eraser Switch)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x25, 0x01, # Logical Maximum (1)
+ 0x75, 0x01, # Report Size (1)
+ 0x95, 0x04, # Report Count (4)
+ 0x81, 0x02, # Input (Data,Var,Abs)
+ 0x75, 0x04, # Report Size (4) -- Filler
+ 0x95, 0x01, # Report Count (1) -- Filler
+ 0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
+ 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
+ 0x15, 0x00, # Logical Minimum (0)
+ 0x26, 0xff, 0x7f, # Logical Maximum (32767)
+ 0x09, 0x30, # Usage (X)
+ 0x09, 0x31, # Usage (Y)
+ 0x75, 0x10, # Report Size (16)
+ 0x95, 0x02, # Report Count (2)
+ 0x81, 0x02, # Input (Data,Var,Abs)
+ 0xC0, # End Collection
+ 0xC0, # End Collection
+ )))
-DIGITIZER_WITH_ID = hid.ReportDescriptor(
- description="DIGITIZER",
- report_descriptor=bytes([
- # Digitizer (used as an absolute pointer)
- 0x05, 0x0D, # Usage Page (Digitizers)
- 0x09, 0x02, # Usage (Pen)
- 0xA1, 0x01, # Collection (Application)
- 0x85, REPORT_IDS["DIGITIZER"], # Report ID (n)
- 0x09, 0x01, # Usage (Stylus)
- 0xA1, 0x00, # Collection (Physical)
- 0x09, 0x32, # Usage (In-Range)
- 0x09, 0x42, # Usage (Tip Switch)
- 0x09, 0x44, # Usage (Barrel Switch)
- 0x09, 0x45, # Usage (Eraser Switch)
- 0x15, 0x00, # Logical Minimum (0)
- 0x25, 0x01, # Logical Maximum (1)
- 0x75, 0x01, # Report Size (1)
- 0x95, 0x04, # Report Count (4)
- 0x81, 0x02, # Input (Data,Var,Abs)
- 0x75, 0x04, # Report Size (4) -- Filler
- 0x95, 0x01, # Report Count (1) -- Filler
- 0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
- 0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
- 0x15, 0x00, # Logical Minimum (0)
- 0x26, 0xff, 0x7f, # Logical Maximum (32767)
- 0x09, 0x30, # Usage (X)
- 0x09, 0x31, # Usage (Y)
- 0x75, 0x10, # Report Size (16)
- 0x95, 0x02, # Report Count (2)
- 0x81, 0x02, # Input (Data,Var,Abs)
- 0xC0, # End Collection
- 0xC0, # End Collection
- ]))
+def xac_compatible_gamepad_hid_descriptor(report_id):
+ data = HID_DEVICE_DATA["XAC_COMPATIBLE_GAMEPAD"]
+ return hid.ReportDescriptor(
+ description="XAC",
+ report_descriptor=bytes(
+ # This descriptor mimics the simple joystick from PDP that the XBox likes
+ (0x05, data.usage_page, # Usage Page (Desktop),
+ 0x09, data.usage, # Usage (Gamepad),
+ 0xA1, 0x01, # Collection (Application),
+ ) +
+ ((0x85, report_id) if report_id != 0 else ()) +
+ (0x15, 0x00, # Logical Minimum (0),
+ 0x25, 0x01, # Logical Maximum (1),
+ 0x35, 0x00, # Physical Minimum (0),
+ 0x45, 0x01, # Physical Maximum (1),
+ 0x75, 0x01, # Report Size (1),
+ 0x95, 0x08, # Report Count (8),
+ 0x05, 0x09, # Usage Page (Button),
+ 0x19, 0x01, # Usage Minimum (01h),
+ 0x29, 0x08, # Usage Maximum (08h),
+ 0x81, 0x02, # Input (Variable),
+ 0x05, 0x01, # Usage Page (Desktop),
+ 0x26, 0xFF, 0x00, # Logical Maximum (255),
+ 0x46, 0xFF, 0x00, # Physical Maximum (255),
+ 0x09, 0x30, # Usage (X),
+ 0x09, 0x31, # Usage (Y),
+ 0x75, 0x08, # Report Size (8),
+ 0x95, 0x02, # Report Count (2),
+ 0x81, 0x02, # Input (Variable),
+ 0xC0 # End Collection
+ )))
-# Byte count for each kind of report. Length does not include report ID in first byte.
-REPORT_DESCRIPTORS = {
- "KEYBOARD" : KEYBOARD_WITH_ID,
- "MOUSE" : MOUSE_WITH_ID,
- "CONSUMER" : CONSUMER_WITH_ID,
- "SYS_CONTROL" : SYS_CONTROL_WITH_ID,
- "GAMEPAD" : GAMEPAD_WITH_ID,
- "DIGITIZER" : DIGITIZER_WITH_ID,
- }
+def raw_hid_descriptor(report_id):
+ if report_id != 0:
+ raise ValueError("raw hid must not have a report id")
+ data = HID_DEVICE_DATA["RAW"]
+ return hid.ReportDescriptor(
+ description="RAW",
+ report_descriptor=bytes(
+ # Provide vendor-defined
+ # This is a two-byte page value.
+ (0x06, data.usage_page & 0xff, (data.usage_page >> 8) & 0xff, # Usage Page (Vendor 0xFFAF "Adafruit"),
+ 0x09, data.usage, # Usage (AF),
+ 0xA1, 0x01, # Collection (Application),
+ 0x75, 0x08, # Report Size (8),
+ 0x15, 0x00, # Logical Minimum (0),
+ 0x26, 0xFF, 0x00, # Logical Maximum (255),
+ 0x95, 0x08, # Report Count (8),
+ 0x09, 0x01, # Usage(xxx)
+ 0x81, 0x02, # Input (Variable)
+ 0x95, 0x08, # Report Count (8),
+ 0x09, 0x02, # Usage(xxx)
+ 0x91, 0x02, # Input (Variable)
+ 0xC0 # End Collection
+ )))
+
+# Function to call for each kind of HID descriptor.
+REPORT_DESCRIPTOR_FUNCTIONS = {
+ "KEYBOARD" : keyboard_hid_descriptor,
+ "MOUSE" : mouse_hid_descriptor,
+ "CONSUMER" : consumer_hid_descriptor,
+ "SYS_CONTROL" : sys_control_hid_descriptor,
+ "GAMEPAD" : gamepad_hid_descriptor,
+ "DIGITIZER" : digitizer_hid_descriptor,
+ "XAC_COMPATIBLE_GAMEPAD" : xac_compatible_gamepad_hid_descriptor,
+ "RAW" : raw_hid_descriptor,
+}
diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py
index bb6959f0d..2199e9d39 100755
--- a/tools/preprocess_frozen_modules.py
+++ b/tools/preprocess_frozen_modules.py
@@ -32,8 +32,9 @@ def version_string(path=None, *, valid_semver=False):
def copy_and_process(in_dir, out_dir):
for root, subdirs, files in os.walk(in_dir):
- # Skip library examples directories.
- if Path(root).name in ['examples', 'docs', 'tests']:
+ # Skip library examples directory and subfolders.
+ relative_path_parts = Path(root).relative_to(in_dir).parts
+ if relative_path_parts and relative_path_parts[0] in ['examples', 'docs', 'tests']:
continue
for file in files:
diff --git a/tools/upload_release_files.py b/tools/upload_release_files.py
new file mode 100755
index 000000000..4f193a8be
--- /dev/null
+++ b/tools/upload_release_files.py
@@ -0,0 +1,35 @@
+#! /usr/bin/env python3
+
+import os
+import os.path
+import sys
+import uritemplate
+
+sys.path.append("adabot")
+import adabot.github_requests as github
+
+exit_status = 0
+
+for dirpath, dirnames, filenames in os.walk("../bin"):
+ if not filenames:
+ continue
+ for filename in filenames:
+ full_filename = os.path.join(dirpath, filename)
+ label = filename.replace("adafruit-circuitpython-", "")
+ url_vars = {}
+ url_vars["name"] = filename
+ url_vars["label"] = label
+ url = uritemplate.expand(os.environ["UPLOAD_URL"], url_vars)
+ headers = {"content-type": "application/octet-stream"}
+ print(url)
+ with open(full_filename, "rb") as f:
+ response = github.post(url, data=f, headers=headers)
+ if not response.ok:
+ if response.status_code == 422 and response.json().get("errors", [{"code":""}])[0]["code"] == "already_exists":
+ print("File already uploaded. Skipping.")
+ continue
+ print("Upload of {} failed with {}.".format(filename, response.status_code))
+ print(response.text)
+ sys.exit(response.status_code)
+
+sys.exit(exit_status)