displayio: Add RGB555/565/_SWAPPED format support

This is helpful when displaying frames from an OV7670 camera, which
uses the RGB565_SWAPPED format internally.
This commit is contained in:
Jeff Epler 2021-04-19 10:23:47 -05:00
parent fc4538f845
commit 76d68f21ac
7 changed files with 95 additions and 6 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -26,6 +26,7 @@
#include <stdint.h>
#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) },

View File

@ -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

View File

@ -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));

View File

@ -36,6 +36,7 @@
typedef struct {
mp_obj_base_t base;
bool dither;
uint8_t input_colorspace;
uint32_t transparent_color;
} displayio_colorconverter_t;