diff options
Diffstat (limited to 'quantum/painter')
-rw-r--r-- | quantum/painter/lvgl/qp_lvgl.c | 11 | ||||
-rw-r--r-- | quantum/painter/lvgl/qp_lvgl.h | 4 | ||||
-rw-r--r-- | quantum/painter/qff.c | 8 | ||||
-rw-r--r-- | quantum/painter/qff.h | 2 | ||||
-rw-r--r-- | quantum/painter/qgf.c | 39 | ||||
-rw-r--r-- | quantum/painter/qgf.h | 6 | ||||
-rw-r--r-- | quantum/painter/qp.c | 123 | ||||
-rw-r--r-- | quantum/painter/qp.h | 41 | ||||
-rw-r--r-- | quantum/painter/qp_draw_ellipse.c | 12 | ||||
-rw-r--r-- | quantum/painter/qp_draw_image.c | 9 | ||||
-rw-r--r-- | quantum/painter/qp_draw_text.c | 3 | ||||
-rw-r--r-- | quantum/painter/qp_internal.c | 1 | ||||
-rw-r--r-- | quantum/painter/qp_internal_formats.h | 4 | ||||
-rw-r--r-- | quantum/painter/rules.mk | 86 |
14 files changed, 267 insertions, 82 deletions
diff --git a/quantum/painter/lvgl/qp_lvgl.c b/quantum/painter/lvgl/qp_lvgl.c index 280aeaf91f..877b2652c6 100644 --- a/quantum/painter/lvgl/qp_lvgl.c +++ b/quantum/painter/lvgl/qp_lvgl.c @@ -81,8 +81,8 @@ bool qp_lvgl_attach(painter_device_t device) { lvgl_state_t *lv_task_handler_state = &lvgl_states[1]; lv_task_handler_state->fnc_id = 1; - lv_task_handler_state->delay_ms = 5; - lv_task_handler_state->defer_token = defer_exec_advanced(lvgl_executors, 2, 5, tick_task_callback, lv_task_handler_state); + lv_task_handler_state->delay_ms = QP_LVGL_TASK_PERIOD; + lv_task_handler_state->defer_token = defer_exec_advanced(lvgl_executors, 2, QP_LVGL_TASK_PERIOD, tick_task_callback, lv_task_handler_state); if (lv_task_handler_state->defer_token == INVALID_DEFERRED_TOKEN) { qp_dprintf("qp_lvgl_attach: fail (could not set up qp_lvgl executor)\n"); @@ -96,13 +96,14 @@ bool qp_lvgl_attach(painter_device_t device) { // Set up lvgl display buffer static lv_disp_draw_buf_t draw_buf; // Allocate a buffer for 1/10 screen size - const size_t count_required = driver->panel_width * driver->panel_height / 10; - color_buffer = color_buffer ? realloc(color_buffer, sizeof(lv_color_t) * count_required) : malloc(sizeof(lv_color_t) * count_required); - if (!color_buffer) { + const size_t count_required = driver->panel_width * driver->panel_height / 10; + void * new_color_buffer = realloc(color_buffer, sizeof(lv_color_t) * count_required); + if (!new_color_buffer) { qp_dprintf("qp_lvgl_attach: fail (could not set up memory buffer)\n"); qp_lvgl_detach(); return false; } + color_buffer = new_color_buffer; memset(color_buffer, 0, sizeof(lv_color_t) * count_required); // Initialize the display buffer. lv_disp_draw_buf_init(&draw_buf, color_buffer, NULL, count_required); diff --git a/quantum/painter/lvgl/qp_lvgl.h b/quantum/painter/lvgl/qp_lvgl.h index d9ad5e8df1..87ba3ac0a5 100644 --- a/quantum/painter/lvgl/qp_lvgl.h +++ b/quantum/painter/lvgl/qp_lvgl.h @@ -7,6 +7,10 @@ #include "qp.h" #include "lvgl.h" +#ifndef QP_LVGL_TASK_PERIOD +# define QP_LVGL_TASK_PERIOD 5 +#endif + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantum Painter - LVGL External API diff --git a/quantum/painter/qff.c b/quantum/painter/qff.c index cd6af788f9..8590f5b400 100644 --- a/quantum/painter/qff.c +++ b/quantum/painter/qff.c @@ -10,7 +10,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // QFF API -bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, painter_compression_t *compression_scheme, uint32_t *total_bytes) { +bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, bool *is_panel_native, painter_compression_t *compression_scheme, uint32_t *total_bytes) { // Seek to the start qp_stream_setpos(stream, 0); @@ -49,7 +49,7 @@ bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *h *num_unicode_glyphs = font_descriptor.num_unicode_glyphs; } if (bpp || has_palette) { - if (!qgf_parse_format(font_descriptor.format, bpp, has_palette)) { + if (!qgf_parse_format(font_descriptor.format, bpp, has_palette, is_panel_native)) { return false; } } @@ -102,7 +102,7 @@ bool qff_validate_stream(qp_stream_t *stream) { bool has_ascii_table; uint16_t num_unicode_glyphs; - if (!qff_read_font_descriptor(stream, NULL, &has_ascii_table, &num_unicode_glyphs, NULL, NULL, NULL, NULL)) { + if (!qff_read_font_descriptor(stream, NULL, &has_ascii_table, &num_unicode_glyphs, NULL, NULL, NULL, NULL, NULL)) { return false; } @@ -127,7 +127,7 @@ uint32_t qff_get_total_size(qp_stream_t *stream) { // Read the font descriptor, grabbing the size uint32_t total_size; - if (!qff_read_font_descriptor(stream, NULL, NULL, NULL, NULL, NULL, NULL, &total_size)) { + if (!qff_read_font_descriptor(stream, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &total_size)) { return false; } diff --git a/quantum/painter/qff.h b/quantum/painter/qff.h index d1d629582f..c3b831da17 100644 --- a/quantum/painter/qff.h +++ b/quantum/painter/qff.h @@ -85,4 +85,4 @@ typedef struct QP_PACKED qff_unicode_glyph_table_v1_t { bool qff_validate_stream(qp_stream_t *stream); uint32_t qff_get_total_size(qp_stream_t *stream); -bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, painter_compression_t *compression_scheme, uint32_t *total_bytes); +bool qff_read_font_descriptor(qp_stream_t *stream, uint8_t *line_height, bool *has_ascii_table, uint16_t *num_unicode_glyphs, uint8_t *bpp, bool *has_palette, bool *is_panel_native, painter_compression_t *compression_scheme, uint32_t *total_bytes); diff --git a/quantum/painter/qgf.c b/quantum/painter/qgf.c index 6a4af07001..bc2df94933 100644 --- a/quantum/painter/qgf.c +++ b/quantum/painter/qgf.c @@ -24,22 +24,23 @@ bool qgf_validate_block_header(qgf_block_header_v1_t *desc, uint8_t expected_typ return true; } -bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette) { +bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette, bool *is_panel_native) { // clang-format off - static const struct QP_PACKED { + static const struct QP_PACKED { uint8_t bpp; bool has_palette; + bool is_panel_native; } formats[] = { - [GRAYSCALE_1BPP] = {.bpp = 1, .has_palette = false}, - [GRAYSCALE_2BPP] = {.bpp = 2, .has_palette = false}, - [GRAYSCALE_4BPP] = {.bpp = 4, .has_palette = false}, - [GRAYSCALE_8BPP] = {.bpp = 8, .has_palette = false}, - [PALETTE_1BPP] = {.bpp = 1, .has_palette = true}, - [PALETTE_2BPP] = {.bpp = 2, .has_palette = true}, - [PALETTE_4BPP] = {.bpp = 4, .has_palette = true}, - [PALETTE_8BPP] = {.bpp = 8, .has_palette = true}, - [RGB565_16BPP] = {.bpp = 16, .has_palette = false}, - [RGB888_24BPP] = {.bpp = 24, .has_palette = false}, + [GRAYSCALE_1BPP] = {.bpp = 1, .has_palette = false, .is_panel_native = false}, + [GRAYSCALE_2BPP] = {.bpp = 2, .has_palette = false, .is_panel_native = false}, + [GRAYSCALE_4BPP] = {.bpp = 4, .has_palette = false, .is_panel_native = false}, + [GRAYSCALE_8BPP] = {.bpp = 8, .has_palette = false, .is_panel_native = false}, + [PALETTE_1BPP] = {.bpp = 1, .has_palette = true, .is_panel_native = false}, + [PALETTE_2BPP] = {.bpp = 2, .has_palette = true, .is_panel_native = false}, + [PALETTE_4BPP] = {.bpp = 4, .has_palette = true, .is_panel_native = false}, + [PALETTE_8BPP] = {.bpp = 8, .has_palette = true, .is_panel_native = false}, + [RGB565_16BPP] = {.bpp = 16, .has_palette = false, .is_panel_native = true}, + [RGB888_24BPP] = {.bpp = 24, .has_palette = false, .is_panel_native = true}, }; // clang-format on @@ -56,13 +57,16 @@ bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette) if (has_palette) { *has_palette = formats[format].has_palette; } + if (is_panel_native) { + *is_panel_native = formats[format].is_panel_native; + } return true; } -bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay) { +bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay) { // Decode the format - qgf_parse_format(frame_descriptor->format, bpp, has_palette); + qgf_parse_format(frame_descriptor->format, bpp, has_palette, is_panel_native); // Copy out the required info if (is_delta) { @@ -173,7 +177,7 @@ void qgf_seek_to_frame_descriptor(qp_stream_t *stream, uint16_t frame_number) { qp_stream_setpos(stream, offset); } -bool qgf_validate_frame_descriptor(qp_stream_t *stream, uint16_t frame_number, uint8_t *bpp, bool *has_palette, bool *is_delta) { +bool qgf_validate_frame_descriptor(qp_stream_t *stream, uint16_t frame_number, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta) { // Seek to the correct location qgf_seek_to_frame_descriptor(stream, frame_number); @@ -189,7 +193,7 @@ bool qgf_validate_frame_descriptor(qp_stream_t *stream, uint16_t frame_number, u return false; } - return qgf_parse_frame_descriptor(&frame_descriptor, bpp, has_palette, is_delta, NULL, NULL); + return qgf_parse_frame_descriptor(&frame_descriptor, bpp, has_palette, is_panel_native, is_delta, NULL, NULL); } bool qgf_validate_palette_descriptor(qp_stream_t *stream, uint16_t frame_number, uint8_t bpp) { @@ -253,8 +257,9 @@ bool qgf_validate_stream(qp_stream_t *stream) { // Validate the frame descriptor block uint8_t bpp; bool has_palette; + bool is_panel_native; bool has_delta; - if (!qgf_validate_frame_descriptor(stream, i, &bpp, &has_palette, &has_delta)) { + if (!qgf_validate_frame_descriptor(stream, i, &bpp, &has_palette, &is_panel_native, &has_delta)) { return false; } diff --git a/quantum/painter/qgf.h b/quantum/painter/qgf.h index 54585edd04..33a37709e6 100644 --- a/quantum/painter/qgf.h +++ b/quantum/painter/qgf.h @@ -65,7 +65,7 @@ _Static_assert(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), typedef struct QP_PACKED qgf_frame_v1_t { qgf_block_header_v1_t header; // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = 6 } - qp_image_format_t format : 8; // Frame format, see qp.h. + qp_image_format_t format : 8; // Frame format, see qp_internal_formats.h. uint8_t flags; // Frame flags, see below. painter_compression_t compression_scheme : 8; // Compression scheme, see qp.h. uint8_t transparency_index; // palette index used for transparent pixels (not yet implemented) @@ -131,6 +131,6 @@ uint32_t qgf_get_total_size(qp_stream_t *stream); bool qgf_validate_stream(qp_stream_t *stream); bool qgf_validate_block_header(qgf_block_header_v1_t *desc, uint8_t expected_typeid, int32_t expected_length); bool qgf_read_graphics_descriptor(qp_stream_t *stream, uint16_t *image_width, uint16_t *image_height, uint16_t *frame_count, uint32_t *total_bytes); -bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette); +bool qgf_parse_format(qp_image_format_t format, uint8_t *bpp, bool *has_palette, bool *is_panel_native); void qgf_seek_to_frame_descriptor(qp_stream_t *stream, uint16_t frame_number); -bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay); +bool qgf_parse_frame_descriptor(qgf_frame_v1_t *frame_descriptor, uint8_t *bpp, bool *has_palette, bool *is_panel_native, bool *is_delta, painter_compression_t *compression_scheme, uint16_t *delay); diff --git a/quantum/painter/qp.c b/quantum/painter/qp.c index f27bb7892a..3759866509 100644 --- a/quantum/painter/qp.c +++ b/quantum/painter/qp.c @@ -12,11 +12,11 @@ // Internal driver validation static bool validate_driver_vtable(painter_driver_t *driver) { - return (driver->driver_vtable && driver->driver_vtable->init && driver->driver_vtable->power && driver->driver_vtable->clear && driver->driver_vtable->viewport && driver->driver_vtable->pixdata && driver->driver_vtable->palette_convert && driver->driver_vtable->append_pixels && driver->driver_vtable->append_pixdata) ? true : false; + return (driver && driver->driver_vtable && driver->driver_vtable->init && driver->driver_vtable->power && driver->driver_vtable->clear && driver->driver_vtable->viewport && driver->driver_vtable->pixdata && driver->driver_vtable->palette_convert && driver->driver_vtable->append_pixels && driver->driver_vtable->append_pixdata) ? true : false; } static bool validate_comms_vtable(painter_driver_t *driver) { - return (driver->comms_vtable && driver->comms_vtable->comms_init && driver->comms_vtable->comms_start && driver->comms_vtable->comms_stop && driver->comms_vtable->comms_send) ? true : false; + return (driver && driver->comms_vtable && driver->comms_vtable->comms_init && driver->comms_vtable->comms_start && driver->comms_vtable->comms_stop && driver->comms_vtable->comms_send) ? true : false; } static bool validate_driver_integrity(painter_driver_t *driver) { @@ -131,49 +131,126 @@ bool qp_flush(painter_device_t device) { } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter External API: qp_get_geometry +// Quantum Painter External API: qp_get_* -void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) { - qp_dprintf("qp_get_geometry: entry\n"); +uint16_t qp_get_width(painter_device_t device) { + qp_dprintf("qp_get_width: entry\n"); painter_driver_t *driver = (painter_driver_t *)device; - if (!driver) { - qp_dprintf("qp_get_geometry: fail (pointer to NULL)\n"); - return; + if (!driver || !driver->validate_ok) { + qp_dprintf("qp_get_width: fail (invalid driver)\n"); + return 0; + } + + uint16_t width; + switch (driver->rotation) { + default: + case QP_ROTATION_0: + case QP_ROTATION_180: + width = driver->panel_width; + break; + case QP_ROTATION_90: + case QP_ROTATION_270: + width = driver->panel_height; + break; } + qp_dprintf("qp_get_width: ok\n"); + return width; +} + +uint16_t qp_get_height(painter_device_t device) { + qp_dprintf("qp_get_height: entry\n"); + painter_driver_t *driver = (painter_driver_t *)device; + + if (!driver || !driver->validate_ok) { + qp_dprintf("qp_get_height: fail (invalid driver)\n"); + return 0; + } + + uint16_t height; switch (driver->rotation) { default: case QP_ROTATION_0: case QP_ROTATION_180: - if (width) { - *width = driver->panel_width; - } - if (height) { - *height = driver->panel_height; - } + height = driver->panel_height; break; case QP_ROTATION_90: case QP_ROTATION_270: - if (width) { - *width = driver->panel_height; - } - if (height) { - *height = driver->panel_width; - } + height = driver->panel_width; break; } + qp_dprintf("qp_get_height: ok\n"); + return height; +} + +painter_rotation_t qp_get_rotation(painter_device_t device) { + qp_dprintf("qp_get_rotation: entry\n"); + painter_driver_t *driver = (painter_driver_t *)device; + + if (!driver || !driver->validate_ok) { + qp_dprintf("qp_get_rotation: fail (invalid driver)\n"); + return QP_ROTATION_0; + } + + qp_dprintf("qp_get_rotation: ok\n"); + return driver->rotation; +} + +uint16_t qp_get_offset_x(painter_device_t device) { + qp_dprintf("qp_get_offset_x: entry\n"); + painter_driver_t *driver = (painter_driver_t *)device; + + if (!driver || !driver->validate_ok) { + qp_dprintf("qp_get_offset_x: fail (invalid driver)\n"); + return 0; + } + + qp_dprintf("qp_get_offset_x: ok\n"); + return driver->offset_x; +} + +uint16_t qp_get_offset_y(painter_device_t device) { + qp_dprintf("qp_get_offset_y: entry\n"); + painter_driver_t *driver = (painter_driver_t *)device; + + if (!driver || !driver->validate_ok) { + qp_dprintf("qp_get_offset_y: fail (invalid driver)\n"); + return 0; + } + + qp_dprintf("qp_get_offset_y: ok\n"); + return driver->offset_y; +} + +void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) { + qp_dprintf("qp_geometry: entry\n"); + painter_driver_t *driver = (painter_driver_t *)device; + + if (!driver || !driver->validate_ok) { + qp_dprintf("qp_geometry: fail (invalid driver)\n"); + return; + } + + if (width) { + *width = qp_get_width(device); + } + + if (height) { + *height = qp_get_height(device); + } + if (rotation) { - *rotation = driver->rotation; + *rotation = qp_get_rotation(device); } if (offset_x) { - *offset_x = driver->offset_x; + *offset_x = qp_get_offset_x(device); } if (offset_y) { - *offset_y = driver->offset_y; + *offset_y = qp_get_offset_y(device); } qp_dprintf("qp_get_geometry: ok\n"); diff --git a/quantum/painter/qp.h b/quantum/painter/qp.h index 7222d3b413..873a9d9f32 100644 --- a/quantum/painter/qp.h +++ b/quantum/painter/qp.h @@ -176,6 +176,41 @@ bool qp_clear(painter_device_t device); bool qp_flush(painter_device_t device); /** + * Retrieves the width of the display. + * + * @param device[in] the handle of the device to control + */ +uint16_t qp_get_width(painter_device_t device); + +/** + * Retrieves the height of the display. + * + * @param device[in] the handle of the device to control + */ +uint16_t qp_get_height(painter_device_t device); + +/** + * Retrieves the rotation of the display. + * + * @param device[in] the handle of the device to control + */ +painter_rotation_t qp_get_rotation(painter_device_t device); + +/** + * Retrieves the x-offset of the display. + * + * @param device[in] the handle of the device to control + */ +uint16_t qp_get_offset_x(painter_device_t device); + +/** + * Retrieves the y-offset of the display. + * + * @param device[in] the handle of the device to control + */ +uint16_t qp_get_offset_y(painter_device_t device); + +/** * Retrieves the size, rotation, and offsets for the display. * * @note Any arguments of NULL will be ignored. @@ -504,6 +539,12 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai # define SSD1351_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_SSD1351_ENABLE +#ifdef QUANTUM_PAINTER_SH1106_ENABLE +# include "qp_sh1106.h" +#else // QUANTUM_PAINTER_SH1106_ENABLE +# define SH1106_NUM_DEVICES 0 +#endif // QUANTUM_PAINTER_SH1106_ENABLE + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantum Painter Extras diff --git a/quantum/painter/qp_draw_ellipse.c b/quantum/painter/qp_draw_ellipse.c index e912a3e91f..9e77bca8b0 100644 --- a/quantum/painter/qp_draw_ellipse.c +++ b/quantum/painter/qp_draw_ellipse.c @@ -67,10 +67,10 @@ bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex, return false; } - int16_t aa = ((int16_t)sizex) * ((int16_t)sizex); - int16_t bb = ((int16_t)sizey) * ((int16_t)sizey); - int16_t fa = 4 * ((int16_t)aa); - int16_t fb = 4 * ((int16_t)bb); + int32_t aa = ((int32_t)sizex) * ((int32_t)sizex); + int32_t bb = ((int32_t)sizey) * ((int32_t)sizey); + int32_t fa = 4 * aa; + int32_t fb = 4 * bb; int16_t dx = 0; int16_t dy = ((int16_t)sizey); @@ -83,7 +83,7 @@ bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex, } bool ret = true; - for (int16_t delta = (2 * bb) + (aa * (1 - (2 * sizey))); bb * dx <= aa * dy; dx++) { + for (int32_t delta = (2 * bb) + (aa * (1 - (2 * sizey))); bb * dx <= aa * dy; dx++) { if (!qp_ellipse_helper_impl(device, x, y, dx, dy, filled)) { ret = false; break; @@ -98,7 +98,7 @@ bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex, dx = sizex; dy = 0; - for (int16_t delta = (2 * aa) + (bb * (1 - (2 * sizex))); aa * dy <= bb * dx; dy++) { + for (int32_t delta = (2 * aa) + (bb * (1 - (2 * sizex))); aa * dy <= bb * dx; dy++) { if (!qp_ellipse_helper_impl(device, x, y, dx, dy, filled)) { ret = false; break; diff --git a/quantum/painter/qp_draw_image.c b/quantum/painter/qp_draw_image.c index fb17a05a1b..87c59148c2 100644 --- a/quantum/painter/qp_draw_image.c +++ b/quantum/painter/qp_draw_image.c @@ -115,6 +115,7 @@ typedef struct qgf_frame_info_t { painter_compression_t compression_scheme; uint8_t bpp; bool has_palette; + bool is_panel_native; bool is_delta; uint16_t left; uint16_t top; @@ -143,7 +144,7 @@ static bool qp_drawimage_prepare_frame_for_stream_read(painter_device_t device, } // Parse out the frame info - if (!qgf_parse_frame_descriptor(&frame_descriptor, &info->bpp, &info->has_palette, &info->is_delta, &info->compression_scheme, &info->delay)) { + if (!qgf_parse_frame_descriptor(&frame_descriptor, &info->bpp, &info->has_palette, &info->is_panel_native, &info->is_delta, &info->compression_scheme, &info->delay)) { return false; } @@ -236,8 +237,8 @@ static bool qp_drawimage_recolor_impl(painter_device_t device, uint16_t x, uint1 if (frame_info->is_delta) { l = x + frame_info->left; t = y + frame_info->top; - r = x + frame_info->right - 1; - b = y + frame_info->bottom - 1; + r = x + frame_info->right; + b = y + frame_info->bottom; } else { l = x; t = y; @@ -263,7 +264,7 @@ static bool qp_drawimage_recolor_impl(painter_device_t device, uint16_t x, uint1 } bool ret = false; - if (frame_info->bpp <= 8) { + if (!frame_info->is_panel_native) { // Set up the output state qp_internal_pixel_output_state_t output_state = {.device = device, .pixel_write_pos = 0, .max_pixels = qp_internal_num_pixels_in_buffer(device)}; diff --git a/quantum/painter/qp_draw_text.c b/quantum/painter/qp_draw_text.c index ff6fc01d11..1ac5cab646 100644 --- a/quantum/painter/qp_draw_text.c +++ b/quantum/painter/qp_draw_text.c @@ -19,6 +19,7 @@ typedef struct qff_font_handle_t { uint16_t num_unicode_glyphs; uint8_t bpp; bool has_palette; + bool is_panel_native; painter_compression_t compression_scheme; union { qp_stream_t stream; @@ -97,7 +98,7 @@ static painter_font_handle_t qp_load_font_internal(bool (*stream_factory)(qff_fo #endif // QUANTUM_PAINTER_LOAD_FONTS_TO_RAM // Read the info (parsing already successful above, no need to check return value) - qff_read_font_descriptor(&font->stream, &font->base.line_height, &font->has_ascii_table, &font->num_unicode_glyphs, &font->bpp, &font->has_palette, &font->compression_scheme, NULL); + qff_read_font_descriptor(&font->stream, &font->base.line_height, &font->has_ascii_table, &font->num_unicode_glyphs, &font->bpp, &font->has_palette, &font->is_panel_native, &font->compression_scheme, NULL); if (!qp_internal_bpp_capable(font->bpp)) { qp_dprintf("qp_load_font: fail (image bpp too high (%d), check QUANTUM_PAINTER_SUPPORTS_256_PALETTE or QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS)\n", (int)font->bpp); diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c index 87a30c3f9b..0e81467e26 100644 --- a/quantum/painter/qp_internal.c +++ b/quantum/painter/qp_internal.c @@ -16,6 +16,7 @@ enum { + (ST7735_NUM_DEVICES) // ST7735 + (GC9A01_NUM_DEVICES) // GC9A01 + (SSD1351_NUM_DEVICES) // SSD1351 + + (SH1106_NUM_DEVICES) // SH1106 }; static painter_device_t qp_devices[QP_NUM_DEVICES] = {NULL}; diff --git a/quantum/painter/qp_internal_formats.h b/quantum/painter/qp_internal_formats.h index 194f82b31a..1beb604b9e 100644 --- a/quantum/painter/qp_internal_formats.h +++ b/quantum/painter/qp_internal_formats.h @@ -44,8 +44,8 @@ typedef enum qp_image_format_t { PALETTE_2BPP = 0x05, PALETTE_4BPP = 0x06, PALETTE_8BPP = 0x07, - RGB565_16BPP = 0x08, - RGB888_24BPP = 0x09, + RGB565_16BPP = 0x08, // Natively streamed to the panel, no interpolation or palette handling + RGB888_24BPP = 0x09, // Natively streamed to the panel, no interpolation or palette handling } qp_image_format_t; typedef enum painter_compression_t { IMAGE_UNCOMPRESSED, IMAGE_COMPRESSED_RLE } painter_compression_t; diff --git a/quantum/painter/rules.mk b/quantum/painter/rules.mk index 7752936cbd..ca81cffb03 100644 --- a/quantum/painter/rules.mk +++ b/quantum/painter/rules.mk @@ -6,14 +6,16 @@ QUANTUM_PAINTER_LVGL_INTEGRATION ?= no # The list of permissible drivers that can be listed in QUANTUM_PAINTER_DRIVERS VALID_QUANTUM_PAINTER_DRIVERS := \ - rgb565_surface \ - ili9163_spi \ - ili9341_spi \ - ili9488_spi \ - st7735_spi \ - st7789_spi \ - gc9a01_spi \ - ssd1351_spi + surface \ + ili9163_spi \ + ili9341_spi \ + ili9488_spi \ + st7735_spi \ + st7789_spi \ + gc9a01_spi \ + ssd1351_spi \ + sh1106_i2c \ + sh1106_spi #------------------------------------------------------------------------------- @@ -42,7 +44,9 @@ ifeq ($(strip $(QUANTUM_PAINTER_ANIMATIONS_ENABLE)), yes) endif # Comms flags +QUANTUM_PAINTER_NEEDS_COMMS_DUMMY ?= no QUANTUM_PAINTER_NEEDS_COMMS_SPI ?= no +QUANTUM_PAINTER_NEEDS_COMMS_I2C ?= no # Handler for each driver define handle_quantum_painter_driver @@ -51,12 +55,8 @@ define handle_quantum_painter_driver ifeq ($$(filter $$(strip $$(CURRENT_PAINTER_DRIVER)),$$(VALID_QUANTUM_PAINTER_DRIVERS)),) $$(error "$$(CURRENT_PAINTER_DRIVER)" is not a valid Quantum Painter driver) - else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),rgb565_surface) - OPT_DEFS += -DQUANTUM_PAINTER_RGB565_SURFACE_ENABLE - COMMON_VPATH += \ - $(DRIVER_PATH)/painter/generic - SRC += \ - $(DRIVER_PATH)/painter/generic/qp_rgb565_surface.c \ + else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),surface) + QUANTUM_PAINTER_NEEDS_SURFACE := yes else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9163_spi) QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes @@ -135,16 +135,60 @@ define handle_quantum_painter_driver $(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \ $(DRIVER_PATH)/painter/ssd1351/qp_ssd1351.c + else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),sh1106_spi) + QUANTUM_PAINTER_NEEDS_SURFACE := yes + QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes + QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes + OPT_DEFS += -DQUANTUM_PAINTER_SH1106_ENABLE -DQUANTUM_PAINTER_SH1106_SPI_ENABLE + COMMON_VPATH += \ + $(DRIVER_PATH)/painter/oled_panel \ + $(DRIVER_PATH)/painter/sh1106 + SRC += \ + $(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \ + $(DRIVER_PATH)/painter/sh1106/qp_sh1106.c + + else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),sh1106_i2c) + QUANTUM_PAINTER_NEEDS_SURFACE := yes + QUANTUM_PAINTER_NEEDS_COMMS_I2C := yes + OPT_DEFS += -DQUANTUM_PAINTER_SH1106_ENABLE -DQUANTUM_PAINTER_SH1106_I2C_ENABLE + COMMON_VPATH += \ + $(DRIVER_PATH)/painter/oled_panel \ + $(DRIVER_PATH)/painter/sh1106 + SRC += \ + $(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \ + $(DRIVER_PATH)/painter/sh1106/qp_sh1106.c + endif endef # Iterate through the listed drivers for the build, including what's necessary $(foreach qp_driver,$(QUANTUM_PAINTER_DRIVERS),$(eval $(call handle_quantum_painter_driver,$(qp_driver)))) +# If a surface is needed, set up the required files +ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_SURFACE)), yes) + QUANTUM_PAINTER_NEEDS_COMMS_DUMMY := yes + OPT_DEFS += -DQUANTUM_PAINTER_SURFACE_ENABLE + COMMON_VPATH += \ + $(DRIVER_PATH)/painter/generic + SRC += \ + $(DRIVER_PATH)/painter/generic/qp_surface_common.c \ + $(DRIVER_PATH)/painter/generic/qp_surface_mono1bpp.c \ + $(DRIVER_PATH)/painter/generic/qp_surface_rgb565.c +endif + +# If dummy comms is needed, set up the required files +ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_DUMMY)), yes) + OPT_DEFS += -DQUANTUM_PAINTER_DUMMY_COMMS_ENABLE + VPATH += $(DRIVER_PATH)/painter/comms + SRC += \ + $(QUANTUM_DIR)/painter/qp_comms.c \ + $(DRIVER_PATH)/painter/comms/qp_comms_dummy.c +endif + # If SPI comms is needed, set up the required files ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_SPI)), yes) OPT_DEFS += -DQUANTUM_PAINTER_SPI_ENABLE - QUANTUM_LIB_SRC += spi_master.c + SPI_DRIVER_REQUIRED = yes VPATH += $(DRIVER_PATH)/painter/comms SRC += \ $(QUANTUM_DIR)/painter/qp_comms.c \ @@ -155,7 +199,17 @@ ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_SPI)), yes) endif endif +# If I2C comms is needed, set up the required files +ifeq ($(strip $(QUANTUM_PAINTER_NEEDS_COMMS_I2C)), yes) + OPT_DEFS += -DQUANTUM_PAINTER_I2C_ENABLE + I2C_DRIVER_REQUIRED = yes + VPATH += $(DRIVER_PATH)/painter/comms + SRC += \ + $(QUANTUM_DIR)/painter/qp_comms.c \ + $(DRIVER_PATH)/painter/comms/qp_comms_i2c.c +endif + # Check if LVGL needs to be enabled ifeq ($(strip $(QUANTUM_PAINTER_LVGL_INTEGRATION)), yes) - include $(QUANTUM_DIR)/painter/lvgl/rules.mk + include $(QUANTUM_DIR)/painter/lvgl/rules.mk endif |