summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy Hooper <rhooper@toybox.ca>2019-12-10 20:44:43 -0500
committerRoy Hooper <rhooper@toybox.ca>2019-12-10 20:44:43 -0500
commit0326c98fd5409d10167d3d2cb3c6ea9dd898a543 (patch)
tree6665cb6a1af9399dbbd9d8ca166237106ebf87ea
parent222dd29a142a530b43fdf4d1ea01e276962b9886 (diff)
parent024ba978ec909d39d411a74b443d2ffa20250fa6 (diff)
Merge branch 'master' into new-pixelbuf-api
-rw-r--r--.github/workflows/build.yml4
-rw-r--r--.gitmodules6
-rw-r--r--drivers/wiznet5k/internet/dns/dns.c4
-rw-r--r--extmod/machine_i2c.c21
-rw-r--r--extmod/machine_i2c.h2
-rw-r--r--extmod/machine_pinbase.c1
-rw-r--r--extmod/machine_signal.c8
-rw-r--r--extmod/machine_spi.c7
-rw-r--r--extmod/machine_spi.h2
-rw-r--r--extmod/modframebuf.c16
-rw-r--r--extmod/modlwip.c1
-rw-r--r--extmod/modussl_axtls.c1
-rw-r--r--extmod/modussl_mbedtls.c1
-rw-r--r--extmod/moduzlib.c1
-rw-r--r--extmod/modwebrepl.c1
-rw-r--r--extmod/modwebsocket.c1
-rw-r--r--extmod/vfs.c2
-rw-r--r--extmod/vfs.h2
-rw-r--r--extmod/vfs_fat.c1
-rw-r--r--extmod/vfs_fat_file.c2
-rw-r--r--extmod/vfs_posix.c1
-rw-r--r--extmod/vfs_posix_file.c2
-rw-r--r--extmod/virtpin.c5
-rw-r--r--extmod/virtpin.h2
m---------lib/mp30
-rw-r--r--lib/oofatfs/ff.c6
-rw-r--r--lib/oofatfs/ffconf.h6
-rw-r--r--lib/utils/sys_stdio_mphal.c2
-rw-r--r--locale/ID.po22
-rw-r--r--locale/circuitpython.pot20
-rw-r--r--locale/de_DE.po22
-rw-r--r--locale/en_US.po22
-rw-r--r--locale/en_x_pirate.po22
-rw-r--r--locale/es.po22
-rw-r--r--locale/fil.po22
-rw-r--r--locale/fr.po22
-rw-r--r--locale/it_IT.po22
-rw-r--r--locale/ko.po22
-rw-r--r--locale/pl.po20
-rw-r--r--locale/pt_BR.po22
-rw-r--r--locale/zh_Latn_pinyin.po28
-rw-r--r--ports/atmel-samd/Makefile9
-rw-r--r--ports/atmel-samd/background.c26
-rw-r--r--ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pewpew10/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pyruler/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/common-hal/busio/UART.c9
-rw-r--r--ports/atmel-samd/common-hal/neopixel_write/__init__.c157
-rw-r--r--ports/atmel-samd/common-hal/time/__init__.c4
-rw-r--r--ports/atmel-samd/mpconfigport.mk4
-rw-r--r--ports/atmel-samd/mphalport.c6
-rw-r--r--ports/atmel-samd/mphalport.h6
-rw-r--r--ports/atmel-samd/tick.c36
-rw-r--r--ports/atmel-samd/tick.h2
-rw-r--r--ports/cxd56/common-hal/time/__init__.c4
-rw-r--r--ports/cxd56/mphalport.c6
-rw-r--r--ports/cxd56/mphalport.h2
-rw-r--r--ports/cxd56/tick.c15
-rw-r--r--ports/cxd56/tick.h2
-rwxr-xr-xports/nrf/Makefile1
-rw-r--r--ports/nrf/bluetooth/ble_drv.c10
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/board.c14
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h3
-rw-r--r--ports/nrf/boards/circuitplayground_bluefruit/pins.c6
-rw-r--r--ports/nrf/common-hal/_bleio/Adapter.c49
-rw-r--r--ports/nrf/common-hal/_bleio/CharacteristicBuffer.c5
-rw-r--r--ports/nrf/common-hal/_bleio/Connection.c84
-rw-r--r--ports/nrf/common-hal/_bleio/Connection.h2
-rw-r--r--ports/nrf/common-hal/_bleio/Service.c7
-rw-r--r--ports/nrf/common-hal/_bleio/__init__.c6
-rw-r--r--ports/nrf/common-hal/audiopwmio/PWMAudioOut.c16
-rw-r--r--ports/nrf/common-hal/audiopwmio/PWMAudioOut.h2
-rw-r--r--ports/nrf/common-hal/busio/UART.c4
-rw-r--r--ports/nrf/common-hal/time/__init__.c2
-rw-r--r--ports/nrf/mphalport.c5
-rw-r--r--ports/nrf/mphalport.h5
-rw-r--r--ports/nrf/tick.c33
-rw-r--r--ports/nrf/tick.h2
-rw-r--r--ports/stm32f4/boards/pyb_nano_v2/board.c39
-rw-r--r--ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.h47
-rw-r--r--ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.mk19
-rw-r--r--ports/stm32f4/boards/pyb_nano_v2/pins.c59
-rw-r--r--ports/stm32f4/boards/pyb_nano_v2/stm32f4xx_hal_conf.h440
-rw-r--r--ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h2
-rw-r--r--ports/stm32f4/common-hal/busio/I2C.c25
-rw-r--r--ports/stm32f4/common-hal/busio/SPI.c5
-rw-r--r--ports/stm32f4/common-hal/busio/UART.c4
-rw-r--r--ports/stm32f4/common-hal/digitalio/DigitalInOut.c6
-rw-r--r--ports/stm32f4/common-hal/displayio/ParallelBus.c68
-rw-r--r--ports/stm32f4/common-hal/displayio/ParallelBus.h36
-rw-r--r--ports/stm32f4/common-hal/microcontroller/Pin.c4
-rw-r--r--ports/stm32f4/common-hal/microcontroller/__init__.c6
-rw-r--r--ports/stm32f4/common-hal/neopixel_write/__init__.c16
-rw-r--r--ports/stm32f4/common-hal/time/__init__.c2
-rw-r--r--ports/stm32f4/mpconfigport.mk3
-rw-r--r--ports/stm32f4/mphalport.c6
-rw-r--r--ports/stm32f4/mphalport.h4
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c3
-rw-r--r--ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c115
-rw-r--r--ports/stm32f4/tick.c32
-rw-r--r--ports/stm32f4/tick.h2
-rw-r--r--ports/unix/coverage.c2
-rw-r--r--ports/unix/file.c2
-rw-r--r--ports/unix/modusocket.c1
-rw-r--r--py/circuitpy_defns.mk25
-rw-r--r--py/circuitpy_mpconfig.h23
-rw-r--r--py/circuitpy_mpconfig.mk9
-rw-r--r--py/makeqstrdata.py39
-rw-r--r--py/modio.c2
-rw-r--r--py/objstringio.c2
-rw-r--r--py/proto.c50
-rw-r--r--py/proto.h43
-rw-r--r--py/py.mk1
-rw-r--r--py/stream.c11
-rw-r--r--py/stream.h4
-rw-r--r--shared-bindings/_bleio/Adapter.c3
-rw-r--r--shared-bindings/_bleio/CharacteristicBuffer.c1
-rw-r--r--shared-bindings/_bleio/Connection.c58
-rw-r--r--shared-bindings/_bleio/Connection.h5
-rw-r--r--shared-bindings/_bleio/Service.c2
-rw-r--r--shared-bindings/audiocore/RawSample.c11
-rw-r--r--shared-bindings/audiocore/RawSample.h2
-rw-r--r--shared-bindings/audiocore/WaveFile.c12
-rw-r--r--shared-bindings/audiomixer/Mixer.c11
-rw-r--r--shared-bindings/audiomixer/Mixer.h2
-rw-r--r--shared-bindings/audiomp3/MP3File.c226
-rw-r--r--shared-bindings/audiomp3/MP3File.h48
-rw-r--r--shared-bindings/audiomp3/__init__.c60
-rw-r--r--shared-bindings/audiomp3/__init__.h34
-rw-r--r--shared-bindings/busio/UART.c1
-rw-r--r--shared-bindings/displayio/OnDiskBitmap.c2
-rw-r--r--shared-bindings/socket/__init__.c1
-rw-r--r--shared-bindings/terminalio/Terminal.c1
-rw-r--r--shared-bindings/usb_midi/PortIn.c1
-rw-r--r--shared-bindings/usb_midi/PortOut.c1
-rw-r--r--shared-module/audiocore/RawSample.c6
-rw-r--r--shared-module/audiocore/__init__.c92
-rw-r--r--shared-module/audiocore/__init__.h23
-rw-r--r--shared-module/audiomixer/Mixer.c8
-rw-r--r--shared-module/audiomp3/MP3File.c270
-rw-r--r--shared-module/audiomp3/MP3File.h70
-rw-r--r--shared-module/audiomp3/__init__.c0
-rw-r--r--shared-module/audiomp3/__init__.h30
-rw-r--r--shared-module/displayio/Display.c11
-rw-r--r--shared-module/displayio/EPaperDisplay.c5
-rw-r--r--shared-module/displayio/FourWire.c4
-rw-r--r--shared-module/displayio/display_core.c5
-rw-r--r--shared-module/network/__init__.c4
-rw-r--r--shared-module/usb_hid/Device.c5
-rw-r--r--supervisor/shared/bluetooth.c12
-rw-r--r--supervisor/shared/rgb_led_status.c9
-rw-r--r--supervisor/shared/safe_mode.c5
-rw-r--r--supervisor/shared/tick.c94
-rw-r--r--supervisor/shared/tick.h67
-rw-r--r--supervisor/shared/translate.c20
-rw-r--r--supervisor/supervisor.mk1
158 files changed, 2721 insertions, 613 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index bc22361bd..e4ec73d4c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -129,6 +129,7 @@ jobs:
- "pewpew10"
- "pewpew_m4"
- "pirkey_m0"
+ - "pyb_nano_v2"
- "pybadge"
- "pybadge_airlift"
- "pyboard_v11"
@@ -169,7 +170,8 @@ jobs:
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
+ wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/RC2.1/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2
+ sudo tar -C /usr --strip-components=1 -xaf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2
- name: Versions
run: |
gcc --version
diff --git a/.gitmodules b/.gitmodules
index bb62a5c39..98252c2af 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -76,7 +76,8 @@
[submodule "lib/tinyusb"]
path = lib/tinyusb
url = https://github.com/hathach/tinyusb.git
- branch = develop
+ branch = master
+ fetchRecurseSubmodules = false
[submodule "tools/huffman"]
path = tools/huffman
url = https://github.com/tannewt/huffman.git
@@ -101,3 +102,6 @@
[submodule "ports/cxd56/spresense-exported-sdk"]
path = ports/cxd56/spresense-exported-sdk
url = https://github.com/sonydevworld/spresense-exported-sdk.git
+[submodule "lib/mp3"]
+ path = lib/mp3
+ url = https://github.com/adafruit/Adafruit_MP3
diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c
index daf4db123..8b9e96670 100644
--- a/drivers/wiznet5k/internet/dns/dns.c
+++ b/drivers/wiznet5k/internet/dns/dns.c
@@ -52,7 +52,7 @@
#include <string.h>
#include <stdlib.h>
-#include "tick.h"
+#include "supervisor/shared/tick.h"
//#include "Ethernet/socket.h"
//#include "Internet/DNS/dns.h"
@@ -125,7 +125,7 @@ uint16_t DNS_MSGID; // DNS message ID
uint32_t HAL_GetTick(void) {
- return ticks_ms;
+ return supervisor_ticks_ms32();
}
uint32_t hal_sys_tick;
diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c
index 85b46a9f6..4129ace0a 100644
--- a/extmod/machine_i2c.c
+++ b/extmod/machine_i2c.c
@@ -318,7 +318,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init);
STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
mp_obj_t list = mp_obj_new_list(0, NULL);
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
for (int addr = 0x08; addr < 0x78; ++addr) {
@@ -333,7 +333,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
if (i2c_p->start == NULL) {
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
}
@@ -347,7 +347,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
if (i2c_p->stop == NULL) {
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
}
@@ -361,7 +361,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
if (i2c_p->read == NULL) {
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
}
@@ -385,7 +385,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_
STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
if (i2c_p->write == NULL) {
mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported"));
}
@@ -407,7 +407,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write);
STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
mp_int_t addr = mp_obj_get_int(args[1]);
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[2]));
@@ -422,7 +422,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_
STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
mp_int_t addr = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
@@ -437,7 +437,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine
STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
mp_int_t addr = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
@@ -453,7 +453,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machin
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
uint8_t memaddr_buf[4];
size_t memaddr_len = 0;
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
@@ -473,7 +473,7 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a
STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c);
// need some memory to create the buffer to send; try to use stack if possible
uint8_t buf2_stack[MAX_MEMADDR_SIZE + BUF_STACK_SIZE];
@@ -621,6 +621,7 @@ int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t
}
STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_i2c)
.start = (int(*)(mp_obj_base_t*))mp_hal_i2c_start,
.stop = (int(*)(mp_obj_base_t*))mp_hal_i2c_stop,
.read = mp_machine_soft_i2c_read,
diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h
index f5af6656f..7f5ee568e 100644
--- a/extmod/machine_i2c.h
+++ b/extmod/machine_i2c.h
@@ -27,10 +27,12 @@
#define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
#include "py/obj.h"
+#include "py/proto.h"
// I2C protocol
// the first 4 methods can be NULL, meaning operation is not supported
typedef struct _mp_machine_i2c_p_t {
+ MP_PROTOCOL_HEAD
int (*start)(mp_obj_base_t *obj);
int (*stop)(mp_obj_base_t *obj);
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack);
diff --git a/extmod/machine_pinbase.c b/extmod/machine_pinbase.c
index 997a6fd99..6cd14c187 100644
--- a/extmod/machine_pinbase.c
+++ b/extmod/machine_pinbase.c
@@ -74,6 +74,7 @@ mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *err
}
STATIC const mp_pin_p_t pinbase_pin_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin)
.ioctl = pinbase_ioctl,
};
diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c
index 62658cbb1..50501e34f 100644
--- a/extmod/machine_signal.c
+++ b/extmod/machine_signal.c
@@ -47,12 +47,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, const
bool invert = false;
#if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW)
- mp_pin_p_t *pin_p = NULL;
-
- if (MP_OBJ_IS_OBJ(pin)) {
- mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- pin_p = (mp_pin_p_t*)pin_base->type->protocol;
- }
+ mp_pin_p_t *pin_p = (mp_pin_t*)mp_proto_get(QSTR_pin_protocol, pin);
if (pin_p == NULL) {
// If first argument isn't a Pin-like object, we filter out "invert"
@@ -170,6 +165,7 @@ STATIC const mp_rom_map_elem_t signal_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(signal_locals_dict, signal_locals_dict_table);
STATIC const mp_pin_p_t signal_pin_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin)
.ioctl = signal_ioctl,
};
diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c
index c5707a3d0..4ead321d9 100644
--- a/extmod/machine_spi.c
+++ b/extmod/machine_spi.c
@@ -67,7 +67,7 @@ mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, const
STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s);
spi_p->init(s, n_args - 1, args + 1, kw_args);
return mp_const_none;
}
@@ -75,7 +75,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init);
STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s);
if (spi_p->deinit != NULL) {
spi_p->deinit(s);
}
@@ -85,7 +85,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit);
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) {
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s);
spi_p->transfer(s, len, src, dest);
}
@@ -268,6 +268,7 @@ STATIC void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, con
}
const mp_machine_spi_p_t mp_machine_soft_spi_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_spi)
.init = mp_machine_soft_spi_init,
.deinit = NULL,
.transfer = mp_machine_soft_spi_transfer,
diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h
index db21e1cd3..365b44d6e 100644
--- a/extmod/machine_spi.h
+++ b/extmod/machine_spi.h
@@ -27,11 +27,13 @@
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
#include "py/obj.h"
+#include "py/proto.h"
#include "py/mphal.h"
#include "drivers/bus/spi.h"
// SPI protocol
typedef struct _mp_machine_spi_p_t {
+ MP_PROTOCOL_HEAD
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void (*deinit)(mp_obj_base_t *obj); // can be NULL
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index 561b842bc..a51d1c380 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -28,6 +28,7 @@
#include <string.h>
#include "py/runtime.h"
+#include "py/proto.h"
#if MICROPY_PY_FRAMEBUF
@@ -46,6 +47,7 @@ typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t*, int, int);
typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, int, int, int, int, uint32_t);
typedef struct _mp_framebuf_p_t {
+ MP_PROTOCOL_HEAD
setpixel_t setpixel;
getpixel_t getpixel;
fill_rect_t fill_rect;
@@ -227,13 +229,13 @@ STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int
}
STATIC mp_framebuf_p_t formats[] = {
- [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
- [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
- [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
- [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
- [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
- [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
- [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
+ [FRAMEBUF_MVLSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
+ [FRAMEBUF_RGB565] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
+ [FRAMEBUF_GS2_HMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
+ [FRAMEBUF_GS4_HMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
+ [FRAMEBUF_GS8] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs8_setpixel, gs8_getpixel, gs8_fill_rect},
+ [FRAMEBUF_MHLSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
+ [FRAMEBUF_MHMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
};
static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index e5e92c42b..776b81ee5 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -1261,6 +1261,7 @@ STATIC const mp_rom_map_elem_t lwip_socket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(lwip_socket_locals_dict, lwip_socket_locals_dict_table);
STATIC const mp_stream_p_t lwip_socket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = lwip_socket_read,
.write = lwip_socket_write,
.ioctl = lwip_socket_ioctl,
diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c
index cfa652585..032dea09f 100644
--- a/extmod/modussl_axtls.c
+++ b/extmod/modussl_axtls.c
@@ -221,6 +221,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
STATIC const mp_stream_p_t ussl_socket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,
diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c
index 08807d20b..9abdeb966 100644
--- a/extmod/modussl_mbedtls.c
+++ b/extmod/modussl_mbedtls.c
@@ -305,6 +305,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
STATIC const mp_stream_p_t ussl_socket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,
diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c
index 7f15d02a8..3a081bc45 100644
--- a/extmod/moduzlib.c
+++ b/extmod/moduzlib.c
@@ -134,6 +134,7 @@ STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
STATIC const mp_stream_p_t decompio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = decompio_read,
};
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index 06da210d1..fb4d97358 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -331,6 +331,7 @@ STATIC const mp_rom_map_elem_t webrepl_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(webrepl_locals_dict, webrepl_locals_dict_table);
STATIC const mp_stream_p_t webrepl_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = webrepl_read,
.write = webrepl_write,
.ioctl = webrepl_ioctl,
diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c
index 997c7e262..496e4b5bb 100644
--- a/extmod/modwebsocket.c
+++ b/extmod/modwebsocket.c
@@ -286,6 +286,7 @@ STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
STATIC const mp_stream_p_t websocket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = websocket_read,
.write = websocket_write,
.ioctl = websocket_ioctl,
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 7599739e0..4d344095a 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -126,7 +126,7 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) {
}
// If the mounted object has the VFS protocol, call its import_stat helper
- const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol;
+ const mp_vfs_proto_t *proto = (mp_vfs_proto_t*)mp_proto_get(MP_QSTR_protocol_vfs, vfs->obj);
if (proto != NULL) {
return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out);
}
diff --git a/extmod/vfs.h b/extmod/vfs.h
index 38c77943c..6c0692365 100644
--- a/extmod/vfs.h
+++ b/extmod/vfs.h
@@ -28,6 +28,7 @@
#include "py/lexer.h"
#include "py/obj.h"
+#include "py/proto.h"
// return values of mp_vfs_lookup_path
// ROOT is 0 so that the default current directory is the root directory
@@ -47,6 +48,7 @@
// At the moment the VFS protocol just has import_stat, but could be extended to other methods
typedef struct _mp_vfs_proto_t {
+ MP_PROTOCOL_HEAD
mp_import_stat_t (*import_stat)(void *self, const char *path);
} mp_vfs_proto_t;
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index 20d3e3e5c..60f4393f4 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -488,6 +488,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);
STATIC const mp_vfs_proto_t fat_vfs_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_vfs)
.import_stat = fat_vfs_import_stat,
};
diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c
index 6aad1884c..3ea9cee52 100644
--- a/extmod/vfs_fat_file.c
+++ b/extmod/vfs_fat_file.c
@@ -254,6 +254,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t fileio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = file_obj_read,
.write = file_obj_write,
.ioctl = file_obj_ioctl,
@@ -272,6 +273,7 @@ const mp_obj_type_t mp_type_vfs_fat_fileio = {
#endif
STATIC const mp_stream_p_t textio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = file_obj_read,
.write = file_obj_write,
.ioctl = file_obj_ioctl,
diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c
index d28dfe451..56a5de303 100644
--- a/extmod/vfs_posix.c
+++ b/extmod/vfs_posix.c
@@ -350,6 +350,7 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table);
STATIC const mp_vfs_proto_t vfs_posix_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_vfs)
.import_stat = mp_vfs_posix_import_stat,
};
diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c
index b760b3847..be455fa28 100644
--- a/extmod/vfs_posix_file.c
+++ b/extmod/vfs_posix_file.c
@@ -220,6 +220,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t fileio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = vfs_posix_file_read,
.write = vfs_posix_file_write,
.ioctl = vfs_posix_file_ioctl,
@@ -238,6 +239,7 @@ const mp_obj_type_t mp_type_vfs_posix_fileio = {
#endif
STATIC const mp_stream_p_t textio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = vfs_posix_file_read,
.write = vfs_posix_file_write,
.ioctl = vfs_posix_file_ioctl,
diff --git a/extmod/virtpin.c b/extmod/virtpin.c
index dbfa21d66..559f99265 100644
--- a/extmod/virtpin.c
+++ b/extmod/virtpin.c
@@ -25,15 +25,16 @@
*/
#include "extmod/virtpin.h"
+#include "py/proto.h"
int mp_virtual_pin_read(mp_obj_t pin) {
mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
- mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol;
+ const mp_pin_p_t *pin_p = mp_proto_get(MP_QSTR_protocol_pin, s);
return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL);
}
void mp_virtual_pin_write(mp_obj_t pin, int value) {
mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
- mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol;
+ const mp_pin_p_t *pin_p = mp_proto_get(MP_QSTR_protocol_pin, s);
pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
}
diff --git a/extmod/virtpin.h b/extmod/virtpin.h
index 706affc19..591249e48 100644
--- a/extmod/virtpin.h
+++ b/extmod/virtpin.h
@@ -27,6 +27,7 @@
#define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H
#include "py/obj.h"
+#include "py/proto.h"
#define MP_PIN_READ (1)
#define MP_PIN_WRITE (2)
@@ -35,6 +36,7 @@
// Pin protocol
typedef struct _mp_pin_p_t {
+ MP_PROTOCOL_HEAD
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
} mp_pin_p_t;
diff --git a/lib/mp3 b/lib/mp3
new file mode 160000
+Subproject 2a3cc7873b5c642d4bb60043dc14d2555e3377a
diff --git a/lib/oofatfs/ff.c b/lib/oofatfs/ff.c
index b0984756b..71bd19702 100644
--- a/lib/oofatfs/ff.c
+++ b/lib/oofatfs/ff.c
@@ -3382,7 +3382,11 @@ FRESULT f_read (
if (!sect) ABORT(fs, FR_INT_ERR);
sect += csect;
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
- if (cc) { /* Read maximum contiguous sectors directly */
+ if (cc
+#if _FS_DISK_READ_ALIGNED
+ && (((int)rbuff & 3) == 0)
+#endif
+ ) {/* Read maximum contiguous sectors directly */
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
cc = fs->csize - csect;
}
diff --git a/lib/oofatfs/ffconf.h b/lib/oofatfs/ffconf.h
index 214311b4c..a3795fa3f 100644
--- a/lib/oofatfs/ffconf.h
+++ b/lib/oofatfs/ffconf.h
@@ -343,6 +343,12 @@
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
+// Set to nonzero if buffers passed to disk_read have a word alignment
+// restriction
+#ifndef _FS_DISK_READ_ALIGNED
+#define _FS_DISK_READ_ALIGNED 0
+#endif
+
/* #include <windows.h> // O/S definitions */
diff --git a/lib/utils/sys_stdio_mphal.c b/lib/utils/sys_stdio_mphal.c
index 266783f37..c1607dfe8 100644
--- a/lib/utils/sys_stdio_mphal.c
+++ b/lib/utils/sys_stdio_mphal.c
@@ -123,6 +123,7 @@ STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table);
STATIC const mp_stream_p_t stdio_obj_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stdio_read,
.write = stdio_write,
.ioctl = stdio_ioctl,
@@ -158,6 +159,7 @@ STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t
}
STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stdio_buffer_read,
.write = stdio_buffer_write,
.is_text = false,
diff --git a/locale/ID.po b/locale/ID.po
index da1f77548..bee0d9b73 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\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"
@@ -120,6 +120,10 @@ msgstr ""
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' integer 0x%x tidak cukup didalam mask 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -487,11 +491,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Tidak dapat menginisialisasi UART"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -604,6 +618,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, fuzzy, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1773,7 +1791,7 @@ msgstr "argumen keyword ekstra telah diberikan"
msgid "extra positional arguments given"
msgstr "argumen posisi ekstra telah diberikan"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 1d2b8ad86..f172638c3 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -119,6 +119,10 @@ msgstr ""
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr ""
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -477,11 +481,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -593,6 +607,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1743,7 +1761,7 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 29f08834c..6f5fa77c7 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Pascal Deneaux\n"
"Language-Team: Sebastian Plamauer, Pascal Deneaux\n"
@@ -121,6 +121,10 @@ msgstr "'%s' integer %d ist nicht im Bereich %d..%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' Integer 0x%x passt nicht in Maske 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -481,11 +485,21 @@ msgstr "Beschädigter raw code"
msgid "Could not initialize UART"
msgstr "Konnte UART nicht initialisieren"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Konnte first buffer nicht zuteilen"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Konnte second buffer nicht zuteilen"
@@ -597,6 +611,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr "Verbindung nicht erfolgreich: timeout"
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1792,7 +1810,7 @@ msgstr "Es wurden zusätzliche Keyword-Argumente angegeben"
msgid "extra positional arguments given"
msgstr "Es wurden zusätzliche Argumente ohne Keyword angegeben"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.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"
diff --git a/locale/en_US.po b/locale/en_US.po
index 170b2ec56..028a56881 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -119,6 +119,10 @@ msgstr ""
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr ""
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -477,11 +481,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -593,6 +607,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1743,7 +1761,7 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po
index 7813c1a77..4a0903269 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: @sommersoft, @MrCertainly\n"
@@ -121,6 +121,10 @@ msgstr ""
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr ""
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -481,11 +485,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -597,6 +611,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1747,7 +1765,7 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index 6155fdffa..01def0d62 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -121,6 +121,10 @@ msgstr "'%s' entero %d no esta dentro del rango %d..%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' entero 0x%x no cabe en la máscara 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -485,11 +489,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "No se puede inicializar la UART"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "No se pudo asignar el primer buffer"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "No se pudo asignar el segundo buffer"
@@ -601,6 +615,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1795,7 +1813,7 @@ msgstr "argumento(s) por palabra clave adicionales fueron dados"
msgid "extra positional arguments given"
msgstr "argumento posicional adicional dado"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.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"
diff --git a/locale/fil.po b/locale/fil.po
index f341bfc25..d0dc8490a 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-12-20 22:15-0800\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n"
@@ -122,6 +122,10 @@ msgstr "'%s' integer %d ay wala sa sakop ng %d..%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' integer 0x%x ay wala sa mask na sakop ng 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -486,11 +490,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Hindi ma-initialize ang UART"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Hindi ma-iallocate ang first buffer"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Hindi ma-iallocate ang second buffer"
@@ -607,6 +621,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, fuzzy, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1803,7 +1821,7 @@ msgstr "dagdag na keyword argument na ibinigay"
msgid "extra positional arguments given"
msgstr "dagdag na positional argument na ibinigay"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "file ay dapat buksan sa byte mode"
diff --git a/locale/fr.po b/locale/fr.po
index a39cabd66..d981a63d4 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2019-04-14 20:05+0100\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -123,6 +123,10 @@ msgstr "'%s' l'entier %d n'est pas dans la gamme %d..%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' l'entier 0x%x ne correspond pas au masque 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -492,11 +496,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "L'UART n'a pu être initialisé"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Impossible d'allouer le 1er tampon"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Impossible d'allouer le 2e tampon"
@@ -611,6 +625,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, fuzzy, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1835,7 +1853,7 @@ 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/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.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'"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index ff553ab1a..97c15647d 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -121,6 +121,10 @@ msgstr "intero '%s' non è nell'intervallo %d..%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "intero '%s' non è nell'intervallo %d..%d"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -487,11 +491,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Impossibile inizializzare l'UART"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Impossibile allocare il primo buffer"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Impossibile allocare il secondo buffer"
@@ -607,6 +621,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, fuzzy, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1796,7 +1814,7 @@ msgstr "argomento nominato aggiuntivo fornito"
msgid "extra positional arguments given"
msgstr "argomenti posizonali extra dati"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/ko.po b/locale/ko.po
index 406539f2e..5a6d9dc5a 100644
--- a/locale/ko.po
+++ b/locale/ko.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2019-05-06 14:22-0700\n"
"Last-Translator: \n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -121,6 +121,10 @@ msgstr ""
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr ""
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -481,11 +485,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr ""
@@ -597,6 +611,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1748,7 +1766,7 @@ msgstr ""
msgid "extra positional arguments given"
msgstr ""
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/pl.po b/locale/pl.po
index f13bed53b..e1e795398 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -120,6 +120,10 @@ msgstr "'%s' liczba %d poza zakresem %d..%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' liczba 0x%x nie pasuje do maski 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -480,11 +484,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Ustawienie UART nie powiodło się"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Nie udała się alokacja pierwszego bufora"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Nie udała się alokacja drugiego bufora"
@@ -596,6 +610,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1768,7 +1786,7 @@ msgstr "nadmiarowe argumenty nazwane"
msgid "extra positional arguments given"
msgstr "nadmiarowe argumenty pozycyjne"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr "file musi być otwarte w trybie bajtowym"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 68d1c43cc..ed6d01367 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2018-10-02 21:14-0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -121,6 +121,10 @@ msgstr ""
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr ""
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -483,11 +487,21 @@ msgstr ""
msgid "Could not initialize UART"
msgstr "Não foi possível inicializar o UART"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Não pôde alocar primeiro buffer"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Não pôde alocar segundo buffer"
@@ -602,6 +616,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr ""
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, fuzzy, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -1765,7 +1783,7 @@ msgstr "argumentos extras de palavras-chave passados"
msgid "extra positional arguments given"
msgstr "argumentos extra posicionais passados"
-#: shared-bindings/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.c
#: shared-bindings/displayio/OnDiskBitmap.c
msgid "file must be a file opened in byte mode"
msgstr ""
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index d251df5b9..bb214e3f8 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-11-27 14:54-0500\n"
+"POT-Creation-Date: 2019-12-10 13:55-0600\n"
"PO-Revision-Date: 2019-04-13 10:10-0700\n"
"Last-Translator: hexthat\n"
"Language-Team: Chinese Hanyu Pinyin\n"
@@ -121,6 +121,10 @@ msgstr "'%s' zhěngshù %d bùzài fànwéi nèi %d.%d"
msgid "'%s' integer 0x%x does not fit in mask 0x%x"
msgstr "'%s' zhěngshù 0x%x bù shìyòng yú yǎn mǎ 0x%x"
+#: py/proto.c
+msgid "'%s' object does not support '%q'"
+msgstr ""
+
#: py/obj.c
#, c-format
msgid "'%s' object does not support item assignment"
@@ -481,11 +485,21 @@ msgstr "Sǔnhuài de yuánshǐ dàimǎ"
msgid "Could not initialize UART"
msgstr "Wúfǎ chūshǐhuà UART"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate decoder"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate first buffer"
msgstr "Wúfǎ fēnpèi dì yī gè huǎnchōng qū"
+#: shared-module/audiomp3/MP3File.c
+msgid "Couldn't allocate input buffer"
+msgstr ""
+
#: shared-module/audiocore/WaveFile.c shared-module/audiomixer/Mixer.c
+#: shared-module/audiomp3/MP3File.c
msgid "Couldn't allocate second buffer"
msgstr "Wúfǎ fēnpèi dì èr gè huǎnchōng qū"
@@ -597,6 +611,10 @@ msgstr ""
msgid "Failed to connect: timeout"
msgstr "Liánjiē shībài: Chāoshí"
+#: shared-module/audiomp3/MP3File.c
+msgid "Failed to parse MP3 file"
+msgstr ""
+
#: ports/nrf/sd_mutex.c
#, c-format
msgid "Failed to release mutex, err 0x%04x"
@@ -668,11 +686,11 @@ msgstr "Shūrù/shūchū cuòwù"
#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Insufficient authentication"
-msgstr ""
+msgstr "Rènzhèng bùzú"
#: ports/nrf/common-hal/_bleio/__init__.c
msgid "Insufficient encryption"
-msgstr ""
+msgstr "Jiāmì bùzú"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@@ -1779,7 +1797,7 @@ 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/audiocore/WaveFile.c
+#: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3File.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"
@@ -2459,7 +2477,7 @@ msgstr "time.struct_time() xūyào 9 xùliè"
#: shared-bindings/busio/UART.c
msgid "timeout must be 0.0-100.0 seconds"
-msgstr ""
+msgstr "Chāo shí shíjiān bìxū wèi 0.0 Dào 100.0 Miǎo"
#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "timeout must be >= 0.0"
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 11e6874ed..5d47fd087 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -122,7 +122,16 @@ else
ifdef CFLAGS_INLINE_LIMIT
CFLAGS += -finline-limit=$(CFLAGS_INLINE_LIMIT)
endif
+
CFLAGS += -flto -flto-partition=none
+
+ ifeq ($(CIRCUITPY_SMALL_BUILD),1)
+ CFLAGS += --param inline-unit-growth=15 --param max-inline-insns-auto=20
+ endif
+
+ ifdef CFLAGS_BOARD
+ CFLAGS += $(CFLAGS_BOARD)
+ endif
endif
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c
index 386ba0715..ca91a31de 100644
--- a/ports/atmel-samd/background.c
+++ b/ports/atmel-samd/background.c
@@ -28,6 +28,7 @@
#include "audio_dma.h"
#include "tick.h"
#include "supervisor/filesystem.h"
+#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "py/runtime.h"
@@ -44,6 +45,23 @@ bool stack_ok_so_far = true;
static bool running_background_tasks = false;
+#ifdef MONITOR_BACKGROUND_TASKS
+// PB03 is physical pin "SCL" on the Metro M4 express
+// so you can't use this code AND an i2c peripheral
+// at the same time unless you change this
+STATIC void start_background_task(void) {
+ REG_PORT_DIRSET1 = (1<<3);
+ REG_PORT_OUTSET1 = (1<<3);
+}
+
+STATIC void finish_background_task(void) {
+ REG_PORT_OUTCLR1 = (1<<3);
+}
+#else
+STATIC void start_background_task(void) {}
+STATIC void finish_background_task(void) {}
+#endif
+
void background_tasks_reset(void) {
running_background_tasks = false;
}
@@ -53,6 +71,9 @@ void run_background_tasks(void) {
if (running_background_tasks) {
return;
}
+
+ start_background_task();
+
assert_heap_ok();
running_background_tasks = true;
@@ -71,9 +92,10 @@ void run_background_tasks(void) {
running_background_tasks = false;
assert_heap_ok();
- last_finished_tick = ticks_ms;
+ last_finished_tick = supervisor_ticks_ms64();
+ finish_background_task();
}
bool background_tasks_ok(void) {
- return ticks_ms - last_finished_tick < 1000;
+ return supervisor_ticks_ms64() - last_finished_tick < 1000;
}
diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
index 453be3b5e..b9b88a368 100644
--- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
@@ -16,3 +16,4 @@ CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_NETWORK = 0
CIRCUITPY_PS2IO = 0
+CIRCUITPY_AUDIOMP3 = 0
diff --git a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
index e24a29051..8a1d6b16a 100644
--- a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
@@ -23,3 +23,5 @@ CIRCUITPY_USB_MIDI = 0
SUPEROPT_GC = 0
FROZEN_MPY_DIRS += $(TOP)/frozen/pew-pewpew-standalone-10.x
+
+CFLAGS_BOARD = --param max-inline-insns-auto=15
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
index 6ce25cf69..8b82f0a09 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
@@ -29,3 +29,5 @@ SUPEROPT_GC = 0
# FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_IRRemote
+
+CFLAGS_BOARD = --param max-inline-insns-auto=12
diff --git a/ports/atmel-samd/boards/pyruler/mpconfigboard.mk b/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
index 9d9e4ba34..63d4cfed7 100644
--- a/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
@@ -13,6 +13,7 @@ CIRCUITPY_SMALL_BUILD = 1
SUPEROPT_GC = 0
+CFLAGS_BOARD = --param max-inline-insns-auto=15
ifeq ($(TRANSLATION), zh_Latn_pinyin)
CFLAGS_INLINE_LIMIT = 35
-endif
+endif \ No newline at end of file
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index b4a00b654..af8b561a2 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -12,3 +12,9 @@ LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
SUPEROPT_GC = 0
+
+CFLAGS_BOARD = --param max-inline-insns-auto=15
+ifeq ($(TRANSLATION), zh_Latn_pinyin)
+CFLAGS_INLINE_LIMIT = 35
+endif
+
diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c
index d869f70ff..4ad47a58d 100644
--- a/ports/atmel-samd/common-hal/busio/UART.c
+++ b/ports/atmel-samd/common-hal/busio/UART.c
@@ -34,8 +34,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/translate.h"
-
-#include "tick.h"
+#include "supervisor/shared/tick.h"
#include "hpl_sercom_config.h"
#include "peripheral_clk_config.h"
@@ -272,10 +271,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
usart_async_get_io_descriptor(usart_desc_p, &io);
size_t total_read = 0;
- uint64_t start_ticks = ticks_ms;
+ uint64_t start_ticks = supervisor_ticks_ms64();
// Busy-wait until timeout or until we've read enough chars.
- while (ticks_ms - start_ticks <= self->timeout_ms) {
+ while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) {
// Read as many chars as we can right now, up to len.
size_t num_read = io_read(io, data, len);
@@ -289,7 +288,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
}
if (num_read > 0) {
// Reset the timeout on every character read.
- start_ticks = ticks_ms;
+ start_ticks = supervisor_ticks_ms64();
}
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
diff --git a/ports/atmel-samd/common-hal/neopixel_write/__init__.c b/ports/atmel-samd/common-hal/neopixel_write/__init__.c
index 57e963c91..ba69174af 100644
--- a/ports/atmel-samd/common-hal/neopixel_write/__init__.c
+++ b/ports/atmel-samd/common-hal/neopixel_write/__init__.c
@@ -34,24 +34,62 @@
#ifdef SAMD51
#include "hri/hri_cmcc_d51.h"
#include "hri/hri_nvmctrl_d51.h"
-
-// This magical macro makes sure the delay isn't optimized out and is the
-// minimal three instructions.
-#define delay_cycles(cycles) \
-{ \
- uint32_t t; \
- asm volatile ( \
- "movs %[t], %[c]\n\t" \
- "loop%=:\n\t" \
- "subs %[t], #1\n\t" \
- "bne.n loop%=" : [t] "=r"(t) : [c] "I" (cycles)); \
- }
#endif
-// Ensure this code is compiled with -Os. Any other optimization level may change the timing of it
-// and break neopixels.
-#pragma GCC push_options
-#pragma GCC optimize ("Os")
+__attribute__((naked,noinline,aligned(16)))
+static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMask,
+ const uint8_t *ptr, int numBytes);
+
+static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMask,
+ const uint8_t *ptr, int numBytes) {
+ asm volatile(" push {r4, r5, r6, lr};"
+ " add r3, r2, r3;"
+ "loopLoad:"
+ " ldrb r5, [r2, #0];" // r5 := *ptr
+ " add r2, #1;" // ptr++
+ " movs r4, #128;" // r4-mask, 0x80
+ "loopBit:"
+ " str r1, [r0, #4];" // set
+ #ifdef SAMD21
+ " movs r6, #3; d2: sub r6, #1; bne d2;" // delay 3
+ #endif
+ #ifdef SAMD51
+ " movs r6, #3; d2: subs r6, #1; bne d2;" // delay 3
+ #endif
+ " tst r4, r5;" // mask&r5
+ " bne skipclr;"
+ " str r1, [r0, #0];" // clr
+ "skipclr:"
+ #ifdef SAMD21
+ " movs r6, #6; d0: sub r6, #1; bne d0;" // delay 6
+ #endif
+ #ifdef SAMD51
+ " movs r6, #6; d0: subs r6, #1; bne d0;" // delay 6
+ #endif
+ " str r1, [r0, #0];" // clr (possibly again, doesn't matter)
+ #ifdef SAMD21
+ " asr r4, r4, #1;" // mask >>= 1
+ #endif
+ #ifdef SAMD51
+ " asrs r4, r4, #1;" // mask >>= 1
+ #endif
+ " beq nextbyte;"
+ " uxtb r4, r4;"
+ #ifdef SAMD21
+ " movs r6, #2; d1: sub r6, #1; bne d1;" // delay 2
+ #endif
+ #ifdef SAMD51
+ " movs r6, #2; d1: subs r6, #1; bne d1;" // delay 2
+ #endif
+ " b loopBit;"
+ "nextbyte:"
+ " cmp r2, r3;"
+ " bcs neopixel_stop;"
+ " b loopLoad;"
+ "neopixel_stop:"
+ " pop {r4, r5, r6, pc};"
+ "");
+}
uint64_t next_start_tick_ms = 0;
uint32_t next_start_tick_us = 1000;
@@ -59,7 +97,7 @@ uint32_t next_start_tick_us = 1000;
void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
// This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code:
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
- uint8_t *ptr, *end, p, bitMask;
+ // and the asm version from https://github.com/microsoft/uf2-samdx1/blob/master/inc/neopixel.h
uint32_t pinMask;
PortGroup* port;
@@ -71,21 +109,18 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
mp_hal_disable_all_interrupts();
- #ifdef SAMD21
- // Make sure the NVM cache is consistently timed.
- NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_DETERMINISTIC_Val;
- #endif
-
#ifdef SAMD51
// When this routine is positioned at certain addresses, the timing logic
// below can be too fast by about 2.5x. This is some kind of (un)fortunate code
- // positiong with respect to a cache line.
+ // positioning with respect to a cache line.
// Theoretically we should turn on off the CMCC caches and the
// NVM caches to ensure consistent timing. Testing shows the the NVMCTRL
// cache disabling seems to make the difference. But turn both off to make sure.
// It's difficult to test because additions to the code before the timing loop
- // below change instruction placement. Testing was done by adding cache changes
- // below the loop (so only the first time through is wrong).
+ // below change instruction placement. (though this should be less true now that
+ // the main code is in the cache-aligned function neopixel_send_buffer_core)
+ // Testing was done by adding cache changes below the loop (so only the
+ // first time through is wrong).
//
// Turn off instruction, data, and NVM caches to force consistent timing.
// Invalidate existing cache entries.
@@ -93,78 +128,13 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
hri_cmcc_write_MAINT0_reg(CMCC, CMCC_MAINT0_INVALL);
hri_nvmctrl_set_CTRLA_CACHEDIS0_bit(NVMCTRL);
hri_nvmctrl_set_CTRLA_CACHEDIS1_bit(NVMCTRL);
- #endif
+ #endif
uint32_t pin = digitalinout->pin->number;
port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register
pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code.
- ptr = pixels;
- end = ptr + numBytes;
- p = *ptr++;
- bitMask = 0x80;
-
- volatile uint32_t *set = &(port->OUTSET.reg),
- *clr = &(port->OUTCLR.reg);
-
- for(;;) {
- *set = pinMask;
- // This is the time where the line is always high regardless of the bit.
- // For the SK6812 its 0.3us +- 0.15us
- #ifdef SAMD21
- asm("nop; nop;");
- #endif
- #ifdef SAMD51
- delay_cycles(2);
- #endif
- if((p & bitMask) != 0) {
- // This is the high delay unique to a one bit.
- // For the SK6812 its 0.3us
- #ifdef SAMD21
- asm("nop; nop; nop; nop; nop; nop; nop;");
- #endif
- #ifdef SAMD51
- delay_cycles(3);
- #endif
- *clr = pinMask;
- } else {
- *clr = pinMask;
- // This is the low delay unique to a zero bit.
- // For the SK6812 its 0.3us
- #ifdef SAMD21
- asm("nop; nop;");
- #endif
- #ifdef SAMD51
- delay_cycles(2);
- #endif
- }
- if((bitMask >>= 1) != 0) {
- // This is the delay between bits in a byte and is the 1 code low
- // level time from the datasheet.
- // For the SK6812 its 0.6us +- 0.15us
- #ifdef SAMD21
- asm("nop; nop; nop; nop; nop;");
- #endif
- #ifdef SAMD51
- delay_cycles(4);
- #endif
- } else {
- if(ptr >= end) break;
- p = *ptr++;
- bitMask = 0x80;
- // This is the delay between bytes. It's similar to the other branch
- // in the if statement except its tuned to account for the time the
- // above operations take.
- // For the SK6812 its 0.6us +- 0.15us
- #ifdef SAMD51
- delay_cycles(3);
- #endif
- }
- }
-
- #ifdef SAMD21
- // Speed up! (But inconsistent timing.)
- NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY_Val;
- #endif
+ volatile uint32_t *clr = &(port->OUTCLR.reg);
+ neopixel_send_buffer_core(clr, pinMask, pixels, numBytes);
#ifdef SAMD51
// Turn instruction, data, and NVM caches back on.
@@ -189,4 +159,3 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
}
-#pragma GCC pop_options
diff --git a/ports/atmel-samd/common-hal/time/__init__.c b/ports/atmel-samd/common-hal/time/__init__.c
index 0d60adef2..2d82b3d1a 100644
--- a/ports/atmel-samd/common-hal/time/__init__.c
+++ b/ports/atmel-samd/common-hal/time/__init__.c
@@ -28,10 +28,10 @@
#include "shared-bindings/time/__init__.h"
-#include "tick.h"
+#include "supervisor/shared/tick.h"
inline uint64_t common_hal_time_monotonic() {
- return ticks_ms;
+ return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {
diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk
index df108664a..58bf07247 100644
--- a/ports/atmel-samd/mpconfigport.mk
+++ b/ports/atmel-samd/mpconfigport.mk
@@ -21,6 +21,10 @@ ifndef CIRCUITPY_AUDIOMIXER
CIRCUITPY_AUDIOMIXER = 0
endif
+ifndef CIRCUITPY_AUDIOMP3
+CIRCUITPY_AUDIOMP3 = 0
+endif
+
ifndef CIRCUITPY_FREQUENCYIO
CIRCUITPY_FREQUENCYIO = 0
endif
diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c
index 957bf6073..96433d729 100644
--- a/ports/atmel-samd/mphalport.c
+++ b/ports/atmel-samd/mphalport.c
@@ -45,12 +45,12 @@
#include "mpconfigboard.h"
#include "mphalport.h"
#include "reset.h"
-#include "tick.h"
+#include "supervisor/shared/tick.h"
extern uint32_t common_hal_mcu_processor_get_frequency(void);
void mp_hal_delay_ms(mp_uint_t delay) {
- uint64_t start_tick = ticks_ms;
+ uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
RUN_BACKGROUND_TASKS;
@@ -59,7 +59,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
- duration = (ticks_ms - start_tick);
+ duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}
diff --git a/ports/atmel-samd/mphalport.h b/ports/atmel-samd/mphalport.h
index 64269b201..8a762e258 100644
--- a/ports/atmel-samd/mphalport.h
+++ b/ports/atmel-samd/mphalport.h
@@ -31,11 +31,11 @@
#include "lib/oofatfs/ff.h"
-// Global millisecond tick count (driven by SysTick interrupt).
-extern volatile uint64_t ticks_ms;
+#include "supervisor/shared/tick.h"
+// Global millisecond tick count (driven by SysTick interrupt).
static inline mp_uint_t mp_hal_ticks_ms(void) {
- return ticks_ms;
+ return supervisor_ticks_ms32();
}
// Number of bytes in receive buffer
volatile uint8_t usb_rx_count;
diff --git a/ports/atmel-samd/tick.c b/ports/atmel-samd/tick.c
index 4d7bb9dca..f996440ae 100644
--- a/ports/atmel-samd/tick.c
+++ b/ports/atmel-samd/tick.c
@@ -28,47 +28,21 @@
#include "peripheral_clk_config.h"
-#include "supervisor/shared/autoreload.h"
-#include "supervisor/filesystem.h"
+#include "supervisor/shared/tick.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
-#if CIRCUITPY_GAMEPAD
-#include "shared-module/gamepad/__init__.h"
-#endif
-
-#if CIRCUITPY_GAMEPADSHIFT
-#include "shared-module/gamepadshift/__init__.h"
-#endif
-// 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).
common_hal_mcu_disable_interrupts();
- ticks_ms += 1;
// Read the control register to reset the COUNTFLAG.
(void) SysTick->CTRL;
common_hal_mcu_enable_interrupts();
-#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)) {
- #if CIRCUITPY_GAMEPAD
- gamepad_tick();
- #endif
- #if CIRCUITPY_GAMEPADSHIFT
- gamepadshift_tick();
- #endif
- }
-#endif
+ // Do things common to all ports when the tick occurs
+ supervisor_tick();
}
void tick_init() {
@@ -115,7 +89,7 @@ void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t tick_status = SysTick->CTRL;
uint32_t current_us = SysTick->VAL;
uint32_t tick_status2 = SysTick->CTRL;
- uint64_t current_ms = ticks_ms;
+ uint64_t current_ms = supervisor_ticks_ms64();
// The second clause ensures our value actually rolled over. Its possible it hit zero between
// the VAL read and CTRL read.
if ((tick_status & SysTick_CTRL_COUNTFLAG_Msk) != 0 ||
@@ -129,5 +103,5 @@ void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
- while (ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
+ while (supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}
diff --git a/ports/atmel-samd/tick.h b/ports/atmel-samd/tick.h
index c8c8d739a..334352df2 100644
--- a/ports/atmel-samd/tick.h
+++ b/ports/atmel-samd/tick.h
@@ -28,8 +28,6 @@
#include "py/mpconfig.h"
-extern volatile uint64_t ticks_ms;
-
extern struct timer_descriptor ms_timer;
void tick_init(void);
diff --git a/ports/cxd56/common-hal/time/__init__.c b/ports/cxd56/common-hal/time/__init__.c
index 8f7326b62..6f5eedd41 100644
--- a/ports/cxd56/common-hal/time/__init__.c
+++ b/ports/cxd56/common-hal/time/__init__.c
@@ -26,10 +26,10 @@
#include "py/mphal.h"
-#include "tick.h"
+#include "supervisor/shared/tick.h"
uint64_t common_hal_time_monotonic(void) {
- return ticks_ms;
+ return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {
diff --git a/ports/cxd56/mphalport.c b/ports/cxd56/mphalport.c
index 79d93f975..1305706ca 100644
--- a/ports/cxd56/mphalport.c
+++ b/ports/cxd56/mphalport.c
@@ -31,7 +31,7 @@
#include "py/mpstate.h"
-#include "tick.h"
+#include "supervisor/shared/tick.h"
#define DELAY_CORRECTION (700)
#define DELAY_INTERVAL (50)
@@ -57,7 +57,7 @@ mp_uint_t mp_hal_ticks_cpu(void) {
}
void mp_hal_delay_ms(mp_uint_t delay) {
- uint64_t start_tick = ticks_ms;
+ uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
#ifdef MICROPY_VM_HOOK_LOOP
@@ -68,7 +68,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
- duration = (ticks_ms - start_tick);
+ duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}
diff --git a/ports/cxd56/mphalport.h b/ports/cxd56/mphalport.h
index 25bca97ad..a2be10b8d 100644
--- a/ports/cxd56/mphalport.h
+++ b/ports/cxd56/mphalport.h
@@ -31,6 +31,4 @@
#include "lib/utils/interrupt_char.h"
-extern volatile uint64_t ticks_ms;
-
#endif // MICROPY_INCLUDED_CXD56_MPHALPORT_H
diff --git a/ports/cxd56/tick.c b/ports/cxd56/tick.c
index 6529db790..671b82b74 100644
--- a/ports/cxd56/tick.c
+++ b/ports/cxd56/tick.c
@@ -27,19 +27,10 @@
#include "tick.h"
#include "supervisor/shared/autoreload.h"
-#include "supervisor/filesystem.h"
-
-// Global millisecond tick count
-volatile uint64_t ticks_ms = 0;
+#include "supervisor/shared/tick.h"
void board_timerhook(void)
{
- ticks_ms += 1;
-
-#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
- filesystem_tick();
-#endif
-#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
- autoreload_tick();
-#endif
+ // Do things common to all ports when the tick occurs
+ supervisor_tick();
}
diff --git a/ports/cxd56/tick.h b/ports/cxd56/tick.h
index a0d9ee526..d641d9cd4 100644
--- a/ports/cxd56/tick.h
+++ b/ports/cxd56/tick.h
@@ -29,6 +29,4 @@
#include "py/mpconfig.h"
-extern volatile uint64_t ticks_ms;
-
#endif // MICROPY_INCLUDED_CXD56_TICK_H
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index be8a71b3f..096dfaa4b 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -106,6 +106,7 @@ CFLAGS += -Wno-undef
CFLAGS += -Wno-cast-align
NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET
+NRF_DEFINES += -D_FS_DISK_READ_ALIGNED=1
CFLAGS += $(NRF_DEFINES)
CFLAGS += \
diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c
index 16475e4b3..63d67a7f4 100644
--- a/ports/nrf/bluetooth/ble_drv.c
+++ b/ports/nrf/bluetooth/ble_drv.c
@@ -134,6 +134,9 @@ void SD_EVT_IRQHandler(void) {
}
ble_evt_t* event = (ble_evt_t *)m_ble_evt_buf;
+ #if CIRCUITPY_VERBOSE_BLE
+ mp_printf(&mp_plat_print, "BLE event: 0x%04x\n", event->header.evt_id);
+ #endif
if (supervisor_bluetooth_hook(event)) {
continue;
@@ -145,8 +148,11 @@ void SD_EVT_IRQHandler(void) {
done = it->func(event, it->param) || done;
it = it->next;
}
- if (!done) {
- //mp_printf(&mp_plat_print, "Unhandled ble event: 0x%04x\n", event->header.evt_id);
+ #if CIRCUITPY_VERBOSE_BLE
+ if (event->header.evt_id == BLE_GATTS_EVT_WRITE) {
+ ble_gatts_evt_write_t* write_evt = &event->evt.gatts_evt.params.write;
+ mp_printf(&mp_plat_print, "Write to: UUID(0x%04x) handle %x of length %d auth %x\n", write_evt->uuid.uuid, write_evt->handle, write_evt->len, write_evt->auth_required);
}
+ #endif
}
}
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/board.c b/ports/nrf/boards/circuitplayground_bluefruit/board.c
index 4421970ee..7c8ec8e9a 100644
--- a/ports/nrf/boards/circuitplayground_bluefruit/board.c
+++ b/ports/nrf/boards/circuitplayground_bluefruit/board.c
@@ -25,6 +25,11 @@
*/
#include "boards/board.h"
+#include "mpconfigboard.h"
+#include "py/obj.h"
+#include "peripherals/nrf/pins.h"
+
+#include "nrf_gpio.h"
void board_init(void) {
}
@@ -34,5 +39,12 @@ bool board_requests_safe_mode(void) {
}
void reset_board(void) {
-
+ // Turn off board.POWER_SWITCH (power-saving switch) on each soft reload, to prevent confusion.
+ nrf_gpio_cfg(POWER_SWITCH_PIN->number,
+ NRF_GPIO_PIN_DIR_OUTPUT,
+ NRF_GPIO_PIN_INPUT_DISCONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+ nrf_gpio_pin_write(POWER_SWITCH_PIN->number, false);
}
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
index 4e37eae0a..21ba3a976 100644
--- a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
+++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h
@@ -54,6 +54,9 @@
#define SPI_FLASH_CS_PIN &pin_P0_15
#endif
+// Disables onboard peripherals and neopixels to save power.
+#define POWER_SWITCH_PIN (&pin_P0_06)
+
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
diff --git a/ports/nrf/boards/circuitplayground_bluefruit/pins.c b/ports/nrf/boards/circuitplayground_bluefruit/pins.c
index e8e5f4110..d0d9659db 100644
--- a/ports/nrf/boards/circuitplayground_bluefruit/pins.c
+++ b/ports/nrf/boards/circuitplayground_bluefruit/pins.c
@@ -48,8 +48,12 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ 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) },
+ // If high, turns off NeoPixels, LIS3DH, sound sensor, light sensor, temp sensor.
+ { MP_ROM_QSTR(MP_QSTR_POWER_SWITCH), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_P0_06) },
+
{ MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_14) },
+ { MP_ROM_QSTR(MP_QSTR_D13), 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) },
diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c
index ec8d36111..8f67d66d2 100644
--- a/ports/nrf/common-hal/_bleio/Adapter.c
+++ b/ports/nrf/common-hal/_bleio/Adapter.c
@@ -40,6 +40,7 @@
#include "py/objstr.h"
#include "py/runtime.h"
#include "supervisor/shared/safe_mode.h"
+#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
@@ -179,9 +180,18 @@ STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
connection->conn_handle = ble_evt->evt.gap_evt.conn_handle;
connection->connection_obj = mp_const_none;
connection->pair_status = PAIR_NOT_PAIRED;
+
ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection);
self->connection_objs = NULL;
+ // Save the current connection parameters.
+ memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t));
+
+ #if CIRCUITPY_VERBOSE_BLE
+ ble_gap_conn_params_t *cp = &connected->conn_params;
+ mp_printf(&mp_plat_print, "conn params: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout);
+ #endif
+
// See if connection interval set by Central is out of range.
// If so, negotiate our preferred range.
ble_gap_conn_params_t conn_params;
@@ -343,7 +353,7 @@ STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) {
ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report;
shared_module_bleio_scanresults_append(scan_results,
- ticks_ms,
+ supervisor_ticks_ms64(),
report->type.connectable,
report->type.scan_response,
report->rssi,
@@ -498,8 +508,9 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle.
uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
-STATIC void check_data_fit(size_t data_len) {
- if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
+STATIC void check_data_fit(size_t data_len, bool connectable) {
+ if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED ||
+ (connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) {
mp_raise_ValueError(translate("Data too large for advertisement packet"));
}
}
@@ -515,11 +526,31 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
common_hal_bleio_adapter_stop_advertising(self);
}
+
+ bool extended = advertising_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX ||
+ scan_response_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX;
+
+ uint8_t adv_type;
+ if (extended) {
+ if (connectable) {
+ adv_type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED;
+ } else if (scan_response_data_len > 0) {
+ adv_type = BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_UNDIRECTED;
+ } else {
+ adv_type = BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
+ }
+ } else if (connectable) {
+ adv_type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
+ } else if (scan_response_data_len > 0) {
+ adv_type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED;
+ } else {
+ adv_type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
+ }
+
uint32_t err_code;
ble_gap_adv_params_t adv_params = {
.interval = SEC_TO_UNITS(interval, UNIT_0_625_MS),
- .properties.type = connectable ? BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED
- : BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED,
+ .properties.type = adv_type,
.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
.filter_policy = BLE_GAP_ADV_FP_ANY,
.primary_phy = BLE_GAP_PHY_1MBPS,
@@ -552,15 +583,15 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
}
// interval value has already been validated.
- check_data_fit(advertising_data_bufinfo->len);
- check_data_fit(scan_response_data_bufinfo->len);
+ check_data_fit(advertising_data_bufinfo->len, connectable);
+ check_data_fit(scan_response_data_bufinfo->len, connectable);
// The advertising data buffers must not move, because the SoftDevice depends on them.
// So make them long-lived and reuse them onwards.
if (self->advertising_data == NULL) {
- self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true);
+ self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true);
}
if (self->scan_response_data == NULL) {
- self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true);
+ self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true);
}
memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len);
diff --git a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c
index 5f280e121..9f9b453de 100644
--- a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c
+++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c
@@ -39,6 +39,7 @@
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Connection.h"
+#include "supervisor/shared/tick.h"
#include "common-hal/_bleio/CharacteristicBuffer.h"
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
@@ -100,10 +101,10 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
}
int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
- uint64_t start_ticks = ticks_ms;
+ uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for all bytes received or timeout
- while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
+ while ( (ringbuf_count(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c
index 0e1e187c2..e0b50901a 100644
--- a/ports/nrf/common-hal/_bleio/Connection.c
+++ b/ports/nrf/common-hal/_bleio/Connection.c
@@ -70,8 +70,6 @@ static volatile bool m_discovery_successful;
static bleio_service_obj_t *m_char_discovery_service;
static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
-bool dump_events = false;
-
bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
bleio_connection_internal_t *self = (bleio_connection_internal_t*)self_in;
@@ -84,16 +82,9 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
return false;
}
- // For debugging.
- if (dump_events) {
- mp_printf(&mp_plat_print, "Connection event: 0x%04x\n", ble_evt->header.evt_id);
- }
-
switch (ble_evt->header.evt_id) {
case BLE_GAP_EVT_DISCONNECTED:
break;
- case BLE_GAP_EVT_CONN_PARAM_UPDATE: // 0x12
- break;
case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
ble_gap_phys_t const phys = {
.rx_phys = BLE_GAP_PHY_AUTO,
@@ -124,15 +115,61 @@ bool connection_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_GATTS_EVT_HVN_TX_COMPLETE: // Capture this for now. 0x55
+ #if CIRCUITPY_VERBOSE_BLE
+ // Use read authorization to snoop on all reads when doing verbose debugging.
+ case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: {
+
+ ble_gatts_evt_rw_authorize_request_t *request =
+ &ble_evt->evt.gatts_evt.params.authorize_request;
+
+ mp_printf(&mp_plat_print, "Read %x offset %d ", request->request.read.handle, request->request.read.offset);
+ uint8_t value_bytes[22];
+ ble_gatts_value_t value;
+ value.offset = request->request.read.offset;
+ value.len = 22;
+ value.p_value = value_bytes;
+
+ sd_ble_gatts_value_get(self->conn_handle, request->request.read.handle, &value);
+ size_t len = value.len;
+ if (len > 22) {
+ len = 22;
+ }
+ for (uint8_t i = 0; i < len; i++) {
+ mp_printf(&mp_plat_print, " %02x", value_bytes[i]);
+ }
+ mp_printf(&mp_plat_print, "\n");
+ ble_gatts_rw_authorize_reply_params_t reply;
+ reply.type = request->type;
+ reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ reply.params.read.update = false;
+ reply.params.read.offset = request->request.read.offset;
+ sd_ble_gatts_rw_authorize_reply(self->conn_handle, &reply);
break;
+ }
+ #endif
+ case BLE_GATTS_EVT_HVN_TX_COMPLETE: // Capture this for now. 0x55
+ break;
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
+ self->conn_params_updating = true;
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);
break;
}
+ case BLE_GAP_EVT_CONN_PARAM_UPDATE: { // 0x12
+ ble_gap_evt_conn_param_update_t *result =
+ &ble_evt->evt.gap_evt.params.conn_param_update;
+
+ #if CIRCUITPY_VERBOSE_BLE
+ ble_gap_conn_params_t *cp = &ble_evt->evt.gap_evt.params.conn_param_update.conn_params;
+ mp_printf(&mp_plat_print, "conn params updated: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout);
+ #endif
+
+ memcpy(&self->conn_params, &result->conn_params, sizeof(ble_gap_conn_params_t));
+ self->conn_params_updating = false;
+ break;
+ }
case BLE_GAP_EVT_SEC_PARAMS_REQUEST: {
ble_gap_sec_keyset_t keyset = {
.keys_own = {
@@ -211,11 +248,6 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
default:
- // For debugging.
- if (dump_events) {
- mp_printf(&mp_plat_print, "Unhandled connection event: 0x%04x\n", ble_evt->header.evt_id);
- }
-
return false;
}
return true;
@@ -262,6 +294,25 @@ void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bo
check_sec_status(self->sec_status);
}
+mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self) {
+ while (self->conn_params_updating && !mp_hal_is_interrupted()) {
+ RUN_BACKGROUND_TASKS;
+ }
+ return 1.25f * self->conn_params.min_conn_interval;
+}
+
+void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) {
+ self->conn_params_updating = true;
+ uint16_t interval = new_interval / 1.25f;
+ self->conn_params.min_conn_interval = interval;
+ self->conn_params.max_conn_interval = interval;
+ uint32_t status = NRF_ERROR_BUSY;
+ while (status == NRF_ERROR_BUSY) {
+ status = sd_ble_gap_conn_param_update(self->conn_handle, &self->conn_params);
+ RUN_BACKGROUND_TASKS;
+ }
+ check_nrf_error(status);
+}
// service_uuid may be NULL, to discover all services.
STATIC bool discover_next_services(bleio_connection_internal_t* connection, uint16_t start_handle, ble_uuid_t *service_uuid) {
@@ -600,8 +651,10 @@ STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t
ble_drv_remove_event_handler(discovery_on_ble_evt, self);
}
+
mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) {
discover_remote_services(self->connection, service_uuids_whitelist);
+ bleio_connection_ensure_connected(self);
// Convert to a tuple and then clear the list so the callee will take ownership.
mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_list);
self->connection->remote_service_list = NULL;
@@ -609,7 +662,6 @@ mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_conne
return services_tuple;
}
-
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) {
if (self == NULL || self->connection == NULL) {
return BLE_CONN_HANDLE_INVALID;
diff --git a/ports/nrf/common-hal/_bleio/Connection.h b/ports/nrf/common-hal/_bleio/Connection.h
index d5548de45..1474a0a6c 100644
--- a/ports/nrf/common-hal/_bleio/Connection.h
+++ b/ports/nrf/common-hal/_bleio/Connection.h
@@ -63,6 +63,8 @@ typedef struct {
uint8_t sec_status; // Internal security status.
mp_obj_t connection_obj;
ble_drv_evt_handler_entry_t handler_entry;
+ ble_gap_conn_params_t conn_params;
+ volatile bool conn_params_updating;
} bleio_connection_internal_t;
typedef struct {
diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c
index 5918327c1..19288f747 100644
--- a/ports/nrf/common-hal/_bleio/Service.c
+++ b/ports/nrf/common-hal/_bleio/Service.c
@@ -119,6 +119,10 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm);
bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm);
+ #if CIRCUITPY_VERBOSE_BLE
+ // Turn on read authorization so that we receive an event to print on every read.
+ char_attr_md.rd_auth = true;
+ #endif
ble_gatts_attr_t char_attr = {
.p_uuid = &char_uuid,
@@ -137,6 +141,9 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
characteristic->cccd_handle = char_handles.cccd_handle;
characteristic->sccd_handle = char_handles.sccd_handle;
characteristic->handle = char_handles.value_handle;
+ #if CIRCUITPY_VERBOSE_BLE
+ mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle);
+ #endif
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
}
diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c
index 7ba3dc8c1..4b2780ded 100644
--- a/ports/nrf/common-hal/_bleio/__init__.c
+++ b/ports/nrf/common-hal/_bleio/__init__.c
@@ -187,7 +187,11 @@ size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_
read_info.done = false;
ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info);
- check_nrf_error(sd_ble_gattc_read(conn_handle, handle, 0));
+ uint32_t nrf_error = NRF_ERROR_BUSY;
+ while (nrf_error == NRF_ERROR_BUSY) {
+ nrf_error = sd_ble_gattc_read(conn_handle, handle, 0);
+ }
+ check_nrf_error(nrf_error);
while (!read_info.done) {
RUN_BACKGROUND_TASKS;
diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
index 9496277b1..b4c626355 100644
--- a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
+++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
@@ -97,27 +97,28 @@ STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) {
common_hal_audiopwmio_pwmaudioout_stop(self);
return;
}
- uint32_t num_samples = buffer_length / self->bytes_per_sample / self->spacing;
+ uint32_t num_samples = buffer_length / self->bytes_per_sample / self->sample_channel_count;
+ uint16_t *end_dev_buffer = dev_buffer + 2 * num_samples;
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++) {
+ while (dev_buffer < end_dev_buffer) {
uint8_t rawval = (*buffer++ + offset);
uint16_t val = (uint16_t)(((uint32_t)rawval * (uint32_t)scale) >> 8);
*dev_buffer++ = val;
- if (self->spacing == 1)
+ if (self->sample_channel_count == 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++) {
+ while (dev_buffer < end_dev_buffer) {
uint16_t rawval = (*buffer16++ + offset);
uint16_t val = (uint16_t)((rawval * (uint32_t)scale) >> 16);
*dev_buffer++ = val;
- if (self->spacing == 1)
+ if (self->sample_channel_count == 1)
*dev_buffer++ = val;
}
}
@@ -231,9 +232,12 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self,
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
uint32_t max_buffer_length;
+ uint8_t spacing;
audiosample_get_buffer_structure(sample, /* single channel */ false,
&self->single_buffer, &self->signed_to_unsigned, &max_buffer_length,
- &self->spacing);
+ &spacing);
+ self->sample_channel_count = audiosample_channel_count(sample);
+
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);
}
diff --git a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
index 8deff5d34..ed00324c4 100644
--- a/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
+++ b/ports/nrf/common-hal/audiopwmio/PWMAudioOut.h
@@ -41,7 +41,7 @@ typedef struct {
uint8_t left_channel_number;
uint8_t right_channel_number;
- uint8_t spacing;
+ uint8_t sample_channel_count;
uint8_t bytes_per_sample;
bool playing;
diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c
index a0ae8af00..9cdc197e7 100644
--- a/ports/nrf/common-hal/busio/UART.c
+++ b/ports/nrf/common-hal/busio/UART.c
@@ -231,10 +231,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
}
size_t rx_bytes = 0;
- uint64_t start_ticks = ticks_ms;
+ uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for all bytes received or timeout
- while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
+ while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
diff --git a/ports/nrf/common-hal/time/__init__.c b/ports/nrf/common-hal/time/__init__.c
index e3cb481ef..976f519db 100644
--- a/ports/nrf/common-hal/time/__init__.c
+++ b/ports/nrf/common-hal/time/__init__.c
@@ -29,7 +29,7 @@
#include "tick.h"
uint64_t common_hal_time_monotonic(void) {
- return ticks_ms;
+ return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {
diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c
index bcd9fb114..3885d5a82 100644
--- a/ports/nrf/mphalport.c
+++ b/ports/nrf/mphalport.c
@@ -31,12 +31,13 @@
#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/gc.h"
+#include "supervisor/shared/tick.h"
/*------------------------------------------------------------------*/
/* delay
*------------------------------------------------------------------*/
void mp_hal_delay_ms(mp_uint_t delay) {
- uint64_t start_tick = ticks_ms;
+ uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
RUN_BACKGROUND_TASKS;
@@ -45,7 +46,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
- duration = (ticks_ms - start_tick);
+ duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}
diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h
index a1929a4ac..8bb351401 100644
--- a/ports/nrf/mphalport.h
+++ b/ports/nrf/mphalport.h
@@ -33,12 +33,11 @@
#include "lib/utils/interrupt_char.h"
#include "nrfx_uarte.h"
#include "py/mpconfig.h"
+#include "supervisor/shared/tick.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_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32())
#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us))
bool mp_hal_stdin_any(void);
diff --git a/ports/nrf/tick.c b/ports/nrf/tick.c
index 6d8fd13e0..ac825a7f1 100644
--- a/ports/nrf/tick.c
+++ b/ports/nrf/tick.c
@@ -26,31 +26,14 @@
#include "tick.h"
-#include "supervisor/shared/autoreload.h"
-#include "supervisor/filesystem.h"
+#include "supervisor/shared/tick.h"
#include "shared-module/gamepad/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "nrf.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
+ // Do things common to all ports when the tick occurs
+ supervisor_tick();
}
void tick_init() {
@@ -61,11 +44,11 @@ void tick_init() {
void tick_delay(uint32_t us) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
uint32_t us_between_ticks = SysTick->VAL / ticks_per_us;
- uint64_t start_ms = ticks_ms;
+ uint64_t start_ms = supervisor_ticks_ms64();
while (us > 1000) {
- while (ticks_ms == start_ms) {}
+ while (supervisor_ticks_ms64() == start_ms) {}
us -= us_between_ticks;
- start_ms = ticks_ms;
+ start_ms = supervisor_ticks_ms64();
us_between_ticks = 1000;
}
while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
@@ -74,11 +57,11 @@ void tick_delay(uint32_t us) {
// us counts down!
void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
- *ms = ticks_ms;
+ *ms = supervisor_ticks_ms64();
*us_until_ms = SysTick->VAL / ticks_per_us;
}
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
- while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
+ while(supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}
diff --git a/ports/nrf/tick.h b/ports/nrf/tick.h
index 838e9fbea..d638ad025 100644
--- a/ports/nrf/tick.h
+++ b/ports/nrf/tick.h
@@ -30,8 +30,6 @@
#include <stdint.h>
-extern volatile uint64_t ticks_ms;
-
extern struct timer_descriptor ms_timer;
void tick_init(void);
diff --git a/ports/stm32f4/boards/pyb_nano_v2/board.c b/ports/stm32f4/boards/pyb_nano_v2/board.c
new file mode 100644
index 000000000..82b0c506e
--- /dev/null
+++ b/ports/stm32f4/boards/pyb_nano_v2/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"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.h b/ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.h
new file mode 100644
index 000000000..7980ca93d
--- /dev/null
+++ b/ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "PYB LR Nano V2"
+#define MICROPY_HW_MCU_NAME "STM32F411CE"
+
+#define FLASH_SIZE (0x80000)
+#define FLASH_PAGE_SIZE (0x4000)
+
+#define BOARD_OSC_DIV 8
+
+// On-board flash
+#define SPI_FLASH_MOSI_PIN (&pin_PB15)
+#define SPI_FLASH_MISO_PIN (&pin_PB14)
+#define SPI_FLASH_SCK_PIN (&pin_PB13)
+#define SPI_FLASH_CS_PIN (&pin_PB12)
+
+#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/pyb_nano_v2/mpconfigboard.mk b/ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.mk
new file mode 100644
index 000000000..d46ee0b08
--- /dev/null
+++ b/ports/stm32f4/boards/pyb_nano_v2/mpconfigboard.mk
@@ -0,0 +1,19 @@
+USB_VID = 0x239A
+USB_PID = 0x8068
+USB_PRODUCT = "PYB LR Nano V2"
+USB_MANUFACTURER = "MicroPython Chinese Community"
+USB_DEVICES = "CDC,MSC"
+
+SPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = W25Q64JV_IQ
+LONGINT_IMPL = MPZ
+
+MCU_SERIES = m4
+MCU_VARIANT = stm32f4
+MCU_SUB_VARIANT = stm32f411xe
+MCU_PACKAGE = 48
+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/pyb_nano_v2/pins.c b/ports/stm32f4/boards/pyb_nano_v2/pins.c
new file mode 100644
index 000000000..e10124f6a
--- /dev/null
+++ b/ports/stm32f4/boards/pyb_nano_v2/pins.c
@@ -0,0 +1,59 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_Y10), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_Y9), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_Y8), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_Y7), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_Y6), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_Y5), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_Y4), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_Y3), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_Y2), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_Y1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_Y0), MP_ROM_PTR(&pin_PB09) },
+
+ { MP_ROM_QSTR(MP_QSTR_X15), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_X14), MP_ROM_PTR(&pin_PB15) },
+ { MP_ROM_QSTR(MP_QSTR_X13), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_X12), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_X11), MP_ROM_PTR(&pin_PB12) },
+ { MP_ROM_QSTR(MP_QSTR_X10), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_X9), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_X8), MP_ROM_PTR(&pin_PB00) },
+ { MP_ROM_QSTR(MP_QSTR_X7), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_X6), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_X5), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_X4), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_X3), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_X2), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_X1), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_X0), MP_ROM_PTR(&pin_PA00) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_SDA2), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_SCL2), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_SDA3), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_SCL3), MP_ROM_PTR(&pin_PA08) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_MISO1), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI1), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_SCK2), MP_ROM_PTR(&pin_PB13) },
+ { MP_ROM_QSTR(MP_QSTR_MISO2), MP_ROM_PTR(&pin_PB14) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI2), MP_ROM_PTR(&pin_PB15) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX1), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_RX1), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_TX2), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_RX2), MP_ROM_PTR(&pin_PA03) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_LED_GREEN), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_LED_YELLOW), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_LED_BLUE), MP_ROM_PTR(&pin_PA03) },
+
+ { MP_ROM_QSTR(MP_QSTR_SW), MP_ROM_PTR(&pin_PC13) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/stm32f4/boards/pyb_nano_v2/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/pyb_nano_v2/stm32f4xx_hal_conf.h
new file mode 100644
index 000000000..ab04df318
--- /dev/null
+++ b/ports/stm32f4/boards/pyb_nano_v2/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)8000000) /*!< 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/stm32f411ve_discovery/mpconfigboard.h b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h
index d7898ba0b..0c6f537f8 100644
--- a/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h
+++ b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h
@@ -32,6 +32,8 @@
#define FLASH_SIZE (0x80000) //512K
#define FLASH_PAGE_SIZE (0x4000) //16K
+#define BOARD_OSC_DIV 8
+
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x2000 - 0xC000)
diff --git a/ports/stm32f4/common-hal/busio/I2C.c b/ports/stm32f4/common-hal/busio/I2C.c
index c2f5dbe0a..d2292845e 100644
--- a/ports/stm32f4/common-hal/busio/I2C.c
+++ b/ports/stm32f4/common-hal/busio/I2C.c
@@ -36,6 +36,7 @@
#include "common-hal/microcontroller/Pin.h"
STATIC bool reserved_i2c[3];
+STATIC bool never_reset[3];
void i2c_reset(void) {
//Note: I2Cs are also forcibly reset in construct, due to silicon error
@@ -48,11 +49,24 @@ void i2c_reset(void) {
__HAL_RCC_I2C2_CLK_DISABLE();
#endif
#ifdef I2C3
- reserved_i2c[3] = false;
+ reserved_i2c[2] = false;
__HAL_RCC_I2C3_CLK_DISABLE();
#endif
}
+void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
+ for (size_t i = 0 ; i < MP_ARRAY_SIZE(mcu_i2c_banks); i++) {
+ if (self->handle.Instance == mcu_i2c_banks[i]) {
+ never_reset[i] = true;
+
+ never_reset_pin_number(self->scl->pin->port, self->scl->pin->number);
+ never_reset_pin_number(self->sda->pin->port, self->scl->pin->number);
+ break;
+ }
+ }
+}
+
+
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) {
@@ -166,19 +180,22 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
}
#ifdef I2C1
if(self->handle.Instance==I2C1) {
- reserved_i2c[0] = 0;
+ never_reset[0] = false;
+ reserved_i2c[0] = false;
__HAL_RCC_I2C1_CLK_DISABLE();
}
#endif
#ifdef I2C2
if(self->handle.Instance==I2C2) {
- reserved_i2c[1] = 0;
+ never_reset[1] = false;
+ reserved_i2c[1] = false;
__HAL_RCC_I2C2_CLK_DISABLE();
}
#endif
#ifdef I2C3
if(self->handle.Instance==I2C3) {
- reserved_i2c[3] = 0;
+ never_reset[2] = false;
+ reserved_i2c[2] = false;
__HAL_RCC_I2C3_CLK_DISABLE();
}
#endif
diff --git a/ports/stm32f4/common-hal/busio/SPI.c b/ports/stm32f4/common-hal/busio/SPI.c
index b5517f470..32089887f 100644
--- a/ports/stm32f4/common-hal/busio/SPI.c
+++ b/ports/stm32f4/common-hal/busio/SPI.c
@@ -165,7 +165,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
self->baudrate = (get_busclock(SPIx)/16);
self->prescaler = 16;
self->polarity = 0;
- self->phase = 1;
+ self->phase = 0;
self->bits = 8;
claim_pin(sck);
@@ -191,7 +191,8 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
spi_clock_disable(1<<(self->sck->spi_index - 1));
- reserved_spi[self->sck->spi_index - 1] = true;
+ reserved_spi[self->sck->spi_index - 1] = false;
+ never_reset_spi[self->sck->spi_index - 1] = false;
reset_pin_number(self->sck->pin->port,self->sck->pin->number);
reset_pin_number(self->mosi->pin->port,self->mosi->pin->number);
diff --git a/ports/stm32f4/common-hal/busio/UART.c b/ports/stm32f4/common-hal/busio/UART.c
index f0e0cc9eb..aa792dae1 100644
--- a/ports/stm32f4/common-hal/busio/UART.c
+++ b/ports/stm32f4/common-hal/busio/UART.c
@@ -250,10 +250,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
}
size_t rx_bytes = 0;
- uint64_t start_ticks = ticks_ms;
+ uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for all bytes received or timeout, same as nrf
- while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
+ while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
//restart if it failed in the callback
if (errflag != HAL_OK) {
diff --git a/ports/stm32f4/common-hal/digitalio/DigitalInOut.c b/ports/stm32f4/common-hal/digitalio/DigitalInOut.c
index 51b1fde73..36c1075e2 100644
--- a/ports/stm32f4/common-hal/digitalio/DigitalInOut.c
+++ b/ports/stm32f4/common-hal/digitalio/DigitalInOut.c
@@ -47,7 +47,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct(
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;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(pin_port(self->pin->port), &GPIO_InitStruct);
return DIGITALINOUT_OK;
@@ -73,7 +73,7 @@ void common_hal_digitalio_digitalinout_switch_to_input(
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;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(pin_port(self->pin->port), &GPIO_InitStruct);
common_hal_digitalio_digitalinout_set_pull(self, pull);
@@ -114,7 +114,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
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;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(pin_port(self->pin->port), &GPIO_InitStruct);
}
diff --git a/ports/stm32f4/common-hal/displayio/ParallelBus.c b/ports/stm32f4/common-hal/displayio/ParallelBus.c
new file mode 100644
index 000000000..1b808ec02
--- /dev/null
+++ b/ports/stm32f4/common-hal/displayio/ParallelBus.c
@@ -0,0 +1,68 @@
+/*
+ * 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 "shared-bindings/displayio/ParallelBus.h"
+
+#include <stdint.h>
+
+#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"
+
+void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* self,
+ const mcu_pin_obj_t* data0, const mcu_pin_obj_t* command, const mcu_pin_obj_t* chip_select,
+ const mcu_pin_obj_t* write, const mcu_pin_obj_t* read, const mcu_pin_obj_t* reset) {
+
+ mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
+}
+
+void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self) {
+
+}
+
+bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
+ return false;
+}
+
+bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
+ return false;
+}
+
+bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
+
+ return false;
+}
+
+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) {
+
+}
+
+void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {
+
+}
diff --git a/ports/stm32f4/common-hal/displayio/ParallelBus.h b/ports/stm32f4/common-hal/displayio/ParallelBus.h
new file mode 100644
index 000000000..85d100715
--- /dev/null
+++ b/ports/stm32f4/common-hal/displayio/ParallelBus.h
@@ -0,0 +1,36 @@
+/*
+ * 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_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
+#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
+
+#include "common-hal/digitalio/DigitalInOut.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} displayio_parallelbus_obj_t;
+
+#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
diff --git a/ports/stm32f4/common-hal/microcontroller/Pin.c b/ports/stm32f4/common-hal/microcontroller/Pin.c
index 21290e03c..615e48358 100644
--- a/ports/stm32f4/common-hal/microcontroller/Pin.c
+++ b/ports/stm32f4/common-hal/microcontroller/Pin.c
@@ -46,8 +46,12 @@ bool neopixel_in_use;
#elif MCU_PACKAGE == 64
#define GPIO_PORT_COUNT 3
GPIO_TypeDef * ports[GPIO_PORT_COUNT] = {GPIOA, GPIOB, GPIOC};
+#elif MCU_PACKAGE == 48
+ #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];
diff --git a/ports/stm32f4/common-hal/microcontroller/__init__.c b/ports/stm32f4/common-hal/microcontroller/__init__.c
index c7493a4d6..16cc056c1 100644
--- a/ports/stm32f4/common-hal/microcontroller/__init__.c
+++ b/ports/stm32f4/common-hal/microcontroller/__init__.c
@@ -48,9 +48,9 @@ STATIC uint32_t get_us(void) {
uint32_t ticks_per_us = HAL_RCC_GetSysClockFreq()/1000000;
uint32_t micros, sys_cycles;
do {
- micros = ticks_ms;
+ micros = supervisor_ticks_ms32();
sys_cycles = SysTick->VAL; //counts backwards
- } while (micros != ticks_ms); //try again if ticks_ms rolled over
+ } while (micros != supervisor_ticks_ms32()); //try again if ticks_ms rolled over
return (micros * 1000) + (ticks_per_us * 1000 - sys_cycles) / ticks_per_us;
}
@@ -169,7 +169,7 @@ STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = {
{ 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
+#if MCU_PACKAGE == 144
{ MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) },
#endif
{ MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) },
diff --git a/ports/stm32f4/common-hal/neopixel_write/__init__.c b/ports/stm32f4/common-hal/neopixel_write/__init__.c
index fd46825d0..6740a0d34 100644
--- a/ports/stm32f4/common-hal/neopixel_write/__init__.c
+++ b/ports/stm32f4/common-hal/neopixel_write/__init__.c
@@ -28,6 +28,8 @@
#include "shared-bindings/neopixel_write/__init__.h"
#include "tick.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
#include "common-hal/microcontroller/Pin.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_ll_gpio.h"
@@ -40,6 +42,9 @@ uint32_t next_start_tick_us = 1000;
#define MAGIC_800_T0H 2800000 // ~0.36 us -> 0.44 field
#define MAGIC_800_T1H 1350000 // ~0.74 us -> 0.84 field
+#pragma GCC push_options
+#pragma GCC optimize ("Os")
+
void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels,
uint32_t numBytes) {
uint8_t *p = pixels, *end = p + numBytes, pix = *p++, mask = 0x80;
@@ -48,7 +53,7 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
//assumes 800_000Hz frequency
//Theoretical values here are 800_000 -> 1.25us, 2500000->0.4us, 1250000->0.8us
- //But they don't work, possibly due to bad optimization? Use tested magic values instead
+ //TODO: try to get dynamic weighting working again
uint32_t sys_freq = HAL_RCC_GetSysClockFreq();
uint32_t interval = sys_freq/MAGIC_800_INT;
uint32_t t0 = (sys_freq/MAGIC_800_T0H);
@@ -63,23 +68,22 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
__disable_irq();
// Enable DWT in debug core. Useable when interrupts disabled, as opposed to Systick->VAL
- //ITM->LAR = 0xC5ACCE55; //this should be required but isn't
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
DWT->CYCCNT = 0;
for(;;) {
+ cyc = (pix & mask) ? t1 : t0;
start = DWT->CYCCNT;
LL_GPIO_SetOutputPin(p_port, p_mask);
- cyc = (pix & mask) ? t1 : t0;
- while(DWT->CYCCNT - start < cyc);
+ while((DWT->CYCCNT - start) < cyc);
LL_GPIO_ResetOutputPin(p_port, p_mask);
+ while((DWT->CYCCNT - start) < interval);
if(!(mask >>= 1)) {
if(p >= end) break;
pix = *p++;
mask = 0x80;
}
- while(DWT->CYCCNT - start < interval); //wait for interval to finish
}
// Enable interrupts again
@@ -94,3 +98,5 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
next_start_tick_us -= 100;
}
}
+
+#pragma GCC pop_options \ No newline at end of file
diff --git a/ports/stm32f4/common-hal/time/__init__.c b/ports/stm32f4/common-hal/time/__init__.c
index e3cb481ef..976f519db 100644
--- a/ports/stm32f4/common-hal/time/__init__.c
+++ b/ports/stm32f4/common-hal/time/__init__.c
@@ -29,7 +29,7 @@
#include "tick.h"
uint64_t common_hal_time_monotonic(void) {
- return ticks_ms;
+ return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {
diff --git a/ports/stm32f4/mpconfigport.mk b/ports/stm32f4/mpconfigport.mk
index 3ae0daaa0..88636a9d8 100644
--- a/ports/stm32f4/mpconfigport.mk
+++ b/ports/stm32f4/mpconfigport.mk
@@ -65,6 +65,9 @@ ifndef CIRCUITPY_NEOPIXEL_WRITE
CIRCUITPY_NEOPIXEL_WRITE = 1
endif
+ifndef
+CIRCUITPY_DISPLAYIO = 1
+endif
#ifeq ($(MCU_SUB_VARIANT), stm32f412zx)
#endif
diff --git a/ports/stm32f4/mphalport.c b/ports/stm32f4/mphalport.c
index ea864e7ce..f78e9c750 100644
--- a/ports/stm32f4/mphalport.c
+++ b/ports/stm32f4/mphalport.c
@@ -31,11 +31,13 @@
#include "py/mpstate.h"
#include "py/gc.h"
+#include "supervisor/shared/tick.h"
+
/*------------------------------------------------------------------*/
/* delay
*------------------------------------------------------------------*/
void mp_hal_delay_ms(mp_uint_t delay) {
- uint64_t start_tick = ticks_ms;
+ uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
#ifdef MICROPY_VM_HOOK_LOOP
@@ -46,7 +48,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
- duration = (ticks_ms - start_tick);
+ duration = (supervisor_ticks_ms64() - 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
index d184138f7..df2f0ca65 100644
--- a/ports/stm32f4/mphalport.h
+++ b/ports/stm32f4/mphalport.h
@@ -32,10 +32,10 @@
#include "lib/utils/interrupt_char.h"
#include "py/mpconfig.h"
+#include "supervisor/shared/tick.h"
-extern volatile uint64_t ticks_ms;
-#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms)
+#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32())
//#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us))
bool mp_hal_stdin_any(void);
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
index 883c252d5..53810af26 100644
--- a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/clocks.c
@@ -25,6 +25,7 @@
* THE SOFTWARE.
*/
#include "stm32f4xx_hal.h"
+#include "py/mpconfig.h"
void stm32f4_peripherals_clocks_init(void) {
//System clock init
@@ -44,7 +45,7 @@ void stm32f4_peripherals_clocks_init(void) {
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.PLLM = BOARD_OSC_DIV;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
index 2b80647c0..2b0e2b288 100644
--- a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
+++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/gpio.c
@@ -24,94 +24,12 @@
* 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 */
+ //* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
@@ -119,31 +37,12 @@ void stm32f4_peripherals_gpio_init(void) {
__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
@@ -152,18 +51,6 @@ void stm32f4_peripherals_gpio_init(void) {
//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/tick.c b/ports/stm32f4/tick.c
index 688f71dbd..f4adf183a 100644
--- a/ports/stm32f4/tick.c
+++ b/ports/stm32f4/tick.c
@@ -26,37 +26,23 @@
#include "tick.h"
-#include "supervisor/shared/autoreload.h"
#include "supervisor/filesystem.h"
-#include "shared-module/gamepad/__init__.h"
+#include "supervisor/shared/tick.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
+ // Do things common to all ports when the tick occurs
+ supervisor_tick();
}
uint32_t HAL_GetTick(void) //override ST HAL
{
- return (uint32_t)ticks_ms;
+ return (uint32_t)supervisor_ticks_ms32();
}
void tick_init() {
@@ -72,11 +58,11 @@ void tick_init() {
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;
+ uint64_t start_ms = supervisor_ticks_ms64();
while (us > 1000) {
- while (ticks_ms == start_ms) {}
+ while (supervisor_ticks_ms64() == start_ms) {}
us -= us_between_ticks;
- start_ms = ticks_ms;
+ start_ms = supervisor_ticks_ms64();
us_between_ticks = 1000;
}
while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
@@ -85,11 +71,11 @@ void tick_delay(uint32_t 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;
+ *ms = supervisor_ticks_ms32();
*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) {}
+ while(supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}
diff --git a/ports/stm32f4/tick.h b/ports/stm32f4/tick.h
index e4772fa2c..999acc7a3 100644
--- a/ports/stm32f4/tick.h
+++ b/ports/stm32f4/tick.h
@@ -30,8 +30,6 @@
#include <stdint.h>
-extern volatile uint64_t ticks_ms;
-
extern struct timer_descriptor ms_timer;
void tick_init(void);
diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c
index 841924c58..849820fff 100644
--- a/ports/unix/coverage.c
+++ b/ports/unix/coverage.c
@@ -96,6 +96,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
STATIC const mp_stream_p_t fileio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stest_read,
.write = stest_write,
.ioctl = stest_ioctl,
@@ -123,6 +124,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = {
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2);
STATIC const mp_stream_p_t textio_stream_p2 = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stest_read2,
.write = NULL,
.is_text = true,
diff --git a/ports/unix/file.c b/ports/unix/file.c
index c0cf6dcc4..e5c73d26c 100644
--- a/ports/unix/file.c
+++ b/ports/unix/file.c
@@ -230,6 +230,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t fileio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = fdfile_read,
.write = fdfile_write,
.ioctl = fdfile_ioctl,
@@ -248,6 +249,7 @@ const mp_obj_type_t mp_type_fileio = {
#endif
STATIC const mp_stream_p_t textio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = fdfile_read,
.write = fdfile_write,
.ioctl = fdfile_ioctl,
diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c
index 84e9298fd..95da276ed 100644
--- a/ports/unix/modusocket.c
+++ b/ports/unix/modusocket.c
@@ -374,6 +374,7 @@ STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(usocket_locals_dict, usocket_locals_dict_table);
STATIC const mp_stream_p_t usocket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 211e85368..446620d27 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -117,6 +117,9 @@ endif
ifeq ($(CIRCUITPY_AUDIOMIXER),1)
SRC_PATTERNS += audiomixer/%
endif
+ifeq ($(CIRCUITPY_AUDIOMP3),1)
+SRC_PATTERNS += audiomp3/%
+endif
ifeq ($(CIRCUITPY_BITBANGIO),1)
SRC_PATTERNS += bitbangio/%
endif
@@ -319,6 +322,8 @@ SRC_SHARED_MODULE_ALL = \
audiomixer/__init__.c \
audiomixer/Mixer.c \
audiomixer/MixerVoice.c \
+ audiomp3/__init__.c \
+ audiomp3/MP3File.c \
bitbangio/I2C.c \
bitbangio/OneWire.c \
bitbangio/SPI.c \
@@ -371,6 +376,26 @@ SRC_SHARED_MODULE_ALL += \
touchio/TouchIn.c \
touchio/__init__.c
endif
+ifeq ($(CIRCUITPY_AUDIOMP3),1)
+SRC_MOD += $(addprefix lib/mp3/src/, \
+ bitstream.c \
+ buffers.c \
+ dct32.c \
+ dequant.c \
+ dqchan.c \
+ huffman.c \
+ hufftabs.c \
+ imdct.c \
+ mp3dec.c \
+ mp3tabs.c \
+ polyphase.c \
+ scalfact.c \
+ stproc.c \
+ subband.c \
+ trigtabs.c \
+)
+$(BUILD)/lib/mp3/src/buffers.o: CFLAGS += -include "py/misc.h" -D'MPDEC_ALLOCATOR(x)=m_malloc(x,0)' -D'MPDEC_FREE(x)=m_free(x)'
+endif
# All possible sources are listed here, and are filtered by SRC_PATTERNS.
SRC_SHARED_MODULE_INTERNAL = \
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index b1e7bc05a..5ee5d52c0 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -28,11 +28,12 @@
// sure that the same feature set and settings are used, such as in atmel-samd
// and nrf.
-#include <stdint.h>
-
#ifndef __INCLUDED_MPCONFIG_CIRCUITPY_H
#define __INCLUDED_MPCONFIG_CIRCUITPY_H
+#include <stdint.h>
+#include <stdatomic.h>
+
// This is CircuitPython.
#define CIRCUITPY 1
@@ -251,6 +252,13 @@ extern const struct _mp_obj_module_t audiomixer_module;
#define AUDIOMIXER_MODULE
#endif
+#if CIRCUITPY_AUDIOMP3
+#define AUDIOMP3_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiomp3), (mp_obj_t)&audiomp3_module },
+extern const struct _mp_obj_module_t audiomp3_module;
+#else
+#define AUDIOMP3_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;
@@ -581,6 +589,7 @@ extern const struct _mp_obj_module_t ustack_module;
AUDIOCORE_MODULE \
AUDIOIO_MODULE \
AUDIOMIXER_MODULE \
+ AUDIOMP3_MODULE \
AUDIOPWMIO_MODULE \
BITBANGIO_MODULE \
BLEIO_MODULE \
@@ -652,17 +661,19 @@ extern const struct _mp_obj_module_t ustack_module;
FLASH_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \
-void run_background_tasks(void);
-#define RUN_BACKGROUND_TASKS (run_background_tasks())
+void supervisor_run_background_tasks_if_tick(void);
+#define RUN_BACKGROUND_TASKS (supervisor_run_background_tasks_if_tick())
// TODO: Used in wiznet5k driver, but may not be needed in the long run.
#define MICROPY_THREAD_YIELD()
-#define MICROPY_VM_HOOK_LOOP run_background_tasks();
-#define MICROPY_VM_HOOK_RETURN run_background_tasks();
+#define MICROPY_VM_HOOK_LOOP RUN_BACKGROUND_TASKS;
+#define MICROPY_VM_HOOK_RETURN RUN_BACKGROUND_TASKS;
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
#define CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS 1000
#define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt"
+#define CIRCUITPY_VERBOSE_BLE 0
+
#endif // __INCLUDED_MPCONFIG_CIRCUITPY_H
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index 241fa1017..c614ea06a 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -104,6 +104,15 @@ CIRCUITPY_AUDIOMIXER = $(CIRCUITPY_AUDIOIO)
endif
CFLAGS += -DCIRCUITPY_AUDIOMIXER=$(CIRCUITPY_AUDIOMIXER)
+ifndef CIRCUITPY_AUDIOMP3
+ifeq ($(CIRCUITPY_FULL_BUILD),1)
+CIRCUITPY_AUDIOMP3 = $(CIRCUITPY_AUDIOCORE)
+else
+CIRCUITPY_AUDIOMP3 = 0
+endif
+endif
+CFLAGS += -DCIRCUITPY_AUDIOMP3=$(CIRCUITPY_AUDIOMP3)
+
ifndef CIRCUITPY_BITBANGIO
CIRCUITPY_BITBANGIO = $(CIRCUITPY_FULL_BUILD)
endif
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 8e3835d86..0d667959d 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -103,14 +103,10 @@ def compute_huffman_coding(translations, qstrs, compression_filename):
# go through each qstr and print it out
for _, _, qstr in qstrs.values():
all_strings.append(qstr)
- all_strings_concat = "".join(all_strings).encode("utf-8")
+ all_strings_concat = "".join(all_strings)
counts = collections.Counter(all_strings_concat)
- # add other values
- for i in range(256):
- if i not in counts:
- counts[i] = 0
cb = huffman.codebook(counts.items())
- values = bytearray()
+ values = []
length_count = {}
renumbered = 0
last_l = None
@@ -124,26 +120,27 @@ def compute_huffman_coding(translations, qstrs, compression_filename):
if last_l:
renumbered <<= (l - last_l)
canonical[ch] = '{0:0{width}b}'.format(renumbered, width=l)
- if chr(ch) in C_ESCAPES:
- s = C_ESCAPES[chr(ch)]
- else:
- s = chr(ch)
- print("//", ch, s, counts[ch], canonical[ch], renumbered)
+ s = C_ESCAPES.get(ch, ch)
+ print("//", ord(ch), s, counts[ch], canonical[ch], renumbered)
renumbered += 1
last_l = l
lengths = bytearray()
- for i in range(1, max(length_count) + 1):
+ print("// length count", length_count)
+ for i in range(1, max(length_count) + 2):
lengths.append(length_count.get(i, 0))
+ print("// values", values, "lengths", len(lengths), lengths)
+ print("// estimated total memory size", len(lengths) + 2*len(values) + sum(len(cb[u]) for u in all_strings_concat))
print("//", values, lengths)
+ values_type = "uint16_t" if max(ord(u) for u in values) > 255 else "uint8_t"
with open(compression_filename, "w") as f:
f.write("const uint8_t lengths[] = {{ {} }};\n".format(", ".join(map(str, lengths))))
- f.write("const uint8_t values[256] = {{ {} }};\n".format(", ".join(map(str, values))))
+ f.write("const {} values[] = {{ {} }};\n".format(values_type, ", ".join(str(ord(u)) for u in values)))
return values, lengths
def decompress(encoding_table, length, encoded):
values, lengths = encoding_table
#print(l, encoded)
- dec = bytearray(length)
+ dec = []
this_byte = 0
this_bit = 7
b = encoded[this_byte]
@@ -173,14 +170,14 @@ def decompress(encoding_table, length, encoded):
searched_length += lengths[bit_length]
v = values[searched_length + bits - max_code]
- dec[i] = v
- return dec
+ dec.append(v)
+ return ''.join(dec)
def compress(encoding_table, decompressed):
- if not isinstance(decompressed, bytes):
+ if not isinstance(decompressed, str):
raise TypeError()
values, lengths = encoding_table
- enc = bytearray(len(decompressed) * 2)
+ enc = bytearray(len(decompressed) * 3)
#print(decompressed)
#print(lengths)
current_bit = 7
@@ -228,7 +225,7 @@ def compress(encoding_table, decompressed):
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)
+ print("Note: compression increased length", repr(decompressed), len(decompressed), current_byte, file=sys.stderr)
return enc[:current_byte]
def qstr_escape(qst):
@@ -347,9 +344,9 @@ def print_qstr_data(encoding_table, qcfgs, qstrs, i18ns):
total_text_compressed_size = 0
for original, translation in i18ns:
translation_encoded = translation.encode("utf-8")
- compressed = compress(encoding_table, translation_encoded)
+ compressed = compress(encoding_table, translation)
total_text_compressed_size += len(compressed)
- decompressed = decompress(encoding_table, len(translation_encoded), compressed).decode("utf-8")
+ decompressed = decompress(encoding_table, len(translation_encoded), compressed)
for c in C_ESCAPES:
decompressed = decompressed.replace(c, C_ESCAPES[c])
print("TRANSLATION(\"{}\", {}, {{ {} }}) // {}".format(original, len(translation_encoded)+1, ", ".join(["0x{:02x}".format(x) for x in compressed]), decompressed))
diff --git a/py/modio.c b/py/modio.c
index d7c1a58a8..17840a6d8 100644
--- a/py/modio.c
+++ b/py/modio.c
@@ -90,6 +90,7 @@ STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, in
}
STATIC const mp_stream_p_t iobase_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = iobase_read,
.write = iobase_write,
.ioctl = iobase_ioctl,
@@ -185,6 +186,7 @@ STATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table);
STATIC const mp_stream_p_t bufwriter_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.write = bufwriter_write,
};
diff --git a/py/objstringio.c b/py/objstringio.c
index d2ca6decd..178e6446c 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -240,6 +240,7 @@ STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table);
STATIC const mp_stream_p_t stringio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stringio_read,
.write = stringio_write,
.ioctl = stringio_ioctl,
@@ -247,6 +248,7 @@ STATIC const mp_stream_p_t stringio_stream_p = {
};
STATIC const mp_stream_p_t bytesio_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = stringio_read,
.write = stringio_write,
.ioctl = stringio_ioctl,
diff --git a/py/proto.c b/py/proto.c
new file mode 100644
index 000000000..e5053130b
--- /dev/null
+++ b/py/proto.c
@@ -0,0 +1,50 @@
+/*
+ * 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 "py/obj.h"
+#include "py/proto.h"
+#include "py/runtime.h"
+
+#ifndef MICROPY_UNSAFE_PROTO
+const void *mp_proto_get(uint16_t name, mp_const_obj_t obj) {
+ mp_obj_type_t *type = mp_obj_get_type(obj);
+ if (!type->protocol) return NULL;
+ uint16_t proto_name = *(const uint16_t*) type->protocol;
+ if (proto_name == name) {
+ return type->protocol;
+ }
+ return NULL;
+}
+#endif
+
+const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj) {
+ const void *proto = mp_proto_get(name, obj);
+ if (proto) {
+ return proto;
+ }
+ mp_raise_TypeError_varg(translate("'%s' object does not support '%q'"),
+ mp_obj_get_type_str(obj), name);
+}
diff --git a/py/proto.h b/py/proto.h
new file mode 100644
index 000000000..2d4f80565
--- /dev/null
+++ b/py/proto.h
@@ -0,0 +1,43 @@
+/*
+ * 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_PY_PROTO_H
+#define MICROPY_INCLUDED_PY_PROTO_H
+
+#ifdef MICROPY_UNSAFE_PROTO
+#define MP_PROTOCOL_HEAD /* NOTHING */
+#define MP_PROTO_IMPLEMENT(name) /* NOTHING */
+static inline void *mp_proto_get(uint16_t name, mp_const_obj_type_t obj) { return mp_obj_get_type(obj)->protocol; }
+#else
+#define MP_PROTOCOL_HEAD \
+ uint16_t name; // The name of this protocol, a qstr
+#define MP_PROTO_IMPLEMENT(n) .name = n,
+const void *mp_proto_get(uint16_t name, mp_const_obj_t obj);
+const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj);
+#endif
+
+#endif
+
diff --git a/py/py.mk b/py/py.mk
index 17cb79264..ae9b005b6 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -214,6 +214,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\
objtype.o \
objzip.o \
opmethods.o \
+ proto.o \
reload.o \
sequence.o \
stream.o \
diff --git a/py/stream.c b/py/stream.c
index 1d25f6470..2ff2b76a6 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -86,8 +86,7 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode
}
const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) {
- mp_obj_type_t *type = mp_obj_get_type(self_in);
- const mp_stream_p_t *stream_p = type->protocol;
+ const mp_stream_p_t *stream_p = mp_proto_get(MP_QSTR_protocol_stream, self_in);
if (stream_p == NULL
|| ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL)
|| ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL)
@@ -522,7 +521,7 @@ int mp_stream_errno;
ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) {
mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = mp_get_stream(o);
mp_uint_t out_sz = stream_p->write(stream, buf, len, &mp_stream_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
@@ -533,7 +532,7 @@ ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) {
ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) {
mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = mp_get_stream(o);
mp_uint_t out_sz = stream_p->read(stream, buf, len, &mp_stream_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
@@ -544,7 +543,7 @@ ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) {
off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) {
const mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = mp_get_stream(o);
struct mp_stream_seek_t seek_s;
seek_s.offset = offset;
seek_s.whence = whence;
@@ -557,7 +556,7 @@ off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) {
int mp_stream_posix_fsync(mp_obj_t stream) {
mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream);
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = mp_get_stream(o);
mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_FLUSH, 0, &mp_stream_errno);
if (res == MP_STREAM_ERROR) {
return -1;
diff --git a/py/stream.h b/py/stream.h
index 03e24c746..543fe8c82 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -27,6 +27,7 @@
#define MICROPY_INCLUDED_PY_STREAM_H
#include "py/obj.h"
+#include "py/proto.h"
#include "py/mperrno.h"
#define MP_STREAM_ERROR ((mp_uint_t)-1)
@@ -64,6 +65,7 @@ struct mp_stream_seek_t {
// Stream protocol
typedef struct _mp_stream_p_t {
+ MP_PROTOCOL_HEAD
// On error, functions should return MP_STREAM_ERROR and fill in *errcode (values
// are implementation-dependent, but will be exposed to user, e.g. via exception).
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
@@ -93,7 +95,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj);
// Object is assumed to have a non-NULL stream protocol with valid r/w/ioctl methods
static inline const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) {
- return (const mp_stream_p_t*)((const mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type->protocol;
+ return mp_proto_get(MP_QSTR_protocol_stream, self);
}
const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags);
diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c
index 7e2a5f05b..9772fa830 100644
--- a/shared-bindings/_bleio/Adapter.c
+++ b/shared-bindings/_bleio/Adapter.c
@@ -144,6 +144,9 @@ const mp_obj_property_t bleio_adapter_name_obj = {
//| Starts advertising until `stop_advertising` is called or if connectable, another device
//| connects to us.
//|
+//| .. warning: If data is longer than 31 bytes, then this will automatically advertise as an
+//| extended advertisement that older BLE 4.x clients won't be able to scan for.
+//|
//| :param buf data: advertising data packet bytes
//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed.
//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral.
diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c
index e7524da2d..fc95d0d50 100644
--- a/shared-bindings/_bleio/CharacteristicBuffer.c
+++ b/shared-bindings/_bleio/CharacteristicBuffer.c
@@ -230,6 +230,7 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_buffer_locals_dict_table[] =
STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_buffer_locals_dict, bleio_characteristic_buffer_locals_dict_table);
STATIC const mp_stream_p_t characteristic_buffer_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = bleio_characteristic_buffer_read,
.write = bleio_characteristic_buffer_write,
.ioctl = bleio_characteristic_buffer_ioctl,
diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c
index da2fbff28..c157af365 100644
--- a/shared-bindings/_bleio/Connection.c
+++ b/shared-bindings/_bleio/Connection.c
@@ -66,7 +66,7 @@
//| connection = _bleio.adapter.connect(my_entry.address, timeout=10)
//|
-STATIC void ensure_connected(bleio_connection_obj_t *self) {
+void bleio_connection_ensure_connected(bleio_connection_obj_t *self) {
if (!common_hal_bleio_connection_get_connected(self)) {
mp_raise_bleio_ConnectionError(translate("Connection has been disconnected and can no longer be used. Create a new connection."));
}
@@ -80,14 +80,12 @@ STATIC void ensure_connected(bleio_connection_obj_t *self) {
//|
//| .. method:: disconnect()
//|
-//| Disconnects from the remote peripheral.
+//| Disconnects from the remote peripheral. Does nothing if already disconnected.
//|
STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) {
bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
- ensure_connected(self);
-
+ // common_hal_bleio_connection_disconnect() does nothing if already disconnected.
common_hal_bleio_connection_disconnect(self->connection);
-
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connection_disconnect);
@@ -108,7 +106,7 @@ STATIC mp_obj_t bleio_connection_pair(mp_uint_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);
- ensure_connected(self);
+ bleio_connection_ensure_connected(self);
common_hal_bleio_connection_pair(self->connection, args[ARG_bond].u_bool);
return mp_const_none;
@@ -150,7 +148,7 @@ STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, cons
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);
- ensure_connected(self);
+ bleio_connection_ensure_connected(self);
return MP_OBJ_FROM_PTR(common_hal_bleio_connection_discover_remote_services(
self,
@@ -195,6 +193,46 @@ const mp_obj_property_t bleio_connection_paired_obj = {
(mp_obj_t)&mp_const_none_obj },
};
+
+//| .. attribute:: connection_interval
+//|
+//| Time between transmissions in milliseconds. Will be multiple of 1.25ms. Lower numbers
+//| increase speed and decrease latency but increase power consumption.
+//|
+//| When setting connection_interval, the peer may reject the new interval and
+//| `connection_interval` will then remain the same.
+//|
+//| Apple has additional guidelines that dictate should be a multiple of 15ms except if HID is
+//| available. When HID is available Apple devices may accept 11.25ms intervals.
+//|
+//|
+STATIC mp_obj_t bleio_connection_get_connection_interval(mp_obj_t self_in) {
+ bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ bleio_connection_ensure_connected(self);
+ return mp_obj_new_float(common_hal_bleio_connection_get_connection_interval(self->connection));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connection_interval_obj, bleio_connection_get_connection_interval);
+
+STATIC mp_obj_t bleio_connection_set_connection_interval(mp_obj_t self_in, mp_obj_t interval_in) {
+ bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_float_t interval = mp_obj_get_float(interval_in);
+
+ bleio_connection_ensure_connected(self);
+ common_hal_bleio_connection_set_connection_interval(self->connection, interval);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_connection_set_connection_interval_obj, bleio_connection_set_connection_interval);
+
+const mp_obj_property_t bleio_connection_connection_interval_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_connection_get_connection_interval_obj,
+ (mp_obj_t)&bleio_connection_set_connection_interval_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_connection_pair_obj) },
@@ -202,8 +240,10 @@ STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_connection_discover_remote_services_obj) },
// Properties
- { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) },
- { MP_ROM_QSTR(MP_QSTR_paired), MP_ROM_PTR(&bleio_connection_paired_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_paired), MP_ROM_PTR(&bleio_connection_paired_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connection_interval), MP_ROM_PTR(&bleio_connection_connection_interval_obj) },
+
};
STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table);
diff --git a/shared-bindings/_bleio/Connection.h b/shared-bindings/_bleio/Connection.h
index f7eee180f..c6f260160 100644
--- a/shared-bindings/_bleio/Connection.h
+++ b/shared-bindings/_bleio/Connection.h
@@ -40,4 +40,9 @@ extern bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *se
extern bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self);
extern mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist);
+mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self);
+void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval);
+
+void bleio_connection_ensure_connected(bleio_connection_obj_t *self);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H
diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c
index 43679393a..bc242bc36 100644
--- a/shared-bindings/_bleio/Service.c
+++ b/shared-bindings/_bleio/Service.c
@@ -136,7 +136,7 @@ const mp_obj_property_t bleio_service_secondary_obj = {
//| .. attribute:: uuid
//|
//| The UUID of this service. (read-only)
-//|
+//|
//| Will be ``None`` if the 128-bit UUID for this service is not known.
//|
STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) {
diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c
index 07f8c683f..87d410ea1 100644
--- a/shared-bindings/audiocore/RawSample.c
+++ b/shared-bindings/audiocore/RawSample.c
@@ -180,9 +180,20 @@ STATIC const mp_rom_map_elem_t audioio_rawsample_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(audioio_rawsample_locals_dict, audioio_rawsample_locals_dict_table);
+STATIC const audiosample_p_t audioio_rawsample_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
+ .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_rawsample_get_sample_rate,
+ .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_rawsample_get_bits_per_sample,
+ .channel_count = (audiosample_channel_count_fun)common_hal_audioio_rawsample_get_channel_count,
+ .reset_buffer = (audiosample_reset_buffer_fun)audioio_rawsample_reset_buffer,
+ .get_buffer = (audiosample_get_buffer_fun)audioio_rawsample_get_buffer,
+ .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_rawsample_get_buffer_structure,
+};
+
const mp_obj_type_t audioio_rawsample_type = {
{ &mp_type_type },
.name = MP_QSTR_RawSample,
.make_new = audioio_rawsample_make_new,
.locals_dict = (mp_obj_dict_t*)&audioio_rawsample_locals_dict,
+ .protocol = &audioio_rawsample_proto,
};
diff --git a/shared-bindings/audiocore/RawSample.h b/shared-bindings/audiocore/RawSample.h
index b02778cad..61f61a066 100644
--- a/shared-bindings/audiocore/RawSample.h
+++ b/shared-bindings/audiocore/RawSample.h
@@ -39,6 +39,8 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t* self,
void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t* self);
bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t* self);
uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t* self);
+uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t* self);
+uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t* self);
void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t* self, uint32_t sample_rate);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_RAWSAMPLE_H
diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c
index 1b3a94ff3..178d2a139 100644
--- a/shared-bindings/audiocore/WaveFile.c
+++ b/shared-bindings/audiocore/WaveFile.c
@@ -206,9 +206,21 @@ STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table);
+STATIC const audiosample_p_t audioio_wavefile_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
+ .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_wavefile_get_sample_rate,
+ .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_wavefile_get_bits_per_sample,
+ .channel_count = (audiosample_channel_count_fun)common_hal_audioio_wavefile_get_channel_count,
+ .reset_buffer = (audiosample_reset_buffer_fun)audioio_wavefile_reset_buffer,
+ .get_buffer = (audiosample_get_buffer_fun)audioio_wavefile_get_buffer,
+ .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_wavefile_get_buffer_structure,
+};
+
+
const mp_obj_type_t audioio_wavefile_type = {
{ &mp_type_type },
.name = MP_QSTR_WaveFile,
.make_new = audioio_wavefile_make_new,
.locals_dict = (mp_obj_dict_t*)&audioio_wavefile_locals_dict,
+ .protocol = &audioio_wavefile_proto,
};
diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c
index ed7b95d9e..03ffb9373 100644
--- a/shared-bindings/audiomixer/Mixer.c
+++ b/shared-bindings/audiomixer/Mixer.c
@@ -291,9 +291,20 @@ STATIC const mp_rom_map_elem_t audiomixer_mixer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(audiomixer_mixer_locals_dict, audiomixer_mixer_locals_dict_table);
+STATIC const audiosample_p_t audiomixer_mixer_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
+ .sample_rate = (audiosample_sample_rate_fun)common_hal_audiomixer_mixer_get_sample_rate,
+ .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomixer_mixer_get_bits_per_sample,
+ .channel_count = (audiosample_channel_count_fun)common_hal_audiomixer_mixer_get_channel_count,
+ .reset_buffer = (audiosample_reset_buffer_fun)audiomixer_mixer_reset_buffer,
+ .get_buffer = (audiosample_get_buffer_fun)audiomixer_mixer_get_buffer,
+ .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomixer_mixer_get_buffer_structure,
+};
+
const mp_obj_type_t audiomixer_mixer_type = {
{ &mp_type_type },
.name = MP_QSTR_Mixer,
.make_new = audiomixer_mixer_make_new,
.locals_dict = (mp_obj_dict_t*)&audiomixer_mixer_locals_dict,
+ .protocol = &audiomixer_mixer_proto,
};
diff --git a/shared-bindings/audiomixer/Mixer.h b/shared-bindings/audiomixer/Mixer.h
index 9eabbf61d..a99e1bf62 100644
--- a/shared-bindings/audiomixer/Mixer.h
+++ b/shared-bindings/audiomixer/Mixer.h
@@ -47,5 +47,7 @@ bool common_hal_audiomixer_mixer_deinited(audiomixer_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);
+uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t* self);
+uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t* self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER_MIXER_H
diff --git a/shared-bindings/audiomp3/MP3File.c b/shared-bindings/audiomp3/MP3File.c
new file mode 100644
index 000000000..f518bae4b
--- /dev/null
+++ b/shared-bindings/audiomp3/MP3File.c
@@ -0,0 +1,226 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ * 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 "lib/utils/context_manager_helpers.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/audiomp3/MP3File.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: audiomp3
+//|
+//| :class:`MP3` -- Load a mp3 file for audio playback
+//| ========================================================
+//|
+//| A .mp3 file prepped for audio playback. Only mono and stereo files are supported. Samples must
+//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
+//| an internal buffer.
+//|
+//| .. class:: MP3(file[, buffer])
+//|
+//| Load a .mp3 file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
+//|
+//| :param typing.BinaryIO file: Already opened mp3 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 buffers are allocated internally. The specific buffer size required depends on the mp3 file.
+//|
+//|
+//| Playing a mp3 file from flash::
+//|
+//| import board
+//| import audiomp3
+//| import audioio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| data = open("cplay-16bit-16khz-64kbps.mp3", "rb")
+//| mp3 = audiomp3.MP3File(data)
+//| a = audioio.AudioOut(board.A0)
+//|
+//| print("playing")
+//| a.play(mp3)
+//| while a.playing:
+//| pass
+//| print("stopped")
+//|
+STATIC mp_obj_t audiomp3_mp3file_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, 2, false);
+
+ audiomp3_mp3file_obj_t *self = m_new_obj(audiomp3_mp3file_obj_t);
+ self->base.type = &audiomp3_mp3file_type;
+ 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_audiomp3_mp3file_construct(self, MP_OBJ_TO_PTR(args[0]),
+ buffer, buffer_size);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the MP3 and releases all memory resources for reuse.
+//|
+STATIC mp_obj_t audiomp3_mp3file_deinit(mp_obj_t self_in) {
+ audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_audiomp3_mp3file_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_deinit_obj, audiomp3_mp3file_deinit);
+
+STATIC void check_for_deinit(audiomp3_mp3file_obj_t *self) {
+ if (common_hal_audiomp3_mp3file_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 audiomp3_mp3file_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_audiomp3_mp3file_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomp3_mp3file___exit___obj, 4, 4, audiomp3_mp3file_obj___exit__);
+
+//| .. attribute:: sample_rate
+//|
+//| 32 bit value that dictates how quickly samples are loaded into the DAC
+//| in Hertz (cycles per second). When the sample is looped, this can change
+//| the pitch output without changing the underlying sample.
+//|
+STATIC mp_obj_t audiomp3_mp3file_obj_get_sample_rate(mp_obj_t self_in) {
+ audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_sample_rate(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_sample_rate_obj, audiomp3_mp3file_obj_get_sample_rate);
+
+STATIC mp_obj_t audiomp3_mp3file_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
+ audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ common_hal_audiomp3_mp3file_set_sample_rate(self, mp_obj_get_int(sample_rate));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_sample_rate_obj, audiomp3_mp3file_obj_set_sample_rate);
+
+const mp_obj_property_t audiomp3_mp3file_sample_rate_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomp3_mp3file_get_sample_rate_obj,
+ (mp_obj_t)&audiomp3_mp3file_set_sample_rate_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: bits_per_sample
+//|
+//| Bits per sample. (read only)
+//|
+STATIC mp_obj_t audiomp3_mp3file_obj_get_bits_per_sample(mp_obj_t self_in) {
+ audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_bits_per_sample(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_bits_per_sample_obj, audiomp3_mp3file_obj_get_bits_per_sample);
+
+const mp_obj_property_t audiomp3_mp3file_bits_per_sample_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomp3_mp3file_get_bits_per_sample_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: channel_count
+//|
+//| Number of audio channels. (read only)
+//|
+STATIC mp_obj_t audiomp3_mp3file_obj_get_channel_count(mp_obj_t self_in) {
+ audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ check_for_deinit(self);
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_channel_count(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_channel_count_obj, audiomp3_mp3file_obj_get_channel_count);
+
+const mp_obj_property_t audiomp3_mp3file_channel_count_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audiomp3_mp3file_get_channel_count_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
+STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiomp3_mp3file_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiomp3_mp3file___exit___obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiomp3_mp3file_sample_rate_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiomp3_mp3file_bits_per_sample_obj) },
+ { MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiomp3_mp3file_channel_count_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(audiomp3_mp3file_locals_dict, audiomp3_mp3file_locals_dict_table);
+
+STATIC const audiosample_p_t audiomp3_mp3file_proto = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
+ .sample_rate = (audiosample_sample_rate_fun)common_hal_audiomp3_mp3file_get_sample_rate,
+ .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomp3_mp3file_get_bits_per_sample,
+ .channel_count = (audiosample_channel_count_fun)common_hal_audiomp3_mp3file_get_channel_count,
+ .reset_buffer = (audiosample_reset_buffer_fun)audiomp3_mp3file_reset_buffer,
+ .get_buffer = (audiosample_get_buffer_fun)audiomp3_mp3file_get_buffer,
+ .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomp3_mp3file_get_buffer_structure,
+};
+
+const mp_obj_type_t audiomp3_mp3file_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_MP3File,
+ .make_new = audiomp3_mp3file_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audiomp3_mp3file_locals_dict,
+ .protocol = &audiomp3_mp3file_proto,
+};
diff --git a/shared-bindings/audiomp3/MP3File.h b/shared-bindings/audiomp3/MP3File.h
new file mode 100644
index 000000000..adc13ea2c
--- /dev/null
+++ b/shared-bindings/audiomp3/MP3File.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * 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_SHARED_BINDINGS_AUDIOIO_MP3FILE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MP3FILE_H
+
+#include "py/obj.h"
+#include "extmod/vfs_fat.h"
+
+#include "shared-module/audiomp3/MP3File.h"
+
+extern const mp_obj_type_t audiomp3_mp3file_type;
+
+void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
+ pyb_file_obj_t* file, uint8_t *buffer, size_t buffer_size);
+
+void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t* self);
+bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t* self);
+uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t* self);
+void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t* self, uint32_t sample_rate);
+uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t* self);
+uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MP3FILE_H
diff --git a/shared-bindings/audiomp3/__init__.c b/shared-bindings/audiomp3/__init__.c
new file mode 100644
index 000000000..06f852ff1
--- /dev/null
+++ b/shared-bindings/audiomp3/__init__.c
@@ -0,0 +1,60 @@
+/*
+ * 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 "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/audiomp3/MP3File.h"
+
+//| :mod:`audiomp3` --- Support for MP3-compressed audio files
+//| ==========================================================
+//|
+//| .. module:: audiomp3
+//| :synopsis: Support for mp3 files
+//|
+//| The `audiomp3` module contains an mp3 decoder
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| MP3File
+//|
+
+STATIC const mp_rom_map_elem_t audiomp3_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiomp3) },
+ { MP_ROM_QSTR(MP_QSTR_MP3File), MP_ROM_PTR(&audiomp3_mp3file_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(audiomp3_module_globals, audiomp3_module_globals_table);
+
+const mp_obj_module_t audiomp3_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&audiomp3_module_globals,
+};
diff --git a/shared-bindings/audiomp3/__init__.h b/shared-bindings/audiomp3/__init__.h
new file mode 100644
index 000000000..9026af636
--- /dev/null
+++ b/shared-bindings/audiomp3/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * 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_SHARED_BINDINGS_AUDIOMP3___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMP3___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMP3___INIT___H
diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c
index 7a3b48e89..1fc81e78e 100644
--- a/shared-bindings/busio/UART.c
+++ b/shared-bindings/busio/UART.c
@@ -398,6 +398,7 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(busio_uart_locals_dict, busio_uart_locals_dict_table);
STATIC const mp_stream_p_t uart_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = busio_uart_read,
.write = busio_uart_write,
.ioctl = busio_uart_ioctl,
diff --git a/shared-bindings/displayio/OnDiskBitmap.c b/shared-bindings/displayio/OnDiskBitmap.c
index bf00ef855..f7e2bf693 100644
--- a/shared-bindings/displayio/OnDiskBitmap.c
+++ b/shared-bindings/displayio/OnDiskBitmap.c
@@ -59,7 +59,7 @@
//|
//| with open("/sample.bmp", "rb") as f:
//| odb = displayio.OnDiskBitmap(f)
-//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter(), position=(0,0))
+//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter())
//| splash.append(face)
//| # Wait for the image to load.
//| board.DISPLAY.wait_for_frame()
diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c
index 6d04a9893..2d6c16e90 100644
--- a/shared-bindings/socket/__init__.c
+++ b/shared-bindings/socket/__init__.c
@@ -500,6 +500,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *
}
STATIC const mp_stream_p_t socket_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.ioctl = socket_ioctl,
.is_text = false,
};
diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c
index cdde672d3..9c01fba20 100644
--- a/shared-bindings/terminalio/Terminal.c
+++ b/shared-bindings/terminalio/Terminal.c
@@ -112,6 +112,7 @@ STATIC const mp_rom_map_elem_t terminalio_terminal_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(terminalio_terminal_locals_dict, terminalio_terminal_locals_dict_table);
STATIC const mp_stream_p_t terminalio_terminal_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = NULL,
.write = terminalio_terminal_write,
.ioctl = terminalio_terminal_ioctl,
diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c
index 356a81d52..e2df56e95 100644
--- a/shared-bindings/usb_midi/PortIn.c
+++ b/shared-bindings/usb_midi/PortIn.c
@@ -107,6 +107,7 @@ STATIC const mp_rom_map_elem_t usb_midi_portin_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(usb_midi_portin_locals_dict, usb_midi_portin_locals_dict_table);
STATIC const mp_stream_p_t usb_midi_portin_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = usb_midi_portin_read,
.write = NULL,
.ioctl = usb_midi_portin_ioctl,
diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c
index 6f4ce6716..e3eddfaf5 100644
--- a/shared-bindings/usb_midi/PortOut.c
+++ b/shared-bindings/usb_midi/PortOut.c
@@ -89,6 +89,7 @@ STATIC const mp_rom_map_elem_t usb_midi_portout_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(usb_midi_portout_locals_dict, usb_midi_portout_locals_dict_table);
STATIC const mp_stream_p_t usb_midi_portout_stream_p = {
+ MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = NULL,
.write = usb_midi_portout_write,
.ioctl = usb_midi_portout_ioctl,
diff --git a/shared-module/audiocore/RawSample.c b/shared-module/audiocore/RawSample.c
index d6bf3a567..a69ddeb65 100644
--- a/shared-module/audiocore/RawSample.c
+++ b/shared-module/audiocore/RawSample.c
@@ -60,6 +60,12 @@ void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t* self,
uint32_t sample_rate) {
self->sample_rate = sample_rate;
}
+uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t* self) {
+ return self->bits_per_sample;
+}
+uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t* self) {
+ return self->channel_count;
+}
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t* self,
bool single_channel,
diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c
index f9762676f..1553dbe96 100644
--- a/shared-module/audiocore/__init__.c
+++ b/shared-module/audiocore/__init__.c
@@ -36,103 +36,37 @@
#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;
+ const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
+ return proto->sample_rate(MP_OBJ_TO_PTR(sample_obj));
}
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;
+ const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
+ return proto->bits_per_sample(MP_OBJ_TO_PTR(sample_obj));
}
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;
+ const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
+ return proto->channel_count(MP_OBJ_TO_PTR(sample_obj));
}
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
- 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
- }
+ const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
+ proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj));
}
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;
+ const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
+ return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, channel, buffer, buffer_length);
}
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
- }
+ const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
+ proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel, single_buffer,
+ samples_signed, max_buffer_length, spacing);
}
diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h
index 7aa0c1824..38c1f5aeb 100644
--- a/shared-module/audiocore/__init__.h
+++ b/shared-module/audiocore/__init__.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include "py/obj.h"
+#include "py/proto.h"
typedef enum {
GET_BUFFER_DONE, // No more data to read
@@ -38,6 +39,28 @@ typedef enum {
GET_BUFFER_ERROR, // Error while reading data.
} audioio_get_buffer_result_t;
+typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t);
+typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t);
+typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t);
+typedef void (*audiosample_reset_buffer_fun)(mp_obj_t);
+typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t,
+ bool single_channel, uint8_t channel, uint8_t** buffer,
+ uint32_t* buffer_length);
+typedef void (*audiosample_get_buffer_structure_fun)(mp_obj_t,
+ bool single_channel, bool* single_buffer,
+ bool* samples_signed, uint32_t *max_buffer_length,
+ uint8_t* spacing);
+
+typedef struct _audiosample_p_t {
+ MP_PROTOCOL_HEAD // MP_QSTR_protocol_audiosample
+ audiosample_sample_rate_fun sample_rate;
+ audiosample_bits_per_sample_fun bits_per_sample;
+ audiosample_channel_count_fun channel_count;
+ audiosample_reset_buffer_fun reset_buffer;
+ audiosample_get_buffer_fun get_buffer;
+ audiosample_get_buffer_structure_fun get_buffer_structure;
+} audiosample_p_t;
+
uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
uint8_t audiosample_channel_count(mp_obj_t sample_obj);
diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c
index a52489f85..afa3a0632 100644
--- a/shared-module/audiomixer/Mixer.c
+++ b/shared-module/audiomixer/Mixer.c
@@ -76,6 +76,14 @@ uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t* sel
return self->sample_rate;
}
+uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t* self) {
+ return self->channel_count;
+}
+
+uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t* self) {
+ return self->bits_per_sample;
+}
+
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]))) {
diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c
new file mode 100644
index 000000000..cabb46105
--- /dev/null
+++ b/shared-module/audiomp3/MP3File.c
@@ -0,0 +1,270 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ * 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 "shared-bindings/audiomp3/MP3File.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include "py/mperrno.h"
+#include "py/runtime.h"
+
+#include "shared-module/audiomp3/MP3File.h"
+#include "supervisor/shared/translate.h"
+#include "lib/mp3/src/mp3common.h"
+
+/** Fill the input buffer if it is less than half full.
+ *
+ * Returns true if the input buffer contains any useful data,
+ * false otherwise. (The input buffer will be padded to the end with
+ * 0 bytes, which do not interfere with MP3 decoding)
+ *
+ * Raises OSError if f_read fails.
+ *
+ * Sets self->eof if any read of the file returns 0 bytes
+ */
+STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) {
+ // If buffer is over half full, do nothing
+ if (self->inbuf_offset < self->inbuf_length/2) return true;
+
+ // If we didn't previously reach the end of file, we can try reading now
+ if (!self->eof) {
+
+ // Move the unconsumed portion of the buffer to the start
+ uint8_t *end_of_buffer = self->inbuf + self->inbuf_length;
+ uint8_t *new_end_of_data = self->inbuf + self->inbuf_length - self->inbuf_offset;
+ memmove(self->inbuf, self->inbuf + self->inbuf_offset,
+ self->inbuf_length - self->inbuf_offset);
+ self->inbuf_offset = 0;
+
+ UINT to_read = end_of_buffer - new_end_of_data;
+ UINT bytes_read = 0;
+ memset(new_end_of_data, 0, to_read);
+ if (f_read(&self->file->fp, new_end_of_data, to_read, &bytes_read) != FR_OK) {
+ self->eof = true;
+ mp_raise_OSError(MP_EIO);
+ }
+
+ if (bytes_read == 0) {
+ self->eof = true;
+ }
+
+ if (to_read != bytes_read) {
+ new_end_of_data += bytes_read;
+ memset(new_end_of_data, 0, end_of_buffer - new_end_of_data);
+ }
+
+ }
+
+ // Return true iff there are at least some useful bytes in the buffer
+ return self->inbuf_offset < self->inbuf_length;
+}
+
+#define READ_PTR(self) (self->inbuf + self->inbuf_offset)
+#define BYTES_LEFT(self) (self->inbuf_length - self->inbuf_offset)
+#define CONSUME(self, n) (self->inbuf_offset += n)
+
+/* If a sync word can be found, advance to it and return true. Otherwise,
+ * return false.
+ */
+STATIC bool mp3file_find_sync_word(audiomp3_mp3file_obj_t* self) {
+ do {
+ mp3file_update_inbuf(self);
+ int offset = MP3FindSyncWord(READ_PTR(self), BYTES_LEFT(self));
+ if (offset >= 0) {
+ CONSUME(self, offset);
+ mp3file_update_inbuf(self);
+ return true;
+ }
+ CONSUME(self, MAX(0, BYTES_LEFT(self) - 16));
+ } while (!self->eof);
+ return false;
+}
+
+STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameInfo* fi) {
+ int err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self));
+ return err == ERR_MP3_NONE;
+}
+
+void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
+ pyb_file_obj_t* file,
+ uint8_t *buffer,
+ size_t buffer_size) {
+ // XXX Adafruit_MP3 uses a 2kB input buffer and two 4kB output buffers.
+ // for a whopping total of 10kB buffers (+mp3 decoder state and frame buffer)
+ // At 44kHz, that's 23ms of output audio data.
+ //
+ // We will choose a slightly different allocation strategy for the output:
+ // Make sure the buffers are sized exactly to match (a multiple of) the
+ // frame size; this is typically 2304 * 2 bytes, so a little bit bigger
+ // than the two 4kB output buffers, except that the alignment allows to
+ // never allocate that extra frame buffer.
+
+ self->file = file;
+ self->inbuf_length = 2048;
+ self->inbuf_offset = self->inbuf_length;
+ self->inbuf = m_malloc(self->inbuf_length, false);
+ if (self->inbuf == NULL) {
+ common_hal_audiomp3_mp3file_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate input buffer"));
+ }
+ self->decoder = MP3InitDecoder();
+ if (self->decoder == NULL) {
+ common_hal_audiomp3_mp3file_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate decoder"));
+ }
+
+ mp3file_find_sync_word(self);
+ MP3FrameInfo fi;
+ if(!mp3file_get_next_frame_info(self, &fi)) {
+ mp_raise_msg(&mp_type_RuntimeError,
+ translate("Failed to parse MP3 file"));
+ }
+
+ self->sample_rate = fi.samprate;
+ self->channel_count = fi.nChans;
+ self->frame_buffer_size = fi.outputSamps*sizeof(int16_t);
+
+ if (buffer_size >= 2 * self->frame_buffer_size) {
+ self->len = buffer_size / 2 / self->frame_buffer_size * self->frame_buffer_size;
+ self->buffers[0] = buffer;
+ self->buffers[1] = buffer + self->len;
+ } else {
+ self->len = 2 * self->frame_buffer_size;
+ self->buffers[0] = m_malloc(self->len, false);
+ if (self->buffers[0] == NULL) {
+ common_hal_audiomp3_mp3file_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate first buffer"));
+ }
+
+ self->buffers[1] = m_malloc(self->len, false);
+ if (self->buffers[1] == NULL) {
+ common_hal_audiomp3_mp3file_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError,
+ translate("Couldn't allocate second buffer"));
+ }
+ }
+}
+
+void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t* self) {
+ MP3FreeDecoder(self->decoder);
+ self->decoder = NULL;
+ self->inbuf = NULL;
+ self->buffers[0] = NULL;
+ self->buffers[1] = NULL;
+ self->file = NULL;
+}
+
+bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t* self) {
+ return self->buffers[0] == NULL;
+}
+
+uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t* self) {
+ return self->sample_rate;
+}
+
+void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t* self,
+ uint32_t sample_rate) {
+ self->sample_rate = sample_rate;
+}
+
+uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t* self) {
+ return 16;
+}
+
+uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t* self) {
+ return self->channel_count;
+}
+
+bool audiomp3_mp3file_samples_signed(audiomp3_mp3file_obj_t* self) {
+ return true;
+}
+
+void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self,
+ bool single_channel,
+ uint8_t channel) {
+ if (single_channel && channel == 1) {
+ return;
+ }
+ // We don't reset the buffer index in case we're looping and we have an odd number of buffer
+ // loads
+ f_lseek(&self->file->fp, 0);
+ self->inbuf_offset = self->inbuf_length;
+ self->eof = 0;
+ mp3file_update_inbuf(self);
+ mp3file_find_sync_word(self);
+}
+
+audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** bufptr,
+ uint32_t* buffer_length) {
+ if (!single_channel) {
+ channel = 0;
+ }
+
+ uint16_t channel_read_count = self->channel_read_count[channel]++;
+ bool need_more_data = self->read_count++ == channel_read_count;
+
+ *bufptr = self->buffers[self->buffer_index] + channel;
+ *buffer_length = self->frame_buffer_size;
+
+ if (need_more_data) {
+ self->buffer_index = !self->buffer_index;
+ int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index];
+
+ if (!mp3file_find_sync_word(self)) {
+ return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR;
+ }
+ int bytes_left = BYTES_LEFT(self);
+ uint8_t *inbuf = READ_PTR(self);
+ int err = MP3Decode(self->decoder, &inbuf, &bytes_left, buffer, 0);
+ CONSUME(self, BYTES_LEFT(self) - bytes_left);
+ if (err) {
+ return GET_BUFFER_DONE;
+ }
+ }
+
+ return GET_BUFFER_MORE_DATA;
+}
+
+void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing) {
+ *single_buffer = false;
+ *samples_signed = true;
+ *max_buffer_length = self->frame_buffer_size;
+ if (single_channel) {
+ *spacing = self->channel_count;
+ } else {
+ *spacing = 1;
+ }
+}
diff --git a/shared-module/audiomp3/MP3File.h b/shared-module/audiomp3/MP3File.h
new file mode 100644
index 000000000..12649ac1a
--- /dev/null
+++ b/shared-module/audiomp3/MP3File.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft
+ * 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_SHARED_MODULE_AUDIOIO_MP3FILE_H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H
+
+#include "extmod/vfs_fat.h"
+#include "py/obj.h"
+
+#include "shared-module/audiocore/__init__.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ struct _MP3DecInfo *decoder;
+ uint8_t* inbuf;
+ uint32_t inbuf_length;
+ uint32_t inbuf_offset;
+ uint8_t* buffers[2];
+ uint32_t len;
+ uint32_t frame_buffer_size;
+
+ uint32_t sample_rate;
+ pyb_file_obj_t* file;
+
+ uint8_t buffer_index;
+ uint8_t channel_count;
+ bool eof;
+
+ uint16_t read_count;
+ uint16_t channel_read_count[2];
+} audiomp3_mp3file_obj_t;
+
+// These are not available from Python because it may be called in an interrupt.
+void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self,
+ bool single_channel,
+ uint8_t channel);
+audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* self,
+ bool single_channel,
+ uint8_t channel,
+ uint8_t** buffer,
+ uint32_t* buffer_length); // length in bytes
+void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool single_channel,
+ bool* single_buffer, bool* samples_signed,
+ uint32_t* max_buffer_length, uint8_t* spacing);
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H
diff --git a/shared-module/audiomp3/__init__.c b/shared-module/audiomp3/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/shared-module/audiomp3/__init__.c
diff --git a/shared-module/audiomp3/__init__.h b/shared-module/audiomp3/__init__.h
new file mode 100644
index 000000000..e7b1f3aab
--- /dev/null
+++ b/shared-module/audiomp3/__init__.h
@@ -0,0 +1,30 @@
+/*
+ * 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_SHARED_MODULE_AUDIOMP3__INIT__H
+#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOMP3__INIT__H
+
+#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOMP3__INIT__H
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index 862d2cf59..11db0f8ff 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -35,6 +35,7 @@
#include "shared-module/displayio/__init__.h"
#include "shared-module/displayio/display_core.h"
#include "supervisor/shared/display.h"
+#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include <stdint.h>
@@ -313,7 +314,7 @@ uint16_t common_hal_displayio_display_get_rotation(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) {
if (!self->auto_refresh && !self->first_manual_refresh) {
- uint64_t current_time = ticks_ms;
+ uint64_t current_time = supervisor_ticks_ms64();
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) {
@@ -327,7 +328,7 @@ bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_
}
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) {
+ while (supervisor_ticks_ms64() - self->last_refresh_call < remaining_time) {
RUN_BACKGROUND_TASKS;
}
}
@@ -350,20 +351,20 @@ STATIC void _update_backlight(displayio_display_obj_t* self) {
if (!self->auto_brightness || self->updating_backlight) {
return;
}
- if (ticks_ms - self->last_backlight_refresh < 100) {
+ if (supervisor_ticks_ms64() - self->last_backlight_refresh < 100) {
return;
}
// TODO(tannewt): Fade the backlight based on it's existing value and a target value. The target
// should account for ambient light when possible.
common_hal_displayio_display_set_brightness(self, 1.0);
- self->last_backlight_refresh = ticks_ms;
+ self->last_backlight_refresh = supervisor_ticks_ms64();
}
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) {
+ if (self->auto_refresh && (supervisor_ticks_ms64() - self->core.last_refresh) > self->native_ms_per_frame) {
_refresh_display(self);
}
}
diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c
index 252b39eb7..91d4bb7f9 100644
--- a/shared-module/displayio/EPaperDisplay.c
+++ b/shared-module/displayio/EPaperDisplay.c
@@ -36,6 +36,7 @@
#include "shared-bindings/time/__init__.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/display.h"
+#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include <stdint.h>
@@ -176,7 +177,7 @@ uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaper
return 0;
}
// Refresh at seconds per frame rate.
- uint32_t elapsed_time = ticks_ms - self->core.last_refresh;
+ uint32_t elapsed_time = supervisor_ticks_ms64() - self->core.last_refresh;
if (elapsed_time > self->milliseconds_per_frame) {
return 0;
}
@@ -340,7 +341,7 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) {
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;
+ refresh_done = supervisor_ticks_ms64() - self->core.last_refresh > self->refresh_time;
}
if (refresh_done) {
self->refreshing = false;
diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c
index 92d4507dd..256c29642 100644
--- a/shared-module/displayio/FourWire.c
+++ b/shared-module/displayio/FourWire.c
@@ -49,8 +49,8 @@ void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self,
gc_never_free(self->bus);
self->frequency = baudrate;
- self->polarity = common_hal_busio_spi_get_polarity(spi);
- self->phase = common_hal_busio_spi_get_phase(spi);
+ self->polarity = 0;
+ self->phase = 0;
common_hal_digitalio_digitalinout_construct(&self->command, command);
common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL);
diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c
index a73ea81d1..658daa8d6 100644
--- a/shared-module/displayio/display_core.c
+++ b/shared-module/displayio/display_core.c
@@ -35,6 +35,7 @@
#include "shared-bindings/time/__init__.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/display.h"
+#include "supervisor/shared/tick.h"
#include <stdint.h>
#include <string.h>
@@ -281,7 +282,7 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self,
}
void displayio_display_core_start_refresh(displayio_display_core_t* self) {
- self->last_refresh = ticks_ms;
+ self->last_refresh = supervisor_ticks_ms64();
}
void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
@@ -289,7 +290,7 @@ void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
displayio_group_finish_refresh(self->current_group);
}
self->full_refresh = false;
- self->last_refresh = ticks_ms;
+ self->last_refresh = supervisor_ticks_ms64();
}
void release_display_core(displayio_display_core_t* self) {
diff --git a/shared-module/network/__init__.c b/shared-module/network/__init__.c
index 96648b260..925e9a2a3 100644
--- a/shared-module/network/__init__.c
+++ b/shared-module/network/__init__.c
@@ -31,6 +31,8 @@
#include "py/mphal.h"
#include "py/mperrno.h"
+#include "supervisor/shared/tick.h"
+
#include "shared-bindings/random/__init__.h"
#include "shared-module/network/__init__.h"
@@ -53,7 +55,7 @@ void network_module_deinit(void) {
void network_module_background(void) {
static uint32_t next_tick = 0;
- uint32_t this_tick = ticks_ms;
+ uint32_t this_tick = supervisor_ticks_ms32();
if (this_tick < next_tick) return;
next_tick = this_tick + 1000;
diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c
index bed7d163f..8744f2ed3 100644
--- a/shared-module/usb_hid/Device.c
+++ b/shared-module/usb_hid/Device.c
@@ -30,6 +30,7 @@
#include "shared-bindings/usb_hid/Device.h"
#include "shared-module/usb_hid/Device.h"
#include "supervisor/shared/translate.h"
+#include "supervisor/shared/tick.h"
#include "tusb.h"
uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) {
@@ -46,8 +47,8 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t*
}
// Wait until interface is ready, timeout = 2 seconds
- uint64_t end_ticks = ticks_ms + 2000;
- while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) {
+ uint64_t end_ticks = supervisor_ticks_ms64() + 2000;
+ while ( (supervisor_ticks_ms64() < end_ticks) && !tud_hid_ready() ) {
RUN_BACKGROUND_TASKS;
}
diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c
index 02258de74..18caa2eb4 100644
--- a/supervisor/shared/bluetooth.c
+++ b/supervisor/shared/bluetooth.c
@@ -51,8 +51,12 @@ bleio_characteristic_obj_t supervisor_ble_length_characteristic;
bleio_uuid_obj_t supervisor_ble_length_uuid;
bleio_characteristic_obj_t supervisor_ble_contents_characteristic;
bleio_uuid_obj_t supervisor_ble_contents_uuid;
+
+// This is the base UUID for CircuitPython services and characteristics.
const uint8_t circuitpython_base_uuid[16] = {0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x00, 0xaf, 0xad };
-uint8_t circuitpython_advertising_data[] = { 0x02, 0x01, 0x06, 0x02, 0x0a, 0x00, 0x11, 0x07, 0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x01, 0xaf, 0xad, 0x06, 0x08, 0x43, 0x49, 0x52, 0x43, 0x55 };
+// This standard advertisement advertises the CircuitPython editing service and a CIRCUITPY short name.
+uint8_t circuitpython_advertising_data[] = { 0x02, 0x01, 0x06, 0x02, 0x0a, 0x00, 0x11, 0x07, 0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x01, 0xaf, 0xad, 0x06, 0x08, 0x43, 0x49, 0x52, 0x43, 0x55 };
+// This scan response advertises the full CIRCUITPYXXXX device name.
uint8_t circuitpython_scan_response_data[15] = {0x0e, 0x09, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00};
mp_obj_list_t service_list;
mp_obj_t service_list_items[1];
@@ -86,7 +90,7 @@ void supervisor_start_bluetooth(void) {
characteristic_list.len = 0;
characteristic_list.items = characteristic_list_items;
mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items));
-
+
_common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list);
// File length
@@ -225,7 +229,7 @@ void supervisor_bluetooth_background(void) {
uint16_t current_length = ((uint16_t*) current_command)[0];
if (current_length > 0 && current_length == current_offset) {
uint16_t command = ((uint16_t *) current_command)[1];
-
+
if (command == 1) {
uint16_t max_len = 20; //supervisor_ble_contents_characteristic.max_length;
uint8_t buf[max_len];
@@ -274,7 +278,7 @@ void supervisor_bluetooth_background(void) {
f_write(&active_file, &data, 1, &actual);
}
}
-
+
f_lseek(&active_file, offset);
uint8_t* data = (uint8_t *) (current_command + 4);
UINT written;
diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c
index 940cbf1f2..f751a7ffd 100644
--- a/supervisor/shared/rgb_led_status.c
+++ b/supervisor/shared/rgb_led_status.c
@@ -27,6 +27,7 @@
#include "mphalport.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "rgb_led_status.h"
+#include "supervisor/shared/tick.h"
#ifdef MICROPY_HW_NEOPIXEL
uint8_t rgb_status_brightness = 63;
@@ -360,7 +361,7 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
rgb_status_animation_t* status) {
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED))
new_status_color(ALL_DONE);
- status->pattern_start = ticks_ms;
+ status->pattern_start = supervisor_ticks_ms32();
status->safe_mode = safe_mode;
status->found_main = found_main;
status->total_exception_cycle = 0;
@@ -405,11 +406,11 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
void tick_rgb_status_animation(rgb_status_animation_t* status) {
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED))
- uint32_t tick_diff = ticks_ms - status->pattern_start;
+ uint32_t tick_diff = supervisor_ticks_ms32() - status->pattern_start;
if (status->ok) {
// All is good. Ramp ALL_DONE up and down.
if (tick_diff > ALL_GOOD_CYCLE_MS) {
- status->pattern_start = ticks_ms;
+ status->pattern_start = supervisor_ticks_ms32();
tick_diff = 0;
}
@@ -424,7 +425,7 @@ void tick_rgb_status_animation(rgb_status_animation_t* status) {
}
} else {
if (tick_diff > status->total_exception_cycle) {
- status->pattern_start = ticks_ms;
+ status->pattern_start = supervisor_ticks_ms32();
tick_diff = 0;
}
// First flash the file color.
diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c
index d8d3ab379..363181da0 100644
--- a/supervisor/shared/safe_mode.c
+++ b/supervisor/shared/safe_mode.c
@@ -34,6 +34,7 @@
#include "supervisor/shared/rgb_led_colors.h"
#include "supervisor/shared/rgb_led_status.h"
#include "supervisor/shared/translate.h"
+#include "supervisor/shared/tick.h"
#define SAFE_MODE_DATA_GUARD 0xad0000af
#define SAFE_MODE_DATA_GUARD_MASK 0xff0000ff
@@ -59,14 +60,14 @@ safe_mode_t wait_for_safe_mode_reset(void) {
common_hal_digitalio_digitalinout_construct(&status_led, MICROPY_HW_LED_STATUS);
common_hal_digitalio_digitalinout_switch_to_output(&status_led, true, DRIVE_MODE_PUSH_PULL);
#endif
- uint64_t start_ticks = ticks_ms;
+ uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t diff = 0;
while (diff < 700) {
#ifdef MICROPY_HW_LED_STATUS
// Blink on for 100, off for 100, on for 100, off for 100 and on for 200
common_hal_digitalio_digitalinout_set_value(&status_led, diff > 100 && diff / 100 != 2 && diff / 100 != 4);
#endif
- diff = ticks_ms - start_ticks;
+ diff = supervisor_ticks_ms64() - start_ticks;
}
#ifdef MICROPY_HW_LED_STATUS
common_hal_digitalio_digitalinout_deinit(&status_led);
diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c
new file mode 100644
index 000000000..69256081c
--- /dev/null
+++ b/supervisor/shared/tick.c
@@ -0,0 +1,94 @@
+/*
+ * 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 "supervisor/shared/tick.h"
+#include "supervisor/filesystem.h"
+#include "supervisor/shared/autoreload.h"
+
+static volatile uint64_t ticks_ms;
+static volatile uint32_t background_ticks_ms32;
+
+#if CIRCUITPY_GAMEPAD
+#include "shared-module/gamepad/__init__.h"
+#endif
+
+#if CIRCUITPY_GAMEPADSHIFT
+#include "shared-module/gamepadshift/__init__.h"
+#endif
+
+#include "shared-bindings/microcontroller/__init__.h"
+
+void supervisor_tick(void) {
+
+ ticks_ms ++;
+
+#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)) {
+ #if CIRCUITPY_GAMEPAD
+ gamepad_tick();
+ #endif
+ #if CIRCUITPY_GAMEPADSHIFT
+ gamepadshift_tick();
+ #endif
+ }
+#endif
+}
+
+uint64_t supervisor_ticks_ms64() {
+ uint64_t result;
+ common_hal_mcu_disable_interrupts();
+ result = ticks_ms;
+ common_hal_mcu_enable_interrupts();
+ return result;
+}
+
+uint32_t supervisor_ticks_ms32() {
+ return ticks_ms;
+}
+
+extern void run_background_tasks(void);
+
+void supervisor_run_background_tasks_if_tick() {
+ uint32_t now32 = ticks_ms;
+
+ if (now32 == background_ticks_ms32) {
+ return;
+ }
+ background_ticks_ms32 = now32;
+
+ run_background_tasks();
+}
+
+void supervisor_fake_tick() {
+ uint32_t now32 = ticks_ms;
+ background_ticks_ms32 = (now32 - 1);
+}
diff --git a/supervisor/shared/tick.h b/supervisor/shared/tick.h
new file mode 100644
index 000000000..7ce8281ba
--- /dev/null
+++ b/supervisor/shared/tick.h
@@ -0,0 +1,67 @@
+/*
+ * 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 __INCLUDED_SUPERVISOR_TICK_H
+#define __INCLUDED_SUPERVISOR_TICK_H
+
+#include <stdint.h>
+
+/** @brief To be called once every ms
+ *
+ * The port must call supervisor_tick once per millisecond to perform regular tasks.
+ * This is called from the SysTick interrupt or similar, and is safe to call in an
+ * interrupt context.
+ */
+extern void supervisor_tick(void);
+/** @brief Cause background tasks to be called soon
+ *
+ * Normally, background tasks are only run once per tick. For other cases where
+ * an event noticed from an interrupt context needs to be completed by a background
+ * task activity, the interrupt can call supervisor_fake_tick.
+ */
+extern void supervisor_fake_tick(void);
+/** @brief Get the lower 32 bits of the time in milliseconds
+ *
+ * This can be more efficient than supervisor_ticks_ms64, for sites where a wraparound
+ * of ~49.5 days is not harmful.
+ */
+extern uint32_t supervisor_ticks_ms32(void);
+/** @brief Get the full time in milliseconds
+ *
+ * Because common ARM mcus cannot atomically work with 64-bit quantities, this
+ * function must briefly disable interrupts in order to return the value. If
+ * only relative durations of less than about ~49.5 days need to be considered,
+ * then it may be possible to use supervisor_ticks_ms64 instead.
+ */
+extern uint64_t supervisor_ticks_ms64(void);
+/** @brief Run background ticks, but only about every millisecond.
+ *
+ * Normally, this is not called directly. Instead use the RUN_BACKGROUND_TASKS
+ * macro.
+ */
+extern void supervisor_run_background_if_tick(void);
+
+#endif
diff --git a/supervisor/shared/translate.c b/supervisor/shared/translate.c
index aa5e4517c..187d5ff8a 100644
--- a/supervisor/shared/translate.c
+++ b/supervisor/shared/translate.c
@@ -42,12 +42,28 @@ void serial_write_compressed(const compressed_string_t* compressed) {
serial_write(decompressed);
}
+STATIC int put_utf8(char *buf, int u) {
+ if(u <= 0x7f) {
+ *buf = u;
+ return 1;
+ } else if(u <= 0x07ff) {
+ *buf++ = 0b11000000 | (u >> 6);
+ *buf = 0b10000000 | (u & 0b00111111);
+ return 2;
+ } else { // u <= 0xffff)
+ *buf++ = 0b11000000 | (u >> 12);
+ *buf = 0b10000000 | ((u >> 6) & 0b00111111);
+ *buf = 0b10000000 | (u & 0b00111111);
+ return 3;
+ }
+}
+
char* decompress(const compressed_string_t* compressed, char* decompressed) {
uint8_t this_byte = 0;
uint8_t this_bit = 7;
uint8_t b = compressed->data[this_byte];
// Stop one early because the last byte is always NULL.
- for (uint16_t i = 0; i < compressed->length - 1; i++) {
+ for (uint16_t i = 0; i < compressed->length - 1;) {
uint32_t bits = 0;
uint8_t bit_length = 0;
uint32_t max_code = lengths[0];
@@ -72,7 +88,7 @@ char* decompress(const compressed_string_t* compressed, char* decompressed) {
max_code = (max_code << 1) + lengths[bit_length];
searched_length += lengths[bit_length];
}
- decompressed[i] = values[searched_length + bits - max_code];
+ i += put_utf8(decompressed + i, values[searched_length + bits - max_code]);
}
decompressed[compressed->length-1] = '\0';
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index b2e4eb1dc..5e997ee78 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -10,6 +10,7 @@ SRC_SUPERVISOR = \
supervisor/shared/safe_mode.c \
supervisor/shared/stack.c \
supervisor/shared/status_leds.c \
+ supervisor/shared/tick.c \
supervisor/shared/translate.c
ifndef $(NO_USB)