Skip to content

Commit af8cfbe

Browse files
committed
Add knobs for SSD1322 and two fixes.
* Fix terminal clear after first successful code.py run. * Fix transmitting too many bytes for column constraint with single byte bounds.
1 parent d99d3bd commit af8cfbe

File tree

7 files changed

+66
-41
lines changed

7 files changed

+66
-41
lines changed

shared-bindings/displayio/Display.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
//| Most people should not use this class directly. Use a specific display driver instead that will
5252
//| contain the initialization sequence at minimum.
5353
//|
54-
//| .. class:: Display(display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, grayscale=False, pixels_in_byte_share_row=True, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness_command=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False)
54+
//| .. class:: Display(display_bus, init_sequence, *, width, height, colstart=0, rowstart=0, rotation=0, color_depth=16, grayscale=False, pixels_in_byte_share_row=True, bytes_per_cell=1, reverse_pixels_in_byte=False, set_column_command=0x2a, set_row_command=0x2b, write_ram_command=0x2c, set_vertical_scroll=0, backlight_pin=None, brightness_command=None, brightness=1.0, auto_brightness=False, single_byte_bounds=False, data_as_commands=False)
5555
//|
5656
//| Create a Display object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`).
5757
//|
@@ -90,6 +90,8 @@
9090
//| support 18 bit but 16 is easier to transmit. The last bit is extrapolated.)
9191
//| :param bool grayscale: True if the display only shows a single color.
9292
//| :param bool pixels_in_byte_share_row: True when pixels are less than a byte and a byte includes pixels from the same row of the display. When False, pixels share a column.
93+
//| :param int bytes_per_cell: Number of bytes per addressable memory location when color_depth < 8. When greater than one, bytes share a row or column according to pixels_in_byte_share_row.
94+
//| :param bool reverse_pixels_in_byte: Reverses the pixel order within each byte when color_depth < 8. Does not apply across multiple bytes even if there is more than one byte per cell (bytes_per_cell.)
9395
//| :param int set_column_command: Command used to set the start and end columns to update
9496
//| :param int set_row_command: Command used so set the start and end rows to update
9597
//| :param int write_ram_command: Command used to write pixels values into the update region. Ignored if data_as_commands is set.
@@ -102,7 +104,7 @@
102104
//| :param bool data_as_commands: Treat all init and boundary data as SPI commands. Certain displays require this.
103105
//|
104106
STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
105-
enum { ARG_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_auto_brightness, ARG_single_byte_bounds, ARG_data_as_commands };
107+
enum { ARG_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_bytes_per_cell, ARG_reverse_pixels_in_byte, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_auto_brightness, ARG_single_byte_bounds, ARG_data_as_commands };
106108
static const mp_arg_t allowed_args[] = {
107109
{ MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ },
108110
{ MP_QSTR_init_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ },
@@ -114,6 +116,8 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
114116
{ MP_QSTR_color_depth, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} },
115117
{ MP_QSTR_grayscale, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
116118
{ MP_QSTR_pixels_in_byte_share_row, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
119+
{ MP_QSTR_bytes_per_cell, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1} },
120+
{ MP_QSTR_reverse_pixels_in_byte, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
117121
{ MP_QSTR_set_column_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2a} },
118122
{ MP_QSTR_set_row_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2b} },
119123
{ MP_QSTR_write_ram_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2c} },
@@ -163,7 +167,8 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
163167
common_hal_displayio_display_construct(
164168
self,
165169
display_bus, args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation,
166-
args[ARG_color_depth].u_int, args[ARG_grayscale].u_bool, args[ARG_pixels_in_byte_share_row].u_bool,
170+
args[ARG_color_depth].u_int, args[ARG_grayscale].u_bool,
171+
args[ARG_pixels_in_byte_share_row].u_bool, args[ARG_bytes_per_cell].u_bool, args[ARG_reverse_pixels_in_byte].u_bool,
167172
args[ARG_set_column_command].u_int, args[ARG_set_row_command].u_int,
168173
args[ARG_write_ram_command].u_int,
169174
args[ARG_set_vertical_scroll].u_int,
@@ -199,7 +204,10 @@ STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in)
199204
group = MP_OBJ_TO_PTR(native_group(group_in));
200205
}
201206

202-
common_hal_displayio_display_show(self, group);
207+
bool ok = common_hal_displayio_display_show(self, group);
208+
if (!ok) {
209+
mp_raise_ValueError(translate("Group already used"));
210+
}
203211
return mp_const_none;
204212
}
205213
MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_show_obj, displayio_display_obj_show);

shared-bindings/displayio/Display.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ extern const mp_obj_type_t displayio_display_type;
4040

