From a62a1ae2bd16a4d8e4029b26bd23761da1b12d5f Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Sun, 21 Jul 2019 16:30:09 -0400 Subject: WIP: refactor _pixelbuf to use strings instead of classes --- shared-module/_pixelbuf/PixelBuf.c | 6 +++--- shared-module/_pixelbuf/PixelBuf.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'shared-module') diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index d32697239..6b222eec8 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -31,7 +31,7 @@ #include "PixelBuf.h" #include -void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder) { +void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder) { buf[byteorder->byteorder.r] = value >> 16 & 0xff; buf[byteorder->byteorder.g] = (value >> 8) & 0xff; buf[byteorder->byteorder.b] = value & 0xff; @@ -43,7 +43,7 @@ void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj } } -void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) { +void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar) { if (MP_OBJ_IS_INT(item)) { uint8_t *target = rawbuf ? rawbuf : buf; pixelbuf_set_pixel_int(target, mp_obj_get_int_truncated(item), byteorder); @@ -94,7 +94,7 @@ void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_ } } -mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar) { +mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, bool dotstar) { mp_obj_t elems[len]; for (uint i = 0; i < len; i++) { elems[i] = pixelbuf_get_pixel(buf + (i * step), byteorder, dotstar); diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h index 9e115fe0c..6b3272e19 100644 --- a/shared-module/_pixelbuf/PixelBuf.h +++ b/shared-module/_pixelbuf/PixelBuf.h @@ -42,9 +42,9 @@ #define DOTSTAR_GET_BRIGHTNESS(value) ((value & 0b00011111) / 31.0) #define DOTSTAR_LED_START_FULL_BRIGHT 0xFF -void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar); -mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar); -mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar); -void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder); +void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar); +mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar); +mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, bool dotstar); +void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder); #endif -- cgit v1.2.3 From 31e4591691891abd92d8e3851cd13fb6dbc9bf64 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Sun, 21 Jul 2019 16:37:06 -0400 Subject: WIP: refactor _pixelbuf to use strings instead of classes --- shared-bindings/_pixelbuf/PixelBuf.c | 2 +- shared-bindings/_pixelbuf/__init__.c | 122 +---------------------------------- shared-module/_pixelbuf/PixelBuf.c | 2 +- 3 files changed, 3 insertions(+), 123 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index 2ea40d1de..01ba702c3 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -133,7 +133,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_a if (args[ARG_byteorder].u_obj == NULL) byteorder_str = "BGR"; else - byteorder_str = mp_obj_str_get_data(byteorder_str, bo_len); + byteorder_str = mp_obj_str_get_data(args[ARG_byteorder].u_obj, &bo_len); parse_byteorder_string(byteorder_str, byteorder_details); diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index 229c04603..02d5f49b3 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -82,126 +82,6 @@ const int32_t colorwheel(float pos) { } } - -/// RGB -//| .. data:: RGB -//| -//| * **order** Red, Green, Blue -//| * **bpp** 3 -PIXELBUF_BYTEORDER(RGB, 3, 0, 1, 2, 3, false, false) -//| .. data:: RBG -//| -//| * **order** Red, Blue, Green -//| * **bpp** 3 -PIXELBUF_BYTEORDER(RBG, 3, 0, 2, 1, 3, false, false) -//| .. data:: GRB -//| -//| * **order** Green, Red, Blue -//| * **bpp** 3 -//| -//| Commonly used by NeoPixel. -PIXELBUF_BYTEORDER(GRB, 3, 1, 0, 2, 3, false, false) -//| .. data:: GBR -//| -//| * **order** Green, Blue, Red -//| * **bpp** 3 -PIXELBUF_BYTEORDER(GBR, 3, 1, 2, 0, 3, false, false) -//| .. data:: BRG -//| -//| * **order** Blue, Red, Green -//| * **bpp** 3 -PIXELBUF_BYTEORDER(BRG, 3, 2, 0, 1, 3, false, false) -//| .. data:: BGR -//| -//| * **order** Blue, Green, Red -//| * **bpp** 3 -//| -//| Commonly used by Dotstar. -PIXELBUF_BYTEORDER(BGR, 3, 2, 1, 0, 3, false, false) - -// RGBW -//| .. data:: RGBW -//| -//| * **order** Red, Green, Blue, White -//| * **bpp** 4 -//| * **has_white** True -PIXELBUF_BYTEORDER(RGBW, 4, 0, 1, 2, 3, true, false) -//| .. data:: RBGW -//| -//| * **order** Red, Blue, Green, White -//| * **bpp** 4 -//| * **has_white** True -PIXELBUF_BYTEORDER(RBGW, 4, 0, 2, 1, 3, true, false) -//| .. data:: GRBW -//| -//| * **order** Green, Red, Blue, White -//| * **bpp** 4 -//| * **has_white** True -//| -//| Commonly used by RGBW NeoPixels. -PIXELBUF_BYTEORDER(GRBW, 4, 1, 0, 2, 3, true, false) -//| .. data:: GBRW -//| -//| * **order** Green, Blue, Red, White -//| * **bpp** 4 -//| * **has_white** True -PIXELBUF_BYTEORDER(GBRW, 4, 1, 2, 0, 3, true, false) -//| .. data:: BRGW -//| -//| * **order** Blue, Red, Green, White -//| * **bpp** 4 -//| * **has_white** True -PIXELBUF_BYTEORDER(BRGW, 4, 2, 0, 1, 3, true, false) -//| .. data:: BGRW -//| -//| * **order** Blue, Green, Red, White -//| * **bpp** 4 -//| * **has_white** True -PIXELBUF_BYTEORDER(BGRW, 4, 2, 1, 0, 3, true, false) - -// Luminosity + RGB (eg for Dotstar) -// Luminosity chosen because the luminosity of a Dotstar at full bright -// burns the eyes like looking at the Sun. -// https://www.thesaurus.com/browse/luminosity?s=t -//| .. data:: LRGB -//| -//| * **order** *Luminosity*, Red, Green, Blue -//| * **bpp** 4 -//| * **has_luminosity** True -PIXELBUF_BYTEORDER(LRGB, 4, 1, 2, 3, 0, false, true) -//| .. data:: LRBG -//| -//| * **order** *Luminosity*, Red, Blue, Green -//| * **bpp** 4 -//| * **has_luminosity** True -PIXELBUF_BYTEORDER(LRBG, 4, 1, 3, 2, 0, false, true) -//| .. data:: LGRB -//| -//| * **order** *Luminosity*, Green, Red, Blue -//| * **bpp** 4 -//| * **has_luminosity** True -PIXELBUF_BYTEORDER(LGRB, 4, 2, 1, 3, 0, false, true) -//| .. data:: LGBR -//| -//| * **order** *Luminosity*, Green, Blue, Red -//| * **bpp** 4 -//| * **has_luminosity** True -PIXELBUF_BYTEORDER(LGBR, 4, 2, 3, 1, 0, false, true) -//| .. data:: LBRG -//| -//| * **order** *Luminosity*, Blue, Red, Green -//| * **bpp** 4 -//| * **has_luminosity** True -PIXELBUF_BYTEORDER(LBRG, 4, 3, 1, 2, 0, false, true) -//| .. data:: LBGR -//| -//| * **order** *Luminosity*, Blue, Green, Red -//| * **bpp** 4 -//| * **has_luminosity** True -//| -//| Actual format commonly used by DotStar (5 bit luninance value) -PIXELBUF_BYTEORDER(LBGR, 4, 3, 2, 1, 0, false, true) - STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pixelbuf) }, { MP_ROM_QSTR(MP_QSTR_PixelBuf), MP_ROM_PTR(&pixelbuf_pixelbuf_type) }, @@ -223,7 +103,7 @@ STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GBRD), MP_ROM_QSTR(MP_QSTR_GBRD) }, { MP_ROM_QSTR(MP_QSTR_BRGD), MP_ROM_QSTR(MP_QSTR_BRGD) }, { MP_ROM_QSTR(MP_QSTR_BGRD), MP_ROM_QSTR(MP_QSTR_BGRD) }, - { MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_QSTR(&pixelbuf_wheel_obj) }, + { MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_PTR(&pixelbuf_wheel_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pixelbuf_module_globals, pixelbuf_module_globals_table); diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index 6b222eec8..b7cdef483 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -102,7 +102,7 @@ mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_de return mp_obj_new_tuple(len, elems); } -mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) { +mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar) { mp_obj_t elems[byteorder->bpp]; elems[0] = mp_obj_new_int(buf[byteorder->byteorder.r]); -- cgit v1.2.3 From 3cf9a475b99090d72b9992816808cbde309dcc40 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Sun, 4 Aug 2019 11:02:33 -0400 Subject: fix 'white' byte for dotstars --- shared-bindings/_pixelbuf/PixelBuf.c | 4 ++-- shared-module/_pixelbuf/PixelBuf.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index 90210d4f3..969d16709 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -119,8 +119,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_a byteorder_details.byteorder.r = r - byteorder; byteorder_details.byteorder.g = g - byteorder; byteorder_details.byteorder.b = b - byteorder; - if (w) - byteorder_details.byteorder.w = w - byteorder; + byteorder_details.byteorder.w = w ? w - byteorder : 0; // The dotstar brightness byte is always first (as it goes with the pixel start bits) // if 'D' is found at the end, adjust byte position // if 'D' is elsewhere, error out @@ -130,6 +129,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_a byteorder_details.byteorder.b += 1; byteorder_details.byteorder.g += 1; byteorder_details.byteorder.r += 1; + byteorder_details.byteorder.w = 0; } else if (dotstar_pos != 0) { mp_raise_ValueError(translate("Invalid byteorder string")); } diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index b7cdef483..e26f05ac3 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -47,11 +47,11 @@ void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_ if (MP_OBJ_IS_INT(item)) { uint8_t *target = rawbuf ? rawbuf : buf; pixelbuf_set_pixel_int(target, mp_obj_get_int_truncated(item), byteorder); - if (dotstar) { + if (dotstar) { buf[0] = DOTSTAR_LED_START_FULL_BRIGHT; if (rawbuf) rawbuf[0] = DOTSTAR_LED_START_FULL_BRIGHT; - } + } if (rawbuf) { buf[byteorder->byteorder.r] = rawbuf[byteorder->byteorder.r] * brightness; buf[byteorder->byteorder.g] = rawbuf[byteorder->byteorder.g] * brightness; -- cgit v1.2.3 From 2970680e6af663200b35227bfbca5240542a4c47 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Sun, 20 Oct 2019 19:54:25 -0400 Subject: fix show and fix step > 1 --- py/obj.c | 9 +++++++-- py/objtype.c | 3 ++- shared-bindings/_pixelbuf/PixelBuf.c | 31 +++++++++++++++++++------------ shared-bindings/_pixelbuf/PixelBuf.h | 2 +- shared-module/_pixelbuf/PixelBuf.c | 7 +++++-- shared-module/_pixelbuf/PixelBuf.h | 2 +- 6 files changed, 35 insertions(+), 19 deletions(-) (limited to 'shared-module') diff --git a/py/obj.c b/py/obj.c index bd2aaf9d2..f91b00a64 100644 --- a/py/obj.c +++ b/py/obj.c @@ -489,14 +489,19 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(base); + mp_obj_t instance = base; + // If we got an MP_OBJ_SENTINEL as the type, then we got called by instance_subscr + if (type == MP_OBJ_SENTINEL) { + instance = ((mp_obj_t *)base)[1]; + type = mp_obj_get_type(((mp_obj_t *)base)[2]); + } if (type->subscr != NULL) { - mp_obj_t ret = type->subscr(base, index, value); + mp_obj_t ret = type->subscr(instance, index, value); // May have called port specific C code. Make sure it didn't mess up the heap. assert_heap_ok(); if (ret != MP_OBJ_NULL) { return ret; } - // TODO: call base classes here? } if (value == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { diff --git a/py/objtype.c b/py/objtype.c index 5133d849f..7d41b8656 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -850,7 +850,8 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value meth_args = 3; } if (member[0] == MP_OBJ_SENTINEL) { - return mp_obj_subscr(self->subobj[0], index, value); + mp_obj_t args[3] = {MP_OBJ_SENTINEL, self_in, self->subobj[0]}; + return mp_obj_subscr(args, index, value); } else if (member[0] != MP_OBJ_NULL) { mp_obj_t args[3] = {self_in, index, value}; // TODO probably need to call mp_convert_member_lookup, and use mp_call_method_n_kw diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index 3a2c88ef6..aeed6f504 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -230,7 +230,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_obj_set_brightness(mp_obj_t self_in, mp_obj_t if (self->two_buffers) pixelbuf_recalculate_brightness(self); if (self->auto_write) - call_show(self_in); + call_show(self_in, 'b'); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_set_brightness_obj, pixelbuf_pixelbuf_obj_set_brightness); @@ -253,7 +253,7 @@ void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self) { } } -mp_obj_t call_show(mp_obj_t self_in) { +mp_obj_t call_show(mp_obj_t self_in, char origin) { mp_obj_t dest[2]; mp_load_method(self_in, MP_QSTR_show, dest); return mp_call_method_n_kw(0, 0, dest); @@ -356,29 +356,35 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp } pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); + if (0) { #if MICROPY_PY_BUILTINS_SLICE } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(self->bytes, index_in, &slice)) - // TODO support stepping!!! - mp_raise_NotImplementedError(translate("Only slices with step=1 (aka None) are supported")); + mp_seq_get_fast_slice_indexes(self->bytes, index_in, &slice); + if ((slice.stop * self->pixel_step) > self->bytes) mp_raise_IndexError(translate("Range out of bounds")); + if (slice.step < 0) + mp_raise_IndexError(translate("Negative step not supported")); if (value == MP_OBJ_SENTINEL) { // Get size_t len = slice.stop - slice.start; uint8_t *readbuf = self->two_buffers ? self->rawbuf : self->buf; - return pixelbuf_get_pixel_array(readbuf + slice.start, len, &self->byteorder, self->pixel_step, self->byteorder.is_dotstar); + return pixelbuf_get_pixel_array(readbuf + slice.start, len, &self->byteorder, self->pixel_step, slice.step, self->byteorder.is_dotstar); } else { // Set #if MICROPY_PY_ARRAY_SLICE_ASSIGN if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple))) mp_raise_ValueError(translate("tuple/list required on RHS")); - size_t dst_len = slice.stop - slice.start; - + size_t dst_len = (slice.stop - slice.start); + dst_len = (slice.stop - slice.start) / slice.step; + if (slice.step > 1) { + if ((slice.stop - slice.start) % slice.step) + dst_len ++; + } mp_obj_t *src_objs; size_t num_items; if (MP_OBJ_IS_TYPE(value, &mp_type_list)) { @@ -394,16 +400,17 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."), dst_len, num_items); - for (size_t i = slice.start; i < slice.stop; i++) { + size_t target_i = slice.start; + for (size_t i = slice.start; target_i < slice.stop; i++, target_i += slice.step) { mp_obj_t *item = src_objs[i-slice.start]; if (MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple) || MP_OBJ_IS_INT(value)) { - pixelbuf_set_pixel(self->buf + (i * self->pixel_step), + pixelbuf_set_pixel(self->buf + (target_i * self->pixel_step), self->two_buffers ? self->rawbuf + (i * self->pixel_step) : NULL, self->brightness, item, &self->byteorder, self->byteorder.is_dotstar); } } if (self->auto_write) - call_show(self_in); + call_show(self_in, 's'); return mp_const_none; #else return MP_OBJ_NULL; // op not supported @@ -423,7 +430,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp pixelbuf_set_pixel(self->buf + offset, self->two_buffers ? self->rawbuf + offset : NULL, self->brightness, value, &self->byteorder, self->byteorder.is_dotstar); if (self->auto_write) - call_show(self_in); + call_show(self_in, 'i'); return mp_const_none; } } diff --git a/shared-bindings/_pixelbuf/PixelBuf.h b/shared-bindings/_pixelbuf/PixelBuf.h index aa09e9261..18caa9219 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.h +++ b/shared-bindings/_pixelbuf/PixelBuf.h @@ -48,6 +48,6 @@ typedef struct { } pixelbuf_pixelbuf_obj_t; void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self); -mp_obj_t call_show(mp_obj_t self_in); +mp_obj_t call_show(mp_obj_t self_in, char origin); #endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index e26f05ac3..a0071903a 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -94,10 +94,13 @@ void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_ } } -mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, bool dotstar) { +mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar) { mp_obj_t elems[len]; + if (slice_step > 1) { + len = len / slice_step; + } for (uint i = 0; i < len; i++) { - elems[i] = pixelbuf_get_pixel(buf + (i * step), byteorder, dotstar); + elems[i] = pixelbuf_get_pixel(buf + ((i * slice_step) * step), byteorder, dotstar); } return mp_obj_new_tuple(len, elems); } diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h index 6b3272e19..173ce61a8 100644 --- a/shared-module/_pixelbuf/PixelBuf.h +++ b/shared-module/_pixelbuf/PixelBuf.h @@ -44,7 +44,7 @@ void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar); mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar); -mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, bool dotstar); +mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar); void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder); #endif -- cgit v1.2.3 From 7f744a2369a5036cadfa05575da1704f709c98bb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 18 Nov 2019 08:22:41 -0600 Subject: Supervisor: move most of systick to the supervisor This code is shared by most parts, except where not all the #ifdefs inside the tick function were present in all ports. This mostly would have broken gamepad tick support on non-samd ports. The "ms32" and "ms64" variants of the tick functions are introduced because there is no 64-bit atomic read. Disabling interrupts avoids a low probability bug where milliseconds could be off by ~49.5 days once every ~49.5 days (2^32 ms). Avoiding disabling interrupts when only the low 32 bits are needed is a minor optimization. Testing performed: on metro m4 express, USB still works and time.monotonic_ns() still counts up --- drivers/wiznet5k/internet/dns/dns.c | 4 +- ports/atmel-samd/background.c | 5 +- ports/atmel-samd/common-hal/busio/UART.c | 13 ++-- ports/atmel-samd/common-hal/time/__init__.c | 4 +- ports/atmel-samd/mphalport.c | 6 +- ports/atmel-samd/mphalport.h | 6 +- ports/atmel-samd/tick.c | 36 ++-------- ports/atmel-samd/tick.h | 2 - ports/cxd56/common-hal/time/__init__.c | 4 +- ports/cxd56/mphalport.c | 6 +- ports/cxd56/mphalport.h | 2 - ports/cxd56/tick.c | 15 +---- ports/cxd56/tick.h | 2 - ports/nrf/common-hal/_bleio/Adapter.c | 3 +- ports/nrf/common-hal/_bleio/CharacteristicBuffer.c | 5 +- ports/nrf/common-hal/busio/UART.c | 12 ++-- ports/nrf/common-hal/time/__init__.c | 2 +- ports/nrf/mphalport.c | 5 +- ports/nrf/mphalport.h | 5 +- ports/nrf/tick.c | 33 +++------- ports/nrf/tick.h | 2 - ports/stm32f4/common-hal/time/__init__.c | 2 +- ports/stm32f4/mphalport.c | 6 +- ports/stm32f4/mphalport.h | 4 +- ports/stm32f4/tick.c | 32 +++------ ports/stm32f4/tick.h | 2 - py/circuitpy_mpconfig.h | 1 + shared-module/displayio/Display.c | 11 ++-- shared-module/displayio/EPaperDisplay.c | 5 +- shared-module/displayio/display_core.c | 5 +- shared-module/network/__init__.c | 4 +- shared-module/usb_hid/Device.c | 5 +- supervisor/shared/rgb_led_status.c | 9 +-- supervisor/shared/safe_mode.c | 5 +- supervisor/shared/tick.c | 76 ++++++++++++++++++++++ supervisor/shared/tick.h | 37 +++++++++++ supervisor/supervisor.mk | 1 + 37 files changed, 214 insertions(+), 163 deletions(-) create mode 100644 supervisor/shared/tick.c create mode 100644 supervisor/shared/tick.h (limited to 'shared-module') 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 #include -#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/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 386ba0715..3b698768b 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" @@ -71,9 +72,9 @@ void run_background_tasks(void) { running_background_tasks = false; assert_heap_ok(); - last_finished_tick = ticks_ms; + last_finished_tick = supervisor_ticks_ms64(); } 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/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 2505e894a..42493a6b6 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. @@ -330,9 +329,9 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, // Wait until write is complete or timeout. bool done = false; - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Busy-wait for timeout. - while (ticks_ms - start_ticks < self->timeout_ms) { + while (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) { if (usart_async_is_tx_empty(usart_desc_p)) { done = true; break; 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/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/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 295a42d63..c3b8dcebe 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" @@ -353,7 +354,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, 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/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 54a66ddbe..982b8efa9 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() ) { @@ -265,15 +265,15 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, if ( len == 0 ) return 0; - uint64_t start_ticks = ticks_ms; + uint64_t start_ticks = supervisor_ticks_ms64(); // Wait for on-going transfer to complete - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { + while ( nrfx_uarte_tx_in_progress(self->uarte) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { RUN_BACKGROUND_TASKS; } // Time up - if ( !(ticks_ms - start_ticks < self->timeout_ms) ) { + if ( !(supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } @@ -290,7 +290,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, _VERIFY_ERR(*errcode); (*errcode) = 0; - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { + while ( nrfx_uarte_tx_in_progress(self->uarte) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { RUN_BACKGROUND_TASKS; } 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 -extern volatile uint64_t ticks_ms; - extern struct timer_descriptor ms_timer; void tick_init(void); 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/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/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 -extern volatile uint64_t ticks_ms; - extern struct timer_descriptor ms_timer; void tick_init(void); diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 61d324291..7853e4de9 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -32,6 +32,7 @@ #define __INCLUDED_MPCONFIG_CIRCUITPY_H #include +#include // This is CircuitPython. #define CIRCUITPY 1 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 @@ -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 df1d5162b..ad2559a83 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.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 "supervisor/usb.h" #include @@ -175,7 +176,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; } @@ -339,7 +340,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/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 #include @@ -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/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..d4a6ac5d7 --- /dev/null +++ b/supervisor/shared/tick.c @@ -0,0 +1,76 @@ +/* + * 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; + +#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; +} diff --git a/supervisor/shared/tick.h b/supervisor/shared/tick.h new file mode 100644 index 000000000..3defeb108 --- /dev/null +++ b/supervisor/shared/tick.h @@ -0,0 +1,37 @@ +/* + * 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 +#include + +extern void supervisor_tick(void); +extern uint32_t supervisor_ticks_ms32(void); +extern uint64_t supervisor_ticks_ms64(void); + +#endif 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) -- cgit v1.2.3 From d32dc814d3f0d3e845e54a043467f37a5908f5f0 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 26 Nov 2019 12:48:36 -0800 Subject: Fix ePaper so it works after a GC. We weren't correctly collecting the start and stop sequences. As a result, the GC would free the space and allocate other info there. Thanks to JacobT on Discord for the bug report! --- shared-module/displayio/EPaperDisplay.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index df1d5162b..252b39eb7 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -26,6 +26,7 @@ #include "shared-bindings/displayio/EPaperDisplay.h" +#include "py/gc.h" #include "py/runtime.h" #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/FourWire.h" @@ -298,7 +299,7 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c } bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* self) { - + if (self->refreshing && self->busy.base.type == &digitalio_digitalinout_type) { if (common_hal_digitalio_digitalinout_get_value(&self->busy) != self->busy_state) { self->refreshing = false; @@ -365,6 +366,8 @@ void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) { void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self) { displayio_display_core_collect_ptrs(&self->core); + gc_collect_ptr(self->start_sequence); + gc_collect_ptr(self->stop_sequence); } bool maybe_refresh_epaperdisplay(void) { -- cgit v1.2.3 From 56720eae0a9eb6fe8845cf20eb1298c3fb68a373 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Tue, 26 Nov 2019 18:39:08 -0500 Subject: remove unnecessary intermediate mp_obj_subscr wrapper --- extmod/modurandom.c | 2 +- extmod/vfs.c | 2 +- ports/unix/modjni.c | 2 +- py/obj.c | 6 +----- py/obj.h | 3 +-- py/objreversed.c | 2 +- py/objtype.c | 2 +- py/vm.c | 4 ++-- shared-bindings/random/__init__.c | 2 +- shared-module/os/__init__.c | 2 +- 10 files changed, 11 insertions(+), 16 deletions(-) (limited to 'shared-module') diff --git a/extmod/modurandom.c b/extmod/modurandom.c index 1512a3fd4..101c80cf8 100644 --- a/extmod/modurandom.c +++ b/extmod/modurandom.c @@ -150,7 +150,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint); STATIC mp_obj_t mod_urandom_choice(mp_obj_t seq) { mp_int_t len = mp_obj_get_int(mp_obj_len(seq)); if (len > 0) { - return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL); + return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL, seq); } else { nlr_raise(mp_obj_new_exception(&mp_type_IndexError)); } diff --git a/extmod/vfs.c b/extmod/vfs.c index 7d6e6999b..7599739e0 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -373,7 +373,7 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) { mp_obj_t dir_list = mp_obj_new_list(0, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { - mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL)); + mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL, next)); } return dir_list; } diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 50dd10dd2..8f0eac5a9 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -311,7 +311,7 @@ STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { // TODO: subscr_load_adaptor & subscr_getiter convenience functions // should be moved to common location for reuse. STATIC mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { - return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL); + return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL, self_in); } MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor); diff --git a/py/obj.c b/py/obj.c index 54822c977..47aa1aebf 100644 --- a/py/obj.c +++ b/py/obj.c @@ -487,11 +487,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { } } -mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { - return mp_obj_subscr_impl(base, index, value, base); -} - -mp_obj_t mp_obj_subscr_impl(mp_obj_t base, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { mp_obj_type_t *type = mp_obj_get_type(base); if (type->subscr != NULL) { diff --git a/py/obj.h b/py/obj.h index edeeb2a4b..ff97b34d8 100644 --- a/py/obj.h +++ b/py/obj.h @@ -707,8 +707,7 @@ size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool mp_obj_t mp_obj_id(mp_obj_t o_in); mp_obj_t mp_obj_len(mp_obj_t o_in); mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL -mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); -mp_obj_t mp_obj_subscr_impl(mp_obj_t base, mp_obj_t index, mp_obj_t val, mp_obj_t instance); +mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val, mp_obj_t instance); mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in); // cell diff --git a/py/objreversed.c b/py/objreversed.c index 4937d0818..0b21e6938 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -66,7 +66,7 @@ STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { // pre-decrement and index sequence self->cur_index -= 1; - return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL); + return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL, self->seq); } const mp_obj_type_t mp_type_reversed = { diff --git a/py/objtype.c b/py/objtype.c index 7d0760a10..9608a9242 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -852,7 +852,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value meth_args = 3; } if (member[0] == MP_OBJ_SENTINEL) { - return mp_obj_subscr_impl(self->subobj[0], index, value, instance); + return mp_obj_subscr(self->subobj[0], index, value, instance); } else if (member[0] != MP_OBJ_NULL) { mp_obj_t args[3] = {self_in, index, value}; // TODO probably need to call mp_convert_member_lookup, and use mp_call_method_n_kw diff --git a/py/vm.c b/py/vm.c index 353fc8810..2fe8d3237 100644 --- a/py/vm.c +++ b/py/vm.c @@ -386,7 +386,7 @@ dispatch_loop: ENTRY(MP_BC_LOAD_SUBSCR): { MARK_EXC_IP_SELECTIVE(); mp_obj_t index = POP(); - SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL)); + SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL, TOP())); DISPATCH(); } @@ -464,7 +464,7 @@ dispatch_loop: ENTRY(MP_BC_STORE_SUBSCR): MARK_EXC_IP_SELECTIVE(); - mp_obj_subscr(sp[-1], sp[0], sp[-2]); + mp_obj_subscr(sp[-1], sp[0], sp[-2], sp[-1]); sp -= 3; DISPATCH(); diff --git a/shared-bindings/random/__init__.c b/shared-bindings/random/__init__.c index 83698eac5..fdef91443 100644 --- a/shared-bindings/random/__init__.c +++ b/shared-bindings/random/__init__.c @@ -145,7 +145,7 @@ STATIC mp_obj_t random_choice(mp_obj_t seq) { if (len == 0) { mp_raise_IndexError(translate("empty sequence")); } - return mp_obj_subscr(seq, mp_obj_new_int(shared_modules_random_randrange(0, len, 1)), MP_OBJ_SENTINEL); + return mp_obj_subscr(seq, mp_obj_new_int(shared_modules_random_randrange(0, len, 1)), MP_OBJ_SENTINEL, seq); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(random_choice_obj, random_choice); diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 8060eec4f..ad76251c8 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -127,7 +127,7 @@ mp_obj_t common_hal_os_listdir(const char* path) { mp_obj_t next; while ((next = mp_iternext(iter_obj)) != MP_OBJ_STOP_ITERATION) { // next[0] is the filename. - mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL)); + mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL, dir_list)); RUN_BACKGROUND_TASKS; } return dir_list; -- cgit v1.2.3 From b32a9192df04c6fb36027b2b9b3e0e3a3548005a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 27 Nov 2019 12:52:11 -0500 Subject: make UART.write be blocking on SAMD; add timeout property --- ports/atmel-samd/common-hal/busio/UART.c | 36 ++++++------ ports/cxd56/common-hal/busio/UART.c | 12 +++- ports/cxd56/common-hal/busio/UART.h | 2 +- ports/nrf/common-hal/busio/UART.c | 24 ++++---- ports/stm32f4/common-hal/busio/UART.c | 98 ++++++++++++++++++-------------- shared-bindings/board/__init__.c | 6 ++ shared-bindings/busio/UART.c | 46 +++++++++++++-- shared-bindings/busio/UART.h | 3 +- shared-module/board/__init__.c | 2 +- 9 files changed, 144 insertions(+), 85 deletions(-) (limited to 'shared-module') diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 2505e894a..d869f70ff 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -323,29 +323,23 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, struct io_descriptor *io; usart_async_get_io_descriptor(usart_desc_p, &io); + // Start writing characters. This is non-blocking and will + // return immediately after setting up the write. if (io_write(io, data, len) < 0) { *errcode = MP_EAGAIN; return MP_STREAM_ERROR; } - // Wait until write is complete or timeout. - bool done = false; - uint64_t start_ticks = ticks_ms; - // Busy-wait for timeout. - while (ticks_ms - start_ticks < self->timeout_ms) { - if (usart_async_is_tx_empty(usart_desc_p)) { - done = true; + // Busy-wait until all characters transmitted. + struct usart_async_status async_status; + while (true) { + usart_async_get_status(usart_desc_p, &async_status); + if (async_status.txcnt >= len) { break; } RUN_BACKGROUND_TASKS; } - if (!done) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - - // All the characters got written. return len; } @@ -368,6 +362,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat self->baudrate = baudrate; } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout_ms / 1000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_ms = timeout * 1000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { // This assignment is only here because the usart_async routines take a *const argument. struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; @@ -383,12 +385,14 @@ void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { } +// True if there are no characters still to be written. bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { if (self->tx_pin == NO_PIN) { return false; } // This assignment is only here because the usart_async routines take a *const argument. - const struct _usart_async_device * const usart_device_p = - (struct _usart_async_device * const) &self->usart_desc.device; - return _usart_async_is_byte_sent(usart_device_p); + struct usart_async_descriptor * const usart_desc_p = (struct usart_async_descriptor * const) &self->usart_desc; + struct usart_async_status async_status; + usart_async_get_status(usart_desc_p, &async_status); + return !(async_status.flags & USART_ASYNC_STATUS_BUSY); } diff --git a/ports/cxd56/common-hal/busio/UART.c b/ports/cxd56/common-hal/busio/UART.c index 4a1376f19..6ae2403c1 100644 --- a/ports/cxd56/common-hal/busio/UART.c +++ b/ports/cxd56/common-hal/busio/UART.c @@ -102,7 +102,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, self->tx_pin = tx; self->rx_pin = rx; self->baudrate = baudrate; - self->timeout = timeout; + self->timeout_us = timeout * 1000000; } void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { @@ -135,7 +135,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t FD_SET(busio_uart_dev[self->number].fd, &rfds); tv.tv_sec = 0; - tv.tv_usec = self->timeout * 1000; + tv.tv_usec = self->timeout_us; retval = select(busio_uart_dev[self->number].fd + 1, &rfds, NULL, NULL, &tv); @@ -172,6 +172,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat ioctl(busio_uart_dev[self->number].fd, TCFLSH, (long unsigned int)NULL); } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout / 1000000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_us = timeout * 1000000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { int count = 0; diff --git a/ports/cxd56/common-hal/busio/UART.h b/ports/cxd56/common-hal/busio/UART.h index e1d816149..a69c47056 100644 --- a/ports/cxd56/common-hal/busio/UART.h +++ b/ports/cxd56/common-hal/busio/UART.h @@ -37,7 +37,7 @@ typedef struct { const mcu_pin_obj_t *tx_pin; const mcu_pin_obj_t *rx_pin; uint32_t baudrate; - uint32_t timeout; + uint32_t timeout_us; } busio_uart_obj_t; void busio_uart_reset(void); diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 54a66ddbe..a0ae8af00 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -265,19 +265,6 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, if ( len == 0 ) return 0; - uint64_t start_ticks = ticks_ms; - - // Wait for on-going transfer to complete - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { - RUN_BACKGROUND_TASKS; - } - - // Time up - if ( !(ticks_ms - start_ticks < self->timeout_ms) ) { - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; - } - // EasyDMA can only access SRAM uint8_t * tx_buf = (uint8_t*) data; if ( !nrfx_is_in_ram(data) ) { @@ -290,7 +277,8 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, _VERIFY_ERR(*errcode); (*errcode) = 0; - while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { + // Wait for write to complete. + while ( nrfx_uarte_tx_in_progress(self->uarte) ) { RUN_BACKGROUND_TASKS; } @@ -310,6 +298,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat nrf_uarte_baudrate_set(self->uarte->p_reg, get_nrf_baud(baudrate)); } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout_ms / 1000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_ms = timeout * 1000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { return ringbuf_count(&self->rbuf); } diff --git a/ports/stm32f4/common-hal/busio/UART.c b/ports/stm32f4/common-hal/busio/UART.c index c4ab237cd..f0e0cc9eb 100644 --- a/ports/stm32f4/common-hal/busio/UART.c +++ b/ports/stm32f4/common-hal/busio/UART.c @@ -36,7 +36,7 @@ #include "supervisor/shared/translate.h" #include "tick.h" -#include "stm32f4xx_hal.h" +#include "stm32f4xx_hal.h" #define ALL_UARTS 0xFFFF @@ -55,7 +55,7 @@ void uart_reset(void) { uart_clock_disable(ALL_UARTS); } -STATIC USART_TypeDef * assign_uart_or_throw(busio_uart_obj_t* self, bool pin_eval, +STATIC USART_TypeDef * assign_uart_or_throw(busio_uart_obj_t* self, bool pin_eval, int uart_index, bool uart_taken) { if (pin_eval) { //assign a root pointer pointer for IRQ @@ -82,7 +82,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, uint8_t rx_len = sizeof(mcu_uart_rx_list)/sizeof(*mcu_uart_rx_list); bool uart_taken = false; uint8_t uart_index = 0; //origin 0 corrected - + //Can have both pins, or either if ((tx != mp_const_none) && (rx != mp_const_none)) { //normal find loop if both pins exist @@ -90,7 +90,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, if (mcu_uart_tx_list[i].pin == tx) { //rx for (uint j = 0; j < rx_len; j++) { - if (mcu_uart_rx_list[j].pin == rx + if (mcu_uart_rx_list[j].pin == rx && mcu_uart_rx_list[j].uart_index == mcu_uart_tx_list[i].uart_index) { //keep looking if the UART is taken, edge case if (reserved_uart[mcu_uart_tx_list[i].uart_index - 1]) { @@ -106,7 +106,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, } } uart_index = self->tx->uart_index - 1; - USARTx = assign_uart_or_throw(self, (self->tx != NULL && self->rx != NULL), + USARTx = assign_uart_or_throw(self, (self->tx != NULL && self->rx != NULL), uart_index, uart_taken); } else if (tx == mp_const_none) { //If there is no tx, run only rx @@ -123,7 +123,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, } } uart_index = self->rx->uart_index - 1; - USARTx = assign_uart_or_throw(self, (self->rx != NULL), + USARTx = assign_uart_or_throw(self, (self->rx != NULL), uart_index, uart_taken); } else if (rx == mp_const_none) { //If there is no rx, run only tx @@ -140,7 +140,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, } } uart_index = self->tx->uart_index - 1; - USARTx = assign_uart_or_throw(self, (self->tx != NULL), + USARTx = assign_uart_or_throw(self, (self->tx != NULL), uart_index, uart_taken); } else { //both pins cannot be empty @@ -173,7 +173,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = self->rx->altfn_index; + GPIO_InitStruct.Alternate = self->rx->altfn_index; HAL_GPIO_Init(pin_port(rx->port), &GPIO_InitStruct); } @@ -186,7 +186,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t* self, self->handle.Init.BaudRate = baudrate; self->handle.Init.WordLength = (bits == 9) ? UART_WORDLENGTH_9B : UART_WORDLENGTH_8B; self->handle.Init.StopBits = (stop > 1) ? UART_STOPBITS_2 : UART_STOPBITS_1; - self->handle.Init.Parity = (parity == PARITY_ODD) ? UART_PARITY_ODD : + self->handle.Init.Parity = (parity == PARITY_ODD) ? UART_PARITY_ODD : (parity == PARITY_EVEN) ? UART_PARITY_EVEN : UART_PARITY_NONE; self->handle.Init.Mode = (self->tx != NULL && self->rx != NULL) ? UART_MODE_TX_RX : @@ -234,7 +234,7 @@ bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { if (common_hal_busio_uart_deinited(self)) return; - + reset_pin_number(self->tx->pin->port,self->tx->pin->number); reset_pin_number(self->rx->pin->port,self->rx->pin->number); self->tx = mp_const_none; @@ -279,7 +279,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t *errcode = EAGAIN; return MP_STREAM_ERROR; } - return rx_bytes; + return rx_bytes; } // Write characters. @@ -290,13 +290,15 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, bool write_err = false; //write error shouldn't disable interrupts HAL_NVIC_DisableIRQ(self->irq); - if (HAL_UART_Transmit(&self->handle, (uint8_t*)data, len, self->timeout_ms) != HAL_OK) { + if (HAL_UART_Transmit(&self->handle, (uint8_t*)data, len, HAL_MAX_DELAY) != HAL_OK) { write_err = true; } HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1); HAL_NVIC_EnableIRQ(self->irq); - if (write_err) mp_raise_ValueError(translate("UART write error")); + if (write_err) { + mp_raise_ValueError(translate("UART write error")); + } return len; } @@ -312,7 +314,7 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *handle) } ringbuf_put_n(&context->rbuf, &context->rx_char, 1); errflag = HAL_UART_Receive_IT(handle, &context->rx_char, 1); - + return; } } @@ -360,6 +362,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat self->baudrate = baudrate; } +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t) (self->timeout_ms / 1000.0f); +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout_ms = timeout * 1000; +} + uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { return ringbuf_count(&self->rbuf); } @@ -414,71 +424,71 @@ STATIC void uart_clock_enable(uint16_t mask) { if (mask & (1 << 0)) { __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); - __HAL_RCC_USART1_CLK_ENABLE(); + __HAL_RCC_USART1_CLK_ENABLE(); } #endif #ifdef USART2 if (mask & (1 << 1)) { __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); - __HAL_RCC_USART2_CLK_ENABLE(); + __HAL_RCC_USART2_CLK_ENABLE(); } #endif #ifdef USART3 if (mask & (1 << 2)) { __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); - __HAL_RCC_USART3_CLK_ENABLE(); + __HAL_RCC_USART3_CLK_ENABLE(); } #endif #ifdef UART4 if (mask & (1 << 3)) { __HAL_RCC_UART4_FORCE_RESET(); __HAL_RCC_UART4_RELEASE_RESET(); - __HAL_RCC_UART4_CLK_ENABLE(); + __HAL_RCC_UART4_CLK_ENABLE(); } #endif #ifdef UART5 if (mask & (1 << 4)) { __HAL_RCC_UART5_FORCE_RESET(); __HAL_RCC_UART5_RELEASE_RESET(); - __HAL_RCC_UART5_CLK_ENABLE(); + __HAL_RCC_UART5_CLK_ENABLE(); } #endif #ifdef USART6 if (mask & (1 << 5)) { __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); - __HAL_RCC_USART6_CLK_ENABLE(); - } + __HAL_RCC_USART6_CLK_ENABLE(); + } #endif #ifdef UART7 if (mask & (1 << 6)) { __HAL_RCC_UART7_FORCE_RESET(); __HAL_RCC_UART7_RELEASE_RESET(); - __HAL_RCC_UART7_CLK_ENABLE(); - } + __HAL_RCC_UART7_CLK_ENABLE(); + } #endif #ifdef UART8 if (mask & (1 << 7)) { __HAL_RCC_UART8_FORCE_RESET(); __HAL_RCC_UART8_RELEASE_RESET(); - __HAL_RCC_UART8_CLK_ENABLE(); - } + __HAL_RCC_UART8_CLK_ENABLE(); + } #endif #ifdef UART9 if (mask & (1 << 8)) { __HAL_RCC_UART9_FORCE_RESET(); __HAL_RCC_UART9_RELEASE_RESET(); - __HAL_RCC_UART9_CLK_ENABLE(); - } + __HAL_RCC_UART9_CLK_ENABLE(); + } #endif #ifdef UART10 if (mask & (1 << 9)) { __HAL_RCC_UART10_FORCE_RESET(); __HAL_RCC_UART10_RELEASE_RESET(); - __HAL_RCC_UART10_CLK_ENABLE(); - } + __HAL_RCC_UART10_CLK_ENABLE(); + } #endif } @@ -487,71 +497,71 @@ STATIC void uart_clock_disable(uint16_t mask) { if (mask & (1 << 0)) { __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); - __HAL_RCC_USART1_CLK_DISABLE(); + __HAL_RCC_USART1_CLK_DISABLE(); } #endif #ifdef USART2 if (mask & (1 << 1)) { __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); - __HAL_RCC_USART2_CLK_DISABLE(); + __HAL_RCC_USART2_CLK_DISABLE(); } #endif #ifdef USART3 if (mask & (1 << 2)) { __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); - __HAL_RCC_USART3_CLK_DISABLE(); + __HAL_RCC_USART3_CLK_DISABLE(); } #endif #ifdef UART4 if (mask & (1 << 3)) { __HAL_RCC_UART4_FORCE_RESET(); __HAL_RCC_UART4_RELEASE_RESET(); - __HAL_RCC_UART4_CLK_DISABLE(); + __HAL_RCC_UART4_CLK_DISABLE(); } #endif #ifdef UART5 if (mask & (1 << 4)) { __HAL_RCC_UART5_FORCE_RESET(); __HAL_RCC_UART5_RELEASE_RESET(); - __HAL_RCC_UART5_CLK_DISABLE(); + __HAL_RCC_UART5_CLK_DISABLE(); } #endif #ifdef USART6 if (mask & (1 << 5)) { __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); - __HAL_RCC_USART6_CLK_DISABLE(); - } + __HAL_RCC_USART6_CLK_DISABLE(); + } #endif #ifdef UART7 if (mask & (1 << 6)) { __HAL_RCC_UART7_FORCE_RESET(); __HAL_RCC_UART7_RELEASE_RESET(); - __HAL_RCC_UART7_CLK_DISABLE(); - } + __HAL_RCC_UART7_CLK_DISABLE(); + } #endif #ifdef UART8 if (mask & (1 << 7)) { __HAL_RCC_UART8_FORCE_RESET(); __HAL_RCC_UART8_RELEASE_RESET(); - __HAL_RCC_UART8_CLK_DISABLE(); - } + __HAL_RCC_UART8_CLK_DISABLE(); + } #endif #ifdef UART9 if (mask & (1 << 8)) { __HAL_RCC_UART9_FORCE_RESET(); __HAL_RCC_UART9_RELEASE_RESET(); - __HAL_RCC_UART9_CLK_DISABLE(); - } + __HAL_RCC_UART9_CLK_DISABLE(); + } #endif #ifdef UART10 if (mask & (1 << 9)) { __HAL_RCC_UART10_FORCE_RESET(); __HAL_RCC_UART10_RELEASE_RESET(); - __HAL_RCC_UART10_CLK_DISABLE(); - } + __HAL_RCC_UART10_CLK_DISABLE(); + } #endif } diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c index 47e2d64bc..3dda59fb8 100644 --- a/shared-bindings/board/__init__.c +++ b/shared-bindings/board/__init__.c @@ -93,6 +93,12 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi); //| //| Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton. //| +//| The object created uses the default parameter values for `busio.UART`. If you need to set +//| parameters that are not changeable after creation, such as ``receiver_buffer_size``, +//| do not use `board.UART()`; instead create a `busio.UART` object explicitly with the +//| desired parameters. +//| +//| #if BOARD_UART mp_obj_t board_uart(void) { mp_obj_t singleton = common_hal_board_get_uart(); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index c7eef8c43..9606c77e9 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -57,7 +57,7 @@ //| :param int bits: the number of bits per byte, 7, 8 or 9. //| :param Parity parity: the parity used for error checking. //| :param int stop: the number of stop bits, 1 or 2. -//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters. Raises ``ValueError`` if timeout >100 seconds. +//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds. //| :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.) //| //| *New in CircuitPython 4.0:* ``timeout`` has incompatibly changed units from milliseconds to seconds. @@ -69,6 +69,12 @@ typedef struct { extern const busio_uart_parity_obj_t busio_uart_parity_even_obj; extern const busio_uart_parity_obj_t busio_uart_parity_odd_obj; +STATIC void validate_timeout(mp_float_t timeout) { + if (timeout < (mp_float_t) 0.0f || timeout > (mp_float_t) 100.0f) { + mp_raise_ValueError(translate("timeout must be 0.0-100.0 (units are now seconds, not msecs)")); + } +} + STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // Always initially allocate the UART object within the long-lived heap. // This is needed to avoid crashes with certain UART implementations which @@ -116,9 +122,7 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co } mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - if (timeout > (mp_float_t)100.0) { - mp_raise_ValueError(translate("timeout >100 (units are now seconds, not msecs)")); - } + validate_timeout(timeout); common_hal_busio_uart_construct(self, tx, rx, args[ARG_baudrate].u_int, bits, parity, stop, timeout, @@ -286,6 +290,35 @@ const mp_obj_property_t busio_uart_in_waiting_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: timeout +//| +//| The current timeout, in seconds (float). +//| +STATIC mp_obj_t busio_uart_obj_get_timeout(mp_obj_t self_in) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_float(common_hal_busio_uart_get_timeout(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_get_timeout_obj, busio_uart_obj_get_timeout); + +STATIC mp_obj_t busio_uart_obj_set_timeout(mp_obj_t self_in, mp_obj_t timeout) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + mp_float_t timeout_float = mp_obj_get_float(timeout); + validate_timeout(timeout_float); + common_hal_busio_uart_set_timeout(self, timeout_float); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(busio_uart_set_timeout_obj, busio_uart_obj_set_timeout); + + +const mp_obj_property_t busio_uart_timeout_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&busio_uart_get_timeout_obj, + (mp_obj_t)&busio_uart_set_timeout_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| .. method:: reset_input_buffer() //| //| Discard any unread characters in the input buffer. @@ -355,8 +388,9 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&busio_uart_reset_input_buffer_obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, - { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&busio_uart_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, + { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&busio_uart_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&busio_uart_timeout_obj) }, // Nested Enum-like Classes. { MP_ROM_QSTR(MP_QSTR_Parity), MP_ROM_PTR(&busio_uart_parity_type) }, diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h index 776a996be..cfd2c800c 100644 --- a/shared-bindings/busio/UART.h +++ b/shared-bindings/busio/UART.h @@ -57,7 +57,8 @@ extern size_t common_hal_busio_uart_write(busio_uart_obj_t *self, extern uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self); extern void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate); - +extern mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self); +extern void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout); extern uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self); extern void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index dd07d7190..914bc4313 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -101,7 +101,7 @@ mp_obj_t common_hal_board_create_uart(void) { const mcu_pin_obj_t* rx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RX); const mcu_pin_obj_t* tx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_TX); - common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1000, 64); + common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1.0f, 64); MP_STATE_VM(shared_uart_bus) = MP_OBJ_FROM_PTR(self); return MP_STATE_VM(shared_uart_bus); } -- cgit v1.2.3 From feb8eb935bd69ce855533bf9a4316e3025602c1a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 4 Dec 2019 09:31:52 -0600 Subject: audiosample: convert to use a protocol This eases addition of new sample sources, since the manual virtual function dispatch functions are just calls via a protocol --- shared-bindings/audiocore/RawSample.c | 11 +++++ shared-bindings/audiocore/RawSample.h | 2 + shared-bindings/audiocore/WaveFile.c | 12 +++++ shared-bindings/audiomixer/Mixer.c | 11 +++++ shared-bindings/audiomixer/Mixer.h | 2 + shared-module/audiocore/RawSample.c | 6 +++ shared-module/audiocore/__init__.c | 92 +++++------------------------------ shared-module/audiocore/__init__.h | 35 ++++++++++--- shared-module/audiomixer/Mixer.c | 8 +++ 9 files changed, 94 insertions(+), 85 deletions(-) (limited to 'shared-module') 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-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..4b306f8ba 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -31,6 +31,7 @@ #include #include "py/obj.h" +#include "py/proto.h" typedef enum { GET_BUFFER_DONE, // No more data to read @@ -38,15 +39,37 @@ typedef enum { GET_BUFFER_ERROR, // Error while reading data. } audioio_get_buffer_result_t; -uint32_t audiosample_sample_rate(mp_obj_t sample_obj); -uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); -uint8_t audiosample_channel_count(mp_obj_t sample_obj); -void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel); -audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, +typedef uint32_t (*audiosample_sample_rate_fun)(void* sample_obj); +typedef uint8_t (*audiosample_bits_per_sample_fun)(void* sample_obj); +typedef uint8_t (*audiosample_channel_count_fun)(void* sample_obj); +typedef void (*audiosample_reset_buffer_fun)(void* sample_obj); +typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(void* sample_obj, + bool single_channel, uint8_t channel, uint8_t** buffer, + uint32_t* buffer_length); +typedef void (*audiosample_get_buffer_structure_fun)(void* sample_obj, + 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(void* sample_obj); +uint8_t audiosample_bits_per_sample(void* sample_obj); +uint8_t audiosample_channel_count(void* sample_obj); +void audiosample_reset_buffer(void* sample_obj, bool single_channel, uint8_t audio_channel); +audioio_get_buffer_result_t audiosample_get_buffer(void* sample_obj, bool single_channel, uint8_t channel, uint8_t** buffer, uint32_t* buffer_length); -void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, +void audiosample_get_buffer_structure(void* sample_obj, bool single_channel, bool* single_buffer, bool* samples_signed, uint32_t* max_buffer_length, uint8_t* spacing); 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]))) { -- cgit v1.2.3 From ab74f45bfbed78fd752e3ed3a12c01fa910ad672 Mon Sep 17 00:00:00 2001 From: Hierophect Date: Thu, 5 Dec 2019 11:44:21 -0500 Subject: Define polarity and phase in Fourwire --- shared-module/displayio/FourWire.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-module') 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); -- cgit v1.2.3 From 60f489d36a364dfc4feb55af4d139987302c0242 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 5 Dec 2019 13:08:32 -0600 Subject: audiocore: restore the prototypes of audiosample_xxx functions --- shared-module/audiocore/__init__.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 4b306f8ba..9012c0d8b 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -61,15 +61,15 @@ typedef struct _audiosample_p_t { audiosample_get_buffer_structure_fun get_buffer_structure; } audiosample_p_t; -uint32_t audiosample_sample_rate(void* sample_obj); -uint8_t audiosample_bits_per_sample(void* sample_obj); -uint8_t audiosample_channel_count(void* sample_obj); -void audiosample_reset_buffer(void* sample_obj, bool single_channel, uint8_t audio_channel); -audioio_get_buffer_result_t audiosample_get_buffer(void* sample_obj, +uint32_t audiosample_sample_rate(mp_obj_t sample_obj); +uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); +uint8_t audiosample_channel_count(mp_obj_t sample_obj); +void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel); +audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t channel, uint8_t** buffer, uint32_t* buffer_length); -void audiosample_get_buffer_structure(void* sample_obj, bool single_channel, +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); -- cgit v1.2.3 From d5eca87ca23e9288b31c51f3d841fd2bb37c631b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 6 Dec 2019 13:25:40 -0600 Subject: audiocore: use mp_obj_t in prototypes --- shared-module/audiocore/__init__.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 9012c0d8b..38c1f5aeb 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -39,14 +39,14 @@ typedef enum { GET_BUFFER_ERROR, // Error while reading data. } audioio_get_buffer_result_t; -typedef uint32_t (*audiosample_sample_rate_fun)(void* sample_obj); -typedef uint8_t (*audiosample_bits_per_sample_fun)(void* sample_obj); -typedef uint8_t (*audiosample_channel_count_fun)(void* sample_obj); -typedef void (*audiosample_reset_buffer_fun)(void* sample_obj); -typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(void* sample_obj, +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)(void* sample_obj, +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); -- cgit v1.2.3 From a08d9e6d8e0059c8aa59feadd7b94d95d691e273 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Nov 2019 09:29:55 -0600 Subject: audiocore: Add MP3File using Adafruit_MP3 library --- .gitmodules | 3 + lib/mp3 | 1 + locale/ID.po | 18 +- locale/circuitpython.pot | 18 +- locale/de_DE.po | 18 +- locale/en_US.po | 18 +- locale/en_x_pirate.po | 18 +- locale/es.po | 18 +- locale/fil.po | 18 +- locale/fr.po | 18 +- locale/it_IT.po | 18 +- locale/ko.po | 18 +- locale/pl.po | 18 +- locale/pt_BR.po | 18 +- locale/zh_Latn_pinyin.po | 18 +- .../boards/kicksat-sprite/mpconfigboard.mk | 1 + ports/atmel-samd/mpconfigport.mk | 4 + py/circuitpy_defns.mk | 25 ++ py/circuitpy_mpconfig.h | 8 + py/circuitpy_mpconfig.mk | 9 + shared-bindings/audiomp3/MP3File.c | 226 +++++++++++++++++ shared-bindings/audiomp3/MP3File.h | 48 ++++ shared-bindings/audiomp3/__init__.c | 60 +++++ shared-bindings/audiomp3/__init__.h | 34 +++ shared-module/audiomp3/MP3File.c | 270 +++++++++++++++++++++ shared-module/audiomp3/MP3File.h | 70 ++++++ shared-module/audiomp3/__init__.c | 0 shared-module/audiomp3/__init__.h | 30 +++ 28 files changed, 997 insertions(+), 26 deletions(-) create mode 160000 lib/mp3 create mode 100644 shared-bindings/audiomp3/MP3File.c create mode 100644 shared-bindings/audiomp3/MP3File.h create mode 100644 shared-bindings/audiomp3/__init__.c create mode 100644 shared-bindings/audiomp3/__init__.h create mode 100644 shared-module/audiomp3/MP3File.c create mode 100644 shared-module/audiomp3/MP3File.h create mode 100644 shared-module/audiomp3/__init__.c create mode 100644 shared-module/audiomp3/__init__.h (limited to 'shared-module') diff --git a/.gitmodules b/.gitmodules index 764456cd6..98252c2af 100644 --- a/.gitmodules +++ b/.gitmodules @@ -102,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/lib/mp3 b/lib/mp3 new file mode 160000 index 000000000..2a3cc7873 --- /dev/null +++ b/lib/mp3 @@ -0,0 +1 @@ +Subproject commit 2a3cc7873b5c642d4bb60043dc14d2555e3377a5 diff --git a/locale/ID.po b/locale/ID.po index 472c042c6..4be18ec0d 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-12-06 13:25-0600\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 \n" "Language-Team: LANGUAGE \n" @@ -496,11 +496,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 "" @@ -613,6 +623,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" @@ -1779,7 +1793,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 1541b1f74..f00720207 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-12-06 13:25-0600\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 \n" "Language-Team: LANGUAGE \n" @@ -486,11 +486,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 "" @@ -602,6 +612,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" @@ -1749,7 +1763,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 b34626ea1..1756a7717 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-12-06 13:25-0600\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" @@ -490,11 +490,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" @@ -606,6 +616,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" @@ -1798,7 +1812,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 95884c7b2..79940e95e 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-12-06 13:25-0600\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" @@ -486,11 +486,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 "" @@ -602,6 +612,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" @@ -1749,7 +1763,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 ed7d2cec7..9fe49ec9f 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-12-06 13:25-0600\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" @@ -490,11 +490,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 "" @@ -606,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 #, c-format msgid "Failed to release mutex, err 0x%04x" @@ -1753,7 +1767,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 fac38c081..b5c375481 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-12-06 13:25-0600\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" @@ -494,11 +494,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" @@ -610,6 +620,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" @@ -1802,7 +1816,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 776002768..ba20e69b8 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-12-06 13:25-0600\n" +"POT-Creation-Date: 2019-12-10 13:55-0600\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy \n" "Language-Team: fil\n" @@ -495,11 +495,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" @@ -616,6 +626,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" @@ -1810,7 +1824,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 78d079bf1..e103cd06d 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-12-06 13:25-0600\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 \n" "Language-Team: fr\n" @@ -501,11 +501,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" @@ -620,6 +630,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" @@ -1842,7 +1856,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 67585fe2f..c1a445fa2 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-12-06 13:25-0600\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 \n" "Language-Team: \n" @@ -496,11 +496,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" @@ -616,6 +626,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 +1817,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 0cf674737..93a476b87 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-12-06 13:25-0600\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 \n" @@ -490,11 +490,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 "" @@ -606,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 #, c-format msgid "Failed to release mutex, err 0x%04x" @@ -1754,7 +1768,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 0e33f3022..8efab1867 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-12-06 13:25-0600\n" +"POT-Creation-Date: 2019-12-10 13:55-0600\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski \n" "Language-Team: pl\n" @@ -489,11 +489,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" @@ -605,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" @@ -1774,7 +1788,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 f1f707f63..1ca6b7d9a 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-12-06 13:25-0600\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" @@ -492,11 +492,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" @@ -611,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" @@ -1771,7 +1785,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 6e49774b5..40966090d 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-12-06 13:25-0600\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" @@ -490,11 +490,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ū" @@ -606,6 +616,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" @@ -1785,7 +1799,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" 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/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/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 000674c4f..5ee5d52c0 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -252,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; @@ -582,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 \ 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/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 + +#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 + +#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-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 +#include + +#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 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 -- cgit v1.2.3 From 222dd29a142a530b43fdf4d1ea01e276962b9886 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Tue, 10 Dec 2019 20:42:39 -0500 Subject: Fix slice step. --- shared-bindings/_pixelbuf/PixelBuf.c | 8 +++++--- shared-module/_pixelbuf/PixelBuf.c | 3 --- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index dabc23d35..feda2c573 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -391,6 +391,9 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp if (value == MP_OBJ_SENTINEL) { // Get size_t len = slice.stop - slice.start; + if (slice.step > 1) { + len = (len / slice.step) + (len % slice.step ? 1 : 0); + } uint8_t *readbuf = self->two_buffers ? self->rawbuf : self->buf; return pixelbuf_get_pixel_array(readbuf + slice.start, len, &self->byteorder, self->pixel_step, slice.step, self->byteorder.is_dotstar); } else { // Set @@ -399,10 +402,9 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple))) mp_raise_ValueError(translate("tuple/list required on RHS")); - size_t dst_len = (slice.stop - slice.start) / slice.step; + size_t dst_len = (slice.stop - slice.start); if (slice.step > 1) { - if ((slice.stop - slice.start) % slice.step) - dst_len ++; + dst_len = (dst_len / slice.step) + (dst_len % slice.step ? 1 : 0); } mp_obj_t *src_objs; size_t num_items; diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index a0071903a..020151bc3 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -96,9 +96,6 @@ void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_ mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar) { mp_obj_t elems[len]; - if (slice_step > 1) { - len = len / slice_step; - } for (uint i = 0; i < len; i++) { elems[i] = pixelbuf_get_pixel(buf + ((i * slice_step) * step), byteorder, dotstar); } -- cgit v1.2.3 From 8c841af9461eba6252690c38bc3e726f2fd09e8b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 11 Dec 2019 22:04:10 -0600 Subject: MP3File: Avoid crash in get_buffer when deinitted When a playing mp3 is deinitted, it's possible to reach get_buffer, but all the internal pointers are NULL. This would lead to a hard fault. Avoid it by returning GET_BUFFER_ERROR instead. --- shared-module/audiomp3/MP3File.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shared-module') diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index cabb46105..f0c4adc26 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -227,6 +227,9 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* uint8_t channel, uint8_t** bufptr, uint32_t* buffer_length) { + if (!self->inbuf) { + return GET_BUFFER_ERROR; + } if (!single_channel) { channel = 0; } -- cgit v1.2.3 From 1cdac3f16a9244c992e8494a7246ab643cdb47c0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 12 Dec 2019 08:44:15 -0600 Subject: MP3File: Fix stereo playback on samd AudioOut There were several problems with the way this worked -- the read_count approach was too complicated and I made a mistake "simplifying" it from WaveFile. And when the right channel was returned, it was off by 1 byte, making it into static. Instead, directly track which is the "other" channel that has data available, and by using the right data type make the "+ channel" arithmetic give the right result. This requires a double cast (int16_t*)(void*) due to an alignment warning; the alignment is now ensured manually, but the compiler doesn't make the necessary inference that the low address bit must be clear. --- shared-module/audiomp3/MP3File.c | 46 +++++++++++++++++++++++----------------- shared-module/audiomp3/MP3File.h | 6 +++--- 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index f0c4adc26..f4861da36 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -151,10 +151,13 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self, self->channel_count = fi.nChans; self->frame_buffer_size = fi.outputSamps*sizeof(int16_t); + if ((intptr_t)buffer & 1) { + buffer += 1; buffer_size -= 1; + } 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; + self->buffers[0] = (int16_t*)(void*)buffer; + self->buffers[1] = (int16_t*)(void*)buffer + self->len; } else { self->len = 2 * self->frame_buffer_size; self->buffers[0] = m_malloc(self->len, false); @@ -218,6 +221,7 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self, f_lseek(&self->file->fp, 0); self->inbuf_offset = self->inbuf_length; self->eof = 0; + self->other_channel = -1; mp3file_update_inbuf(self); mp3file_find_sync_word(self); } @@ -234,26 +238,30 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* 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; + *bufptr = (uint8_t*)(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 (channel == self->other_channel) { + *bufptr = (uint8_t*)(self->buffers[self->other_buffer_index] + channel); + self->other_channel = -1; + return GET_BUFFER_MORE_DATA; + } - 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; - } + self->other_channel = 1-channel; + self->other_buffer_index = self->buffer_index; + + 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; diff --git a/shared-module/audiomp3/MP3File.h b/shared-module/audiomp3/MP3File.h index 12649ac1a..9d99e8d1f 100644 --- a/shared-module/audiomp3/MP3File.h +++ b/shared-module/audiomp3/MP3File.h @@ -39,7 +39,7 @@ typedef struct { uint8_t* inbuf; uint32_t inbuf_length; uint32_t inbuf_offset; - uint8_t* buffers[2]; + int16_t* buffers[2]; uint32_t len; uint32_t frame_buffer_size; @@ -50,8 +50,8 @@ typedef struct { uint8_t channel_count; bool eof; - uint16_t read_count; - uint16_t channel_read_count[2]; + int8_t other_channel; + int8_t other_buffer_index; } audiomp3_mp3file_obj_t; // These are not available from Python because it may be called in an interrupt. -- cgit v1.2.3 From dc8dd6df20f4904917169f4ec1172c8f3827e822 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Fri, 13 Dec 2019 14:29:15 -0500 Subject: Revert subscr signature change --- extmod/machine_mem.c | 2 +- extmod/modbtree.c | 2 +- extmod/moductypes.c | 2 +- extmod/modurandom.c | 2 +- extmod/vfs.c | 2 +- ports/unix/modjni.c | 4 ++-- py/obj.c | 6 +++--- py/obj.h | 4 ++-- py/objarray.c | 3 +-- py/objdict.c | 2 +- py/objlist.c | 2 +- py/objrange.c | 2 +- py/objreversed.c | 2 +- py/objstr.c | 2 +- py/objstrunicode.c | 2 +- py/objtuple.c | 2 +- py/objtuple.h | 2 +- py/objtype.c | 4 ++-- py/opmethods.c | 6 +++--- py/vm.c | 4 ++-- shared-bindings/_pixelbuf/PixelBuf.c | 6 +++--- shared-bindings/displayio/Bitmap.c | 2 +- shared-bindings/displayio/Group.c | 2 +- shared-bindings/displayio/Palette.c | 2 +- shared-bindings/displayio/TileGrid.c | 2 +- shared-bindings/nvm/ByteArray.c | 2 +- shared-bindings/pulseio/PulseIn.c | 2 +- shared-bindings/random/__init__.c | 2 +- shared-module/os/__init__.c | 2 +- 29 files changed, 39 insertions(+), 40 deletions(-) (limited to 'shared-module') diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c index 826c59d0f..75496c6b5 100644 --- a/extmod/machine_mem.c +++ b/extmod/machine_mem.c @@ -61,7 +61,7 @@ STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { // TODO support slice index to read/write multiple values at once machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in); if (value == MP_OBJ_NULL) { diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 939ab813e..ad845163d 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -247,7 +247,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) { } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { //mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_btree_t *self = mp_instance_cast_to_native_base(self_in, &btree_type); if (value == MP_OBJ_NULL) { diff --git a/extmod/moductypes.c b/extmod/moductypes.c index 145b34887..bf5f1cef7 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -519,7 +519,7 @@ STATIC void uctypes_struct_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_obj_t value) { mp_obj_uctypes_struct_t *self = mp_instance_cast_to_native_base(base_in, &uctypes_struct_type); if (value == MP_OBJ_NULL) { diff --git a/extmod/modurandom.c b/extmod/modurandom.c index 101c80cf8..1512a3fd4 100644 --- a/extmod/modurandom.c +++ b/extmod/modurandom.c @@ -150,7 +150,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint); STATIC mp_obj_t mod_urandom_choice(mp_obj_t seq) { mp_int_t len = mp_obj_get_int(mp_obj_len(seq)); if (len > 0) { - return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL, seq); + return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL); } else { nlr_raise(mp_obj_new_exception(&mp_type_IndexError)); } diff --git a/extmod/vfs.c b/extmod/vfs.c index 4d344095a..2bb4057e7 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -373,7 +373,7 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) { mp_obj_t dir_list = mp_obj_new_list(0, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { - mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL, next)); + mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL)); } return dir_list; } diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index 8f0eac5a9..e18a26f3c 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -242,7 +242,7 @@ STATIC void get_jclass_name(jobject obj, char *buf) { } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = self_in; mp_uint_t idx = mp_obj_get_int(index); char class_name[64]; @@ -311,7 +311,7 @@ STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { // TODO: subscr_load_adaptor & subscr_getiter convenience functions // should be moved to common location for reuse. STATIC mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { - return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL, self_in); + return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor); diff --git a/py/obj.c b/py/obj.c index 47aa1aebf..09e71be4d 100644 --- a/py/obj.c +++ b/py/obj.c @@ -487,11 +487,11 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { } } -mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(base); if (type->subscr != NULL) { - mp_obj_t ret = type->subscr(base, index, value, instance); + mp_obj_t ret = type->subscr(base, index, value); // May have called port specific C code. Make sure it didn't mess up the heap. assert_heap_ok(); if (ret != MP_OBJ_NULL) { @@ -546,7 +546,7 @@ STATIC mp_obj_t generic_it_iternext(mp_obj_t self_in) { mp_obj_type_t *type = mp_obj_get_type(self->obj); mp_obj_t current_length = type->unary_op(MP_UNARY_OP_LEN, self->obj); if (self->cur < MP_OBJ_SMALL_INT_VALUE(current_length)) { - mp_obj_t o_out = type->subscr(self->obj, MP_OBJ_NEW_SMALL_INT(self->cur), MP_OBJ_SENTINEL, self->obj); + mp_obj_t o_out = type->subscr(self->obj, MP_OBJ_NEW_SMALL_INT(self->cur), MP_OBJ_SENTINEL); self->cur += 1; return o_out; } else { diff --git a/py/obj.h b/py/obj.h index ff97b34d8..cf4216d02 100644 --- a/py/obj.h +++ b/py/obj.h @@ -444,7 +444,7 @@ typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, cons typedef mp_obj_t (*mp_unary_op_fun_t)(mp_unary_op_t op, mp_obj_t); typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_t op, mp_obj_t, mp_obj_t); typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); -typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance); +typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); // Buffer protocol @@ -707,7 +707,7 @@ size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool mp_obj_t mp_obj_id(mp_obj_t o_in); mp_obj_t mp_obj_len(mp_obj_t o_in); mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL -mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val, mp_obj_t instance); +mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in); // cell diff --git a/py/objarray.c b/py/objarray.c index 6fffa8412..9114a63c5 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -396,8 +396,7 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_extend_obj, array_extend); #endif -#pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // TODO implement diff --git a/py/objdict.c b/py/objdict.c index 2c07331e7..5bbe939b1 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -175,7 +175,7 @@ mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) { } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete mp_obj_dict_delete(self_in, index); diff --git a/py/objlist.c b/py/objlist.c index 0c0d60aa8..64381bc70 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -159,7 +159,7 @@ STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_list_t *self = mp_instance_cast_to_native_base(self_in, &mp_type_list); if (value == MP_OBJ_NULL) { // delete diff --git a/py/objrange.c b/py/objrange.c index 328416303..6f14bcc9f 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -159,7 +159,7 @@ STATIC mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs #endif #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/py/objreversed.c b/py/objreversed.c index 0b21e6938..4937d0818 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -66,7 +66,7 @@ STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { // pre-decrement and index sequence self->cur_index -= 1; - return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL, self->seq); + return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL); } const mp_obj_type_t mp_type_reversed = { diff --git a/py/objstr.c b/py/objstr.c index fd802fe85..567e73444 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -440,7 +440,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s // This is used for both bytes and 8-bit strings. This is not used for unicode strings. #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(self_in); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { diff --git a/py/objstrunicode.c b/py/objstrunicode.c index dc8c0743d..2540a1d7b 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -198,7 +198,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s } #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(self_in); assert(type == &mp_type_str); GET_STR_DATA_LEN(self_in, self_data, self_len); diff --git a/py/objtuple.c b/py/objtuple.c index b6640def5..7a4c09ab7 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -178,7 +178,7 @@ mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } #pragma GCC diagnostic ignored "-Wunused-parameter" -mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/py/objtuple.h b/py/objtuple.h index 4df3aeded..7f20ab7b6 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -45,7 +45,7 @@ extern const mp_obj_type_t mp_type_tuple; void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in); mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); -mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value, mp_obj_t instance); +mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value); mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf); extern const mp_obj_type_t mp_type_attrtuple; diff --git a/py/objtype.c b/py/objtype.c index c7dc2ae78..a5e733208 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -826,7 +826,7 @@ STATIC void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { @@ -855,7 +855,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value if (member[0] == MP_OBJ_SENTINEL) { // native base subscr exists mp_obj_type_t *subobj_type = mp_obj_get_type(self->subobj[0]); // return mp_obj_subscr(self->subobj[0], index, value, instance); - mp_obj_t ret = subobj_type->subscr(self_in, index, value, instance); + mp_obj_t ret = subobj_type->subscr(self_in, index, value); // May have called port specific C code. Make sure it didn't mess up the heap. assert_heap_ok(); return ret; diff --git a/py/opmethods.c b/py/opmethods.c index d906ddb6a..247fa5bbc 100644 --- a/py/opmethods.c +++ b/py/opmethods.c @@ -29,19 +29,19 @@ STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->subscr(self_in, key_in, MP_OBJ_SENTINEL, self_in); + return type->subscr(self_in, key_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->subscr(self_in, key_in, value_in, self_in); + return type->subscr(self_in, key_in, value_in); } MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { mp_obj_type_t *type = mp_obj_get_type(self_in); - return type->subscr(self_in, key_in, MP_OBJ_NULL, self_in); + return type->subscr(self_in, key_in, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); diff --git a/py/vm.c b/py/vm.c index 2fe8d3237..353fc8810 100644 --- a/py/vm.c +++ b/py/vm.c @@ -386,7 +386,7 @@ dispatch_loop: ENTRY(MP_BC_LOAD_SUBSCR): { MARK_EXC_IP_SELECTIVE(); mp_obj_t index = POP(); - SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL, TOP())); + SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL)); DISPATCH(); } @@ -464,7 +464,7 @@ dispatch_loop: ENTRY(MP_BC_STORE_SUBSCR): MARK_EXC_IP_SELECTIVE(); - mp_obj_subscr(sp[-1], sp[0], sp[-2], sp[-1]); + mp_obj_subscr(sp[-1], sp[0], sp[-2]); sp -= 3; DISPATCH(); diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index feda2c573..a3579c92c 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -368,7 +368,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_fill_obj, pixelbuf_pixelbuf_f //| //| Sets the pixel value at the given index. //| -STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // slice deletion @@ -431,7 +431,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp } } if (self->auto_write) - call_show(instance); + call_show(self_in); return mp_const_none; #else return MP_OBJ_NULL; // op not supported @@ -451,7 +451,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp pixelbuf_set_pixel(self->buf + offset, self->two_buffers ? self->rawbuf + offset : NULL, self->brightness, value, &self->byteorder, self->byteorder.is_dotstar); if (self->auto_write) - call_show(instance); + call_show(self_in); return mp_const_none; } } diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c index 7c77d05ed..ca9484a40 100644 --- a/shared-bindings/displayio/Bitmap.c +++ b/shared-bindings/displayio/Bitmap.c @@ -134,7 +134,7 @@ const mp_obj_property_t displayio_bitmap_height_obj = { //| bitmap[0,1] = 3 //| #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj, mp_obj_t instance) { +STATIC mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) { if (value_obj == mp_const_none) { // delete item mp_raise_AttributeError(translate("Cannot delete values")); diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c index 40f2704c0..f5e3c2263 100644 --- a/shared-bindings/displayio/Group.c +++ b/shared-bindings/displayio/Group.c @@ -311,7 +311,7 @@ STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| del group[0] //| #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) { displayio_group_t *self = native_group(self_in); if (MP_OBJ_IS_TYPE(index_obj, &mp_type_slice)) { diff --git a/shared-bindings/displayio/Palette.c b/shared-bindings/displayio/Palette.c index 2fa65867a..903338abb 100644 --- a/shared-bindings/displayio/Palette.c +++ b/shared-bindings/displayio/Palette.c @@ -96,7 +96,7 @@ STATIC mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| palette[3] = bytearray(b'\x00\x00\xFF') # set using a bytearay of 3 or 4 bytes //| #pragma GCC diagnostic ignored "-Wunused-parameter" -STATIC mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item return MP_OBJ_NULL; // op not supported diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 5acf8496f..288eb4b23 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -349,7 +349,7 @@ const mp_obj_property_t displayio_tilegrid_pixel_shader_obj = { //| //| grid[0,0] = 10 //| -STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj, mp_obj_t instance) { +STATIC mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) { displayio_tilegrid_t *self = native_tilegrid(self_in); diff --git a/shared-bindings/nvm/ByteArray.c b/shared-bindings/nvm/ByteArray.c index 5ac46b260..31bedeacc 100644 --- a/shared-bindings/nvm/ByteArray.c +++ b/shared-bindings/nvm/ByteArray.c @@ -70,7 +70,7 @@ STATIC const mp_rom_map_elem_t nvm_bytearray_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(nvm_bytearray_locals_dict, nvm_bytearray_locals_dict_table); -STATIC mp_obj_t nvm_bytearray_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t nvm_bytearray_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // slice deletion diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c index 5947329a5..8b69109f0 100644 --- a/shared-bindings/pulseio/PulseIn.c +++ b/shared-bindings/pulseio/PulseIn.c @@ -272,7 +272,7 @@ STATIC mp_obj_t pulsein_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| pulses = pulseio.PulseIn(pin) //| print(pulses[0]) //| -STATIC mp_obj_t pulsein_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value, mp_obj_t instance) { +STATIC mp_obj_t pulsein_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) { if (value == mp_const_none) { // delete item mp_raise_AttributeError(translate("Cannot delete values")); diff --git a/shared-bindings/random/__init__.c b/shared-bindings/random/__init__.c index fdef91443..83698eac5 100644 --- a/shared-bindings/random/__init__.c +++ b/shared-bindings/random/__init__.c @@ -145,7 +145,7 @@ STATIC mp_obj_t random_choice(mp_obj_t seq) { if (len == 0) { mp_raise_IndexError(translate("empty sequence")); } - return mp_obj_subscr(seq, mp_obj_new_int(shared_modules_random_randrange(0, len, 1)), MP_OBJ_SENTINEL, seq); + return mp_obj_subscr(seq, mp_obj_new_int(shared_modules_random_randrange(0, len, 1)), MP_OBJ_SENTINEL); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(random_choice_obj, random_choice); diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index ad76251c8..8060eec4f 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -127,7 +127,7 @@ mp_obj_t common_hal_os_listdir(const char* path) { mp_obj_t next; while ((next = mp_iternext(iter_obj)) != MP_OBJ_STOP_ITERATION) { // next[0] is the filename. - mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL, dir_list)); + mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL)); RUN_BACKGROUND_TASKS; } return dir_list; -- cgit v1.2.3 From a854a76819e4b871f9d0c4e059ca5c03f05dca76 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 13 Dec 2019 14:05:56 -0600 Subject: audiocore: The arguments to reset_buffer went missing In conversion I missed these arguments were being passed, but noticed it when an implausible value for audio_channel was sent to mp3's reset_buffer method. It's not clear whether there was any negative impact to this, but it should be fixed! --- shared-module/audiocore/__init__.c | 2 +- shared-module/audiocore/__init__.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index 1553dbe96..ac9d41b60 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -52,7 +52,7 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) { void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) { 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)); + proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, audio_channel); } audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 38c1f5aeb..7a56454b8 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -42,7 +42,8 @@ typedef enum { 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 void (*audiosample_reset_buffer_fun)(mp_obj_t, + bool single_channel, uint8_t audio_channel); 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); -- cgit v1.2.3 From bf9b7e7ece6186b2fb7716323fba8ef24315cb47 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 13 Dec 2019 14:07:00 -0600 Subject: MP3: skip ID3V2 metadata This was one reason that the "bartlebeats" mp3s would not play. --- shared-module/audiomp3/MP3File.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'shared-module') diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index f4861da36..789d75e0f 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -88,6 +88,39 @@ STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) { #define BYTES_LEFT(self) (self->inbuf_length - self->inbuf_offset) #define CONSUME(self, n) (self->inbuf_offset += n) +// http://id3.org/d3v2.3.0 +// http://id3.org/id3v2.3.0 +STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) { + mp3file_update_inbuf(self); + if (BYTES_LEFT(self) < 10) { + return; + } + uint8_t *data = READ_PTR(self); + if (!( + data[0] == 'I' && + data[1] == 'D' && + data[2] == '3' && + data[3] != 0xff && + data[4] != 0xff && + (data[5] & 0x1f) == 0 && + (data[6] & 0x80) == 0 && + (data[7] & 0x80) == 0 && + (data[8] & 0x80) == 0 && + (data[9] & 0x80) == 0)) { + return; + } + uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]); + size += 10; // size excludes the "header" (but not the "extended header") + // First, deduct from size whatever is left in buffer + uint32_t to_consume = MIN(size, BYTES_LEFT(self)); + CONSUME(self, to_consume); + size -= to_consume; + + // Next, seek in the file after the header + f_lseek(&self->file->fp, f_tell(&self->file->fp) + size); + return; +} + /* If a sync word can be found, advance to it and return true. Otherwise, * return false. */ @@ -223,6 +256,7 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self, self->eof = 0; self->other_channel = -1; mp3file_update_inbuf(self); + mp3file_skip_id3v2(self); mp3file_find_sync_word(self); } @@ -253,6 +287,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* self->buffer_index = !self->buffer_index; int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + mp3file_skip_id3v2(self); if (!mp3file_find_sync_word(self)) { return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR; } -- cgit v1.2.3 From 91a1706160aa653cb00c7910b0930df679bcdd21 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 13 Dec 2019 15:20:48 -0600 Subject: MP3: look harder for frame info Apparently sometimes, a proper "frame info" block is not found after a "sync word". Keep looking for one as needed, instead of giving up after one try. This was one reason that the "bartlebeats" mp3s would not play. --- shared-module/audiomp3/MP3File.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index 789d75e0f..0aa4f24a6 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -139,7 +139,15 @@ STATIC bool mp3file_find_sync_word(audiomp3_mp3file_obj_t* self) { } STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameInfo* fi) { - int err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); + int err; + do { + err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); + if (err == ERR_MP3_NONE) { + break; + } + CONSUME(self, 1); + mp3file_find_sync_word(self); + } while (!self->eof); return err == ERR_MP3_NONE; } -- cgit v1.2.3 From a63da7a6c0e0537cbefaafb724d722f9587b82a2 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 16 Dec 2019 15:23:41 -0600 Subject: displayio: make 'rotation' property settable --- shared-bindings/displayio/Display.c | 9 ++++++++- shared-bindings/displayio/Display.h | 1 + shared-module/displayio/Display.c | 17 +++++++++++++++++ shared-module/displayio/display_core.c | 9 +++++++++ shared-module/displayio/display_core.h | 2 ++ supervisor/shared/display.c | 1 + 6 files changed, 38 insertions(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c index 5ce7b3581..5759e8ad2 100644 --- a/shared-bindings/displayio/Display.c +++ b/shared-bindings/displayio/Display.c @@ -394,11 +394,18 @@ STATIC mp_obj_t displayio_display_obj_get_rotation(mp_obj_t self_in) { return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_display_get_rotation(self)); } MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_rotation_obj, displayio_display_obj_get_rotation); +STATIC mp_obj_t displayio_display_obj_set_rotation(mp_obj_t self_in, mp_obj_t value) { + displayio_display_obj_t *self = native_display(self_in); + common_hal_displayio_display_set_rotation(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_set_rotation_obj, displayio_display_obj_set_rotation); + const mp_obj_property_t displayio_display_rotation_obj = { .base.type = &mp_type_property, .proxy = {(mp_obj_t)&displayio_display_get_rotation_obj, - (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&displayio_display_set_rotation_obj, (mp_obj_t)&mp_const_none_obj}, }; diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h index ca2b2d476..b82a68ebe 100644 --- a/shared-bindings/displayio/Display.h +++ b/shared-bindings/displayio/Display.h @@ -58,6 +58,7 @@ void common_hal_displayio_display_set_auto_refresh(displayio_display_obj_t* self uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self); uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self); uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self); +void common_hal_displayio_display_set_rotation(displayio_display_obj_t* self, int rotation); bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self); void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness); diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 11db0f8ff..299c8ad35 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -308,10 +308,27 @@ STATIC void _refresh_display(displayio_display_obj_t* self) { displayio_display_core_finish_refresh(&self->core); } +void common_hal_displayio_display_set_rotation(displayio_display_obj_t* self, int rotation){ + bool transposed = (self->core.rotation == 90 || self->core.rotation == 270); + bool will_transposed = (rotation == 90 || rotation == 270); + if(transposed != will_transposed) { + int tmp = self->core.width; + self->core.width = self->core.height; + self->core.height = tmp; + } + displayio_display_core_set_rotation(&self->core, rotation); + supervisor_stop_terminal(); + supervisor_start_terminal(self->core.width, self->core.height); + if (self->core.current_group != NULL) { + displayio_group_update_transform(self->core.current_group, &self->core.transform); + } +} + uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self){ return self->core.rotation; } + bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) { if (!self->auto_refresh && !self->first_manual_refresh) { uint64_t current_time = supervisor_ticks_ms64(); diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c index 658daa8d6..120b70f76 100644 --- a/shared-module/displayio/display_core.c +++ b/shared-module/displayio/display_core.c @@ -86,6 +86,15 @@ void displayio_display_core_construct(displayio_display_core_t* self, self->height = height; self->ram_width = ram_width; self->ram_height = ram_height; + + displayio_display_core_set_rotation(self, rotation); +} + +void displayio_display_core_set_rotation( displayio_display_core_t* self, + int rotation) { + int height = self->height; + int width = self->width; + rotation = rotation % 360; self->rotation = rotation; self->transform.x = 0; diff --git a/shared-module/displayio/display_core.h b/shared-module/displayio/display_core.h index 3a69cd40a..1c3d0f09c 100644 --- a/shared-module/displayio/display_core.h +++ b/shared-module/displayio/display_core.h @@ -68,6 +68,8 @@ uint16_t displayio_display_core_get_height(displayio_display_core_t* self); void displayio_display_core_set_dither(displayio_display_core_t* self, bool dither); bool displayio_display_core_get_dither(displayio_display_core_t* self); +void displayio_display_core_set_rotation(displayio_display_core_t* self, int rotation); + bool displayio_display_core_bus_free(displayio_display_core_t *self); bool displayio_display_core_begin_transaction(displayio_display_core_t* self); void displayio_display_core_end_transaction(displayio_display_core_t* self); diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index c6fda0f16..855432d64 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -81,6 +81,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { grid->pixel_width = width_in_tiles * grid->tile_width; grid->pixel_height = height_in_tiles * grid->tile_height; grid->tiles = tiles; + grid->full_change = true; common_hal_terminalio_terminal_construct(&supervisor_terminal, grid, &supervisor_terminal_font); } -- cgit v1.2.3 From 02154caf24a73ac706505661d487261e70342116 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 23 Dec 2019 09:36:46 -0600 Subject: MP3File: Add a settable ".file" property This enables jeplayer to allocate just one MP3File at startup, rather than have to make repeated large allocations while the application is running. The buffers have to be allocated their theoretical maximum, but that doesn't matter much as all the real-life MP3 files I checked needed that much allocation anyway. --- shared-bindings/audiomp3/MP3File.c | 32 ++++++++++++++++++++++++++ shared-bindings/audiomp3/MP3File.h | 1 + shared-module/audiomp3/MP3File.c | 46 +++++++++++++++++++++++--------------- 3 files changed, 61 insertions(+), 18 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/audiomp3/MP3File.c b/shared-bindings/audiomp3/MP3File.c index f518bae4b..d867643f9 100644 --- a/shared-bindings/audiomp3/MP3File.c +++ b/shared-bindings/audiomp3/MP3File.c @@ -129,6 +129,37 @@ STATIC mp_obj_t audiomp3_mp3file_obj___exit__(size_t n_args, const mp_obj_t *arg } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomp3_mp3file___exit___obj, 4, 4, audiomp3_mp3file_obj___exit__); +//| .. attribute:: file +//| +//| File to play back. +//| +STATIC mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) { + audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return self->file; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_file_obj, audiomp3_mp3file_obj_get_file); + +STATIC mp_obj_t audiomp3_mp3file_obj_set_file(mp_obj_t self_in, mp_obj_t file) { + audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (!MP_OBJ_IS_TYPE(file, &mp_type_fileio)) { + mp_raise_TypeError(translate("file must be a file opened in byte mode")); + } + common_hal_audiomp3_mp3file_set_file(self, file); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_file_obj, audiomp3_mp3file_obj_set_file); + +const mp_obj_property_t audiomp3_mp3file_file_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audiomp3_mp3file_get_file_obj, + (mp_obj_t)&audiomp3_mp3file_set_file_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + + + //| .. attribute:: sample_rate //| //| 32 bit value that dictates how quickly samples are loaded into the DAC @@ -201,6 +232,7 @@ STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiomp3_mp3file___exit___obj) }, // Properties + { MP_ROM_QSTR(MP_QSTR_file), MP_ROM_PTR(&audiomp3_mp3file_file_obj) }, { 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) }, diff --git a/shared-bindings/audiomp3/MP3File.h b/shared-bindings/audiomp3/MP3File.h index adc13ea2c..774d839ff 100644 --- a/shared-bindings/audiomp3/MP3File.h +++ b/shared-bindings/audiomp3/MP3File.h @@ -38,6 +38,7 @@ 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_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file); 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); diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index 0aa4f24a6..5896a2561 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -37,6 +37,8 @@ #include "supervisor/shared/translate.h" #include "lib/mp3/src/mp3common.h" +#define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t)) + /** Fill the input buffer if it is less than half full. * * Returns true if the input buffer contains any useful data, @@ -165,7 +167,6 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self, // 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); @@ -181,40 +182,49 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self, 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 ((intptr_t)buffer & 1) { buffer += 1; buffer_size -= 1; } - if (buffer_size >= 2 * self->frame_buffer_size) { - self->len = buffer_size / 2 / self->frame_buffer_size * self->frame_buffer_size; + if (buffer_size >= 2 * MAX_BUFFER_LEN) { self->buffers[0] = (int16_t*)(void*)buffer; - self->buffers[1] = (int16_t*)(void*)buffer + self->len; + self->buffers[1] = (int16_t*)(void*)(buffer + MAX_BUFFER_LEN); } else { - self->len = 2 * self->frame_buffer_size; - self->buffers[0] = m_malloc(self->len, false); + self->buffers[0] = m_malloc(MAX_BUFFER_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); + self->buffers[1] = m_malloc(MAX_BUFFER_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")); } } + + common_hal_audiomp3_mp3file_set_file(self, file); +} + +void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file) { + self->file = file; + f_lseek(&self->file->fp, 0); + self->inbuf_offset = self->inbuf_length; + self->eof = 0; + self->other_channel = -1; + mp3file_update_inbuf(self); + 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); + self->len = 2 * self->frame_buffer_size; } void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t* self) { -- cgit v1.2.3 From 00628a7dddad07ead8b085e81de90c2dabe71fcc Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 23 Dec 2019 09:36:50 -0600 Subject: MP3File: whitespace --- shared-module/audiomp3/MP3File.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index 5896a2561..549fbcdc0 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -145,7 +145,7 @@ STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameIn do { err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); if (err == ERR_MP3_NONE) { - break; + break; } CONSUME(self, 1); mp3file_find_sync_word(self); -- cgit v1.2.3 From 97bb46c0471b5cb9a0323f06183945d4c711207b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 24 Dec 2019 09:43:15 -0600 Subject: MP3File: tweak buffer handling After adding the ability to change files in an existing MP3File object, it became apparent that at the beginning of a track some part of an existing buffer was playing first. I noticed that in get_buffer, the just-populated buffer wasn't being returned, but the other one was. But still after fixing this, I heard wrong audio at the beginning of a track, so I took the heavy duty approach and zeroed the buffers out. That means there's a remaining bug to chase, which is merely hidden by the memset()s. --- shared-module/audiomp3/MP3File.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index 549fbcdc0..390ba2544 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -215,6 +215,13 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file self->other_channel = -1; mp3file_update_inbuf(self); mp3file_find_sync_word(self); + // It **SHOULD** not be necessary to do this; the buffer should be filled + // with fresh content before it is returned by get_buffer(). The fact that + // this is necessary to avoid a glitch at the start of playback of a second + // track using the same decoder object means there's still a bug in + // get_buffer() that I didn't understand. + memset(self->buffers[0], 0, MAX_BUFFER_LEN); + memset(self->buffers[1], 0, MAX_BUFFER_LEN); MP3FrameInfo fi; if(!mp3file_get_next_frame_info(self, &fi)) { mp_raise_msg(&mp_type_RuntimeError, @@ -290,7 +297,6 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* channel = 0; } - *bufptr = (uint8_t*)(self->buffers[self->buffer_index] + channel); *buffer_length = self->frame_buffer_size; if (channel == self->other_channel) { @@ -299,11 +305,12 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* return GET_BUFFER_MORE_DATA; } - self->other_channel = 1-channel; - self->other_buffer_index = self->buffer_index; self->buffer_index = !self->buffer_index; + self->other_channel = 1-channel; + self->other_buffer_index = self->buffer_index; int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + *bufptr = (uint8_t*)buffer; mp3file_skip_id3v2(self); if (!mp3file_find_sync_word(self)) { -- cgit v1.2.3 From ec22520992723a89dbc57a5e59bf03815df9f509 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 2 Jan 2020 15:23:42 -0600 Subject: MP3File: Add rms_level property This lets a music player show it vu-meter style --- shared-bindings/audiomp3/MP3File.c | 19 +++++++++++++++++++ shared-bindings/audiomp3/MP3File.h | 1 + shared-module/audiomp3/MP3File.c | 11 +++++++++++ shared-module/audiomp3/MP3File.h | 2 ++ 4 files changed, 33 insertions(+) (limited to 'shared-module') diff --git a/shared-bindings/audiomp3/MP3File.c b/shared-bindings/audiomp3/MP3File.c index d867643f9..a02e42364 100644 --- a/shared-bindings/audiomp3/MP3File.c +++ b/shared-bindings/audiomp3/MP3File.c @@ -224,6 +224,24 @@ const mp_obj_property_t audiomp3_mp3file_channel_count_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: rms_level +//| +//| The RMS audio level of a recently played moment of audio. (read only) +//| +STATIC mp_obj_t audiomp3_mp3file_obj_get_rms_level(mp_obj_t self_in) { + audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_float(common_hal_audiomp3_mp3file_get_rms_level(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_rms_level_obj, audiomp3_mp3file_obj_get_rms_level); + +const mp_obj_property_t audiomp3_mp3file_rms_level_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audiomp3_mp3file_get_rms_level_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 @@ -236,6 +254,7 @@ STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = { { 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) }, + { MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_obj) }, }; STATIC MP_DEFINE_CONST_DICT(audiomp3_mp3file_locals_dict, audiomp3_mp3file_locals_dict_table); diff --git a/shared-bindings/audiomp3/MP3File.h b/shared-bindings/audiomp3/MP3File.h index 774d839ff..e6787cb8b 100644 --- a/shared-bindings/audiomp3/MP3File.h +++ b/shared-bindings/audiomp3/MP3File.h @@ -45,5 +45,6 @@ uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t* sel 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); +float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MP3FILE_H diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index 390ba2544..515aa0086 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -29,6 +29,7 @@ #include #include +#include #include "py/mperrno.h" #include "py/runtime.h" @@ -339,3 +340,13 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool si *spacing = 1; } } + +float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self) { + float sumsq = 0.f; + // Assumes no DC component to the audio. Is that a safe assumption? + int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + for(size_t i=0; iframe_buffer_size / sizeof(int16_t); i++) { + sumsq += (float)buffer[i] * buffer[i]; + } + return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t)); +} diff --git a/shared-module/audiomp3/MP3File.h b/shared-module/audiomp3/MP3File.h index 9d99e8d1f..9ee1d0949 100644 --- a/shared-module/audiomp3/MP3File.h +++ b/shared-module/audiomp3/MP3File.h @@ -67,4 +67,6 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool si bool* single_buffer, bool* samples_signed, uint32_t* max_buffer_length, uint8_t* spacing); +float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self); + #endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H -- cgit v1.2.3 From dc729718eb2980e3b92a54e4cc60c7d6b0720e8a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 6 Jan 2020 07:51:41 -0600 Subject: audiomp3: rename to MP3Decoder --- shared-bindings/audiomp3/MP3Decoder.c | 275 ++++++++++++++++++++++++++ shared-bindings/audiomp3/MP3Decoder.h | 50 +++++ shared-bindings/audiomp3/MP3File.c | 277 -------------------------- shared-bindings/audiomp3/MP3File.h | 50 ----- shared-bindings/audiomp3/__init__.c | 6 +- shared-module/audiomp3/MP3Decoder.c | 352 ++++++++++++++++++++++++++++++++++ shared-module/audiomp3/MP3Decoder.h | 72 +++++++ shared-module/audiomp3/MP3File.c | 352 ---------------------------------- shared-module/audiomp3/MP3File.h | 72 ------- 9 files changed, 752 insertions(+), 754 deletions(-) create mode 100644 shared-bindings/audiomp3/MP3Decoder.c create mode 100644 shared-bindings/audiomp3/MP3Decoder.h delete mode 100644 shared-bindings/audiomp3/MP3File.c delete mode 100644 shared-bindings/audiomp3/MP3File.h create mode 100644 shared-module/audiomp3/MP3Decoder.c create mode 100644 shared-module/audiomp3/MP3Decoder.h delete mode 100644 shared-module/audiomp3/MP3File.c delete mode 100644 shared-module/audiomp3/MP3File.h (limited to 'shared-module') diff --git a/shared-bindings/audiomp3/MP3Decoder.c b/shared-bindings/audiomp3/MP3Decoder.c new file mode 100644 index 000000000..a93206e15 --- /dev/null +++ b/shared-bindings/audiomp3/MP3Decoder.c @@ -0,0 +1,275 @@ +/* + * 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 + +#include "lib/utils/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/audiomp3/MP3Decoder.h" +#include "shared-bindings/util.h" +#include "supervisor/shared/translate.h" + +//| .. currentmodule:: audiomp3 +//| +//| :class:`MP3Decoder` -- Load a mp3 file for audio playback +//| ======================================================== +//| +//| An object that decodes MP3 files for playback on an audio device. +//| +//| .. 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.MP3Decoder(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:: file +//| +//| File to play back. +//| +STATIC mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) { + audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return self->file; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_file_obj, audiomp3_mp3file_obj_get_file); + +STATIC mp_obj_t audiomp3_mp3file_obj_set_file(mp_obj_t self_in, mp_obj_t file) { + audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (!MP_OBJ_IS_TYPE(file, &mp_type_fileio)) { + mp_raise_TypeError(translate("file must be a file opened in byte mode")); + } + common_hal_audiomp3_mp3file_set_file(self, file); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_file_obj, audiomp3_mp3file_obj_set_file); + +const mp_obj_property_t audiomp3_mp3file_file_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audiomp3_mp3file_get_file_obj, + (mp_obj_t)&audiomp3_mp3file_set_file_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + + + +//| .. 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}, +}; + +//| .. attribute:: rms_level +//| +//| The RMS audio level of a recently played moment of audio. (read only) +//| +STATIC mp_obj_t audiomp3_mp3file_obj_get_rms_level(mp_obj_t self_in) { + audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_float(common_hal_audiomp3_mp3file_get_rms_level(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_rms_level_obj, audiomp3_mp3file_obj_get_rms_level); + +const mp_obj_property_t audiomp3_mp3file_rms_level_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audiomp3_mp3file_get_rms_level_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_file), MP_ROM_PTR(&audiomp3_mp3file_file_obj) }, + { 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) }, + { MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_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_MP3Decoder, + .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/MP3Decoder.h b/shared-bindings/audiomp3/MP3Decoder.h new file mode 100644 index 000000000..36d525e93 --- /dev/null +++ b/shared-bindings/audiomp3/MP3Decoder.h @@ -0,0 +1,50 @@ +/* + * 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/MP3Decoder.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_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file); +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); +float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MP3FILE_H diff --git a/shared-bindings/audiomp3/MP3File.c b/shared-bindings/audiomp3/MP3File.c deleted file mode 100644 index a02e42364..000000000 --- a/shared-bindings/audiomp3/MP3File.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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 - -#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:: file -//| -//| File to play back. -//| -STATIC mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return self->file; -} -MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_file_obj, audiomp3_mp3file_obj_get_file); - -STATIC mp_obj_t audiomp3_mp3file_obj_set_file(mp_obj_t self_in, mp_obj_t file) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - if (!MP_OBJ_IS_TYPE(file, &mp_type_fileio)) { - mp_raise_TypeError(translate("file must be a file opened in byte mode")); - } - common_hal_audiomp3_mp3file_set_file(self, file); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_file_obj, audiomp3_mp3file_obj_set_file); - -const mp_obj_property_t audiomp3_mp3file_file_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&audiomp3_mp3file_get_file_obj, - (mp_obj_t)&audiomp3_mp3file_set_file_obj, - (mp_obj_t)&mp_const_none_obj}, -}; - - - -//| .. 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}, -}; - -//| .. attribute:: rms_level -//| -//| The RMS audio level of a recently played moment of audio. (read only) -//| -STATIC mp_obj_t audiomp3_mp3file_obj_get_rms_level(mp_obj_t self_in) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return mp_obj_new_float(common_hal_audiomp3_mp3file_get_rms_level(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_rms_level_obj, audiomp3_mp3file_obj_get_rms_level); - -const mp_obj_property_t audiomp3_mp3file_rms_level_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&audiomp3_mp3file_get_rms_level_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_file), MP_ROM_PTR(&audiomp3_mp3file_file_obj) }, - { 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) }, - { MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_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 deleted file mode 100644 index e6787cb8b..000000000 --- a/shared-bindings/audiomp3/MP3File.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file); -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); -float common_hal_audiomp3_mp3file_get_rms_level(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 index 06f852ff1..fb2187669 100644 --- a/shared-bindings/audiomp3/__init__.c +++ b/shared-bindings/audiomp3/__init__.c @@ -29,7 +29,7 @@ #include "py/obj.h" #include "py/runtime.h" -#include "shared-bindings/audiomp3/MP3File.h" +#include "shared-bindings/audiomp3/MP3Decoder.h" //| :mod:`audiomp3` --- Support for MP3-compressed audio files //| ========================================================== @@ -44,12 +44,12 @@ //| .. toctree:: //| :maxdepth: 3 //| -//| MP3File +//| MP3Decoder //| 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) }, + { MP_ROM_QSTR(MP_QSTR_MP3Decoder), MP_ROM_PTR(&audiomp3_mp3file_type) }, }; STATIC MP_DEFINE_CONST_DICT(audiomp3_module_globals, audiomp3_module_globals_table); diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c new file mode 100644 index 000000000..515aa0086 --- /dev/null +++ b/shared-module/audiomp3/MP3Decoder.c @@ -0,0 +1,352 @@ +/* + * 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 +#include +#include + +#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" + +#define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t)) + +/** 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) + +// http://id3.org/d3v2.3.0 +// http://id3.org/id3v2.3.0 +STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) { + mp3file_update_inbuf(self); + if (BYTES_LEFT(self) < 10) { + return; + } + uint8_t *data = READ_PTR(self); + if (!( + data[0] == 'I' && + data[1] == 'D' && + data[2] == '3' && + data[3] != 0xff && + data[4] != 0xff && + (data[5] & 0x1f) == 0 && + (data[6] & 0x80) == 0 && + (data[7] & 0x80) == 0 && + (data[8] & 0x80) == 0 && + (data[9] & 0x80) == 0)) { + return; + } + uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]); + size += 10; // size excludes the "header" (but not the "extended header") + // First, deduct from size whatever is left in buffer + uint32_t to_consume = MIN(size, BYTES_LEFT(self)); + CONSUME(self, to_consume); + size -= to_consume; + + // Next, seek in the file after the header + f_lseek(&self->file->fp, f_tell(&self->file->fp) + size); + return; +} + +/* 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; + do { + err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); + if (err == ERR_MP3_NONE) { + break; + } + CONSUME(self, 1); + mp3file_find_sync_word(self); + } while (!self->eof); + 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->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")); + } + + if ((intptr_t)buffer & 1) { + buffer += 1; buffer_size -= 1; + } + if (buffer_size >= 2 * MAX_BUFFER_LEN) { + self->buffers[0] = (int16_t*)(void*)buffer; + self->buffers[1] = (int16_t*)(void*)(buffer + MAX_BUFFER_LEN); + } else { + self->buffers[0] = m_malloc(MAX_BUFFER_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(MAX_BUFFER_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")); + } + } + + common_hal_audiomp3_mp3file_set_file(self, file); +} + +void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file) { + self->file = file; + f_lseek(&self->file->fp, 0); + self->inbuf_offset = self->inbuf_length; + self->eof = 0; + self->other_channel = -1; + mp3file_update_inbuf(self); + mp3file_find_sync_word(self); + // It **SHOULD** not be necessary to do this; the buffer should be filled + // with fresh content before it is returned by get_buffer(). The fact that + // this is necessary to avoid a glitch at the start of playback of a second + // track using the same decoder object means there's still a bug in + // get_buffer() that I didn't understand. + memset(self->buffers[0], 0, MAX_BUFFER_LEN); + memset(self->buffers[1], 0, MAX_BUFFER_LEN); + 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); + self->len = 2 * self->frame_buffer_size; +} + +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; + self->other_channel = -1; + mp3file_update_inbuf(self); + mp3file_skip_id3v2(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 (!self->inbuf) { + return GET_BUFFER_ERROR; + } + if (!single_channel) { + channel = 0; + } + + *buffer_length = self->frame_buffer_size; + + if (channel == self->other_channel) { + *bufptr = (uint8_t*)(self->buffers[self->other_buffer_index] + channel); + self->other_channel = -1; + return GET_BUFFER_MORE_DATA; + } + + + self->buffer_index = !self->buffer_index; + self->other_channel = 1-channel; + self->other_buffer_index = self->buffer_index; + int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + *bufptr = (uint8_t*)buffer; + + mp3file_skip_id3v2(self); + 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; + } +} + +float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self) { + float sumsq = 0.f; + // Assumes no DC component to the audio. Is that a safe assumption? + int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + for(size_t i=0; iframe_buffer_size / sizeof(int16_t); i++) { + sumsq += (float)buffer[i] * buffer[i]; + } + return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t)); +} diff --git a/shared-module/audiomp3/MP3Decoder.h b/shared-module/audiomp3/MP3Decoder.h new file mode 100644 index 000000000..9ee1d0949 --- /dev/null +++ b/shared-module/audiomp3/MP3Decoder.h @@ -0,0 +1,72 @@ +/* + * 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; + int16_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; + + int8_t other_channel; + int8_t other_buffer_index; +} 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); + +float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c deleted file mode 100644 index 515aa0086..000000000 --- a/shared-module/audiomp3/MP3File.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * 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 -#include -#include - -#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" - -#define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t)) - -/** 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) - -// http://id3.org/d3v2.3.0 -// http://id3.org/id3v2.3.0 -STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) { - mp3file_update_inbuf(self); - if (BYTES_LEFT(self) < 10) { - return; - } - uint8_t *data = READ_PTR(self); - if (!( - data[0] == 'I' && - data[1] == 'D' && - data[2] == '3' && - data[3] != 0xff && - data[4] != 0xff && - (data[5] & 0x1f) == 0 && - (data[6] & 0x80) == 0 && - (data[7] & 0x80) == 0 && - (data[8] & 0x80) == 0 && - (data[9] & 0x80) == 0)) { - return; - } - uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]); - size += 10; // size excludes the "header" (but not the "extended header") - // First, deduct from size whatever is left in buffer - uint32_t to_consume = MIN(size, BYTES_LEFT(self)); - CONSUME(self, to_consume); - size -= to_consume; - - // Next, seek in the file after the header - f_lseek(&self->file->fp, f_tell(&self->file->fp) + size); - return; -} - -/* 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; - do { - err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); - if (err == ERR_MP3_NONE) { - break; - } - CONSUME(self, 1); - mp3file_find_sync_word(self); - } while (!self->eof); - 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->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")); - } - - if ((intptr_t)buffer & 1) { - buffer += 1; buffer_size -= 1; - } - if (buffer_size >= 2 * MAX_BUFFER_LEN) { - self->buffers[0] = (int16_t*)(void*)buffer; - self->buffers[1] = (int16_t*)(void*)(buffer + MAX_BUFFER_LEN); - } else { - self->buffers[0] = m_malloc(MAX_BUFFER_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(MAX_BUFFER_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")); - } - } - - common_hal_audiomp3_mp3file_set_file(self, file); -} - -void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file) { - self->file = file; - f_lseek(&self->file->fp, 0); - self->inbuf_offset = self->inbuf_length; - self->eof = 0; - self->other_channel = -1; - mp3file_update_inbuf(self); - mp3file_find_sync_word(self); - // It **SHOULD** not be necessary to do this; the buffer should be filled - // with fresh content before it is returned by get_buffer(). The fact that - // this is necessary to avoid a glitch at the start of playback of a second - // track using the same decoder object means there's still a bug in - // get_buffer() that I didn't understand. - memset(self->buffers[0], 0, MAX_BUFFER_LEN); - memset(self->buffers[1], 0, MAX_BUFFER_LEN); - 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); - self->len = 2 * self->frame_buffer_size; -} - -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; - self->other_channel = -1; - mp3file_update_inbuf(self); - mp3file_skip_id3v2(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 (!self->inbuf) { - return GET_BUFFER_ERROR; - } - if (!single_channel) { - channel = 0; - } - - *buffer_length = self->frame_buffer_size; - - if (channel == self->other_channel) { - *bufptr = (uint8_t*)(self->buffers[self->other_buffer_index] + channel); - self->other_channel = -1; - return GET_BUFFER_MORE_DATA; - } - - - self->buffer_index = !self->buffer_index; - self->other_channel = 1-channel; - self->other_buffer_index = self->buffer_index; - int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; - *bufptr = (uint8_t*)buffer; - - mp3file_skip_id3v2(self); - 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; - } -} - -float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self) { - float sumsq = 0.f; - // Assumes no DC component to the audio. Is that a safe assumption? - int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; - for(size_t i=0; iframe_buffer_size / sizeof(int16_t); i++) { - sumsq += (float)buffer[i] * buffer[i]; - } - return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t)); -} diff --git a/shared-module/audiomp3/MP3File.h b/shared-module/audiomp3/MP3File.h deleted file mode 100644 index 9ee1d0949..000000000 --- a/shared-module/audiomp3/MP3File.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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; - int16_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; - - int8_t other_channel; - int8_t other_buffer_index; -} 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); - -float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self); - -#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H -- cgit v1.2.3 From dd6010a17ef8e12e1cb3f36721b205cc1cb8eee9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 6 Jan 2020 13:35:43 -0600 Subject: Fix more build problems --- py/circuitpy_defns.mk | 2 +- shared-module/audiomp3/MP3Decoder.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'shared-module') diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 8dd4fc6b1..38b41c619 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -322,7 +322,7 @@ SRC_SHARED_MODULE_ALL = \ audiomixer/Mixer.c \ audiomixer/MixerVoice.c \ audiomp3/__init__.c \ - audiomp3/MP3File.c \ + audiomp3/MP3Decoder.c \ bitbangio/I2C.c \ bitbangio/OneWire.c \ bitbangio/SPI.c \ diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c index 515aa0086..30357c616 100644 --- a/shared-module/audiomp3/MP3Decoder.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -25,7 +25,7 @@ * THE SOFTWARE. */ -#include "shared-bindings/audiomp3/MP3File.h" +#include "shared-bindings/audiomp3/MP3Decoder.h" #include #include @@ -34,7 +34,7 @@ #include "py/mperrno.h" #include "py/runtime.h" -#include "shared-module/audiomp3/MP3File.h" +#include "shared-module/audiomp3/MP3Decoder.h" #include "supervisor/shared/translate.h" #include "lib/mp3/src/mp3common.h" -- cgit v1.2.3 From e6869c8983ba732f77076242c86041aa77a047e0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 12 Jan 2020 10:12:42 -0600 Subject: mixer: factor out mix_one_voice --- shared-module/audiomixer/Mixer.c | 159 ++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 77 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index afa3a0632..f3a435a09 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -295,6 +295,87 @@ static inline uint32_t mult16signed(uint32_t val, int32_t mul) { #endif } +static void mix_one_voice(audiomixer_mixer_obj_t* self, + audiomixer_mixervoice_obj_t* voice, bool voices_active, + uint32_t* word_buffer, uint32_t length) { + uint32_t j = 0; + bool voice_done = voice->sample == NULL; + for (uint32_t i = 0; i < length; i++) { + if (!voice_done && j >= voice->buffer_length) { + if (!voice->more_data) { + if (voice->loop) { + audiosample_reset_buffer(voice->sample, false, 0); + } else { + voice->sample = NULL; + voice_done = true; + } + } + if (!voice_done) { + // Load another buffer + audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length); + // Track length in terms of words. + voice->buffer_length /= sizeof(uint32_t); + voice->more_data = result == GET_BUFFER_MORE_DATA; + j = 0; + } + } + // First active voice gets copied over verbatim. + uint32_t sample_value; + if (voice_done) { + // Exit early if another voice already set all samples once. + if (voices_active) { + continue; + } + sample_value = 0; + if (!self->samples_signed) { + if (self->bits_per_sample == 8) { + sample_value = 0x7f7f7f7f; + } else { + sample_value = 0x7fff7fff; + } + } + } else { + sample_value = voice->remaining_buffer[j]; + } + + // apply the mixer level + if (!self->samples_signed) { + if (self->bits_per_sample == 8) { + sample_value = mult8unsigned(sample_value, voice->level); + } else { + sample_value = mult16unsigned(sample_value, voice->level); + } + } else { + if (self->bits_per_sample == 8) { + sample_value = mult8signed(sample_value, voice->level); + } else { + sample_value = mult16signed(sample_value, voice->level); + } + } + + if (!voices_active) { + word_buffer[i] = sample_value; + } else { + if (self->bits_per_sample == 8) { + if (self->samples_signed) { + word_buffer[i] = add8signed(word_buffer[i], sample_value); + } else { + word_buffer[i] = add8unsigned(word_buffer[i], sample_value); + } + } else { + if (self->samples_signed) { + word_buffer[i] = add16signed(word_buffer[i], sample_value); + } else { + word_buffer[i] = add16unsigned(word_buffer[i], sample_value); + } + } + } + j++; + } + voice->buffer_length -= j; + voice->remaining_buffer += j; +} + audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* self, bool single_channel, uint8_t channel, @@ -325,83 +406,7 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* for (int32_t v = 0; v < self->voice_count; v++) { audiomixer_mixervoice_obj_t* voice = MP_OBJ_TO_PTR(self->voice[v]); - uint32_t j = 0; - bool voice_done = voice->sample == NULL; - for (uint32_t i = 0; i < self->len / sizeof(uint32_t); i++) { - if (!voice_done && j >= voice->buffer_length) { - if (!voice->more_data) { - if (voice->loop) { - audiosample_reset_buffer(voice->sample, false, 0); - } else { - voice->sample = NULL; - voice_done = true; - } - } - if (!voice_done) { - // Load another buffer - audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length); - // Track length in terms of words. - voice->buffer_length /= sizeof(uint32_t); - voice->more_data = result == GET_BUFFER_MORE_DATA; - j = 0; - } - } - // First active voice gets copied over verbatim. - uint32_t sample_value; - if (voice_done) { - // Exit early if another voice already set all samples once. - if (voices_active) { - continue; - } - sample_value = 0; - if (!self->samples_signed) { - if (self->bits_per_sample == 8) { - sample_value = 0x7f7f7f7f; - } else { - sample_value = 0x7fff7fff; - } - } - } else { - sample_value = voice->remaining_buffer[j]; - } - - // apply the mixer level - if (!self->samples_signed) { - if (self->bits_per_sample == 8) { - sample_value = mult8unsigned(sample_value, voice->level); - } else { - sample_value = mult16unsigned(sample_value, voice->level); - } - } else { - if (self->bits_per_sample == 8) { - sample_value = mult8signed(sample_value, voice->level); - } else { - sample_value = mult16signed(sample_value, voice->level); - } - } - - if (!voices_active) { - word_buffer[i] = sample_value; - } else { - if (self->bits_per_sample == 8) { - if (self->samples_signed) { - word_buffer[i] = add8signed(word_buffer[i], sample_value); - } else { - word_buffer[i] = add8unsigned(word_buffer[i], sample_value); - } - } else { - if (self->samples_signed) { - word_buffer[i] = add16signed(word_buffer[i], sample_value); - } else { - word_buffer[i] = add16unsigned(word_buffer[i], sample_value); - } - } - } - j++; - } - voice->buffer_length -= j; - voice->remaining_buffer += j; - + mix_one_voice(self, voice, voices_active, word_buffer, self->len / sizeof(uint32_t)); voices_active = true; } -- cgit v1.2.3 From 449dbea4567dbc27a01ae695b9cebf776a6927f0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 12 Jan 2020 11:02:47 -0600 Subject: Mixer: Rework for performance, particularly of the S16 case This removes downscaling (halving-add) when multiple voices are being mixed. To avoid clipping, and get similar behavior to before, set the "level" of each voice to (1/voice_count). Slow paths that were applicable to only M0 chips were removed. As a side effect, the internal volume representation is now 0 .. 0x8000 (inclusive), which additionally makes a level of exactly 0.5 representable. Testing performed, on PyGamer: For all 4 data cases, for stereo and mono, for 1 and 2 voices, play pure sign waves represented as RawSamples and view the result on a scope and through headphones. Also, scope the amount of time spent in background tasks. Code size: growth of +272 bytes Performance (time in background task when mixing 2 stereo 16-bit voices): 76us per down from 135us (once per ~2.9ms long term average) (Decrease from 4.7% to 2.4% of all CPU time) --- shared-module/audiomixer/Mixer.c | 332 +++++++++++----------------------- shared-module/audiomixer/MixerVoice.c | 6 +- shared-module/audiomixer/MixerVoice.h | 2 +- 3 files changed, 109 insertions(+), 231 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index f3a435a09..3c1c9a491 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -101,213 +101,60 @@ void audiomixer_mixer_reset_buffer(audiomixer_mixer_obj_t* self, } } -uint32_t add8signed(uint32_t a, uint32_t b) { - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - return __SHADD8(a, b); - #else - uint32_t result = 0; - for (int8_t i = 0; i < 4; i++) { - int8_t ai = a >> (sizeof(int8_t) * 8 * i); - int8_t bi = b >> (sizeof(int8_t) * 8 * i); - int32_t intermediate = (int32_t) ai + bi / 2; - if (intermediate > CHAR_MAX) { - intermediate = CHAR_MAX; - } else if (intermediate < CHAR_MIN) { - intermediate = CHAR_MIN; - } - result |= ((uint32_t) intermediate & 0xff) << (sizeof(int8_t) * 8 * i); - } - return result; - #endif +__attribute__((always_inline)) +static inline uint32_t add16signed(uint32_t a, uint32_t b) { + return __QADD16(a, b); } -uint32_t add8unsigned(uint32_t a, uint32_t b) { - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - return __UHADD8(a, b); - #else - uint32_t result = 0; - for (int8_t i = 0; i < 4; i++) { - uint8_t ai = (a >> (sizeof(uint8_t) * 8 * i)); - uint8_t bi = (b >> (sizeof(uint8_t) * 8 * i)); - int32_t intermediate = (int32_t) (ai + bi) / 2; - if (intermediate > UCHAR_MAX) { - intermediate = UCHAR_MAX; - } - result |= ((uint32_t) intermediate & 0xff) << (sizeof(uint8_t) * 8 * i); - } - return result; - #endif +__attribute__((always_inline)) +static inline uint32_t mult16signed(uint32_t val, int32_t mul) { + mul <<= 16; + int32_t hi, lo; + enum { bits = 16 }; // saturate to 16 bits + enum { shift = 15 }; // shift is done automatically + asm volatile("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul), "r" (val)); + asm volatile("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul), "r" (val)); + asm volatile("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); + asm volatile("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); + asm volatile("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack + return val; } -uint32_t add16signed(uint32_t a, uint32_t b) { - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - return __SHADD16(a, b); - #else - uint32_t result = 0; - for (int8_t i = 0; i < 2; i++) { - int16_t ai = a >> (sizeof(int16_t) * 8 * i); - int16_t bi = b >> (sizeof(int16_t) * 8 * i); - int32_t intermediate = (int32_t) ai + bi / 2; - if (intermediate > SHRT_MAX) { - intermediate = SHRT_MAX; - } else if (intermediate < SHRT_MIN) { - intermediate = SHRT_MIN; - } - result |= (((uint32_t) intermediate) & 0xffff) << (sizeof(int16_t) * 8 * i); - } - return result; - #endif +static inline uint32_t tounsigned8(uint32_t val) { + return __UADD8(val, 0x80808080); } -uint32_t add16unsigned(uint32_t a, uint32_t b) { - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - return __UHADD16(a, b); - #else - uint32_t result = 0; - for (int8_t i = 0; i < 2; i++) { - int16_t ai = (a >> (sizeof(uint16_t) * 8 * i)) - 0x8000; - int16_t bi = (b >> (sizeof(uint16_t) * 8 * i)) - 0x8000; - int32_t intermediate = (int32_t) ai + bi / 2; - if (intermediate > USHRT_MAX) { - intermediate = USHRT_MAX; - } - result |= ((uint32_t) intermediate & 0xffff) << (sizeof(int16_t) * 8 * i); - } - return result; - #endif +static inline uint32_t tounsigned16(uint32_t val) { + return __UADD16(val, 0x80008000); } -static inline uint32_t mult8unsigned(uint32_t val, int32_t mul) { - // if mul == 0, no need in wasting cycles - if (mul == 0) { - return 0; - } - /* TODO: workout ARMv7 instructions - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - return val; - #else*/ - uint32_t result = 0; - float mod_mul = (float) mul / (float) ((1<<15)-1); - for (int8_t i = 0; i < 4; i++) { - uint8_t ai = val >> (sizeof(uint8_t) * 8 * i); - int32_t intermediate = ai * mod_mul; - if (intermediate > SHRT_MAX) { - intermediate = SHRT_MAX; - } - result |= ((uint32_t) intermediate & 0xff) << (sizeof(uint8_t) * 8 * i); - } - - return result; - //#endif -} - -static inline uint32_t mult8signed(uint32_t val, int32_t mul) { - // if mul == 0, no need in wasting cycles - if (mul == 0) { - return 0; - } - /* TODO: workout ARMv7 instructions - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - return val; - #else - */ - uint32_t result = 0; - float mod_mul = (float)mul / (float)((1<<15)-1); - for (int8_t i = 0; i < 4; i++) { - int16_t ai = val >> (sizeof(int8_t) * 8 * i); - int32_t intermediate = ai * mod_mul; - if (intermediate > CHAR_MAX) { - intermediate = CHAR_MAX; - } else if (intermediate < CHAR_MIN) { - intermediate = CHAR_MIN; - } - result |= (((uint32_t) intermediate) & 0xff) << (sizeof(int16_t) * 8 * i); - } - return result; - //#endif +static inline uint32_t tosigned16(uint32_t val) { + return __UADD16(val, 0x80008000); } -//TODO: -static inline uint32_t mult16unsigned(uint32_t val, int32_t mul) { - // if mul == 0, no need in wasting cycles - if (mul == 0) { - return 0; - } - /* TODO: the below ARMv7m instructions "work", but the amplitude is much higher/louder - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - // there is no unsigned equivalent to the 'SMULWx' ARMv7 Thumb function, - // so we have to do it by hand. - uint32_t lo = val & 0xffff; - uint32_t hi = val >> 16; - //mp_printf(&mp_plat_print, "pre-asm: (mul: %d)\n\tval: %x\tlo: %x\thi: %x\n", mul, val, lo, hi); - uint32_t val_lo; - asm volatile("mul %0, %1, %2" : "=r" (val_lo) : "r" (mul), "r" (lo)); - asm volatile("mla %0, %1, %2, %3" : "=r" (val) : "r" (mul), "r" (hi), "r" (val_lo)); - //mp_printf(&mp_plat_print, "post-asm:\n\tval: %x\tlo: %x\n\n", val, val_lo); - return val; - #else - */ - uint32_t result = 0; - float mod_mul = (float)mul / (float)((1<<15)-1); - for (int8_t i = 0; i < 2; i++) { - int16_t ai = (val >> (sizeof(uint16_t) * 8 * i)) - 0x8000; - int32_t intermediate = ai * mod_mul; - if (intermediate > SHRT_MAX) { - intermediate = SHRT_MAX; - } else if (intermediate < SHRT_MIN) { - intermediate = SHRT_MIN; - } - result |= (((uint32_t) intermediate) + 0x8000) << (sizeof(int16_t) * 8 * i); - } - return result; - //#endif +static inline uint32_t unpack8(uint16_t val) { + return ((val & 0xff00) << 16) | ((val & 0x00ff) << 8); } -static inline uint32_t mult16signed(uint32_t val, int32_t mul) { - // if mul == 0, no need in wasting cycles - if (mul == 0) { - return 0; - } - #if (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) //Cortex-M4 w/FPU - int32_t hi, lo; - enum { bits = 16 }; // saturate to 16 bits - enum { shift = 0 }; // shift is done automatically - asm volatile("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul), "r" (val)); - asm volatile("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul), "r" (val)); - asm volatile("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); - asm volatile("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); - asm volatile("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack - return val; - #else - uint32_t result = 0; - float mod_mul = (float)mul / (float)((1<<15)-1); - for (int8_t i = 0; i < 2; i++) { - int16_t ai = val >> (sizeof(int16_t) * 8 * i); - int32_t intermediate = ai * mod_mul; - if (intermediate > SHRT_MAX) { - intermediate = SHRT_MAX; - } else if (intermediate < SHRT_MIN) { - intermediate = SHRT_MIN; - } - result |= (((uint32_t) intermediate) & 0xffff) << (sizeof(int16_t) * 8 * i); - } - return result; - #endif +static inline uint32_t pack8(uint32_t val) { + return ((val & 0xff000000) >> 16) | ((val & 0xff00) >> 8); } +#define LIKELY(x) (__builtin_expect(!!(x), 1)) +#define UNLIKELY(x) (__builtin_expect(!!(x), 0)) static void mix_one_voice(audiomixer_mixer_obj_t* self, audiomixer_mixervoice_obj_t* voice, bool voices_active, uint32_t* word_buffer, uint32_t length) { - uint32_t j = 0; bool voice_done = voice->sample == NULL; - for (uint32_t i = 0; i < length; i++) { - if (!voice_done && j >= voice->buffer_length) { + while (!voice_done && length != 0) { + if (voice->buffer_length == 0) { if (!voice->more_data) { if (voice->loop) { audiosample_reset_buffer(voice->sample, false, 0); } else { voice->sample = NULL; voice_done = true; + break; } } if (!voice_done) { @@ -316,64 +163,81 @@ static void mix_one_voice(audiomixer_mixer_obj_t* self, // Track length in terms of words. voice->buffer_length /= sizeof(uint32_t); voice->more_data = result == GET_BUFFER_MORE_DATA; - j = 0; } } + + uint32_t n = MIN(voice->buffer_length, length); + uint32_t *src = voice->remaining_buffer; + uint16_t level = voice->level; + // First active voice gets copied over verbatim. - uint32_t sample_value; - if (voice_done) { - // Exit early if another voice already set all samples once. - if (voices_active) { - continue; - } - sample_value = 0; - if (!self->samples_signed) { - if (self->bits_per_sample == 8) { - sample_value = 0x7f7f7f7f; + if (!voices_active) { + if (LIKELY(self->bits_per_sample == 16)) { + if (LIKELY(self->samples_signed)) { + for (uint32_t i = 0; iremaining_buffer[j]; - } - - // apply the mixer level - if (!self->samples_signed) { - if (self->bits_per_sample == 8) { - sample_value = mult8unsigned(sample_value, voice->level); - } else { - sample_value = mult16unsigned(sample_value, voice->level); - } - } else { - if (self->bits_per_sample == 8) { - sample_value = mult8signed(sample_value, voice->level); } else { - sample_value = mult16signed(sample_value, voice->level); + uint16_t *hword_buffer = (uint16_t*)word_buffer; + uint16_t *hsrc = (uint16_t*)src; + for (uint32_t i = 0; isamples_signed)) { + word = tosigned16(word); + } + word = mult16signed(word, level); + hword_buffer[i] = pack8(word); + } } - } - - if (!voices_active) { - word_buffer[i] = sample_value; } else { - if (self->bits_per_sample == 8) { - if (self->samples_signed) { - word_buffer[i] = add8signed(word_buffer[i], sample_value); + if (LIKELY(self->bits_per_sample == 16)) { + if (LIKELY(self->samples_signed)) { + for (uint32_t i = 0; isamples_signed) { - word_buffer[i] = add16signed(word_buffer[i], sample_value); - } else { - word_buffer[i] = add16unsigned(word_buffer[i], sample_value); + uint16_t *hword_buffer = (uint16_t*)word_buffer; + uint16_t *hsrc = (uint16_t*)src; + for (uint32_t i = 0; isamples_signed)) { + word = tosigned16(word); + } + word = mult16signed(word, level); + word = add16signed(word, unpack8(hword_buffer[i])); + hword_buffer[i] = pack8(word); } } } - j++; + length -= n; + word_buffer += n; + voice->remaining_buffer += n; + voice->buffer_length -= n; + } + + if (length && !voices_active) { + uint32_t sample_value = self->bits_per_sample == 8 + ? 0x80808080 : 0x80008000; + for (uint32_t i = 0; ibuffer_length -= j; - voice->remaining_buffer += j; } audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* self, @@ -403,13 +267,27 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* } self->use_first_buffer = !self->use_first_buffer; bool voices_active = false; + uint32_t length = self->len / sizeof(uint32_t); + for (int32_t v = 0; v < self->voice_count; v++) { audiomixer_mixervoice_obj_t* voice = MP_OBJ_TO_PTR(self->voice[v]); - mix_one_voice(self, voice, voices_active, word_buffer, self->len / sizeof(uint32_t)); + mix_one_voice(self, voice, voices_active, word_buffer, length); voices_active = true; } + if (!self->samples_signed) { + if (self->bits_per_sample == 16) { + for (uint32_t i = 0; i < length; i++) { + word_buffer[i] = tounsigned16(word_buffer[i]); + } + } else { + for (uint32_t i = 0; i < length; i++) { + word_buffer[i] = tounsigned8(word_buffer[i]); + } + } + } + self->read_count += 1; } else if (!self->use_first_buffer) { *buffer = (uint8_t*) self->first_buffer; diff --git a/shared-module/audiomixer/MixerVoice.c b/shared-module/audiomixer/MixerVoice.c index ff05dc93e..9be104afc 100644 --- a/shared-module/audiomixer/MixerVoice.c +++ b/shared-module/audiomixer/MixerVoice.c @@ -34,7 +34,7 @@ void common_hal_audiomixer_mixervoice_construct(audiomixer_mixervoice_obj_t *self) { self->sample = NULL; - self->level = ((1 << 15) - 1); + self->level = 1 << 15; } void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t* self, audiomixer_mixer_obj_t *parent) { @@ -42,11 +42,11 @@ void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t* se } float common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t* self) { - return ((float) self->level / ((1 << 15) - 1)); + return ((float) self->level / (1 << 15)); } void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t* self, float level) { - self->level = level * ((1 << 15)-1); + self->level = level * (1 << 15); } void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t* self, mp_obj_t sample, bool loop) { diff --git a/shared-module/audiomixer/MixerVoice.h b/shared-module/audiomixer/MixerVoice.h index efac19156..a85316e3d 100644 --- a/shared-module/audiomixer/MixerVoice.h +++ b/shared-module/audiomixer/MixerVoice.h @@ -39,7 +39,7 @@ typedef struct { bool more_data; uint32_t* remaining_buffer; uint32_t buffer_length; - int16_t level; + uint16_t level; } audiomixer_mixervoice_obj_t; -- cgit v1.2.3 From 982c63a71712fc9092b35fca3ef34e4b404c03cb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 20 Jan 2020 14:08:32 -0600 Subject: Mixer: use MP_LIKELY macro instead of locally brewed one --- shared-module/audiomixer/Mixer.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 3c1c9a491..9370adf01 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -140,8 +140,6 @@ static inline uint32_t pack8(uint32_t val) { return ((val & 0xff000000) >> 16) | ((val & 0xff00) >> 8); } -#define LIKELY(x) (__builtin_expect(!!(x), 1)) -#define UNLIKELY(x) (__builtin_expect(!!(x), 0)) static void mix_one_voice(audiomixer_mixer_obj_t* self, audiomixer_mixervoice_obj_t* voice, bool voices_active, uint32_t* word_buffer, uint32_t length) { @@ -172,8 +170,8 @@ static void mix_one_voice(audiomixer_mixer_obj_t* self, // First active voice gets copied over verbatim. if (!voices_active) { - if (LIKELY(self->bits_per_sample == 16)) { - if (LIKELY(self->samples_signed)) { + if (MP_LIKELY(self->bits_per_sample == 16)) { + if (MP_LIKELY(self->samples_signed)) { for (uint32_t i = 0; isamples_signed)) { + if (MP_LIKELY(!self->samples_signed)) { word = tosigned16(word); } word = mult16signed(word, level); @@ -198,8 +196,8 @@ static void mix_one_voice(audiomixer_mixer_obj_t* self, } } } else { - if (LIKELY(self->bits_per_sample == 16)) { - if (LIKELY(self->samples_signed)) { + if (MP_LIKELY(self->bits_per_sample == 16)) { + if (MP_LIKELY(self->samples_signed)) { for (uint32_t i = 0; isamples_signed)) { + if (MP_LIKELY(!self->samples_signed)) { word = tosigned16(word); } word = mult16signed(word, level); -- cgit v1.2.3 From b4ddee2bb6ae40a73efe15e30de8d33ab9ce8011 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 20 Jan 2020 14:06:39 -0600 Subject: Mixer: rename function based on review comment --- shared-module/audiomixer/Mixer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-module') diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 9370adf01..4a72dab28 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -140,7 +140,7 @@ static inline uint32_t pack8(uint32_t val) { return ((val & 0xff000000) >> 16) | ((val & 0xff00) >> 8); } -static void mix_one_voice(audiomixer_mixer_obj_t* self, +static void mix_down_one_voice(audiomixer_mixer_obj_t* self, audiomixer_mixervoice_obj_t* voice, bool voices_active, uint32_t* word_buffer, uint32_t length) { bool voice_done = voice->sample == NULL; @@ -270,7 +270,7 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t* for (int32_t v = 0; v < self->voice_count; v++) { audiomixer_mixervoice_obj_t* voice = MP_OBJ_TO_PTR(self->voice[v]); - mix_one_voice(self, voice, voices_active, word_buffer, length); + mix_down_one_voice(self, voice, voices_active, word_buffer, length); voices_active = true; } -- cgit v1.2.3 From 2afca4e942df2f4aa656f6c8a6aa84de581682c9 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 24 Jan 2020 14:25:36 -0500 Subject: Fix flash-display conflict error --- ports/stm32f4/boards/meowbit_v121/mpconfigboard.h | 1 + ports/stm32f4/common-hal/busio/SPI.c | 12 ++++++++++++ py/circuitpy_mpconfig.h | 1 + shared-bindings/board/__init__.h | 2 ++ shared-module/board/__init__.c | 11 +++++++++++ shared-module/displayio/__init__.c | 5 +++++ 6 files changed, 32 insertions(+) (limited to 'shared-module') diff --git a/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h b/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h index 72d4f1c88..bf738e961 100644 --- a/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h +++ b/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h @@ -38,6 +38,7 @@ #define BOARD_OSC_DIV 12 #define BOARD_NO_VBUS_SENSE //#define BOARD_VTOR_DEFER //Leave VTOR relocation to bootloader +#define SHOW_FLASH_SPI // On-board flash #define SPI_FLASH_MOSI_PIN (&pin_PB15) diff --git a/ports/stm32f4/common-hal/busio/SPI.c b/ports/stm32f4/common-hal/busio/SPI.c index afc6cfcbd..e00b5e9f0 100644 --- a/ports/stm32f4/common-hal/busio/SPI.c +++ b/ports/stm32f4/common-hal/busio/SPI.c @@ -428,31 +428,43 @@ STATIC void spi_clock_disable(uint8_t mask) { #ifdef SPI1 if (mask & (1 << 0)) { __HAL_RCC_SPI1_CLK_DISABLE(); + __HAL_RCC_SPI1_FORCE_RESET(); + __HAL_RCC_SPI1_RELEASE_RESET(); } #endif #ifdef SPI2 if (mask & (1 << 1)) { __HAL_RCC_SPI2_CLK_DISABLE(); + __HAL_RCC_SPI2_FORCE_RESET(); + __HAL_RCC_SPI2_RELEASE_RESET(); } #endif #ifdef SPI3 if (mask & (1 << 2)) { __HAL_RCC_SPI3_CLK_DISABLE(); + __HAL_RCC_SPI3_FORCE_RESET(); + __HAL_RCC_SPI3_RELEASE_RESET(); } #endif #ifdef SPI4 if (mask & (1 << 3)) { __HAL_RCC_SPI4_CLK_DISABLE(); + __HAL_RCC_SPI4_FORCE_RESET(); + __HAL_RCC_SPI4_RELEASE_RESET(); } #endif #ifdef SPI5 if (mask & (1 << 4)) { __HAL_RCC_SPI5_CLK_DISABLE(); + __HAL_RCC_SPI5_FORCE_RESET(); + __HAL_RCC_SPI5_RELEASE_RESET(); } #endif #ifdef SPI6 if (mask & (1 << 5)) { __HAL_RCC_SPI6_CLK_DISABLE(); + __HAL_RCC_SPI6_FORCE_RESET(); + __HAL_RCC_SPI6_RELEASE_RESET(); } #endif } diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 5b705a088..b5d9bb9a8 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -296,6 +296,7 @@ extern const struct _mp_obj_module_t board_module; #define BOARD_I2C (defined(DEFAULT_I2C_BUS_SDA) && defined(DEFAULT_I2C_BUS_SCL)) #define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI)) #define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX)) +#define BOARD_INTERNAL_SPI (defined(SHOW_FLASH_SPI)) // I2C and SPI are always allocated off the heap. diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h index a9b652ba8..2842057ad 100644 --- a/shared-bindings/board/__init__.h +++ b/shared-bindings/board/__init__.h @@ -37,6 +37,8 @@ mp_obj_t common_hal_board_get_i2c(void); mp_obj_t common_hal_board_create_i2c(void); MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj); +mp_obj_t common_hal_board_get_internal_spi(void); + mp_obj_t common_hal_board_get_spi(void); mp_obj_t common_hal_board_create_spi(void); MP_DECLARE_CONST_FUN_OBJ_0(board_spi_obj); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 914bc4313..8d87a98eb 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -29,6 +29,8 @@ #include "mpconfigboard.h" #include "py/runtime.h" +#include "supervisor/spi_flash_api.h" + #if CIRCUITPY_BUSIO #include "shared-bindings/busio/I2C.h" #include "shared-bindings/busio/SPI.h" @@ -89,6 +91,15 @@ mp_obj_t common_hal_board_create_spi(void) { } #endif +#if BOARD_INTERNAL_SPI +//Provide a reference to the internal SPI, if required. +mp_obj_t common_hal_board_get_internal_spi(void) { + //TODO: can we change the name of this without having to change every instance of spi in every + //flash file? + return (mp_obj_t)(&spi); +} +#endif + #if BOARD_UART mp_obj_t common_hal_board_get_uart(void) { return MP_STATE_VM(shared_uart_bus); diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index af22cb0df..795de7b87 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -100,6 +100,11 @@ void reset_displays(void) { continue; } #endif + #if BOARD_INTERNAL_SPI + if (original_spi == common_hal_board_get_internal_spi()) { + continue; + } + #endif memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t)); fourwire->bus = &fourwire->inline_bus; // Check for other displays that use the same spi bus and swap them too. -- cgit v1.2.3 From 70932cab4223463816974e57945f6f803bbe7371 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 24 Jan 2020 14:33:28 -0500 Subject: Simplify the flash-display conflict fix --- ports/stm32f4/boards/meowbit_v121/mpconfigboard.h | 2 +- py/circuitpy_mpconfig.h | 1 - shared-bindings/board/__init__.h | 2 -- shared-module/board/__init__.c | 11 ----------- shared-module/displayio/__init__.c | 7 +++++-- 5 files changed, 6 insertions(+), 17 deletions(-) (limited to 'shared-module') diff --git a/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h b/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h index bf738e961..2d8ff8761 100644 --- a/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h +++ b/ports/stm32f4/boards/meowbit_v121/mpconfigboard.h @@ -38,7 +38,7 @@ #define BOARD_OSC_DIV 12 #define BOARD_NO_VBUS_SENSE //#define BOARD_VTOR_DEFER //Leave VTOR relocation to bootloader -#define SHOW_FLASH_SPI +#define BOARD_USE_INTERNAL_SPI // On-board flash #define SPI_FLASH_MOSI_PIN (&pin_PB15) diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index b5d9bb9a8..5b705a088 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -296,7 +296,6 @@ extern const struct _mp_obj_module_t board_module; #define BOARD_I2C (defined(DEFAULT_I2C_BUS_SDA) && defined(DEFAULT_I2C_BUS_SCL)) #define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI)) #define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX)) -#define BOARD_INTERNAL_SPI (defined(SHOW_FLASH_SPI)) // I2C and SPI are always allocated off the heap. diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h index 2842057ad..a9b652ba8 100644 --- a/shared-bindings/board/__init__.h +++ b/shared-bindings/board/__init__.h @@ -37,8 +37,6 @@ mp_obj_t common_hal_board_get_i2c(void); mp_obj_t common_hal_board_create_i2c(void); MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj); -mp_obj_t common_hal_board_get_internal_spi(void); - mp_obj_t common_hal_board_get_spi(void); mp_obj_t common_hal_board_create_spi(void); MP_DECLARE_CONST_FUN_OBJ_0(board_spi_obj); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 8d87a98eb..914bc4313 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -29,8 +29,6 @@ #include "mpconfigboard.h" #include "py/runtime.h" -#include "supervisor/spi_flash_api.h" - #if CIRCUITPY_BUSIO #include "shared-bindings/busio/I2C.h" #include "shared-bindings/busio/SPI.h" @@ -91,15 +89,6 @@ mp_obj_t common_hal_board_create_spi(void) { } #endif -#if BOARD_INTERNAL_SPI -//Provide a reference to the internal SPI, if required. -mp_obj_t common_hal_board_get_internal_spi(void) { - //TODO: can we change the name of this without having to change every instance of spi in every - //flash file? - return (mp_obj_t)(&spi); -} -#endif - #if BOARD_UART mp_obj_t common_hal_board_get_uart(void) { return MP_STATE_VM(shared_uart_bus); diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 795de7b87..8d9f14883 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -16,6 +16,9 @@ #include "supervisor/shared/display.h" #include "supervisor/memory.h" +#include "supervisor/spi_flash_api.h" +#include "py/mpconfig.h" + primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT]; // Check for recursive calls to displayio_background. @@ -100,8 +103,8 @@ void reset_displays(void) { continue; } #endif - #if BOARD_INTERNAL_SPI - if (original_spi == common_hal_board_get_internal_spi()) { + #ifdef BOARD_USE_INTERNAL_SPI + if (original_spi == (mp_obj_t)(&spi)) { continue; } #endif -- cgit v1.2.3 From 39971794dd48b9dba0be389b22d4eae8ecd30f7d Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 24 Jan 2020 18:23:07 -0800 Subject: Encapsulate buffers inside PixelBuf and refactor it. --- shared-bindings/_pixelbuf/PixelBuf.c | 327 ++++++++++++++--------------------- shared-bindings/_pixelbuf/PixelBuf.h | 35 ++-- shared-bindings/_pixelbuf/__init__.c | 35 +--- shared-bindings/_pixelbuf/__init__.h | 1 - shared-bindings/_pixelbuf/types.h | 47 ----- shared-module/_pixelbuf/PixelBuf.c | 299 ++++++++++++++++++++++++-------- shared-module/_pixelbuf/PixelBuf.h | 37 +++- 7 files changed, 407 insertions(+), 374 deletions(-) delete mode 100644 shared-bindings/_pixelbuf/types.h (limited to 'shared-module') diff --git a/shared-bindings/_pixelbuf/PixelBuf.c b/shared-bindings/_pixelbuf/PixelBuf.c index 3e9319047..61b4c9ae0 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.c +++ b/shared-bindings/_pixelbuf/PixelBuf.c @@ -36,13 +36,14 @@ #include -#include "PixelBuf.h" -#include "shared-bindings/_pixelbuf/types.h" -#include "../../shared-module/_pixelbuf/PixelBuf.h" +#include "shared-bindings/_pixelbuf/PixelBuf.h" +#include "shared-module/_pixelbuf/PixelBuf.h" #include "shared-bindings/digitalio/DigitalInOut.h" extern const int32_t colorwheel(float pos); +static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t* parsed); + //| .. currentmodule:: pixelbuf //| //| :class:`PixelBuf` -- A fast RGB[W] pixel buffer for LED and similar devices @@ -50,140 +51,109 @@ extern const int32_t colorwheel(float pos); //| //| :class:`~_pixelbuf.PixelBuf` implements an RGB[W] bytearray abstraction. //| -//| .. class:: PixelBuf(size, buf, byteorder="BGR", brightness=0, rawbuf=None, offset=0, auto_write=False) +//| .. class:: PixelBuf(size, *, byteorder="BGR", brightness=0, auto_write=False, header=b"", trailer=b"") //| //| Create a PixelBuf object of the specified size, byteorder, and bits per pixel. //| -//| When given a second bytearray (``rawbuf``), changing brightness adjusts the -//| brightness of all members of ``buf``. -//| -//| When only given ``buf``, ``brightness`` applies to the next pixel assignment. +//| When brightness is less than 1.0, a second buffer will be used to store the color values +//| before they are adjusted for brightness. //| -//| When ``P`` (pwm duration) is present as the 4th character of the byteorder -//| string, the 4th value in the tuple/list for a pixel is the individual pixel +//| When ``P`` (pwm duration) is present as the 4th character of the byteorder +//| string, the 4th value in the tuple/list for a pixel is the individual pixel //| brightness (0.0-1.0) and will enable a Dotstar compatible 1st byte in the //| output buffer (``buf``). //| //| :param ~int size: Number of pixelsx -//| :param ~bytearray buf: Bytearray in which to store pixel data //| :param ~str byteorder: Byte order string (such as "BGR" or "PBGR") //| :param ~float brightness: Brightness (0 to 1.0, default 1.0) -//| :param ~bytearray rawbuf: Bytearray in which to store raw pixel data (before brightness adjustment) -//| :param ~int offset: Offset from start of buffer (default 0) //| :param ~bool auto_write: Whether to automatically write pixels (Default False) +//| :param bytes header: Sequence of bytes to always send before pixel values. +//| :param bytes trailer: Sequence of bytes to always send after pixel values. //| STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 2, MP_OBJ_FUN_ARGS_MAX, true); - enum { ARG_size, ARG_buf, ARG_byteorder, ARG_brightness, ARG_rawbuf, ARG_offset, - ARG_auto_write }; + mp_arg_check_num(n_args, kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true); + enum { ARG_size, ARG_byteorder, ARG_brightness, ARG_auto_write, ARG_header, ARG_trailer }; static const mp_arg_t allowed_args[] = { { MP_QSTR_size, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_byteorder, MP_ARG_OBJ, { .u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_BGR) } }, - { MP_QSTR_brightness, MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_rawbuf, MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_offset, MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_auto_write, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_byteorder, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_BGR) } }, + { MP_QSTR_brightness, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_auto_write, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_header, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_trailer, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - const char *byteorder = NULL; pixelbuf_byteorder_details_t byteorder_details; - size_t bo_len; - if (!MP_OBJ_IS_STR(args[ARG_byteorder].u_obj)) + parse_byteorder(args[ARG_byteorder].u_obj, &byteorder_details); + + mp_buffer_info_t header_bufinfo; + mp_buffer_info_t trailer_bufinfo; + + if (!mp_get_buffer(args[ARG_header].u_obj, &header_bufinfo, MP_BUFFER_READ)) { + header_bufinfo.buf = NULL; + header_bufinfo.len = 0; + } + if (!mp_get_buffer(args[ARG_trailer].u_obj, &trailer_bufinfo, MP_BUFFER_READ)) { + trailer_bufinfo.buf = NULL; + trailer_bufinfo.len = 0; + } + + float brightness = 1.0; + if (args[ARG_brightness].u_obj != mp_const_none) { + brightness = mp_obj_get_float(args[ARG_brightness].u_obj); + if (brightness < 0) { + brightness = 0; + } else if (brightness > 1) { + brightness = 1; + } + } + + // Validation complete, allocate and populate object. + pixelbuf_pixelbuf_obj_t *self = m_new_obj(pixelbuf_pixelbuf_obj_t); + self->base.type = &pixelbuf_pixelbuf_type; + common_hal__pixelbuf_pixelbuf_construct(self, args[ARG_size].u_int, + &byteorder_details, brightness, args[ARG_auto_write].u_bool, header_bufinfo.buf, + header_bufinfo.len, trailer_bufinfo.buf, trailer_bufinfo.len); + + return MP_OBJ_FROM_PTR(self); +} + +static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t* parsed) { + if (!MP_OBJ_IS_STR(byteorder_obj)) { mp_raise_TypeError(translate("byteorder is not a string")); + } - byteorder = mp_obj_str_get_data(args[ARG_byteorder].u_obj, &bo_len); - if (bo_len < 3 || bo_len > 4) + size_t bo_len; + const char *byteorder = mp_obj_str_get_data(byteorder_obj, &bo_len); + if (bo_len < 3 || bo_len > 4) { mp_raise_ValueError(translate("Invalid byteorder string")); - byteorder_details.order = args[ARG_byteorder].u_obj; + } + parsed->order_string = byteorder_obj; - byteorder_details.bpp = bo_len; + parsed->bpp = bo_len; char *dotstar = strchr(byteorder, 'P'); char *r = strchr(byteorder, 'R'); char *g = strchr(byteorder, 'G'); char *b = strchr(byteorder, 'B'); char *w = strchr(byteorder, 'W'); int num_chars = (dotstar ? 1 : 0) + (w ? 1 : 0) + (r ? 1 : 0) + (g ? 1 : 0) + (b ? 1 : 0); - if ((num_chars < byteorder_details.bpp) || !(r && b && g)) + if ((num_chars < parsed->bpp) || !(r && b && g)) { mp_raise_ValueError(translate("Invalid byteorder string")); - byteorder_details.is_dotstar = dotstar ? true : false; - byteorder_details.has_white = w ? true : false; - byteorder_details.byteorder.r = r - byteorder; - byteorder_details.byteorder.g = g - byteorder; - byteorder_details.byteorder.b = b - byteorder; - byteorder_details.byteorder.w = w ? w - byteorder : 0; + } + parsed->is_dotstar = dotstar ? true : false; + parsed->has_white = w ? true : false; + parsed->byteorder.r = r - byteorder; + parsed->byteorder.g = g - byteorder; + parsed->byteorder.b = b - byteorder; + parsed->byteorder.w = w ? w - byteorder : 0; // The dotstar brightness byte is always first (as it goes with the pixel start bits) if (dotstar && byteorder[0] != 'P') { mp_raise_ValueError(translate("Invalid byteorder string")); } - if (byteorder_details.has_white && byteorder_details.is_dotstar) + if (parsed->has_white && parsed->is_dotstar) { mp_raise_ValueError(translate("Invalid byteorder string")); - - size_t effective_bpp = byteorder_details.is_dotstar ? 4 : byteorder_details.bpp; // Always 4 for DotStar - size_t bytes = args[ARG_size].u_int * effective_bpp; - size_t offset = args[ARG_offset].u_int; - mp_buffer_info_t bufinfo, rawbufinfo; - - mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ | MP_BUFFER_WRITE); - bool two_buffers = args[ARG_rawbuf].u_obj != mp_const_none; - if (two_buffers) { - mp_get_buffer_raise(args[ARG_rawbuf].u_obj, &rawbufinfo, MP_BUFFER_READ | MP_BUFFER_WRITE); - if (rawbufinfo.len != bufinfo.len) { - mp_raise_ValueError(translate("rawbuf is not the same size as buf")); - } - } - - if (bytes + offset > bufinfo.len) - mp_raise_ValueError_varg(translate("buf is too small. need %d bytes"), bytes + offset); - - // Validation complete, allocate and populate object. - pixelbuf_pixelbuf_obj_t *self = m_new_obj(pixelbuf_pixelbuf_obj_t); - - self->base.type = &pixelbuf_pixelbuf_type; - self->pixels = args[ARG_size].u_int; - self->bytes = bytes; - self->byteorder = byteorder_details; // Copied because we modify for dotstar - self->bytearray = args[ARG_buf].u_obj; - self->two_buffers = two_buffers; - self->rawbytearray = two_buffers ? args[ARG_rawbuf].u_obj : NULL; - self->offset = offset; - self->buf = (uint8_t *)bufinfo.buf + offset; - self->rawbuf = two_buffers ? (uint8_t *)rawbufinfo.buf + offset : NULL; - self->pixel_step = effective_bpp; - self->auto_write = args[ARG_auto_write].u_bool; - - if (args[ARG_brightness].u_obj == mp_const_none) { - self->brightness = 1.0; - } else { - self->brightness = mp_obj_get_float(args[ARG_brightness].u_obj); - if (self->brightness < 0) - self->brightness = 0; - else if (self->brightness > 1) - self->brightness = 1; } - - if (self->byteorder.is_dotstar) { - // Initialize the buffer with the dotstar start bytes. - // Note: Header and end must be setup by caller - for (uint i = 0; i < self->pixels * 4; i += 4) { - self->buf[i] = DOTSTAR_LED_START_FULL_BRIGHT; - if (two_buffers) { - self->rawbuf[i] = DOTSTAR_LED_START_FULL_BRIGHT; - } - } - } - - return MP_OBJ_FROM_PTR(self); -} - - -// Helper to ensure we have the native super class instead of a subclass. -static pixelbuf_pixelbuf_obj_t* native_pixelbuf(mp_obj_t pixelbuf_obj) { - mp_obj_t native_pixelbuf = mp_instance_cast_to_native_base(pixelbuf_obj, &pixelbuf_pixelbuf_type); - mp_obj_assert_native_inited(native_pixelbuf); - return MP_OBJ_TO_PTR(native_pixelbuf); } //| .. attribute:: bpp @@ -191,8 +161,7 @@ static pixelbuf_pixelbuf_obj_t* native_pixelbuf(mp_obj_t pixelbuf_obj) { //| The number of bytes per pixel in the buffer (read-only) //| STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_bpp(mp_obj_t self_in) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - return mp_obj_new_int_from_uint(self->byteorder.bpp); + return MP_OBJ_NEW_SMALL_INT(common_hal__pixelbuf_pixelbuf_get_bpp(self_in)); } MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_bpp_obj, pixelbuf_pixelbuf_obj_get_bpp); @@ -207,30 +176,24 @@ const mp_obj_property_t pixelbuf_pixelbuf_bpp_obj = { //| .. attribute:: brightness //| //| Float value between 0 and 1. Output brightness. -//| If the PixelBuf was allocated with two both a buf and a rawbuf, -//| setting this value causes a recomputation of the values in buf. -//| If only a buf was provided, then the brightness only applies to -//| future pixel changes. -//| In DotStar mode +//| +//| When brightness is less than 1.0, a second buffer will be used to store the color values +//| before they are adjusted for brightness. //| STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_brightness(mp_obj_t self_in) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - return mp_obj_new_float(self->brightness); + return mp_obj_new_float(common_hal__pixelbuf_pixelbuf_get_brightness(self_in)); } MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_brightness_obj, pixelbuf_pixelbuf_obj_get_brightness); STATIC mp_obj_t pixelbuf_pixelbuf_obj_set_brightness(mp_obj_t self_in, mp_obj_t value) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - self->brightness = mp_obj_float_get(value); - if (self->brightness > 1) - self->brightness = 1; - else if (self->brightness < 0) - self->brightness = 0; - if (self->two_buffers) - pixelbuf_recalculate_brightness(self); - if (self->auto_write) - pixelbuf_call_show(self_in); + mp_float_t brightness = mp_obj_float_get(value); + if (brightness > 1) { + brightness = 1; + } else if (brightness < 0) { + brightness = 0; + } + common_hal__pixelbuf_pixelbuf_set_brightness(self_in, brightness); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_set_brightness_obj, pixelbuf_pixelbuf_obj_set_brightness); @@ -242,37 +205,18 @@ const mp_obj_property_t pixelbuf_pixelbuf_brightness_obj = { (mp_obj_t)&mp_const_none_obj}, }; -void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self) { - uint8_t *buf = (uint8_t *)self->buf; - uint8_t *rawbuf = (uint8_t *)self->rawbuf; - // Compensate for shifted buffer (bpp=3 dotstar) - for (uint i = 0; i < self->bytes; i++) { - // Don't adjust per-pixel luminance bytes in dotstar mode - if (!self->byteorder.is_dotstar || (i % 4 != 0)) - buf[i] = rawbuf[i] * self->brightness; - } -} - -mp_obj_t pixelbuf_call_show(mp_obj_t self_in) { - mp_obj_t dest[2]; - mp_load_method(self_in, MP_QSTR_show, dest); - return mp_call_method_n_kw(0, 0, dest); -} - //| .. attribute:: auto_write //| //| Whether to automatically write the pixels after each update. //| STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_auto_write(mp_obj_t self_in) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - return mp_obj_new_bool(self->auto_write); + return mp_obj_new_bool(common_hal__pixelbuf_pixelbuf_get_auto_write(self_in)); } MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_auto_write_obj, pixelbuf_pixelbuf_obj_get_auto_write); STATIC mp_obj_t pixelbuf_pixelbuf_obj_set_auto_write(mp_obj_t self_in, mp_obj_t value) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - self->auto_write = mp_obj_is_true(value); + common_hal__pixelbuf_pixelbuf_set_auto_write(self_in, mp_obj_is_true(value)); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_set_auto_write_obj, pixelbuf_pixelbuf_obj_set_auto_write); @@ -284,33 +228,12 @@ const mp_obj_property_t pixelbuf_pixelbuf_auto_write_obj = { (mp_obj_t)&mp_const_none_obj}, }; - -//| .. attribute:: buf -//| -//| (read-only) bytearray of pixel data after brightness adjustment. If an offset was provided -//| then this bytearray is the subset of the bytearray passed in that represents the -//| actual pixels. -//| -STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_buf(mp_obj_t self_in) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - return mp_obj_new_bytearray_by_ref(self->bytes, self->buf); -} -MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_buf_obj, pixelbuf_pixelbuf_obj_get_buf); - -const mp_obj_property_t pixelbuf_pixelbuf_buf_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&pixelbuf_pixelbuf_get_buf_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj}, -}; - //| .. attribute:: byteorder //| //| byteorder string for the buffer (read-only) //| STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_byteorder(mp_obj_t self_in) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - return self->byteorder.order; + return common_hal__pixelbuf_pixelbuf_get_byteorder_string(self_in); } MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_byteorder_str, pixelbuf_pixelbuf_obj_get_byteorder); @@ -322,32 +245,49 @@ const mp_obj_property_t pixelbuf_pixelbuf_byteorder_str = { }; STATIC mp_obj_t pixelbuf_pixelbuf_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_const_true; - case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->pixels); + case MP_UNARY_OP_LEN: + return MP_OBJ_NEW_SMALL_INT(common_hal__pixelbuf_pixelbuf_get_len(self_in)); default: return MP_OBJ_NULL; // op not supported } } //| .. method:: show() //| -//| Must be implemented in subclasses. +//| Transmits the color data to the pixels so that they are shown. This is done automatically +//| when `auto_write` is True. //| STATIC mp_obj_t pixelbuf_pixelbuf_show(mp_obj_t self_in) { - mp_raise_NotImplementedError(NULL); + common_hal__pixelbuf_pixelbuf_show(self_in); + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_show_obj, pixelbuf_pixelbuf_show); +//| .. function:: fill(color) +//| +//| Fills the given pixelbuf with the given color. +//| + +STATIC mp_obj_t pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t value) { + common_hal__pixelbuf_pixelbuf_fill(self_in, value); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_fill_obj, pixelbuf_pixelbuf_fill); + //| .. method:: __getitem__(index) //| -//| Returns the pixel value at the given index. +//| Returns the pixel value at the given index as a tuple of (Red, Green, Blue[, White]) values +//| between 0 and 255. //| //| .. method:: __setitem__(index, value) //| -//| Sets the pixel value at the given index. +//| Sets the pixel value at the given index. Value can either be a tuple of (Red, Green, Blue +//| [, White]) values between 0 and 255 or an integer where the red, green and blue values are +//| packed into the lower three bytes (0xRRGGBB). //| STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { @@ -356,32 +296,34 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp return MP_OBJ_NULL; // op not supported } - pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); - if (0) { #if MICROPY_PY_BUILTINS_SLICE } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { mp_bound_slice_t slice; - mp_seq_get_fast_slice_indexes(self->pixels, index_in, &slice); + size_t length = common_hal__pixelbuf_pixelbuf_get_len(self_in); + mp_seq_get_fast_slice_indexes(length, index_in, &slice); - if ((slice.stop * self->pixel_step) > self->bytes) - mp_raise_IndexError(translate("Range out of bounds")); - if (slice.step < 0) + if (slice.step < 0) { mp_raise_IndexError(translate("Negative step not supported")); + } if (value == MP_OBJ_SENTINEL) { // Get size_t len = slice.stop - slice.start; if (slice.step > 1) { len = (len / slice.step) + (len % slice.step ? 1 : 0); } - uint8_t *readbuf = self->two_buffers ? self->rawbuf : self->buf; - return pixelbuf_get_pixel_array(readbuf + slice.start, len, &self->byteorder, self->pixel_step, slice.step, self->byteorder.is_dotstar); + mp_obj_tuple_t* t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); + for (uint i = 0; i < len; i++) { + t->items[i] = common_hal__pixelbuf_pixelbuf_get_pixel(self_in, i * slice.step); + } + return MP_OBJ_FROM_PTR(t); } else { // Set #if MICROPY_PY_ARRAY_SLICE_ASSIGN - if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple))) + if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple))) { mp_raise_ValueError(translate("tuple/list required on RHS")); + } size_t dst_len = (slice.stop - slice.start); if (slice.step > 1) { @@ -398,21 +340,12 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp num_items = l->len; src_objs = l->items; } - if (num_items != dst_len) + if (num_items != dst_len) { mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."), dst_len, num_items); - - size_t target_i = slice.start; - for (size_t i = slice.start; target_i < slice.stop; i++, target_i += slice.step) { - mp_obj_t *item = src_objs[i-slice.start]; - if (MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple) || MP_OBJ_IS_INT(value)) { - pixelbuf_set_pixel(self->buf + (target_i * self->pixel_step), - self->two_buffers ? self->rawbuf + (i * self->pixel_step) : NULL, - self->brightness, item, &self->byteorder, self->byteorder.is_dotstar); - } } - if (self->auto_write) - pixelbuf_call_show(self_in); + + common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.stop, slice.step, src_objs); return mp_const_none; #else return MP_OBJ_NULL; // op not supported @@ -420,19 +353,13 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp } #endif } else { // Single index rather than slice. - size_t index = mp_get_index(self->base.type, self->pixels, index_in, false); - size_t offset = (index * self->pixel_step); - if (offset > self->bytes) - mp_raise_IndexError(translate("Pixel beyond bounds of buffer")); + size_t length = common_hal__pixelbuf_pixelbuf_get_len(self_in); + size_t index = mp_get_index(mp_obj_get_type(self_in), length, index_in, false); if (value == MP_OBJ_SENTINEL) { // Get - uint8_t *pixelstart = (uint8_t *)(self->two_buffers ? self->rawbuf : self->buf) + offset; - return pixelbuf_get_pixel(pixelstart, &self->byteorder, self->byteorder.is_dotstar); + return common_hal__pixelbuf_pixelbuf_get_pixel(self_in, index); } else { // Store - pixelbuf_set_pixel(self->buf + offset, self->two_buffers ? self->rawbuf + offset : NULL, - self->brightness, value, &self->byteorder, self->byteorder.is_dotstar); - if (self->auto_write) - pixelbuf_call_show(self_in); + common_hal__pixelbuf_pixelbuf_set_pixel(self_in, index, value); return mp_const_none; } } @@ -442,9 +369,9 @@ STATIC const mp_rom_map_elem_t pixelbuf_pixelbuf_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_auto_write), MP_ROM_PTR(&pixelbuf_pixelbuf_auto_write_obj)}, { MP_ROM_QSTR(MP_QSTR_bpp), MP_ROM_PTR(&pixelbuf_pixelbuf_bpp_obj)}, { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&pixelbuf_pixelbuf_brightness_obj)}, - { MP_ROM_QSTR(MP_QSTR_buf), MP_ROM_PTR(&pixelbuf_pixelbuf_buf_obj)}, { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_PTR(&pixelbuf_pixelbuf_byteorder_str)}, { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&pixelbuf_pixelbuf_show_obj)}, + { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&pixelbuf_pixelbuf_fill_obj)}, }; STATIC MP_DEFINE_CONST_DICT(pixelbuf_pixelbuf_locals_dict, pixelbuf_pixelbuf_locals_dict_table); diff --git a/shared-bindings/_pixelbuf/PixelBuf.h b/shared-bindings/_pixelbuf/PixelBuf.h index 691da3cd3..68d6d4eef 100644 --- a/shared-bindings/_pixelbuf/PixelBuf.h +++ b/shared-bindings/_pixelbuf/PixelBuf.h @@ -27,27 +27,26 @@ #ifndef CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H #define CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H -#include "shared-bindings/_pixelbuf/types.h" +#include "shared-module/_pixelbuf/PixelBuf.h" const mp_obj_type_t pixelbuf_pixelbuf_type; -typedef struct { - mp_obj_base_t base; - size_t pixels; - size_t bytes; - size_t pixel_step; - pixelbuf_byteorder_details_t byteorder; - mp_obj_t bytearray; - mp_obj_t rawbytearray; - mp_float_t brightness; - bool two_buffers; - size_t offset; - uint8_t *rawbuf; - uint8_t *buf; - bool auto_write; -} pixelbuf_pixelbuf_obj_t; +void common_hal__pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size_t n, + pixelbuf_byteorder_details_t* byteorder, mp_float_t brightness, bool auto_write, uint8_t* header, + size_t header_len, uint8_t* trailer, size_t trailer_len); -void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self); -mp_obj_t pixelbuf_call_show(mp_obj_t self_in); +// These take mp_obj_t because they are called on subclasses of PixelBuf. +uint8_t common_hal__pixelbuf_pixelbuf_get_bpp(mp_obj_t self); +mp_float_t common_hal__pixelbuf_pixelbuf_get_brightness(mp_obj_t self); +void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self, mp_float_t brightness); +bool common_hal__pixelbuf_pixelbuf_get_auto_write(mp_obj_t self); +void common_hal__pixelbuf_pixelbuf_set_auto_write(mp_obj_t self, bool auto_write); +size_t common_hal__pixelbuf_pixelbuf_get_len(mp_obj_t self_in); +mp_obj_t common_hal__pixelbuf_pixelbuf_get_byteorder_string(mp_obj_t self); +void common_hal__pixelbuf_pixelbuf_fill(mp_obj_t self, mp_obj_t item); +void common_hal__pixelbuf_pixelbuf_show(mp_obj_t self); +mp_obj_t common_hal__pixelbuf_pixelbuf_get_pixel(mp_obj_t self, size_t index); +void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self, size_t index, mp_obj_t item); +void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, size_t stop, size_t step, mp_obj_t* values); #endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index ed264f3bb..424ed23e4 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -29,11 +29,8 @@ #include "py/runtime.h" #include "py/objproperty.h" -#include "types.h" -#include "__init__.h" - -#include "PixelBuf.h" -#include "../../shared-module/_pixelbuf/PixelBuf.h" +#include "shared-bindings/_pixelbuf/__init__.h" +#include "shared-bindings/_pixelbuf/PixelBuf.h" //| :mod:`_pixelbuf` --- Fast RGB(W) pixel buffer and helpers @@ -82,39 +79,15 @@ const int32_t colorwheel(float pos) { } } - -//| .. function:: fill(pixelbuf, color) -//| -//| Fills the given pixelbuf with the given color. -//| - -STATIC mp_obj_t pixelbuf_fill(mp_obj_t pixelbuf_in, mp_obj_t value) { - mp_obj_t obj = mp_instance_cast_to_native_base(pixelbuf_in, &pixelbuf_pixelbuf_type); - if (obj == MP_OBJ_NULL) - mp_raise_TypeError(translate("Expected a PixelBuf instance")); - pixelbuf_pixelbuf_obj_t *pixelbuf = MP_OBJ_TO_PTR(obj); - - for (size_t offset = 0; offset < pixelbuf->bytes; offset+= pixelbuf->pixel_step) { - pixelbuf_set_pixel(pixelbuf->buf + offset, pixelbuf->two_buffers ? (pixelbuf->rawbuf + offset) : NULL, - pixelbuf->brightness, value, &pixelbuf->byteorder, pixelbuf->byteorder.is_dotstar); - } - if (pixelbuf->auto_write) - pixelbuf_call_show(pixelbuf_in); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_fill_obj, pixelbuf_fill); - - STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pixelbuf) }, { MP_ROM_QSTR(MP_QSTR_PixelBuf), MP_ROM_PTR(&pixelbuf_pixelbuf_type) }, { MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_PTR(&pixelbuf_wheel_obj) }, - { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&pixelbuf_fill_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pixelbuf_module_globals, pixelbuf_module_globals_table); const mp_obj_module_t pixelbuf_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&pixelbuf_module_globals, + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&pixelbuf_module_globals, }; diff --git a/shared-bindings/_pixelbuf/__init__.h b/shared-bindings/_pixelbuf/__init__.h index f70ffe508..0e8c4a37f 100644 --- a/shared-bindings/_pixelbuf/__init__.h +++ b/shared-bindings/_pixelbuf/__init__.h @@ -30,6 +30,5 @@ #include "common-hal/digitalio/DigitalInOut.h" const int32_t colorwheel(float pos); -extern void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* gpio, uint8_t *pixels, uint32_t numBytes); #endif //CP_SHARED_BINDINGS_PIXELBUF_INIT_H diff --git a/shared-bindings/_pixelbuf/types.h b/shared-bindings/_pixelbuf/types.h deleted file mode 100644 index f7dc1a109..000000000 --- a/shared-bindings/_pixelbuf/types.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Roy Hooper - * - * 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 CIRCUITPYTHON_PIXELBUF_TYPES_H -#define CIRCUITPYTHON_PIXELBUF_TYPES_H - -//| :orphan: - -typedef struct { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t w; -} pixelbuf_rgbw_t; - -typedef struct { - uint8_t bpp; - pixelbuf_rgbw_t byteorder; - bool has_white; - bool is_dotstar; - mp_obj_t *order; -} pixelbuf_byteorder_details_t; - -#endif // CIRCUITPYTHON_PIXELBUF_TYPES_H diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index 020151bc3..ab5bcb441 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -26,95 +26,256 @@ #include "py/obj.h" -#include "py/objarray.h" +#include "py/objstr.h" +#include "py/objtype.h" #include "py/runtime.h" -#include "PixelBuf.h" +#include "shared-bindings/_pixelbuf/PixelBuf.h" #include -void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder) { - buf[byteorder->byteorder.r] = value >> 16 & 0xff; - buf[byteorder->byteorder.g] = (value >> 8) & 0xff; - buf[byteorder->byteorder.b] = value & 0xff; - if (byteorder->bpp == 4 && byteorder->has_white && - (buf[byteorder->byteorder.r] == buf[byteorder->byteorder.g] && - buf[byteorder->byteorder.r] == buf[byteorder->byteorder.b])) { - buf[byteorder->byteorder.w] = buf[byteorder->byteorder.r]; - buf[byteorder->byteorder.r] = buf[byteorder->byteorder.g] = buf[byteorder->byteorder.b] = 0; - } -} - -void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar) { - if (MP_OBJ_IS_INT(item)) { - uint8_t *target = rawbuf ? rawbuf : buf; - pixelbuf_set_pixel_int(target, mp_obj_get_int_truncated(item), byteorder); - if (dotstar) { - buf[0] = DOTSTAR_LED_START_FULL_BRIGHT; - if (rawbuf) - rawbuf[0] = DOTSTAR_LED_START_FULL_BRIGHT; +// Helper to ensure we have the native super class instead of a subclass. +static pixelbuf_pixelbuf_obj_t* native_pixelbuf(mp_obj_t pixelbuf_obj) { + mp_obj_t native_pixelbuf = mp_instance_cast_to_native_base(pixelbuf_obj, &pixelbuf_pixelbuf_type); + mp_obj_assert_native_inited(native_pixelbuf); + return MP_OBJ_TO_PTR(native_pixelbuf); +} + +void common_hal__pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size_t n, + pixelbuf_byteorder_details_t* byteorder, mp_float_t brightness, bool auto_write, + uint8_t* header, size_t header_len, uint8_t* trailer, size_t trailer_len) { + + self->pixel_count = n; + self->byteorder = *byteorder; // Copied because we modify for dotstar + self->bytes_per_pixel = byteorder->is_dotstar ? 4 : byteorder->bpp; + self->auto_write = false; + + size_t pixel_len = self->pixel_count * self->bytes_per_pixel; + self->transmit_buffer_obj = mp_obj_new_bytes_of_zeros(header_len + pixel_len + trailer_len); + mp_obj_str_t *o = MP_OBJ_TO_PTR(self->transmit_buffer_obj); + + // Abuse the bytes object a bit by mutating it's data by dropping the const. If the user's + // Python code holds onto it, they'll find out that it changes. At least this way it isn't + // mutable by the code itself. + uint8_t* transmit_buffer = (uint8_t*) o->data; + memcpy(transmit_buffer, header, header_len); + memcpy(transmit_buffer + header_len + pixel_len, trailer, trailer_len); + self->post_brightness_buffer = transmit_buffer + header_len; + + if (self->byteorder.is_dotstar) { + // Initialize the buffer with the dotstar start bytes. + // Note: Header and end must be setup by caller + for (uint i = 0; i < self->pixel_count * 4; i += 4) { + self->post_brightness_buffer[i] = DOTSTAR_LED_START_FULL_BRIGHT; } - if (rawbuf) { - buf[byteorder->byteorder.r] = rawbuf[byteorder->byteorder.r] * brightness; - buf[byteorder->byteorder.g] = rawbuf[byteorder->byteorder.g] * brightness; - buf[byteorder->byteorder.b] = rawbuf[byteorder->byteorder.b] * brightness; - } else { - buf[byteorder->byteorder.r] *= brightness; - buf[byteorder->byteorder.g] *= brightness; - buf[byteorder->byteorder.b] *= brightness; + } + // Call set_brightness so that it can allocate a second buffer if needed. + common_hal__pixelbuf_pixelbuf_set_brightness(MP_OBJ_FROM_PTR(self), brightness); + + // Turn on auto_write. We don't want to do it with the above brightness call. + self->auto_write = auto_write; +} + +size_t common_hal__pixelbuf_pixelbuf_get_len(mp_obj_t self_in) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + return self->pixel_count; +} + +uint8_t common_hal__pixelbuf_pixelbuf_get_bpp(mp_obj_t self_in) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + return self->byteorder.bpp; +} + +mp_obj_t common_hal__pixelbuf_pixelbuf_get_byteorder_string(mp_obj_t self_in) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + return self->byteorder.order_string; +} + +bool common_hal__pixelbuf_pixelbuf_get_auto_write(mp_obj_t self_in) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + return self->auto_write; +} + +void common_hal__pixelbuf_pixelbuf_set_auto_write(mp_obj_t self_in, bool auto_write) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + self->auto_write = auto_write; +} + +mp_float_t common_hal__pixelbuf_pixelbuf_get_brightness(mp_obj_t self_in) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + return self->brightness; +} + +void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t brightness) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + self->brightness = brightness; + size_t pixel_len = self->pixel_count * self->bytes_per_pixel; + if (self->pre_brightness_buffer == NULL) { + self->pre_brightness_buffer = m_malloc(pixel_len, false); + memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len); + } + for (size_t i = 0; i < pixel_len; i++) { + // Don't adjust per-pixel luminance bytes in dotstar mode + if (self->byteorder.is_dotstar && i % 4 == 0) { + continue; + } + self->post_brightness_buffer[i] = self->pre_brightness_buffer[i] * self->brightness; + } + + if (self->auto_write) { + common_hal__pixelbuf_pixelbuf_show(self_in); + } +} + +void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* w) { + pixelbuf_byteorder_details_t *byteorder = &self->byteorder; + // w is shared between white in NeoPixels and brightness in dotstars (so that DotStars can have + // per-pixel brightness). Set the defaults here in case it isn't set below. + if (byteorder->is_dotstar) { + *w = 255; + } else { + *w = 0; + } + + if (MP_OBJ_IS_INT(color)) { + mp_int_t value = mp_obj_get_int_truncated(color); + *r = value >> 16 & 0xff; + *g = (value >> 8) & 0xff; + *b = value & 0xff; + // Int colors can't set white directly so convert to white when all components are equal. + if (!byteorder->is_dotstar && byteorder->bpp == 4 && byteorder->has_white && *r == *g && *r == *b) { + *w = *r; + *r = 0; + *g = 0; + *b = 0; } } else { mp_obj_t *items; size_t len; - mp_obj_get_array(item, &len, &items); - if (len != byteorder->bpp && !dotstar) + mp_obj_get_array(color, &len, &items); + if (len != byteorder->bpp && !byteorder->is_dotstar) { mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len); - - buf[byteorder->byteorder.r] = mp_obj_get_int_truncated(items[PIXEL_R]) * brightness; - buf[byteorder->byteorder.g] = mp_obj_get_int_truncated(items[PIXEL_G]) * brightness; - buf[byteorder->byteorder.b] = mp_obj_get_int_truncated(items[PIXEL_B]) * brightness; - if (rawbuf) { - rawbuf[byteorder->byteorder.r] = mp_obj_get_int_truncated(items[PIXEL_R]); - rawbuf[byteorder->byteorder.g] = mp_obj_get_int_truncated(items[PIXEL_G]); - rawbuf[byteorder->byteorder.b] = mp_obj_get_int_truncated(items[PIXEL_B]); } + + *r = mp_obj_get_int_truncated(items[PIXEL_R]); + *g = mp_obj_get_int_truncated(items[PIXEL_G]); + *b = mp_obj_get_int_truncated(items[PIXEL_B]); if (len > 3) { - if (dotstar) { - buf[byteorder->byteorder.w] = DOTSTAR_LED_START | DOTSTAR_BRIGHTNESS(mp_obj_get_float(items[PIXEL_W])); - if (rawbuf) - rawbuf[byteorder->byteorder.w] = buf[byteorder->byteorder.w]; + if (mp_obj_is_float(items[PIXEL_W])) { + *w = 255 * mp_obj_get_float(items[PIXEL_W]); } else { - buf[byteorder->byteorder.w] = mp_obj_get_int_truncated(items[PIXEL_W]) * brightness; - if (rawbuf) - rawbuf[byteorder->byteorder.w] = mp_obj_get_int_truncated(items[PIXEL_W]); + *w = mp_obj_get_int_truncated(items[PIXEL_W]); } - } else if (dotstar) { - buf[byteorder->byteorder.w] = DOTSTAR_LED_START_FULL_BRIGHT; - if (rawbuf) - rawbuf[byteorder->byteorder.w] = DOTSTAR_LED_START_FULL_BRIGHT; } } } -mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar) { - mp_obj_t elems[len]; - for (uint i = 0; i < len; i++) { - elems[i] = pixelbuf_get_pixel(buf + ((i * slice_step) * step), byteorder, dotstar); +void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + // DotStars don't have white, instead they have 5 bit brightness so pack it into w. Shift right + // by three to leave the top five bits. + if (self->bytes_per_pixel == 4 && self->byteorder.is_dotstar) { + w = DOTSTAR_LED_START | w >> 3; + } + pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder; + size_t offset = index * self->bytes_per_pixel; + if (self->pre_brightness_buffer != NULL) { + uint8_t* pre_brightness_buffer = self->pre_brightness_buffer + offset; + if (self->bytes_per_pixel == 4) { + pre_brightness_buffer[rgbw_order->w] = w; + } + + pre_brightness_buffer[rgbw_order->r] = r; + pre_brightness_buffer[rgbw_order->g] = g; + pre_brightness_buffer[rgbw_order->b] = b; + } + + uint8_t* post_brightness_buffer = self->post_brightness_buffer + offset; + if (self->bytes_per_pixel == 4) { + // Only apply brightness if w is actually white (aka not DotStar.) + if (!self->byteorder.is_dotstar) { + w *= self->brightness; + } + post_brightness_buffer[rgbw_order->w] = w; + } + post_brightness_buffer[rgbw_order->r] = r * self->brightness; + post_brightness_buffer[rgbw_order->g] = g * self->brightness; + post_brightness_buffer[rgbw_order->b] = b * self->brightness; +} + +void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t value) { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t w; + _pixelbuf_parse_color(self, value, &r, &g, &b, &w); + _pixelbuf_set_pixel_color(self, index, r, g, b, w); +} + +void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, size_t stop, size_t step, mp_obj_t* values) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + size_t source_i = 0; + for (size_t target_i = start; target_i < stop; target_i += step) { + _pixelbuf_set_pixel(self, target_i, values[source_i]); + source_i++; + } + if (self->auto_write) { + common_hal__pixelbuf_pixelbuf_show(self_in); + } +} + +void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self_in, size_t index, mp_obj_t value) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + _pixelbuf_set_pixel(self, index, value); + if (self->auto_write) { + common_hal__pixelbuf_pixelbuf_show(self_in); } - return mp_obj_new_tuple(len, elems); } -mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar) { - mp_obj_t elems[byteorder->bpp]; - - elems[0] = mp_obj_new_int(buf[byteorder->byteorder.r]); - elems[1] = mp_obj_new_int(buf[byteorder->byteorder.g]); - elems[2] = mp_obj_new_int(buf[byteorder->byteorder.b]); - if (byteorder->bpp > 3) - { - if (dotstar) - elems[3] = mp_obj_new_float(DOTSTAR_GET_BRIGHTNESS(buf[byteorder->byteorder.w])); - else - elems[3] = mp_obj_new_int(buf[byteorder->byteorder.w]); +mp_obj_t common_hal__pixelbuf_pixelbuf_get_pixel(mp_obj_t self_in, size_t index) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + mp_obj_t elems[self->byteorder.bpp]; + uint8_t* pixel_buffer = self->post_brightness_buffer; + if (self->pre_brightness_buffer != NULL) { + pixel_buffer = self->pre_brightness_buffer; + } + + pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder; + elems[0] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->r]); + elems[1] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->g]); + elems[2] = MP_OBJ_NEW_SMALL_INT(pixel_buffer[rgbw_order->b]); + if (self->byteorder.bpp > 3) { + uint8_t w = pixel_buffer[rgbw_order->w]; + if (self->byteorder.is_dotstar) { + elems[3] = mp_obj_new_float((w & 0b00011111) / 31.0); + } else { + elems[3] = MP_OBJ_NEW_SMALL_INT(w); + } } - return mp_obj_new_tuple(byteorder->bpp, elems); + return mp_obj_new_tuple(self->byteorder.bpp, elems); +} + +void common_hal__pixelbuf_pixelbuf_show(mp_obj_t self_in) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + mp_obj_t dest[2 + 1]; + mp_load_method(self_in, MP_QSTR__transmit, dest); + + dest[2] = self->transmit_buffer_obj; + + mp_call_method_n_kw(1, 0, dest); +} + +void common_hal__pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t fill_color) { + pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t w; + _pixelbuf_parse_color(self, fill_color, &r, &g, &b, &w); + + for (size_t i = 0; i < self->pixel_count; i++) { + _pixelbuf_set_pixel_color(self, i, r, g, b, w); + } + if (self->auto_write) { + common_hal__pixelbuf_pixelbuf_show(self_in); + } } diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h index 173ce61a8..a9fbed366 100644 --- a/shared-module/_pixelbuf/PixelBuf.h +++ b/shared-module/_pixelbuf/PixelBuf.h @@ -27,24 +27,45 @@ #include "py/obj.h" #include "py/objarray.h" -#include "../../shared-bindings/_pixelbuf/types.h" #ifndef PIXELBUF_SHARED_MODULE_H #define PIXELBUF_SHARED_MODULE_H +typedef struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t w; +} pixelbuf_rgbw_t; + +typedef struct { + uint8_t bpp; + pixelbuf_rgbw_t byteorder; + bool has_white; + bool is_dotstar; + mp_obj_t order_string; +} pixelbuf_byteorder_details_t; + +typedef struct { + mp_obj_base_t base; + size_t pixel_count; + size_t bytes_per_pixel; + pixelbuf_byteorder_details_t byteorder; + mp_float_t brightness; + mp_obj_t transmit_buffer_obj; + // The post_brightness_buffer is offset into the buffer allocated in transmit_buffer_obj to + // account for any header. + uint8_t *post_brightness_buffer; + uint8_t *pre_brightness_buffer; + bool auto_write; +} pixelbuf_pixelbuf_obj_t; + #define PIXEL_R 0 #define PIXEL_G 1 #define PIXEL_B 2 #define PIXEL_W 3 #define DOTSTAR_LED_START 0b11100000 -#define DOTSTAR_BRIGHTNESS(brightness) ((32 - (uint8_t)(32 - brightness * 31)) & 0b00011111) -#define DOTSTAR_GET_BRIGHTNESS(value) ((value & 0b00011111) / 31.0) #define DOTSTAR_LED_START_FULL_BRIGHT 0xFF -void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar); -mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar); -mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar); -void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder); - #endif -- cgit v1.2.3 From 5e789b38504846982a8cd7fa447297a51efc8352 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 27 Jan 2020 15:10:32 -0800 Subject: Don't allocate the pre brightness buffer if brightness is 1.0 still --- shared-module/_pixelbuf/PixelBuf.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'shared-module') diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c index ab5bcb441..bad8539ea 100644 --- a/shared-module/_pixelbuf/PixelBuf.c +++ b/shared-module/_pixelbuf/PixelBuf.c @@ -68,6 +68,7 @@ void common_hal__pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size } } // Call set_brightness so that it can allocate a second buffer if needed. + self->brightness = 1.0; common_hal__pixelbuf_pixelbuf_set_brightness(MP_OBJ_FROM_PTR(self), brightness); // Turn on auto_write. We don't want to do it with the above brightness call. @@ -106,6 +107,12 @@ mp_float_t common_hal__pixelbuf_pixelbuf_get_brightness(mp_obj_t self_in) { void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t brightness) { pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); + // Skip out if the brightness is already set. The default of self->brightness is 1.0. So, this + // also prevents the pre_brightness_buffer allocation when brightness is set to 1.0 again. + mp_float_t change = brightness - self->brightness; + if (-0.001 < change && change < 0.001) { + return; + } self->brightness = brightness; size_t pixel_len = self->pixel_count * self->bytes_per_pixel; if (self->pre_brightness_buffer == NULL) { -- cgit v1.2.3 From 3c8600554654926fe88d65fc0b5d668c0bea476a Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Tue, 28 Jan 2020 17:11:25 -0500 Subject: Implement requested changes --- ports/stm32f4/boards/meowbit_v121/pins.c | 2 +- ports/stm32f4/common-hal/pulseio/PWMOut.c | 6 +++--- shared-module/displayio/__init__.c | 2 +- supervisor/shared/external_flash/spi_flash.c | 32 ++++++++++++++-------------- supervisor/spi_flash_api.h | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) (limited to 'shared-module') diff --git a/ports/stm32f4/boards/meowbit_v121/pins.c b/ports/stm32f4/boards/meowbit_v121/pins.c index 0cdbefd59..1489c23f1 100644 --- a/ports/stm32f4/boards/meowbit_v121/pins.c +++ b/ports/stm32f4/boards/meowbit_v121/pins.c @@ -60,6 +60,6 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_P0), MP_ROM_PTR(&pin_PA00) }, { MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_PB00) }, - { MP_ROM_QSTR(MP_QSTR_INTERNAL_SPI), MP_ROM_PTR(&spi) }, + { MP_ROM_QSTR(MP_QSTR_INTERNAL_SPI), MP_ROM_PTR(&supervisor_flash_spi_bus) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c index 000325be3..29376691b 100644 --- a/ports/stm32f4/common-hal/pulseio/PWMOut.c +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -68,9 +68,9 @@ STATIC uint32_t timer_get_source_freq(uint32_t tim_id) { } STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) { - //duty cycle is (0xFFFF - duty)/0xFFFF fraction x (number of pulses per period) + //duty cycle is duty/0xFFFF fraction x (number of pulses per period) //Note that pulses are inverted, so duty cycle is inverted - return ((0xFFFF - duty)*period) / ((1 << 16) - 1); + return (duty*period) / ((1 << 16) - 1); } STATIC void timer_get_optimal_divisors(uint32_t*period, uint32_t*prescaler, @@ -203,7 +203,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, //Channel/PWM init self->chan_handle.OCMode = TIM_OCMODE_PWM1; self->chan_handle.Pulse = timer_get_internal_duty(duty, period); - self->chan_handle.OCPolarity = TIM_OCPOLARITY_LOW; + self->chan_handle.OCPolarity = TIM_OCPOLARITY_HIGH; self->chan_handle.OCFastMode = TIM_OCFAST_DISABLE; self->chan_handle.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 self->chan_handle.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 8d9f14883..efa61265e 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -104,7 +104,7 @@ void reset_displays(void) { } #endif #ifdef BOARD_USE_INTERNAL_SPI - if (original_spi == (mp_obj_t)(&spi)) { + if (original_spi == (mp_obj_t)(&supervisor_flash_spi_bus)) { continue; } #endif diff --git a/supervisor/shared/external_flash/spi_flash.c b/supervisor/shared/external_flash/spi_flash.c index 12888f2d3..67e64c970 100644 --- a/supervisor/shared/external_flash/spi_flash.c +++ b/supervisor/shared/external_flash/spi_flash.c @@ -36,33 +36,33 @@ #include "py/mpconfig.h" digitalio_digitalinout_obj_t cs_pin; -busio_spi_obj_t spi; +busio_spi_obj_t supervisor_flash_spi_bus; const external_flash_device* flash_device; uint32_t spi_flash_baudrate; // Enable the flash over SPI. static void flash_enable(void) { - while (!common_hal_busio_spi_try_lock(&spi)) {} + while (!common_hal_busio_spi_try_lock(&supervisor_flash_spi_bus)) {} common_hal_digitalio_digitalinout_set_value(&cs_pin, false); } // Disable the flash over SPI. static void flash_disable(void) { common_hal_digitalio_digitalinout_set_value(&cs_pin, true); - common_hal_busio_spi_unlock(&spi); + common_hal_busio_spi_unlock(&supervisor_flash_spi_bus); } static bool transfer(uint8_t* command, uint32_t command_length, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { flash_enable(); - bool status = common_hal_busio_spi_write(&spi, command, command_length); + bool status = common_hal_busio_spi_write(&supervisor_flash_spi_bus, command, command_length); if (status) { if (data_in != NULL && data_out != NULL) { - status = common_hal_busio_spi_transfer(&spi, data_out, data_in, data_length); + status = common_hal_busio_spi_transfer(&supervisor_flash_spi_bus, data_out, data_in, data_length); } else if (data_out != NULL) { - status = common_hal_busio_spi_read(&spi, data_out, data_length, 0xff); + status = common_hal_busio_spi_read(&supervisor_flash_spi_bus, data_out, data_length, 0xff); } else if (data_in != NULL) { - status = common_hal_busio_spi_write(&spi, data_in, data_length); + status = common_hal_busio_spi_write(&supervisor_flash_spi_bus, data_in, data_length); } } flash_disable(); @@ -103,10 +103,10 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); flash_enable(); - common_hal_busio_spi_configure(&spi, spi_flash_baudrate, 0, 0, 8); - bool status = common_hal_busio_spi_write(&spi, request, 4); + common_hal_busio_spi_configure(&supervisor_flash_spi_bus, spi_flash_baudrate, 0, 0, 8); + bool status = common_hal_busio_spi_write(&supervisor_flash_spi_bus, request, 4); if (status) { - status = common_hal_busio_spi_write(&spi, data, data_length); + status = common_hal_busio_spi_write(&supervisor_flash_spi_bus, data, data_length); } flash_disable(); return status; @@ -122,10 +122,10 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); flash_enable(); - common_hal_busio_spi_configure(&spi, spi_flash_baudrate, 0, 0, 8); - bool status = common_hal_busio_spi_write(&spi, request, command_length); + common_hal_busio_spi_configure(&supervisor_flash_spi_bus, spi_flash_baudrate, 0, 0, 8); + bool status = common_hal_busio_spi_write(&supervisor_flash_spi_bus, request, command_length); if (status) { - status = common_hal_busio_spi_read(&spi, data, data_length, 0xff); + status = common_hal_busio_spi_read(&supervisor_flash_spi_bus, data, data_length, 0xff); } flash_disable(); return status; @@ -140,9 +140,9 @@ void spi_flash_init(void) { common_hal_digitalio_digitalinout_switch_to_output(&cs_pin, true, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_never_reset(&cs_pin); - spi.base.type = &busio_spi_type; - common_hal_busio_spi_construct(&spi, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN); - common_hal_busio_spi_never_reset(&spi); + supervisor_flash_spi_bus.base.type = &busio_spi_type; + common_hal_busio_spi_construct(&supervisor_flash_spi_bus, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN); + common_hal_busio_spi_never_reset(&supervisor_flash_spi_bus); } void spi_flash_init_device(const external_flash_device* device) { diff --git a/supervisor/spi_flash_api.h b/supervisor/spi_flash_api.h index b477308ba..f59346e25 100644 --- a/supervisor/spi_flash_api.h +++ b/supervisor/spi_flash_api.h @@ -33,7 +33,7 @@ #include "shared-bindings/busio/SPI.h" -extern busio_spi_obj_t spi; //Used to share SPI bus on some boards +extern busio_spi_obj_t supervisor_flash_spi_bus; //Used to share SPI bus on some boards // This API is implemented for both normal SPI peripherals and QSPI peripherals. -- cgit v1.2.3 From 27c36eea2bbadd1e5df1ef4fd9bf54824068f2c2 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Thu, 30 Jan 2020 15:24:04 +0100 Subject: circuitpython-stage: allow choosing background color --- frozen/circuitpython-stage | 2 +- shared-bindings/_stage/__init__.c | 11 ++++++++--- shared-module/_stage/__init__.c | 6 +++++- shared-module/_stage/__init__.h | 3 ++- 4 files changed, 16 insertions(+), 6 deletions(-) (limited to 'shared-module') diff --git a/frozen/circuitpython-stage b/frozen/circuitpython-stage index 8d5cc3840..19a66d79f 160000 --- a/frozen/circuitpython-stage +++ b/frozen/circuitpython-stage @@ -1 +1 @@ -Subproject commit 8d5cc384058b1cb296aaeab86fb8405042d547ed +Subproject commit 19a66d79f0650a15e502464b42e16692365eab36 diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c index 1154bbbf1..4bac280bf 100644 --- a/shared-bindings/_stage/__init__.c +++ b/shared-bindings/_stage/__init__.c @@ -51,7 +51,7 @@ //| Layer //| Text //| -//| .. function:: render(x0, y0, x1, y1, layers, buffer, display[, scale]) +//| .. function:: render(x0, y0, x1, y1, layers, buffer, display[, scale[, background]]) //| //| Render and send to the display a fragment of the screen. //| @@ -63,6 +63,7 @@ //| :param bytearray buffer: A buffer to use for rendering. //| :param ~displayio.Display display: The display to use. //| :param int scale: How many times should the image be scaled up. +//| :param int background: What color to display when nothing is there. //| //| There are also no sanity checks, outside of the basic overflow //| checking. The caller is responsible for making the passed parameters @@ -92,12 +93,16 @@ STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) { } displayio_display_obj_t *display = MP_OBJ_TO_PTR(native_display); uint8_t scale = 1; - if (n_args >= 8) { + if (n_args > 7) { scale = mp_obj_get_int(args[7]); } + uint16_t background = 0; + if (n_args > 8) { + background = mp_obj_get_int(args[8]); + } render_stage(x0, y0, x1, y1, layers, layers_size, buffer, buffer_size, - display, scale); + display, scale, background); return mp_const_none; } diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c index d5da74272..0323c32cb 100644 --- a/shared-module/_stage/__init__.c +++ b/shared-module/_stage/__init__.c @@ -34,7 +34,8 @@ void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, mp_obj_t *layers, size_t layers_size, uint16_t *buffer, size_t buffer_size, - displayio_display_obj_t *display, uint8_t scale) { + displayio_display_obj_t *display, + uint8_t scale, uint16_t background) { displayio_area_t area; @@ -68,6 +69,9 @@ void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, break; } } + if (c == TRANSPARENT) { + c = background; + } for (uint8_t xscale = 0; xscale < scale; ++xscale) { buffer[index] = c; index += 1; diff --git a/shared-module/_stage/__init__.h b/shared-module/_stage/__init__.h index 5af2124ae..7a1826200 100644 --- a/shared-module/_stage/__init__.h +++ b/shared-module/_stage/__init__.h @@ -37,6 +37,7 @@ void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, mp_obj_t *layers, size_t layers_size, uint16_t *buffer, size_t buffer_size, - displayio_display_obj_t *display, uint8_t scale); + displayio_display_obj_t *display, + uint8_t scale, uint16_t background); #endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE -- cgit v1.2.3 From 5c6d94d3e5ac2c4bb8514ac920d59a465300465b Mon Sep 17 00:00:00 2001 From: James Bowman Date: Fri, 7 Feb 2020 10:30:49 -0800 Subject: Split into shared-module and shared-bindings --- py/circuitpy_defns.mk | 3 +- shared-bindings/_eve/__init__.c | 80 +++----- shared-bindings/_eve/mod_eve-gen.h | 372 +++++++++++++++++-------------------- shared-module/_eve/__init__.c | 270 +++++++++++++++++++++++++++ shared-module/_eve/__init__.h | 91 +++++++++ 5 files changed, 557 insertions(+), 259 deletions(-) create mode 100644 shared-module/_eve/__init__.c create mode 100644 shared-module/_eve/__init__.h (limited to 'shared-module') diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index e7d49ae24..68fa25d8d 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -363,7 +363,8 @@ SRC_SHARED_MODULE_ALL = \ uheap/__init__.c \ ustack/__init__.c \ _pew/__init__.c \ - _pew/PewPew.c + _pew/PewPew.c \ + _eve/__init__.c # All possible sources are listed here, and are filtered by SRC_PATTERNS. SRC_SHARED_MODULE = $(filter $(SRC_PATTERNS), $(SRC_SHARED_MODULE_ALL)) diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c index 8d36118da..6f2a39db5 100644 --- a/shared-bindings/_eve/__init__.c +++ b/shared-bindings/_eve/__init__.c @@ -31,6 +31,8 @@ #include "py/runtime.h" #include "py/binary.h" +#include "shared-module/_eve/__init__.h" + //| :mod:`_eve` --- low-level BridgeTek EVE bindings //| ================================================ //| @@ -45,94 +47,57 @@ typedef struct _mp_obj__EVE_t { mp_obj_base_t base; - mp_obj_t dest[3]; // Own 'write' method, plus argument - int vscale; // fixed-point scaling used for Vertex2f - size_t n; // Current size of command buffer - uint8_t buf[512]; // Command buffer + common_hal__eve_t _eve; } mp_obj__EVE_t; STATIC const mp_obj_type_t _EVE_type; -STATIC void _write(mp_obj__EVE_t *_EVE, mp_obj_t b) { - _EVE->dest[2] = b; - mp_call_method_n_kw(1, 0, _EVE->dest); -} +#define EVEHAL(s) \ + (&((mp_obj__EVE_t*)mp_instance_cast_to_native_base((s), &_EVE_type))->_eve) STATIC mp_obj_t _register(mp_obj_t self, mp_obj_t o) { - mp_obj__EVE_t *_EVE = mp_instance_cast_to_native_base(self, &_EVE_type); - mp_load_method(o, MP_QSTR_write, _EVE->dest); + common_hal__eve_t *eve = EVEHAL(self); + mp_load_method(o, MP_QSTR_write, eve->dest); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(register_obj, _register); STATIC mp_obj_t _flush(mp_obj_t self) { - mp_obj__EVE_t *_EVE = mp_instance_cast_to_native_base(self, &_EVE_type); - if (_EVE->n != 0) { - _write(_EVE, mp_obj_new_bytearray_by_ref(_EVE->n, _EVE->buf)); - _EVE->n = 0; - } + common_hal__eve_flush(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(flush_obj, _flush); -STATIC void *append(mp_obj_t self, size_t m) { - mp_obj__EVE_t *_EVE = mp_instance_cast_to_native_base(self, &_EVE_type); - if ((_EVE->n + m) > sizeof(_EVE->buf)) - _flush((mp_obj_t)_EVE); - uint8_t *r = _EVE->buf + _EVE->n; - _EVE->n += m; - return (void*)r; -} - STATIC mp_obj_t _cc(mp_obj_t self, mp_obj_t b) { - mp_obj__EVE_t *_EVE = mp_instance_cast_to_native_base(self, &_EVE_type); mp_buffer_info_t buffer_info; mp_get_buffer_raise(b, &buffer_info, MP_BUFFER_READ); - if (buffer_info.len <= sizeof(_EVE->buf)) { - uint8_t *p = (uint8_t*)append(_EVE, buffer_info.len); - // memcpy(p, buffer_info.buf, buffer_info.len); - uint8_t *s = buffer_info.buf; - for (size_t i = 0; i < buffer_info.len; i++) - *p++ = *s++; - } else { - _flush(self); - _write(_EVE, b); - } - + common_hal__eve_add(EVEHAL(self), buffer_info.len, buffer_info.buf); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc_obj, _cc); -#define C4(self, u) (*(uint32_t*)append((self), sizeof(uint32_t)) = (u)) - #include "mod_eve-gen.h" // Hand-written functions { +#define ADD_X(self, x) \ + common_hal__eve_add(EVEHAL(self), sizeof(x), &(x)); + STATIC mp_obj_t _cmd0(mp_obj_t self, mp_obj_t n) { - C4(self, (0xffffff00 | mp_obj_get_int_truncated(n))); + uint32_t code = 0xffffff00 | mp_obj_get_int_truncated(n); + ADD_X(self, code); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(cmd0_obj, _cmd0); STATIC mp_obj_t _vertex2f(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - mp_obj__EVE_t *_EVE = mp_instance_cast_to_native_base(self, &_EVE_type); - int16_t x = (int16_t)(_EVE->vscale * mp_obj_get_float(a0)); - int16_t y = (int16_t)(_EVE->vscale * mp_obj_get_float(a1)); - C4(self, (0x40000000 | ((x & 32767) << 15) | (y & 32767))); + mp_float_t x = mp_obj_get_float(a0); + mp_float_t y = mp_obj_get_float(a1); + common_hal__eve_Vertex2f(EVEHAL(self), x, y); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vertex2f_obj, _vertex2f); -STATIC mp_obj_t _vertexformat(mp_obj_t self, mp_obj_t a0) { - mp_obj__EVE_t *_EVE = mp_instance_cast_to_native_base(self, &_EVE_type); - uint32_t frac = mp_obj_get_int_truncated(a0); - C4(self, ((0x27 << 24) | (frac & 3))); - _EVE->vscale = 1 << frac; - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertexformat_obj, _vertexformat); - STATIC mp_obj_t _cmd(size_t n_args, const mp_obj_t *args) { mp_obj_t self = args[0]; mp_obj_t num = args[1]; @@ -159,7 +124,8 @@ STATIC mp_obj_t _cmd(size_t n_args, const mp_obj_t *args) { } } - uint32_t *p = (uint32_t*)append(self, sizeof(uint32_t) * (1 + n)); + uint32_t buf[16]; + uint32_t *p = buf; *p++ = 0xffffff00 | mp_obj_get_int_truncated(num); mp_obj_t *a = items; uint32_t lo; @@ -181,6 +147,8 @@ STATIC mp_obj_t _cmd(size_t n_args, const mp_obj_t *args) { break; } } + + common_hal__eve_add(EVEHAL(self), sizeof(uint32_t) * (1 + n), buf); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(cmd_obj, 4, 4, _cmd); @@ -190,7 +158,6 @@ STATIC const mp_rom_map_elem_t _EVE_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_cc), MP_ROM_PTR(&cc_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&flush_obj) }, { MP_ROM_QSTR(MP_QSTR_Vertex2f), MP_ROM_PTR(&vertex2f_obj) }, - { MP_ROM_QSTR(MP_QSTR_VertexFormat), MP_ROM_PTR(&vertexformat_obj) }, { MP_ROM_QSTR(MP_QSTR_cmd), MP_ROM_PTR(&cmd_obj) }, { MP_ROM_QSTR(MP_QSTR_cmd0), MP_ROM_PTR(&cmd0_obj) }, ROM_DECLS @@ -206,10 +173,9 @@ STATIC void _EVE_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ STATIC mp_obj_t _EVE_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_obj__EVE_t *o = m_new_obj(mp_obj__EVE_t); - mp_printf(&mp_plat_print, "_EVE %p make_new\n", o); o->base.type = &_EVE_type; - o->n = 0; - o->vscale = 16; + o->_eve.n = 0; + o->_eve.vscale = 16; return MP_OBJ_FROM_PTR(o); } diff --git a/shared-bindings/_eve/mod_eve-gen.h b/shared-bindings/_eve/mod_eve-gen.h index 1c8d5ae12..c5dafb16f 100644 --- a/shared-bindings/_eve/mod_eve-gen.h +++ b/shared-bindings/_eve/mod_eve-gen.h @@ -1,42 +1,37 @@ -STATIC mp_obj_t _alphafunc(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t func = mp_obj_get_int_truncated(a0); - uint32_t ref = mp_obj_get_int_truncated(a1); - C4(self, ((9 << 24) | ((func & 7) << 8) | ((ref & 255))) -); +STATIC mp_obj_t _alphafunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t func = mp_obj_get_int_truncated(a0); + uint32_t ref = mp_obj_get_int_truncated(a1); + common_hal__eve_AlphaFunc(EVEHAL(self), func, ref); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(alphafunc_obj, _alphafunc); -STATIC mp_obj_t _begin(mp_obj_t self , mp_obj_t a0) { - uint32_t prim = mp_obj_get_int_truncated(a0); - C4(self, ((31 << 24) | ((prim & 15))) -); +STATIC mp_obj_t _begin(mp_obj_t self, mp_obj_t a0) { + uint32_t prim = mp_obj_get_int_truncated(a0); + common_hal__eve_Begin(EVEHAL(self), prim); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(begin_obj, _begin); -STATIC mp_obj_t _bitmapextformat(mp_obj_t self , mp_obj_t a0) { - uint32_t fmt = mp_obj_get_int_truncated(a0); - C4(self, ((46 << 24) | (fmt & 65535)) -); +STATIC mp_obj_t _bitmapextformat(mp_obj_t self, mp_obj_t a0) { + uint32_t fmt = mp_obj_get_int_truncated(a0); + common_hal__eve_BitmapExtFormat(EVEHAL(self), fmt); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmapextformat_obj, _bitmapextformat); -STATIC mp_obj_t _bitmaphandle(mp_obj_t self , mp_obj_t a0) { +STATIC mp_obj_t _bitmaphandle(mp_obj_t self, mp_obj_t a0) { uint32_t handle = mp_obj_get_int_truncated(a0); - C4(self, ((5 << 24) | ((handle & 31))) -); + common_hal__eve_BitmapHandle(EVEHAL(self), handle); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaphandle_obj, _bitmaphandle); -STATIC mp_obj_t _bitmaplayouth(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { +STATIC mp_obj_t _bitmaplayouth(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t linestride = mp_obj_get_int_truncated(a0); uint32_t height = mp_obj_get_int_truncated(a1); - C4(self, ((40 << 24) | (((linestride) & 3) << 2) | (((height) & 3))) -); + common_hal__eve_BitmapLayoutH(EVEHAL(self), linestride, height); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaplayouth_obj, _bitmaplayouth); @@ -45,368 +40,343 @@ STATIC mp_obj_t _bitmaplayout(size_t n_args, const mp_obj_t *args) { uint32_t format = mp_obj_get_int_truncated(args[1]); uint32_t linestride = mp_obj_get_int_truncated(args[2]); uint32_t height = mp_obj_get_int_truncated(args[3]); - C4(args[0], ((7 << 24) | ((format & 31) << 19) | ((linestride & 1023) << 9) | ((height & 511))) -); + common_hal__eve_BitmapLayout(EVEHAL(args[0]), format, linestride, height); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaplayout_obj, 4, 4, _bitmaplayout); -STATIC mp_obj_t _bitmapsizeh(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t width = mp_obj_get_int_truncated(a0); +STATIC mp_obj_t _bitmapsizeh(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t width = mp_obj_get_int_truncated(a0); uint32_t height = mp_obj_get_int_truncated(a1); - C4(self, ((41 << 24) | (((width) & 3) << 2) | (((height) & 3))) -); + common_hal__eve_BitmapSizeH(EVEHAL(self), width, height); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmapsizeh_obj, _bitmapsizeh); STATIC mp_obj_t _bitmapsize(size_t n_args, const mp_obj_t *args) { uint32_t filter = mp_obj_get_int_truncated(args[1]); - uint32_t wrapx = mp_obj_get_int_truncated(args[2]); - uint32_t wrapy = mp_obj_get_int_truncated(args[3]); - uint32_t width = mp_obj_get_int_truncated(args[4]); + uint32_t wrapx = mp_obj_get_int_truncated(args[2]); + uint32_t wrapy = mp_obj_get_int_truncated(args[3]); + uint32_t width = mp_obj_get_int_truncated(args[4]); uint32_t height = mp_obj_get_int_truncated(args[5]); - C4(args[0], ((8 << 24) | ((filter & 1) << 20) | ((wrapx & 1) << 19) | ((wrapy & 1) << 18) | ((width & 511) << 9) | ((height & 511))) -); + common_hal__eve_BitmapSize(EVEHAL(args[0]), filter, wrapx, wrapy, width, height); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapsize_obj, 6, 6, _bitmapsize); -STATIC mp_obj_t _bitmapsource(mp_obj_t self , mp_obj_t a0) { - uint32_t addr = mp_obj_get_int_truncated(a0); - C4(self, ((1 << 24) | ((addr & 0xffffff))) -); +STATIC mp_obj_t _bitmapsource(mp_obj_t self, mp_obj_t a0) { + uint32_t addr = mp_obj_get_int_truncated(a0); + common_hal__eve_BitmapSource(EVEHAL(self), addr); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmapsource_obj, _bitmapsource); STATIC mp_obj_t _bitmapswizzle(size_t n_args, const mp_obj_t *args) { - uint32_t r = mp_obj_get_int_truncated(args[1]); - uint32_t g = mp_obj_get_int_truncated(args[2]); - uint32_t b = mp_obj_get_int_truncated(args[3]); - uint32_t a = mp_obj_get_int_truncated(args[4]); - C4(args[0], ((47 << 24) | ((r & 7) << 9) | ((g & 7) << 6) | ((b & 7) << 3) | ((a & 7))) -); + uint32_t r = mp_obj_get_int_truncated(args[1]); + uint32_t g = mp_obj_get_int_truncated(args[2]); + uint32_t b = mp_obj_get_int_truncated(args[3]); + uint32_t a = mp_obj_get_int_truncated(args[4]); + common_hal__eve_BitmapSwizzle(EVEHAL(args[0]), r, g, b, a); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapswizzle_obj, 5, 5, _bitmapswizzle); -STATIC mp_obj_t _bitmaptransforma(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t a = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - C4(self, ((21 << 24) | ((p & 1) << 17) | ((a & 131071))) -); +STATIC mp_obj_t _bitmaptransforma(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t a = mp_obj_get_int_truncated(a0); + uint32_t p = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformA(EVEHAL(self), a, p); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforma_obj, _bitmaptransforma); -STATIC mp_obj_t _bitmaptransformb(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t b = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - C4(self, ((22 << 24) | ((p & 1) << 17) | ((b & 131071))) -); +STATIC mp_obj_t _bitmaptransformb(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t b = mp_obj_get_int_truncated(a0); + uint32_t p = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformB(EVEHAL(self), b, p); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformb_obj, _bitmaptransformb); -STATIC mp_obj_t _bitmaptransformc(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t c = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - C4(self, ((23 << 24) | ((p & 1) << 17) | ((c & 16777215))) -); +STATIC mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t c = mp_obj_get_int_truncated(a0); + uint32_t p = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformC(EVEHAL(self), c, p); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformc_obj, _bitmaptransformc); -STATIC mp_obj_t _bitmaptransformd(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t d = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - C4(self, ((24 << 24) | ((p & 1) << 17) | ((d & 131071))) -); +STATIC mp_obj_t _bitmaptransformd(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t d = mp_obj_get_int_truncated(a0); + uint32_t p = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformD(EVEHAL(self), d, p); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformd_obj, _bitmaptransformd); -STATIC mp_obj_t _bitmaptransforme(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t e = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - C4(self, ((25 << 24) | ((p & 1) << 17) | ((e & 131071))) -); +STATIC mp_obj_t _bitmaptransforme(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t e = mp_obj_get_int_truncated(a0); + uint32_t p = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformE(EVEHAL(self), e, p); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforme_obj, _bitmaptransforme); -STATIC mp_obj_t _bitmaptransformf(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t f = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - C4(self, ((26 << 24) | ((p & 1) << 17) | ((f & 16777215))) -); +STATIC mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t f = mp_obj_get_int_truncated(a0); + uint32_t p = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformF(EVEHAL(self), f, p); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformf_obj, _bitmaptransformf); -STATIC mp_obj_t _blendfunc(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t src = mp_obj_get_int_truncated(a0); - uint32_t dst = mp_obj_get_int_truncated(a1); - C4(self, ((11 << 24) | ((src & 7) << 3) | ((dst & 7))) -); +STATIC mp_obj_t _blendfunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t src = mp_obj_get_int_truncated(a0); + uint32_t dst = mp_obj_get_int_truncated(a1); + common_hal__eve_BlendFunc(EVEHAL(self), src, dst); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(blendfunc_obj, _blendfunc); -STATIC mp_obj_t _call(mp_obj_t self , mp_obj_t a0) { - uint32_t dest = mp_obj_get_int_truncated(a0); - C4(self, ((29 << 24) | ((dest & 65535))) -); +STATIC mp_obj_t _call(mp_obj_t self, mp_obj_t a0) { + uint32_t dest = mp_obj_get_int_truncated(a0); + common_hal__eve_Call(EVEHAL(self), dest); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(call_obj, _call); -STATIC mp_obj_t _cell(mp_obj_t self , mp_obj_t a0) { - uint32_t cell = mp_obj_get_int_truncated(a0); - C4(self, ((6 << 24) | ((cell & 127))) -); +STATIC mp_obj_t _cell(mp_obj_t self, mp_obj_t a0) { + uint32_t cell = mp_obj_get_int_truncated(a0); + common_hal__eve_Cell(EVEHAL(self), cell); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(cell_obj, _cell); -STATIC mp_obj_t _clearcolora(mp_obj_t self , mp_obj_t a0) { - uint32_t alpha = mp_obj_get_int_truncated(a0); - C4(self, ((15 << 24) | ((alpha & 255))) -); +STATIC mp_obj_t _clearcolora(mp_obj_t self, mp_obj_t a0) { + uint32_t alpha = mp_obj_get_int_truncated(a0); + common_hal__eve_ClearColorA(EVEHAL(self), alpha); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(clearcolora_obj, _clearcolora); STATIC mp_obj_t _clearcolorrgb(size_t n_args, const mp_obj_t *args) { - uint32_t red = mp_obj_get_int_truncated(args[1]); - uint32_t green = mp_obj_get_int_truncated(args[2]); - uint32_t blue = mp_obj_get_int_truncated(args[3]); - C4(args[0], ((2 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | ((blue & 255))) -); + uint32_t red = mp_obj_get_int_truncated(args[1]); + uint32_t green = mp_obj_get_int_truncated(args[2]); + uint32_t blue = mp_obj_get_int_truncated(args[3]); + common_hal__eve_ClearColorRGB(EVEHAL(args[0]), red, green, blue); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clearcolorrgb_obj, 4, 4, _clearcolorrgb); STATIC mp_obj_t _clear(size_t n_args, const mp_obj_t *args) { - uint32_t c = mp_obj_get_int_truncated(args[1]); - uint32_t s = mp_obj_get_int_truncated(args[2]); - uint32_t t = mp_obj_get_int_truncated(args[3]); - C4(args[0], ((38 << 24) | ((c & 1) << 2) | ((s & 1) << 1) | ((t & 1))) -); + uint32_t c = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 1; + uint32_t s = (n_args > 2) ? mp_obj_get_int_truncated(args[2]) : 1; + uint32_t t = (n_args > 3) ? mp_obj_get_int_truncated(args[3]) : 1; + common_hal__eve_Clear(EVEHAL(args[0]), c, s, t); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clear_obj, 4, 4, _clear); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clear_obj, 1, 4, _clear); -STATIC mp_obj_t _clearstencil(mp_obj_t self , mp_obj_t a0) { - uint32_t s = mp_obj_get_int_truncated(a0); - C4(self, ((17 << 24) | ((s & 255))) -); +STATIC mp_obj_t _clearstencil(mp_obj_t self, mp_obj_t a0) { + uint32_t s = mp_obj_get_int_truncated(a0); + common_hal__eve_ClearStencil(EVEHAL(self), s); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(clearstencil_obj, _clearstencil); -STATIC mp_obj_t _cleartag(mp_obj_t self , mp_obj_t a0) { - uint32_t s = mp_obj_get_int_truncated(a0); - C4(self, ((18 << 24) | ((s & 255))) -); +STATIC mp_obj_t _cleartag(mp_obj_t self, mp_obj_t a0) { + uint32_t s = mp_obj_get_int_truncated(a0); + common_hal__eve_ClearTag(EVEHAL(self), s); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(cleartag_obj, _cleartag); -STATIC mp_obj_t _colora(mp_obj_t self , mp_obj_t a0) { - uint32_t alpha = mp_obj_get_int_truncated(a0); - C4(self, ((16 << 24) | ((alpha & 255))) -); +STATIC mp_obj_t _colora(mp_obj_t self, mp_obj_t a0) { + uint32_t alpha = mp_obj_get_int_truncated(a0); + common_hal__eve_ColorA(EVEHAL(self), alpha); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(colora_obj, _colora); STATIC mp_obj_t _colormask(size_t n_args, const mp_obj_t *args) { - uint32_t r = mp_obj_get_int_truncated(args[1]); - uint32_t g = mp_obj_get_int_truncated(args[2]); - uint32_t b = mp_obj_get_int_truncated(args[3]); - uint32_t a = mp_obj_get_int_truncated(args[4]); - C4(args[0], ((32 << 24) | ((r & 1) << 3) | ((g & 1) << 2) | ((b & 1) << 1) | ((a & 1))) -); + uint32_t r = mp_obj_get_int_truncated(args[1]); + uint32_t g = mp_obj_get_int_truncated(args[2]); + uint32_t b = mp_obj_get_int_truncated(args[3]); + uint32_t a = mp_obj_get_int_truncated(args[4]); + common_hal__eve_ColorMask(EVEHAL(args[0]), r, g, b, a); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(colormask_obj, 5, 5, _colormask); STATIC mp_obj_t _colorrgb(size_t n_args, const mp_obj_t *args) { - uint32_t red = mp_obj_get_int_truncated(args[1]); - uint32_t green = mp_obj_get_int_truncated(args[2]); - uint32_t blue = mp_obj_get_int_truncated(args[3]); - C4(args[0], ((4 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | ((blue & 255))) -); + uint32_t red = mp_obj_get_int_truncated(args[1]); + uint32_t green = mp_obj_get_int_truncated(args[2]); + uint32_t blue = mp_obj_get_int_truncated(args[3]); + common_hal__eve_ColorRGB(EVEHAL(args[0]), red, green, blue); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(colorrgb_obj, 4, 4, _colorrgb); -STATIC mp_obj_t _display(mp_obj_t self ) { +STATIC mp_obj_t _display(mp_obj_t self) { - C4(self, ((0 << 24)) -); + common_hal__eve_Display(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_obj, _display); -STATIC mp_obj_t _end(mp_obj_t self ) { +STATIC mp_obj_t _end(mp_obj_t self) { - C4(self, ((33 << 24)) -); + common_hal__eve_End(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(end_obj, _end); -STATIC mp_obj_t _jump(mp_obj_t self , mp_obj_t a0) { - uint32_t dest = mp_obj_get_int_truncated(a0); - C4(self, ((30 << 24) | ((dest & 65535))) -); +STATIC mp_obj_t _jump(mp_obj_t self, mp_obj_t a0) { + uint32_t dest = mp_obj_get_int_truncated(a0); + common_hal__eve_Jump(EVEHAL(self), dest); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(jump_obj, _jump); -STATIC mp_obj_t _linewidth(mp_obj_t self , mp_obj_t a0) { - uint32_t width = mp_obj_get_int_truncated(a0); - C4(self, ((14 << 24) | ((width & 4095))) -); +STATIC mp_obj_t _linewidth(mp_obj_t self, mp_obj_t a0) { + uint32_t width = mp_obj_get_int_truncated(a0); + common_hal__eve_LineWidth(EVEHAL(self), width); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(linewidth_obj, _linewidth); -STATIC mp_obj_t _macro(mp_obj_t self , mp_obj_t a0) { - uint32_t m = mp_obj_get_int_truncated(a0); - C4(self, ((37 << 24) | ((m & 1))) -); +STATIC mp_obj_t _macro(mp_obj_t self, mp_obj_t a0) { + uint32_t m = mp_obj_get_int_truncated(a0); + common_hal__eve_Macro(EVEHAL(self), m); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(macro_obj, _macro); -STATIC mp_obj_t _nop(mp_obj_t self ) { +STATIC mp_obj_t _nop(mp_obj_t self) { - C4(self, ((45 << 24)) -); + common_hal__eve_Nop(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(nop_obj, _nop); -STATIC mp_obj_t _palettesource(mp_obj_t self , mp_obj_t a0) { - uint32_t addr = mp_obj_get_int_truncated(a0); - C4(self, ((42 << 24) | (((addr) & 4194303))) -); +STATIC mp_obj_t _palettesource(mp_obj_t self, mp_obj_t a0) { + uint32_t addr = mp_obj_get_int_truncated(a0); + common_hal__eve_PaletteSource(EVEHAL(self), addr); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(palettesource_obj, _palettesource); -STATIC mp_obj_t _pointsize(mp_obj_t self , mp_obj_t a0) { - uint32_t size = mp_obj_get_int_truncated(a0); - C4(self, ((13 << 24) | ((size & 8191))) -); +STATIC mp_obj_t _pointsize(mp_obj_t self, mp_obj_t a0) { + uint32_t size = mp_obj_get_int_truncated(a0); + common_hal__eve_PointSize(EVEHAL(self), size); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(pointsize_obj, _pointsize); -STATIC mp_obj_t _restorecontext(mp_obj_t self ) { +STATIC mp_obj_t _restorecontext(mp_obj_t self) { - C4(self, ((35 << 24)) -); + common_hal__eve_RestoreContext(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(restorecontext_obj, _restorecontext); -STATIC mp_obj_t _return(mp_obj_t self ) { +STATIC mp_obj_t _return(mp_obj_t self) { - C4(self, ((36 << 24)) -); + common_hal__eve_Return(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(return_obj, _return); -STATIC mp_obj_t _savecontext(mp_obj_t self ) { +STATIC mp_obj_t _savecontext(mp_obj_t self) { - C4(self, ((34 << 24)) -); + common_hal__eve_SaveContext(EVEHAL(self)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(savecontext_obj, _savecontext); -STATIC mp_obj_t _scissorsize(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t width = mp_obj_get_int_truncated(a0); +STATIC mp_obj_t _scissorsize(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t width = mp_obj_get_int_truncated(a0); uint32_t height = mp_obj_get_int_truncated(a1); - C4(self, ((28 << 24) | ((width & 4095) << 12) | ((height & 4095))) -); + common_hal__eve_ScissorSize(EVEHAL(self), width, height); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(scissorsize_obj, _scissorsize); -STATIC mp_obj_t _scissorxy(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t x = mp_obj_get_int_truncated(a0); - uint32_t y = mp_obj_get_int_truncated(a1); - C4(self, ((27 << 24) | ((x & 2047) << 11) | ((y & 2047))) -); +STATIC mp_obj_t _scissorxy(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t x = mp_obj_get_int_truncated(a0); + uint32_t y = mp_obj_get_int_truncated(a1); + common_hal__eve_ScissorXY(EVEHAL(self), x, y); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(scissorxy_obj, _scissorxy); STATIC mp_obj_t _stencilfunc(size_t n_args, const mp_obj_t *args) { - uint32_t func = mp_obj_get_int_truncated(args[1]); - uint32_t ref = mp_obj_get_int_truncated(args[2]); - uint32_t mask = mp_obj_get_int_truncated(args[3]); - C4(args[0], ((10 << 24) | ((func & 7) << 16) | ((ref & 255) << 8) | ((mask & 255))) -); + uint32_t func = mp_obj_get_int_truncated(args[1]); + uint32_t ref = mp_obj_get_int_truncated(args[2]); + uint32_t mask = mp_obj_get_int_truncated(args[3]); + common_hal__eve_StencilFunc(EVEHAL(args[0]), func, ref, mask); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stencilfunc_obj, 4, 4, _stencilfunc); -STATIC mp_obj_t _stencilmask(mp_obj_t self , mp_obj_t a0) { - uint32_t mask = mp_obj_get_int_truncated(a0); - C4(self, ((19 << 24) | ((mask & 255))) -); +STATIC mp_obj_t _stencilmask(mp_obj_t self, mp_obj_t a0) { + uint32_t mask = mp_obj_get_int_truncated(a0); + common_hal__eve_StencilMask(EVEHAL(self), mask); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(stencilmask_obj, _stencilmask); -STATIC mp_obj_t _stencilop(mp_obj_t self , mp_obj_t a0, mp_obj_t a1) { - uint32_t sfail = mp_obj_get_int_truncated(a0); - uint32_t spass = mp_obj_get_int_truncated(a1); - C4(self, ((12 << 24) | ((sfail & 7) << 3) | ((spass & 7))) -); +STATIC mp_obj_t _stencilop(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + uint32_t sfail = mp_obj_get_int_truncated(a0); + uint32_t spass = mp_obj_get_int_truncated(a1); + common_hal__eve_StencilOp(EVEHAL(self), sfail, spass); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(stencilop_obj, _stencilop); -STATIC mp_obj_t _tagmask(mp_obj_t self , mp_obj_t a0) { - uint32_t mask = mp_obj_get_int_truncated(a0); - C4(self, ((20 << 24) | ((mask & 1))) -); +STATIC mp_obj_t _tagmask(mp_obj_t self, mp_obj_t a0) { + uint32_t mask = mp_obj_get_int_truncated(a0); + common_hal__eve_TagMask(EVEHAL(self), mask); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(tagmask_obj, _tagmask); -STATIC mp_obj_t _tag(mp_obj_t self , mp_obj_t a0) { - uint32_t s = mp_obj_get_int_truncated(a0); - C4(self, ((3 << 24) | ((s & 255))) -); +STATIC mp_obj_t _tag(mp_obj_t self, mp_obj_t a0) { + uint32_t s = mp_obj_get_int_truncated(a0); + common_hal__eve_Tag(EVEHAL(self), s); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(tag_obj, _tag); -STATIC mp_obj_t _vertextranslatex(mp_obj_t self , mp_obj_t a0) { - uint32_t x = mp_obj_get_int_truncated(a0); - C4(self, ((43 << 24) | (((x) & 131071))) -); +STATIC mp_obj_t _vertextranslatex(mp_obj_t self, mp_obj_t a0) { + uint32_t x = mp_obj_get_int_truncated(a0); + common_hal__eve_VertexTranslateX(EVEHAL(self), x); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatex_obj, _vertextranslatex); -STATIC mp_obj_t _vertextranslatey(mp_obj_t self , mp_obj_t a0) { - uint32_t y = mp_obj_get_int_truncated(a0); - C4(self, ((44 << 24) | (((y) & 131071))) -); +STATIC mp_obj_t _vertextranslatey(mp_obj_t self, mp_obj_t a0) { + uint32_t y = mp_obj_get_int_truncated(a0); + common_hal__eve_VertexTranslateY(EVEHAL(self), y); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatey_obj, _vertextranslatey); -#define N_METHODS 47 -#define METHOD_SETUP do { stem_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_AlphaFunc), MP_OBJ_FROM_PTR(&alphafunc_obj) }; stem_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Begin), MP_OBJ_FROM_PTR(&begin_obj) }; stem_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapExtFormat), MP_OBJ_FROM_PTR(&bitmapextformat_obj) }; stem_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapHandle), MP_OBJ_FROM_PTR(&bitmaphandle_obj) }; stem_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapLayoutH), MP_OBJ_FROM_PTR(&bitmaplayouth_obj) }; stem_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapLayout), MP_OBJ_FROM_PTR(&bitmaplayout_obj) }; stem_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSizeH), MP_OBJ_FROM_PTR(&bitmapsizeh_obj) }; stem_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSize), MP_OBJ_FROM_PTR(&bitmapsize_obj) }; stem_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSource), MP_OBJ_FROM_PTR(&bitmapsource_obj) }; stem_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSwizzle), MP_OBJ_FROM_PTR(&bitmapswizzle_obj) }; stem_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformA), MP_OBJ_FROM_PTR(&bitmaptransforma_obj) }; stem_locals_dict_table[11] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformB), MP_OBJ_FROM_PTR(&bitmaptransformb_obj) }; stem_locals_dict_table[12] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformC), MP_OBJ_FROM_PTR(&bitmaptransformc_obj) }; stem_locals_dict_table[13] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformD), MP_OBJ_FROM_PTR(&bitmaptransformd_obj) }; stem_locals_dict_table[14] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformE), MP_OBJ_FROM_PTR(&bitmaptransforme_obj) }; stem_locals_dict_table[15] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformF), MP_OBJ_FROM_PTR(&bitmaptransformf_obj) }; stem_locals_dict_table[16] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BlendFunc), MP_OBJ_FROM_PTR(&blendfunc_obj) }; stem_locals_dict_table[17] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Call), MP_OBJ_FROM_PTR(&call_obj) }; stem_locals_dict_table[18] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Cell), MP_OBJ_FROM_PTR(&cell_obj) }; stem_locals_dict_table[19] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearColorA), MP_OBJ_FROM_PTR(&clearcolora_obj) }; stem_locals_dict_table[20] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearColorRGB), MP_OBJ_FROM_PTR(&clearcolorrgb_obj) }; stem_locals_dict_table[21] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Clear), MP_OBJ_FROM_PTR(&clear_obj) }; stem_locals_dict_table[22] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearStencil), MP_OBJ_FROM_PTR(&clearstencil_obj) }; stem_locals_dict_table[23] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearTag), MP_OBJ_FROM_PTR(&cleartag_obj) }; stem_locals_dict_table[24] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ColorA), MP_OBJ_FROM_PTR(&colora_obj) }; stem_locals_dict_table[25] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ColorMask), MP_OBJ_FROM_PTR(&colormask_obj) }; stem_locals_dict_table[26] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ColorRGB), MP_OBJ_FROM_PTR(&colorrgb_obj) }; stem_locals_dict_table[27] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Display), MP_OBJ_FROM_PTR(&display_obj) }; stem_locals_dict_table[28] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_End), MP_OBJ_FROM_PTR(&end_obj) }; stem_locals_dict_table[29] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Jump), MP_OBJ_FROM_PTR(&jump_obj) }; stem_locals_dict_table[30] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_LineWidth), MP_OBJ_FROM_PTR(&linewidth_obj) }; stem_locals_dict_table[31] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Macro), MP_OBJ_FROM_PTR(¯o_obj) }; stem_locals_dict_table[32] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Nop), MP_OBJ_FROM_PTR(&nop_obj) }; stem_locals_dict_table[33] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_PaletteSource), MP_OBJ_FROM_PTR(&palettesource_obj) }; stem_locals_dict_table[34] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_PointSize), MP_OBJ_FROM_PTR(&pointsize_obj) }; stem_locals_dict_table[35] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_RestoreContext), MP_OBJ_FROM_PTR(&restorecontext_obj) }; stem_locals_dict_table[36] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Return), MP_OBJ_FROM_PTR(&return_obj) }; stem_locals_dict_table[37] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_SaveContext), MP_OBJ_FROM_PTR(&savecontext_obj) }; stem_locals_dict_table[38] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ScissorSize), MP_OBJ_FROM_PTR(&scissorsize_obj) }; stem_locals_dict_table[39] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ScissorXY), MP_OBJ_FROM_PTR(&scissorxy_obj) }; stem_locals_dict_table[40] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_StencilFunc), MP_OBJ_FROM_PTR(&stencilfunc_obj) }; stem_locals_dict_table[41] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_StencilMask), MP_OBJ_FROM_PTR(&stencilmask_obj) }; stem_locals_dict_table[42] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_StencilOp), MP_OBJ_FROM_PTR(&stencilop_obj) }; stem_locals_dict_table[43] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_TagMask), MP_OBJ_FROM_PTR(&tagmask_obj) }; stem_locals_dict_table[44] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Tag), MP_OBJ_FROM_PTR(&tag_obj) }; stem_locals_dict_table[45] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_VertexTranslateX), MP_OBJ_FROM_PTR(&vertextranslatex_obj) }; stem_locals_dict_table[46] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_VertexTranslateY), MP_OBJ_FROM_PTR(&vertextranslatey_obj) }; } while (0) -#define ROM_DECLS { MP_ROM_QSTR(MP_QSTR_AlphaFunc), MP_ROM_PTR(&alphafunc_obj) }, { MP_ROM_QSTR(MP_QSTR_Begin), MP_ROM_PTR(&begin_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapExtFormat), MP_ROM_PTR(&bitmapextformat_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapHandle), MP_ROM_PTR(&bitmaphandle_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapLayoutH), MP_ROM_PTR(&bitmaplayouth_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapLayout), MP_ROM_PTR(&bitmaplayout_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSizeH), MP_ROM_PTR(&bitmapsizeh_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSize), MP_ROM_PTR(&bitmapsize_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSource), MP_ROM_PTR(&bitmapsource_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSwizzle), MP_ROM_PTR(&bitmapswizzle_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformA), MP_ROM_PTR(&bitmaptransforma_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformB), MP_ROM_PTR(&bitmaptransformb_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformC), MP_ROM_PTR(&bitmaptransformc_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformD), MP_ROM_PTR(&bitmaptransformd_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformE), MP_ROM_PTR(&bitmaptransforme_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformF), MP_ROM_PTR(&bitmaptransformf_obj) }, { MP_ROM_QSTR(MP_QSTR_BlendFunc), MP_ROM_PTR(&blendfunc_obj) }, { MP_ROM_QSTR(MP_QSTR_Call), MP_ROM_PTR(&call_obj) }, { MP_ROM_QSTR(MP_QSTR_Cell), MP_ROM_PTR(&cell_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearColorA), MP_ROM_PTR(&clearcolora_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearColorRGB), MP_ROM_PTR(&clearcolorrgb_obj) }, { MP_ROM_QSTR(MP_QSTR_Clear), MP_ROM_PTR(&clear_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearStencil), MP_ROM_PTR(&clearstencil_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearTag), MP_ROM_PTR(&cleartag_obj) }, { MP_ROM_QSTR(MP_QSTR_ColorA), MP_ROM_PTR(&colora_obj) }, { MP_ROM_QSTR(MP_QSTR_ColorMask), MP_ROM_PTR(&colormask_obj) }, { MP_ROM_QSTR(MP_QSTR_ColorRGB), MP_ROM_PTR(&colorrgb_obj) }, { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&display_obj) }, { MP_ROM_QSTR(MP_QSTR_End), MP_ROM_PTR(&end_obj) }, { MP_ROM_QSTR(MP_QSTR_Jump), MP_ROM_PTR(&jump_obj) }, { MP_ROM_QSTR(MP_QSTR_LineWidth), MP_ROM_PTR(&linewidth_obj) }, { MP_ROM_QSTR(MP_QSTR_Macro), MP_ROM_PTR(¯o_obj) }, { MP_ROM_QSTR(MP_QSTR_Nop), MP_ROM_PTR(&nop_obj) }, { MP_ROM_QSTR(MP_QSTR_PaletteSource), MP_ROM_PTR(&palettesource_obj) }, { MP_ROM_QSTR(MP_QSTR_PointSize), MP_ROM_PTR(&pointsize_obj) }, { MP_ROM_QSTR(MP_QSTR_RestoreContext), MP_ROM_PTR(&restorecontext_obj) }, { MP_ROM_QSTR(MP_QSTR_Return), MP_ROM_PTR(&return_obj) }, { MP_ROM_QSTR(MP_QSTR_SaveContext), MP_ROM_PTR(&savecontext_obj) }, { MP_ROM_QSTR(MP_QSTR_ScissorSize), MP_ROM_PTR(&scissorsize_obj) }, { MP_ROM_QSTR(MP_QSTR_ScissorXY), MP_ROM_PTR(&scissorxy_obj) }, { MP_ROM_QSTR(MP_QSTR_StencilFunc), MP_ROM_PTR(&stencilfunc_obj) }, { MP_ROM_QSTR(MP_QSTR_StencilMask), MP_ROM_PTR(&stencilmask_obj) }, { MP_ROM_QSTR(MP_QSTR_StencilOp), MP_ROM_PTR(&stencilop_obj) }, { MP_ROM_QSTR(MP_QSTR_TagMask), MP_ROM_PTR(&tagmask_obj) }, { MP_ROM_QSTR(MP_QSTR_Tag), MP_ROM_PTR(&tag_obj) }, { MP_ROM_QSTR(MP_QSTR_VertexTranslateX), MP_ROM_PTR(&vertextranslatex_obj) }, { MP_ROM_QSTR(MP_QSTR_VertexTranslateY), MP_ROM_PTR(&vertextranslatey_obj) } + +STATIC mp_obj_t _vertexformat(mp_obj_t self, mp_obj_t a0) { + uint32_t frac = mp_obj_get_int_truncated(a0); + common_hal__eve_VertexFormat(EVEHAL(self), frac); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vertexformat_obj, _vertexformat); + +STATIC mp_obj_t _vertex2ii(size_t n_args, const mp_obj_t *args) { + uint32_t x = mp_obj_get_int_truncated(args[1]); + uint32_t y = mp_obj_get_int_truncated(args[2]); + uint32_t handle = (n_args > 3) ? mp_obj_get_int_truncated(args[3]) : 0; + uint32_t cell = (n_args > 4) ? mp_obj_get_int_truncated(args[4]) : 0; + common_hal__eve_Vertex2ii(EVEHAL(args[0]), x, y, handle, cell); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii); +#define N_METHODS 49 +#define METHOD_SETUP do { stem_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_AlphaFunc), MP_OBJ_FROM_PTR(&alphafunc_obj) }; stem_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Begin), MP_OBJ_FROM_PTR(&begin_obj) }; stem_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapExtFormat), MP_OBJ_FROM_PTR(&bitmapextformat_obj) }; stem_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapHandle), MP_OBJ_FROM_PTR(&bitmaphandle_obj) }; stem_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapLayoutH), MP_OBJ_FROM_PTR(&bitmaplayouth_obj) }; stem_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapLayout), MP_OBJ_FROM_PTR(&bitmaplayout_obj) }; stem_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSizeH), MP_OBJ_FROM_PTR(&bitmapsizeh_obj) }; stem_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSize), MP_OBJ_FROM_PTR(&bitmapsize_obj) }; stem_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSource), MP_OBJ_FROM_PTR(&bitmapsource_obj) }; stem_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapSwizzle), MP_OBJ_FROM_PTR(&bitmapswizzle_obj) }; stem_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformA), MP_OBJ_FROM_PTR(&bitmaptransforma_obj) }; stem_locals_dict_table[11] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformB), MP_OBJ_FROM_PTR(&bitmaptransformb_obj) }; stem_locals_dict_table[12] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformC), MP_OBJ_FROM_PTR(&bitmaptransformc_obj) }; stem_locals_dict_table[13] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformD), MP_OBJ_FROM_PTR(&bitmaptransformd_obj) }; stem_locals_dict_table[14] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformE), MP_OBJ_FROM_PTR(&bitmaptransforme_obj) }; stem_locals_dict_table[15] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BitmapTransformF), MP_OBJ_FROM_PTR(&bitmaptransformf_obj) }; stem_locals_dict_table[16] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_BlendFunc), MP_OBJ_FROM_PTR(&blendfunc_obj) }; stem_locals_dict_table[17] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Call), MP_OBJ_FROM_PTR(&call_obj) }; stem_locals_dict_table[18] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Cell), MP_OBJ_FROM_PTR(&cell_obj) }; stem_locals_dict_table[19] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearColorA), MP_OBJ_FROM_PTR(&clearcolora_obj) }; stem_locals_dict_table[20] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearColorRGB), MP_OBJ_FROM_PTR(&clearcolorrgb_obj) }; stem_locals_dict_table[21] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Clear), MP_OBJ_FROM_PTR(&clear_obj) }; stem_locals_dict_table[22] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearStencil), MP_OBJ_FROM_PTR(&clearstencil_obj) }; stem_locals_dict_table[23] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ClearTag), MP_OBJ_FROM_PTR(&cleartag_obj) }; stem_locals_dict_table[24] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ColorA), MP_OBJ_FROM_PTR(&colora_obj) }; stem_locals_dict_table[25] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ColorMask), MP_OBJ_FROM_PTR(&colormask_obj) }; stem_locals_dict_table[26] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ColorRGB), MP_OBJ_FROM_PTR(&colorrgb_obj) }; stem_locals_dict_table[27] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Display), MP_OBJ_FROM_PTR(&display_obj) }; stem_locals_dict_table[28] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_End), MP_OBJ_FROM_PTR(&end_obj) }; stem_locals_dict_table[29] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Jump), MP_OBJ_FROM_PTR(&jump_obj) }; stem_locals_dict_table[30] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_LineWidth), MP_OBJ_FROM_PTR(&linewidth_obj) }; stem_locals_dict_table[31] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Macro), MP_OBJ_FROM_PTR(¯o_obj) }; stem_locals_dict_table[32] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Nop), MP_OBJ_FROM_PTR(&nop_obj) }; stem_locals_dict_table[33] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_PaletteSource), MP_OBJ_FROM_PTR(&palettesource_obj) }; stem_locals_dict_table[34] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_PointSize), MP_OBJ_FROM_PTR(&pointsize_obj) }; stem_locals_dict_table[35] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_RestoreContext), MP_OBJ_FROM_PTR(&restorecontext_obj) }; stem_locals_dict_table[36] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Return), MP_OBJ_FROM_PTR(&return_obj) }; stem_locals_dict_table[37] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_SaveContext), MP_OBJ_FROM_PTR(&savecontext_obj) }; stem_locals_dict_table[38] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ScissorSize), MP_OBJ_FROM_PTR(&scissorsize_obj) }; stem_locals_dict_table[39] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ScissorXY), MP_OBJ_FROM_PTR(&scissorxy_obj) }; stem_locals_dict_table[40] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_StencilFunc), MP_OBJ_FROM_PTR(&stencilfunc_obj) }; stem_locals_dict_table[41] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_StencilMask), MP_OBJ_FROM_PTR(&stencilmask_obj) }; stem_locals_dict_table[42] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_StencilOp), MP_OBJ_FROM_PTR(&stencilop_obj) }; stem_locals_dict_table[43] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_TagMask), MP_OBJ_FROM_PTR(&tagmask_obj) }; stem_locals_dict_table[44] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Tag), MP_OBJ_FROM_PTR(&tag_obj) }; stem_locals_dict_table[45] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_VertexTranslateX), MP_OBJ_FROM_PTR(&vertextranslatex_obj) }; stem_locals_dict_table[46] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_VertexTranslateY), MP_OBJ_FROM_PTR(&vertextranslatey_obj) }; stem_locals_dict_table[47] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_VertexFormat), MP_OBJ_FROM_PTR(&vertexformat_obj) }; stem_locals_dict_table[48] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_Vertex2ii), MP_OBJ_FROM_PTR(&vertex2ii_obj) }; } while (0) +#define ROM_DECLS { MP_ROM_QSTR(MP_QSTR_AlphaFunc), MP_ROM_PTR(&alphafunc_obj) }, { MP_ROM_QSTR(MP_QSTR_Begin), MP_ROM_PTR(&begin_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapExtFormat), MP_ROM_PTR(&bitmapextformat_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapHandle), MP_ROM_PTR(&bitmaphandle_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapLayoutH), MP_ROM_PTR(&bitmaplayouth_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapLayout), MP_ROM_PTR(&bitmaplayout_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSizeH), MP_ROM_PTR(&bitmapsizeh_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSize), MP_ROM_PTR(&bitmapsize_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSource), MP_ROM_PTR(&bitmapsource_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapSwizzle), MP_ROM_PTR(&bitmapswizzle_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformA), MP_ROM_PTR(&bitmaptransforma_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformB), MP_ROM_PTR(&bitmaptransformb_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformC), MP_ROM_PTR(&bitmaptransformc_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformD), MP_ROM_PTR(&bitmaptransformd_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformE), MP_ROM_PTR(&bitmaptransforme_obj) }, { MP_ROM_QSTR(MP_QSTR_BitmapTransformF), MP_ROM_PTR(&bitmaptransformf_obj) }, { MP_ROM_QSTR(MP_QSTR_BlendFunc), MP_ROM_PTR(&blendfunc_obj) }, { MP_ROM_QSTR(MP_QSTR_Call), MP_ROM_PTR(&call_obj) }, { MP_ROM_QSTR(MP_QSTR_Cell), MP_ROM_PTR(&cell_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearColorA), MP_ROM_PTR(&clearcolora_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearColorRGB), MP_ROM_PTR(&clearcolorrgb_obj) }, { MP_ROM_QSTR(MP_QSTR_Clear), MP_ROM_PTR(&clear_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearStencil), MP_ROM_PTR(&clearstencil_obj) }, { MP_ROM_QSTR(MP_QSTR_ClearTag), MP_ROM_PTR(&cleartag_obj) }, { MP_ROM_QSTR(MP_QSTR_ColorA), MP_ROM_PTR(&colora_obj) }, { MP_ROM_QSTR(MP_QSTR_ColorMask), MP_ROM_PTR(&colormask_obj) }, { MP_ROM_QSTR(MP_QSTR_ColorRGB), MP_ROM_PTR(&colorrgb_obj) }, { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&display_obj) }, { MP_ROM_QSTR(MP_QSTR_End), MP_ROM_PTR(&end_obj) }, { MP_ROM_QSTR(MP_QSTR_Jump), MP_ROM_PTR(&jump_obj) }, { MP_ROM_QSTR(MP_QSTR_LineWidth), MP_ROM_PTR(&linewidth_obj) }, { MP_ROM_QSTR(MP_QSTR_Macro), MP_ROM_PTR(¯o_obj) }, { MP_ROM_QSTR(MP_QSTR_Nop), MP_ROM_PTR(&nop_obj) }, { MP_ROM_QSTR(MP_QSTR_PaletteSource), MP_ROM_PTR(&palettesource_obj) }, { MP_ROM_QSTR(MP_QSTR_PointSize), MP_ROM_PTR(&pointsize_obj) }, { MP_ROM_QSTR(MP_QSTR_RestoreContext), MP_ROM_PTR(&restorecontext_obj) }, { MP_ROM_QSTR(MP_QSTR_Return), MP_ROM_PTR(&return_obj) }, { MP_ROM_QSTR(MP_QSTR_SaveContext), MP_ROM_PTR(&savecontext_obj) }, { MP_ROM_QSTR(MP_QSTR_ScissorSize), MP_ROM_PTR(&scissorsize_obj) }, { MP_ROM_QSTR(MP_QSTR_ScissorXY), MP_ROM_PTR(&scissorxy_obj) }, { MP_ROM_QSTR(MP_QSTR_StencilFunc), MP_ROM_PTR(&stencilfunc_obj) }, { MP_ROM_QSTR(MP_QSTR_StencilMask), MP_ROM_PTR(&stencilmask_obj) }, { MP_ROM_QSTR(MP_QSTR_StencilOp), MP_ROM_PTR(&stencilop_obj) }, { MP_ROM_QSTR(MP_QSTR_TagMask), MP_ROM_PTR(&tagmask_obj) }, { MP_ROM_QSTR(MP_QSTR_Tag), MP_ROM_PTR(&tag_obj) }, { MP_ROM_QSTR(MP_QSTR_VertexTranslateX), MP_ROM_PTR(&vertextranslatex_obj) }, { MP_ROM_QSTR(MP_QSTR_VertexTranslateY), MP_ROM_PTR(&vertextranslatey_obj) }, { MP_ROM_QSTR(MP_QSTR_VertexFormat), MP_ROM_PTR(&vertexformat_obj) }, { MP_ROM_QSTR(MP_QSTR_Vertex2ii), MP_ROM_PTR(&vertex2ii_obj) } diff --git a/shared-module/_eve/__init__.c b/shared-module/_eve/__init__.c new file mode 100644 index 000000000..ca6fd4031 --- /dev/null +++ b/shared-module/_eve/__init__.c @@ -0,0 +1,270 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 James Bowman for Excamera Labs + * + * 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 +#include +#include "py/runtime.h" +#include "shared-module/_eve/__init__.h" + +STATIC void write(common_hal__eve_t *eve, size_t len, void *buf) { + eve->dest[2] = mp_obj_new_bytearray_by_ref(len, buf); + mp_call_method_n_kw(1, 0, eve->dest); +} + +void common_hal__eve_flush(common_hal__eve_t *eve) { + if (eve->n != 0) { + write(eve, eve->n, eve->buf); + eve->n = 0; + } +} + +static void *append(common_hal__eve_t *eve, size_t m) { + if ((eve->n + m) > sizeof(eve->buf)) + common_hal__eve_flush(eve); + uint8_t *r = eve->buf + eve->n; + eve->n += m; + return (void*)r; +} + +void common_hal__eve_add(common_hal__eve_t *eve, size_t len, void *buf) { + if (len <= sizeof(eve->buf)) { + uint8_t *p = (uint8_t*)append(eve, len); + // memcpy(p, buffer_info.buf, buffer_info.len); + uint8_t *s = buf; for (size_t i = 0; i < len; i++) *p++ = *s++; + } else { + common_hal__eve_flush(eve); + write(eve, len, buf); + } +} + +#define C4(eve, u) (*(uint32_t*)append((eve), sizeof(uint32_t)) = (u)) + +void common_hal__eve_Vertex2f(common_hal__eve_t *eve, mp_float_t x, mp_float_t y) { + int16_t ix = (int)(eve->vscale * x); + int16_t iy = (int)(eve->vscale * y); + C4(eve, (1 << 30) | ((ix & 32767) << 15) | (iy & 32767)); +} + +void common_hal__eve_VertexFormat(common_hal__eve_t *eve, uint32_t frac) +{ + C4(eve, ((27 << 24) | ((frac & 7)))); + eve->vscale = 1 << eve->vscale; +} + + + +void common_hal__eve_AlphaFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref) { + C4(eve, ((9 << 24) | ((func & 7) << 8) | ((ref & 255)))); +} + +void common_hal__eve_Begin(common_hal__eve_t *eve, uint32_t prim) { + C4(eve, ((31 << 24) | ((prim & 15)))); +} + +void common_hal__eve_BitmapExtFormat(common_hal__eve_t *eve, uint32_t fmt) { + C4(eve, ((46 << 24) | (fmt & 65535))); +} + +void common_hal__eve_BitmapHandle(common_hal__eve_t *eve, uint32_t handle) { + C4(eve, ((5 << 24) | ((handle & 31)))); +} + +void common_hal__eve_BitmapLayoutH(common_hal__eve_t *eve, uint32_t linestride, uint32_t height) { + C4(eve, ((40 << 24) | (((linestride) & 3) << 2) | (((height) & 3)))); +} + +void common_hal__eve_BitmapLayout(common_hal__eve_t *eve, uint32_t format, uint32_t linestride, uint32_t height) { + C4(eve, ((7 << 24) | ((format & 31) << 19) | ((linestride & 1023) << 9) | ((height & 511)))); +} + +void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_t height) { + C4(eve, ((41 << 24) | (((width) & 3) << 2) | (((height) & 3)))); +} + +void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height) { + C4(eve, ((8 << 24) | ((filter & 1) << 20) | ((wrapx & 1) << 19) | ((wrapy & 1) << 18) | ((width & 511) << 9) | ((height & 511)))); +} + +void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr) { + C4(eve, ((1 << 24) | ((addr & 0xffffff)))); +} + +void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { + C4(eve, ((47 << 24) | ((r & 7) << 9) | ((g & 7) << 6) | ((b & 7) << 3) | ((a & 7)))); +} + +void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t a, uint32_t p) { + C4(eve, ((21 << 24) | ((p & 1) << 17) | ((a & 131071)))); +} + +void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t b, uint32_t p) { + C4(eve, ((22 << 24) | ((p & 1) << 17) | ((b & 131071)))); +} + +void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t c, uint32_t p) { + C4(eve, ((23 << 24) | ((p & 1) << 17) | ((c & 16777215)))); +} + +void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t d, uint32_t p) { + C4(eve, ((24 << 24) | ((p & 1) << 17) | ((d & 131071)))); +} + +void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t e, uint32_t p) { + C4(eve, ((25 << 24) | ((p & 1) << 17) | ((e & 131071)))); +} + +void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t f, uint32_t p) { + C4(eve, ((26 << 24) | ((p & 1) << 17) | ((f & 16777215)))); +} + +void common_hal__eve_BlendFunc(common_hal__eve_t *eve, uint32_t src, uint32_t dst) { + C4(eve, ((11 << 24) | ((src & 7) << 3) | ((dst & 7)))); +} + +void common_hal__eve_Call(common_hal__eve_t *eve, uint32_t dest) { + C4(eve, ((29 << 24) | ((dest & 65535)))); +} + +void common_hal__eve_Cell(common_hal__eve_t *eve, uint32_t cell) { + C4(eve, ((6 << 24) | ((cell & 127)))); +} + +void common_hal__eve_ClearColorA(common_hal__eve_t *eve, uint32_t alpha) { + C4(eve, ((15 << 24) | ((alpha & 255)))); +} + +void common_hal__eve_ClearColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue) { + C4(eve, ((2 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | ((blue & 255)))); +} + +void common_hal__eve_Clear(common_hal__eve_t *eve, uint32_t c, uint32_t s, uint32_t t) { + C4(eve, ((38 << 24) | ((c & 1) << 2) | ((s & 1) << 1) | ((t & 1)))); +} + +void common_hal__eve_ClearStencil(common_hal__eve_t *eve, uint32_t s) { + C4(eve, ((17 << 24) | ((s & 255)))); +} + +void common_hal__eve_ClearTag(common_hal__eve_t *eve, uint32_t s) { + C4(eve, ((18 << 24) | ((s & 255)))); +} + +void common_hal__eve_ColorA(common_hal__eve_t *eve, uint32_t alpha) { + C4(eve, ((16 << 24) | ((alpha & 255)))); +} + +void common_hal__eve_ColorMask(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { + C4(eve, ((32 << 24) | ((r & 1) << 3) | ((g & 1) << 2) | ((b & 1) << 1) | ((a & 1)))); +} + +void common_hal__eve_ColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue) { + C4(eve, ((4 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | ((blue & 255)))); +} + +void common_hal__eve_Display(common_hal__eve_t *eve) { + C4(eve, ((0 << 24))); +} + +void common_hal__eve_End(common_hal__eve_t *eve) { + C4(eve, ((33 << 24))); +} + +void common_hal__eve_Jump(common_hal__eve_t *eve, uint32_t dest) { + C4(eve, ((30 << 24) | ((dest & 65535)))); +} + +void common_hal__eve_LineWidth(common_hal__eve_t *eve, uint32_t width) { + C4(eve, ((14 << 24) | ((width & 4095)))); +} + +void common_hal__eve_Macro(common_hal__eve_t *eve, uint32_t m) { + C4(eve, ((37 << 24) | ((m & 1)))); +} + +void common_hal__eve_Nop(common_hal__eve_t *eve) { + C4(eve, ((45 << 24))); +} + +void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr) { + C4(eve, ((42 << 24) | (((addr) & 4194303)))); +} + +void common_hal__eve_PointSize(common_hal__eve_t *eve, uint32_t size) { + C4(eve, ((13 << 24) | ((size & 8191)))); +} + +void common_hal__eve_RestoreContext(common_hal__eve_t *eve) { + C4(eve, ((35 << 24))); +} + +void common_hal__eve_Return(common_hal__eve_t *eve) { + C4(eve, ((36 << 24))); +} + +void common_hal__eve_SaveContext(common_hal__eve_t *eve) { + C4(eve, ((34 << 24))); +} + +void common_hal__eve_ScissorSize(common_hal__eve_t *eve, uint32_t width, uint32_t height) { + C4(eve, ((28 << 24) | ((width & 4095) << 12) | ((height & 4095)))); +} + +void common_hal__eve_ScissorXY(common_hal__eve_t *eve, uint32_t x, uint32_t y) { + C4(eve, ((27 << 24) | ((x & 2047) << 11) | ((y & 2047)))); +} + +void common_hal__eve_StencilFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref, uint32_t mask) { + C4(eve, ((10 << 24) | ((func & 7) << 16) | ((ref & 255) << 8) | ((mask & 255)))); +} + +void common_hal__eve_StencilMask(common_hal__eve_t *eve, uint32_t mask) { + C4(eve, ((19 << 24) | ((mask & 255)))); +} + +void common_hal__eve_StencilOp(common_hal__eve_t *eve, uint32_t sfail, uint32_t spass) { + C4(eve, ((12 << 24) | ((sfail & 7) << 3) | ((spass & 7)))); +} + +void common_hal__eve_TagMask(common_hal__eve_t *eve, uint32_t mask) { + C4(eve, ((20 << 24) | ((mask & 1)))); +} + +void common_hal__eve_Tag(common_hal__eve_t *eve, uint32_t s) { + C4(eve, ((3 << 24) | ((s & 255)))); +} + +void common_hal__eve_VertexTranslateX(common_hal__eve_t *eve, uint32_t x) { + C4(eve, ((43 << 24) | (((x) & 131071)))); +} + +void common_hal__eve_VertexTranslateY(common_hal__eve_t *eve, uint32_t y) { + C4(eve, ((44 << 24) | (((y) & 131071)))); +} + +void common_hal__eve_Vertex2ii(common_hal__eve_t *eve, uint32_t x, uint32_t y, uint32_t handle, uint32_t cell) { + C4(eve, ((2 << 30) | (((x) & 511) << 21) | (((y) & 511) << 12) | (((handle) & 31) << 7) | (((cell) & 127) << 0))); +} + diff --git a/shared-module/_eve/__init__.h b/shared-module/_eve/__init__.h new file mode 100644 index 000000000..f2fd7a943 --- /dev/null +++ b/shared-module/_eve/__init__.h @@ -0,0 +1,91 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 James Bowman for Excamera Labs + * + * 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__EVE___INIT___H +#define MICROPY_INCLUDED_SHARED_MODULE__EVE___INIT___H + +typedef struct _common_hal__eve_t { + mp_obj_t dest[3]; // Own 'write' method, plus argument + int vscale; // fixed-point scaling used for Vertex2f + size_t n; // Current size of command buffer + uint8_t buf[512]; // Command buffer +} common_hal__eve_t; + +void common_hal__eve_flush(common_hal__eve_t *eve); +void common_hal__eve_add(common_hal__eve_t *eve, size_t len, void *buf); +void common_hal__eve_Vertex2f(common_hal__eve_t *eve, mp_float_t x, mp_float_t y); + +void common_hal__eve_AlphaFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref); +void common_hal__eve_Begin(common_hal__eve_t *eve, uint32_t prim); +void common_hal__eve_BitmapExtFormat(common_hal__eve_t *eve, uint32_t fmt); +void common_hal__eve_BitmapHandle(common_hal__eve_t *eve, uint32_t handle); +void common_hal__eve_BitmapLayoutH(common_hal__eve_t *eve, uint32_t linestride, uint32_t height); +void common_hal__eve_BitmapLayout(common_hal__eve_t *eve, uint32_t format, uint32_t linestride, uint32_t height); +void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_t height); +void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height); +void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr); +void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); +void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t a, uint32_t p); +void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t b, uint32_t p); +void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t c, uint32_t p); +void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t d, uint32_t p); +void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t e, uint32_t p); +void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t f, uint32_t p); +void common_hal__eve_BlendFunc(common_hal__eve_t *eve, uint32_t src, uint32_t dst); +void common_hal__eve_Call(common_hal__eve_t *eve, uint32_t dest); +void common_hal__eve_Cell(common_hal__eve_t *eve, uint32_t cell); +void common_hal__eve_ClearColorA(common_hal__eve_t *eve, uint32_t alpha); +void common_hal__eve_ClearColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue); +void common_hal__eve_Clear(common_hal__eve_t *eve, uint32_t c, uint32_t s, uint32_t t); +void common_hal__eve_ClearStencil(common_hal__eve_t *eve, uint32_t s); +void common_hal__eve_ClearTag(common_hal__eve_t *eve, uint32_t s); +void common_hal__eve_ColorA(common_hal__eve_t *eve, uint32_t alpha); +void common_hal__eve_ColorMask(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); +void common_hal__eve_ColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue); +void common_hal__eve_Display(common_hal__eve_t *eve); +void common_hal__eve_End(common_hal__eve_t *eve); +void common_hal__eve_Jump(common_hal__eve_t *eve, uint32_t dest); +void common_hal__eve_LineWidth(common_hal__eve_t *eve, uint32_t width); +void common_hal__eve_Macro(common_hal__eve_t *eve, uint32_t m); +void common_hal__eve_Nop(common_hal__eve_t *eve); +void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr); +void common_hal__eve_PointSize(common_hal__eve_t *eve, uint32_t size); +void common_hal__eve_RestoreContext(common_hal__eve_t *eve); +void common_hal__eve_Return(common_hal__eve_t *eve); +void common_hal__eve_SaveContext(common_hal__eve_t *eve); +void common_hal__eve_ScissorSize(common_hal__eve_t *eve, uint32_t width, uint32_t height); +void common_hal__eve_ScissorXY(common_hal__eve_t *eve, uint32_t x, uint32_t y); +void common_hal__eve_StencilFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref, uint32_t mask); +void common_hal__eve_StencilMask(common_hal__eve_t *eve, uint32_t mask); +void common_hal__eve_StencilOp(common_hal__eve_t *eve, uint32_t sfail, uint32_t spass); +void common_hal__eve_TagMask(common_hal__eve_t *eve, uint32_t mask); +void common_hal__eve_Tag(common_hal__eve_t *eve, uint32_t s); +void common_hal__eve_VertexTranslateX(common_hal__eve_t *eve, uint32_t x); +void common_hal__eve_VertexTranslateY(common_hal__eve_t *eve, uint32_t y); +void common_hal__eve_VertexFormat(common_hal__eve_t *eve, uint32_t frac); +void common_hal__eve_Vertex2ii(common_hal__eve_t *eve, uint32_t x, uint32_t y, uint32_t handle, uint32_t cell); + +#endif // MICROPY_INCLUDED_SHARED_MODULE__EVE___INIT___H -- cgit v1.2.3 From f101ff60c505f5ddcdd69cfd1f58e83c4676eb46 Mon Sep 17 00:00:00 2001 From: James Bowman Date: Fri, 7 Feb 2020 17:10:19 -0800 Subject: Move _eve module declarations into shared-bindings header --- shared-bindings/_eve/__init__.c | 3 +- shared-bindings/_eve/__init__.h | 84 +++++++++++++++++++++++++++++++++++++++++ shared-module/_eve/__init__.h | 54 -------------------------- 3 files changed, 86 insertions(+), 55 deletions(-) create mode 100644 shared-bindings/_eve/__init__.h (limited to 'shared-module') diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c index b398c0a5d..d3076afbf 100644 --- a/shared-bindings/_eve/__init__.c +++ b/shared-bindings/_eve/__init__.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2020 James Bowman + * Copyright (c) 2020 James Bowman for Excamera Labs * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,6 +32,7 @@ #include "py/binary.h" #include "shared-module/_eve/__init__.h" +#include "shared-bindings/_eve/__init__.h" //| :mod:`_eve` --- low-level BridgeTek EVE bindings //| ================================================ diff --git a/shared-bindings/_eve/__init__.h b/shared-bindings/_eve/__init__.h new file mode 100644 index 000000000..6287fb606 --- /dev/null +++ b/shared-bindings/_eve/__init__.h @@ -0,0 +1,84 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 James Bowman for Excamera Labs + * + * 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__EVE___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS__EVE___INIT___H + +void common_hal__eve_flush(common_hal__eve_t *eve); +void common_hal__eve_add(common_hal__eve_t *eve, size_t len, void *buf); +void common_hal__eve_Vertex2f(common_hal__eve_t *eve, mp_float_t x, mp_float_t y); + +void common_hal__eve_AlphaFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref); +void common_hal__eve_Begin(common_hal__eve_t *eve, uint32_t prim); +void common_hal__eve_BitmapExtFormat(common_hal__eve_t *eve, uint32_t fmt); +void common_hal__eve_BitmapHandle(common_hal__eve_t *eve, uint32_t handle); +void common_hal__eve_BitmapLayoutH(common_hal__eve_t *eve, uint32_t linestride, uint32_t height); +void common_hal__eve_BitmapLayout(common_hal__eve_t *eve, uint32_t format, uint32_t linestride, uint32_t height); +void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_t height); +void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height); +void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr); +void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); +void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t a, uint32_t p); +void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t b, uint32_t p); +void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t c, uint32_t p); +void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t d, uint32_t p); +void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t e, uint32_t p); +void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t f, uint32_t p); +void common_hal__eve_BlendFunc(common_hal__eve_t *eve, uint32_t src, uint32_t dst); +void common_hal__eve_Call(common_hal__eve_t *eve, uint32_t dest); +void common_hal__eve_Cell(common_hal__eve_t *eve, uint32_t cell); +void common_hal__eve_ClearColorA(common_hal__eve_t *eve, uint32_t alpha); +void common_hal__eve_ClearColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue); +void common_hal__eve_Clear(common_hal__eve_t *eve, uint32_t c, uint32_t s, uint32_t t); +void common_hal__eve_ClearStencil(common_hal__eve_t *eve, uint32_t s); +void common_hal__eve_ClearTag(common_hal__eve_t *eve, uint32_t s); +void common_hal__eve_ColorA(common_hal__eve_t *eve, uint32_t alpha); +void common_hal__eve_ColorMask(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); +void common_hal__eve_ColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue); +void common_hal__eve_Display(common_hal__eve_t *eve); +void common_hal__eve_End(common_hal__eve_t *eve); +void common_hal__eve_Jump(common_hal__eve_t *eve, uint32_t dest); +void common_hal__eve_LineWidth(common_hal__eve_t *eve, uint32_t width); +void common_hal__eve_Macro(common_hal__eve_t *eve, uint32_t m); +void common_hal__eve_Nop(common_hal__eve_t *eve); +void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr); +void common_hal__eve_PointSize(common_hal__eve_t *eve, uint32_t size); +void common_hal__eve_RestoreContext(common_hal__eve_t *eve); +void common_hal__eve_Return(common_hal__eve_t *eve); +void common_hal__eve_SaveContext(common_hal__eve_t *eve); +void common_hal__eve_ScissorSize(common_hal__eve_t *eve, uint32_t width, uint32_t height); +void common_hal__eve_ScissorXY(common_hal__eve_t *eve, uint32_t x, uint32_t y); +void common_hal__eve_StencilFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref, uint32_t mask); +void common_hal__eve_StencilMask(common_hal__eve_t *eve, uint32_t mask); +void common_hal__eve_StencilOp(common_hal__eve_t *eve, uint32_t sfail, uint32_t spass); +void common_hal__eve_TagMask(common_hal__eve_t *eve, uint32_t mask); +void common_hal__eve_Tag(common_hal__eve_t *eve, uint32_t s); +void common_hal__eve_VertexTranslateX(common_hal__eve_t *eve, uint32_t x); +void common_hal__eve_VertexTranslateY(common_hal__eve_t *eve, uint32_t y); +void common_hal__eve_VertexFormat(common_hal__eve_t *eve, uint32_t frac); +void common_hal__eve_Vertex2ii(common_hal__eve_t *eve, uint32_t x, uint32_t y, uint32_t handle, uint32_t cell); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS__EVE___INIT___H diff --git a/shared-module/_eve/__init__.h b/shared-module/_eve/__init__.h index f2fd7a943..5217d860a 100644 --- a/shared-module/_eve/__init__.h +++ b/shared-module/_eve/__init__.h @@ -34,58 +34,4 @@ typedef struct _common_hal__eve_t { uint8_t buf[512]; // Command buffer } common_hal__eve_t; -void common_hal__eve_flush(common_hal__eve_t *eve); -void common_hal__eve_add(common_hal__eve_t *eve, size_t len, void *buf); -void common_hal__eve_Vertex2f(common_hal__eve_t *eve, mp_float_t x, mp_float_t y); - -void common_hal__eve_AlphaFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref); -void common_hal__eve_Begin(common_hal__eve_t *eve, uint32_t prim); -void common_hal__eve_BitmapExtFormat(common_hal__eve_t *eve, uint32_t fmt); -void common_hal__eve_BitmapHandle(common_hal__eve_t *eve, uint32_t handle); -void common_hal__eve_BitmapLayoutH(common_hal__eve_t *eve, uint32_t linestride, uint32_t height); -void common_hal__eve_BitmapLayout(common_hal__eve_t *eve, uint32_t format, uint32_t linestride, uint32_t height); -void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_t height); -void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height); -void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr); -void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); -void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t a, uint32_t p); -void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t b, uint32_t p); -void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t c, uint32_t p); -void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t d, uint32_t p); -void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t e, uint32_t p); -void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t f, uint32_t p); -void common_hal__eve_BlendFunc(common_hal__eve_t *eve, uint32_t src, uint32_t dst); -void common_hal__eve_Call(common_hal__eve_t *eve, uint32_t dest); -void common_hal__eve_Cell(common_hal__eve_t *eve, uint32_t cell); -void common_hal__eve_ClearColorA(common_hal__eve_t *eve, uint32_t alpha); -void common_hal__eve_ClearColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue); -void common_hal__eve_Clear(common_hal__eve_t *eve, uint32_t c, uint32_t s, uint32_t t); -void common_hal__eve_ClearStencil(common_hal__eve_t *eve, uint32_t s); -void common_hal__eve_ClearTag(common_hal__eve_t *eve, uint32_t s); -void common_hal__eve_ColorA(common_hal__eve_t *eve, uint32_t alpha); -void common_hal__eve_ColorMask(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); -void common_hal__eve_ColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue); -void common_hal__eve_Display(common_hal__eve_t *eve); -void common_hal__eve_End(common_hal__eve_t *eve); -void common_hal__eve_Jump(common_hal__eve_t *eve, uint32_t dest); -void common_hal__eve_LineWidth(common_hal__eve_t *eve, uint32_t width); -void common_hal__eve_Macro(common_hal__eve_t *eve, uint32_t m); -void common_hal__eve_Nop(common_hal__eve_t *eve); -void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr); -void common_hal__eve_PointSize(common_hal__eve_t *eve, uint32_t size); -void common_hal__eve_RestoreContext(common_hal__eve_t *eve); -void common_hal__eve_Return(common_hal__eve_t *eve); -void common_hal__eve_SaveContext(common_hal__eve_t *eve); -void common_hal__eve_ScissorSize(common_hal__eve_t *eve, uint32_t width, uint32_t height); -void common_hal__eve_ScissorXY(common_hal__eve_t *eve, uint32_t x, uint32_t y); -void common_hal__eve_StencilFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref, uint32_t mask); -void common_hal__eve_StencilMask(common_hal__eve_t *eve, uint32_t mask); -void common_hal__eve_StencilOp(common_hal__eve_t *eve, uint32_t sfail, uint32_t spass); -void common_hal__eve_TagMask(common_hal__eve_t *eve, uint32_t mask); -void common_hal__eve_Tag(common_hal__eve_t *eve, uint32_t s); -void common_hal__eve_VertexTranslateX(common_hal__eve_t *eve, uint32_t x); -void common_hal__eve_VertexTranslateY(common_hal__eve_t *eve, uint32_t y); -void common_hal__eve_VertexFormat(common_hal__eve_t *eve, uint32_t frac); -void common_hal__eve_Vertex2ii(common_hal__eve_t *eve, uint32_t x, uint32_t y, uint32_t handle, uint32_t cell); - #endif // MICROPY_INCLUDED_SHARED_MODULE__EVE___INIT___H -- cgit v1.2.3 From a87dee2f66732690bde509e7d1221cce4c1fb466 Mon Sep 17 00:00:00 2001 From: James Bowman Date: Mon, 10 Feb 2020 19:34:38 -0800 Subject: Correct the BitmapTransform operations. Correct argument order better argument naming fix copypaste bug on C and F arguments --- shared-bindings/_eve/__init__.c | 58 ++++++++++++++++++--------------- shared-bindings/_eve/__init__.h | 12 +++---- shared-module/_eve/__init__.c | 71 ++++++++++++++++++++++++++++++++++------- 3 files changed, 97 insertions(+), 44 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c index 8ea9d033f..97b4e8c47 100644 --- a/shared-bindings/_eve/__init__.c +++ b/shared-bindings/_eve/__init__.c @@ -268,13 +268,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapswizzle_obj, 5, 5, _bitmapswizz //| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 //| :param int v: The :math:`a` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256 //| +//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0. +//| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| STATIC mp_obj_t _bitmaptransforma(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t a = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformA(EVEHAL(self), a, p); + uint32_t p = mp_obj_get_int_truncated(a0); + uint32_t v = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformA(EVEHAL(self), p, v); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforma_obj, _bitmaptransforma); @@ -286,33 +288,34 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforma_obj, _bitmaptransforma); //| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 //| :param int v: The :math:`b` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0 //| +//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0. +//| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| STATIC mp_obj_t _bitmaptransformb(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t b = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformB(EVEHAL(self), b, p); + uint32_t p = mp_obj_get_int_truncated(a0); + uint32_t v = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformB(EVEHAL(self), p, v); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformb_obj, _bitmaptransformb); -//| .. method:: BitmapTransformC(c) +//| .. method:: BitmapTransformC(v) //| //| Set the :math:`c` component of the bitmap transform matrix //| -//| :param int c: The :math:`c` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0 +//| :param int v: The :math:`c` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0 //| //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| -STATIC mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t c = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformC(EVEHAL(self), c, p); +STATIC mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0) { + uint32_t v = mp_obj_get_int_truncated(a0); + common_hal__eve_BitmapTransformC(EVEHAL(self), v); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformc_obj, _bitmaptransformc); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformc_obj, _bitmaptransformc); //| .. method:: BitmapTransformD(p, v) //| @@ -321,13 +324,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformc_obj, _bitmaptransformc); //| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 //| :param int v: The :math:`d` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0 //| +//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0. +//| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| STATIC mp_obj_t _bitmaptransformd(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t d = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformD(EVEHAL(self), d, p); + uint32_t p = mp_obj_get_int_truncated(a0); + uint32_t v = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformD(EVEHAL(self), p, v); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformd_obj, _bitmaptransformd); @@ -339,33 +344,34 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformd_obj, _bitmaptransformd); //| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 //| :param int v: The :math:`e` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256 //| +//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0. +//| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| STATIC mp_obj_t _bitmaptransforme(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t e = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformE(EVEHAL(self), e, p); + uint32_t p = mp_obj_get_int_truncated(a0); + uint32_t v = mp_obj_get_int_truncated(a1); + common_hal__eve_BitmapTransformE(EVEHAL(self), p, v); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforme_obj, _bitmaptransforme); -//| .. method:: BitmapTransformF(f) +//| .. method:: BitmapTransformF(v) //| //| Set the :math:`f` component of the bitmap transform matrix //| -//| :param int f: The :math:`f` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0 +//| :param int v: The :math:`f` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0 //| //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| -STATIC mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t f = mp_obj_get_int_truncated(a0); - uint32_t p = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformF(EVEHAL(self), f, p); +STATIC mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0) { + uint32_t v = mp_obj_get_int_truncated(a0); + common_hal__eve_BitmapTransformF(EVEHAL(self), v); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformf_obj, _bitmaptransformf); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformf_obj, _bitmaptransformf); //| .. method:: BlendFunc(src, dst) //| diff --git a/shared-bindings/_eve/__init__.h b/shared-bindings/_eve/__init__.h index 6287fb606..759a629bb 100644 --- a/shared-bindings/_eve/__init__.h +++ b/shared-bindings/_eve/__init__.h @@ -41,12 +41,12 @@ void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_ void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height); void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr); void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); -void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t a, uint32_t p); -void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t b, uint32_t p); -void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t c, uint32_t p); -void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t d, uint32_t p); -void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t e, uint32_t p); -void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t f, uint32_t p); +void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t p, uint32_t v); +void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t p, uint32_t v); +void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t v); +void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t p, uint32_t v); +void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t p, uint32_t v); +void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t v); void common_hal__eve_BlendFunc(common_hal__eve_t *eve, uint32_t src, uint32_t dst); void common_hal__eve_Call(common_hal__eve_t *eve, uint32_t dest); void common_hal__eve_Cell(common_hal__eve_t *eve, uint32_t cell); diff --git a/shared-module/_eve/__init__.c b/shared-module/_eve/__init__.c index ca6fd4031..2c93eb69f 100644 --- a/shared-module/_eve/__init__.c +++ b/shared-module/_eve/__init__.c @@ -80,190 +80,237 @@ void common_hal__eve_AlphaFunc(common_hal__eve_t *eve, uint32_t func, uint32_t r C4(eve, ((9 << 24) | ((func & 7) << 8) | ((ref & 255)))); } + void common_hal__eve_Begin(common_hal__eve_t *eve, uint32_t prim) { C4(eve, ((31 << 24) | ((prim & 15)))); } + void common_hal__eve_BitmapExtFormat(common_hal__eve_t *eve, uint32_t fmt) { C4(eve, ((46 << 24) | (fmt & 65535))); } + void common_hal__eve_BitmapHandle(common_hal__eve_t *eve, uint32_t handle) { C4(eve, ((5 << 24) | ((handle & 31)))); } + void common_hal__eve_BitmapLayoutH(common_hal__eve_t *eve, uint32_t linestride, uint32_t height) { C4(eve, ((40 << 24) | (((linestride) & 3) << 2) | (((height) & 3)))); } + void common_hal__eve_BitmapLayout(common_hal__eve_t *eve, uint32_t format, uint32_t linestride, uint32_t height) { C4(eve, ((7 << 24) | ((format & 31) << 19) | ((linestride & 1023) << 9) | ((height & 511)))); } + void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_t height) { C4(eve, ((41 << 24) | (((width) & 3) << 2) | (((height) & 3)))); } + void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height) { C4(eve, ((8 << 24) | ((filter & 1) << 20) | ((wrapx & 1) << 19) | ((wrapy & 1) << 18) | ((width & 511) << 9) | ((height & 511)))); } + void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr) { C4(eve, ((1 << 24) | ((addr & 0xffffff)))); } + void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { C4(eve, ((47 << 24) | ((r & 7) << 9) | ((g & 7) << 6) | ((b & 7) << 3) | ((a & 7)))); } -void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t a, uint32_t p) { - C4(eve, ((21 << 24) | ((p & 1) << 17) | ((a & 131071)))); + +void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t p, uint32_t v) { + C4(eve, ((21 << 24) | ((p & 1) << 17) | ((v & 131071)))); } -void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t b, uint32_t p) { - C4(eve, ((22 << 24) | ((p & 1) << 17) | ((b & 131071)))); + +void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t p, uint32_t v) { + C4(eve, ((22 << 24) | ((p & 1) << 17) | ((v & 131071)))); } -void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t c, uint32_t p) { - C4(eve, ((23 << 24) | ((p & 1) << 17) | ((c & 16777215)))); + +void common_hal__eve_BitmapTransformC(common_hal__eve_t *eve, uint32_t v) { + C4(eve, ((23 << 24) | ((v & 16777215)))); } -void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t d, uint32_t p) { - C4(eve, ((24 << 24) | ((p & 1) << 17) | ((d & 131071)))); + +void common_hal__eve_BitmapTransformD(common_hal__eve_t *eve, uint32_t p, uint32_t v) { + C4(eve, ((24 << 24) | ((p & 1) << 17) | ((v & 131071)))); } -void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t e, uint32_t p) { - C4(eve, ((25 << 24) | ((p & 1) << 17) | ((e & 131071)))); + +void common_hal__eve_BitmapTransformE(common_hal__eve_t *eve, uint32_t p, uint32_t v) { + C4(eve, ((25 << 24) | ((p & 1) << 17) | ((v & 131071)))); } -void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t f, uint32_t p) { - C4(eve, ((26 << 24) | ((p & 1) << 17) | ((f & 16777215)))); + +void common_hal__eve_BitmapTransformF(common_hal__eve_t *eve, uint32_t v) { + C4(eve, ((26 << 24) | ((v & 16777215)))); } + void common_hal__eve_BlendFunc(common_hal__eve_t *eve, uint32_t src, uint32_t dst) { C4(eve, ((11 << 24) | ((src & 7) << 3) | ((dst & 7)))); } + void common_hal__eve_Call(common_hal__eve_t *eve, uint32_t dest) { C4(eve, ((29 << 24) | ((dest & 65535)))); } + void common_hal__eve_Cell(common_hal__eve_t *eve, uint32_t cell) { C4(eve, ((6 << 24) | ((cell & 127)))); } + void common_hal__eve_ClearColorA(common_hal__eve_t *eve, uint32_t alpha) { C4(eve, ((15 << 24) | ((alpha & 255)))); } + void common_hal__eve_ClearColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue) { C4(eve, ((2 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | ((blue & 255)))); } + void common_hal__eve_Clear(common_hal__eve_t *eve, uint32_t c, uint32_t s, uint32_t t) { C4(eve, ((38 << 24) | ((c & 1) << 2) | ((s & 1) << 1) | ((t & 1)))); } + void common_hal__eve_ClearStencil(common_hal__eve_t *eve, uint32_t s) { C4(eve, ((17 << 24) | ((s & 255)))); } + void common_hal__eve_ClearTag(common_hal__eve_t *eve, uint32_t s) { C4(eve, ((18 << 24) | ((s & 255)))); } + void common_hal__eve_ColorA(common_hal__eve_t *eve, uint32_t alpha) { C4(eve, ((16 << 24) | ((alpha & 255)))); } + void common_hal__eve_ColorMask(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { C4(eve, ((32 << 24) | ((r & 1) << 3) | ((g & 1) << 2) | ((b & 1) << 1) | ((a & 1)))); } + void common_hal__eve_ColorRGB(common_hal__eve_t *eve, uint32_t red, uint32_t green, uint32_t blue) { C4(eve, ((4 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | ((blue & 255)))); } + void common_hal__eve_Display(common_hal__eve_t *eve) { C4(eve, ((0 << 24))); } + void common_hal__eve_End(common_hal__eve_t *eve) { C4(eve, ((33 << 24))); } + void common_hal__eve_Jump(common_hal__eve_t *eve, uint32_t dest) { C4(eve, ((30 << 24) | ((dest & 65535)))); } + void common_hal__eve_LineWidth(common_hal__eve_t *eve, uint32_t width) { C4(eve, ((14 << 24) | ((width & 4095)))); } + void common_hal__eve_Macro(common_hal__eve_t *eve, uint32_t m) { C4(eve, ((37 << 24) | ((m & 1)))); } + void common_hal__eve_Nop(common_hal__eve_t *eve) { C4(eve, ((45 << 24))); } + void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr) { C4(eve, ((42 << 24) | (((addr) & 4194303)))); } + void common_hal__eve_PointSize(common_hal__eve_t *eve, uint32_t size) { C4(eve, ((13 << 24) | ((size & 8191)))); } + void common_hal__eve_RestoreContext(common_hal__eve_t *eve) { C4(eve, ((35 << 24))); } + void common_hal__eve_Return(common_hal__eve_t *eve) { C4(eve, ((36 << 24))); } + void common_hal__eve_SaveContext(common_hal__eve_t *eve) { C4(eve, ((34 << 24))); } + void common_hal__eve_ScissorSize(common_hal__eve_t *eve, uint32_t width, uint32_t height) { C4(eve, ((28 << 24) | ((width & 4095) << 12) | ((height & 4095)))); } + void common_hal__eve_ScissorXY(common_hal__eve_t *eve, uint32_t x, uint32_t y) { C4(eve, ((27 << 24) | ((x & 2047) << 11) | ((y & 2047)))); } + void common_hal__eve_StencilFunc(common_hal__eve_t *eve, uint32_t func, uint32_t ref, uint32_t mask) { C4(eve, ((10 << 24) | ((func & 7) << 16) | ((ref & 255) << 8) | ((mask & 255)))); } + void common_hal__eve_StencilMask(common_hal__eve_t *eve, uint32_t mask) { C4(eve, ((19 << 24) | ((mask & 255)))); } + void common_hal__eve_StencilOp(common_hal__eve_t *eve, uint32_t sfail, uint32_t spass) { C4(eve, ((12 << 24) | ((sfail & 7) << 3) | ((spass & 7)))); } + void common_hal__eve_TagMask(common_hal__eve_t *eve, uint32_t mask) { C4(eve, ((20 << 24) | ((mask & 1)))); } + void common_hal__eve_Tag(common_hal__eve_t *eve, uint32_t s) { C4(eve, ((3 << 24) | ((s & 255)))); } + void common_hal__eve_VertexTranslateX(common_hal__eve_t *eve, uint32_t x) { C4(eve, ((43 << 24) | (((x) & 131071)))); } + void common_hal__eve_VertexTranslateY(common_hal__eve_t *eve, uint32_t y) { C4(eve, ((44 << 24) | (((y) & 131071)))); } + void common_hal__eve_Vertex2ii(common_hal__eve_t *eve, uint32_t x, uint32_t y, uint32_t handle, uint32_t cell) { C4(eve, ((2 << 30) | (((x) & 511) << 21) | (((y) & 511) << 12) | (((handle) & 31) << 7) | (((cell) & 127) << 0))); } -- cgit v1.2.3 From 07708f15185d96930621493c3e2886cc2e948622 Mon Sep 17 00:00:00 2001 From: Gadi Rotenberg Date: Sun, 9 Feb 2020 13:25:16 +0200 Subject: Added fix to allow remount when usb enabled but msc is ejected --- shared-module/storage/__init__.c | 4 +--- supervisor/shared/usb/usb_msc_flash.c | 10 +++++++++- supervisor/usb.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'shared-module') diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 215e1356a..c3d4b50c8 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -149,9 +149,7 @@ void common_hal_storage_remount(const char *mount_path, bool readonly, bool disa } #ifdef USB_AVAILABLE - // TODO(dhalbert): is this is a good enough check? It checks for - // CDC enabled. There is no "MSC enabled" check. - if (usb_enabled()) { + if (!usb_msc_ejected()) { mp_raise_RuntimeError(translate("Cannot remount '/' when USB is active.")); } #endif diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index 0376cfc1d..c0279f9e5 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -39,7 +39,7 @@ #define MSC_FLASH_BLOCK_SIZE 512 -static bool ejected[1]; +static bool ejected[1] = {true}; void usb_msc_mount(void) { // Reset the ejection tracking every time we're plugged into USB. This allows for us to battery @@ -53,6 +53,14 @@ void usb_msc_umount(void) { } +bool usb_msc_ejected(void) { + bool all_ejected = true; + for (uint8_t i = 0; i < sizeof(ejected); i++) { + all_ejected &= ejected[i]; + } + return all_ejected; +} + // The root FS is always at the end of the list. static fs_user_mount_t* get_vfs(int lun) { // TODO(tannewt): Return the mount which matches the lun where 0 is the end diff --git a/supervisor/usb.h b/supervisor/usb.h index 0cc361619..29280c725 100644 --- a/supervisor/usb.h +++ b/supervisor/usb.h @@ -44,5 +44,6 @@ void usb_init(void); // Propagate plug/unplug events to the MSC logic. void usb_msc_mount(void); void usb_msc_umount(void); +bool usb_msc_ejected(void); #endif // MICROPY_INCLUDED_SUPERVISOR_USB_H -- cgit v1.2.3 From 84ad3d8393db46eacfe3432d6476f1c5c48077e3 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sun, 16 Feb 2020 00:23:43 +0000 Subject: Addition of RTS/CTS/RS485 UART functionality --- ports/mimxrt10xx/common-hal/busio/UART.c | 62 ++++++++++++++--- .../peripherals/mimxrt10xx/MIMXRT1021/periph.c | 80 ++++++++++++++++------ .../peripherals/mimxrt10xx/MIMXRT1021/periph.h | 2 + shared-bindings/busio/UART.c | 13 +++- shared-bindings/busio/UART.h | 7 +- shared-module/board/__init__.c | 17 ++++- 6 files changed, 145 insertions(+), 36 deletions(-) (limited to 'shared-module') diff --git a/ports/mimxrt10xx/common-hal/busio/UART.c b/ports/mimxrt10xx/common-hal/busio/UART.c index a4819798b..2842b2cd9 100644 --- a/ports/mimxrt10xx/common-hal/busio/UART.c +++ b/ports/mimxrt10xx/common-hal/busio/UART.c @@ -53,8 +53,8 @@ static void config_periph_pin(const mcu_periph_obj_t *periph) { IOMUXC_SetPinConfig(0, 0, 0, 0, periph->pin->cfg_reg, IOMUXC_SW_PAD_CTL_PAD_HYS(0) - | IOMUXC_SW_PAD_CTL_PAD_PUS(0) - | IOMUXC_SW_PAD_CTL_PAD_PUE(0) + | IOMUXC_SW_PAD_CTL_PAD_PUS(1) + | IOMUXC_SW_PAD_CTL_PAD_PUE(1) | IOMUXC_SW_PAD_CTL_PAD_PKE(1) | IOMUXC_SW_PAD_CTL_PAD_ODE(0) | IOMUXC_SW_PAD_CTL_PAD_SPEED(1) @@ -72,9 +72,10 @@ void LPUART_UserCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t st } void common_hal_busio_uart_construct(busio_uart_obj_t *self, - const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, - uint8_t bits, uart_parity_t parity, uint8_t stop, mp_float_t timeout, - uint16_t receiver_buffer_size) { + const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, + const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, bool rs485_mode, + uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop, + mp_float_t timeout, uint16_t receiver_buffer_size) { // TODO: Allow none rx or tx @@ -111,12 +112,48 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if(self->rx_pin == NULL || self->tx_pin == NULL) { mp_raise_RuntimeError(translate("Invalid UART pin selection")); - } else { - self->uart = mcu_uart_banks[self->tx_pin->bank_idx - 1]; } + // Now check for RTS/CTS pin(s) + const uint32_t rts_count = sizeof(mcu_uart_rts_list) / sizeof(mcu_periph_obj_t); + const uint32_t cts_count = sizeof(mcu_uart_cts_list) / sizeof(mcu_periph_obj_t); + + if (rts != mp_const_none) { + for (uint32_t i=0; i < rts_count; ++i) + { + if (mcu_uart_rts_list[i].bank_idx == self->rx_pin->bank_idx) { + if (mcu_uart_rts_list[i].pin == rts) { + self->rts_pin = &mcu_uart_rts_list[i]; + break; + } + } + } + if (self->rts_pin == NULL) + mp_raise_ValueError(translate("Selected RTS pin not valid")); + } + + if (cts != mp_const_none) { + for (uint32_t i=0; i < cts_count; ++i) + { + if (mcu_uart_cts_list[i].bank_idx == self->rx_pin->bank_idx) { + if (mcu_uart_cts_list[i].pin == cts) { + self->cts_pin = &mcu_uart_cts_list[i]; + break; + } + } + } + if (self->cts_pin == NULL) + mp_raise_ValueError(translate("Selected CTS pin not valid")); + } + + self->uart = mcu_uart_banks[self->tx_pin->bank_idx - 1]; + config_periph_pin(self->rx_pin); config_periph_pin(self->tx_pin); + if (self->rts_pin) + config_periph_pin(self->rts_pin); + if (self->cts_pin) + config_periph_pin(self->cts_pin); lpuart_config_t config = { 0 }; LPUART_GetDefaultConfig(&config); @@ -125,10 +162,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, config.baudRate_Bps = self->baudrate; config.enableTx = self->tx_pin != NULL; config.enableRx = self->rx_pin != NULL; - + config.enableRxRTS = self->rts_pin != NULL; + config.enableTxCTS = self->cts_pin != NULL; + LPUART_Init(self->uart, &config, UART_CLOCK_FREQ); - claim_pin(self->tx_pin->pin); + if (self->tx_pin != NULL) + claim_pin(self->tx_pin->pin); if (self->rx_pin != NULL) { ringbuf_alloc(&self->rbuf, receiver_buffer_size, true); @@ -203,7 +243,9 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t LPUART_TransferAbortReceive(self->uart, &self->handle); } - return len - self->handle.rxDataSize; + // The only place we can reliably tell how many bytes have been received is from the current + // wp in the handle (because the abort nukes rxDataSize, and reading it before abort is a race.) + return self->handle.rxData-data; } // Write characters. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.c b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.c index 39e4f0131..0417f29cc 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.c +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.c @@ -109,53 +109,93 @@ LPUART_Type *mcu_uart_banks[] = { LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, L const mcu_periph_obj_t mcu_uart_rx_list[16] = { PERIPH_PIN(1, 2, 0, 0, &pin_GPIO_AD_B0_07), - PERIPH_PIN(2, 2, kIOMUXC_LPUART2_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_23), - PERIPH_PIN(2, 2, kIOMUXC_LPUART2_RX_SELECT_INPUT, 1, &pin_GPIO_AD_B1_09), + PERIPH_PIN(2, 2, kIOMUXC_LPUART2_RX_SELECT_INPUT, 0, &pin_GPIO_AD_B1_09), + PERIPH_PIN(2, 2, kIOMUXC_LPUART2_RX_SELECT_INPUT, 1, &pin_GPIO_EMC_23), PERIPH_PIN(3, 2, kIOMUXC_LPUART3_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_07), PERIPH_PIN(3, 2, kIOMUXC_LPUART3_RX_SELECT_INPUT, 1, &pin_GPIO_AD_B0_15), PERIPH_PIN(4, 2, kIOMUXC_LPUART4_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_03), - PERIPH_PIN(4, 2, kIOMUXC_LPUART4_RX_SELECT_INPUT, 1, &pin_GPIO_EMC_33), - PERIPH_PIN(4, 2, kIOMUXC_LPUART4_RX_SELECT_INPUT, 2, &pin_GPIO_AD_B1_11), + PERIPH_PIN(4, 2, kIOMUXC_LPUART4_RX_SELECT_INPUT, 1, &pin_GPIO_AD_B1_11), + PERIPH_PIN(4, 2, kIOMUXC_LPUART4_RX_SELECT_INPUT, 2, &pin_GPIO_EMC_33), - PERIPH_PIN(5, 2, kIOMUXC_LPUART5_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_39), - PERIPH_PIN(5, 2, kIOMUXC_LPUART5_RX_SELECT_INPUT, 1, &pin_GPIO_AD_B0_11), + PERIPH_PIN(5, 2, kIOMUXC_LPUART5_RX_SELECT_INPUT, 0, &pin_GPIO_AD_B0_11), + PERIPH_PIN(5, 2, kIOMUXC_LPUART5_RX_SELECT_INPUT, 1, &pin_GPIO_EMC_39), PERIPH_PIN(6, 2, kIOMUXC_LPUART6_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_13), PERIPH_PIN(6, 2, kIOMUXC_LPUART6_RX_SELECT_INPUT, 1, &pin_GPIO_SD_B1_01), - PERIPH_PIN(7, 2, kIOMUXC_LPUART7_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_35), - PERIPH_PIN(7, 2, kIOMUXC_LPUART7_RX_SELECT_INPUT, 1, &pin_GPIO_SD_B0_05), + PERIPH_PIN(7, 2, kIOMUXC_LPUART7_RX_SELECT_INPUT, 0, &pin_GPIO_SD_B0_05), + PERIPH_PIN(7, 2, kIOMUXC_LPUART7_RX_SELECT_INPUT, 1, &pin_GPIO_EMC_35), - PERIPH_PIN(8, 2, kIOMUXC_LPUART8_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_27), - PERIPH_PIN(8, 2, kIOMUXC_LPUART8_RX_SELECT_INPUT, 1, &pin_GPIO_SD_B1_03), + PERIPH_PIN(8, 2, kIOMUXC_LPUART8_RX_SELECT_INPUT, 0, &pin_GPIO_SD_B1_03), + PERIPH_PIN(8, 2, kIOMUXC_LPUART8_RX_SELECT_INPUT, 1, &pin_GPIO_EMC_27), }; const mcu_periph_obj_t mcu_uart_tx_list[16] = { PERIPH_PIN(1, 2, 0, 0, &pin_GPIO_AD_B0_06), - PERIPH_PIN(2, 2, kIOMUXC_LPUART2_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_22), - PERIPH_PIN(2, 2, kIOMUXC_LPUART2_TX_SELECT_INPUT, 1, &pin_GPIO_AD_B1_08), + PERIPH_PIN(2, 2, kIOMUXC_LPUART2_TX_SELECT_INPUT, 0, &pin_GPIO_AD_B1_08), + PERIPH_PIN(2, 2, kIOMUXC_LPUART2_TX_SELECT_INPUT, 1, &pin_GPIO_EMC_22), PERIPH_PIN(3, 2, kIOMUXC_LPUART3_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_06), PERIPH_PIN(3, 2, kIOMUXC_LPUART3_TX_SELECT_INPUT, 1, &pin_GPIO_AD_B0_14), PERIPH_PIN(4, 2, kIOMUXC_LPUART4_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_02), - PERIPH_PIN(4, 2, kIOMUXC_LPUART4_TX_SELECT_INPUT, 1, &pin_GPIO_EMC_32), - PERIPH_PIN(4, 2, kIOMUXC_LPUART4_TX_SELECT_INPUT, 2, &pin_GPIO_AD_B1_10), + PERIPH_PIN(4, 2, kIOMUXC_LPUART4_TX_SELECT_INPUT, 1, &pin_GPIO_AD_B1_10), + PERIPH_PIN(4, 2, kIOMUXC_LPUART4_TX_SELECT_INPUT, 2, &pin_GPIO_EMC_32), - PERIPH_PIN(5, 2, kIOMUXC_LPUART5_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_38), - PERIPH_PIN(5, 2, kIOMUXC_LPUART5_TX_SELECT_INPUT, 1, &pin_GPIO_AD_B0_10), + PERIPH_PIN(5, 2, kIOMUXC_LPUART5_TX_SELECT_INPUT, 0, &pin_GPIO_AD_B0_10), + PERIPH_PIN(5, 2, kIOMUXC_LPUART5_TX_SELECT_INPUT, 1, &pin_GPIO_EMC_38), PERIPH_PIN(6, 2, kIOMUXC_LPUART6_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_12), PERIPH_PIN(6, 2, kIOMUXC_LPUART6_TX_SELECT_INPUT, 1, &pin_GPIO_SD_B1_00), - PERIPH_PIN(7, 2, kIOMUXC_LPUART7_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_34), - PERIPH_PIN(7, 2, kIOMUXC_LPUART7_TX_SELECT_INPUT, 1, &pin_GPIO_SD_B0_04), + PERIPH_PIN(7, 2, kIOMUXC_LPUART7_TX_SELECT_INPUT, 0, &pin_GPIO_SD_B0_04), + PERIPH_PIN(7, 2, kIOMUXC_LPUART7_TX_SELECT_INPUT, 1, &pin_GPIO_EMC_34), - PERIPH_PIN(8, 2, kIOMUXC_LPUART8_TX_SELECT_INPUT, 0, &pin_GPIO_EMC_26), - PERIPH_PIN(8, 2, kIOMUXC_LPUART8_TX_SELECT_INPUT, 1, &pin_GPIO_SD_B1_02), + PERIPH_PIN(8, 2, kIOMUXC_LPUART8_TX_SELECT_INPUT, 0, &pin_GPIO_SD_B1_02), + PERIPH_PIN(8, 2, kIOMUXC_LPUART8_TX_SELECT_INPUT, 1, &pin_GPIO_EMC_26), +}; + +const mcu_periph_obj_t mcu_uart_rts_list[10] = { + PERIPH_PIN(1, 2, 0, 0, &pin_GPIO_AD_B0_09), + + PERIPH_PIN(2, 2, 0, 0, &pin_GPIO_EMC_21), + PERIPH_PIN(2, 2, 0, 1, &pin_GPIO_AD_B1_07), + + PERIPH_PIN(3, 2, 0, 1, &pin_GPIO_AD_B0_13), + + PERIPH_PIN(4, 2, 0, 0, &pin_GPIO_EMC_01), + PERIPH_PIN(4, 2, 0, 1, &pin_GPIO_EMC_31), + + PERIPH_PIN(5, 2, 0, 0, &pin_GPIO_EMC_37), + + PERIPH_PIN(6, 2, 0, 0, &pin_GPIO_EMC_15), + + PERIPH_PIN(7, 2, 0, 1, &pin_GPIO_SD_B0_03), + + PERIPH_PIN(8, 2, 0, 0, &pin_GPIO_EMC_25), +}; + +const mcu_periph_obj_t mcu_uart_cts_list[10] = { + PERIPH_PIN(1, 2, 0, 0, &pin_GPIO_AD_B0_08), + + PERIPH_PIN(2, 2, kIOMUXC_LPUART2_CTS_B_SELECT_INPUT, 0, &pin_GPIO_AD_B1_06), + PERIPH_PIN(2, 2, kIOMUXC_LPUART2_CTS_B_SELECT_INPUT, 1, &pin_GPIO_EMC_20), + + PERIPH_PIN(3, 2, 0, 1, &pin_GPIO_AD_B0_12), + + PERIPH_PIN(4, 2, kIOMUXC_LPUART4_CTS_B_SELECT_INPUT, 0, &pin_GPIO_EMC_00), + PERIPH_PIN(4, 2, kIOMUXC_LPUART4_CTS_B_SELECT_INPUT, 0, &pin_GPIO_EMC_30), + + PERIPH_PIN(5, 2, 0, 0, &pin_GPIO_EMC_36), + + PERIPH_PIN(6, 2, 0, 0, &pin_GPIO_EMC_14), + + PERIPH_PIN(7, 2, 0, 0, &pin_GPIO_SD_B0_02), + + PERIPH_PIN(8, 2, 0, 0, &pin_GPIO_EMC_24), }; const mcu_pwm_obj_t mcu_pwm_list[39] = { diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.h index 1d720f633..ba88ef4c6 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/periph.h @@ -37,6 +37,8 @@ extern const mcu_periph_obj_t mcu_spi_miso_list[8]; extern const mcu_periph_obj_t mcu_uart_rx_list[16]; extern const mcu_periph_obj_t mcu_uart_tx_list[16]; +extern const mcu_periph_obj_t mcu_uart_rts_list[10]; +extern const mcu_periph_obj_t mcu_uart_cts_list[10]; extern const mcu_pwm_obj_t mcu_pwm_list[39]; diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 1fc81e78e..529d2d3ce 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -82,7 +82,7 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co // https://github.com/adafruit/circuitpython/issues/1056) busio_uart_obj_t *self = m_new_ll_obj(busio_uart_obj_t); self->base.type = &busio_uart_type; - enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size}; + enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size, ARG_rts, ARG_cts, ARG_rs485}; static const mp_arg_t allowed_args[] = { { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -92,6 +92,9 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(1)} }, { MP_QSTR_receiver_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, + { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_rs485, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -124,7 +127,13 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); validate_timeout(timeout); - common_hal_busio_uart_construct(self, tx, rx, + const mcu_pin_obj_t* rts = MP_OBJ_TO_PTR(args[ARG_rts].u_obj); + + const mcu_pin_obj_t* cts = MP_OBJ_TO_PTR(args[ARG_cts].u_obj); + + bool rs485 = args[ARG_rs485].u_bool; + + common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485, args[ARG_baudrate].u_int, bits, parity, stop, timeout, args[ARG_receiver_buffer_size].u_int); return (mp_obj_t)self; diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h index cfd2c800c..1d748ecc7 100644 --- a/shared-bindings/busio/UART.h +++ b/shared-bindings/busio/UART.h @@ -40,9 +40,10 @@ typedef enum { // Construct an underlying UART object. extern void common_hal_busio_uart_construct(busio_uart_obj_t *self, - const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, - uint8_t bits, uart_parity_t parity, uint8_t stop, mp_float_t timeout, - uint16_t receiver_buffer_size); + const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, + const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, bool rs485_mode, + uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop, + mp_float_t timeout, uint16_t receiver_buffer_size); extern void common_hal_busio_uart_deinit(busio_uart_obj_t *self); extern bool common_hal_busio_uart_deinited(busio_uart_obj_t *self); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 914bc4313..05567d7ab 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -100,8 +100,23 @@ mp_obj_t common_hal_board_create_uart(void) { const mcu_pin_obj_t* rx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RX); const mcu_pin_obj_t* tx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_TX); +#ifdef DEFAULT_UART_BUS_RTS + const mcu_pin_obj_t* rts = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RTS); +#else + const mcu_pin_obj_t* rts = mp_const_none; +#endif +#ifdef DEFAULT_UART_BUS_CTS + const mcu_pin_obj_t* cts = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_CTS); +#else + const mcu_pin_obj_t* cts = mp_const_none; +#endif +#ifdef DEFAULT_UART_IS_RS485 + const bool rs485 = true; +#else + const bool rs485 = false; +#endif - common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1.0f, 64); + common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485, 9600, 8, PARITY_NONE, 1, 1.0f, 64); MP_STATE_VM(shared_uart_bus) = MP_OBJ_FROM_PTR(self); return MP_STATE_VM(shared_uart_bus); } -- cgit v1.2.3 From d388899985b24530cc08cdf10ed15e3c7ba41349 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Tue, 18 Feb 2020 00:09:35 +0000 Subject: Addition of RS485 support --- ports/mimxrt10xx/common-hal/busio/UART.c | 38 +++++++++++++++++++--- .../mimxrt10xx/supervisor/flexspi_nor_flash_ops.c | 2 +- shared-bindings/busio/UART.c | 15 ++++++--- shared-bindings/busio/UART.h | 3 +- shared-module/board/__init__.c | 11 +++++-- 5 files changed, 56 insertions(+), 13 deletions(-) (limited to 'shared-module') diff --git a/ports/mimxrt10xx/common-hal/busio/UART.c b/ports/mimxrt10xx/common-hal/busio/UART.c index 2842b2cd9..3609a9998 100644 --- a/ports/mimxrt10xx/common-hal/busio/UART.c +++ b/ports/mimxrt10xx/common-hal/busio/UART.c @@ -73,7 +73,8 @@ void LPUART_UserCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t st void common_hal_busio_uart_construct(busio_uart_obj_t *self, const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, - const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, bool rs485_mode, + const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, + const mcu_pin_obj_t * rs485_dir, bool rs485_invert, uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop, mp_float_t timeout, uint16_t receiver_buffer_size) { @@ -114,7 +115,22 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, mp_raise_RuntimeError(translate("Invalid UART pin selection")); } - // Now check for RTS/CTS pin(s) + // Filter for sane settings for RS485 + if (rs485_dir != mp_const_none) { + if ((rts != mp_const_none) || (cts != mp_const_none)) { + mp_raise_ValueError(translate("Cannot specify RTS or CTS in RS485 mode")); + } + // For IMXRT the RTS pin is used for RS485 direction + rts = rs485_dir; + } + else + { + if (rs485_invert == true) { + mp_raise_ValueError(translate("RS485 inversion specified when not in RS485 mode")); + } + } + + // Now check for RTS/CTS (or overloaded RS485 direction) pin(s) const uint32_t rts_count = sizeof(mcu_uart_rts_list) / sizeof(mcu_periph_obj_t); const uint32_t cts_count = sizeof(mcu_uart_cts_list) / sizeof(mcu_periph_obj_t); @@ -163,10 +179,24 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, config.enableTx = self->tx_pin != NULL; config.enableRx = self->rx_pin != NULL; config.enableRxRTS = self->rts_pin != NULL; - config.enableTxCTS = self->cts_pin != NULL; - + config.enableTxCTS = self->cts_pin != NULL; + if (self->rts_pin != NULL) + claim_pin(self->rts_pin->pin); + if (self->cts_pin != NULL) + claim_pin(self->cts_pin->pin); + LPUART_Init(self->uart, &config, UART_CLOCK_FREQ); + // Before we init, setup RS485 direction pin + // ..unfortunately this isn't done by the driver library + uint32_t modir = (self->uart->MODIR) & ~(LPUART_MODIR_TXRTSPOL_MASK | LPUART_MODIR_TXRTSE_MASK); + if (rs485_dir != mp_const_none) { + modir |= LPUART_MODIR_TXRTSE_MASK; + if ( rs485_invert == true ) + modir |= LPUART_MODIR_TXRTSPOL_MASK; + } + self->uart->MODIR = modir; + if (self->tx_pin != NULL) claim_pin(self->tx_pin->pin); diff --git a/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c b/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c index 71252d677..f97a54a89 100644 --- a/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c +++ b/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c @@ -324,7 +324,7 @@ void flexspi_nor_flash_init(FLEXSPI_Type *base) config.ahbConfig.enableAHBBufferable = true; config.ahbConfig.enableReadAddressOpt = true; config.ahbConfig.enableAHBCachable = true; - config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad; + config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally; //kFLEXSPI_ReadSampleClkLoopbackFromDqsPad; FLEXSPI_Init(base, &config); /* Configure flash settings according to serial flash feature. */ diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 529d2d3ce..02c5afb16 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -53,6 +53,10 @@ //| //| :param ~microcontroller.Pin tx: the pin to transmit with, or ``None`` if this ``UART`` is receive-only. //| :param ~microcontroller.Pin rx: the pin to receive on, or ``None`` if this ``UART`` is transmit-only. +//| :param ~microcontroller.Pin rts: the pin for rts, or ``None`` if rts not in use. +//| :param ~microcontroller.Pin cts: the pin for cts, or ``None`` if cts not in use. +//| :param ~microcontroller.Pin rs485_dir: the pin for rs485 direction setting, or ``None`` if rs485 not in use. +//| :param bool rs485_invert: set to invert the sense of the rs485_dir pin. //| :param int baudrate: the transmit and receive speed. //| :param int bits: the number of bits per byte, 7, 8 or 9. //| :param Parity parity: the parity used for error checking. @@ -82,7 +86,8 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co // https://github.com/adafruit/circuitpython/issues/1056) busio_uart_obj_t *self = m_new_ll_obj(busio_uart_obj_t); self->base.type = &busio_uart_type; - enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size, ARG_rts, ARG_cts, ARG_rs485}; + enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_receiver_buffer_size, + ARG_rts, ARG_cts, ARG_rs485_dir,ARG_rs485_invert}; static const mp_arg_t allowed_args[] = { { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -94,7 +99,8 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co { MP_QSTR_receiver_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_rs485, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false } }, + { MP_QSTR_rs485_dir, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none } }, + { MP_QSTR_rs485_invert, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -131,9 +137,10 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co const mcu_pin_obj_t* cts = MP_OBJ_TO_PTR(args[ARG_cts].u_obj); - bool rs485 = args[ARG_rs485].u_bool; + const mcu_pin_obj_t* rs485_dir = args[ARG_rs485_dir].u_obj; + bool rs485_invert = args[ARG_rs485_invert].u_bool; - common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485, + common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert, args[ARG_baudrate].u_int, bits, parity, stop, timeout, args[ARG_receiver_buffer_size].u_int); return (mp_obj_t)self; diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h index 1d748ecc7..fe71e8668 100644 --- a/shared-bindings/busio/UART.h +++ b/shared-bindings/busio/UART.h @@ -41,7 +41,8 @@ typedef enum { // Construct an underlying UART object. extern void common_hal_busio_uart_construct(busio_uart_obj_t *self, const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, - const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, bool rs485_mode, + const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts, + const mcu_pin_obj_t * rs485_dir, bool rs485_invert, uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop, mp_float_t timeout, uint16_t receiver_buffer_size); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 05567d7ab..952e1fc10 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -111,12 +111,17 @@ mp_obj_t common_hal_board_create_uart(void) { const mcu_pin_obj_t* cts = mp_const_none; #endif #ifdef DEFAULT_UART_IS_RS485 - const bool rs485 = true; + const mcu_pin_obj_t* rs485_dir = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RS485DIR); +#ifdef DEFAULT_UART_RS485_INVERT + const bool rs485_invert = true; +#endif #else - const bool rs485 = false; + const mcu_pin_obj_t* rs485_dir = mp_const_none; + const bool rs485_invert = true; #endif - common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485, 9600, 8, PARITY_NONE, 1, 1.0f, 64); + common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert, + 9600, 8, PARITY_NONE, 1, 1.0f, 64); MP_STATE_VM(shared_uart_bus) = MP_OBJ_FROM_PTR(self); return MP_STATE_VM(shared_uart_bus); } -- cgit v1.2.3 From d41cf2e9265e3250d8e98c06ce0ea8dfc523edb1 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sun, 23 Feb 2020 11:16:24 +0000 Subject: Fix incorrect initialisation of default UART --- shared-module/board/__init__.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 952e1fc10..bbf177384 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -114,10 +114,12 @@ mp_obj_t common_hal_board_create_uart(void) { const mcu_pin_obj_t* rs485_dir = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RS485DIR); #ifdef DEFAULT_UART_RS485_INVERT const bool rs485_invert = true; +#else + const bool rs485_invert = false; #endif #else const mcu_pin_obj_t* rs485_dir = mp_const_none; - const bool rs485_invert = true; + const bool rs485_invert = false; #endif common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert, -- cgit v1.2.3