Skip to content

Commit 8d43a2c

Browse files
committed
adding tilepalettemapper
1 parent 6e7baea commit 8d43a2c

File tree

12 files changed

+309
-1
lines changed

12 files changed

+309
-1
lines changed

py/circuitpy_defns.mk

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ endif
396396
ifeq ($(CIRCUITPY_FONTIO),1)
397397
SRC_PATTERNS += fontio/%
398398
endif
399+
ifeq ($(CIRCUITPY_TILEPALETTEMAPPER),1)
400+
SRC_PATTERNS += tilepalettemapper/%
401+
endif
399402
ifeq ($(CIRCUITPY_TIME),1)
400403
SRC_PATTERNS += time/%
401404
endif
@@ -733,6 +736,8 @@ SRC_SHARED_MODULE_ALL = \
733736
synthio/__init__.c \
734737
terminalio/Terminal.c \
735738
terminalio/__init__.c \
739+
tilepalettemapper/__init__.c \
740+
tilepalettemapper/TilePaletteMapper.c \
736741
time/__init__.c \
737742
traceback/__init__.c \
738743
uheap/__init__.c \

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,9 @@ CFLAGS += -DCIRCUITPY_TERMINALIO=$(CIRCUITPY_TERMINALIO)
555555
CIRCUITPY_FONTIO ?= $(call enable-if-all,$(CIRCUITPY_DISPLAYIO) $(CIRCUITPY_TERMINALIO))
556556
CFLAGS += -DCIRCUITPY_FONTIO=$(CIRCUITPY_FONTIO)
557557

558+
CIRCUITPY_TILEPALETTEMAPPER ?= $(CIRCUITPY_FULL_BUILD)
559+
CFLAGS += -DCIRCUITPY_TILEPALETTEMAPPER=$(CIRCUITPY_TILEPALETTEMAPPER)
560+
558561
CIRCUITPY_TIME ?= 1
559562
CFLAGS += -DCIRCUITPY_TIME=$(CIRCUITPY_TIME)
560563

shared-bindings/displayio/TileGrid.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
#include "shared-bindings/displayio/ColorConverter.h"
1818
#include "shared-bindings/displayio/OnDiskBitmap.h"
1919
#include "shared-bindings/displayio/Palette.h"
20+
#ifdef CIRCUITPY_TILEPALETTEMAPPER
21+
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"
22+
#endif
23+
2024

2125
//| class TileGrid:
2226
//| """A grid of tiles sourced out of one bitmap
@@ -323,8 +327,19 @@ MP_DEFINE_CONST_FUN_OBJ_1(displayio_tilegrid_get_pixel_shader_obj, displayio_til
323327

324328
static mp_obj_t displayio_tilegrid_obj_set_pixel_shader(mp_obj_t self_in, mp_obj_t pixel_shader) {
325329
displayio_tilegrid_t *self = native_tilegrid(self_in);
330+
bool valid_type = true;
326331
if (!mp_obj_is_type(pixel_shader, &displayio_palette_type) && !mp_obj_is_type(pixel_shader, &displayio_colorconverter_type)) {
327-
mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader);
332+
valid_type = false;
333+
}
334+
mp_printf(&mp_plat_print, "checking tilepalettemapper\n");
335+
#ifdef CIRCUITPY_TILEPALETTEMAPPER
336+
mp_printf(&mp_plat_print, "tilepalettemapper enabled inside set pixel shader\n");
337+
if (mp_obj_is_type(pixel_shader, &tilepalettemapper_tilepalettemapper_type)) {
338+
valid_type = true;
339+
}
340+
#endif
341+
if (!valid_type) {
342+
mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader);
328343
}
329344