4141
void common_hal_displayio_display_construct(displayio_display_obj_t* self,
4242
mp_obj_t bus, uint16_t width, uint16_t height,
43-
int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row,
43+
int16_t colstart, int16_t rowstart, uint16_t rotation, uint16_t color_depth, bool grayscale,
44+
bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte,
4445
uint8_t set_column_command, uint8_t set_row_command, uint8_t write_ram_command, uint8_t set_vertical_scroll,
4546
uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin, uint16_t brightness_command,
4647
mp_float_t brightness, bool auto_brightness,
4748
bool single_byte_bounds, bool data_as_commands);
4849

4950
int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self);
5051

51-
void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group);
52+
bool common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group);
5253

5354
void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self);
5455

shared-module/displayio/Display.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@
4444

4545
void common_hal_displayio_display_construct(displayio_display_obj_t* self,
4646
mp_obj_t bus, uint16_t width, uint16_t height, int16_t colstart, int16_t rowstart, uint16_t rotation,
47-
uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row,
47+
uint16_t color_depth, bool grayscale, bool pixels_in_byte_share_row, uint8_t bytes_per_cell, bool reverse_pixels_in_byte,
4848
uint8_t set_column_command, uint8_t set_row_command,
4949
uint8_t write_ram_command, uint8_t set_vertical_scroll, uint8_t* init_sequence, uint16_t init_sequence_len,
5050
const mcu_pin_obj_t* backlight_pin, uint16_t brightness_command, mp_float_t brightness, bool auto_brightness,
5151
bool single_byte_bounds, bool data_as_commands) {
5252
self->colorspace.depth = color_depth;
5353
self->colorspace.grayscale = grayscale;
5454
self->colorspace.pixels_in_byte_share_row = pixels_in_byte_share_row;
55+
self->colorspace.bytes_per_cell = bytes_per_cell;
56+
self->colorspace.reverse_pixels_in_byte = reverse_pixels_in_byte;
5557
self->set_column_command = set_column_command;
5658
self->set_row_command = set_row_command;
5759
self->write_ram_command = write_ram_command;
@@ -195,17 +197,25 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
195197
common_hal_displayio_display_show(self, &circuitpython_splash);
196198
}
197199

198-
void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
200+
bool common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
199201
if (root_group == NULL) {
200202
root_group = &circuitpython_splash;
201203
}
202204
if (root_group == self->current_group) {
203-
return;
205+
return true;
206+
}
207+
if (root_group->in_group) {
208+
return false;
209+
}
210+
if (self->current_group != NULL) {
211+
self->current_group->in_group = false;
204212
}
205213
displayio_group_update_transform(root_group, &self->transform);
214+
root_group->in_group = true;
206215
self->current_group = root_group;
207216
self->full_refresh = true;
208217
common_hal_displayio_display_refresh_soon(self);
218+
return true;
209219
}
210220

