qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

qp.h (23477B)


      1 // Copyright 2021-2023 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #pragma once
      5 
      6 #include <stdint.h>
      7 #include <stdbool.h>
      8 
      9 #include "deferred_exec.h"
     10 
     11 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     12 // Quantum Painter global configurables (add to your keyboard's config.h)
     13 
     14 #ifndef QUANTUM_PAINTER_DISPLAY_TIMEOUT
     15 /**
     16  * @def This controls the amount of time (in milliseconds) that all displays will remain on after the last user input.
     17  *      If set to 0, the display will remain on indefinitely.
     18  */
     19 #    define QUANTUM_PAINTER_DISPLAY_TIMEOUT 30000
     20 #endif // QUANTUM_PAINTER_DISPLAY_TIMEOUT
     21 
     22 #ifndef QUANTUM_PAINTER_TASK_THROTTLE
     23 /**
     24  * @def This controls the amount of time (in milliseconds) that the Quantum Painter internal task will wait between
     25  *      each execution.
     26  */
     27 #    define QUANTUM_PAINTER_TASK_THROTTLE 1
     28 #endif // QUANTUM_PAINTER_TASK_THROTTLE
     29 
     30 #ifndef QUANTUM_PAINTER_NUM_IMAGES
     31 /**
     32  * @def This controls the maximum number of images that Quantum Painter can load at any one time. Images can be loaded
     33  *      using \ref qp_load_image_mem, and can be unloaded by calling \ref qp_close_image. Increasing this number in
     34  *      order to load more images increases the amount of RAM required. Image data is not held in RAM, just metadata.
     35  */
     36 #    define QUANTUM_PAINTER_NUM_IMAGES 8
     37 #endif // QUANTUM_PAINTER_NUM_IMAGES
     38 
     39 #ifndef QUANTUM_PAINTER_NUM_FONTS
     40 /**
     41  * @def This controls the maximum number of fonts that Quantum Painter can load. Fonts can be loaded using
     42  *      \ref qp_load_font_mem, and can be unloaded by calling \ref qp_close_font. Increasing this number in order to
     43  *      load more fonts increases the amount of RAM required. Font data is not held in RAM, unless
     44  *      \ref QUANTUM_PAINTER_LOAD_FONTS_TO_RAM is set to TRUE.
     45  */
     46 #    define QUANTUM_PAINTER_NUM_FONTS 4
     47 #endif // QUANTUM_PAINTER_NUM_FONTS
     48 
     49 #ifndef QUANTUM_PAINTER_LOAD_FONTS_TO_RAM
     50 /**
     51  * @def This controls whether or not fonts should be cached in RAM. Under normal circumstances, fonts can have quite
     52  *      random access patterns, and due to timing of flash memory or external storage, it may be a significant speedup
     53  *      moving the font into RAM before use. Defaults to "off", but if it's enabled it will fallback to reading from the
     54  *      original location if corresponding RAM could not be allocated (such as being too large).
     55  */
     56 #    define QUANTUM_PAINTER_LOAD_FONTS_TO_RAM FALSE
     57 #endif
     58 
     59 #ifndef QUANTUM_PAINTER_CONCURRENT_ANIMATIONS
     60 /**
     61  * @def This controls the maximum number of animations that Quantum Painter can play simultaneously. Increasing this
     62  *      number in order to play more animations at the same time increases the amount of RAM required.
     63  */
     64 #    define QUANTUM_PAINTER_CONCURRENT_ANIMATIONS 4
     65 #endif // QUANTUM_PAINTER_CONCURRENT_ANIMATIONS
     66 
     67 #ifndef QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE
     68 /**
     69  * @def This controls the maximum size of the pixel data buffer used for single blocks of transmission. Larger buffers
     70  *      means more data is processed at one time, with less frequent transmissions, at the cost of RAM.
     71  */
     72 #    define QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE 1024
     73 #endif
     74 
     75 #ifndef QUANTUM_PAINTER_SUPPORTS_256_PALETTE
     76 /**
     77  * @def This controls whether 256-color palettes are supported. This has relatively hefty requirements on RAM -- at
     78  *      least 1kB extra is required just to store the palette information, with more required for other metadata.
     79  */
     80 #    define QUANTUM_PAINTER_SUPPORTS_256_PALETTE FALSE
     81 #endif
     82 
     83 #ifndef QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS
     84 /**
     85  * @def This controls whether the native color range is supported. This avoids the use of palettes but each image
     86  *      requires more storage space.
     87  */
     88 #    define QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS FALSE
     89 #endif
     90 
     91 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     92 // Quantum Painter types
     93 
     94 /**
     95  * @typedef A handle to a Quantum Painter device, such as an LCD or OLED. Most Quantum Painter APIs require this
     96  *          argument in order to perform operations on the display.
     97  */
     98 typedef const void *painter_device_t;
     99 
    100 /**
    101  * @typedef The desired rotation of a panel. Used as a parameter to \ref qp_init, and can be queried by
    102  *          \ref qp_get_geometry.
    103  */
    104 typedef enum { QP_ROTATION_0, QP_ROTATION_90, QP_ROTATION_180, QP_ROTATION_270 } painter_rotation_t;
    105 
    106 /**
    107  * @typedef A descriptor for a Quantum Painter image.
    108  */
    109 typedef struct painter_image_desc_t {
    110     uint16_t width;       ///< Image width
    111     uint16_t height;      ///< Image height
    112     uint16_t frame_count; ///< Number of frames in this image
    113 } painter_image_desc_t;
    114 
    115 /**
    116  * @typedef A handle to a Quantum Painter image.
    117  */
    118 typedef const painter_image_desc_t *painter_image_handle_t;
    119 
    120 /**
    121  * @typedef A descriptor for a Quantum Painter font.
    122  */
    123 typedef struct painter_font_desc_t {
    124     uint8_t line_height; ///< The number of pixels in height for each line
    125 } painter_font_desc_t;
    126 
    127 /**
    128  * @typedef A handle to a Quantum Painter font.
    129  */
    130 typedef const painter_font_desc_t *painter_font_handle_t;
    131 
    132 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    133 // Quantum Painter External API
    134 
    135 /**
    136  * Initialize a device and set its rotation.
    137  *
    138  * @param device[in] the handle of the device to initialize
    139  * @param rotation[in] the rotation to use
    140  * @return true if initialization succeeded
    141  * @return false if initialization failed
    142  */
    143 bool qp_init(painter_device_t device, painter_rotation_t rotation);
    144 
    145 /**
    146  * Controls whether a display is on or off.
    147  *
    148  * @note If backlighting is used to control brightness (such as for an LCD), it will need to be handled external to
    149  *       Quantum Painter.
    150  *
    151  * @param device[in] the handle of the device to control
    152  * @param power_on[in] whether or not the device should be on
    153  * @return true if controlling the power state succeeded
    154  * @return false if controlling the power state failed
    155  */
    156 bool qp_power(painter_device_t device, bool power_on);
    157 
    158 /**
    159  * Clears a device's screen.
    160  *
    161  * @param device[in] the handle of the device to control
    162  * @return true if clearing the screen succeeded
    163  * @return false if clearing the screen failed
    164  */
    165 bool qp_clear(painter_device_t device);
    166 
    167 /**
    168  * Transmits any outstanding data to the screen in order to persist all changes to the display.
    169  *
    170  * @note Drivers without internal framebuffers will likely ignore this API.
    171  *
    172  * @param device[in] the handle of the device to control
    173  * @return true if flushing changes to the screen succeeded
    174  * @return false if flushing changes to the screen failed
    175  */
    176 bool qp_flush(painter_device_t device);
    177 
    178 /**
    179  * Retrieves the width of the display.
    180  *
    181  * @param device[in] the handle of the device to control
    182  */
    183 uint16_t qp_get_width(painter_device_t device);
    184 
    185 /**
    186  * Retrieves the height of the display.
    187  *
    188  * @param device[in] the handle of the device to control
    189  */
    190 uint16_t qp_get_height(painter_device_t device);
    191 
    192 /**
    193  * Retrieves the rotation of the display.
    194  *
    195  * @param device[in] the handle of the device to control
    196  */
    197 painter_rotation_t qp_get_rotation(painter_device_t device);
    198 
    199 /**
    200  * Retrieves the x-offset of the display.
    201  *
    202  * @param device[in] the handle of the device to control
    203  */
    204 uint16_t qp_get_offset_x(painter_device_t device);
    205 
    206 /**
    207  * Retrieves the y-offset of the display.
    208  *
    209  * @param device[in] the handle of the device to control
    210  */
    211 uint16_t qp_get_offset_y(painter_device_t device);
    212 
    213 /**
    214  * Retrieves the size, rotation, and offsets for the display.
    215  *
    216  * @note Any arguments of NULL will be ignored.
    217  *
    218  * @param device[in] the handle of the device to control
    219  * @param width[out] the device's width
    220  * @param height[out] the device's height
    221  * @param rotation[out] the device's rotation
    222  * @param offset_x[out] the device's x-offset applied while drawing
    223  * @param offset_y[out] the device's y-offset applied while drawing
    224  */
    225 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);
    226 
    227 /**
    228  * Allows repositioning of the viewport if the panel geometry offsets are non-zero.
    229  *
    230  * @param device[in] the handle of the device to control
    231  * @param offset_x[in] the device's x-offset applied while drawing
    232  * @param offset_y[in] the device's y-offset applied while drawing
    233  */
    234 void qp_set_viewport_offsets(painter_device_t device, uint16_t offset_x, uint16_t offset_y);
    235 
    236 /**
    237  * Sets a pixel to the specified color.
    238  *
    239  * @param device[in] the handle of the device to control
    240  * @param x[in] the x-position to draw onto the device
    241  * @param y[in] the y-position to draw onto the device
    242  * @param hue[in] the hue to use, with 0-360 mapped to 0-255
    243  * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
    244  * @param val[in] the value to use, with 0-100% mapped to 0-255
    245  * @return true if setting the pixel succeeded
    246  * @return false if setting the pixel failed
    247  */
    248 bool qp_setpixel(painter_device_t device, uint16_t x, uint16_t y, uint8_t hue, uint8_t sat, uint8_t val);
    249 
    250 /**
    251  * Draws a line using the specified color.
    252  *
    253  * @param device[in] the handle of the device to control
    254  * @param x0[in] the device's x-position to start
    255  * @param y0[in] the device's y-position to start
    256  * @param x1[in] the device's x-position to finish
    257  * @param y1[in] the device's y-position to finish
    258  * @param hue[in] the hue to use, with 0-360 mapped to 0-255
    259  * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
    260  * @param val[in] the value to use, with 0-100% mapped to 0-255
    261  * @return true if drawing the line succeeded
    262  * @return false if drawing the line failed
    263  */
    264 bool qp_line(painter_device_t device, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t hue, uint8_t sat, uint8_t val);
    265 
    266 /**
    267  * Draws a rectangle using the specified color, optionally filled.
    268  *
    269  * @param device[in] the handle of the device to control
    270  * @param left[in] the device's x-position to start
    271  * @param top[in] the device's y-position to start
    272  * @param right[in] the device's x-position to finish
    273  * @param bottom[in] the device's y-position to finish
    274  * @param hue[in] the hue to use, with 0-360 mapped to 0-255
    275  * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
    276  * @param val[in] the value to use, with 0-100% mapped to 0-255
    277  * @param filled[in] whether the rectangle should be filled
    278  * @return true if drawing the rectangle succeeded
    279  * @return false if drawing the rectangle failed
    280  */
    281 bool qp_rect(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint8_t hue, uint8_t sat, uint8_t val, bool filled);
    282 
    283 /**
    284  * Draws a circle using the specified color, optionally filled.
    285  *
    286  * @param device[in] the handle of the device to control
    287  * @param x[in] the x-position of the centre of the circle to draw onto the device
    288  * @param y[in] the y-position of the centre of the circle to draw onto the device
    289  * @param radius[in] the radius of the circle to draw
    290  * @param hue[in] the hue to use, with 0-360 mapped to 0-255
    291  * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
    292  * @param val[in] the value to use, with 0-100% mapped to 0-255
    293  * @param filled[in] whether the circle should be filled
    294  * @return true if drawing the circle succeeded
    295  * @return false if drawing the circle failed
    296  */
    297 bool qp_circle(painter_device_t device, uint16_t x, uint16_t y, uint16_t radius, uint8_t hue, uint8_t sat, uint8_t val, bool filled);
    298 
    299 /**
    300  * Draws a ellipse using the specified color, optionally filled.
    301  *
    302  * @param device[in] the handle of the device to control
    303  * @param x[in] the x-position of the centre of the ellipse to draw onto the device
    304  * @param y[in] the y-position of the centre of the ellipse to draw onto the device
    305  * @param sizex[in] the horizontal size of the ellipse
    306  * @param sizey[in] the vertical size of the ellipse
    307  * @param hue[in] the hue to use, with 0-360 mapped to 0-255
    308  * @param sat[in] the saturation to use, with 0-100% mapped to 0-255
    309  * @param val[in] the value to use, with 0-100% mapped to 0-255
    310  * @param filled[in] whether the ellipse should be filled
    311  * @return true if drawing the ellipse succeeded
    312  * @return false if drawing the ellipse failed
    313  */
    314 bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex, uint16_t sizey, uint8_t hue, uint8_t sat, uint8_t val, bool filled);
    315 
    316 /**
    317  * Sets up the location on the display to stream raw pixel data to the display, using \ref qp_pixdata.
    318  *
    319  * @note This is for advanced uses only, and should not be required for normal Quantum Painter functionality.
    320  *
    321  * @param device[in] the handle of the device to control
    322  * @param left[in] the device's x-position to start
    323  * @param top[in] the device's y-position to start
    324  * @param right[in] the device's x-position to finish
    325  * @param bottom[in] the device's y-position to finish
    326  * @return true if setting the viewport succeeded
    327  * @return false if setting the viewport failed
    328  */
    329 bool qp_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom);
    330 
    331 /**
    332  * Streams raw pixel data (in the native panel format) to the area previously set by \ref qp_viewport.
    333  *
    334  * @note This is for advanced uses only, and should not be required for normal Quantum Painter functionality.
    335  *
    336  * @param device[in] the handle of the device to control
    337  * @param pixel_data[in] pointer to buffer data
    338  * @param native_pixel_count[in] the number of pixels to transmit
    339  * @return true if streaming of data succeeded
    340  * @return false if streaming of data failed
    341  */
    342 bool qp_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count);
    343 
    344 /**
    345  * Loads an image into memory.
    346  *
    347  * @note Images can be unloaded by calling \ref qp_close_image.
    348  *
    349  * @param buffer[in] the image data to load
    350  * @return an image handle usable with \ref qp_drawimage, \ref qp_drawimage_recolor, \ref qp_animate, and
    351  *         \ref qp_animate_recolor.
    352  * @return NULL if loading the image failed
    353  */
    354 painter_image_handle_t qp_load_image_mem(const void *buffer);
    355 
    356 /**
    357  * Closes an image handle when no longer in use.
    358  *
    359  * @param image[in] the handle of the image to unload
    360  * @return true if unloading the image succeeded
    361  * @return false if unloading the image failed
    362  */
    363 bool qp_close_image(painter_image_handle_t image);
    364 
    365 /**
    366  * Draws an image to the display.
    367  *
    368  * @param device[in] the handle of the device to control
    369  * @param x[in] the x-position where the image should be drawn onto the device
    370  * @param y[in] the y-position where the image should be drawn onto the device
    371  * @param image[in] the handle of the image to draw
    372  * @return true if drawing the image succeeded
    373  * @return false if drawing the image failed
    374  */
    375 bool qp_drawimage(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image);
    376 
    377 /**
    378  * Draws an image to the display, recoloring monochrome images to the desired foreground/background.
    379  *
    380  * @param device[in] the handle of the device to control
    381  * @param x[in] the x-position where the image should be drawn onto the device
    382  * @param y[in] the y-position where the image should be drawn onto the device
    383  * @param image[in] the handle of the image to draw
    384  * @param hue_fg[in] the foreground hue to use, with 0-360 mapped to 0-255
    385  * @param sat_fg[in] the foreground saturation to use, with 0-100% mapped to 0-255
    386  * @param val_fg[in] the foreground value to use, with 0-100% mapped to 0-255
    387  * @param hue_bg[in] the background hue to use, with 0-360 mapped to 0-255
    388  * @param sat_bg[in] the background saturation to use, with 0-100% mapped to 0-255
    389  * @param val_bg[in] the background value to use, with 0-100% mapped to 0-255
    390  * @return true if drawing the image succeeded
    391  * @return false if drawing the image failed
    392  */
    393 bool qp_drawimage_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg);
    394 
    395 /**
    396  * Draws an animation to the display.
    397  *
    398  * @param device[in] the handle of the device to control
    399  * @param x[in] the x-position where the image should be drawn onto the device
    400  * @param y[in] the y-position where the image should be drawn onto the device
    401  * @param image[in] the handle of the image to draw
    402  * @return the \ref deferred_token to use with \ref qp_stop_animation in order to stop animating
    403  * @return INVALID_DEFERRED_TOKEN if animating the image failed
    404  */
    405 deferred_token qp_animate(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image);
    406 
    407 /**
    408  * Draws an animation to the display, recoloring monochrome images to the desired foreground/background.
    409  *
    410  * @param device[in] the handle of the device to control
    411  * @param x[in] the x-position where the image should be drawn onto the device
    412  * @param y[in] the y-position where the image should be drawn onto the device
    413  * @param image[in] the handle of the image to draw
    414  * @param hue_fg[in] the foreground hue to use, with 0-360 mapped to 0-255
    415  * @param sat_fg[in] the foreground saturation to use, with 0-100% mapped to 0-255
    416  * @param val_fg[in] the foreground value to use, with 0-100% mapped to 0-255
    417  * @param hue_bg[in] the background hue to use, with 0-360 mapped to 0-255
    418  * @param sat_bg[in] the background saturation to use, with 0-100% mapped to 0-255
    419  * @param val_bg[in] the background value to use, with 0-100% mapped to 0-255
    420  * @return the \ref deferred_token to use with \ref qp_stop_animation in order to stop animating
    421  * @return INVALID_DEFERRED_TOKEN if animating the image failed
    422  */
    423 deferred_token qp_animate_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg);
    424 
    425 /**
    426  * Cancels a running animation.
    427  *
    428  * @param anim_token[in] the animation token returned by \ref qp_animate, or \ref qp_animate_recolor.
    429  */
    430 void qp_stop_animation(deferred_token anim_token);
    431 
    432 /**
    433  * Loads a font into memory.
    434  *
    435  * @note Fonts can be unloaded by calling \ref qp_close_font.
    436  *
    437  * @param buffer[in] the font data to load
    438  * @return an image handle usable with \ref qp_textwidth, \ref qp_drawtext, and \ref qp_drawtext_recolor.
    439  * @return NULL if loading the font failed
    440  */
    441 painter_font_handle_t qp_load_font_mem(const void *buffer);
    442 
    443 /**
    444  * Closes a font handle when no longer in use.
    445  *
    446  * @param font[in] the handle of the font to unload
    447  * @return true if unloading the font succeeded
    448  * @return false if unloading the font failed
    449  */
    450 bool qp_close_font(painter_font_handle_t font);
    451 
    452 /**
    453  * Measures the width (in pixels) of the supplied string, given the specified font.
    454  *
    455  * @param font[in] the handle of the font
    456  * @param str[in] the string to measure
    457  * @return the width (in pixels) needed to draw the specified string
    458  */
    459 int16_t qp_textwidth(painter_font_handle_t font, const char *str);
    460 
    461 /**
    462  * Draws text to the display.
    463  *
    464  * @param device[in] the handle of the device to control
    465  * @param x[in] the x-position where the text should be drawn onto the device
    466  * @param y[in] the y-position where the text should be drawn onto the device
    467  * @param font[in] the handle of the font
    468  * @param str[in] the string to draw
    469  * @return the width (in pixels) used when drawing the specified string
    470  */
    471 int16_t qp_drawtext(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str);
    472 
    473 /**
    474  * Draws text to the display, recoloring monochrome fonts to the desired foreground/background.
    475  *
    476  * @param device[in] the handle of the device to control
    477  * @param x[in] the x-position where the text should be drawn onto the device
    478  * @param y[in] the y-position where the text should be drawn onto the device
    479  * @param font[in] the handle of the font
    480  * @param str[in] the string to draw
    481  * @param hue_fg[in] the foreground hue to use, with 0-360 mapped to 0-255
    482  * @param sat_fg[in] the foreground saturation to use, with 0-100% mapped to 0-255
    483  * @param val_fg[in] the foreground value to use, with 0-100% mapped to 0-255
    484  * @param hue_bg[in] the background hue to use, with 0-360 mapped to 0-255
    485  * @param sat_bg[in] the background saturation to use, with 0-100% mapped to 0-255
    486  * @param val_bg[in] the background value to use, with 0-100% mapped to 0-255
    487  * @return the width (in pixels) used when drawing the specified string
    488  */
    489 int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg);
    490 
    491 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    492 // Quantum Painter Drivers
    493 
    494 #ifdef QUANTUM_PAINTER_RGB565_SURFACE_ENABLE
    495 #    include "qp_rgb565_surface.h"
    496 #else // QUANTUM_PAINTER_RGB565_SURFACE_ENABLE
    497 #    define RGB565_SURFACE_NUM_DEVICES 0
    498 #endif // QUANTUM_PAINTER_RGB565_SURFACE_ENABLE
    499 
    500 #ifdef QUANTUM_PAINTER_ILI9163_ENABLE
    501 #    include "qp_ili9163.h"
    502 #else // QUANTUM_PAINTER_ILI9163_ENABLE
    503 #    define ILI9163_NUM_DEVICES 0
    504 #endif // QUANTUM_PAINTER_ILI9163_ENABLE
    505 
    506 #ifdef QUANTUM_PAINTER_ILI9341_ENABLE
    507 #    include "qp_ili9341.h"
    508 #else // QUANTUM_PAINTER_ILI9341_ENABLE
    509 #    define ILI9341_NUM_DEVICES 0
    510 #endif // QUANTUM_PAINTER_ILI9341_ENABLE
    511 
    512 #ifdef QUANTUM_PAINTER_ILI9486_ENABLE
    513 #    include "qp_ili9486.h"
    514 #else // QUANTUM_PAINTER_ILI9486_ENABLE
    515 #    define ILI9486_NUM_DEVICES 0
    516 #endif // QUANTUM_PAINTER_ILI9486_ENABLE
    517 
    518 #ifdef QUANTUM_PAINTER_ILI9488_ENABLE
    519 #    include "qp_ili9488.h"
    520 #else // QUANTUM_PAINTER_ILI9488_ENABLE
    521 #    define ILI9488_NUM_DEVICES 0
    522 #endif // QUANTUM_PAINTER_ILI9488_ENABLE
    523 
    524 #ifdef QUANTUM_PAINTER_ST7789_ENABLE
    525 #    include "qp_st7789.h"
    526 #else // QUANTUM_PAINTER_ST7789_ENABLE
    527 #    define ST7789_NUM_DEVICES 0
    528 #endif // QUANTUM_PAINTER_ST7789_ENABLE
    529 
    530 #ifdef QUANTUM_PAINTER_ST7735_ENABLE
    531 #    include "qp_st7735.h"
    532 #else // QUANTUM_PAINTER_ST7735_ENABLE
    533 #    define ST7735_NUM_DEVICES 0
    534 #endif // QUANTUM_PAINTER_ST7735_ENABLE
    535 
    536 #ifdef QUANTUM_PAINTER_GC9A01_ENABLE
    537 #    include "qp_gc9a01.h"
    538 #else // QUANTUM_PAINTER_GC9A01_ENABLE
    539 #    define GC9A01_NUM_DEVICES 0
    540 #endif // QUANTUM_PAINTER_GC9A01_ENABLE
    541 
    542 #ifdef QUANTUM_PAINTER_GC9107_ENABLE
    543 #    include "qp_gc9107.h"
    544 #else // QUANTUM_PAINTER_GC9107_ENABLE
    545 #    define GC9107_NUM_DEVICES 0
    546 #endif // QUANTUM_PAINTER_GC9107_ENABLE
    547 
    548 #ifdef QUANTUM_PAINTER_SSD1351_ENABLE
    549 #    include "qp_ssd1351.h"
    550 #else // QUANTUM_PAINTER_SSD1351_ENABLE
    551 #    define SSD1351_NUM_DEVICES 0
    552 #endif // QUANTUM_PAINTER_SSD1351_ENABLE
    553 
    554 #ifdef QUANTUM_PAINTER_SH1106_ENABLE
    555 #    include "qp_sh1106.h"
    556 #else // QUANTUM_PAINTER_SH1106_ENABLE
    557 #    define SH1106_NUM_DEVICES 0
    558 #endif // QUANTUM_PAINTER_SH1106_ENABLE
    559 
    560 #ifdef QUANTUM_PAINTER_SH1107_ENABLE
    561 #    include "qp_sh1107.h"
    562 #else // QUANTUM_PAINTER_SH1107_ENABLE
    563 #    define SH1107_NUM_DEVICES 0
    564 #endif // QUANTUM_PAINTER_SH1107_ENABLE
    565 
    566 #ifdef QUANTUM_PAINTER_LD7032_ENABLE
    567 #    include "qp_ld7032.h"
    568 #else // QUANTUM_PAINTER_LD7032_ENABLE
    569 #    define LD7032_NUM_DEVICES 0
    570 #endif // QUANTUM_PAINTER_LD7032_ENABLE
    571 
    572 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    573 // Quantum Painter Extras
    574 
    575 #ifdef QUANTUM_PAINTER_LVGL_INTEGRATION_ENABLE
    576 #    include "qp_lvgl.h"
    577 #endif // QUANTUM_PAINTER_LVGL_INTEGRATION_ENABLE