From 9907e3fa288eb9c31d0152e56c4d9ba998cf8122 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Sat, 3 Aug 2019 13:48:55 +0200 Subject: Allow to specify pre-allocated buffer in audicore.WaveFile It lets us re-use the same buffer for playing multiple files. This also allows us to control the size of the buffer. Half of the buffer will be used for the fist, and half for the second internal buffer. --- shared-bindings/audiocore/WaveFile.c | 22 ++++++++++++++++------ shared-bindings/audiocore/WaveFile.h | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'shared-bindings') diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 4c1993b7c..7398353b0 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -39,13 +39,15 @@ //| ======================================================== //| //| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must -//| be 8 bit unsigned or 16 bit signed. +//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating +//| an internal buffer. //| -//| .. class:: WaveFile(file) +//| .. class:: WaveFile(file[, buffer]) //| //| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`. //| //| :param typing.BinaryIO file: Already opened wave file +//| :param bytearray buffer: Optional pre-allocated buffer //| //| Playing a wave file from flash:: //| @@ -68,15 +70,23 @@ //| print("stopped") //| STATIC mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 1, 1, false); + mp_arg_check_num(n_args, kw_args, 1, 2, false); audioio_wavefile_obj_t *self = m_new_obj(audioio_wavefile_obj_t); self->base.type = &audioio_wavefile_type; - if (MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) { - common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0])); - } else { + if (!MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) { mp_raise_TypeError(translate("file must be a file opened in byte mode")); } + uint8_t *buffer = NULL; + size_t buffer_size = 0; + if (n_args >= 2) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + buffer = bufinfo.buf; + buffer_size = bufinfo.len; + } + common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]), + buffer, buffer_size); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiocore/WaveFile.h b/shared-bindings/audiocore/WaveFile.h index d2572318b..f4a172319 100644 --- a/shared-bindings/audiocore/WaveFile.h +++ b/shared-bindings/audiocore/WaveFile.h @@ -35,7 +35,7 @@ extern const mp_obj_type_t audioio_wavefile_type; void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self, - pyb_file_obj_t* file); + pyb_file_obj_t* file, uint8_t *buffer, size_t buffer_size); void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self); bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self); -- cgit v1.2.3 From 32a6d3640540e5fa5860f05c1a12b9182bc58de7 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 11 Aug 2019 08:40:09 -0500 Subject: shared-bindings: Use RUN_BACKGROUND_TASKS --- shared-bindings/_stage/__init__.c | 4 +--- shared-bindings/displayio/FourWire.c | 4 +--- shared-bindings/displayio/I2CDisplay.c | 4 +--- shared-bindings/displayio/ParallelBus.c | 4 +--- shared-bindings/i2cslave/I2CSlave.c | 6 +++--- 5 files changed, 7 insertions(+), 15 deletions(-) (limited to 'shared-bindings') diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c index 485fa80c5..6096f6b6d 100644 --- a/shared-bindings/_stage/__init__.c +++ b/shared-bindings/_stage/__init__.c @@ -96,9 +96,7 @@ STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) { } while (!displayio_display_begin_transaction(display)) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP ; -#endif + RUN_BACKGROUND_TASKS; } displayio_area_t area; area.x1 = x0; diff --git a/shared-bindings/displayio/FourWire.c b/shared-bindings/displayio/FourWire.c index af64a2028..0d41359ee 100644 --- a/shared-bindings/displayio/FourWire.c +++ b/shared-bindings/displayio/FourWire.c @@ -119,9 +119,7 @@ STATIC mp_obj_t displayio_fourwire_obj_send(mp_obj_t self, mp_obj_t command_obj, // Wait for display bus to be available. while (!common_hal_displayio_fourwire_begin_transaction(self)) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP ; -#endif + RUN_BACKGROUND_TASKS; } common_hal_displayio_fourwire_send(self, true, &command, 1); common_hal_displayio_fourwire_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len); diff --git a/shared-bindings/displayio/I2CDisplay.c b/shared-bindings/displayio/I2CDisplay.c index 1f74e8c9e..9ef989d71 100644 --- a/shared-bindings/displayio/I2CDisplay.c +++ b/shared-bindings/displayio/I2CDisplay.c @@ -111,9 +111,7 @@ STATIC mp_obj_t displayio_i2cdisplay_obj_send(mp_obj_t self, mp_obj_t command_ob // Wait for display bus to be available. while (!common_hal_displayio_i2cdisplay_begin_transaction(self)) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP ; -#endif + RUN_BACKGROUND_TASKS; } uint8_t full_command[bufinfo.len + 1]; full_command[0] = command; diff --git a/shared-bindings/displayio/ParallelBus.c b/shared-bindings/displayio/ParallelBus.c index 00a96d230..c29c79fff 100644 --- a/shared-bindings/displayio/ParallelBus.c +++ b/shared-bindings/displayio/ParallelBus.c @@ -122,9 +122,7 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o // Wait for display bus to be available. while (!common_hal_displayio_parallelbus_begin_transaction(self)) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP ; -#endif + RUN_BACKGROUND_TASKS; } common_hal_displayio_parallelbus_send(self, true, &command, 1); common_hal_displayio_parallelbus_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len); diff --git a/shared-bindings/i2cslave/I2CSlave.c b/shared-bindings/i2cslave/I2CSlave.c index 2598accbb..c98ea52e0 100644 --- a/shared-bindings/i2cslave/I2CSlave.c +++ b/shared-bindings/i2cslave/I2CSlave.c @@ -182,7 +182,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request(size_t n_args, const mp_obj_t *pos_ar bool is_read; bool is_restart; - MICROPY_VM_HOOK_LOOP + RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { return mp_const_none; } @@ -337,7 +337,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request_read(size_t n_args, const mp_obj_t *p uint8_t *buffer = NULL; uint64_t timeout_end = common_hal_time_monotonic() + 10 * 1000; while (common_hal_time_monotonic() < timeout_end) { - MICROPY_VM_HOOK_LOOP + RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { break; } @@ -382,7 +382,7 @@ STATIC mp_obj_t i2cslave_i2c_slave_request_write(mp_obj_t self_in, mp_obj_t buf_ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); for (size_t i = 0; i < bufinfo.len; i++) { - MICROPY_VM_HOOK_LOOP + RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { break; } -- cgit v1.2.3 From 58b4cd49562dab4df42511cf86537bcf8209f2d9 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Sat, 17 Aug 2019 11:31:45 +0200 Subject: Improve docs for WaveFile buffer --- shared-bindings/audiocore/WaveFile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-bindings') diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 7398353b0..01dc1e4c9 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -47,7 +47,8 @@ //| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`. //| //| :param typing.BinaryIO file: Already opened wave file -//| :param bytearray buffer: Optional pre-allocated buffer +//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally. +//| //| //| Playing a wave file from flash:: //| -- cgit v1.2.3 From 47d6dd843ee89bfd3f6613d02dd51905c0fc56e5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 17 Aug 2019 13:48:03 -0500 Subject: audioio: By default, be compatible with 4.x Testing performed: That the shipped .mpy files on a PyPortal (CP 4.x) still work (play audio) with this branch, instead of erroring because `WaveFile` can't be found in `audioio`. Flash usage grew by 28 bytes. (I expected 24, there must be some other effect on size/alignment that I didn't predict) --- py/circuitpy_mpconfig.mk | 6 ++++++ shared-bindings/audioio/__init__.c | 15 +++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'shared-bindings') diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index a408cd7ac..ac40223fe 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -74,6 +74,12 @@ CIRCUITPY_AUDIOIO = $(CIRCUITPY_FULL_BUILD) endif CFLAGS += -DCIRCUITPY_AUDIOIO=$(CIRCUITPY_AUDIOIO) +ifndef CIRCUITPY_AUDIOIO_COMPAT +CIRCUITPY_AUDIOIO_COMPAT = $(CIRCUITPY_AUDIOIO) +endif +CFLAGS += -DCIRCUITPY_AUDIOIO_COMPAT=$(CIRCUITPY_AUDIOIO_COMPAT) + + ifndef CIRCUITPY_AUDIOPWMIO CIRCUITPY_AUDIOPWMIO = 0 endif diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c index 3fecf2708..bd771dda2 100644 --- a/shared-bindings/audioio/__init__.c +++ b/shared-bindings/audioio/__init__.c @@ -33,6 +33,12 @@ #include "shared-bindings/audioio/__init__.h" #include "shared-bindings/audioio/AudioOut.h" +#ifdef CIRCUITPY_AUDIOIO_COMPAT +#include "shared-bindings/audiocore/Mixer.h" +#include "shared-bindings/audiocore/RawSample.h" +#include "shared-bindings/audiocore/WaveFile.h" +#endif + //| :mod:`audioio` --- Support for audio input and output //| ====================================================== //| @@ -57,10 +63,19 @@ //| Since CircuitPython 5, `Mixer`, `RawSample` and `WaveFile` are moved //| to :mod:`audiocore`. //| +//| For compatibility with CircuitPython 4.x, some builds allow the items in +//| `audiocore` to be imported from `audioio`. This will be removed for all +//| boards in a future build of CicuitPython. +//| STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioio) }, { MP_ROM_QSTR(MP_QSTR_AudioOut), MP_ROM_PTR(&audioio_audioout_type) }, +#ifdef CIRCUITPY_AUDIOIO_COMPAT + { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audioio_mixer_type) }, + { MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) }, + { MP_ROM_QSTR(MP_QSTR_WaveFile), MP_ROM_PTR(&audioio_wavefile_type) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(audioio_module_globals, audioio_module_globals_table); -- cgit v1.2.3 From 9d164965c9fe04f3485b6ee213507548cac403d0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 17 Aug 2019 20:49:05 -0500 Subject: localtime: don't hard-fault on argument type errors; handle localtime(float) It turns out `mp_obj_int_get_checked` is not appropriate to call when the argument is not of int or long type--the "checked" refers to guarding against overflow/underflow, not type checking. For compatibility with CPython, handle float arguments. Closes: #2069 --- shared-bindings/time/__init__.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'shared-bindings') diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index f34cb9c46..420bedf1c 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -236,7 +236,12 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { return rtc_get_time_source_time(); } - mp_int_t secs = mp_obj_int_get_checked(args[0]); + mp_obj_t arg = args[0]; + if(mp_obj_is_float(arg)) + arg = mp_obj_new_int_from_float(mp_obj_get_float(arg)); + + mp_int_t secs = mp_obj_get_int(arg); + if (secs < EPOCH1970_EPOCH2000_DIFF_SECS) mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t")); -- cgit v1.2.3 From f384d2dd8004e1becac6183243caef4b4bbedf56 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 18 Aug 2019 08:11:14 -0500 Subject: shared-bindings/time: style --- shared-bindings/time/__init__.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'shared-bindings') diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 420bedf1c..2654de09a 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -237,13 +237,15 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { } mp_obj_t arg = args[0]; - if(mp_obj_is_float(arg)) + if (mp_obj_is_float(arg)) { arg = mp_obj_new_int_from_float(mp_obj_get_float(arg)); + } mp_int_t secs = mp_obj_get_int(arg); - if (secs < EPOCH1970_EPOCH2000_DIFF_SECS) + if (secs < EPOCH1970_EPOCH2000_DIFF_SECS) { mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t")); + } timeutils_struct_time_t tm; timeutils_seconds_since_epoch_to_struct_time(secs, &tm); @@ -275,8 +277,9 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) { mp_raise_TypeError(translate("function takes exactly 9 arguments")); } - if (mp_obj_get_int(elem[0]) < 2000) + if (mp_obj_get_int(elem[0]) < 2000) { mp_raise_msg(&mp_type_OverflowError, translate("timestamp out of range for platform time_t")); + } mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])); -- cgit v1.2.3