Skip to content

Commit 0d16498

Browse files
committed
Add grayscale EInk support
1 parent fc591c8 commit 0d16498

File tree

7 files changed

+48
-16
lines changed

7 files changed

+48
-16
lines changed

shared-bindings/displayio/EPaperDisplay.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,19 @@
4949
//| Most people should not use this class directly. Use a specific display driver instead that will
5050
//| contain the startup and shutdown sequences at minimum."""
5151
//|
52-
//| 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:
52+
//| def __init__(self, display_bus: _DisplayBus,
53+
//| start_sequence: ReadableBuffer, stop_sequence: ReadableBuffer, *,
54+
//| width: int, height: int, ram_width: int, ram_height: int,
55+
//| colstart: int = 0, rowstart: int = 0, rotation: int = 0,
56+
//| set_column_window_command: Optional[int] = None,
57+
//| set_row_window_command: Optional[int] = None, single_byte_bounds: bool = False,
58+
//| write_black_ram_command: int, black_bits_inverted: bool = False,
59+
//| write_color_ram_command: Optional[int] = None,
60+
//| color_bits_inverted: bool = False, highlight_color: int = 0x000000,
61+
//| refresh_display_command: int, refresh_time: float = 40,
62+
//| busy_pin: Optional[microcontroller.Pin] = None, busy_state: bool = True,
63+
//| seconds_per_frame: float = 180, always_toggle_chip_select: bool = False,
64+
//| grayscale: bool = False) -> None:
5365
//| """Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
5466
//|
5567
//| The ``start_sequence`` and ``stop_sequence`` are bitpacked to minimize the ram impact. Every
@@ -84,11 +96,18 @@
8496
//| :param microcontroller.Pin busy_pin: Pin used to signify the display is busy
8597
//| :param bool busy_state: State of the busy pin when the display is busy
8698
//| :param float seconds_per_frame: Minimum number of seconds between screen refreshes
87-
//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte"""
99+
//| :param bool always_toggle_chip_select: When True, chip select is toggled every byte
100+
//| :param bool grayscale: When true, the color ram is the low bit of 2-bit grayscale"""
88101
//| ...
89102
//|
90103
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) {
91-
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 };
104+
enum { ARG_display_bus, ARG_start_sequence, ARG_stop_sequence, ARG_width, ARG_height,
105+
ARG_ram_width, ARG_ram_height, ARG_colstart, ARG_rowstart, ARG_rotation,
106+
ARG_set_column_window_command, ARG_set_row_window_command, ARG_set_current_column_command,
107+
ARG_set_current_row_command, ARG_write_black_ram_command, ARG_black_bits_inverted,
108+
ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color,
109+
ARG_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state,
110+
ARG_seconds_per_frame, ARG_always_toggle_chip_select, ARG_grayscale };
92111
static const mp_arg_t allowed_args[] = {
93112
{ MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
94113
{ 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
115134
{ MP_QSTR_busy_state, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
116135
{ MP_QSTR_seconds_per_frame, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(180)} },
117136
{ MP_QSTR_always_toggle_chip_select, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
137+
{ MP_QSTR_grayscale, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
118138
};
119139
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
120140
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
151171
self,
152172
display_bus,
153173
start_bufinfo.buf, start_bufinfo.len, stop_bufinfo.buf, stop_bufinfo.len,
154-
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,
174+
args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_ram_width].u_int, args[ARG_ram_height].u_int,
175+
args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation,
155176
args[ARG_set_column_window_command].u_int, args[ARG_set_row_window_command].u_int,
156177
args[ARG_set_current_column_command].u_int, args[ARG_set_current_row_command].u_int,
157-
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,
158-
busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame, args[ARG_always_toggle_chip_select].u_bool
178+
args[ARG_write_black_ram_command].u_int, args[ARG_black_bits_inverted].u_bool, write_color_ram_command,
179+
args[ARG_color_bits_inverted].u_bool, highlight_color, args[ARG_refresh_display_command].u_int, refresh_time,
180+
busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame,
181+
args[ARG_always_toggle_chip_select].u_bool, args[ARG_grayscale].u_bool
159182
);
160183

161184
return self;

shared-bindings/displayio/EPaperDisplay.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t*
4444
uint16_t set_column_window_command, uint16_t set_row_window_command,
4545
uint16_t set_current_column_command, uint16_t set_current_row_command,
4646
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,
47-
const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool always_toggle_chip_select);
47+
const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool always_toggle_chip_select, bool grayscale);
4848

4949
bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t* self);
5050

