From cd94ba031c832266cca609951abc97eb52c90567 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Mon, 20 Mar 2023 14:13:53 +1100 Subject: Quantum Painter QoL enhancements -- auto-poweroff, auto-flush, buffer sizing (#20013) --- quantum/painter/qp.h | 36 +++++++++++++- quantum/painter/qp_draw_image.c | 14 +----- quantum/painter/qp_internal.c | 96 ++++++++++++++++++++++++++++++++++++ quantum/painter/qp_internal_driver.h | 7 ++- quantum/painter/rules.mk | 1 + 5 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 quantum/painter/qp_internal.c (limited to 'quantum/painter') diff --git a/quantum/painter/qp.h b/quantum/painter/qp.h index 00f5d7931a..7222d3b413 100644 --- a/quantum/painter/qp.h +++ b/quantum/painter/qp.h @@ -1,4 +1,4 @@ -// Copyright 2021 Nick Brassel (@tzarc) +// Copyright 2021-2023 Nick Brassel (@tzarc) // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -11,6 +11,22 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantum Painter global configurables (add to your keyboard's config.h) +#ifndef QUANTUM_PAINTER_DISPLAY_TIMEOUT +/** + * @def This controls the amount of time (in milliseconds) that all displays will remain on after the last user input. + * If set to 0, the display will remain on indefinitely. + */ +# define QUANTUM_PAINTER_DISPLAY_TIMEOUT 30000 +#endif // QUANTUM_PAINTER_DISPLAY_TIMEOUT + +#ifndef QUANTUM_PAINTER_TASK_THROTTLE +/** + * @def This controls the amount of time (in milliseconds) that the Quantum Painter internal task will wait between + * each execution. + */ +# define QUANTUM_PAINTER_TASK_THROTTLE 1 +#endif // QUANTUM_PAINTER_TASK_THROTTLE + #ifndef QUANTUM_PAINTER_NUM_IMAGES /** * @def This controls the maximum number of images that Quantum Painter can load at any one time. Images can be loaded @@ -53,7 +69,7 @@ * @def This controls the maximum size of the pixel data buffer used for single blocks of transmission. Larger buffers * means more data is processed at one time, with less frequent transmissions, at the cost of RAM. */ -# define QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE 32 +# define QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE 1024 #endif #ifndef QUANTUM_PAINTER_SUPPORTS_256_PALETTE @@ -442,34 +458,50 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai #ifdef QUANTUM_PAINTER_RGB565_SURFACE_ENABLE # include "qp_rgb565_surface.h" +#else // QUANTUM_PAINTER_RGB565_SURFACE_ENABLE +# define RGB565_SURFACE_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_RGB565_SURFACE_ENABLE #ifdef QUANTUM_PAINTER_ILI9163_ENABLE # include "qp_ili9163.h" +#else // QUANTUM_PAINTER_ILI9163_ENABLE +# define ILI9163_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_ILI9163_ENABLE #ifdef QUANTUM_PAINTER_ILI9341_ENABLE # include "qp_ili9341.h" +#else // QUANTUM_PAINTER_ILI9341_ENABLE +# define ILI9341_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_ILI9341_ENABLE #ifdef QUANTUM_PAINTER_ILI9488_ENABLE # include "qp_ili9488.h" +#else // QUANTUM_PAINTER_ILI9488_ENABLE +# define ILI9488_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_ILI9488_ENABLE #ifdef QUANTUM_PAINTER_ST7789_ENABLE # include "qp_st7789.h" +#else // QUANTUM_PAINTER_ST7789_ENABLE +# define ST7789_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_ST7789_ENABLE #ifdef QUANTUM_PAINTER_ST7735_ENABLE # include "qp_st7735.h" +#else // QUANTUM_PAINTER_ST7735_ENABLE +# define ST7735_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_ST7735_ENABLE #ifdef QUANTUM_PAINTER_GC9A01_ENABLE # include "qp_gc9a01.h" +#else // QUANTUM_PAINTER_GC9A01_ENABLE +# define GC9A01_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_GC9A01_ENABLE #ifdef QUANTUM_PAINTER_SSD1351_ENABLE # include "qp_ssd1351.h" +#else // QUANTUM_PAINTER_SSD1351_ENABLE +# define SSD1351_NUM_DEVICES 0 #endif // QUANTUM_PAINTER_SSD1351_ENABLE //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/quantum/painter/qp_draw_image.c b/quantum/painter/qp_draw_image.c index fa80617242..e722f3cf02 100644 --- a/quantum/painter/qp_draw_image.c +++ b/quantum/painter/qp_draw_image.c @@ -1,4 +1,4 @@ -// Copyright 2021 Nick Brassel (@tzarc) +// Copyright 2021-2023 Nick Brassel (@tzarc) // SPDX-License-Identifier: GPL-2.0-or-later #include "qp_internal.h" @@ -414,15 +414,3 @@ void qp_internal_animation_tick(void) { static uint32_t last_anim_exec = 0; deferred_exec_advanced_task(animation_executors, QUANTUM_PAINTER_CONCURRENT_ANIMATIONS, &last_anim_exec); } - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter Core API: qp_internal_task - -void qp_internal_task(void) { - qp_internal_animation_tick(); -#ifdef QUANTUM_PAINTER_LVGL_INTEGRATION_ENABLE - // Run LVGL ticks - void qp_lvgl_internal_tick(void); - qp_lvgl_internal_tick(); -#endif -} diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c new file mode 100644 index 0000000000..ea23aef7c3 --- /dev/null +++ b/quantum/painter/qp_internal.c @@ -0,0 +1,96 @@ +// Copyright 2023 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "qp_internal.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantum Painter Core API: device registration + +enum { + // Work out how many devices we're actually going to be instantiating + // NOTE: We intentionally do not include surfaces here, despite them conforming to the same API. + QP_NUM_DEVICES = (ILI9163_NUM_DEVICES) // ILI9163 + + (ILI9341_NUM_DEVICES) // ILI9341 + + (ILI9488_NUM_DEVICES) // ILI9488 + + (ST7789_NUM_DEVICES) // ST7789 + + (ST7735_NUM_DEVICES) // ST7735 + + (GC9A01_NUM_DEVICES) // GC9A01 + + (SSD1351_NUM_DEVICES) // SSD1351 +}; + +static painter_device_t qp_devices[QP_NUM_DEVICES] = {NULL}; + +bool qp_internal_register_device(painter_device_t driver) { + for (uint8_t i = 0; i < QP_NUM_DEVICES; i++) { + if (qp_devices[i] == NULL) { + qp_devices[i] = driver; + return true; + } + } + + // We should never get here -- someone has screwed up their device counts during config + qp_dprintf("qp_internal_register_device: no more space for devices!\n"); + return false; +} + +#if (QUANTUM_PAINTER_DISPLAY_TIMEOUT) > 0 +static void qp_internal_display_timeout_task(void) { + // Handle power on/off state + static bool display_on = true; + bool should_change_display_state = false; + bool target_display_state = false; + if (last_input_activity_elapsed() < (QUANTUM_PAINTER_DISPLAY_TIMEOUT)) { + should_change_display_state = display_on == false; + target_display_state = true; + } else { + should_change_display_state = display_on == true; + target_display_state = false; + } + + if (should_change_display_state) { + for (uint8_t i = 0; i < QP_NUM_DEVICES; i++) { + if (qp_devices[i] != NULL) { + qp_power(qp_devices[i], target_display_state); + } + } + + display_on = target_display_state; + } +} +#endif // (QUANTUM_PAINTER_DISPLAY_TIMEOUT) > 0 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantum Painter Core API: qp_internal_task + +_Static_assert((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999"); + +void qp_internal_task(void) { + // Perform throttling of the internal processing of Quantum Painter + static uint32_t last_tick = 0; + uint32_t now = timer_read32(); + if (TIMER_DIFF_32(now, last_tick) < (QUANTUM_PAINTER_TASK_THROTTLE)) { + return; + } + last_tick = now; + +#if (QUANTUM_PAINTER_DISPLAY_TIMEOUT) > 0 + qp_internal_display_timeout_task(); +#endif // (QUANTUM_PAINTER_DISPLAY_TIMEOUT) > 0 + + // Handle animations + void qp_internal_animation_tick(void); + qp_internal_animation_tick(); + +#ifdef QUANTUM_PAINTER_LVGL_INTEGRATION_ENABLE + // Run LVGL ticks + void qp_lvgl_internal_tick(void); + qp_lvgl_internal_tick(); +#endif + + // Flush (render) dirty regions to corresponding displays + for (uint8_t i = 0; i < QP_NUM_DEVICES; i++) { + if (qp_devices[i] != NULL) { + qp_flush(qp_devices[i]); + } + } +} diff --git a/quantum/painter/qp_internal_driver.h b/quantum/painter/qp_internal_driver.h index 82a0178a73..c976ff9db7 100644 --- a/quantum/painter/qp_internal_driver.h +++ b/quantum/painter/qp_internal_driver.h @@ -1,4 +1,4 @@ -// Copyright 2021 Nick Brassel (@tzarc) +// Copyright 2021-2023 Nick Brassel (@tzarc) // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -82,3 +82,8 @@ struct painter_driver_t { // Comms config pointer -- needs to point to an appropriate comms config if the comms driver requires it. void *comms_config; }; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Device internals + +bool qp_internal_register_device(painter_device_t driver); diff --git a/quantum/painter/rules.mk b/quantum/painter/rules.mk index 199e406dd6..7752936cbd 100644 --- a/quantum/painter/rules.mk +++ b/quantum/painter/rules.mk @@ -24,6 +24,7 @@ SRC += \ $(QUANTUM_DIR)/unicode/utf8.c \ $(QUANTUM_DIR)/color.c \ $(QUANTUM_DIR)/painter/qp.c \ + $(QUANTUM_DIR)/painter/qp_internal.c \ $(QUANTUM_DIR)/painter/qp_stream.c \ $(QUANTUM_DIR)/painter/qgf.c \ $(QUANTUM_DIR)/painter/qff.c \ -- cgit v1.2.3