330345
common_hal_displayio_tilegrid_set_pixel_shader(self, pixel_shader);
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
#include <stdint.h>
7+
#include <stdlib.h>
8+
#include "shared/runtime/context_manager_helpers.h"
9+
#include "py/binary.h"
10+
#include "py/objproperty.h"
11+
#include "py/runtime.h"
12+
#include "shared-bindings/util.h"
13+
#include "shared-bindings/displayio/Palette.h"
14+
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"
15+
16+
static mp_obj_t tilepalettemapper_tilepalettemapper_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
17+
enum { ARG_palette, ARG_width, ARG_height };
18+
static const mp_arg_t allowed_args[] = {
19+
{ MP_QSTR_palette, MP_ARG_OBJ | MP_ARG_REQUIRED },
20+
{ MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 1} },
21+
{ MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 1} },
22+
};
23+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
24+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
25+
mp_obj_t palette = args[ARG_palette].u_obj;
26+
if (!mp_obj_is_type(palette, &displayio_palette_type)) {
27+
mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader);
28+
}
29+
tilepalettemapper_tilepalettemapper_t *self = mp_obj_malloc(tilepalettemapper_tilepalettemapper_t, &tilepalettemapper_tilepalettemapper_type);
30+
common_hal_tilepalettemapper_tilepalettemapper_construct(self, palette, args[ARG_width].u_int, args[ARG_height].u_int);
31+
32+
return MP_OBJ_FROM_PTR(self);
33+
}
34+
35+
//| width: int
36+
//| """Width of the tile palette mapper in tiles."""
37+
static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_width(mp_obj_t self_in) {
38+
tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in);
39+
return MP_OBJ_NEW_SMALL_INT(common_hal_tilepalettemapper_tilepalettemapper_get_width(self));
40+
}
41+
MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_width_obj, tilepalettemapper_tilepalettemapper_obj_get_width);
42+
43+
MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_width_obj,
44+
(mp_obj_t)&tilepalettemapper_tilepalettemapper_get_width_obj);
45+
46+
//| height: int
47+
//| """Height of the tile palette mapper in tiles."""
48+
static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_height(mp_obj_t self_in) {
49+
tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in);
50+
return MP_OBJ_NEW_SMALL_INT(common_hal_tilepalettemapper_tilepalettemapper_get_height(self));
51+
}
52+
MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_height_obj, tilepalettemapper_tilepalettemapper_obj_get_height);
53+
54+
MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_height_obj,
55+
(mp_obj_t)&tilepalettemapper_tilepalettemapper_get_height_obj);
56+
57+
58+
//| palette: displayio.Palette
59+
//| """The palette that the mapper uses."""
60+
static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_palette(mp_obj_t self_in) {
61+
tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in);
62+
return common_hal_tilepalettemapper_tilepalettemapper_get_palette(self);
63+
}
64+
MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_palette_obj, tilepalettemapper_tilepalettemapper_obj_get_palette);
65+
66+
MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_palette_obj,
67+
(mp_obj_t)&tilepalettemapper_tilepalettemapper_get_palette_obj);
68+
69+
70+
//| def __getitem__(self, index: Union[Tuple[int, int], int]) -> List[int]:
71+
//| """Returns the mapping for the given index. The index can either be an x,y tuple or an int equal
72+
//| to ``y * width + x``.
73+
//|
74+
//| This allows you to::
75+
//|
76+
//| print(tpm[0])"""
77+
//| ...
78+
//|
79+
//| def __setitem__(self, index: Union[Tuple[int, int], int], value: List[int]) -> None:
80+
//| """Sets the mapping at the given tile index. The index can either be an x,y tuple or an int equal
81+
//| to ``y * width + x``.
82+
//|
83+
//| This allows you to::
84+
//|
85+
//| tpm[0] = [1,0]
86+
//|
87+
//| or::
88+
//|
89+
//| tpm[0,0] = [1,0]"""
90+
//| ...
91+
//|
92+
//|
93+
static mp_obj_t tilepalettemapper_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) {
94+
tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in);
95+
if (mp_obj_is_type(index_obj, &mp_type_slice)) {
96+
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slices not supported"));
97+
} else {
98+
uint16_t x = 0;
99+
uint16_t y = 0;
100+
if (mp_obj_is_small_int(index_obj)) {
101+
mp_int_t i = MP_OBJ_SMALL_INT_VALUE(index_obj);
102+
uint16_t width = common_hal_tilepalettemapper_tilepalettemapper_get_width(self);
103+
x = i % width;
104+
y = i / width;
105+
} else {
106+
mp_obj_t *items;
107+
mp_obj_get_array_fixed_n(index_obj, 2, &items);
108+
x = mp_obj_get_int(items[0]);
109+
y = mp_obj_get_int(items[1]);
110+
}
111+
if (x >= common_hal_tilepalettemapper_tilepalettemapper_get_width(self) ||
112+
y >= common_hal_tilepalettemapper_tilepalettemapper_get_height(self)) {
113+
mp_raise_IndexError(MP_ERROR_TEXT("Tile index out of bounds"));
114+
}
115+
116+
if (value_obj == MP_OBJ_SENTINEL) {
117+
// load
118+
return common_hal_tilepalettemapper_tilepalettemapper_get_mapping(self, x, y);
119+
} else if (value_obj == mp_const_none) {
120+
return MP_OBJ_NULL; // op not supported
121+
} else {
122+
size_t len = 0;
123+
mp_obj_t *items;
124+
mp_obj_list_get(value_obj, &len, &items);
125+
uint32_t palette_len = common_hal_displayio_palette_get_len(self->palette);
126+
127+
mp_arg_validate_int_range(len, 0, palette_len, MP_QSTR_mapping_length);
128+
common_hal_tilepalettemapper_tilepalettemapper_set_mapping(self, x, y, len, items);
129+
}
130+
}
131+
return mp_const_none;
132+
}
133+
134+
135+
static const mp_rom_map_elem_t tilepalettemapper_tilepalettemapper_locals_dict_table[] = {
136+
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_width_obj) },
137+
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_height_obj) },
138+
{ MP_ROM_QSTR(MP_QSTR_palette), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_palette_obj) },
139+
};
140+
static MP_DEFINE_CONST_DICT(tilepalettemapper_tilepalettemapper_locals_dict, tilepalettemapper_tilepalettemapper_locals_dict_table);
141+
142+
MP_DEFINE_CONST_OBJ_TYPE(
143+
tilepalettemapper_tilepalettemapper_type,
144+
MP_QSTR_TilePaletteMapper,
145+
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
146+
make_new, tilepalettemapper_tilepalettemapper_make_new,
147+
locals_dict, &tilepalettemapper_tilepalettemapper_locals_dict,
148+
subscr, tilepalettemapper_subscr,
149+
iter, mp_obj_generic_subscript_getiter
150+
);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// Created by timc on 3/4/25.
3+
//
4+
#include "shared-module/tilepalettemapper/TilePaletteMapper.h"
5+
6+
extern const mp_obj_type_t tilepalettemapper_tilepalettemapper_type;
7+
8+
void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_tilepalettemapper_t *self,
9+
mp_obj_t paltte, uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles);
10+
11+
12+
uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_width(tilepalettemapper_tilepalettemapper_t *self);
13+
uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_height(tilepalettemapper_tilepalettemapper_t *self);
14+
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_palette(tilepalettemapper_tilepalettemapper_t *self);
15+
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y);
16+
void common_hal_tilepalettemapper_tilepalettemapper_set_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y, size_t len, mp_obj_t *items);
17+
18+
uint32_t common_hal_tilepalettemapper_tilepalettemapper_get_color(tilepalettemapper_tilepalettemapper_t *self, uint16_t tile_index, uint32_t palette_index);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks
4+
//
5+
// SPDX-License-Identifier: MIT
6+
#include "py/obj.h"
7+
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"
8+
9+
10+
static const mp_rom_map_elem_t tilepalettemapper_module_globals_table[] = {
11+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tilepalettemapper) },
12+
{ MP_ROM_QSTR(MP_QSTR_TilePaletteMapper), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_type) },
13+
};
14+
//mp_printf(&mp_plat_print, tilepalettemapper_module_globals_table[0])
15+
static MP_DEFINE_CONST_DICT(tilepalettemapper_module_globals, tilepalettemapper_module_globals_table);
16+
17+
const mp_obj_module_t tilepalettemapper_module = {
18+
.base = {&mp_type_module },
19+
.globals = (mp_obj_dict_t *)&tilepalettemapper_module_globals,
20+
};
21+
22+
MP_REGISTER_MODULE(MP_QSTR_tilepalettemapper, tilepalettemapper_module);

