diff --git a/py/misc.h b/py/misc.h index cb7192a56f..acb0d50cec 100644 --- a/py/misc.h +++ b/py/misc.h @@ -55,6 +55,13 @@ typedef unsigned int uint; // Static assertion macro #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) +// Explicit fallthrough delcarations for case statements +#ifdef __GNUC__ +#define FALLTHROUGH __attribute__((fallthrough)) +#else +#define FALLTHROUGH ((void)0) /* FALLTHROUGH */ +#endif + /** memory allocation ******************************************/ // TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element) diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c index d102d7f9d1..ce1af77839 100644 --- a/shared-bindings/displayio/ColorConverter.c +++ b/shared-bindings/displayio/ColorConverter.c @@ -30,6 +30,7 @@ #include "lib/utils/context_manager_helpers.h" #include "py/binary.h" +#include "py/enum.h" #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" @@ -49,10 +50,11 @@ // TODO(tannewt): Add support for other color formats. //| STATIC mp_obj_t displayio_colorconverter_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_dither}; + enum { ARG_dither, ARG_input_colorspace }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_dither, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} } + { MP_QSTR_dither, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_input_colorspace, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = (void *)&displayio_colorspace_RGB888_obj} }, }; 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); @@ -60,7 +62,7 @@ STATIC mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, siz displayio_colorconverter_t *self = m_new_obj(displayio_colorconverter_t); self->base.type = &displayio_colorconverter_type; - common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool); + common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool, (displayio_colorspace_t)cp_enum_value(&displayio_colorspace_type, args[ARG_input_colorspace].u_obj)); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/displayio/ColorConverter.h b/shared-bindings/displayio/ColorConverter.h index d5a5d05243..018db92c96 100644 --- a/shared-bindings/displayio/ColorConverter.h +++ b/shared-bindings/displayio/ColorConverter.h @@ -27,13 +27,14 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_COLORCONVERTER_H #define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_COLORCONVERTER_H +#include "shared-bindings/displayio/__init__.h" #include "shared-module/displayio/ColorConverter.h" #include "shared-module/displayio/Palette.h" extern const mp_obj_type_t displayio_colorconverter_type; -void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither); +void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither, displayio_colorspace_t input_colorspace); void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *colorconverter, const _displayio_colorspace_t *colorspace, uint32_t input_color, uint32_t *output_color); void common_hal_displayio_colorconverter_set_dither(displayio_colorconverter_t *self, bool dither); diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c index bca4289b0e..eaa085031f 100644 --- a/shared-bindings/displayio/__init__.c +++ b/shared-bindings/displayio/__init__.c @@ -26,6 +26,7 @@ #include +#include "py/enum.h" #include "py/obj.h" #include "py/runtime.h" @@ -49,7 +50,6 @@ //| including synchronizing with refresh rates and partial updating.""" //| - //| def release_displays() -> None: //| """Releases any actively used displays so their busses and pins can be used again. This will also //| release the builtin display on boards that have one. You will need to reinitialize it yourself @@ -65,10 +65,48 @@ STATIC mp_obj_t displayio_release_displays(void) { } MP_DEFINE_CONST_FUN_OBJ_0(displayio_release_displays_obj, displayio_release_displays); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB888, DISPLAYIO_COLORSPACE_RGB888); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565, DISPLAYIO_COLORSPACE_RGB565); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB565_SWAPPED); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555, DISPLAYIO_COLORSPACE_RGB555); +MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED); + +//| class Colorspace: +//| """The colorspace for a ColorConverter to operate in""" +//| +//| RGB888: object +//| """The standard 24-bit colorspace""" +//| +//| RGB565: object +//| """The standard 16-bit colorspace""" +//| +//| RGB565_SWAPPED: object +//| """The standard 16-bit colorspace, with low and high bytes swapped""" +//| +//| RGB555: object +//| """The standard 15-bit colorspace""" +//| +//| RGB555_SWAPPED: object +//| """The standard 15-bit colorspace, with low and high bytes swapped""" +//| +MAKE_ENUM_MAP(displayio_colorspace) { + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB888), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565_SWAPPED), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555), + MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555_SWAPPED), +}; +STATIC MP_DEFINE_CONST_DICT(displayio_colorspace_locals_dict, displayio_colorspace_locals_table); + +MAKE_PRINTER(displayio, displayio_colorspace); +MAKE_ENUM_TYPE(displayio, ColorSpace, displayio_colorspace); + + STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_displayio) }, { MP_ROM_QSTR(MP_QSTR_Bitmap), MP_ROM_PTR(&displayio_bitmap_type) }, { MP_ROM_QSTR(MP_QSTR_ColorConverter), MP_ROM_PTR(&displayio_colorconverter_type) }, + { MP_ROM_QSTR(MP_QSTR_Colorspace), MP_ROM_PTR(&displayio_colorspace_type) }, { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&displayio_display_type) }, { MP_ROM_QSTR(MP_QSTR_EPaperDisplay), MP_ROM_PTR(&displayio_epaperdisplay_type) }, { MP_ROM_QSTR(MP_QSTR_Group), MP_ROM_PTR(&displayio_group_type) }, diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h index 4fc666c598..31af2ff2ba 100644 --- a/shared-bindings/displayio/__init__.h +++ b/shared-bindings/displayio/__init__.h @@ -27,6 +27,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H #define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H +#include "py/enum.h" #include "py/obj.h" typedef enum { @@ -39,6 +40,14 @@ typedef enum { CHIP_SELECT_TOGGLE_EVERY_BYTE } display_chip_select_behavior_t; +typedef enum { + DISPLAYIO_COLORSPACE_RGB888, + DISPLAYIO_COLORSPACE_RGB565, + DISPLAYIO_COLORSPACE_RGB555, + DISPLAYIO_COLORSPACE_RGB565_SWAPPED, + DISPLAYIO_COLORSPACE_RGB555_SWAPPED, +} displayio_colorspace_t; + 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); @@ -48,4 +57,7 @@ typedef void (*display_bus_end_transaction)(mp_obj_t bus); void common_hal_displayio_release_displays(void); +extern const mp_obj_type_t displayio_colorspace_type; +extern const cp_enum_obj_t displayio_colorspace_RGB888_obj; + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index be9e9dc1a5..47cb903f3f 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -41,9 +41,10 @@ uint32_t displayio_colorconverter_dither_noise_2(uint32_t x, uint32_t y) { return displayio_colorconverter_dither_noise_1(x + y * 0xFFFF); } -void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither) { +void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither, displayio_colorspace_t input_colorspace) { self->dither = dither; self->transparent_color = NO_TRANSPARENT_COLOR; + self->input_colorspace = input_colorspace; } uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888) { @@ -152,6 +153,33 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d return; } + switch (self->input_colorspace) { + case DISPLAYIO_COLORSPACE_RGB565_SWAPPED: + pixel = __builtin_bswap16(pixel); + FALLTHROUGH; + case DISPLAYIO_COLORSPACE_RGB565: { + uint32_t r8 = (pixel >> 11) << 3; + uint32_t g8 = ((pixel >> 5) << 2) & 0xff; + uint32_t b8 = (pixel << 3) & 0xff; + pixel = (r8 << 16) | (g8 << 8) | b8; + } + break; + + case DISPLAYIO_COLORSPACE_RGB555_SWAPPED: + pixel = __builtin_bswap16(pixel); + FALLTHROUGH; + case DISPLAYIO_COLORSPACE_RGB555: { + uint32_t r8 = (pixel >> 10) << 3; + uint32_t g8 = ((pixel >> 5) << 3) & 0xff; + uint32_t b8 = (pixel << 3) & 0xff; + pixel = (r8 << 16) | (g8 << 8) | b8; + } + break; + + case DISPLAYIO_COLORSPACE_RGB888: + break; + } + if (self->dither) { uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y)); uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x + 33,input_pixel->tile_y)); diff --git a/shared-module/displayio/ColorConverter.h b/shared-module/displayio/ColorConverter.h index ebe4b27194..55f86982dc 100644 --- a/shared-module/displayio/ColorConverter.h +++ b/shared-module/displayio/ColorConverter.h @@ -36,6 +36,7 @@ typedef struct { mp_obj_base_t base; bool dither; + uint8_t input_colorspace; uint32_t transparent_color; } displayio_colorconverter_t;