diff --git a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk index c647039bc8aaf..c17121de67d7c 100755 --- a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk @@ -11,3 +11,4 @@ EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ CIRCUITPY_JPEGIO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index 811336885b86d..9fe7fe80d201f 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -9,3 +9,5 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL064L" LONGINT_IMPL = MPZ + +CIRCUITPY_DISPLAYIO = 0 diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 99f1699fbe89c..f58ba0687aa0b 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -385,6 +385,42 @@ MP_PROPERTY_GETSET(displayio_tilegrid_bitmap_obj, (mp_obj_t)&displayio_tilegrid_get_bitmap_obj, (mp_obj_t)&displayio_tilegrid_set_bitmap_obj); +//| def get_inverted(self, tile_coords: tuple) -> bool: +//| """Returns True if the tile at the given x, y coordinates is inverted.""" +//| +static mp_obj_t displayio_tilegrid_obj_get_inverted(mp_obj_t self_in, mp_obj_t tile_coords) { + displayio_tilegrid_t *self = MP_OBJ_TO_PTR(self_in); + + mp_obj_t *tile_coords_items; + mp_obj_get_array_fixed_n(tile_coords, 2, &tile_coords_items); + uint16_t x = 0; + uint16_t y = 0; + x = mp_arg_validate_int_range(mp_obj_get_int(tile_coords_items[0]), 0, self->width_in_tiles - 1, MP_QSTR_x); + y = mp_arg_validate_int_range(mp_obj_get_int(tile_coords_items[1]), 0, self->height_in_tiles - 1, MP_QSTR_y); + + return mp_obj_new_bool(common_hal_displayio_tilegrid_get_inverted(self, x, y)); +} +MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_get_inverted_obj, displayio_tilegrid_obj_get_inverted); + +//| def set_inverted(self, tile_coords: tuple, inverted: bool) -> None: +//| """Set the tile at the given x, y coordinates to be inverted or not.""" +//| +static mp_obj_t displayio_tilegrid_obj_set_inverted(mp_obj_t self_in, mp_obj_t tile_coords, mp_obj_t inverted_obj) { + displayio_tilegrid_t *self = MP_OBJ_TO_PTR(self_in); + + mp_obj_t *tile_coords_items; + mp_obj_get_array_fixed_n(tile_coords, 2, &tile_coords_items); + uint16_t x = 0; + uint16_t y = 0; + x = mp_arg_validate_int_range(mp_obj_get_int(tile_coords_items[0]), 0, self->width_in_tiles - 1, MP_QSTR_x); + y = mp_arg_validate_int_range(mp_obj_get_int(tile_coords_items[1]), 0, self->height_in_tiles - 1, MP_QSTR_y); + bool inverted = mp_obj_is_true(inverted_obj); + + common_hal_displayio_tilegrid_set_inverted(self, x, y, inverted); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(displayio_tilegrid_set_inverted_obj, displayio_tilegrid_obj_set_inverted); + //| def __getitem__(self, index: Union[Tuple[int, int], int]) -> int: //| """Returns the tile index at the given index. The index can either be an x,y tuple or an int equal //| to ``y * width + x``. @@ -461,6 +497,8 @@ static const mp_rom_map_elem_t displayio_tilegrid_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_flip_y), MP_ROM_PTR(&displayio_tilegrid_flip_y_obj) }, { MP_ROM_QSTR(MP_QSTR_transpose_xy), MP_ROM_PTR(&displayio_tilegrid_transpose_xy_obj) }, { MP_ROM_QSTR(MP_QSTR_contains), MP_ROM_PTR(&displayio_tilegrid_contains_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_inverted), MP_ROM_PTR(&displayio_tilegrid_get_inverted_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_inverted), MP_ROM_PTR(&displayio_tilegrid_set_inverted_obj) }, { MP_ROM_QSTR(MP_QSTR_pixel_shader), MP_ROM_PTR(&displayio_tilegrid_pixel_shader_obj) }, { MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&displayio_tilegrid_bitmap_obj) }, }; diff --git a/shared-bindings/displayio/TileGrid.h b/shared-bindings/displayio/TileGrid.h index 19af39fadeb37..f74e832deb92f 100644 --- a/shared-bindings/displayio/TileGrid.h +++ b/shared-bindings/displayio/TileGrid.h @@ -46,6 +46,9 @@ uint16_t common_hal_displayio_tilegrid_get_tile_height(displayio_tilegrid_t *sel uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y); void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index); +bool common_hal_displayio_tilegrid_get_inverted(displayio_tilegrid_t *self, uint16_t x, uint16_t y); +void common_hal_displayio_tilegrid_set_inverted(displayio_tilegrid_t *self, uint16_t x, uint16_t y, bool inverted); + // Private API for scrolling the TileGrid. void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y); void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint8_t tile_index); diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index 926637c11fbdd..1103b302bb748 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -17,6 +17,7 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_ mp_obj_t pixel_shader, uint16_t width, uint16_t height, uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) { uint32_t total_tiles = width * height; + self->inverts = (bool *)m_malloc(total_tiles); // Sprites will only have one tile so save a little memory by inlining values in the pointer. uint8_t inline_tiles = sizeof(uint8_t *); if (total_tiles <= inline_tiles) { @@ -54,6 +55,7 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_ self->flip_y = false; self->transpose_xy = false; self->absolute_transform = NULL; + displayio_tilegird_clear_inverts(self); } @@ -65,6 +67,12 @@ bool displayio_tilegrid_get_rendered_hidden(displayio_tilegrid_t *self) { return self->rendered_hidden; } +void displayio_tilegird_clear_inverts(displayio_tilegrid_t *self) { + for (uint32_t i = 0; i < self->width_in_tiles * self->height_in_tiles; i++) { + self->inverts[i] = false; + } +} + void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t *self, bool hidden) { self->hidden = hidden; self->rendered_hidden = false; @@ -355,6 +363,17 @@ bool common_hal_displayio_tilegrid_contains(displayio_tilegrid_t *self, uint16_t y >= self->y && y < bottom_edge; } +bool common_hal_displayio_tilegrid_get_inverted(displayio_tilegrid_t *self, uint16_t x, uint16_t y) { + uint16_t tile_location = y * self->width_in_tiles + x; + return self->inverts[tile_location]; +} + +void common_hal_displayio_tilegrid_set_inverted(displayio_tilegrid_t *self, uint16_t x, uint16_t y, bool inverted) { + uint16_t tile_location = y * self->width_in_tiles + x; + self->inverts[tile_location] = inverted; + common_hal_displayio_tilegrid_set_tile(self, x, y, common_hal_displayio_tilegrid_get_tile(self, x, y)); +} + void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y) { self->top_left_x = x; self->top_left_y = y; @@ -488,6 +507,11 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, if (self->pixel_shader == mp_const_none) { output_pixel.pixel = input_pixel.pixel; } else if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { + if (common_hal_displayio_palette_get_len(self->pixel_shader) == 2) { + if (self->inverts[tile_location]) { + input_pixel.pixel = (input_pixel.pixel + 1) % 2; + } + } displayio_palette_get_color(self->pixel_shader, colorspace, &input_pixel, &output_pixel); } else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) { displayio_colorconverter_convert(self->pixel_shader, colorspace, &input_pixel, &output_pixel); diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h index c9c31696bf8f2..5e7723d91c609 100644 --- a/shared-module/displayio/TileGrid.h +++ b/shared-module/displayio/TileGrid.h @@ -31,6 +31,7 @@ typedef struct { uint16_t top_left_x; uint16_t top_left_y; uint8_t *tiles; + bool *inverts; const displayio_buffer_transform_t *absolute_transform; displayio_area_t dirty_area; // Stored as a relative area until the refresh area is fetched. displayio_area_t previous_area; // Stored as an absolute area. @@ -67,3 +68,5 @@ bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self); bool displayio_tilegrid_get_rendered_hidden(displayio_tilegrid_t *self); + +void displayio_tilegird_clear_inverts(displayio_tilegrid_t *self); diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c index e6f1cb23111ff..0c5864bb7353e 100644 --- a/shared-module/terminalio/Terminal.c +++ b/shared-module/terminalio/Terminal.c @@ -8,6 +8,7 @@ #include "shared-module/fontio/BuiltinFont.h" #include "shared-bindings/displayio/TileGrid.h" +#include "shared-module/displayio/TileGrid.h" #include "shared-bindings/terminalio/Terminal.h" #if CIRCUITPY_STATUS_BAR @@ -33,8 +34,10 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, self->status_y = 0; self->first_row = 0; common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0); + displayio_tilegird_clear_inverts(scroll_area); if (self->status_bar) { common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0); + displayio_tilegird_clear_inverts(self->status_bar); } common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 1); diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index f6788af0a8db4..ec6a9a69536e4 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -46,6 +46,7 @@ extern displayio_group_t circuitpython_splash; #if CIRCUITPY_TERMINALIO static uint8_t *tilegrid_tiles = NULL; +static bool *tilegrid_inverts = NULL; static size_t tilegrid_tiles_size = 0; #endif @@ -93,6 +94,21 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { return; } } + if (tilegrid_inverts) { + if (tilegrid_tiles_size != total_tiles) { + port_free(tilegrid_inverts); + tilegrid_inverts = NULL; + tilegrid_tiles_size = 0; + reset_tiles = true; + } + } + if (!tilegrid_inverts) { + tilegrid_inverts = port_malloc(total_tiles, false); + reset_tiles = true; + if (!tilegrid_inverts) { + return; + } + } if (reset_tiles) { // Adjust the display dimensions to account for scale of the outer group. @@ -117,6 +133,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { status_bar->x = width_px - status_bar->pixel_width; status_bar->top_left_y = 0; status_bar->tiles = tilegrid_tiles; + status_bar->inverts = tilegrid_inverts; status_bar->full_change = true; scroll_area->width_in_tiles = width_in_tiles; @@ -131,6 +148,7 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { // may be clipped by the status bar and that's ok. scroll_area->y = height_px - scroll_area->pixel_height; scroll_area->tiles = tilegrid_tiles + width_in_tiles; + scroll_area->inverts = tilegrid_inverts + width_in_tiles; scroll_area->full_change = true; common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, status_bar); diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py index 2219b4e86da50..3dfd25911c29d 100644 --- a/tools/gen_display_resources.py +++ b/tools/gen_display_resources.py @@ -225,6 +225,7 @@ def _load_row(self, y, row): .top_left_x = {0}, .top_left_y = {0}, .tiles = 0, + .inverts = false, .partial_change = false, .full_change = false, .hidden = false, @@ -275,6 +276,7 @@ def _load_row(self, y, row): .tile_width = {1}, .tile_height = {2}, .tiles = NULL, + .inverts = NULL, .partial_change = false, .full_change = false, .hidden = false, @@ -303,6 +305,7 @@ def _load_row(self, y, row): .tile_width = {1}, .tile_height = {2}, .tiles = NULL, + .inverts = NULL, .partial_change = false, .full_change = false, .hidden = false,