summaryrefslogtreecommitdiff
path: root/drivers/painter
diff options
context:
space:
mode:
authorQMK Bot <hello@qmk.fm>2025-11-11 12:21:26 +0000
committerQMK Bot <hello@qmk.fm>2025-11-11 12:21:26 +0000
commit019cba746d1408365b906fb9d6163d9b0ab204ec (patch)
treebfbc4c305d5d6e95f69b0912a3b08b2a771090c1 /drivers/painter
parent28eeb92f8eec5b8268d2a74ad0561670d14e189a (diff)
parente7ad19bb953c6f430fb3501386b96962dbe9912c (diff)
Merge remote-tracking branch 'origin/master' into develop
Diffstat (limited to 'drivers/painter')
-rw-r--r--drivers/painter/comms/qp_comms_dummy.c3
-rw-r--r--drivers/painter/comms/qp_comms_i2c.c17
-rw-r--r--drivers/painter/comms/qp_comms_i2c.h2
-rw-r--r--drivers/painter/comms/qp_comms_spi.c10
-rw-r--r--drivers/painter/comms/qp_comms_spi.h6
-rw-r--r--drivers/painter/gc9xxx/qp_gc9107.c8
-rw-r--r--drivers/painter/gc9xxx/qp_gc9a01.c8
-rw-r--r--drivers/painter/ili9xxx/qp_ili9163.c8
-rw-r--r--drivers/painter/ili9xxx/qp_ili9341.c8
-rw-r--r--drivers/painter/ili9xxx/qp_ili9486.c16
-rw-r--r--drivers/painter/ili9xxx/qp_ili9488.c8
-rw-r--r--drivers/painter/ld7032/qp_ld7032.c28
-rw-r--r--drivers/painter/sh1106/qp_sh1106.c3
-rw-r--r--drivers/painter/sh1107/qp_sh1107.c3
-rw-r--r--drivers/painter/ssd1351/qp_ssd1351.c12
-rw-r--r--drivers/painter/st77xx/qp_st7735.c8
-rw-r--r--drivers/painter/st77xx/qp_st7789.c8
17 files changed, 96 insertions, 60 deletions
diff --git a/drivers/painter/comms/qp_comms_dummy.c b/drivers/painter/comms/qp_comms_dummy.c
index 2ed49d2232..7a2aef5d37 100644
--- a/drivers/painter/comms/qp_comms_dummy.c
+++ b/drivers/painter/comms/qp_comms_dummy.c
@@ -15,8 +15,9 @@ static bool dummy_comms_start(painter_device_t device) {
15 return true; 15 return true;
16} 16}
17 17
18static void dummy_comms_stop(painter_device_t device) { 18static bool dummy_comms_stop(painter_device_t device) {
19 // No-op. 19 // No-op.
20 return true;
20} 21}
21 22
22uint32_t dummy_comms_send(painter_device_t device, const void *data, uint32_t byte_count) { 23uint32_t dummy_comms_send(painter_device_t device, const void *data, uint32_t byte_count) {
diff --git a/drivers/painter/comms/qp_comms_i2c.c b/drivers/painter/comms/qp_comms_i2c.c
index 93f503f3dd..f093c87ee4 100644
--- a/drivers/painter/comms/qp_comms_i2c.c
+++ b/drivers/painter/comms/qp_comms_i2c.c
@@ -35,7 +35,9 @@ uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint3
35 return qp_comms_i2c_send_raw(device, data, byte_count); 35 return qp_comms_i2c_send_raw(device, data, byte_count);
36} 36}
37 37
38void qp_comms_i2c_stop(painter_device_t device) {} 38bool qp_comms_i2c_stop(painter_device_t device) {
39 return true;
40}
39 41
40//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 42////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41// Command+Data I2C support 43// Command+Data I2C support
@@ -43,9 +45,9 @@ void qp_comms_i2c_stop(painter_device_t device) {}
43static const uint8_t cmd_byte = 0x00; 45static const uint8_t cmd_byte = 0x00;
44static const uint8_t data_byte = 0x40; 46static const uint8_t data_byte = 0x40;
45 47
46void qp_comms_i2c_cmddata_send_command(painter_device_t device, uint8_t cmd) { 48bool qp_comms_i2c_cmddata_send_command(painter_device_t device, uint8_t cmd) {
47 uint8_t buf[2] = {cmd_byte, cmd}; 49 uint8_t buf[2] = {cmd_byte, cmd};
48 qp_comms_i2c_send_raw(device, &buf, 2); 50 return qp_comms_i2c_send_raw(device, &buf, 2);
49} 51}
50 52
51uint32_t qp_comms_i2c_cmddata_send_data(painter_device_t device, const void *data, uint32_t byte_count) { 53uint32_t qp_comms_i2c_cmddata_send_data(painter_device_t device, const void *data, uint32_t byte_count) {
@@ -58,7 +60,7 @@ uint32_t qp_comms_i2c_cmddata_send_data(painter_device_t device, const void *dat
58 return byte_count; 60 return byte_count;
59} 61}
60 62
61void qp_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { 63bool qp_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
62 uint8_t buf[32]; 64 uint8_t buf[32];
63 for (size_t i = 0; i < sequence_len;) { 65 for (size_t i = 0; i < sequence_len;) {
64 uint8_t command = sequence[i]; 66 uint8_t command = sequence[i];
@@ -67,12 +69,17 @@ void qp_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *
67 buf[0] = cmd_byte; 69 buf[0] = cmd_byte;
68 buf[1] = command; 70 buf[1] = command;
69 memcpy(&buf[2], &sequence[i + 3], num_bytes); 71 memcpy(&buf[2], &sequence[i + 3], num_bytes);
70 qp_comms_i2c_send_raw(device, buf, num_bytes + 2); 72 if (!qp_comms_i2c_send_raw(device, buf, num_bytes + 2)) {
73 return false;
74 }
75
71 if (delay > 0) { 76 if (delay > 0) {
72 wait_ms(delay); 77 wait_ms(delay);
73 } 78 }
74 i += (3 + num_bytes); 79 i += (3 + num_bytes);
75 } 80 }
81
82 return true;
76} 83}
77 84
78const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable = { 85const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable = {
diff --git a/drivers/painter/comms/qp_comms_i2c.h b/drivers/painter/comms/qp_comms_i2c.h
index 70083d6526..06a284dc15 100644
--- a/drivers/painter/comms/qp_comms_i2c.h
+++ b/drivers/painter/comms/qp_comms_i2c.h
@@ -19,7 +19,7 @@ typedef struct qp_comms_i2c_config_t {
19bool qp_comms_i2c_init(painter_device_t device); 19bool qp_comms_i2c_init(painter_device_t device);
20bool qp_comms_i2c_start(painter_device_t device); 20bool qp_comms_i2c_start(painter_device_t device);
21uint32_t qp_comms_i2c_send_data(painter_device_t device, const void* data, uint32_t byte_count); 21uint32_t qp_comms_i2c_send_data(painter_device_t device, const void* data, uint32_t byte_count);
22void qp_comms_i2c_stop(painter_device_t device); 22bool qp_comms_i2c_stop(painter_device_t device);
23 23
24extern const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable; 24extern const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable;
25 25
diff --git a/drivers/painter/comms/qp_comms_spi.c b/drivers/painter/comms/qp_comms_spi.c
index 8f4fc12a3c..bd6f34cdc9 100644
--- a/drivers/painter/comms/qp_comms_spi.c
+++ b/drivers/painter/comms/qp_comms_spi.c
@@ -45,11 +45,12 @@ uint32_t qp_comms_spi_send_data(painter_device_t device, const void *data, uint3
45 return byte_count - bytes_remaining; 45 return byte_count - bytes_remaining;
46} 46}
47 47
48void qp_comms_spi_stop(painter_device_t device) { 48bool qp_comms_spi_stop(painter_device_t device) {
49 painter_driver_t * driver = (painter_driver_t *)device; 49 painter_driver_t * driver = (painter_driver_t *)device;
50 qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config; 50 qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config;
51 spi_stop(); 51 spi_stop();
52 gpio_write_pin_high(comms_config->chip_select_pin); 52 gpio_write_pin_high(comms_config->chip_select_pin);
53 return true;
53} 54}
54 55
55const painter_comms_vtable_t spi_comms_vtable = { 56const painter_comms_vtable_t spi_comms_vtable = {
@@ -97,14 +98,15 @@ uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *da
97 return qp_comms_spi_send_data(device, data, byte_count); 98 return qp_comms_spi_send_data(device, data, byte_count);
98} 99}
99 100
100void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) { 101bool qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) {
101 painter_driver_t * driver = (painter_driver_t *)device; 102 painter_driver_t * driver = (painter_driver_t *)device;
102 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; 103 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
103 gpio_write_pin_low(comms_config->dc_pin); 104 gpio_write_pin_low(comms_config->dc_pin);
104 spi_write(cmd); 105 spi_write(cmd);
106 return true;
105} 107}
106 108
107void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { 109bool qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
108 painter_driver_t * driver = (painter_driver_t *)device; 110 painter_driver_t * driver = (painter_driver_t *)device;
109 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; 111 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
110 for (size_t i = 0; i < sequence_len;) { 112 for (size_t i = 0; i < sequence_len;) {
@@ -126,6 +128,8 @@ void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const
126 } 128 }
127 i += (3 + num_bytes); 129 i += (3 + num_bytes);
128 } 130 }
131
132 return true;
129} 133}
130 134
131const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable = { 135const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable = {
diff --git a/drivers/painter/comms/qp_comms_spi.h b/drivers/painter/comms/qp_comms_spi.h
index c39ea95f72..bb1a841519 100644
--- a/drivers/painter/comms/qp_comms_spi.h
+++ b/drivers/painter/comms/qp_comms_spi.h
@@ -22,7 +22,7 @@ typedef struct qp_comms_spi_config_t {
22bool qp_comms_spi_init(painter_device_t device); 22bool qp_comms_spi_init(painter_device_t device);
23bool qp_comms_spi_start(painter_device_t device); 23bool qp_comms_spi_start(painter_device_t device);
24uint32_t qp_comms_spi_send_data(painter_device_t device, const void* data, uint32_t byte_count); 24uint32_t qp_comms_spi_send_data(painter_device_t device, const void* data, uint32_t byte_count);
25void qp_comms_spi_stop(painter_device_t device); 25bool qp_comms_spi_stop(painter_device_t device);
26 26
27extern const painter_comms_vtable_t spi_comms_vtable; 27extern const painter_comms_vtable_t spi_comms_vtable;
28 28
@@ -39,9 +39,9 @@ typedef struct qp_comms_spi_dc_reset_config_t {
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); 41bool qp_comms_spi_dc_reset_init(painter_device_t device);
42void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd); 42bool qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd);
43uint32_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);
44void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len); 44bool qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len);
45 45
46extern const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable; 46extern const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable;
47 47
diff --git a/drivers/painter/gc9xxx/qp_gc9107.c b/drivers/painter/gc9xxx/qp_gc9107.c
index 108344da4f..f0eb24d0cd 100644
--- a/drivers/painter/gc9xxx/qp_gc9107.c
+++ b/drivers/painter/gc9xxx/qp_gc9107.c
@@ -32,7 +32,9 @@ __attribute__((weak)) bool qp_gc9107_init(painter_device_t device, painter_rotat
32 }; 32 };
33 33
34 // clang-format on 34 // clang-format on
35 qp_comms_bulk_command_sequence(device, gc9107_init_sequence, sizeof(gc9107_init_sequence)); 35 if (!qp_comms_bulk_command_sequence(device, gc9107_init_sequence, sizeof(gc9107_init_sequence))) {
36 return false;
37 }
36 38
37 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 39 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
38 const uint8_t madctl[] = { 40 const uint8_t madctl[] = {
@@ -41,9 +43,7 @@ __attribute__((weak)) bool qp_gc9107_init(painter_device_t device, painter_rotat
41 [QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY, 43 [QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY,
42 [QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY, 44 [QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY,
43 }; 45 };
44 qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]); 46 return qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
45
46 return true;
47} 47}
48 48
49//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 49////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/gc9xxx/qp_gc9a01.c b/drivers/painter/gc9xxx/qp_gc9a01.c
index f037a4cc87..a9b5e4b057 100644
--- a/drivers/painter/gc9xxx/qp_gc9a01.c
+++ b/drivers/painter/gc9xxx/qp_gc9a01.c
@@ -45,7 +45,9 @@ __attribute__((weak)) bool qp_gc9a01_init(painter_device_t device, painter_rotat
45 }; 45 };
46 // clang-format on 46 // clang-format on
47 47
48 qp_comms_bulk_command_sequence(device, gc9a01_init_sequence, sizeof(gc9a01_init_sequence)); 48 if (!qp_comms_bulk_command_sequence(device, gc9a01_init_sequence, sizeof(gc9a01_init_sequence))) {
49 return false;
50 }
49 51
50 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 52 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
51 const uint8_t madctl[] = { 53 const uint8_t madctl[] = {
@@ -54,9 +56,7 @@ __attribute__((weak)) bool qp_gc9a01_init(painter_device_t device, painter_rotat
54 [QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY, 56 [QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY,
55 [QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY, 57 [QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY,
56 }; 58 };
57 qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]); 59 return qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
58
59 return true;
60} 60}
61 61
62//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 62////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/ili9xxx/qp_ili9163.c b/drivers/painter/ili9xxx/qp_ili9163.c
index 7f439dc317..74c5cb28ee 100644
--- a/drivers/painter/ili9xxx/qp_ili9163.c
+++ b/drivers/painter/ili9xxx/qp_ili9163.c
@@ -41,7 +41,9 @@ __attribute__((weak)) bool qp_ili9163_init(painter_device_t device, painter_rota
41 ILI9XXX_CMD_DISPLAY_ON, 20, 0 41 ILI9XXX_CMD_DISPLAY_ON, 20, 0
42 }; 42 };
43 // clang-format on 43 // clang-format on
44 qp_comms_bulk_command_sequence(device, ili9163_init_sequence, sizeof(ili9163_init_sequence)); 44 if (!qp_comms_bulk_command_sequence(device, ili9163_init_sequence, sizeof(ili9163_init_sequence))) {
45 return false;
46 }
45 47
46 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 48 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
47 const uint8_t madctl[] = { 49 const uint8_t madctl[] = {
@@ -50,9 +52,7 @@ __attribute__((weak)) bool qp_ili9163_init(painter_device_t device, painter_rota
50 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MY, 52 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MY,
51 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY, 53 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY,
52 }; 54 };
53 qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]); 55 return qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
54
55 return true;
56} 56}
57 57
58//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 58////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/ili9xxx/qp_ili9341.c b/drivers/painter/ili9xxx/qp_ili9341.c
index a101b292aa..4ca22d8a73 100644
--- a/drivers/painter/ili9xxx/qp_ili9341.c
+++ b/drivers/painter/ili9xxx/qp_ili9341.c
@@ -48,7 +48,9 @@ __attribute__((weak)) bool qp_ili9341_init(painter_device_t device, painter_rota
48 ILI9XXX_CMD_DISPLAY_ON, 20, 0 48 ILI9XXX_CMD_DISPLAY_ON, 20, 0
49 }; 49 };
50 // clang-format on 50 // clang-format on
51 qp_comms_bulk_command_sequence(device, ili9341_init_sequence, sizeof(ili9341_init_sequence)); 51 if (!qp_comms_bulk_command_sequence(device, ili9341_init_sequence, sizeof(ili9341_init_sequence))) {
52 return false;
53 }
52 54
53 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 55 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
54 const uint8_t madctl[] = { 56 const uint8_t madctl[] = {
@@ -57,9 +59,7 @@ __attribute__((weak)) bool qp_ili9341_init(painter_device_t device, painter_rota
57 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MY, 59 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MY,
58 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY, 60 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY,
59 }; 61 };
60 qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]); 62 return qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
61
62 return true;
63} 63}
64 64
65//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 65////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/ili9xxx/qp_ili9486.c b/drivers/painter/ili9xxx/qp_ili9486.c
index 5a2e226668..e29cdf8675 100644
--- a/drivers/painter/ili9xxx/qp_ili9486.c
+++ b/drivers/painter/ili9xxx/qp_ili9486.c
@@ -37,7 +37,9 @@ bool qp_ili9486_init(painter_device_t device, painter_rotation_t rotation) {
37 ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02, 37 ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02,
38 }; 38 };
39 // clang-format on 39 // clang-format on
40 qp_comms_bulk_command_sequence(device, ili9486_init_sequence, sizeof(ili9486_init_sequence)); 40 if (!qp_comms_bulk_command_sequence(device, ili9486_init_sequence, sizeof(ili9486_init_sequence))) {
41 return false;
42 }
41 43
42 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 44 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
43 const uint8_t madctl[] = { 45 const uint8_t madctl[] = {
@@ -62,22 +64,22 @@ bool qp_ili9486_init(painter_device_t device, painter_rotation_t rotation) {
62 ILI9XXX_CMD_DISPLAY_ON, 5, 0, 64 ILI9XXX_CMD_DISPLAY_ON, 5, 0,
63 }; 65 };
64 // clang-format on 66 // clang-format on
65 qp_comms_bulk_command_sequence(device, rotation_sequence, sizeof(rotation_sequence)); 67 return qp_comms_bulk_command_sequence(device, rotation_sequence, sizeof(rotation_sequence));
66
67 return true;
68} 68}
69 69
70//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 70////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71// Driver vtable 71// Driver vtable
72 72
73// waveshare variant needs some tweaks due to shift registers 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) { 74static bool 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; 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; 76 qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config;
77 77
78 gpio_write_pin_low(comms_config->spi_config.chip_select_pin); 78 gpio_write_pin_low(comms_config->spi_config.chip_select_pin);
79 qp_comms_spi_dc_reset_send_command(device, cmd); 79 qp_comms_spi_dc_reset_send_command(device, cmd);
80 gpio_write_pin_high(comms_config->spi_config.chip_select_pin); 80 gpio_write_pin_high(comms_config->spi_config.chip_select_pin);
81
82 return true;
81} 83}
82 84
83static uint32_t qp_comms_spi_send_data_odd_cs_pulse(painter_device_t device, const void *data, uint32_t byte_count) { 85static uint32_t qp_comms_spi_send_data_odd_cs_pulse(painter_device_t device, const void *data, uint32_t byte_count) {
@@ -124,7 +126,7 @@ static uint32_t qp_ili9486_send_data_toggling(painter_device_t device, const uin
124 return ret; 126 return ret;
125} 127}
126 128
127static void qp_comms_spi_send_command_sequence_odd_cs_pulse(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { 129static bool 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;) { 130 for (size_t i = 0; i < sequence_len;) {
129 uint8_t command = sequence[i]; 131 uint8_t command = sequence[i];
130 uint8_t delay = sequence[i + 1]; 132 uint8_t delay = sequence[i + 1];
@@ -140,6 +142,8 @@ static void qp_comms_spi_send_command_sequence_odd_cs_pulse(painter_device_t dev
140 } 142 }
141 i += (3 + num_bytes); 143 i += (3 + num_bytes);
142 } 144 }
145
146 return true;
143} 147}
144 148
145static bool qp_ili9486_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) { 149static bool qp_ili9486_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {
diff --git a/drivers/painter/ili9xxx/qp_ili9488.c b/drivers/painter/ili9xxx/qp_ili9488.c
index 63deaf5f2e..fd05db8751 100644
--- a/drivers/painter/ili9xxx/qp_ili9488.c
+++ b/drivers/painter/ili9xxx/qp_ili9488.c
@@ -41,7 +41,9 @@ __attribute__((weak)) bool qp_ili9488_init(painter_device_t device, painter_rota
41 ILI9XXX_CMD_DISPLAY_ON, 20, 0 41 ILI9XXX_CMD_DISPLAY_ON, 20, 0
42 }; 42 };
43 // clang-format on 43 // clang-format on
44 qp_comms_bulk_command_sequence(device, ili9488_init_sequence, sizeof(ili9488_init_sequence)); 44 if (!qp_comms_bulk_command_sequence(device, ili9488_init_sequence, sizeof(ili9488_init_sequence))) {
45 return false;
46 }
45 47
46 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 48 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
47 const uint8_t madctl[] = { 49 const uint8_t madctl[] = {
@@ -50,9 +52,7 @@ __attribute__((weak)) bool qp_ili9488_init(painter_device_t device, painter_rota
50 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX, 52 [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX,
51 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV, 53 [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV,
52 }; 54 };
53 qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]); 55 return qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
54
55 return true;
56} 56}
57 57
58//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 58////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/ld7032/qp_ld7032.c b/drivers/painter/ld7032/qp_ld7032.c
index f43ae8e60d..d73430cc75 100644
--- a/drivers/painter/ld7032/qp_ld7032.c
+++ b/drivers/painter/ld7032/qp_ld7032.c
@@ -10,7 +10,7 @@
10#include "qp_surface.h" 10#include "qp_surface.h"
11#include "qp_surface_internal.h" 11#include "qp_surface_internal.h"
12 12
13typedef void (*ld7032_driver_comms_send_command_and_data_func)(painter_device_t device, uint8_t cmd, uint8_t data); 13typedef bool (*ld7032_driver_comms_send_command_and_data_func)(painter_device_t device, uint8_t cmd, uint8_t data);
14typedef uint32_t (*ld7032_driver_comms_send_command_and_databuf_func)(painter_device_t device, uint8_t cmd, const void *data, uint32_t byte_count); 14typedef uint32_t (*ld7032_driver_comms_send_command_and_databuf_func)(painter_device_t device, uint8_t cmd, const void *data, uint32_t byte_count);
15 15
16typedef struct ld7032_comms_with_command_vtable_t { 16typedef struct ld7032_comms_with_command_vtable_t {
@@ -25,12 +25,13 @@ typedef struct ld7032_comms_with_command_vtable_t {
25// LD7032 Internal API 25// LD7032 Internal API
26//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 26////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
27 27
28void ld7032_comms_i2c_send_command_and_data(painter_device_t device, uint8_t cmd, uint8_t data) { 28#ifdef QUANTUM_PAINTER_LD7032_I2C_ENABLE
29bool ld7032_comms_i2c_send_command_and_data(painter_device_t device, uint8_t cmd, uint8_t data) {
29 uint8_t buf[2] = {cmd, data}; 30 uint8_t buf[2] = {cmd, data};
30 qp_comms_i2c_send_data(device, buf, 2); 31 return qp_comms_i2c_send_data(device, buf, 2);
31} 32}
32 33
33void ld7032_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { 34bool ld7032_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) {
34 uint8_t buf[32]; 35 uint8_t buf[32];
35 for (size_t i = 0; i < sequence_len;) { 36 for (size_t i = 0; i < sequence_len;) {
36 uint8_t command = sequence[i]; 37 uint8_t command = sequence[i];
@@ -38,12 +39,16 @@ void ld7032_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8
38 uint8_t num_bytes = sequence[i + 2]; 39 uint8_t num_bytes = sequence[i + 2];
39 buf[0] = command; 40 buf[0] = command;
40 memcpy(&buf[1], &sequence[i + 3], num_bytes); 41 memcpy(&buf[1], &sequence[i + 3], num_bytes);
41 qp_comms_i2c_send_data(device, buf, num_bytes + 1); 42 if (!qp_comms_i2c_send_data(device, buf, num_bytes + 1)) {
43 return false;
44 }
42 if (delay > 0) { 45 if (delay > 0) {
43 wait_ms(delay); 46 wait_ms(delay);
44 } 47 }
45 i += (3 + num_bytes); 48 i += (3 + num_bytes);
46 } 49 }
50
51 return true;
47} 52}
48 53
49uint32_t ld7032_comms_i2c_send_command_and_databuf(painter_device_t device, uint8_t cmd, const void *data, uint32_t byte_count) { 54uint32_t ld7032_comms_i2c_send_command_and_databuf(painter_device_t device, uint8_t cmd, const void *data, uint32_t byte_count) {
@@ -53,6 +58,7 @@ uint32_t ld7032_comms_i2c_send_command_and_databuf(painter_device_t device, uint
53 memcpy(&buf[1], data, byte_count); 58 memcpy(&buf[1], data, byte_count);
54 return qp_comms_send(device, buf, byte_count + 1); 59 return qp_comms_send(device, buf, byte_count + 1);
55} 60}
61#endif // QUANTUM_PAINTER_LD7032_I2C_ENABLE
56 62
57// Power control 63// Power control
58bool qp_ld7032_power(painter_device_t device, bool power_on) { 64bool qp_ld7032_power(painter_device_t device, bool power_on) {
@@ -201,7 +207,9 @@ __attribute__((weak)) bool qp_ld7032_init(painter_device_t device, painter_rotat
201 }; 207 };
202 // clang-format on 208 // clang-format on
203 209
204 qp_comms_bulk_command_sequence(device, ld7032_init_sequence, sizeof(ld7032_init_sequence)); 210 if (!qp_comms_bulk_command_sequence(device, ld7032_init_sequence, sizeof(ld7032_init_sequence))) {
211 return false;
212 }
205 213
206 uint8_t display_y_start = 40 - driver->oled.base.panel_height; 214 uint8_t display_y_start = 40 - driver->oled.base.panel_height;
207 uint8_t display_x_start = (128 - driver->oled.base.panel_width) / 2; 215 uint8_t display_x_start = (128 - driver->oled.base.panel_width) / 2;
@@ -223,7 +231,9 @@ __attribute__((weak)) bool qp_ld7032_init(painter_device_t device, painter_rotat
223 ld7032_memory_setup[13] = ld7032_memory_setup[4] + 1; 231 ld7032_memory_setup[13] = ld7032_memory_setup[4] + 1;
224 ld7032_memory_setup[17] = driver->oled.base.panel_height; 232 ld7032_memory_setup[17] = driver->oled.base.panel_height;
225 233
226 qp_comms_bulk_command_sequence(device, ld7032_memory_setup, sizeof(ld7032_memory_setup)); 234 if (!qp_comms_bulk_command_sequence(device, ld7032_memory_setup, sizeof(ld7032_memory_setup))) {
235 return false;
236 }
227 237
228 uint8_t write_direction = 0; 238 uint8_t write_direction = 0;
229 switch (rotation) { 239 switch (rotation) {
@@ -245,7 +255,9 @@ __attribute__((weak)) bool qp_ld7032_init(painter_device_t device, painter_rotat
245 painter_driver_t * pdriver = (painter_driver_t *)device; 255 painter_driver_t * pdriver = (painter_driver_t *)device;
246 ld7032_comms_with_command_vtable_t *comms_vtable = (ld7032_comms_with_command_vtable_t *)pdriver->comms_vtable; 256 ld7032_comms_with_command_vtable_t *comms_vtable = (ld7032_comms_with_command_vtable_t *)pdriver->comms_vtable;
247 257
248 comms_vtable->send_command_data(device, LD7032_WRITE_DIRECTION, write_direction); 258 if (!comms_vtable->send_command_data(device, LD7032_WRITE_DIRECTION, write_direction)) {
259 return false;
260 }
249 261
250 qp_ld7032_power(device, true); 262 qp_ld7032_power(device, true);
251 263
diff --git a/drivers/painter/sh1106/qp_sh1106.c b/drivers/painter/sh1106/qp_sh1106.c
index 4117115aec..85da4a973a 100644
--- a/drivers/painter/sh1106/qp_sh1106.c
+++ b/drivers/painter/sh1106/qp_sh1106.c
@@ -71,8 +71,7 @@ __attribute__((weak)) bool qp_sh1106_init(painter_device_t device, painter_rotat
71 sh1106_init_sequence[20] = 0x02; 71 sh1106_init_sequence[20] = 0x02;
72 } 72 }
73 73
74 qp_comms_bulk_command_sequence(device, sh1106_init_sequence, sizeof(sh1106_init_sequence)); 74 return qp_comms_bulk_command_sequence(device, sh1106_init_sequence, sizeof(sh1106_init_sequence));
75 return true;
76} 75}
77 76
78// Screen flush 77// Screen flush
diff --git a/drivers/painter/sh1107/qp_sh1107.c b/drivers/painter/sh1107/qp_sh1107.c
index f4cbd49e40..0b48690803 100644
--- a/drivers/painter/sh1107/qp_sh1107.c
+++ b/drivers/painter/sh1107/qp_sh1107.c
@@ -73,8 +73,7 @@ __attribute__((weak)) bool qp_sh1107_init(painter_device_t device, painter_rotat
73 sh1107_init_sequence[20] = 0x02; 73 sh1107_init_sequence[20] = 0x02;
74 } 74 }
75 75
76 qp_comms_bulk_command_sequence(device, sh1107_init_sequence, sizeof(sh1107_init_sequence)); 76 return qp_comms_bulk_command_sequence(device, sh1107_init_sequence, sizeof(sh1107_init_sequence));
77 return true;
78} 77}
79 78
80// Screen flush 79// Screen flush
diff --git a/drivers/painter/ssd1351/qp_ssd1351.c b/drivers/painter/ssd1351/qp_ssd1351.c
index 3270a362c2..3f652e674e 100644
--- a/drivers/painter/ssd1351/qp_ssd1351.c
+++ b/drivers/painter/ssd1351/qp_ssd1351.c
@@ -44,7 +44,9 @@ __attribute__((weak)) bool qp_ssd1351_init(painter_device_t device, painter_rota
44 SSD1351_DISPLAYON, 5, 0, 44 SSD1351_DISPLAYON, 5, 0,
45 }; 45 };
46 // clang-format on 46 // clang-format on
47 qp_comms_bulk_command_sequence(device, ssd1351_init_sequence, sizeof(ssd1351_init_sequence)); 47 if (!qp_comms_bulk_command_sequence(device, ssd1351_init_sequence, sizeof(ssd1351_init_sequence))) {
48 return false;
49 }
48 50
49 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 51 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
50 const uint8_t madctl[] = { 52 const uint8_t madctl[] = {
@@ -53,10 +55,10 @@ __attribute__((weak)) bool qp_ssd1351_init(painter_device_t device, painter_rota
53 [QP_ROTATION_180] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MX, 55 [QP_ROTATION_180] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MX,
54 [QP_ROTATION_270] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MV, 56 [QP_ROTATION_270] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MV,
55 }; 57 };
56 qp_comms_command_databyte(device, SSD1351_SETREMAP, madctl[rotation]); 58 if (!qp_comms_command_databyte(device, SSD1351_SETREMAP, madctl[rotation])) {
57 qp_comms_command_databyte(device, SSD1351_STARTLINE, (rotation == QP_ROTATION_0 || rotation == QP_ROTATION_90) ? driver->base.panel_height : 0); 59 return false;
58 60 }
59 return true; 61 return qp_comms_command_databyte(device, SSD1351_STARTLINE, (rotation == QP_ROTATION_0 || rotation == QP_ROTATION_90) ? driver->base.panel_height : 0);
60} 62}
61 63
62//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 64////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/st77xx/qp_st7735.c b/drivers/painter/st77xx/qp_st7735.c
index 1db0d01dcb..9e3df477c8 100644
--- a/drivers/painter/st77xx/qp_st7735.c
+++ b/drivers/painter/st77xx/qp_st7735.c
@@ -63,7 +63,9 @@ __attribute__((weak)) bool qp_st7735_init(painter_device_t device, painter_rotat
63 ST77XX_CMD_DISPLAY_ON, 20, 0 63 ST77XX_CMD_DISPLAY_ON, 20, 0
64 }; 64 };
65 // clang-format on 65 // clang-format on
66 qp_comms_bulk_command_sequence(device, st7735_init_sequence, sizeof(st7735_init_sequence)); 66 if (!qp_comms_bulk_command_sequence(device, st7735_init_sequence, sizeof(st7735_init_sequence))) {
67 return false;
68 }
67 69
68 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 70 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
69 const uint8_t madctl[] = { 71 const uint8_t madctl[] = {
@@ -72,7 +74,9 @@ __attribute__((weak)) bool qp_st7735_init(painter_device_t device, painter_rotat
72 [QP_ROTATION_180] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MX | ST77XX_MADCTL_MY, 74 [QP_ROTATION_180] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MX | ST77XX_MADCTL_MY,
73 [QP_ROTATION_270] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MV | ST77XX_MADCTL_MY, 75 [QP_ROTATION_270] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MV | ST77XX_MADCTL_MY,
74 }; 76 };
75 qp_comms_command_databyte(device, ST77XX_SET_MADCTL, madctl[rotation]); 77 if (!qp_comms_command_databyte(device, ST77XX_SET_MADCTL, madctl[rotation])) {
78 return false;
79 }
76 80
77#ifndef ST7735_NO_AUTOMATIC_VIEWPORT_OFFSETS 81#ifndef ST7735_NO_AUTOMATIC_VIEWPORT_OFFSETS
78 st7735_automatic_viewport_offsets(device, rotation); 82 st7735_automatic_viewport_offsets(device, rotation);
diff --git a/drivers/painter/st77xx/qp_st7789.c b/drivers/painter/st77xx/qp_st7789.c
index 855a9cc0c8..b4e24886da 100644
--- a/drivers/painter/st77xx/qp_st7789.c
+++ b/drivers/painter/st77xx/qp_st7789.c
@@ -60,7 +60,9 @@ __attribute__((weak)) bool qp_st7789_init(painter_device_t device, painter_rotat
60 ST77XX_CMD_DISPLAY_ON, 20, 0 60 ST77XX_CMD_DISPLAY_ON, 20, 0
61 }; 61 };
62 // clang-format on 62 // clang-format on
63 qp_comms_bulk_command_sequence(device, st7789_init_sequence, sizeof(st7789_init_sequence)); 63 if (!qp_comms_bulk_command_sequence(device, st7789_init_sequence, sizeof(st7789_init_sequence))) {
64 return false;
65 }
64 66
65 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) 67 // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
66 const uint8_t madctl[] = { 68 const uint8_t madctl[] = {
@@ -69,7 +71,9 @@ __attribute__((weak)) bool qp_st7789_init(painter_device_t device, painter_rotat
69 [QP_ROTATION_180] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MX | ST77XX_MADCTL_MY, 71 [QP_ROTATION_180] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MX | ST77XX_MADCTL_MY,
70 [QP_ROTATION_270] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MV | ST77XX_MADCTL_MY, 72 [QP_ROTATION_270] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MV | ST77XX_MADCTL_MY,
71 }; 73 };
72 qp_comms_command_databyte(device, ST77XX_SET_MADCTL, madctl[rotation]); 74 if (!qp_comms_command_databyte(device, ST77XX_SET_MADCTL, madctl[rotation])) {
75 return false;
76 }
73 77
74#ifndef ST7789_NO_AUTOMATIC_VIEWPORT_OFFSETS 78#ifndef ST7789_NO_AUTOMATIC_VIEWPORT_OFFSETS
75 st7789_automatic_viewport_offsets(device, rotation); 79 st7789_automatic_viewport_offsets(device, rotation);