From 1117edae63df7b66f1575980bf54d6836f9a8aa8 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 24 Oct 2020 17:13:10 +0200 Subject: Fix erroneous claim of board.I2C() by deinited display. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the end of a session that called displayio.release_displays() (and did not initialize a new display), a board.I2C() bus that was previously used by a display would wrongly be considered still in use. While I can’t think of any unrecoverable problem this would cause in the next session, it violates the assumption that a soft reboot resets everything not needed by displays, potentially leading to confusion. By itself, this change does not fix the problem yet - rather, it introduces the same issue as in #3581 for SPI. This needs to be solved in the same way for I2C and SPI. --- shared-module/board/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 39b68a0f1..856103b7b 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -139,7 +139,7 @@ void reset_board_busses(void) { bool display_using_i2c = false; #if CIRCUITPY_DISPLAYIO for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - if (displays[i].i2cdisplay_bus.bus == i2c_singleton) { + if (displays[i].bus_base.type == &displayio_i2cdisplay_type && displays[i].i2cdisplay_bus.bus == i2c_singleton) { display_using_i2c = true; break; } -- cgit v1.2.3 From f4f80e07ca3dc2f5a93484e5342540837a94a505 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 24 Oct 2020 17:23:17 +0200 Subject: Fix lost board.SPI and board.I2C after being used by display. Fixes #3581. Pins were marked as never_reset by common_hal_displayio_fourwire_construct() and common_hal_sharpdisplay_framebuffer_construct(), but these marks were never removed, so at the end of a session after displayio.release_displays(), {spi|i2c}_singleton would be set to NULL but the pins would not be reset. In the next session, board.SPI() and board.I2C() were unable to reconstruct the object because the pins were still in use. For symmetry with creation of the singleton, add deinitialization before setting it to NULL in reset_board_busses(). This makes the pins resettable, so that reset_port(), moved behind it, then resets them. --- main.c | 4 +++- shared-module/board/__init__.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'shared-module') diff --git a/main.c b/main.c index b43b3b8c8..80b163f60 100755 --- a/main.c +++ b/main.c @@ -234,10 +234,12 @@ void cleanup_after_vm(supervisor_allocation* heap) { common_hal_canio_reset(); #endif - reset_port(); + // reset_board_busses() first because it may release pins from the never_reset state, so that + // reset_port() can reset them. #if CIRCUITPY_BOARD reset_board_busses(); #endif + reset_port(); reset_board(); reset_status_led(); } diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 856103b7b..967b430d2 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -145,8 +145,11 @@ void reset_board_busses(void) { } } #endif - if (!display_using_i2c) { - i2c_singleton = NULL; + if (i2c_singleton != NULL) { + if (!display_using_i2c) { + common_hal_busio_i2c_deinit(i2c_singleton); + i2c_singleton = NULL; + } } #endif #if BOARD_SPI @@ -169,9 +172,10 @@ void reset_board_busses(void) { // make sure SPI lock is not held over a soft reset if (spi_singleton != NULL) { common_hal_busio_spi_unlock(spi_singleton); - } - if (!display_using_spi) { - spi_singleton = NULL; + if (!display_using_spi) { + common_hal_busio_spi_deinit(spi_singleton); + spi_singleton = NULL; + } } #endif #if BOARD_UART -- cgit v1.2.3 From 99a3750a2cfd1da8cdd266ca9a0367f0c3a54092 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 24 Oct 2020 17:50:11 +0200 Subject: Fix lost board.SPI and board.I2C after explicitly deiniting them. After calling board.SPI().deinit(), calling board.SPI() again would return the unusable deinited object and there was no way of getting it back into an initialized state until the end of the session. --- shared-bindings/board/__init__.c | 10 ++++++++-- shared-module/board/__init__.c | 10 ++++------ 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c index 6837fc41c..717698408 100644 --- a/shared-bindings/board/__init__.c +++ b/shared-bindings/board/__init__.c @@ -28,6 +28,12 @@ #include "py/runtime.h" #include "shared-bindings/board/__init__.h" +#if BOARD_I2C +#include "shared-bindings/busio/I2C.h" +#endif +#if BOARD_SPI +#include "shared-bindings/busio/SPI.h" +#endif //| """Board specific pin names //| @@ -45,7 +51,7 @@ #if BOARD_I2C mp_obj_t board_i2c(void) { mp_obj_t singleton = common_hal_board_get_i2c(); - if (singleton != NULL) { + if (singleton != NULL && !common_hal_busio_i2c_deinited(singleton)) { return singleton; } assert_pin_free(DEFAULT_I2C_BUS_SDA); @@ -69,7 +75,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c); #if BOARD_SPI mp_obj_t board_spi(void) { mp_obj_t singleton = common_hal_board_get_spi(); - if (singleton != NULL) { + if (singleton != NULL && !common_hal_busio_spi_deinited(singleton)) { return singleton; } assert_pin_free(DEFAULT_SPI_BUS_SCK); diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 967b430d2..2f1c34e56 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -55,9 +55,8 @@ mp_obj_t common_hal_board_get_i2c(void) { } mp_obj_t common_hal_board_create_i2c(void) { - if (i2c_singleton != NULL) { - return i2c_singleton; - } + // All callers have either already verified this or come so early that it can't be otherwise. + assert(i2c_singleton == NULL || common_hal_busio_i2c_deinited(i2c_singleton)); busio_i2c_obj_t *self = &i2c_obj; self->base.type = &busio_i2c_type; @@ -79,9 +78,8 @@ mp_obj_t common_hal_board_get_spi(void) { } mp_obj_t common_hal_board_create_spi(void) { - if (spi_singleton != NULL) { - return spi_singleton; - } + // All callers have either already verified this or come so early that it can't be otherwise. + assert(spi_singleton == NULL || common_hal_busio_spi_deinited(spi_singleton)); busio_spi_obj_t *self = &spi_obj; self->base.type = &busio_spi_type; -- cgit v1.2.3 From 0d1649880f1c23ec6c9c0a4834f3712a8495f9d8 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 26 Oct 2020 16:58:00 -0700 Subject: Add grayscale EInk support --- shared-bindings/displayio/EPaperDisplay.c | 35 +++++++++++++++++++++++++------ shared-bindings/displayio/EPaperDisplay.h | 2 +- shared-module/displayio/ColorConverter.c | 9 ++++---- shared-module/displayio/EPaperDisplay.c | 15 ++++++++----- shared-module/displayio/EPaperDisplay.h | 1 + shared-module/displayio/Palette.h | 1 + shared-module/displayio/display_core.c | 1 + 7 files changed, 48 insertions(+), 16 deletions(-) (limited to 'shared-module') diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c index 8be4ee4c4..e0326d9c8 100644 --- a/shared-bindings/displayio/EPaperDisplay.c +++ b/shared-bindings/displayio/EPaperDisplay.c @@ -49,7 +49,19 @@ //| Most people should not use this class directly. Use a specific display driver instead that will //| contain the startup and shutdown sequences at minimum.""" //| -//| def __init__(self, display_bus: _DisplayBus, start_sequence: ReadableBuffer, stop_sequence: ReadableBuffer, *, width: int, height: int, ram_width: int, ram_height: int, colstart: int = 0, rowstart: int = 0, rotation: int = 0, set_column_window_command: Optional[int] = None, set_row_window_command: Optional[int] = None, single_byte_bounds: bool = False, write_black_ram_command: int, black_bits_inverted: bool = False, write_color_ram_command: Optional[int] = None, color_bits_inverted: bool = False, highlight_color: int = 0x000000, refresh_display_command: int, refresh_time: float = 40, busy_pin: Optional[microcontroller.Pin] = None, busy_state: bool = True, seconds_per_frame: float = 180, always_toggle_chip_select: bool = False) -> None: +//| def __init__(self, display_bus: _DisplayBus, +//| start_sequence: ReadableBuffer, stop_sequence: ReadableBuffer, *, +//| width: int, height: int, ram_width: int, ram_height: int, +//| colstart: int = 0, rowstart: int = 0, rotation: int = 0, +//| set_column_window_command: Optional[int] = None, +//| set_row_window_command: Optional[int] = None, single_byte_bounds: bool = False, +//| write_black_ram_command: int, black_bits_inverted: bool = False, +//| write_color_ram_command: Optional[int] = None, +//| color_bits_inverted: bool = False, highlight_color: int = 0x000000, +//| refresh_display_command: int, refresh_time: float = 40, +//| busy_pin: Optional[microcontroller.Pin] = None, busy_state: bool = True, +//| seconds_per_frame: float = 180, always_toggle_chip_select: bool = False, +//| grayscale: bool = False) -> None: //| """Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`). //| //| The ``start_sequence`` and ``stop_sequence`` are bitpacked to minimize the ram impact. Every @@ -84,11 +96,18 @@ //| :param microcontroller.Pin busy_pin: Pin used to signify the display is busy //| :param bool busy_state: State of the busy pin when the display is busy //| :param float seconds_per_frame: Minimum number of seconds between screen refreshes -//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte""" +//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte +//| :param bool grayscale: When true, the color ram is the low bit of 2-bit grayscale""" //| ... //| STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_display_bus, ARG_start_sequence, ARG_stop_sequence, ARG_width, ARG_height, ARG_ram_width, ARG_ram_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_set_column_window_command, ARG_set_row_window_command, ARG_set_current_column_command, ARG_set_current_row_command, ARG_write_black_ram_command, ARG_black_bits_inverted, ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color, ARG_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state, ARG_seconds_per_frame, ARG_always_toggle_chip_select }; + enum { ARG_display_bus, ARG_start_sequence, ARG_stop_sequence, ARG_width, ARG_height, + ARG_ram_width, ARG_ram_height, ARG_colstart, ARG_rowstart, ARG_rotation, + ARG_set_column_window_command, ARG_set_row_window_command, ARG_set_current_column_command, + ARG_set_current_row_command, ARG_write_black_ram_command, ARG_black_bits_inverted, + ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color, + ARG_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state, + ARG_seconds_per_frame, ARG_always_toggle_chip_select, ARG_grayscale }; static const mp_arg_t allowed_args[] = { { MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_start_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -115,6 +134,7 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size { MP_QSTR_busy_state, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, { MP_QSTR_seconds_per_frame, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(180)} }, { MP_QSTR_always_toggle_chip_select, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + { MP_QSTR_grayscale, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -151,11 +171,14 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size self, display_bus, start_bufinfo.buf, start_bufinfo.len, stop_bufinfo.buf, stop_bufinfo.len, - args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_ram_width].u_int, args[ARG_ram_height].u_int, args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation, + args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_ram_width].u_int, args[ARG_ram_height].u_int, + args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation, args[ARG_set_column_window_command].u_int, args[ARG_set_row_window_command].u_int, args[ARG_set_current_column_command].u_int, args[ARG_set_current_row_command].u_int, - args[ARG_write_black_ram_command].u_int, args[ARG_black_bits_inverted].u_bool, write_color_ram_command, args[ARG_color_bits_inverted].u_bool, highlight_color, args[ARG_refresh_display_command].u_int, refresh_time, - busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame, args[ARG_always_toggle_chip_select].u_bool + args[ARG_write_black_ram_command].u_int, args[ARG_black_bits_inverted].u_bool, write_color_ram_command, + args[ARG_color_bits_inverted].u_bool, highlight_color, args[ARG_refresh_display_command].u_int, refresh_time, + busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame, + args[ARG_always_toggle_chip_select].u_bool, args[ARG_grayscale].u_bool ); return self; diff --git a/shared-bindings/displayio/EPaperDisplay.h b/shared-bindings/displayio/EPaperDisplay.h index e4b81c883..352de899a 100644 --- a/shared-bindings/displayio/EPaperDisplay.h +++ b/shared-bindings/displayio/EPaperDisplay.h @@ -44,7 +44,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* uint16_t set_column_window_command, uint16_t set_row_window_command, uint16_t set_current_column_command, uint16_t set_current_row_command, uint16_t write_black_ram_command, bool black_bits_inverted, uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint16_t refresh_display_command, mp_float_t refresh_time, - const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool always_toggle_chip_select); + const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool always_toggle_chip_select, bool grayscale); bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* self); diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index dc64da03d..03ec99ceb 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -165,9 +165,9 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d g8 = MIN(255,g8 + (randg&0x03)); } else { int bitmask = 0xFF >> colorspace->depth; - b8 = MIN(255,b8 + (randb&bitmask)); - r8 = MIN(255,r8 + (randr&bitmask)); - g8 = MIN(255,g8 + (randg&bitmask)); + b8 = MIN(255,b8 + (randb & bitmask)); + r8 = MIN(255,r8 + (randr & bitmask)); + g8 = MIN(255,g8 + (randg & bitmask)); } pixel = r8 << 16 | g8 << 8 | b8; } @@ -196,7 +196,8 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d return; } else if (colorspace->grayscale && colorspace->depth <= 8) { uint8_t luma = displayio_colorconverter_compute_luma(pixel); - output_color->pixel = luma >> (8 - colorspace->depth); + size_t bitmask = (1 << colorspace->depth) - 1; + output_color->pixel = (luma >> colorspace->grayscale_bit) & bitmask; output_color->opaque = true; return; } diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index 46c7ea82e..514b99a13 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -49,7 +49,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* uint16_t set_column_window_command, uint16_t set_row_window_command, uint16_t set_current_column_command, uint16_t set_current_row_command, uint16_t write_black_ram_command, bool black_bits_inverted, uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, uint16_t refresh_display_command, mp_float_t refresh_time, - const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select) { + const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select, bool grayscale) { if (highlight_color != 0x000000) { self->core.colorspace.tricolor = true; self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(highlight_color); @@ -72,6 +72,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self->refreshing = false; self->milliseconds_per_frame = seconds_per_frame * 1000; self->chip_select = chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED; + self->grayscale = grayscale; self->start_sequence = start_sequence; self->start_sequence_len = start_sequence_len; @@ -230,17 +231,16 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c uint32_t mask[mask_length]; uint8_t passes = 1; - if (self->core.colorspace.tricolor) { + if (self->core.colorspace.tricolor || self->grayscale) { passes = 2; } for (uint8_t pass = 0; pass < passes; pass++) { uint16_t remaining_rows = displayio_area_height(&clipped); - // added false parameter at end for SH1107_addressing quirk if (self->set_row_window_command != NO_COMMAND) { displayio_display_core_set_region_to_update(&self->core, self->set_column_window_command, self->set_row_window_command, self->set_current_column_command, self->set_current_row_command, - false, self->chip_select, &clipped, false); + false, self->chip_select, &clipped, false /* SH1107_addressing */); } uint8_t write_command = self->write_black_ram_command; @@ -270,8 +270,13 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c memset(buffer, 0, buffer_size * sizeof(buffer[0])); self->core.colorspace.grayscale = true; + self->core.colorspace.grayscale_bit = 7; if (pass == 1) { - self->core.colorspace.grayscale = false; + if (self->grayscale) { // 4-color grayscale + self->core.colorspace.grayscale_bit = 6; + } else { // Tri-color + self->core.colorspace.grayscale = false; + } } displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h index 3b9f6e368..4103fe5fc 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -55,6 +55,7 @@ typedef struct { bool black_bits_inverted; bool color_bits_inverted; bool refreshing; + bool grayscale; display_chip_select_behavior_t chip_select; } displayio_epaperdisplay_obj_t; diff --git a/shared-module/displayio/Palette.h b/shared-module/displayio/Palette.h index da72f250f..993912cc5 100644 --- a/shared-module/displayio/Palette.h +++ b/shared-module/displayio/Palette.h @@ -37,6 +37,7 @@ typedef struct { uint8_t bytes_per_cell; uint8_t tricolor_hue; uint8_t tricolor_luma; + uint8_t grayscale_bit; // The lowest grayscale bit. Normally 8 - depth. bool grayscale; bool tricolor; bool pixels_in_byte_share_row; diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c index 411f9f373..57d33b565 100644 --- a/shared-module/displayio/display_core.c +++ b/shared-module/displayio/display_core.c @@ -48,6 +48,7 @@ void displayio_display_core_construct(displayio_display_core_t* self, uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte, bool reverse_bytes_in_word) { self->colorspace.depth = color_depth; self->colorspace.grayscale = grayscale; + self->colorspace.grayscale_bit = 8 - color_depth; self->colorspace.pixels_in_byte_share_row = pixels_in_byte_share_row; self->colorspace.bytes_per_cell = bytes_per_cell; self->colorspace.reverse_pixels_in_byte = reverse_pixels_in_byte; -- cgit v1.2.3 From 9adb77a2d0179f89c7402451f6b25be74629ffbd Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 8 Nov 2020 19:28:46 -0600 Subject: set moved true when unhiding tilegrid --- shared-module/displayio/TileGrid.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'shared-module') diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index e3642107f..e8050a539 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -83,10 +83,16 @@ bool common_hal_displayio_tilegrid_get_hidden(displayio_tilegrid_t* self) { void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t* self, bool hidden) { self->hidden = hidden; + if(!hidden){ + self->moved = true; + } } void displayio_tilegrid_set_hidden_by_parent(displayio_tilegrid_t *self, bool hidden) { self->hidden_by_parent = hidden; + if(!hidden){ + self->moved = true; + } } bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_area_t* area) { -- cgit v1.2.3 From 46c9b28dd880d4e2e2764ab67f64356b175f5f98 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 9 Nov 2020 18:14:31 -0600 Subject: use full_change instead of moved --- shared-module/displayio/TileGrid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-module') diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index e8050a539..19ea10e55 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -84,14 +84,14 @@ bool common_hal_displayio_tilegrid_get_hidden(displayio_tilegrid_t* self) { void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t* self, bool hidden) { self->hidden = hidden; if(!hidden){ - self->moved = true; + self->full_change = true; } } void displayio_tilegrid_set_hidden_by_parent(displayio_tilegrid_t *self, bool hidden) { self->hidden_by_parent = hidden; if(!hidden){ - self->moved = true; + self->full_change = true; } } -- cgit v1.2.3 From 8d4296f96430795936a22769da35732e5342b25c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 10 Nov 2020 18:02:16 -0800 Subject: Add board.DISPLAY to MagTag. Fix luma computation * Initialize the EPaper display on the MagTag at start. * Tweak the display send to take a const buffer. * Correct Luma math * Multiply the blue component, not add. * Add all of the components together before dividing. This reduces the impact of truncated division. --- .../boards/adafruit_magtag_2.9_grayscale/board.c | 122 +++++++++++++++++++++ .../boards/adafruit_magtag_2.9_grayscale/pins.c | 4 + ports/esp32s2/common-hal/displayio/ParallelBus.c | 3 +- shared-bindings/displayio/EPaperDisplay.h | 2 +- shared-bindings/displayio/FourWire.h | 3 +- shared-bindings/displayio/I2CDisplay.h | 3 +- shared-bindings/displayio/ParallelBus.h | 3 +- shared-bindings/displayio/__init__.h | 3 +- shared-module/displayio/ColorConverter.c | 2 +- shared-module/displayio/EPaperDisplay.c | 14 ++- shared-module/displayio/EPaperDisplay.h | 4 +- shared-module/displayio/FourWire.c | 3 +- shared-module/displayio/I2CDisplay.c | 3 +- 13 files changed, 152 insertions(+), 17 deletions(-) (limited to 'shared-module') diff --git a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/board.c b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/board.c index 9f708874b..ecd44e423 100644 --- a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/board.c +++ b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/board.c @@ -26,7 +26,83 @@ #include "boards/board.h" #include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/board.h" + +#define DELAY 0x80 + +// This is an ILO373 control chip. The display is a 2.9" grayscale EInk. + +const uint8_t display_start_sequence[] = { + 0x01, 5, 0x03, 0x00, 0x2b, 0x2b, 0x13, // power setting + 0x06, 3, 0x17, 0x17, 0x17, // booster soft start + 0x04, DELAY, 200, // power on and wait 200 ms + 0x00, 1, 0x7f, // panel setting + 0x50, 1, 0x97, // CDI setting + 0x30, 1, 0x3c, // PLL set to 50 Hx (M = 7, N = 4) + 0x61, 3, 0x80, 0x01, 0x28, // Resolution + 0x82, DELAY | 1, 0x12, 50, // VCM DC and delay 50ms + + // Look up tables for voltage sequence for pixel transition + // Common voltage + 0x20, 0x2a, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x60, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x13, 0x0a, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // White to white + 0x21, 0x2a, + 0x40, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x10, 0x14, 0x0a, 0x00, 0x00, 0x01, + 0xa0, 0x13, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // Black to white + 0x22, 0x2a, + 0x40, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x0a, 0x00, 0x00, 0x01, + 0x99, 0x0c, 0x01, 0x03, 0x04, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // White to black + 0x23, 0x2a, + 0x40, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x0a, 0x00, 0x00, 0x01, + 0x99, 0x0b, 0x04, 0x04, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // Black to black + 0x24, 0x2a, + 0x80, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x20, 0x14, 0x0a, 0x00, 0x00, 0x01, + 0x50, 0x13, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t display_stop_sequence[] = { + 0x50, 0x01, 0x17, // CDI Setting + 0x82, 0x01, 0x00, // VCM DC to -0.1V + 0x02, 0x00 // Power off +}; void board_init(void) { // USB @@ -36,6 +112,52 @@ void board_init(void) { // Debug UART common_hal_never_reset_pin(&pin_GPIO43); common_hal_never_reset_pin(&pin_GPIO44); + + busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL); + common_hal_busio_spi_never_reset(spi); + + displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus; + bus->base.type = &displayio_fourwire_type; + common_hal_displayio_fourwire_construct(bus, + spi, + &pin_GPIO7, // EPD_DC Command or data + &pin_GPIO8, // EPD_CS Chip select + &pin_GPIO6, // EPD_RST Reset + 4000000, // Baudrate + 0, // Polarity + 0); // Phase + + displayio_epaperdisplay_obj_t* display = &displays[0].epaper_display; + display->base.type = &displayio_epaperdisplay_type; + common_hal_displayio_epaperdisplay_construct( + display, + bus, + display_start_sequence, sizeof(display_start_sequence), + display_stop_sequence, sizeof(display_stop_sequence), + 296, // width + 128, // height + 160, // ram_width + 296, // ram_height + 0, // colstart + 0, // rowstart + 270, // rotation + NO_COMMAND, // set_column_window_command + NO_COMMAND, // set_row_window_command + NO_COMMAND, // set_current_column_command + NO_COMMAND, // set_current_row_command + 0x10, // write_black_ram_command + false, // black_bits_inverted + 0x13, // write_color_ram_command + false, // color_bits_inverted + 0x000000, // highlight_color + 0x12, // refresh_display_command + 1.0, // refresh_time + &pin_GPIO5, // busy_pin + false, // busy_state + 5.0, // seconds_per_frame + false, // always_toggle_chip_select + true); // grayscale } bool board_requests_safe_mode(void) { diff --git a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c index 65bc3fb53..40c9e91e4 100644 --- a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c +++ b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c @@ -1,5 +1,7 @@ #include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_AD1), MP_ROM_PTR(&pin_GPIO18) }, @@ -37,5 +39,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)} }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/esp32s2/common-hal/displayio/ParallelBus.c b/ports/esp32s2/common-hal/displayio/ParallelBus.c index 314b72ff7..d0c98f361 100644 --- a/ports/esp32s2/common-hal/displayio/ParallelBus.c +++ b/ports/esp32s2/common-hal/displayio/ParallelBus.c @@ -57,7 +57,8 @@ bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) { return false; } -void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { +void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) { } diff --git a/shared-bindings/displayio/EPaperDisplay.h b/shared-bindings/displayio/EPaperDisplay.h index 352de899a..9a2d93bac 100644 --- a/shared-bindings/displayio/EPaperDisplay.h +++ b/shared-bindings/displayio/EPaperDisplay.h @@ -39,7 +39,7 @@ extern const mp_obj_type_t displayio_epaperdisplay_type; #define NO_COMMAND 0x100 void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self, - mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len, + mp_obj_t bus, const uint8_t* start_sequence, uint16_t start_sequence_len, const uint8_t* stop_sequence, uint16_t stop_sequence_len, uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t set_column_window_command, uint16_t set_row_window_command, uint16_t set_current_column_command, uint16_t set_current_row_command, diff --git a/shared-bindings/displayio/FourWire.h b/shared-bindings/displayio/FourWire.h index ac186d2c3..6f6b528e7 100644 --- a/shared-bindings/displayio/FourWire.h +++ b/shared-bindings/displayio/FourWire.h @@ -48,7 +48,8 @@ bool common_hal_displayio_fourwire_bus_free(mp_obj_t self); bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t self); -void common_hal_displayio_fourwire_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); +void common_hal_displayio_fourwire_send(mp_obj_t self, display_byte_type_t byte_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length); void common_hal_displayio_fourwire_end_transaction(mp_obj_t self); diff --git a/shared-bindings/displayio/I2CDisplay.h b/shared-bindings/displayio/I2CDisplay.h index bae53c491..37520202e 100644 --- a/shared-bindings/displayio/I2CDisplay.h +++ b/shared-bindings/displayio/I2CDisplay.h @@ -44,7 +44,8 @@ bool common_hal_displayio_i2cdisplay_bus_free(mp_obj_t self); bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t self); -void common_hal_displayio_i2cdisplay_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); +void common_hal_displayio_i2cdisplay_send(mp_obj_t self, display_byte_type_t byte_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length); void common_hal_displayio_i2cdisplay_end_transaction(mp_obj_t self); diff --git a/shared-bindings/displayio/ParallelBus.h b/shared-bindings/displayio/ParallelBus.h index be2aef7d4..1e74e3a0a 100644 --- a/shared-bindings/displayio/ParallelBus.h +++ b/shared-bindings/displayio/ParallelBus.h @@ -46,7 +46,8 @@ bool common_hal_displayio_parallelbus_bus_free(mp_obj_t self); bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t self); -void common_hal_displayio_parallelbus_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); +void common_hal_displayio_parallelbus_send(mp_obj_t self, display_byte_type_t byte_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length); void common_hal_displayio_parallelbus_end_transaction(mp_obj_t self); diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h index a7748d029..4fc666c59 100644 --- a/shared-bindings/displayio/__init__.h +++ b/shared-bindings/displayio/__init__.h @@ -42,7 +42,8 @@ typedef enum { typedef bool (*display_bus_bus_reset)(mp_obj_t bus); typedef bool (*display_bus_bus_free)(mp_obj_t bus); typedef bool (*display_bus_begin_transaction)(mp_obj_t bus); -typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); +typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length); typedef void (*display_bus_end_transaction)(mp_obj_t bus); void common_hal_displayio_release_displays(void); diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index 03ec99ceb..80558d037 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -55,7 +55,7 @@ uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888) { uint32_t r8 = (color_rgb888 >> 16); uint32_t g8 = (color_rgb888 >> 8) & 0xff; uint32_t b8 = color_rgb888 & 0xff; - return (r8 * 19) / 255 + (g8 * 182) / 255 + (b8 + 54) / 255; + return (r8 * 19 + g8 * 182 + b8 * 54) / 255; } uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888) { diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index 514b99a13..acca92ac1 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -43,7 +43,8 @@ #include void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self, - mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len, + mp_obj_t bus, const uint8_t* start_sequence, uint16_t start_sequence_len, + const uint8_t* stop_sequence, uint16_t stop_sequence_len, uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t set_column_window_command, uint16_t set_row_window_command, @@ -133,14 +134,15 @@ STATIC void wait_for_busy(displayio_epaperdisplay_obj_t* self) { } } -STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self, bool should_wait_for_busy, uint8_t* sequence, uint32_t sequence_len) { +STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self, + bool should_wait_for_busy, const uint8_t* sequence, uint32_t sequence_len) { uint32_t i = 0; while (i < sequence_len) { - uint8_t *cmd = sequence + i; + const uint8_t *cmd = sequence + i; uint8_t data_size = *(cmd + 1); bool delay = (data_size & DELAY) != 0; data_size &= ~DELAY; - uint8_t *data = cmd + 2; + const uint8_t *data = cmd + 2; displayio_display_core_begin_transaction(&self->core); self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1); self->core.send(self->core.bus, DISPLAY_DATA, self->chip_select, data, data_size); @@ -375,8 +377,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); + gc_collect_ptr((void *) self->start_sequence); + gc_collect_ptr((void *) self->stop_sequence); } bool maybe_refresh_epaperdisplay(void) { diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h index 4103fe5fc..d0668ff44 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -38,9 +38,9 @@ typedef struct { displayio_display_core_t core; digitalio_digitalinout_obj_t busy; uint32_t milliseconds_per_frame; - uint8_t* start_sequence; + const uint8_t* start_sequence; uint32_t start_sequence_len; - uint8_t* stop_sequence; + const uint8_t* stop_sequence; uint32_t stop_sequence_len; uint16_t refresh_time; uint16_t set_column_window_command; diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c index 8c56d7ab6..06f8a84e3 100644 --- a/shared-module/displayio/FourWire.c +++ b/shared-module/displayio/FourWire.c @@ -113,7 +113,8 @@ bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) { return true; } -void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { +void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) { displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj); common_hal_digitalio_digitalinout_set_value(&self->command, data_type == DISPLAY_DATA); if (chip_select == CHIP_SELECT_TOGGLE_EVERY_BYTE) { diff --git a/shared-module/displayio/I2CDisplay.c b/shared-module/displayio/I2CDisplay.c index 5bd03dcd6..cc811e83d 100644 --- a/shared-module/displayio/I2CDisplay.c +++ b/shared-module/displayio/I2CDisplay.c @@ -103,7 +103,8 @@ bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t obj) { return common_hal_busio_i2c_try_lock(self->bus); } -void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { +void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) { displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj); if (data_type == DISPLAY_COMMAND) { uint8_t command_bytes[2 * data_length]; -- cgit v1.2.3 From 78ccac930fbcb3dddd3a1a79809a2ec371d34c6a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 11 Nov 2020 16:53:45 -0800 Subject: Add .busy property to EPaperDisplay --- shared-bindings/displayio/EPaperDisplay.c | 18 ++++++++++++++++++ shared-bindings/displayio/EPaperDisplay.h | 1 + shared-module/displayio/EPaperDisplay.c | 5 +++++ 3 files changed, 24 insertions(+) (limited to 'shared-module') diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c index 8518e3714..ebff64008 100644 --- a/shared-bindings/displayio/EPaperDisplay.c +++ b/shared-bindings/displayio/EPaperDisplay.c @@ -245,6 +245,23 @@ const mp_obj_property_t displayio_epaperdisplay_time_to_refresh_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| busy: bool +//| """True when the display is refreshing. This uses the ``busy_pin`` when available or the +//| ``refresh_time`` otherwise.""" +//| +STATIC mp_obj_t displayio_epaperdisplay_obj_get_busy(mp_obj_t self_in) { + displayio_epaperdisplay_obj_t *self = native_display(self_in); + return mp_obj_new_bool(common_hal_displayio_epaperdisplay_get_busy(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_get_busy_obj, displayio_epaperdisplay_obj_get_busy); + +const mp_obj_property_t displayio_epaperdisplay_busy_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&displayio_epaperdisplay_get_busy_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| width: int //| """Gets the width of the display in pixels""" //| @@ -301,6 +318,7 @@ STATIC const mp_rom_map_elem_t displayio_epaperdisplay_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_epaperdisplay_width_obj) }, { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_epaperdisplay_height_obj) }, { MP_ROM_QSTR(MP_QSTR_bus), MP_ROM_PTR(&displayio_epaperdisplay_bus_obj) }, + { MP_ROM_QSTR(MP_QSTR_busy), MP_ROM_PTR(&displayio_epaperdisplay_busy_obj) }, { MP_ROM_QSTR(MP_QSTR_time_to_refresh), MP_ROM_PTR(&displayio_epaperdisplay_time_to_refresh_obj) }, }; STATIC MP_DEFINE_CONST_DICT(displayio_epaperdisplay_locals_dict, displayio_epaperdisplay_locals_dict_table); diff --git a/shared-bindings/displayio/EPaperDisplay.h b/shared-bindings/displayio/EPaperDisplay.h index 9a2d93bac..f785203a4 100644 --- a/shared-bindings/displayio/EPaperDisplay.h +++ b/shared-bindings/displayio/EPaperDisplay.h @@ -52,6 +52,7 @@ bool common_hal_displayio_epaperdisplay_show(displayio_epaperdisplay_obj_t* self // Returns time in milliseconds. uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaperdisplay_obj_t* self); +bool common_hal_displayio_epaperdisplay_get_busy(displayio_epaperdisplay_obj_t* self); uint16_t common_hal_displayio_epaperdisplay_get_width(displayio_epaperdisplay_obj_t* self); uint16_t common_hal_displayio_epaperdisplay_get_height(displayio_epaperdisplay_obj_t* self); diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index acca92ac1..1b285b4b1 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -360,6 +360,11 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) { } } +bool common_hal_displayio_epaperdisplay_get_busy(displayio_epaperdisplay_obj_t* self) { + displayio_epaperdisplay_background(self); + return self->refreshing; +} + void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) { if (self->refreshing) { wait_for_busy(self); -- cgit v1.2.3 From f61f8f999b5eeb8a545f5cea13b30ac5b3aeb04a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 18 Nov 2020 18:06:31 -0600 Subject: EPaperDisplay: add rotation property untested, because I don't want to mess my magtag demo up :) but it builds --- shared-bindings/displayio/EPaperDisplay.c | 24 ++++++++++++++++++++++++ shared-bindings/displayio/EPaperDisplay.h | 2 ++ shared-module/displayio/EPaperDisplay.c | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+) (limited to 'shared-module') diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c index ebff64008..4f5c47aca 100644 --- a/shared-bindings/displayio/EPaperDisplay.c +++ b/shared-bindings/displayio/EPaperDisplay.c @@ -294,6 +294,29 @@ const mp_obj_property_t displayio_epaperdisplay_height_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| rotation: int +//| """The rotation of the display as an int in degrees.""" +//| +STATIC mp_obj_t displayio_epaperdisplay_obj_get_rotation(mp_obj_t self_in) { + displayio_epaperdisplay_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_epaperdisplay_get_rotation(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(displayio_epaperdisplay_get_rotation_obj, displayio_epaperdisplay_obj_get_rotation); +STATIC mp_obj_t displayio_epaperdisplay_obj_set_rotation(mp_obj_t self_in, mp_obj_t value) { + displayio_epaperdisplay_obj_t *self = native_display(self_in); + common_hal_displayio_epaperdisplay_set_rotation(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(displayio_epaperdisplay_set_rotation_obj, displayio_epaperdisplay_obj_set_rotation); + + +const mp_obj_property_t displayio_epaperdisplay_rotation_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&displayio_epaperdisplay_get_rotation_obj, + (mp_obj_t)&displayio_epaperdisplay_set_rotation_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| bus: _DisplayBus //| """The bus being used by the display""" //| @@ -317,6 +340,7 @@ STATIC const mp_rom_map_elem_t displayio_epaperdisplay_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_epaperdisplay_width_obj) }, { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_epaperdisplay_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&displayio_epaperdisplay_rotation_obj) }, { MP_ROM_QSTR(MP_QSTR_bus), MP_ROM_PTR(&displayio_epaperdisplay_bus_obj) }, { MP_ROM_QSTR(MP_QSTR_busy), MP_ROM_PTR(&displayio_epaperdisplay_busy_obj) }, { MP_ROM_QSTR(MP_QSTR_time_to_refresh), MP_ROM_PTR(&displayio_epaperdisplay_time_to_refresh_obj) }, diff --git a/shared-bindings/displayio/EPaperDisplay.h b/shared-bindings/displayio/EPaperDisplay.h index f785203a4..14d4f6aa9 100644 --- a/shared-bindings/displayio/EPaperDisplay.h +++ b/shared-bindings/displayio/EPaperDisplay.h @@ -56,6 +56,8 @@ bool common_hal_displayio_epaperdisplay_get_busy(displayio_epaperdisplay_obj_t* uint16_t common_hal_displayio_epaperdisplay_get_width(displayio_epaperdisplay_obj_t* self); uint16_t common_hal_displayio_epaperdisplay_get_height(displayio_epaperdisplay_obj_t* self); +uint16_t common_hal_displayio_epaperdisplay_get_rotation(displayio_epaperdisplay_obj_t* self); +void common_hal_displayio_epaperdisplay_set_rotation(displayio_epaperdisplay_obj_t* self, int rotation); mp_obj_t common_hal_displayio_epaperdisplay_get_bus(displayio_epaperdisplay_obj_t* self); diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index 1b285b4b1..3fb37ff21 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -198,6 +198,29 @@ mp_obj_t common_hal_displayio_epaperdisplay_get_bus(displayio_epaperdisplay_obj_ return self->core.bus; } +void common_hal_displayio_epaperdisplay_set_rotation(displayio_epaperdisplay_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); + if (self == &displays[0].epaper_display) { + 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_epaperdisplay_get_rotation(displayio_epaperdisplay_obj_t* self){ + return self->core.rotation; +} + + bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, const displayio_area_t* area) { uint16_t buffer_size = 128; // In uint32_ts -- cgit v1.2.3 From 2463a6d6ac3fb53fa471c77bc585c8ef350d2b96 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 18 Nov 2020 16:28:21 -0800 Subject: Fix Palette grayscale for EInk. It needs to do the bitmasking that was only added to ColorConverter in #3611 --- shared-module/displayio/Palette.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c index facb1fa73..ba5ff665c 100644 --- a/shared-module/displayio/Palette.c +++ b/shared-module/displayio/Palette.c @@ -83,7 +83,8 @@ bool displayio_palette_get_color(displayio_palette_t *self, const _displayio_col uint8_t pixel_hue = self->colors[palette_index].hue; displayio_colorconverter_compute_tricolor(colorspace, pixel_hue, luma, color); } else if (colorspace->grayscale) { - *color = self->colors[palette_index].luma >> (8 - colorspace->depth); + size_t bitmask = (1 << colorspace->depth) - 1; + *color = (self->colors[palette_index].luma >> colorspace->grayscale_bit) & bitmask; } else { uint16_t packed = self->colors[palette_index].rgb565; if (colorspace->reverse_bytes_in_word) { -- cgit v1.2.3 From fc344bc818f8172ff36ee646459d7d060a51289a Mon Sep 17 00:00:00 2001 From: James Bowman Date: Tue, 24 Nov 2020 17:26:39 -0800 Subject: Fix opcode typo in VertexFormat() --- shared-module/_eve/__init__.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-module') diff --git a/shared-module/_eve/__init__.c b/shared-module/_eve/__init__.c index 0f1e12d9f..d95c777dc 100644 --- a/shared-module/_eve/__init__.c +++ b/shared-module/_eve/__init__.c @@ -70,8 +70,8 @@ void common_hal__eve_Vertex2f(common_hal__eve_t *eve, mp_float_t x, mp_float_t y void common_hal__eve_VertexFormat(common_hal__eve_t *eve, uint32_t frac) { - C4(eve, ((27 << 24) | ((frac & 7)))); - eve->vscale = 1 << eve->vscale; + C4(eve, ((39 << 24) | ((frac & 7)))); + eve->vscale = 1 << frac; } -- cgit v1.2.3 From c7404a3ff89c738c002ec63448a58d56330dfcc3 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sun, 11 Oct 2020 14:59:33 +0200 Subject: Add movable allocation system. This allows calls to `allocate_memory()` while the VM is running, it will then allocate from the GC heap (unless there is a suitable hole among the supervisor allocations), and when the VM exits and the GC heap is freed, the allocation will be moved to the bottom of the former GC heap and transformed into a proper supervisor allocation. Existing movable allocations will also be moved to defragment the supervisor heap and ensure that the next VM run gets as much memory as possible for the GC heap. By itself this breaks terminalio because it violates the assumption that supervisor_display_move_memory() still has access to an undisturbed heap to copy the tilegrid from. It will work in many cases, but if you're unlucky you will get garbled terminal contents after exiting from the vm run that created the display. This will be fixed in the following commit, which is separate to simplify review. --- main.c | 13 +- ports/atmel-samd/supervisor/port.c | 4 +- ports/cxd56/supervisor/port.c | 8 +- ports/esp32s2/supervisor/port.c | 8 +- ports/litex/supervisor/port.c | 4 +- ports/mimxrt10xx/supervisor/port.c | 7 +- ports/nrf/supervisor/port.c | 4 +- ports/stm/supervisor/port.c | 4 +- py/circuitpy_mpconfig.h | 4 + shared-module/rgbmatrix/RGBMatrix.c | 2 +- .../sharpdisplay/SharpMemoryFramebuffer.c | 2 +- shared-module/usb_midi/__init__.c | 2 +- supervisor/memory.h | 26 +- supervisor/port.h | 5 +- supervisor/shared/display.c | 4 +- supervisor/shared/external_flash/external_flash.c | 2 +- supervisor/shared/memory.c | 277 +++++++++++++++------ supervisor/shared/stack.c | 38 ++- supervisor/shared/stack.h | 6 +- 19 files changed, 283 insertions(+), 137 deletions(-) (limited to 'shared-module') diff --git a/main.c b/main.c index 80b163f60..1389f524b 100755 --- a/main.c +++ b/main.c @@ -123,15 +123,15 @@ void start_mp(supervisor_allocation* heap) { // to recover from limit hit. (Limit is measured in bytes.) mp_stack_ctrl_init(); - if (stack_alloc != NULL) { - mp_stack_set_limit(stack_alloc->length - 1024); + if (stack_get_bottom() != NULL) { + mp_stack_set_limit(stack_get_length() - 1024); } #if MICROPY_MAX_STACK_USAGE // _ezero (same as _ebss) is an int, so start 4 bytes above it. - if (stack_alloc != NULL) { - mp_stack_set_bottom(stack_alloc->ptr); + if (stack_get_bottom() != NULL) { + mp_stack_set_bottom(stack_get_bottom()); mp_stack_fill_with_sentinel(); } #endif @@ -148,7 +148,7 @@ void start_mp(supervisor_allocation* heap) { #endif #if MICROPY_ENABLE_GC - gc_init(heap->ptr, heap->ptr + heap->length / 4); + gc_init(heap->ptr, heap->ptr + get_allocation_length(heap) / 4); #endif mp_init(); mp_obj_list_init(mp_sys_path, 0); @@ -451,9 +451,6 @@ int __attribute__((used)) main(void) { // initialise the cpu and peripherals safe_mode_t safe_mode = port_init(); - // Init memory after the port in case the port needs to set aside memory. - memory_init(); - // Turn on LEDs init_status_leds(); rgb_led_status_init(); diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index d65d09825..fc1d1198e 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -390,8 +390,8 @@ void reset_cpu(void) { reset(); } -supervisor_allocation* port_fixed_stack(void) { - return NULL; +bool port_has_fixed_stack(void) { + return false; } uint32_t *port_stack_get_limit(void) { diff --git a/ports/cxd56/supervisor/port.c b/ports/cxd56/supervisor/port.c index 086c2d198..d69f35779 100644 --- a/ports/cxd56/supervisor/port.c +++ b/ports/cxd56/supervisor/port.c @@ -98,12 +98,8 @@ void reset_to_bootloader(void) { } } -supervisor_allocation _fixed_stack; - -supervisor_allocation* port_fixed_stack(void) { - _fixed_stack.ptr = port_stack_get_limit(); - _fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t); - return &_fixed_stack; +bool port_has_fixed_stack(void) { + return true; } uint32_t *port_stack_get_limit(void) { diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index aff7dbda4..264bdee97 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -193,12 +193,8 @@ uint32_t *port_stack_get_top(void) { return port_stack_get_limit() + ESP_TASK_MAIN_STACK / (sizeof(uint32_t) / sizeof(StackType_t)); } -supervisor_allocation _fixed_stack; - -supervisor_allocation* port_fixed_stack(void) { - _fixed_stack.ptr = port_stack_get_limit(); - _fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t); - return &_fixed_stack; +bool port_has_fixed_stack(void) { + return true; } // Place the word to save just after our BSS section that gets blanked. diff --git a/ports/litex/supervisor/port.c b/ports/litex/supervisor/port.c index 02617b9af..f5c362ea6 100644 --- a/ports/litex/supervisor/port.c +++ b/ports/litex/supervisor/port.c @@ -98,8 +98,8 @@ void reset_cpu(void) { for(;;) {} } -supervisor_allocation* port_fixed_stack(void) { - return NULL; +bool port_has_fixed_stack(void) { + return false; } uint32_t *port_heap_get_bottom(void) { diff --git a/ports/mimxrt10xx/supervisor/port.c b/ports/mimxrt10xx/supervisor/port.c index e3fef373f..1be2b1039 100644 --- a/ports/mimxrt10xx/supervisor/port.c +++ b/ports/mimxrt10xx/supervisor/port.c @@ -334,11 +334,8 @@ uint32_t *port_stack_get_top(void) { return &_ld_stack_top; } -supervisor_allocation _fixed_stack; -supervisor_allocation* port_fixed_stack(void) { - _fixed_stack.ptr = port_stack_get_limit(); - _fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t); - return &_fixed_stack; +bool port_has_fixed_stack(void) { + return true; } uint32_t *port_heap_get_bottom(void) { diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index 493de43e0..5f1c9f1ba 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -251,8 +251,8 @@ uint32_t *port_heap_get_top(void) { return port_stack_get_top(); } -supervisor_allocation* port_fixed_stack(void) { - return NULL; +bool port_has_fixed_stack(void) { + return false; } uint32_t *port_stack_get_limit(void) { diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index a8aab00ff..dba1cf21e 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -267,8 +267,8 @@ uint32_t *port_heap_get_top(void) { return &_ld_heap_end; } -supervisor_allocation* port_fixed_stack(void) { - return NULL; +bool port_has_fixed_stack(void) { + return false; } uint32_t *port_stack_get_limit(void) { diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 28fd4095c..28fd6e9b0 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -858,6 +858,9 @@ extern const struct _mp_obj_module_t wifi_module; #include "supervisor/flash_root_pointers.h" +// From supervisor/memory.c +struct _supervisor_allocation_node; + #define CIRCUITPY_COMMON_ROOT_POINTERS \ const char *readline_hist[8]; \ vstr_t *repl_line; \ @@ -869,6 +872,7 @@ extern const struct _mp_obj_module_t wifi_module; FLASH_ROOT_POINTERS \ MEMORYMONITOR_ROOT_POINTERS \ NETWORK_ROOT_POINTERS \ + struct _supervisor_allocation_node* first_embedded_allocation; \ void supervisor_run_background_tasks_if_tick(void); #define RUN_BACKGROUND_TASKS (supervisor_run_background_tasks_if_tick()) diff --git a/shared-module/rgbmatrix/RGBMatrix.c b/shared-module/rgbmatrix/RGBMatrix.c index 94c3eda27..1f144aedb 100644 --- a/shared-module/rgbmatrix/RGBMatrix.c +++ b/shared-module/rgbmatrix/RGBMatrix.c @@ -220,7 +220,7 @@ void *common_hal_rgbmatrix_allocator_impl(size_t sz) { if (gc_alloc_possible()) { return m_malloc_maybe(sz + sizeof(void*), true); } else { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false); + supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, false); return allocation ? allocation->ptr : NULL; } } diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c index b199e98d6..aefb6b18d 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c @@ -40,7 +40,7 @@ #define SHARPMEM_BIT_VCOM_LSB (0x40) static void *hybrid_alloc(size_t sz) { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false); + supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, false); if (allocation) { memset(allocation->ptr, 0, sz); return allocation->ptr; diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index 73a314b99..5afdd1821 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -45,7 +45,7 @@ void usb_midi_init(void) { uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t)); // For each embedded MIDI Jack in the descriptor we create a Port - usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false); + usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false, false); mp_obj_tuple_t *ports = (mp_obj_tuple_t *) usb_midi_allocation->ptr; ports->base.type = &mp_type_tuple; diff --git a/supervisor/memory.h b/supervisor/memory.h index f4359ca46..4307e3f21 100755 --- a/supervisor/memory.h +++ b/supervisor/memory.h @@ -33,23 +33,36 @@ #include #include +#include typedef struct { uint32_t* ptr; - uint32_t length; // in bytes } supervisor_allocation; -void memory_init(void); void free_memory(supervisor_allocation* allocation); + +// Find the allocation with the given ptr, NULL if not found. When called from the context of a +// supervisor_move_memory() callback, finds the allocation that had that ptr *before* the move, but +// the returned allocation already contains the ptr after the move. +// When called with NULL, may return either NULL or an unused allocation whose ptr is NULL (this is +// a feature used internally in allocate_memory to save code size). Passing the return value to +// free_memory() is a permissible no-op in either case. supervisor_allocation* allocation_from_ptr(void *ptr); + supervisor_allocation* allocate_remaining_memory(void); // Allocate a piece of a given length in bytes. If high_address is true then it should be allocated // at a lower address from the top of the stack. Otherwise, addresses will increase starting after -// statically allocated memory. -supervisor_allocation* allocate_memory(uint32_t length, bool high_address); +// statically allocated memory. If movable is false, memory will be taken from outside the GC heap +// and will stay stationary until freed. While the VM is running, this will fail unless a previous +// allocation of exactly matching length has recently been freed. If movable is true, memory will be +// taken from either outside or inside the GC heap, and when the VM exits, will be moved outside. +// The ptr of the returned supervisor_allocation will change at that point. If you need to be +// notified of that, add your own callback function at the designated place near the end of +// supervisor_move_memory(). +supervisor_allocation* allocate_memory(uint32_t length, bool high_address, bool movable); static inline uint16_t align32_size(uint16_t size) { if (size % 4 != 0) { @@ -58,7 +71,10 @@ static inline uint16_t align32_size(uint16_t size) { return size; } -// Called after the heap is freed in case the supervisor wants to save some values. +size_t get_allocation_length(supervisor_allocation* allocation); + +// Called after the GC heap is freed, transfers movable allocations from the GC heap to the +// supervisor heap and compacts the supervisor heap. void supervisor_move_memory(void); #endif // MICROPY_INCLUDED_SUPERVISOR_MEMORY_H diff --git a/supervisor/port.h b/supervisor/port.h index f5b3c15d1..5bc06bc4e 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -61,7 +61,8 @@ uint32_t *port_stack_get_limit(void); // Get stack top address uint32_t *port_stack_get_top(void); -supervisor_allocation* port_fixed_stack(void); +// True if stack is not located inside heap (at the top) +bool port_has_fixed_stack(void); // Get heap bottom address uint32_t *port_heap_get_bottom(void); @@ -69,8 +70,6 @@ uint32_t *port_heap_get_bottom(void); // Get heap top address uint32_t *port_heap_get_top(void); -supervisor_allocation* port_fixed_heap(void); - // Save and retrieve a word from memory that is preserved over reset. Used for safe mode. void port_set_saved_word(uint32_t); uint32_t port_get_saved_word(void); diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index a9ae25884..de45e2672 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -82,7 +82,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { uint16_t total_tiles = width_in_tiles * height_in_tiles; // First try to allocate outside the heap. This will fail when the VM is running. - tilegrid_tiles = allocate_memory(align32_size(total_tiles), false); + tilegrid_tiles = allocate_memory(align32_size(total_tiles), false, false); uint8_t* tiles; if (tilegrid_tiles == NULL) { tiles = m_malloc(total_tiles, true); @@ -133,7 +133,7 @@ void supervisor_display_move_memory(void) { grid->tiles == MP_STATE_VM(terminal_tilegrid_tiles)) { uint16_t total_tiles = grid->width_in_tiles * grid->height_in_tiles; - tilegrid_tiles = allocate_memory(align32_size(total_tiles), false); + tilegrid_tiles = allocate_memory(align32_size(total_tiles), false, false); if (tilegrid_tiles != NULL) { memcpy(tilegrid_tiles->ptr, grid->tiles, total_tiles); grid->tiles = (uint8_t*) tilegrid_tiles->ptr; diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index 5bde7fd48..e2d767235 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -338,7 +338,7 @@ static bool allocate_ram_cache(void) { uint32_t table_size = blocks_per_sector * pages_per_block * sizeof(uint32_t); // Attempt to allocate outside the heap first. - supervisor_cache = allocate_memory(table_size + SPI_FLASH_ERASE_SIZE, false); + supervisor_cache = allocate_memory(table_size + SPI_FLASH_ERASE_SIZE, false, false); if (supervisor_cache != NULL) { MP_STATE_VM(flash_ram_cache) = (uint8_t **) supervisor_cache->ptr; uint8_t* page_start = (uint8_t *) supervisor_cache->ptr + table_size; diff --git a/supervisor/shared/memory.c b/supervisor/shared/memory.c index 0f96ae273..2be3b42d6 100755 --- a/supervisor/shared/memory.c +++ b/supervisor/shared/memory.c @@ -27,78 +27,81 @@ #include "supervisor/memory.h" #include "supervisor/port.h" -#include +#include +#include "py/gc.h" #include "supervisor/shared/display.h" #define CIRCUITPY_SUPERVISOR_ALLOC_COUNT (12) -// Using a zero length to mark an unused allocation makes the code a bit shorter (but makes it -// impossible to support zero-length allocations). -#define FREE 0 - // The lowest two bits of a valid length are always zero, so we can use them to mark an allocation -// as freed by the client but not yet reclaimed into the FREE middle. +// as a hole (freed by the client but not yet reclaimed into the free middle) and as movable. +#define FLAGS 3 #define HOLE 1 +#define MOVABLE 2 static supervisor_allocation allocations[CIRCUITPY_SUPERVISOR_ALLOC_COUNT]; -// We use uint32_t* to ensure word (4 byte) alignment. -uint32_t* low_address; -uint32_t* high_address; +supervisor_allocation* old_allocations; -void memory_init(void) { - low_address = port_heap_get_bottom(); - high_address = port_heap_get_top(); -} +typedef struct _supervisor_allocation_node { + struct _supervisor_allocation_node* next; + size_t length; + // We use uint32_t to ensure word (4 byte) alignment. + uint32_t data[]; +} supervisor_allocation_node; + +supervisor_allocation_node* low_head; +supervisor_allocation_node* high_head; + +// Intermediate (void*) is to suppress -Wcast-align warning. Alignment will always be correct +// because this only reverses how (alloc)->ptr was obtained as &(node->data[0]). +#define ALLOCATION_NODE(alloc) ((supervisor_allocation_node*)(void*)((char*)((alloc)->ptr) - sizeof(supervisor_allocation_node))) void free_memory(supervisor_allocation* allocation) { - if (allocation == NULL) { + if (allocation == NULL || allocation->ptr == NULL) { return; } - int32_t index = 0; - bool found = false; - for (index = 0; index < CIRCUITPY_SUPERVISOR_ALLOC_COUNT; index++) { - found = allocation == &allocations[index]; - if (found) { - break; - } + supervisor_allocation_node* node = ALLOCATION_NODE(allocation); + if (node == low_head) { + do { + low_head = low_head->next; + } while (low_head != NULL && (low_head->length & HOLE)); } - if (!found) { - // Bad! - // TODO(tannewt): Add a way to escape into safe mode on error. + else if (node == high_head) { + do { + high_head = high_head->next; + } while (high_head != NULL && (high_head->length & HOLE)); } - if (allocation->ptr == high_address) { - high_address += allocation->length / 4; - allocation->length = FREE; - for (index++; index < CIRCUITPY_SUPERVISOR_ALLOC_COUNT; index++) { - if (!(allocations[index].length & HOLE)) { - break; - } - // Division automatically shifts out the HOLE bit. - high_address += allocations[index].length / 4; - allocations[index].length = FREE; - } - } else if (allocation->ptr + allocation->length / 4 == low_address) { - low_address = allocation->ptr; - allocation->length = FREE; - for (index--; index >= 0; index--) { - if (!(allocations[index].length & HOLE)) { - break; + else { + // Check if it's in the list of embedded allocations. + supervisor_allocation_node** emb = &MP_STATE_VM(first_embedded_allocation); + while (*emb != NULL) { + if (*emb == node) { + // Found, remove it from the list. + *emb = node->next; + m_free(node +#if MICROPY_MALLOC_USES_ALLOCATED_SIZE + , sizeof(supervisor_allocation_node) + (node->length & ~FLAGS) +#endif + ); + goto done; } - low_address -= allocations[index].length / 4; - allocations[index].length = FREE; + emb = &((*emb)->next); } - } else { - // Freed memory isn't in the middle so skip updating bounds. The memory will be added to the - // middle when the memory to the inside is freed. We still need its length, but setting - // only the lowest bit is nondestructive. - allocation->length |= HOLE; + // Else it must be within the low or high ranges and becomes a hole. + node->length = ((node->length & ~FLAGS) | HOLE); } +done: + allocation->ptr = NULL; } supervisor_allocation* allocation_from_ptr(void *ptr) { + // When called from the context of supervisor_move_memory() (old_allocations != NULL), search + // by old pointer to give clients a way of mapping from old to new pointer. But not if + // ptr == NULL, then the caller wants an allocation whose current ptr is NULL. + supervisor_allocation* list = (old_allocations && ptr) ? old_allocations : &allocations[0]; for (size_t index = 0; index < CIRCUITPY_SUPERVISOR_ALLOC_COUNT; index++) { - if (allocations[index].ptr == ptr) { + if (list[index].ptr == ptr) { return &allocations[index]; } } @@ -106,50 +109,172 @@ supervisor_allocation* allocation_from_ptr(void *ptr) { } supervisor_allocation* allocate_remaining_memory(void) { - if (low_address == high_address) { - return NULL; + uint32_t* low_address = low_head ? low_head->data + low_head->length / 4 : port_heap_get_bottom(); + uint32_t* high_address = high_head ? (uint32_t*)high_head : port_heap_get_top(); + return allocate_memory((high_address - low_address) * 4 - sizeof(supervisor_allocation_node), false, false); +} + +static supervisor_allocation_node* find_hole(supervisor_allocation_node* node, size_t length) { + for (; node != NULL; node = node->next) { + if (node->length == (length | HOLE)) { + break; + } } - return allocate_memory((high_address - low_address) * 4, false); + return node; } -supervisor_allocation* allocate_memory(uint32_t length, bool high) { +static supervisor_allocation_node* allocate_memory_node(uint32_t length, bool high, bool movable) { + // supervisor_move_memory() currently does not support movable allocations on the high side, it + // must be extended first if this is ever needed. + assert(!(high && movable)); if (length == 0 || length % 4 != 0) { return NULL; } - uint8_t index = 0; - int8_t direction = 1; - if (high) { - index = CIRCUITPY_SUPERVISOR_ALLOC_COUNT - 1; - direction = -1; - } - supervisor_allocation* alloc; - for (; index < CIRCUITPY_SUPERVISOR_ALLOC_COUNT; index += direction) { - alloc = &allocations[index]; - if (alloc->length == FREE && (high_address - low_address) * 4 >= (int32_t) length) { - break; + // 1. Matching hole on the requested side? + supervisor_allocation_node* node = find_hole(high ? high_head : low_head, length); + if (!node) { + // 2. Enough free space in the middle? + uint32_t* low_address = low_head ? low_head->data + low_head->length / 4 : port_heap_get_bottom(); + uint32_t* high_address = high_head ? (uint32_t*)high_head : port_heap_get_top(); + if ((high_address - low_address) * 4 >= (int32_t)(sizeof(supervisor_allocation_node) + length)) { + if (high) { + high_address -= (sizeof(supervisor_allocation_node) + length) / 4; + node = (supervisor_allocation_node*)high_address; + node->next = high_head; + high_head = node; + } + else { + node = (supervisor_allocation_node*)low_address; + node->next = low_head; + low_head = node; + } } - // If a hole matches in length exactly, we can reuse it. - if (alloc->length == (length | HOLE)) { - alloc->length = length; - return alloc; + else { + // 3. Matching hole on the other side? + node = find_hole(high ? low_head : high_head, length); + if (!node) { + // 4. GC allocation? + if (movable && gc_alloc_possible()) { + node = m_malloc_maybe(sizeof(supervisor_allocation_node) + length, true); + if (node) { + node->next = MP_STATE_VM(first_embedded_allocation); + MP_STATE_VM(first_embedded_allocation) = node; + } + } + if (!node) { + // 5. Give up. + return NULL; + } + } } } - if (index >= CIRCUITPY_SUPERVISOR_ALLOC_COUNT) { + node->length = length; + if (movable) { + node->length |= MOVABLE; + } + return node; +} + +supervisor_allocation* allocate_memory(uint32_t length, bool high, bool movable) { + supervisor_allocation_node* node = allocate_memory_node(length, high, movable); + if (!node) { return NULL; } - if (high) { - high_address -= length / 4; - alloc->ptr = high_address; - } else { - alloc->ptr = low_address; - low_address += length / 4; + // Find the first free allocation. + supervisor_allocation* alloc = allocation_from_ptr(NULL); + if (!alloc) { + // We should free node again to avoid leaking, but something is wrong anyway if clients try + // to make more allocations than available, so don't bother. + return NULL; } - alloc->length = length; + alloc->ptr = &(node->data[0]); return alloc; } +size_t get_allocation_length(supervisor_allocation* allocation) { + return ALLOCATION_NODE(allocation)->length & ~FLAGS; +} + void supervisor_move_memory(void) { + // This must be called exactly after freeing the heap, so that the embedded allocations, if any, + // are now in the free region. + assert(MP_STATE_VM(first_embedded_allocation) == NULL || (low_head < MP_STATE_VM(first_embedded_allocation) && MP_STATE_VM(first_embedded_allocation) < high_head)); + + // Save the old pointers for allocation_from_ptr(). + supervisor_allocation old_allocations_array[CIRCUITPY_SUPERVISOR_ALLOC_COUNT]; + memcpy(old_allocations_array, allocations, sizeof(allocations)); + + // Compact the low side. Traverse the list repeatedly, finding movable allocations preceded by a + // hole and swapping them, until no more are found. This is not the most runtime-efficient way, + // but probably the shortest and simplest code. + bool acted; + do { + acted = false; + supervisor_allocation_node** nodep = &low_head; + while (*nodep != NULL && (*nodep)->next != NULL) { + if (((*nodep)->length & MOVABLE) && ((*nodep)->next->length & HOLE)) { + supervisor_allocation_node* oldnode = *nodep; + supervisor_allocation_node* start = oldnode->next; + supervisor_allocation* alloc = allocation_from_ptr(&(oldnode->data[0])); + assert(alloc != NULL); + alloc->ptr = &(start->data[0]); + oldnode->next = start->next; + size_t holelength = start->length; + size_t size = sizeof(supervisor_allocation_node) + (oldnode->length & ~FLAGS); + memmove(start, oldnode, size); + supervisor_allocation_node* newhole = (supervisor_allocation_node*)(void*)((char*)start + size); + newhole->next = start; + newhole->length = holelength; + *nodep = newhole; + acted = true; + } + nodep = &((*nodep)->next); + } + } while (acted); + // Any holes bubbled to the top can be absorbed into the free middle. + while (low_head != NULL && (low_head->length & HOLE)) { + low_head = low_head->next; + }; + + // Don't bother compacting the high side, there are no movable allocations and no holes there in + // current usage. + + // Promote the embedded allocations to top-level ones, compacting them at the beginning of the + // now free region (or possibly in matching holes). + // The linked list is unordered, but allocations must be processed in order to avoid risking + // overwriting each other. To that end, repeatedly find the lowest element of the list, remove + // it from the list, and process it. This ad-hoc selection sort results in substantially shorter + // code than using the qsort() function from the C library. + while (MP_STATE_VM(first_embedded_allocation)) { + // First element is first candidate. + supervisor_allocation_node** pminnode = &MP_STATE_VM(first_embedded_allocation); + // Iterate from second element (if any) on. + for (supervisor_allocation_node** pnode = &(MP_STATE_VM(first_embedded_allocation)->next); *pnode != NULL; pnode = &(*pnode)->next) { + if (*pnode < *pminnode) { + pminnode = pnode; + } + } + // Remove from list. + supervisor_allocation_node* node = *pminnode; + *pminnode = node->next; + // Process. + size_t length = (node->length & ~FLAGS); + supervisor_allocation* alloc = allocation_from_ptr(&(node->data[0])); + assert(alloc != NULL); + // This may overwrite the header of node if it happened to be there already, but not the + // data. + supervisor_allocation_node* new_node = allocate_memory_node(length, false, true); + // There must be enough free space. + assert(new_node != NULL); + memmove(&(new_node->data[0]), &(node->data[0]), length); + alloc->ptr = &(new_node->data[0]); + } + + // Notify clients that their movable allocations may have moved. + old_allocations = &old_allocations_array[0]; #if CIRCUITPY_DISPLAYIO supervisor_display_move_memory(); #endif + // Add calls to further clients here. + old_allocations = NULL; } diff --git a/supervisor/shared/stack.c b/supervisor/shared/stack.c index e7aa956b0..afea20401 100755 --- a/supervisor/shared/stack.c +++ b/supervisor/shared/stack.c @@ -34,36 +34,42 @@ extern uint32_t _estack; +// Requested size. static uint32_t next_stack_size = CIRCUITPY_DEFAULT_STACK_SIZE; static uint32_t current_stack_size = 0; -supervisor_allocation* stack_alloc = NULL; +// Actual location and size, may be larger than requested. +static uint32_t* stack_limit = NULL; +static size_t stack_length = 0; #define EXCEPTION_STACK_SIZE 1024 void allocate_stack(void) { - if (port_fixed_stack() != NULL) { - stack_alloc = port_fixed_stack(); - current_stack_size = stack_alloc->length; + if (port_has_fixed_stack()) { + stack_limit = port_stack_get_limit(); + stack_length = (port_stack_get_top() - stack_limit)*sizeof(uint32_t); + current_stack_size = stack_length; } else { mp_uint_t regs[10]; mp_uint_t sp = cpu_get_regs_and_sp(regs); mp_uint_t c_size = (uint32_t) port_stack_get_top() - sp; - stack_alloc = allocate_memory(c_size + next_stack_size + EXCEPTION_STACK_SIZE, true); + supervisor_allocation* stack_alloc = allocate_memory(c_size + next_stack_size + EXCEPTION_STACK_SIZE, true, false); if (stack_alloc == NULL) { - stack_alloc = allocate_memory(c_size + CIRCUITPY_DEFAULT_STACK_SIZE + EXCEPTION_STACK_SIZE, true); + stack_alloc = allocate_memory(c_size + CIRCUITPY_DEFAULT_STACK_SIZE + EXCEPTION_STACK_SIZE, true, false); current_stack_size = CIRCUITPY_DEFAULT_STACK_SIZE; } else { current_stack_size = next_stack_size; } + stack_limit = stack_alloc->ptr; + stack_length = get_allocation_length(stack_alloc); } - *stack_alloc->ptr = STACK_CANARY_VALUE; + *stack_limit = STACK_CANARY_VALUE; } inline bool stack_ok(void) { - return stack_alloc == NULL || *stack_alloc->ptr == STACK_CANARY_VALUE; + return stack_limit == NULL || *stack_limit == STACK_CANARY_VALUE; } inline void assert_heap_ok(void) { @@ -77,18 +83,26 @@ void stack_init(void) { } void stack_resize(void) { - if (stack_alloc == NULL) { + if (stack_limit == NULL) { return; } if (next_stack_size == current_stack_size) { - *stack_alloc->ptr = STACK_CANARY_VALUE; + *stack_limit = STACK_CANARY_VALUE; return; } - free_memory(stack_alloc); - stack_alloc = NULL; + free_memory(allocation_from_ptr(stack_limit)); + stack_limit = NULL; allocate_stack(); } +uint32_t* stack_get_bottom(void) { + return stack_limit; +} + +size_t stack_get_length(void) { + return stack_length; +} + void set_next_stack_size(uint32_t size) { next_stack_size = size; } diff --git a/supervisor/shared/stack.h b/supervisor/shared/stack.h index 7096f0b3e..1c75de5f7 100755 --- a/supervisor/shared/stack.h +++ b/supervisor/shared/stack.h @@ -31,10 +31,12 @@ #include "supervisor/memory.h" -extern supervisor_allocation* stack_alloc; - void stack_init(void); void stack_resize(void); +// Actual stack location and size, may be larger than requested. +uint32_t* stack_get_bottom(void); +size_t stack_get_length(void); +// Next/current requested stack size. void set_next_stack_size(uint32_t size); uint32_t get_current_stack_size(void); bool stack_ok(void); -- cgit v1.2.3 From ac91220361e402bbf6ebb741a9b6ea258a05da99 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Fri, 16 Oct 2020 23:08:29 +0200 Subject: Use movable allocation system for Sharp display framebuffer. Hybrid allocation is now part of the infrastructure. Moving memory contents would not be necessary because displayio can recreate them, but does not hurt. --- .../sharpdisplay/SharpMemoryFramebuffer.c | 57 ++++++---------------- .../sharpdisplay/SharpMemoryFramebuffer.h | 1 - 2 files changed, 14 insertions(+), 44 deletions(-) (limited to 'shared-module') diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c index aefb6b18d..4b92bd637 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c @@ -34,32 +34,10 @@ #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" #include "supervisor/memory.h" -#include "supervisor/shared/safe_mode.h" #define SHARPMEM_BIT_WRITECMD_LSB (0x80) #define SHARPMEM_BIT_VCOM_LSB (0x40) -static void *hybrid_alloc(size_t sz) { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, false); - if (allocation) { - memset(allocation->ptr, 0, sz); - return allocation->ptr; - } - if (gc_alloc_possible()) { - return m_malloc(sz, true); - } - reset_into_safe_mode(MEM_MANAGE); - return NULL; // unreached -} - -static inline void hybrid_free(void *ptr_in) { - supervisor_allocation *allocation = allocation_from_ptr(ptr_in); - - if (allocation) { - free_memory(allocation); - } -} - STATIC uint8_t bitrev(uint8_t n) { uint8_t r = 0; for(int i=0;i<8;i++) r |= ((n>>i) & 1)<<(7-i); @@ -102,9 +80,9 @@ void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *s } void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self) { - if (!allocation_from_ptr(self->bufinfo.buf)) { - self->bufinfo.buf = NULL; - } + // Look up the allocation by the old pointer and get the new pointer from it. + supervisor_allocation* alloc = allocation_from_ptr(self->bufinfo.buf); + self->bufinfo.buf = alloc ? alloc->ptr : NULL; } void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo) { @@ -112,7 +90,12 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self); int height = common_hal_sharpdisplay_framebuffer_get_height(self); self->bufinfo.len = row_stride * height + 2; - self->bufinfo.buf = hybrid_alloc(self->bufinfo.len); + supervisor_allocation* alloc = allocate_memory(align32_size(self->bufinfo.len), false, true); + if (alloc == NULL) { + m_malloc_fail(self->bufinfo.len); + } + self->bufinfo.buf = alloc->ptr; + memset(alloc->ptr, 0, self->bufinfo.len); uint8_t *data = self->bufinfo.buf; *data++ = SHARPMEM_BIT_WRITECMD_LSB; @@ -123,7 +106,9 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob } self->full_refresh = true; } - *bufinfo = self->bufinfo; + if (bufinfo) { + *bufinfo = self->bufinfo; + } } void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self) { @@ -137,7 +122,7 @@ void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t * common_hal_reset_pin(self->chip_select.pin); - hybrid_free(self->bufinfo.buf); + free_memory(allocation_from_ptr(self->bufinfo.buf)); memset(self, 0, sizeof(*self)); } @@ -154,19 +139,7 @@ void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_ self->height = height; self->baudrate = baudrate; - int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self); - self->bufinfo.len = row_stride * height + 2; - // re-use a supervisor allocation if possible - self->bufinfo.buf = hybrid_alloc(self->bufinfo.len); - - uint8_t *data = self->bufinfo.buf; - *data++ = SHARPMEM_BIT_WRITECMD_LSB; - - for(int y=0; yheight; y++) { - *data = bitrev(y+1); - data += row_stride; - } - self->full_refresh = true; + common_hal_sharpdisplay_framebuffer_get_bufinfo(self, NULL); } void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask) { @@ -271,7 +244,5 @@ const framebuffer_p_t sharpdisplay_framebuffer_proto = { }; void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *self) { - gc_collect_ptr(self->framebuffer); gc_collect_ptr(self->bus); - gc_collect_ptr(self->bufinfo.buf); } diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h index 8acacc94e..08966a89c 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h @@ -33,7 +33,6 @@ typedef struct { mp_obj_base_t base; - mp_obj_t framebuffer; busio_spi_obj_t* bus; busio_spi_obj_t inline_bus; digitalio_digitalinout_obj_t chip_select; -- cgit v1.2.3 From a4b84cf0e118f06cc3b563866d5c594b94b9b3fb Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 17 Oct 2020 13:49:10 +0200 Subject: Use movable allocation system for RGBMatrix allocations. Hybrid allocation is now part of the infrastructure. Moving memory contents would not be necessary because displayio can recreate them, but does not hurt. --- shared-module/rgbmatrix/RGBMatrix.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'shared-module') diff --git a/shared-module/rgbmatrix/RGBMatrix.c b/shared-module/rgbmatrix/RGBMatrix.c index 1f144aedb..a09767b62 100644 --- a/shared-module/rgbmatrix/RGBMatrix.c +++ b/shared-module/rgbmatrix/RGBMatrix.c @@ -78,10 +78,10 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, // verify that the matrix is big enough mp_get_index(mp_obj_get_type(self->framebuffer), self->bufinfo.len, MP_OBJ_NEW_SMALL_INT(self->bufsize-1), false); } else { - _PM_free(self->bufinfo.buf); - _PM_free(self->protomatter.rgbPins); - _PM_free(self->protomatter.addr); - _PM_free(self->protomatter.screenData); + common_hal_rgbmatrix_free_impl(self->bufinfo.buf); + common_hal_rgbmatrix_free_impl(self->protomatter.rgbPins); + common_hal_rgbmatrix_free_impl(self->protomatter.addr); + common_hal_rgbmatrix_free_impl(self->protomatter.screenData); self->framebuffer = NULL; self->bufinfo.buf = common_hal_rgbmatrix_allocator_impl(self->bufsize); @@ -180,9 +180,6 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) { void rgbmatrix_rgbmatrix_collect_ptrs(rgbmatrix_rgbmatrix_obj_t* self) { gc_collect_ptr(self->framebuffer); - gc_collect_ptr(self->protomatter.rgbPins); - gc_collect_ptr(self->protomatter.addr); - gc_collect_ptr(self->protomatter.screenData); } void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t* self, bool paused) { @@ -217,18 +214,10 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self) { } void *common_hal_rgbmatrix_allocator_impl(size_t sz) { - if (gc_alloc_possible()) { - return m_malloc_maybe(sz + sizeof(void*), true); - } else { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, false); - return allocation ? allocation->ptr : NULL; - } + supervisor_allocation *allocation = allocate_memory(align32_size(sz), false, true); + return allocation ? allocation->ptr : NULL; } void common_hal_rgbmatrix_free_impl(void *ptr_in) { - supervisor_allocation *allocation = allocation_from_ptr(ptr_in); - - if (allocation) { - free_memory(allocation); - } + free_memory(allocation_from_ptr(ptr_in)); } -- cgit v1.2.3 From 7ca36d45a4ffe40c70814d62cb970007b7f40fee Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Fri, 23 Oct 2020 22:35:56 +0200 Subject: Fix align32_size(). It not only caused crashes with requests larger than 64K (can happen with RGBMatrix), but also generated a lot longer code than necessary. --- shared-module/usb_midi/__init__.c | 6 +++--- supervisor/memory.h | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'shared-module') diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index 5afdd1821..3fb3f836c 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -40,9 +40,9 @@ supervisor_allocation* usb_midi_allocation; void usb_midi_init(void) { // TODO(tannewt): Make this dynamic. - uint16_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2); - uint16_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t)); - uint16_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t)); + size_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t*) * 2); + size_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t)); + size_t portout_size = align32_size(sizeof(usb_midi_portout_obj_t)); // For each embedded MIDI Jack in the descriptor we create a Port usb_midi_allocation = allocate_memory(tuple_size + portin_size + portout_size, false, false); diff --git a/supervisor/memory.h b/supervisor/memory.h index 4307e3f21..0f820eac1 100755 --- a/supervisor/memory.h +++ b/supervisor/memory.h @@ -64,11 +64,8 @@ supervisor_allocation* allocate_remaining_memory(void); // supervisor_move_memory(). supervisor_allocation* allocate_memory(uint32_t length, bool high_address, bool movable); -static inline uint16_t align32_size(uint16_t size) { - if (size % 4 != 0) { - return (size & 0xfffc) + 0x4; - } - return size; +static inline size_t align32_size(size_t size) { + return (size + 3) & ~3; } size_t get_allocation_length(supervisor_allocation* allocation); -- cgit v1.2.3