shared-bindings/tilepalettemapper/__init__.h

Whitespace-only changes.

shared-module/displayio/TileGrid.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "shared-bindings/displayio/ColorConverter.h"
1212
#include "shared-bindings/displayio/OnDiskBitmap.h"
1313
#include "shared-bindings/displayio/Palette.h"
14+
#ifdef CIRCUITPY_TILEPALETTEMAPPER
15+
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"
16+
#endif
1417

1518
void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap,
1619
uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles,
@@ -485,6 +488,11 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self,
485488
}
486489

487490
output_pixel.opaque = true;
491+
#ifdef CIRCUITPY_TILEPALETTEMAPPER
492+
if (mp_obj_is_type(self->pixel_shader, &tilepalettemapper_tilepalettemapper_type)){
493+
output_pixel.pixel = common_hal_tilepalettemapper_tilepalettemapper_get_color(self->pixel_shader, tile_location, input_pixel.pixel);
494+
}
495+
#endif
488496
if (self->pixel_shader == mp_const_none) {
489497
output_pixel.pixel = input_pixel.pixel;
490498
} else if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
#include <stdlib.h>
7+
#include "py/runtime.h"
8+
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"
9+
#include "shared-bindings/displayio/Palette.h"
10+
11+
void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_tilepalettemapper_t *self,
12+
mp_obj_t palette, uint16_t width, uint16_t height) {
13+
14+
self->palette = palette;
15+
self->width_in_tiles = width;
16+
self->height_in_tiles = height;
17+
int mappings_len = width * height;
18+
mp_printf(&mp_plat_print, "%d", mappings_len);
19+
self->tile_mappings = (uint16_t**)m_malloc(mappings_len * sizeof(uint16_t*));
20+
uint32_t palette_len = common_hal_displayio_palette_get_len(self->palette);
21+
for (int i = 0; i < mappings_len; i++) {
22+
self->tile_mappings[i] = (uint16_t*)m_malloc(palette_len * sizeof(uint16_t));
23+
for (uint16_t j = 0; j < palette_len; j++) {
24+
self->tile_mappings[i][j] = j;
25+
}
26+
}
27+
}
28+
29+
uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_width(tilepalettemapper_tilepalettemapper_t *self) {
30+
return self->width_in_tiles;
31+
}
32+
33+
uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_height(tilepalettemapper_tilepalettemapper_t *self) {
34+
return self->height_in_tiles;
35+
}
36+
37+
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_palette(tilepalettemapper_tilepalettemapper_t *self) {
38+
return self->palette;
39+
}
40+
41+
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y){
42+
mp_obj_list_t *list = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL));
43+
uint32_t palette_len = common_hal_displayio_palette_get_len(self->palette);
44+
int index = x + y * self->width_in_tiles;
45+
for (uint32_t i = 0; i < palette_len; i++) {
46+
mp_obj_list_append(list, mp_obj_new_int(self->tile_mappings[index][i]));
47+
}
48+
return MP_OBJ_FROM_PTR(list);
49+
}
50+
51+
void common_hal_tilepalettemapper_tilepalettemapper_set_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y, size_t len, mp_obj_t *items) {
52+
// size_t len = 0;
53+
// mp_obj_t *items;
54+
// mp_obj_list_get(mapping, &len, &items);
55+
uint32_t palette_len = common_hal_displayio_palette_get_len(self->palette);
56+
for (uint16_t i = 0; i < len; i++) {
57+
int mapping_val = mp_arg_validate_type_int(items[i], MP_QSTR_mapping_value);
58+
mp_arg_validate_int_range(mapping_val, 0, palette_len-1, MP_QSTR_mapping_value);
59+
self->tile_mappings[y * self->width_in_tiles + x][i] = mapping_val;
60+
}
61+
}
62+
63+
uint32_t common_hal_tilepalettemapper_tilepalettemapper_get_color(tilepalettemapper_tilepalettemapper_t *self, uint16_t tile_index, uint32_t palette_index){
64+
uint32_t mapped_index = self->tile_mappings[tile_index][palette_index];
65+
return common_hal_displayio_palette_get_color(self->palette, mapped_index);
66+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
8+
#pragma once
9+
10+
#include <stdbool.h>
11+
#include <stdint.h>
12+
13+
#include "py/obj.h"
14+
15+
typedef struct {
16+
mp_obj_base_t base;
17+
mp_obj_t palette;
18+
uint16_t width_in_tiles;
19+
uint16_t height_in_tiles;
20+
uint16_t **tile_mappings;
21+
} tilepalettemapper_tilepalettemapper_t;

0 commit comments

Comments
 (0)