shared-module/displayio/ColorConverter.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d
165165
g8 = MIN(255,g8 + (randg&0x03));
166166
} else {
167167
int bitmask = 0xFF >> colorspace->depth;
168-
b8 = MIN(255,b8 + (randb&bitmask));
169-
r8 = MIN(255,r8 + (randr&bitmask));
170-
g8 = MIN(255,g8 + (randg&bitmask));
168+
b8 = MIN(255,b8 + (randb & bitmask));
169+
r8 = MIN(255,r8 + (randr & bitmask));
170+
g8 = MIN(255,g8 + (randg & bitmask));
171171
}
172172
pixel = r8 << 16 | g8 << 8 | b8;
173173
}
@@ -196,7 +196,8 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d
196196
return;
197197
} else if (colorspace->grayscale && colorspace->depth <= 8) {
198198
uint8_t luma = displayio_colorconverter_compute_luma(pixel);
199-
output_color->pixel = luma >> (8 - colorspace->depth);
199+
size_t bitmask = (1 << colorspace->depth) - 1;
200+
output_color->pixel = (luma >> colorspace->grayscale_bit) & bitmask;
200201
output_color->opaque = true;
201202
return;
202203
}

shared-module/displayio/EPaperDisplay.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t*
4949
uint16_t set_column_window_command, uint16_t set_row_window_command,
5050
uint16_t set_current_column_command, uint16_t set_current_row_command,
5151
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,
52-
const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select) {
52+
const mcu_pin_obj_t* busy_pin, bool busy_state, mp_float_t seconds_per_frame, bool chip_select, bool grayscale) {
5353
if (highlight_color != 0x000000) {
5454
self->core.colorspace.tricolor = true;
5555
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*
7272
self->refreshing = false;
7373
self->milliseconds_per_frame = seconds_per_frame * 1000;
7474
self->chip_select = chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED;
75+
self->grayscale = grayscale;
7576

7677
self->start_sequence = start_sequence;
7778
self->start_sequence_len = start_sequence_len;
@@ -230,17 +231,16 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c
230231
uint32_t mask[mask_length];
231232

232233
uint8_t passes = 1;
233-
if (self->core.colorspace.tricolor) {
234+
if (self->core.colorspace.tricolor || self->grayscale) {
234235
passes = 2;
235236
}
236237
for (uint8_t pass = 0; pass < passes; pass++) {
237238
uint16_t remaining_rows = displayio_area_height(&clipped);
238239

239-
// added false parameter at end for SH1107_addressing quirk
240240
if (self->set_row_window_command != NO_COMMAND) {
241241
displayio_display_core_set_region_to_update(&self->core, self->set_column_window_command,
242242
self->set_row_window_command, self->set_current_column_command, self->set_current_row_command,
243-
false, self->chip_select, &clipped, false);
243+
false, self->chip_select, &clipped, false /* SH1107_addressing */);
244244
}
245245

246246
uint8_t write_command = self->write_black_ram_command;
@@ -270,8 +270,13 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c
270270
memset(buffer, 0, buffer_size * sizeof(buffer[0]));
271271

272272
self->core.colorspace.grayscale = true;
273+
self->core.colorspace.grayscale_bit = 7;
273274
if (pass == 1) {
274-
self->core.colorspace.grayscale = false;
275+
if (self->grayscale) { // 4-color grayscale
276+
self->core.colorspace.grayscale_bit = 6;
277+
} else { // Tri-color
278+
self->core.colorspace.grayscale = false;
279+
}
275280
}
276281
displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer);
277282

shared-module/displayio/EPaperDisplay.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ typedef struct {
5555
bool black_bits_inverted;
5656
bool color_bits_inverted;
5757
bool refreshing;
58+
bool grayscale;
5859
display_chip_select_behavior_t chip_select;
5960
} displayio_epaperdisplay_obj_t;
6061

shared-module/displayio/Palette.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef struct {
3737
uint8_t bytes_per_cell;
3838
uint8_t tricolor_hue;
3939
uint8_t tricolor_luma;
40+
uint8_t grayscale_bit; // The lowest grayscale bit. Normally 8 - depth.
4041
bool grayscale;
4142
bool tricolor;
4243
bool pixels_in_byte_share_row;

shared-module/displayio/display_core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void displayio_display_core_construct(displayio_display_core_t* self,
4848
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) {
4949
self->colorspace.depth = color_depth;
5050
self->colorspace.grayscale = grayscale;
51+
self->colorspace.grayscale_bit = 8 - color_depth;
5152
self->colorspace.pixels_in_byte_share_row = pixels_in_byte_share_row;
5253
self->colorspace.bytes_per_cell = bytes_per_cell;
5354
self->colorspace.reverse_pixels_in_byte = reverse_pixels_in_byte;

0 commit comments

Comments
 (0)