211221
void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self) {
@@ -299,11 +309,11 @@ void displayio_display_set_region_to_update(displayio_display_obj_t* self, displ
299309
if (self->colorspace.depth < 8) {
300310
uint8_t pixels_per_byte = 8 / self->colorspace.depth;
301311
if (self->colorspace.pixels_in_byte_share_row) {
302-
x1 /= pixels_per_byte;
303-
x2 /= pixels_per_byte;
312+
x1 /= pixels_per_byte * self->colorspace.bytes_per_cell;
313+
x2 /= pixels_per_byte * self->colorspace.bytes_per_cell;
304314
} else {
305-
y1 /= pixels_per_byte;
306-
y2 /= pixels_per_byte;
315+
y1 /= pixels_per_byte * self->colorspace.bytes_per_cell;
316+
y2 /= pixels_per_byte * self->colorspace.bytes_per_cell;
307317
}
308318
}
309319

@@ -318,7 +328,6 @@ void displayio_display_set_region_to_update(displayio_display_obj_t* self, displ
318328
if (self->single_byte_bounds) {
319329
data[data_length++] = x1 + self->colstart;
320330
data[data_length++] = x2 - 1 + self->colstart;
321-
data_length += 2;
322331
} else {
323332
x1 += self->colstart;
324333
x2 += self->colstart - 1;
@@ -413,7 +422,7 @@ bool displayio_display_clip_area(displayio_display_obj_t *self, const displayio_
413422
// Expand the area if we have multiple pixels per byte and we need to byte
414423
// align the bounds.
415424
if (self->colorspace.depth < 8) {
416-
uint8_t pixels_per_byte = 8 / self->colorspace.depth;
425+
uint8_t pixels_per_byte = 8 / self->colorspace.depth * self->colorspace.bytes_per_cell;
417426
if (self->colorspace.pixels_in_byte_share_row) {
418427
if (clipped->x1 % pixels_per_byte != 0) {
419428
clipped->x1 -= clipped->x1 % pixels_per_byte;

shared-module/displayio/Palette.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ typedef struct {
3636
uint8_t depth;
3737
bool grayscale;
3838
bool pixels_in_byte_share_row;
39+
uint8_t bytes_per_cell;
40+
bool reverse_pixels_in_byte;
3941
uint8_t hue;
4042
} _displayio_colorspace_t;
4143

shared-module/displayio/TileGrid.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,11 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const _displayio_c
436436
// asm("bkpt");
437437
// }
438438
}
439-
((uint8_t*)buffer)[offset / pixels_per_byte] |= pixel << ((offset % pixels_per_byte) * colorspace->depth);
439+
uint8_t shift = (offset % pixels_per_byte) * colorspace->depth;
440+
if (colorspace->reverse_pixels_in_byte) {
441+
shift = (pixels_per_byte - 1) * colorspace->depth - shift;
442+
}
443+
((uint8_t*)buffer)[offset / pixels_per_byte] |= pixel << shift;
440444
}
441445
}
442446
}

shared-module/displayio/__init__.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -209,35 +209,35 @@ void reset_displays(void) {
209209
}
210210
}
211211
} else if (displays[i].i2cdisplay_bus.base.type == &displayio_i2cdisplay_type) {
212-
displayio_i2cdisplay_obj_t* i2c = &displays[i].i2cdisplay_bus;
213-
if (((uint32_t) i2c->bus) < ((uint32_t) &displays) ||
214-
((uint32_t) i2c->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
215-
busio_i2c_obj_t* original_i2c = i2c->bus;
216-
#if BOARD_I2C
217-
// We don't need to move original_i2c if it is the board.SPI object because it is
218-
// statically allocated already. (Doing so would also make it impossible to reference in
219-
// a subsequent VM run.)
220-
if (original_i2c == common_hal_board_get_i2c()) {
221-
continue;
222-
}
223-
#endif
224-
memcpy(&i2c->inline_bus, original_i2c, sizeof(busio_i2c_obj_t));
225-
i2c->bus = &i2c->inline_bus;
226-
// Check for other displays that use the same i2c bus and swap them too.
227-
for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
228-
if (displays[i].i2cdisplay_bus.base.type == &displayio_i2cdisplay_type &&
229-
displays[i].i2cdisplay_bus.bus == original_i2c) {
230-
displays[i].i2cdisplay_bus.bus = &i2c->inline_bus;
231-
}
212+
displayio_i2cdisplay_obj_t* i2c = &displays[i].i2cdisplay_bus;
213+
if (((uint32_t) i2c->bus) < ((uint32_t) &displays) ||
214+
((uint32_t) i2c->bus) > ((uint32_t) &displays + CIRCUITPY_DISPLAY_LIMIT)) {
215+
busio_i2c_obj_t* original_i2c = i2c->bus;
216+
#if BOARD_I2C
217+
// We don't need to move original_i2c if it is the board.SPI object because it is
218+
// statically allocated already. (Doing so would also make it impossible to reference in
219+
// a subsequent VM run.)
220+
if (original_i2c == common_hal_board_get_i2c()) {
221+
continue;
222+
}
223+
#endif
224+
memcpy(&i2c->inline_bus, original_i2c, sizeof(busio_i2c_obj_t));
225+
i2c->bus = &i2c->inline_bus;
226+
// Check for other displays that use the same i2c bus and swap them too.
227+
for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
228+
if (displays[i].i2cdisplay_bus.base.type == &displayio_i2cdisplay_type &&
229+
displays[i].i2cdisplay_bus.bus == original_i2c) {
230+
displays[i].i2cdisplay_bus.bus = &i2c->inline_bus;
232231
}
233232
}
234233
}
235-
}
236-
237-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
238-
if (displays[i].display.base.type == NULL) {
234+
} else {
235+
// Not an active display.
239236
continue;
240237
}
238+
239+
// Reset the displayed group. Only the first will get the terminal but
240+
// that's ok.
241241
displayio_display_obj_t* display = &displays[i].display;
242242
display->auto_brightness = true;
243243
common_hal_displayio_display_show(display, &circuitpython_splash);

supervisor/shared/display.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,5 +229,6 @@ displayio_group_t circuitpython_splash = {
229229
.size = 2,
230230
.max_size = 2,
231231
.children = splash_children,
232-
.item_removed = false
232+
.item_removed = false,
233+
.in_group = false
233234
};

0 commit comments

Comments
 (0)