summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Martínez <58857054+elpekenin@users.noreply.github.com>2024-02-17 08:36:05 +0100
committerGitHub <noreply@github.com>2024-02-17 18:36:05 +1100
commit538333571754c3cbeec92bc793b1b8023744cbbd (patch)
treeb2c46a2422f11a877bc49bf6be7bbba7e63c1865
parent39627c7620ceac2b5928019624cfab071f28420e (diff)
[Driver] ILI9486 on Quantum Painter (#18521)
Co-authored-by: Nick Brassel <nick@tzarc.org>
-rw-r--r--docs/quantum_painter.md34
-rw-r--r--drivers/painter/comms/qp_comms_spi.h1
-rw-r--r--drivers/painter/ili9xxx/qp_ili9486.c298
-rw-r--r--drivers/painter/ili9xxx/qp_ili9486.h52
-rw-r--r--drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h1
-rw-r--r--quantum/painter/qp.h6
-rw-r--r--quantum/painter/qp_internal.c1
-rw-r--r--quantum/painter/rules.mk12
8 files changed, 405 insertions, 0 deletions
diff --git a/docs/quantum_painter.md b/docs/quantum_painter.md
index dc855b1bf6..7f524b07ee 100644
--- a/docs/quantum_painter.md
+++ b/docs/quantum_painter.md
@@ -24,6 +24,7 @@ Supported devices:
24| GC9A01 | RGB LCD (circular) | 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += gc9a01_spi` | 24| GC9A01 | RGB LCD (circular) | 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += gc9a01_spi` |
25| ILI9163 | RGB LCD | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9163_spi` | 25| ILI9163 | RGB LCD | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9163_spi` |
26| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_spi` | 26| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_spi` |
27| ILI9486 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9486_spi` |
27| ILI9488 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9488_spi` | 28| ILI9488 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9488_spi` |
28| SSD1351 | RGB OLED | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ssd1351_spi` | 29| SSD1351 | RGB OLED | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ssd1351_spi` |
29| ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` | 30| ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` |
@@ -281,6 +282,39 @@ The maximum number of displays can be configured by changing the following in yo
281 282
282Native color format rgb565 is compatible with ILI9341 283Native color format rgb565 is compatible with ILI9341
283 284
285#### ** ILI9486 **
286
287Enabling support for the ILI9486 in Quantum Painter is done by adding the following to `rules.mk`:
288
289```make
290QUANTUM_PAINTER_ENABLE = yes
291QUANTUM_PAINTER_DRIVERS += ili9486_spi
292```
293
294Creating a ILI9486 device in firmware can then be done with the following API:
295
296```c
297painter_device_t qp_ili9486_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
298```
299
300There's another variant for this [Waveshare module](https://www.waveshare.com/wiki/3.5inch_TFT_Touch_Shield), because it has a quirky SPI->Parallel converter. You can create it with:
301
302```c
303painter_device_t qp_ili9486_make_spi_waveshare_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
304```
305
306The device handle returned from these functions can be used to perform all other drawing operations.
307
308The maximum number of displays can be configured by changing the following in your `config.h` (default is 1):
309
310```c
311// 3 displays:
312#define ILI9486_NUM_DEVICES 3
313```
314
315Native color format rgb888 is compatible with ILI9486
316Native color format rgb565 is compatible with ILI9486 Waveshare
317
284#### ** ILI9488 ** 318#### ** ILI9488 **
285 319
286Enabling support for the ILI9488 in Quantum Painter is done by adding the following to `rules.mk`: 320Enabling support for the ILI9488 in Quantum Painter is done by adding the following to `rules.mk`:
diff --git a/drivers/painter/comms/qp_comms_spi.h b/drivers/painter/comms/qp_comms_spi.h
index ff323c3c10..c39ea95f72 100644
--- a/drivers/painter/comms/qp_comms_spi.h
+++ b/drivers/painter/comms/qp_comms_spi.h
@@ -38,6 +38,7 @@ typedef struct qp_comms_spi_dc_reset_config_t {
38 bool command_params_uses_command_pin; // keep D/C held low when sending command sequences for data bytes 38 bool command_params_uses_command_pin; // keep D/C held low when sending command sequences for data bytes
39} qp_comms_spi_dc_reset_config_t; 39} qp_comms_spi_dc_reset_config_t;
40 40
41bool qp_comms_spi_dc_reset_init(painter_device_t device);
41void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd); 42void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd);
42uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void* data, uint32_t byte_count); 43uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void* data, uint32_t byte_count);
43void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len); 44void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len);
diff --git a/drivers/painter/ili9xxx/qp_ili9486.c b/drivers/painter/ili9xxx/qp_ili9486.c
new file mode 100644
index 0000000000..c4f3c15cec
--- /dev/null
+++ b/drivers/painter/ili9xxx/qp_ili9486.c
@@ -0,0 +1,298 @@
1// Copyright 2021 Nick Brassel (@tzarc)
2// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev>
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#include "qp_internal.h"
6#include "qp_comms.h"
7#include "qp_ili9486.h"
8#include "qp_ili9xxx_opcodes.h"
9#include "qp_tft_panel.h"
10
11#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE
12# include "spi_master.h"
13# include <qp_comms_spi.h>
14#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE
15
16////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17// Common
18
19// Driver storage
20tft_panel_dc_reset_painter_device_t ili9486_drivers[ILI9486_NUM_DEVICES] = {0};
21
22////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
23// Initialization
24
25bool qp_ili9486_init(painter_device_t device, painter_rotation_t rotation) {
26 // clang-format off
27 const uint8_t ili9486_init_sequence[] = {
28 // Command, Delay, N, Data[N]
29 ILI9XXX_CMD_RESET, 120, 0,
30 ILI9XXX_SET_PIX_FMT, 0, 1, 0x55,
31 ILI9XXX_SET_PGAMMA, 0, 15, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00,
32 ILI9XXX_SET_NGAMMA, 0, 15, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00,
33 ILI9XXX_SET_POWER_CTL_1, 0, 2, 0x0D, 0x0D,
34 ILI9XXX_SET_POWER_CTL_2, 0, 2, 0x43, 0x00,
35 ILI9XXX_SET_POWER_CTL_3, 0, 1, 0x00,
36 ILI9XXX_SET_VCOM_CTL_1, 0, 4, 0x00, 0x48, 0x00, 0x48,
37 ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02,
38 };
39 // clang-format on
40 qp_comms_bulk_command_sequence(device, ili9486_init_sequence, sizeof(ili9486_init_sequence));
41
42 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
43 const uint8_t madctl[] = {
44 [QP_ROTATION_0] = ILI9XXX_MADCTL_BGR,
45 [QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV,
46 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR,
47 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV,
48 };
49 const uint8_t functl[] = {
50 [QP_ROTATION_0] = 0x42,
51 [QP_ROTATION_90] = 0x62,
52 [QP_ROTATION_180] = 0x22,
53 [QP_ROTATION_270] = 0x02,
54 };
55
56 // clang-format off
57 uint8_t rotation_sequence[] = {
58 // Command, Delay, N, Data[N]
59 ILI9XXX_SET_MEM_ACS_CTL, 0, 1, madctl[rotation],
60 ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0x00, functl[rotation],
61 ILI9XXX_CMD_SLEEP_OFF, 5, 0,
62 ILI9XXX_CMD_DISPLAY_ON, 5, 0,
63 };
64 // clang-format on
65 qp_comms_bulk_command_sequence(device, rotation_sequence, sizeof(rotation_sequence));
66
67 return true;
68}
69
70////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71// Driver vtable
72
73// waveshare variant needs some tweaks due to shift registers
74static void qp_comms_spi_dc_reset_send_command_odd_cs_pulse(painter_device_t device, uint8_t cmd) {
75 painter_driver_t * driver = (painter_driver_t *)device;
76 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
77
78 writePinLow(comms_config->spi_config.chip_select_pin);
79 qp_comms_spi_dc_reset_send_command(device, cmd);
80 writePinHigh(comms_config->spi_config.chip_select_pin);
81}
82
83static uint32_t qp_comms_spi_send_data_odd_cs_pulse(painter_device_t device, const void *data, uint32_t byte_count) {
84 painter_driver_t * driver = (painter_driver_t *)device;
85 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
86
87 uint32_t bytes_remaining = byte_count;
88 const uint8_t *p = (const uint8_t *)data;
89 uint32_t max_msg_length = 1024;
90
91 writePinHigh(comms_config->dc_pin);
92 while (bytes_remaining > 0) {
93 uint32_t bytes_this_loop = QP_MIN(bytes_remaining, max_msg_length);
94 bool odd_bytes = bytes_this_loop & 1;
95
96 // send data
97 writePinLow(comms_config->spi_config.chip_select_pin);
98 spi_transmit(p, bytes_this_loop);
99 p += bytes_this_loop;
100
101 // extra CS toggle, for alignment
102 if (odd_bytes) {
103 writePinHigh(comms_config->spi_config.chip_select_pin);
104 writePinLow(comms_config->spi_config.chip_select_pin);
105 }
106
107 bytes_remaining -= bytes_this_loop;
108 }
109
110 return byte_count - bytes_remaining;
111}
112
113static uint32_t qp_ili9486_send_data_toggling(painter_device_t device, const uint8_t *data, uint32_t byte_count) {
114 painter_driver_t * driver = (painter_driver_t *)device;
115 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
116
117 uint32_t ret;
118 for (uint8_t j = 0; j < byte_count; ++j) {
119 writePinLow(comms_config->spi_config.chip_select_pin);
120 ret = qp_comms_spi_dc_reset_send_data(device, &data[j], 1);
121 writePinHigh(comms_config->spi_config.chip_select_pin);
122 }
123
124 return ret;
125}
126
127static void qp_comms_spi_send_command_sequence_odd_cs_pulse(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
128 for (size_t i = 0; i < sequence_len;) {
129 uint8_t command = sequence[i];
130 uint8_t delay = sequence[i + 1];
131 uint8_t num_bytes = sequence[i + 2];
132
133 qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, command);
134 if (num_bytes > 0) {
135 qp_ili9486_send_data_toggling(device, &sequence[i + 3], num_bytes);
136 }
137
138 if (delay > 0) {
139 wait_ms(delay);
140 }
141 i += (3 + num_bytes);
142 }
143}
144
145static bool qp_ili9486_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
146 painter_driver_t * driver = (painter_driver_t *)device;
147 tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable;
148
149 // Fix up the drawing location if required
150 left += driver->offset_x;
151 right += driver->offset_x;
152 top += driver->offset_y;
153 bottom += driver->offset_y;
154
155 // Check if we need to manually swap the window coordinates based on whether or not we're in a sideways rotation
156 if (vtable->swap_window_coords && (driver->rotation == QP_ROTATION_90 || driver->rotation == QP_ROTATION_270)) {
157 uint16_t temp;
158
159 temp = left;
160 left = top;
161 top = temp;
162
163 temp = right;
164 right = bottom;
165 bottom = temp;
166 }
167
168 // Set up the x-window
169 uint8_t xbuf[4] = {left >> 8, left & 0xFF, right >> 8, right & 0xFF};
170 qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.set_column_address);
171 qp_ili9486_send_data_toggling(device, xbuf, 4);
172
173 // Set up the y-window
174 uint8_t ybuf[4] = {top >> 8, top & 0xFF, bottom >> 8, bottom & 0xFF};
175 qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.set_row_address);
176 qp_ili9486_send_data_toggling(device, ybuf, 4);
177
178 // Lock in the window
179 qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.enable_writes);
180 return true;
181}
182
183// Regular
184const tft_panel_dc_reset_painter_driver_vtable_t ili9486_driver_vtable = {
185 .base =
186 {
187 .init = qp_ili9486_init,
188 .power = qp_tft_panel_power,
189 .clear = qp_tft_panel_clear,
190 .flush = qp_tft_panel_flush,
191 .pixdata = qp_tft_panel_pixdata,
192 .viewport = qp_tft_panel_viewport,
193 .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
194 .append_pixels = qp_tft_panel_append_pixels_rgb565,
195 .append_pixdata = qp_tft_panel_append_pixdata,
196 },
197 .num_window_bytes = 2,
198 .swap_window_coords = false,
199 .opcodes =
200 {
201 .display_on = ILI9XXX_CMD_DISPLAY_ON,
202 .display_off = ILI9XXX_CMD_DISPLAY_OFF,
203 .set_column_address = ILI9XXX_SET_COL_ADDR,
204 .set_row_address = ILI9XXX_SET_PAGE_ADDR,
205 .enable_writes = ILI9XXX_SET_MEM,
206 },
207};
208
209// Waveshare tweaks
210const tft_panel_dc_reset_painter_driver_vtable_t ili9486_waveshare_driver_vtable = {
211 .base =
212 {
213 .init = qp_ili9486_init,
214 .power = qp_tft_panel_power,
215 .clear = qp_tft_panel_clear,
216 .flush = qp_tft_panel_flush,
217 .pixdata = qp_tft_panel_pixdata,
218 .viewport = qp_ili9486_viewport,
219 .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
220 .append_pixels = qp_tft_panel_append_pixels_rgb565,
221 .append_pixdata = qp_tft_panel_append_pixdata,
222 },
223 .num_window_bytes = 2,
224 .swap_window_coords = false,
225 .opcodes =
226 {
227 .display_on = ILI9XXX_CMD_DISPLAY_ON,
228 .display_off = ILI9XXX_CMD_DISPLAY_OFF,
229 .set_column_address = ILI9XXX_SET_COL_ADDR,
230 .set_row_address = ILI9XXX_SET_PAGE_ADDR,
231 .enable_writes = ILI9XXX_SET_MEM,
232 },
233};
234
235static const painter_comms_with_command_vtable_t spi_comms_odd_cs_pulse_vtable = {
236 .base =
237 {
238 .comms_init = qp_comms_spi_dc_reset_init,
239 .comms_start = qp_comms_spi_start,
240 .comms_send = qp_comms_spi_send_data_odd_cs_pulse,
241 .comms_stop = qp_comms_spi_stop,
242 },
243 .send_command = qp_comms_spi_dc_reset_send_command_odd_cs_pulse,
244 .bulk_command_sequence = qp_comms_spi_send_command_sequence_odd_cs_pulse,
245};
246
247////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
248// SPI
249
250#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE
251
252// Factory function for creating a handle to the ILI9486 device
253painter_device_t qp_ili9486_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
254 for (uint32_t i = 0; i < ILI9486_NUM_DEVICES; ++i) {
255 tft_panel_dc_reset_painter_device_t *driver = &ili9486_drivers[i];
256 if (!driver->base.driver_vtable) {
257 driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9486_driver_vtable;
258 driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable;
259 driver->base.native_bits_per_pixel = 16; // RGB565
260 driver->base.panel_width = panel_width;
261 driver->base.panel_height = panel_height;
262 driver->base.rotation = QP_ROTATION_0;
263 driver->base.offset_x = 0;
264 driver->base.offset_y = 0;
265
266 // SPI and other pin configuration
267 driver->base.comms_config = &driver->spi_dc_reset_config;
268 driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
269 driver->spi_dc_reset_config.spi_config.divisor = spi_divisor;
270 driver->spi_dc_reset_config.spi_config.lsb_first = false;
271 driver->spi_dc_reset_config.spi_config.mode = spi_mode;
272 driver->spi_dc_reset_config.dc_pin = dc_pin;
273 driver->spi_dc_reset_config.reset_pin = reset_pin;
274
275 if (!qp_internal_register_device((painter_device_t)driver)) {
276 memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t));
277 return NULL;
278 }
279
280 return (painter_device_t)driver;
281 }
282 }
283 return NULL;
284}
285
286painter_device_t qp_ili9486_make_spi_waveshare_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
287 painter_device_t device = qp_ili9486_make_spi_device(panel_width, panel_height, chip_select_pin, dc_pin, reset_pin, spi_divisor, spi_mode);
288 if (device) {
289 tft_panel_dc_reset_painter_device_t *driver = (tft_panel_dc_reset_painter_device_t *)device;
290 driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9486_waveshare_driver_vtable;
291 driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_odd_cs_pulse_vtable;
292 }
293 return device;
294}
295
296#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE
297
298////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/ili9xxx/qp_ili9486.h b/drivers/painter/ili9xxx/qp_ili9486.h
new file mode 100644
index 0000000000..9976a78da4
--- /dev/null
+++ b/drivers/painter/ili9xxx/qp_ili9486.h
@@ -0,0 +1,52 @@
1// Copyright 2021 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "gpio.h"
7#include "qp_internal.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10// Quantum Painter ILI9486 configurables (add to your keyboard's config.h)
11
12#ifndef ILI9486_NUM_DEVICES
13/**
14 * @def This controls the maximum number of ILI9486 devices that Quantum Painter can communicate with at any one time.
15 * Increasing this number allows for multiple displays to be used.
16 */
17# define ILI9486_NUM_DEVICES 1
18#endif
19
20////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
21// Quantum Painter ILI9486 device factories
22
23#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE
24/**
25 * Factory method for an ILI9486 SPI LCD device.
26 *
27 * @param panel_width[in] the width of the display panel
28 * @param panel_height[in] the height of the display panel
29 * @param chip_select_pin[in] the GPIO pin used for SPI chip select
30 * @param dc_pin[in] the GPIO pin used for D/C control
31 * @param reset_pin[in] the GPIO pin used for RST
32 * @param spi_divisor[in] the SPI divisor to use when communicating with the display
33 * @param spi_mode[in] the SPI mode to use when communicating with the display
34 * @return the device handle used with all drawing routines in Quantum Painter
35 */
36painter_device_t qp_ili9486_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
37
38/**
39 * Factory method for an ILI9486 SPI LCD device.
40 *
41 * @param panel_width[in] the width of the display panel
42 * @param panel_height[in] the height of the display panel
43 * @param chip_select_pin[in] the GPIO pin used for SPI chip select
44 * @param dc_pin[in] the GPIO pin used for D/C control
45 * @param reset_pin[in] the GPIO pin used for RST
46 * @param spi_divisor[in] the SPI divisor to use when communicating with the display
47 * @param spi_mode[in] the SPI mode to use when communicating with the display
48 * @return the device handle used with all drawing routines in Quantum Painter
49 */
50painter_device_t qp_ili9486_make_spi_waveshare_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
51
52#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE
diff --git a/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h b/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h
index f57e638e03..906f6cd772 100644
--- a/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h
+++ b/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h
@@ -70,6 +70,7 @@
70#define ILI9XXX_SET_LIGHT_CTL_8 0xBF // Set backlight ctl 8 70#define ILI9XXX_SET_LIGHT_CTL_8 0xBF // Set backlight ctl 8
71#define ILI9XXX_SET_POWER_CTL_1 0xC0 // Set power ctl 1 71#define ILI9XXX_SET_POWER_CTL_1 0xC0 // Set power ctl 1
72#define ILI9XXX_SET_POWER_CTL_2 0xC1 // Set power ctl 2 72#define ILI9XXX_SET_POWER_CTL_2 0xC1 // Set power ctl 2
73#define ILI9XXX_SET_POWER_CTL_3 0xC2 // Set power ctl 3
73#define ILI9XXX_SET_VCOM_CTL_1 0xC5 // Set VCOM ctl 1 74#define ILI9XXX_SET_VCOM_CTL_1 0xC5 // Set VCOM ctl 1
74#define ILI9XXX_SET_VCOM_CTL_2 0xC7 // Set VCOM ctl 2 75#define ILI9XXX_SET_VCOM_CTL_2 0xC7 // Set VCOM ctl 2
75#define ILI9XXX_POWER_CTL_A 0xCB // Set power control A 76#define ILI9XXX_POWER_CTL_A 0xCB // Set power control A
diff --git a/quantum/painter/qp.h b/quantum/painter/qp.h
index 873a9d9f32..02acbf589a 100644
--- a/quantum/painter/qp.h
+++ b/quantum/painter/qp.h
@@ -509,6 +509,12 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai
509# define ILI9341_NUM_DEVICES 0 509# define ILI9341_NUM_DEVICES 0
510#endif // QUANTUM_PAINTER_ILI9341_ENABLE 510#endif // QUANTUM_PAINTER_ILI9341_ENABLE
511 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
512#ifdef QUANTUM_PAINTER_ILI9488_ENABLE 518#ifdef QUANTUM_PAINTER_ILI9488_ENABLE
513# include "qp_ili9488.h" 519# include "qp_ili9488.h"
514#else // QUANTUM_PAINTER_ILI9488_ENABLE 520#else // QUANTUM_PAINTER_ILI9488_ENABLE
diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c
index 0e81467e26..1f0f981796 100644
--- a/quantum/painter/qp_internal.c
+++ b/quantum/painter/qp_internal.c
@@ -11,6 +11,7 @@ enum {
11 // NOTE: We intentionally do not include surfaces here, despite them conforming to the same API. 11 // NOTE: We intentionally do not include surfaces here, despite them conforming to the same API.
12 QP_NUM_DEVICES = (ILI9163_NUM_DEVICES) // ILI9163 12 QP_NUM_DEVICES = (ILI9163_NUM_DEVICES) // ILI9163
13 + (ILI9341_NUM_DEVICES) // ILI9341 13 + (ILI9341_NUM_DEVICES) // ILI9341
14 + (ILI9486_NUM_DEVICES) // ILI9486
14 + (ILI9488_NUM_DEVICES) // ILI9488 15 + (ILI9488_NUM_DEVICES) // ILI9488
15 + (ST7789_NUM_DEVICES) // ST7789 16 + (ST7789_NUM_DEVICES) // ST7789
16 + (ST7735_NUM_DEVICES) // ST7735 17 + (ST7735_NUM_DEVICES) // ST7735
diff --git a/quantum/painter/rules.mk b/quantum/painter/rules.mk
index ca81cffb03..d991a6d742 100644
--- a/quantum/painter/rules.mk
+++ b/quantum/painter/rules.mk
@@ -9,6 +9,7 @@ VALID_QUANTUM_PAINTER_DRIVERS := \
9 surface \ 9 surface \
10 ili9163_spi \ 10 ili9163_spi \
11 ili9341_spi \ 11 ili9341_spi \
12 ili9486_spi \
12 ili9488_spi \ 13 ili9488_spi \
13 st7735_spi \ 14 st7735_spi \
14 st7789_spi \ 15 st7789_spi \
@@ -80,6 +81,17 @@ define handle_quantum_painter_driver
80 $(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \ 81 $(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
81 $(DRIVER_PATH)/painter/ili9xxx/qp_ili9341.c \ 82 $(DRIVER_PATH)/painter/ili9xxx/qp_ili9341.c \
82 83
84 else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9486_spi)
85 QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
86 QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
87 OPT_DEFS += -DQUANTUM_PAINTER_ILI9486_ENABLE -DQUANTUM_PAINTER_ILI9486_SPI_ENABLE
88 COMMON_VPATH += \
89 $(DRIVER_PATH)/painter/tft_panel \
90 $(DRIVER_PATH)/painter/ili9xxx
91 SRC += \
92 $(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
93 $(DRIVER_PATH)/painter/ili9xxx/qp_ili9486.c \
94
83 else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9488_spi) 95 else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9488_spi)
84 QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes 96 QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
85 QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes 97 QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes