diff --git a/drivers/eeprom/painter/comms/qp_comms_dummy.c b/drivers/eeprom/painter/comms/qp_comms_dummy.c deleted file mode 100644 index 2ed49d2232..0000000000 --- a/drivers/eeprom/painter/comms/qp_comms_dummy.c +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef QUANTUM_PAINTER_DUMMY_COMMS_ENABLE - -# include "qp_comms_dummy.h" - -static bool dummy_comms_init(painter_device_t device) { - // No-op. - return true; -} - -static bool dummy_comms_start(painter_device_t device) { - // No-op. - return true; -} - -static void dummy_comms_stop(painter_device_t device) { - // No-op. -} - -uint32_t dummy_comms_send(painter_device_t device, const void *data, uint32_t byte_count) { - // No-op. - return byte_count; -} - -painter_comms_vtable_t dummy_comms_vtable = { - // These are all effective no-op's because they're not actually needed. - .comms_init = dummy_comms_init, - .comms_start = dummy_comms_start, - .comms_stop = dummy_comms_stop, - .comms_send = dummy_comms_send}; - -#endif // QUANTUM_PAINTER_DUMMY_COMMS_ENABLE diff --git a/drivers/eeprom/painter/comms/qp_comms_dummy.h b/drivers/eeprom/painter/comms/qp_comms_dummy.h deleted file mode 100644 index b2d5d6eea5..0000000000 --- a/drivers/eeprom/painter/comms/qp_comms_dummy.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#ifdef QUANTUM_PAINTER_DUMMY_COMMS_ENABLE - -# include "qp_internal.h" - -extern painter_comms_vtable_t dummy_comms_vtable; - -#endif // QUANTUM_PAINTER_DUMMY_COMMS_ENABLE diff --git a/drivers/eeprom/painter/comms/qp_comms_i2c.c b/drivers/eeprom/painter/comms/qp_comms_i2c.c deleted file mode 100644 index 93f503f3dd..0000000000 --- a/drivers/eeprom/painter/comms/qp_comms_i2c.c +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef QUANTUM_PAINTER_I2C_ENABLE - -# include "i2c_master.h" -# include "qp_comms_i2c.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Helpers - -static uint32_t qp_comms_i2c_send_raw(painter_device_t device, const void *data, uint32_t byte_count) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_i2c_config_t *comms_config = (qp_comms_i2c_config_t *)driver->comms_config; - i2c_status_t res = i2c_transmit(comms_config->chip_address << 1, data, byte_count, I2C_TIMEOUT); - if (res < 0) { - return 0; - } - return byte_count; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Base I2C support - -bool qp_comms_i2c_init(painter_device_t device) { - i2c_init(); - return true; -} - -bool qp_comms_i2c_start(painter_device_t device) { - return true; -} - -uint32_t qp_comms_i2c_send_data(painter_device_t device, const void *data, uint32_t byte_count) { - return qp_comms_i2c_send_raw(device, data, byte_count); -} - -void qp_comms_i2c_stop(painter_device_t device) {} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Command+Data I2C support - -static const uint8_t cmd_byte = 0x00; -static const uint8_t data_byte = 0x40; - -void qp_comms_i2c_cmddata_send_command(painter_device_t device, uint8_t cmd) { - uint8_t buf[2] = {cmd_byte, cmd}; - qp_comms_i2c_send_raw(device, &buf, 2); -} - -uint32_t qp_comms_i2c_cmddata_send_data(painter_device_t device, const void *data, uint32_t byte_count) { - uint8_t buf[1 + byte_count]; - buf[0] = data_byte; - memcpy(&buf[1], data, byte_count); - if (qp_comms_i2c_send_raw(device, buf, sizeof(buf)) != sizeof(buf)) { - return 0; - } - return byte_count; -} - -void qp_comms_i2c_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { - uint8_t buf[32]; - for (size_t i = 0; i < sequence_len;) { - uint8_t command = sequence[i]; - uint8_t delay = sequence[i + 1]; - uint8_t num_bytes = sequence[i + 2]; - buf[0] = cmd_byte; - buf[1] = command; - memcpy(&buf[2], &sequence[i + 3], num_bytes); - qp_comms_i2c_send_raw(device, buf, num_bytes + 2); - if (delay > 0) { - wait_ms(delay); - } - i += (3 + num_bytes); - } -} - -const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable = { - .base = - { - .comms_init = qp_comms_i2c_init, - .comms_start = qp_comms_i2c_start, - .comms_send = qp_comms_i2c_cmddata_send_data, - .comms_stop = qp_comms_i2c_stop, - }, - .send_command = qp_comms_i2c_cmddata_send_command, - .bulk_command_sequence = qp_comms_i2c_bulk_command_sequence, -}; - -#endif // QUANTUM_PAINTER_I2C_ENABLE diff --git a/drivers/eeprom/painter/comms/qp_comms_i2c.h b/drivers/eeprom/painter/comms/qp_comms_i2c.h deleted file mode 100644 index 70083d6526..0000000000 --- a/drivers/eeprom/painter/comms/qp_comms_i2c.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#ifdef QUANTUM_PAINTER_I2C_ENABLE - -# include - -# include "gpio.h" -# include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Base I2C support - -typedef struct qp_comms_i2c_config_t { - uint8_t chip_address; -} qp_comms_i2c_config_t; - -bool qp_comms_i2c_init(painter_device_t device); -bool qp_comms_i2c_start(painter_device_t device); -uint32_t qp_comms_i2c_send_data(painter_device_t device, const void* data, uint32_t byte_count); -void qp_comms_i2c_stop(painter_device_t device); - -extern const painter_comms_with_command_vtable_t i2c_comms_cmddata_vtable; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#endif // QUANTUM_PAINTER_I2C_ENABLE diff --git a/drivers/eeprom/painter/comms/qp_comms_spi.c b/drivers/eeprom/painter/comms/qp_comms_spi.c deleted file mode 100644 index 4e6067394b..0000000000 --- a/drivers/eeprom/painter/comms/qp_comms_spi.c +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef QUANTUM_PAINTER_SPI_ENABLE - -# include "spi_master.h" -# include "qp_comms_spi.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Base SPI support - -bool qp_comms_spi_init(painter_device_t device) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config; - - // Initialize the SPI peripheral - spi_init(); - - // Set up CS as output high - gpio_set_pin_output(comms_config->chip_select_pin); - gpio_write_pin_high(comms_config->chip_select_pin); - - return true; -} - -bool qp_comms_spi_start(painter_device_t device) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config; - - return spi_start(comms_config->chip_select_pin, comms_config->lsb_first, comms_config->mode, comms_config->divisor); -} - -uint32_t qp_comms_spi_send_data(painter_device_t device, const void *data, uint32_t byte_count) { - uint32_t bytes_remaining = byte_count; - const uint8_t *p = (const uint8_t *)data; - const uint32_t max_msg_length = 1024; - - while (bytes_remaining > 0) { - uint32_t bytes_this_loop = QP_MIN(bytes_remaining, max_msg_length); - spi_transmit(p, bytes_this_loop); - p += bytes_this_loop; - bytes_remaining -= bytes_this_loop; - } - - return byte_count - bytes_remaining; -} - -void qp_comms_spi_stop(painter_device_t device) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_config_t *comms_config = (qp_comms_spi_config_t *)driver->comms_config; - spi_stop(); - gpio_write_pin_high(comms_config->chip_select_pin); -} - -const painter_comms_vtable_t spi_comms_vtable = { - .comms_init = qp_comms_spi_init, - .comms_start = qp_comms_spi_start, - .comms_send = qp_comms_spi_send_data, - .comms_stop = qp_comms_spi_stop, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI with D/C and RST pins - -# ifdef QUANTUM_PAINTER_SPI_DC_RESET_ENABLE - -bool qp_comms_spi_dc_reset_init(painter_device_t device) { - if (!qp_comms_spi_init(device)) { - return false; - } - - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - - // Set up D/C as output low, if specified - if (comms_config->dc_pin != NO_PIN) { - gpio_set_pin_output(comms_config->dc_pin); - gpio_write_pin_low(comms_config->dc_pin); - } - - // Set up RST as output, if specified, performing a reset in the process - if (comms_config->reset_pin != NO_PIN) { - gpio_set_pin_output(comms_config->reset_pin); - gpio_write_pin_low(comms_config->reset_pin); - wait_ms(20); - gpio_write_pin_high(comms_config->reset_pin); - wait_ms(20); - } - - return true; -} - -uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void *data, uint32_t byte_count) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - gpio_write_pin_high(comms_config->dc_pin); - return qp_comms_spi_send_data(device, data, byte_count); -} - -void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - gpio_write_pin_low(comms_config->dc_pin); - spi_write(cmd); -} - -void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - for (size_t i = 0; i < sequence_len;) { - uint8_t command = sequence[i]; - uint8_t delay = sequence[i + 1]; - uint8_t num_bytes = sequence[i + 2]; - qp_comms_spi_dc_reset_send_command(device, command); - if (num_bytes > 0) { - if (comms_config->command_params_uses_command_pin) { - for (uint8_t j = 0; j < num_bytes; j++) { - qp_comms_spi_dc_reset_send_command(device, sequence[i + 3 + j]); - } - } else { - qp_comms_spi_dc_reset_send_data(device, &sequence[i + 3], num_bytes); - } - } - if (delay > 0) { - wait_ms(delay); - } - i += (3 + num_bytes); - } -} - -const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable = { - .base = - { - .comms_init = qp_comms_spi_dc_reset_init, - .comms_start = qp_comms_spi_start, - .comms_send = qp_comms_spi_dc_reset_send_data, - .comms_stop = qp_comms_spi_stop, - }, - .send_command = qp_comms_spi_dc_reset_send_command, - .bulk_command_sequence = qp_comms_spi_dc_reset_bulk_command_sequence, -}; - -# endif // QUANTUM_PAINTER_SPI_DC_RESET_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#endif // QUANTUM_PAINTER_SPI_ENABLE diff --git a/drivers/eeprom/painter/comms/qp_comms_spi.h b/drivers/eeprom/painter/comms/qp_comms_spi.h deleted file mode 100644 index c39ea95f72..0000000000 --- a/drivers/eeprom/painter/comms/qp_comms_spi.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#ifdef QUANTUM_PAINTER_SPI_ENABLE - -# include - -# include "gpio.h" -# include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Base SPI support - -typedef struct qp_comms_spi_config_t { - pin_t chip_select_pin; - uint16_t divisor; - bool lsb_first; - int8_t mode; -} qp_comms_spi_config_t; - -bool qp_comms_spi_init(painter_device_t device); -bool qp_comms_spi_start(painter_device_t device); -uint32_t qp_comms_spi_send_data(painter_device_t device, const void* data, uint32_t byte_count); -void qp_comms_spi_stop(painter_device_t device); - -extern const painter_comms_vtable_t spi_comms_vtable; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI with D/C and RST pins - -# ifdef QUANTUM_PAINTER_SPI_DC_RESET_ENABLE - -typedef struct qp_comms_spi_dc_reset_config_t { - qp_comms_spi_config_t spi_config; - pin_t dc_pin; - pin_t reset_pin; - bool command_params_uses_command_pin; // keep D/C held low when sending command sequences for data bytes -} qp_comms_spi_dc_reset_config_t; - -bool qp_comms_spi_dc_reset_init(painter_device_t device); -void qp_comms_spi_dc_reset_send_command(painter_device_t device, uint8_t cmd); -uint32_t qp_comms_spi_dc_reset_send_data(painter_device_t device, const void* data, uint32_t byte_count); -void qp_comms_spi_dc_reset_bulk_command_sequence(painter_device_t device, const uint8_t* sequence, size_t sequence_len); - -extern const painter_comms_with_command_vtable_t spi_comms_with_dc_vtable; - -# endif // QUANTUM_PAINTER_SPI_DC_RESET_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#endif // QUANTUM_PAINTER_SPI_ENABLE diff --git a/drivers/eeprom/painter/gc9a01/qp_gc9a01.c b/drivers/eeprom/painter/gc9a01/qp_gc9a01.c deleted file mode 100644 index fe6fa7a9d0..0000000000 --- a/drivers/eeprom/painter/gc9a01/qp_gc9a01.c +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_gc9a01.h" -#include "qp_gc9a01_opcodes.h" -#include "qp_tft_panel.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver storage -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -tft_panel_dc_reset_painter_device_t gc9a01_drivers[GC9A01_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -__attribute__((weak)) bool qp_gc9a01_init(painter_device_t device, painter_rotation_t rotation) { - // A lot of these "unknown" opcodes are sourced from other OSS projects and are seemingly required for this display to function. - // clang-format off - const uint8_t gc9a01_init_sequence[] = { - // Command, Delay, N, Data[N] - GC9A01_SET_INTER_REG_ENABLE2, 0, 0, - 0xEB, 0, 1, 0x14, - GC9A01_SET_INTER_REG_ENABLE1, 0, 0, - GC9A01_SET_INTER_REG_ENABLE2, 0, 0, - 0xEB, 0, 1, 0x14, - 0x84, 0, 1, 0x40, - 0x85, 0, 1, 0xFF, - 0x86, 0, 1, 0xFF, - 0x87, 0, 1, 0xFF, - 0x88, 0, 1, 0x0A, - 0x89, 0, 1, 0x21, - 0x8a, 0, 1, 0x00, - 0x8b, 0, 1, 0x80, - 0x8c, 0, 1, 0x01, - 0x8d, 0, 1, 0x01, - 0x8e, 0, 1, 0xFF, - 0x8f, 0, 1, 0xFF, - GC9A01_SET_FUNCTION_CTL, 0, 2, 0x00, 0x20, - GC9A01_SET_PIX_FMT, 0, 1, 0x55, - 0x90, 0, 4, 0x08, 0x08, 0x08, 0x08, - 0xBD, 0, 1, 0x06, - 0xBC, 0, 1, 0x00, - 0xFF, 0, 3, 0x60, 0x01, 0x04, - GC9A01_SET_POWER_CTL_2, 0, 1, 0x13, - GC9A01_SET_POWER_CTL_3, 0, 1, 0x13, - GC9A01_SET_POWER_CTL_4, 0, 1, 0x22, - 0xBE, 0, 1, 0x11, - 0xE1, 0, 2, 0x10, 0x0E, - 0xDF, 0, 3, 0x21, 0x0C, 0x02, - GC9A01_SET_GAMMA1, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A, - GC9A01_SET_GAMMA2, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F, - GC9A01_SET_GAMMA3, 0, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A, - GC9A01_SET_GAMMA4, 0, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F, - 0xED, 0, 2, 0x1B, 0x0B, - 0xAE, 0, 1, 0x77, - 0xCD, 0, 1, 0x63, - 0x70, 0, 9, 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03, - GC9A01_SET_FRAME_RATE, 0, 1, 0x34, - 0x62, 0, 12, 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70, - 0x63, 0, 12, 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70, - 0x64, 0, 7, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07, - 0x66, 0, 10, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00, - 0x67, 0, 10, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98, - 0x74, 0, 7, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00, - 0x98, 0, 2, 0x3E, 0x07, - GC9A01_CMD_TEARING_OFF, 0, 0, - GC9A01_CMD_INVERT_OFF, 0, 0, - GC9A01_CMD_SLEEP_OFF, 120, 0, - GC9A01_CMD_DISPLAY_ON, 20, 0 - }; - // clang-format on - - // clang-format on - qp_comms_bulk_command_sequence(device, gc9a01_init_sequence, sizeof(gc9a01_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = GC9A01_MADCTL_BGR, - [QP_ROTATION_90] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MX | GC9A01_MADCTL_MV, - [QP_ROTATION_180] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MX | GC9A01_MADCTL_MY, - [QP_ROTATION_270] = GC9A01_MADCTL_BGR | GC9A01_MADCTL_MV | GC9A01_MADCTL_MY, - }; - qp_comms_command_databyte(device, GC9A01_SET_MEM_ACS_CTL, madctl[rotation]); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const tft_panel_dc_reset_painter_driver_vtable_t gc9a01_driver_vtable = { - .base = - { - .init = qp_gc9a01_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = GC9A01_CMD_DISPLAY_ON, - .display_off = GC9A01_CMD_DISPLAY_OFF, - .set_column_address = GC9A01_SET_COL_ADDR, - .set_row_address = GC9A01_SET_PAGE_ADDR, - .enable_writes = GC9A01_SET_MEM, - }, -}; - -#ifdef QUANTUM_PAINTER_GC9A01_SPI_ENABLE -// Factory function for creating a handle to the ILI9341 device -painter_device_t qp_gc9a01_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) { - for (uint32_t i = 0; i < GC9A01_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &gc9a01_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&gc9a01_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.native_bits_per_pixel = 16; // RGB565 - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_GC9A01_SPI_ENABLE diff --git a/drivers/eeprom/painter/gc9a01/qp_gc9a01.h b/drivers/eeprom/painter/gc9a01/qp_gc9a01.h deleted file mode 100644 index 31a3804b50..0000000000 --- a/drivers/eeprom/painter/gc9a01/qp_gc9a01.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter GC9A01 configurables (add to your keyboard's config.h) - -#ifndef GC9A01_NUM_DEVICES -/** - * @def This controls the maximum number of GC9A01 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define GC9A01_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter GC9A01 device factories - -#ifdef QUANTUM_PAINTER_GC9A01_SPI_ENABLE -/** - * Factory method for an GC9A01 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_gc9a01_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); -#endif // QUANTUM_PAINTER_GC9A01_SPI_ENABLE diff --git a/drivers/eeprom/painter/gc9a01/qp_gc9a01_opcodes.h b/drivers/eeprom/painter/gc9a01/qp_gc9a01_opcodes.h deleted file mode 100644 index 828e42752b..0000000000 --- a/drivers/eeprom/painter/gc9a01/qp_gc9a01_opcodes.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter GC9A01 command opcodes -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Level 1 command opcodes - -#define GC9A01_GET_ID_INFO 0x04 // Get ID information -#define GC9A01_GET_STATUS 0x09 // Get status -#define GC9A01_CMD_SLEEP_ON 0x10 // Enter sleep mode -#define GC9A01_CMD_SLEEP_OFF 0x11 // Exit sleep mode -#define GC9A01_CMD_PARTIAL_ON 0x12 // Enter partial mode -#define GC9A01_CMD_PARTIAL_OFF 0x13 // Exit partial mode -#define GC9A01_CMD_INVERT_ON 0x20 // Enter inverted mode -#define GC9A01_CMD_INVERT_OFF 0x21 // Exit inverted mode -#define GC9A01_CMD_DISPLAY_OFF 0x28 // Disable display -#define GC9A01_CMD_DISPLAY_ON 0x29 // Enable display -#define GC9A01_SET_COL_ADDR 0x2A // Set column address -#define GC9A01_SET_PAGE_ADDR 0x2B // Set page address -#define GC9A01_SET_MEM 0x2C // Set memory -#define GC9A01_SET_PARTIAL_AREA 0x30 // Set partial area -#define GC9A01_SET_VSCROLL 0x33 // Set vertical scroll def -#define GC9A01_CMD_TEARING_ON 0x34 // Tearing line enabled -#define GC9A01_CMD_TEARING_OFF 0x35 // Tearing line disabled -#define GC9A01_SET_MEM_ACS_CTL 0x36 // Set mem access ctl -#define GC9A01_SET_VSCROLL_ADDR 0x37 // Set vscroll start addr -#define GC9A01_CMD_IDLE_OFF 0x38 // Exit idle mode -#define GC9A01_CMD_IDLE_ON 0x39 // Enter idle mode -#define GC9A01_SET_PIX_FMT 0x3A // Set pixel format -#define GC9A01_SET_MEM_CONT 0x3C // Set memory continue -#define GC9A01_SET_TEAR_SCANLINE 0x44 // Set tearing scanline -#define GC9A01_GET_TEAR_SCANLINE 0x45 // Get tearing scanline -#define GC9A01_SET_BRIGHTNESS 0x51 // Set brightness -#define GC9A01_SET_DISPLAY_CTL 0x53 // Set display ctl -#define GC9A01_GET_ID1 0xDA // Get ID1 -#define GC9A01_GET_ID2 0xDB // Get ID2 -#define GC9A01_GET_ID3 0xDC // Get ID3 - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Level 2 command opcodes - -#define GC9A01_SET_RGB_IF_SIG_CTL 0xB0 // RGB IF signal ctl -#define GC9A01_SET_BLANKING_PORCH_CTL 0xB5 // Set blanking porch ctl -#define GC9A01_SET_FUNCTION_CTL 0xB6 // Set function ctl -#define GC9A01_SET_TEARING_EFFECT 0xBA // Set backlight ctl 3 -#define GC9A01_SET_IF_CTL 0xF6 // Set interface control - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Level 3 command opcodes - -#define GC9A01_SET_FRAME_RATE 0xE8 // Set frame rate -#define GC9A01_SET_SPI_2DATA 0xE9 // Set frame rate -#define GC9A01_SET_POWER_CTL_1 0xC1 // Set power ctl 1 -#define GC9A01_SET_POWER_CTL_2 0xC3 // Set power ctl 2 -#define GC9A01_SET_POWER_CTL_3 0xC4 // Set power ctl 3 -#define GC9A01_SET_POWER_CTL_4 0xC9 // Set power ctl 4 -#define GC9A01_SET_POWER_CTL_7 0xA7 // Set power ctl 7 -#define GC9A01_SET_INTER_REG_ENABLE1 0xFE // Enable Inter Register 1 -#define GC9A01_SET_INTER_REG_ENABLE2 0xEF // Enable Inter Register 2 -#define GC9A01_SET_GAMMA1 0xF0 // -#define GC9A01_SET_GAMMA2 0xF1 -#define GC9A01_SET_GAMMA3 0xF2 -#define GC9A01_SET_GAMMA4 0xF3 - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// MADCTL Flags -#define GC9A01_MADCTL_MY 0b10000000 -#define GC9A01_MADCTL_MX 0b01000000 -#define GC9A01_MADCTL_MV 0b00100000 -#define GC9A01_MADCTL_ML 0b00010000 -#define GC9A01_MADCTL_RGB 0b00000000 -#define GC9A01_MADCTL_BGR 0b00001000 -#define GC9A01_MADCTL_MH 0b00000100 diff --git a/drivers/eeprom/painter/generic/qp_surface.h b/drivers/eeprom/painter/generic/qp_surface.h deleted file mode 100644 index a291793649..0000000000 --- a/drivers/eeprom/painter/generic/qp_surface.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter surface helpers - -// Helper for determining buffer size required for a surface -#define SURFACE_REQUIRED_BUFFER_BYTE_SIZE(w, h, bpp) ((((w) * (h) * (bpp)) + 7) / 8) - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter surface configurables (add to your keyboard's config.h) - -#ifndef SURFACE_NUM_DEVICES -/** - * @def This controls the maximum number of surface devices that Quantum Painter can use at any one time. - * Increasing this number allows for multiple framebuffers to be used. Each requires its own RAM allocation. - */ -# define SURFACE_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Forward declarations - -#ifdef QUANTUM_PAINTER_SURFACE_ENABLE - -// Surface struct -struct surface_painter_device_t; -typedef struct surface_painter_device_t surface_painter_device_t; - -/** - * Factory method for an RGB565 surface (aka framebuffer). - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param buffer[in] pointer to a preallocated uint8_t buffer of size `SURFACE_REQUIRED_BUFFER_BYTE_SIZE(panel_width, panel_height, 16)` - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_make_rgb565_surface(uint16_t panel_width, uint16_t panel_height, void *buffer); - -/** - * Factory method for a 1bpp monochrome surface (aka framebuffer). - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param buffer[in] pointer to a preallocated uint8_t buffer of size `SURFACE_REQUIRED_BUFFER_BYTE_SIZE(panel_width, panel_height, 1)` - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_make_mono1bpp_surface(uint16_t panel_width, uint16_t panel_height, void *buffer); - -/** - * Helper method to draw the contents of the framebuffer to the target device. - * - * After successful completion, the dirty area is reset. - * - * @param surface[in] the surface to copy from - * @param target[in] the target device to copy into - * @param x[in] the x-location of the original position of the framebuffer - * @param y[in] the y-location of the original position of the framebuffer - * @param entire_surface[in] whether the entire surface should be drawn, instead of just the dirty region - * @return whether the draw operation completed successfully - */ -bool qp_surface_draw(painter_device_t surface, painter_device_t target, uint16_t x, uint16_t y, bool entire_surface); - -#endif // QUANTUM_PAINTER_SURFACE_ENABLE diff --git a/drivers/eeprom/painter/generic/qp_surface_common.c b/drivers/eeprom/painter/generic/qp_surface_common.c deleted file mode 100644 index 2da96c73ac..0000000000 --- a/drivers/eeprom/painter/generic/qp_surface_common.c +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "color.h" -#include "qp_draw.h" -#include "qp_surface_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver storage - -surface_painter_device_t surface_drivers[SURFACE_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Helpers - -void qp_surface_increment_pixdata_location(surface_viewport_data_t *viewport) { - // Increment the X-position - viewport->pixdata_x++; - - // If the x-coord has gone past the right-side edge, loop it back around and increment the y-coord - if (viewport->pixdata_x > viewport->viewport_r) { - viewport->pixdata_x = viewport->viewport_l; - viewport->pixdata_y++; - } - - // If the y-coord has gone past the bottom, loop it back to the top - if (viewport->pixdata_y > viewport->viewport_b) { - viewport->pixdata_y = viewport->viewport_t; - } -} - -void qp_surface_update_dirty(surface_dirty_data_t *dirty, uint16_t x, uint16_t y) { - // Maintain dirty region - if (dirty->l > x) { - dirty->l = x; - dirty->is_dirty = true; - } - if (dirty->r < x) { - dirty->r = x; - dirty->is_dirty = true; - } - if (dirty->t > y) { - dirty->t = y; - dirty->is_dirty = true; - } - if (dirty->b < y) { - dirty->b = y; - dirty->is_dirty = true; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -bool qp_surface_init(painter_device_t device, painter_rotation_t rotation) { - painter_driver_t * driver = (painter_driver_t *)device; - surface_painter_device_t *surface = (surface_painter_device_t *)driver; - memset(surface->buffer, 0, SURFACE_REQUIRED_BUFFER_BYTE_SIZE(driver->panel_width, driver->panel_height, driver->native_bits_per_pixel)); - - surface->dirty.l = 0; - surface->dirty.t = 0; - surface->dirty.r = surface->base.panel_width - 1; - surface->dirty.b = surface->base.panel_height - 1; - surface->dirty.is_dirty = true; - - return true; -} - -bool qp_surface_power(painter_device_t device, bool power_on) { - // No-op. - return true; -} - -bool qp_surface_clear(painter_device_t device) { - painter_driver_t *driver = (painter_driver_t *)device; - driver->driver_vtable->init(device, driver->rotation); // Re-init the surface - return true; -} - -bool qp_surface_flush(painter_device_t device) { - painter_driver_t * driver = (painter_driver_t *)device; - surface_painter_device_t *surface = (surface_painter_device_t *)driver; - surface->dirty.l = surface->dirty.t = UINT16_MAX; - surface->dirty.r = surface->dirty.b = 0; - surface->dirty.is_dirty = false; - return true; -} - -bool qp_surface_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) { - painter_driver_t * driver = (painter_driver_t *)device; - surface_painter_device_t *surface = (surface_painter_device_t *)driver; - - // Set the viewport locations - surface->viewport.viewport_l = left; - surface->viewport.viewport_t = top; - surface->viewport.viewport_r = right; - surface->viewport.viewport_b = bottom; - - // Reset the write location to the top left - surface->viewport.pixdata_x = left; - surface->viewport.pixdata_y = top; - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Drawing routine to copy out the dirty region and send it to another device - -bool qp_surface_draw(painter_device_t surface, painter_device_t target, uint16_t x, uint16_t y, bool entire_surface) { - painter_driver_t * surface_driver = (painter_driver_t *)surface; - surface_painter_device_t *surface_handle = (surface_painter_device_t *)surface_driver; - painter_driver_t * target_driver = (painter_driver_t *)target; - - // If we're not dirty... we're done. - if (!surface_handle->dirty.is_dirty) { - qp_dprintf("qp_surface_draw: ok (not dirty, skipping)\n"); - return true; - } - - // If we have incompatible bit depths, drop out - if (surface_driver->native_bits_per_pixel != target_driver->native_bits_per_pixel) { - qp_dprintf("qp_surface_draw: fail (incompatible bpp: surface=%d, target=%d)\n", (int)surface_driver->native_bits_per_pixel, (int)target_driver->native_bits_per_pixel); - return false; - } - - // Offload to the pixdata transfer function - surface_painter_driver_vtable_t *vtable = (surface_painter_driver_vtable_t *)surface_driver->driver_vtable; - bool ok = vtable->target_pixdata_transfer(surface_driver, target_driver, x, y, entire_surface); - if (!ok) { - qp_dprintf("qp_surface_draw: fail (could not transfer pixel data)\n"); - return false; - } - - // Clear the dirty info for the surface - ok = qp_flush(surface); - if (!ok) { - qp_dprintf("qp_surface_draw: fail (could not flush)\n"); - return false; - } - qp_dprintf("qp_surface_draw: ok\n"); - return true; -} diff --git a/drivers/eeprom/painter/generic/qp_surface_internal.h b/drivers/eeprom/painter/generic/qp_surface_internal.h deleted file mode 100644 index 71f82e924d..0000000000 --- a/drivers/eeprom/painter/generic/qp_surface_internal.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#ifdef QUANTUM_PAINTER_SURFACE_ENABLE - -# include "qp_surface.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Internal declarations - -// Surface vtable -typedef struct surface_painter_driver_vtable_t { - painter_driver_vtable_t base; // must be first, so it can be cast to/from the painter_driver_vtable_t* type - - bool (*target_pixdata_transfer)(painter_driver_t *surface_driver, painter_driver_t *target_driver, uint16_t x, uint16_t y, bool entire_surface); -} surface_painter_driver_vtable_t; - -typedef struct surface_dirty_data_t { - bool is_dirty; - uint16_t l; - uint16_t t; - uint16_t r; - uint16_t b; -} surface_dirty_data_t; - -typedef struct surface_viewport_data_t { - // Manually manage the viewport for streaming pixel data to the display - uint16_t viewport_l; - uint16_t viewport_t; - uint16_t viewport_r; - uint16_t viewport_b; - - // Current write location to the display when streaming pixel data - uint16_t pixdata_x; - uint16_t pixdata_y; -} surface_viewport_data_t; - -// Surface struct -typedef struct surface_painter_device_t { - painter_driver_t base; // must be first, so it can be cast to/from the painter_device_t* type - - // The target buffer - union { - void * buffer; - uint8_t * u8buffer; - uint16_t *u16buffer; - }; - - // Manually manage the viewport for streaming pixel data to the display - surface_viewport_data_t viewport; - - // Maintain a dirty region so we can stream only what we need - surface_dirty_data_t dirty; -} surface_painter_device_t; - -/** - * Factory method for an RGB565 surface (aka framebuffer). Accepts an external device table. - * - * @param device_table[in] the table of devices to use for instantiation - * @param device_table_len[in] the length of the table of devices - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param buffer[in] pointer to a preallocated uint8_t buffer of size `SURFACE_REQUIRED_BUFFER_BYTE_SIZE(panel_width, panel_height, 16)` - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_make_rgb565_surface_advanced(surface_painter_device_t *device_table, size_t device_table_len, uint16_t panel_width, uint16_t panel_height, void *buffer); - -/** - * Factory method for a 1bpp monochrome surface (aka framebuffer). - * - * @param device_table[in] the table of devices to use for instantiation - * @param device_table_len[in] the length of the table of devices - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param buffer[in] pointer to a preallocated uint8_t buffer of size `SURFACE_REQUIRED_BUFFER_BYTE_SIZE(panel_width, panel_height, 16)` - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_make_mono1bpp_surface_advanced(surface_painter_device_t *device_table, size_t device_table_len, uint16_t panel_width, uint16_t panel_height, void *buffer); - -// Driver storage -extern surface_painter_device_t surface_drivers[SURFACE_NUM_DEVICES]; - -// Surface common APIs -bool qp_surface_init(painter_device_t device, painter_rotation_t rotation); -bool qp_surface_power(painter_device_t device, bool power_on); -bool qp_surface_clear(painter_device_t device); -bool qp_surface_flush(painter_device_t device); -bool qp_surface_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom); -void qp_surface_increment_pixdata_location(surface_viewport_data_t *viewport); -void qp_surface_update_dirty(surface_dirty_data_t *dirty, uint16_t x, uint16_t y); - -#endif // QUANTUM_PAINTER_SURFACE_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Factory functions for creating a handle to a surface - -#define SURFACE_FACTORY_FUNCTION_IMPL(function_name, vtable, bpp) \ - painter_device_t(function_name##_advanced)(surface_painter_device_t * device_table, size_t device_table_len, uint16_t panel_width, uint16_t panel_height, void *buffer) { \ - for (uint32_t i = 0; i < device_table_len; ++i) { \ - surface_painter_device_t *driver = &device_table[i]; \ - if (!driver->base.driver_vtable) { \ - driver->base.driver_vtable = (painter_driver_vtable_t *)&(vtable); \ - driver->base.native_bits_per_pixel = (bpp); \ - driver->base.comms_vtable = &dummy_comms_vtable; \ - driver->base.panel_width = panel_width; \ - driver->base.panel_height = panel_height; \ - driver->base.rotation = QP_ROTATION_0; \ - driver->base.offset_x = 0; \ - driver->base.offset_y = 0; \ - driver->buffer = buffer; \ - return (painter_device_t)driver; \ - } \ - } \ - return NULL; \ - } \ - painter_device_t(function_name)(uint16_t panel_width, uint16_t panel_height, void *buffer) { \ - return (function_name##_advanced)(surface_drivers, SURFACE_NUM_DEVICES, panel_width, panel_height, buffer); \ - } diff --git a/drivers/eeprom/painter/generic/qp_surface_mono1bpp.c b/drivers/eeprom/painter/generic/qp_surface_mono1bpp.c deleted file mode 100644 index c66b56519d..0000000000 --- a/drivers/eeprom/painter/generic/qp_surface_mono1bpp.c +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef QUANTUM_PAINTER_SURFACE_ENABLE - -# include "color.h" -# include "qp_draw.h" -# include "qp_surface_internal.h" -# include "qp_comms_dummy.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Surface driver impl: mono1bpp - -static inline void setpixel_mono1bpp(surface_painter_device_t *surface, uint16_t x, uint16_t y, bool mono_pixel) { - uint16_t w = surface->base.panel_width; - uint16_t h = surface->base.panel_height; - - // Drop out if it's off-screen - if (x >= w || y >= h) { - return; - } - - // Figure out which location needs to be updated - uint32_t pixel_num = y * w + x; - uint32_t byte_offset = pixel_num / 8; - uint8_t bit_offset = pixel_num % 8; - bool curr_val = (surface->u8buffer[byte_offset] & (1 << bit_offset)) ? true : false; - - // Skip messing with the dirty info if the original value already matches - if (curr_val != mono_pixel) { - // Update the dirty region - qp_surface_update_dirty(&surface->dirty, x, y); - - // Update the pixel data in the buffer - if (mono_pixel) { - surface->u8buffer[byte_offset] |= (1 << bit_offset); - } else { - surface->u8buffer[byte_offset] &= ~(1 << bit_offset); - } - } -} - -static inline void append_pixel_mono1bpp(surface_painter_device_t *surface, bool mono_pixel) { - setpixel_mono1bpp(surface, surface->viewport.pixdata_x, surface->viewport.pixdata_y, mono_pixel); - qp_surface_increment_pixdata_location(&surface->viewport); -} - -static inline void stream_pixdata_mono1bpp(surface_painter_device_t *surface, const uint8_t *data, uint32_t native_pixel_count) { - for (uint32_t pixel_counter = 0; pixel_counter < native_pixel_count; ++pixel_counter) { - uint32_t byte_offset = pixel_counter / 8; - uint8_t bit_offset = pixel_counter % 8; - append_pixel_mono1bpp(surface, (data[byte_offset] & (1 << bit_offset)) ? true : false); - } -} - -// Stream pixel data to the current write position in GRAM -static bool qp_surface_pixdata_mono1bpp(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) { - painter_driver_t * driver = (painter_driver_t *)device; - surface_painter_device_t *surface = (surface_painter_device_t *)driver; - stream_pixdata_mono1bpp(surface, (const uint8_t *)pixel_data, native_pixel_count); - return true; -} - -// Pixel colour conversion -static bool qp_surface_palette_convert_mono1bpp(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) { - for (int16_t i = 0; i < palette_size; ++i) { - palette[i].mono = (palette[i].hsv888.v > 127) ? 1 : 0; - } - return true; -} - -// Append pixels to the target location, keyed by the pixel index -static bool qp_surface_append_pixels_mono1bpp(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) { - for (uint32_t i = 0; i < pixel_count; ++i) { - uint32_t pixel_num = pixel_offset + i; - uint32_t byte_offset = pixel_num / 8; - uint8_t bit_offset = pixel_num % 8; - if (palette[palette_indices[i]].mono) { - target_buffer[byte_offset] |= (1 << bit_offset); - } else { - target_buffer[byte_offset] &= ~(1 << bit_offset); - } - } - return true; -} - -static bool mono1bpp_target_pixdata_transfer(painter_driver_t *surface_driver, painter_driver_t *target_driver, uint16_t x, uint16_t y, bool entire_surface) { - return false; // Not yet supported. -} - -static bool qp_surface_append_pixdata_mono1bpp(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte) { - return false; // Just use 1bpp images. -} - -const surface_painter_driver_vtable_t mono1bpp_surface_driver_vtable = { - .base = - { - .init = qp_surface_init, - .power = qp_surface_power, - .clear = qp_surface_clear, - .flush = qp_surface_flush, - .pixdata = qp_surface_pixdata_mono1bpp, - .viewport = qp_surface_viewport, - .palette_convert = qp_surface_palette_convert_mono1bpp, - .append_pixels = qp_surface_append_pixels_mono1bpp, - .append_pixdata = qp_surface_append_pixdata_mono1bpp, - }, - .target_pixdata_transfer = mono1bpp_target_pixdata_transfer, -}; - -SURFACE_FACTORY_FUNCTION_IMPL(qp_make_mono1bpp_surface, mono1bpp_surface_driver_vtable, 1); - -#endif // QUANTUM_PAINTER_SURFACE_ENABLE diff --git a/drivers/eeprom/painter/generic/qp_surface_rgb565.c b/drivers/eeprom/painter/generic/qp_surface_rgb565.c deleted file mode 100644 index 8883ed541d..0000000000 --- a/drivers/eeprom/painter/generic/qp_surface_rgb565.c +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2022 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef QUANTUM_PAINTER_SURFACE_ENABLE - -# include "color.h" -# include "qp_draw.h" -# include "qp_surface_internal.h" -# include "qp_comms_dummy.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Surface driver impl: rgb565 - -static inline void setpixel_rgb565(surface_painter_device_t *surface, uint16_t x, uint16_t y, uint16_t rgb565) { - uint16_t w = surface->base.panel_width; - uint16_t h = surface->base.panel_height; - - // Drop out if it's off-screen - if (x >= w || y >= h) { - return; - } - - // Skip messing with the dirty info if the original value already matches - if (surface->u16buffer[y * w + x] != rgb565) { - // Update the dirty region - qp_surface_update_dirty(&surface->dirty, x, y); - - // Update the pixel data in the buffer - surface->u16buffer[y * w + x] = rgb565; - } -} - -static inline void append_pixel_rgb565(surface_painter_device_t *surface, uint16_t rgb565) { - setpixel_rgb565(surface, surface->viewport.pixdata_x, surface->viewport.pixdata_y, rgb565); - qp_surface_increment_pixdata_location(&surface->viewport); -} - -static inline void stream_pixdata_rgb565(surface_painter_device_t *surface, const uint16_t *data, uint32_t native_pixel_count) { - for (uint32_t pixel_counter = 0; pixel_counter < native_pixel_count; ++pixel_counter) { - append_pixel_rgb565(surface, data[pixel_counter]); - } -} - -// Stream pixel data to the current write position in GRAM -static bool qp_surface_pixdata_rgb565(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) { - painter_driver_t * driver = (painter_driver_t *)device; - surface_painter_device_t *surface = (surface_painter_device_t *)driver; - stream_pixdata_rgb565(surface, (const uint16_t *)pixel_data, native_pixel_count); - return true; -} - -// Pixel colour conversion -static bool qp_surface_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) { - for (int16_t i = 0; i < palette_size; ++i) { - RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v}); - uint16_t rgb565 = (((uint16_t)rgb.r) >> 3) << 11 | (((uint16_t)rgb.g) >> 2) << 5 | (((uint16_t)rgb.b) >> 3); - palette[i].rgb565 = __builtin_bswap16(rgb565); - } - return true; -} - -// Append pixels to the target location, keyed by the pixel index -static bool qp_surface_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) { - uint16_t *buf = (uint16_t *)target_buffer; - for (uint32_t i = 0; i < pixel_count; ++i) { - buf[pixel_offset + i] = palette[palette_indices[i]].rgb565; - } - return true; -} - -static bool rgb565_target_pixdata_transfer(painter_driver_t *surface_driver, painter_driver_t *target_driver, uint16_t x, uint16_t y, bool entire_surface) { - surface_painter_device_t *surface_handle = (surface_painter_device_t *)surface_driver; - - uint16_t l = entire_surface ? 0 : surface_handle->dirty.l; - uint16_t t = entire_surface ? 0 : surface_handle->dirty.t; - uint16_t r = entire_surface ? (surface_handle->base.panel_width - 1) : surface_handle->dirty.r; - uint16_t b = entire_surface ? (surface_handle->base.panel_height - 1) : surface_handle->dirty.b; - - // Set the target drawing area - bool ok = qp_viewport((painter_device_t)target_driver, x + l, y + t, x + r, y + b); - if (!ok) { - qp_dprintf("rgb565_target_pixdata_transfer: fail (could not set target viewport)\n"); - return false; - } - - // Housekeeping of the amount of pixels to transfer - uint32_t total_pixel_count = (8 * QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE) / surface_driver->native_bits_per_pixel; - uint32_t pixel_counter = 0; - uint16_t *target_buffer = (uint16_t *)qp_internal_global_pixdata_buffer; - - // Fill the global pixdata area so that we can start transferring to the panel - for (uint16_t y = t; y <= b; ++y) { - for (uint16_t x = l; x <= r; ++x) { - // Update the target buffer - target_buffer[pixel_counter++] = surface_handle->u16buffer[y * surface_handle->base.panel_width + x]; - - // If we've accumulated enough data, send it - if (pixel_counter == total_pixel_count) { - ok = qp_pixdata((painter_device_t)target_driver, qp_internal_global_pixdata_buffer, pixel_counter); - if (!ok) { - qp_dprintf("rgb565_target_pixdata_transfer: fail (could not stream pixdata to target)\n"); - return false; - } - // Reset the counter - pixel_counter = 0; - } - } - } - - // If there's any leftover data, send it - if (pixel_counter > 0) { - ok = qp_pixdata((painter_device_t)target_driver, qp_internal_global_pixdata_buffer, pixel_counter); - if (!ok) { - qp_dprintf("rgb565_target_pixdata_transfer: fail (could not stream pixdata to target)\n"); - return false; - } - } - - return true; -} - -static bool qp_surface_append_pixdata_rgb565(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte) { - target_buffer[pixdata_offset] = pixdata_byte; - return true; -} - -const surface_painter_driver_vtable_t rgb565_surface_driver_vtable = { - .base = - { - .init = qp_surface_init, - .power = qp_surface_power, - .clear = qp_surface_clear, - .flush = qp_surface_flush, - .pixdata = qp_surface_pixdata_rgb565, - .viewport = qp_surface_viewport, - .palette_convert = qp_surface_palette_convert_rgb565_swapped, - .append_pixels = qp_surface_append_pixels_rgb565, - .append_pixdata = qp_surface_append_pixdata_rgb565, - }, - .target_pixdata_transfer = rgb565_target_pixdata_transfer, -}; - -SURFACE_FACTORY_FUNCTION_IMPL(qp_make_rgb565_surface, rgb565_surface_driver_vtable, 16); - -#endif // QUANTUM_PAINTER_SURFACE_ENABLE diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9163.c b/drivers/eeprom/painter/ili9xxx/qp_ili9163.c deleted file mode 100644 index 7f439dc317..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9163.c +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2021-2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_ili9163.h" -#include "qp_ili9xxx_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_ILI9163_SPI_ENABLE -# include "qp_comms_spi.h" -#endif // QUANTUM_PAINTER_ILI9163_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t ili9163_drivers[ILI9163_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -__attribute__((weak)) bool qp_ili9163_init(painter_device_t device, painter_rotation_t rotation) { - // clang-format off - const uint8_t ili9163_init_sequence[] = { - // Command, Delay, N, Data[N] - ILI9XXX_CMD_RESET, 120, 0, - ILI9XXX_CMD_SLEEP_OFF, 5, 0, - ILI9XXX_SET_PIX_FMT, 0, 1, 0x55, - ILI9XXX_SET_GAMMA, 0, 1, 0x04, - ILI9XXX_ENABLE_3_GAMMA, 0, 1, 0x01, - ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0xFF, 0x06, - ILI9XXX_SET_PGAMMA, 0, 15, 0x36, 0x29, 0x12, 0x22, 0x1C, 0x15, 0x42, 0xB7, 0x2F, 0x13, 0x12, 0x0A, 0x11, 0x0B, 0x06, - ILI9XXX_SET_NGAMMA, 0, 15, 0x09, 0x16, 0x2D, 0x0D, 0x13, 0x15, 0x40, 0x48, 0x53, 0x0C, 0x1D, 0x25, 0x2E, 0x34, 0x39, - ILI9XXX_SET_FRAME_CTL_NORMAL, 0, 2, 0x08, 0x02, - ILI9XXX_SET_POWER_CTL_1, 0, 2, 0x0A, 0x02, - ILI9XXX_SET_POWER_CTL_2, 0, 1, 0x02, - ILI9XXX_SET_VCOM_CTL_1, 0, 2, 0x50, 0x63, - ILI9XXX_SET_VCOM_CTL_2, 0, 1, 0x00, - ILI9XXX_CMD_PARTIAL_OFF, 0, 0, - ILI9XXX_CMD_DISPLAY_ON, 20, 0 - }; - // clang-format on - qp_comms_bulk_command_sequence(device, ili9163_init_sequence, sizeof(ili9163_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = ILI9XXX_MADCTL_BGR, - [QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MV, - [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MY, - [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY, - }; - qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -const tft_panel_dc_reset_painter_driver_vtable_t ili9163_driver_vtable = { - .base = - { - .init = qp_ili9163_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ILI9XXX_CMD_DISPLAY_ON, - .display_off = ILI9XXX_CMD_DISPLAY_OFF, - .set_column_address = ILI9XXX_SET_COL_ADDR, - .set_row_address = ILI9XXX_SET_PAGE_ADDR, - .enable_writes = ILI9XXX_SET_MEM, - }, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_ILI9163_SPI_ENABLE - -// Factory function for creating a handle to the ILI9163 device -painter_device_t qp_ili9163_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) { - for (uint32_t i = 0; i < ILI9163_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &ili9163_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9163_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - driver->base.native_bits_per_pixel = 16; // RGB565 - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_ILI9163_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9163.h b/drivers/eeprom/painter/ili9xxx/qp_ili9163.h deleted file mode 100644 index a9b3befd48..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9163.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9163 configurables (add to your keyboard's config.h) - -#ifndef ILI9163_NUM_DEVICES -/** - * @def This controls the maximum number of ILI9163 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define ILI9163_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9163 device factories - -#ifdef QUANTUM_PAINTER_ILI9163_SPI_ENABLE -/** - * Factory method for an ILI9163 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_ili9163_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); -#endif // QUANTUM_PAINTER_ILI9163_SPI_ENABLE diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9341.c b/drivers/eeprom/painter/ili9xxx/qp_ili9341.c deleted file mode 100644 index a101b292aa..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9341.c +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2021-2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_ili9341.h" -#include "qp_ili9xxx_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_ILI9341_SPI_ENABLE -# include -#endif // QUANTUM_PAINTER_ILI9341_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t ili9341_drivers[ILI9341_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -__attribute__((weak)) bool qp_ili9341_init(painter_device_t device, painter_rotation_t rotation) { - // clang-format off - const uint8_t ili9341_init_sequence[] = { - // Command, Delay, N, Data[N] - ILI9XXX_CMD_RESET, 120, 0, - ILI9XXX_CMD_SLEEP_OFF, 5, 0, - ILI9XXX_POWER_CTL_A, 0, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, - ILI9XXX_POWER_CTL_B, 0, 3, 0x00, 0xD9, 0x30, - ILI9XXX_POWER_ON_SEQ_CTL, 0, 4, 0x64, 0x03, 0x12, 0x81, - ILI9XXX_SET_PUMP_RATIO_CTL, 0, 1, 0x20, - ILI9XXX_SET_POWER_CTL_1, 0, 1, 0x26, - ILI9XXX_SET_POWER_CTL_2, 0, 1, 0x11, - ILI9XXX_SET_VCOM_CTL_1, 0, 2, 0x35, 0x3E, - ILI9XXX_SET_VCOM_CTL_2, 0, 1, 0xBE, - ILI9XXX_DRV_TIMING_CTL_A, 0, 3, 0x85, 0x10, 0x7A, - ILI9XXX_DRV_TIMING_CTL_B, 0, 2, 0x00, 0x00, - ILI9XXX_SET_BRIGHTNESS, 0, 1, 0xFF, - ILI9XXX_ENABLE_3_GAMMA, 0, 1, 0x00, - ILI9XXX_SET_GAMMA, 0, 1, 0x01, - ILI9XXX_SET_PGAMMA, 0, 15, 0x0F, 0x29, 0x24, 0x0C, 0x0E, 0x09, 0x4E, 0x78, 0x3C, 0x09, 0x13, 0x05, 0x17, 0x11, 0x00, - ILI9XXX_SET_NGAMMA, 0, 15, 0x00, 0x16, 0x1B, 0x04, 0x11, 0x07, 0x31, 0x33, 0x42, 0x05, 0x0C, 0x0A, 0x28, 0x2F, 0x0F, - ILI9XXX_SET_PIX_FMT, 0, 1, 0x05, - ILI9XXX_SET_FRAME_CTL_NORMAL, 0, 2, 0x00, 0x1B, - ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0x0A, 0xA2, - ILI9XXX_CMD_PARTIAL_OFF, 0, 0, - ILI9XXX_CMD_DISPLAY_ON, 20, 0 - }; - // clang-format on - qp_comms_bulk_command_sequence(device, ili9341_init_sequence, sizeof(ili9341_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = ILI9XXX_MADCTL_BGR, - [QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MV, - [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MY, - [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY, - }; - qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -const tft_panel_dc_reset_painter_driver_vtable_t ili9341_driver_vtable = { - .base = - { - .init = qp_ili9341_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ILI9XXX_CMD_DISPLAY_ON, - .display_off = ILI9XXX_CMD_DISPLAY_OFF, - .set_column_address = ILI9XXX_SET_COL_ADDR, - .set_row_address = ILI9XXX_SET_PAGE_ADDR, - .enable_writes = ILI9XXX_SET_MEM, - }, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_ILI9341_SPI_ENABLE - -// Factory function for creating a handle to the ILI9341 device -painter_device_t qp_ili9341_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) { - for (uint32_t i = 0; i < ILI9341_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &ili9341_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9341_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.native_bits_per_pixel = 16; // RGB565 - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_ILI9341_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9341.h b/drivers/eeprom/painter/ili9xxx/qp_ili9341.h deleted file mode 100644 index d850aba114..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9341.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9341 configurables (add to your keyboard's config.h) - -#ifndef ILI9341_NUM_DEVICES -/** - * @def This controls the maximum number of ILI9341 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define ILI9341_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9341 device factories - -#ifdef QUANTUM_PAINTER_ILI9341_SPI_ENABLE -/** - * Factory method for an ILI9341 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_ili9341_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); -#endif // QUANTUM_PAINTER_ILI9341_SPI_ENABLE diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9486.c b/drivers/eeprom/painter/ili9xxx/qp_ili9486.c deleted file mode 100644 index c4f3c15cec..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9486.c +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// Copyright 2023 Pablo Martinez (@elpekenin) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_ili9486.h" -#include "qp_ili9xxx_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE -# include "spi_master.h" -# include -#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t ili9486_drivers[ILI9486_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -bool qp_ili9486_init(painter_device_t device, painter_rotation_t rotation) { - // clang-format off - const uint8_t ili9486_init_sequence[] = { - // Command, Delay, N, Data[N] - ILI9XXX_CMD_RESET, 120, 0, - ILI9XXX_SET_PIX_FMT, 0, 1, 0x55, - ILI9XXX_SET_PGAMMA, 0, 15, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00, - ILI9XXX_SET_NGAMMA, 0, 15, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00, - ILI9XXX_SET_POWER_CTL_1, 0, 2, 0x0D, 0x0D, - ILI9XXX_SET_POWER_CTL_2, 0, 2, 0x43, 0x00, - ILI9XXX_SET_POWER_CTL_3, 0, 1, 0x00, - ILI9XXX_SET_VCOM_CTL_1, 0, 4, 0x00, 0x48, 0x00, 0x48, - ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02, - }; - // clang-format on - qp_comms_bulk_command_sequence(device, ili9486_init_sequence, sizeof(ili9486_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = ILI9XXX_MADCTL_BGR, - [QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV, - [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR, - [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV, - }; - const uint8_t functl[] = { - [QP_ROTATION_0] = 0x42, - [QP_ROTATION_90] = 0x62, - [QP_ROTATION_180] = 0x22, - [QP_ROTATION_270] = 0x02, - }; - - // clang-format off - uint8_t rotation_sequence[] = { - // Command, Delay, N, Data[N] - ILI9XXX_SET_MEM_ACS_CTL, 0, 1, madctl[rotation], - ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0x00, functl[rotation], - ILI9XXX_CMD_SLEEP_OFF, 5, 0, - ILI9XXX_CMD_DISPLAY_ON, 5, 0, - }; - // clang-format on - qp_comms_bulk_command_sequence(device, rotation_sequence, sizeof(rotation_sequence)); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -// waveshare variant needs some tweaks due to shift registers -static void qp_comms_spi_dc_reset_send_command_odd_cs_pulse(painter_device_t device, uint8_t cmd) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - - writePinLow(comms_config->spi_config.chip_select_pin); - qp_comms_spi_dc_reset_send_command(device, cmd); - writePinHigh(comms_config->spi_config.chip_select_pin); -} - -static uint32_t qp_comms_spi_send_data_odd_cs_pulse(painter_device_t device, const void *data, uint32_t byte_count) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - - uint32_t bytes_remaining = byte_count; - const uint8_t *p = (const uint8_t *)data; - uint32_t max_msg_length = 1024; - - writePinHigh(comms_config->dc_pin); - while (bytes_remaining > 0) { - uint32_t bytes_this_loop = QP_MIN(bytes_remaining, max_msg_length); - bool odd_bytes = bytes_this_loop & 1; - - // send data - writePinLow(comms_config->spi_config.chip_select_pin); - spi_transmit(p, bytes_this_loop); - p += bytes_this_loop; - - // extra CS toggle, for alignment - if (odd_bytes) { - writePinHigh(comms_config->spi_config.chip_select_pin); - writePinLow(comms_config->spi_config.chip_select_pin); - } - - bytes_remaining -= bytes_this_loop; - } - - return byte_count - bytes_remaining; -} - -static uint32_t qp_ili9486_send_data_toggling(painter_device_t device, const uint8_t *data, uint32_t byte_count) { - painter_driver_t * driver = (painter_driver_t *)device; - qp_comms_spi_dc_reset_config_t *comms_config = (qp_comms_spi_dc_reset_config_t *)driver->comms_config; - - uint32_t ret; - for (uint8_t j = 0; j < byte_count; ++j) { - writePinLow(comms_config->spi_config.chip_select_pin); - ret = qp_comms_spi_dc_reset_send_data(device, &data[j], 1); - writePinHigh(comms_config->spi_config.chip_select_pin); - } - - return ret; -} - -static void qp_comms_spi_send_command_sequence_odd_cs_pulse(painter_device_t device, const uint8_t *sequence, size_t sequence_len) { - for (size_t i = 0; i < sequence_len;) { - uint8_t command = sequence[i]; - uint8_t delay = sequence[i + 1]; - uint8_t num_bytes = sequence[i + 2]; - - qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, command); - if (num_bytes > 0) { - qp_ili9486_send_data_toggling(device, &sequence[i + 3], num_bytes); - } - - if (delay > 0) { - wait_ms(delay); - } - i += (3 + num_bytes); - } -} - -static bool qp_ili9486_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) { - painter_driver_t * driver = (painter_driver_t *)device; - tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable; - - // Fix up the drawing location if required - left += driver->offset_x; - right += driver->offset_x; - top += driver->offset_y; - bottom += driver->offset_y; - - // Check if we need to manually swap the window coordinates based on whether or not we're in a sideways rotation - if (vtable->swap_window_coords && (driver->rotation == QP_ROTATION_90 || driver->rotation == QP_ROTATION_270)) { - uint16_t temp; - - temp = left; - left = top; - top = temp; - - temp = right; - right = bottom; - bottom = temp; - } - - // Set up the x-window - uint8_t xbuf[4] = {left >> 8, left & 0xFF, right >> 8, right & 0xFF}; - qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.set_column_address); - qp_ili9486_send_data_toggling(device, xbuf, 4); - - // Set up the y-window - uint8_t ybuf[4] = {top >> 8, top & 0xFF, bottom >> 8, bottom & 0xFF}; - qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.set_row_address); - qp_ili9486_send_data_toggling(device, ybuf, 4); - - // Lock in the window - qp_comms_spi_dc_reset_send_command_odd_cs_pulse(device, vtable->opcodes.enable_writes); - return true; -} - -// Regular -const tft_panel_dc_reset_painter_driver_vtable_t ili9486_driver_vtable = { - .base = - { - .init = qp_ili9486_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ILI9XXX_CMD_DISPLAY_ON, - .display_off = ILI9XXX_CMD_DISPLAY_OFF, - .set_column_address = ILI9XXX_SET_COL_ADDR, - .set_row_address = ILI9XXX_SET_PAGE_ADDR, - .enable_writes = ILI9XXX_SET_MEM, - }, -}; - -// Waveshare tweaks -const tft_panel_dc_reset_painter_driver_vtable_t ili9486_waveshare_driver_vtable = { - .base = - { - .init = qp_ili9486_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_ili9486_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ILI9XXX_CMD_DISPLAY_ON, - .display_off = ILI9XXX_CMD_DISPLAY_OFF, - .set_column_address = ILI9XXX_SET_COL_ADDR, - .set_row_address = ILI9XXX_SET_PAGE_ADDR, - .enable_writes = ILI9XXX_SET_MEM, - }, -}; - -static const painter_comms_with_command_vtable_t spi_comms_odd_cs_pulse_vtable = { - .base = - { - .comms_init = qp_comms_spi_dc_reset_init, - .comms_start = qp_comms_spi_start, - .comms_send = qp_comms_spi_send_data_odd_cs_pulse, - .comms_stop = qp_comms_spi_stop, - }, - .send_command = qp_comms_spi_dc_reset_send_command_odd_cs_pulse, - .bulk_command_sequence = qp_comms_spi_send_command_sequence_odd_cs_pulse, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE - -// Factory function for creating a handle to the ILI9486 device -painter_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) { - for (uint32_t i = 0; i < ILI9486_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &ili9486_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9486_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.native_bits_per_pixel = 16; // RGB565 - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -painter_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) { - painter_device_t device = qp_ili9486_make_spi_device(panel_width, panel_height, chip_select_pin, dc_pin, reset_pin, spi_divisor, spi_mode); - if (device) { - tft_panel_dc_reset_painter_device_t *driver = (tft_panel_dc_reset_painter_device_t *)device; - driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9486_waveshare_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_odd_cs_pulse_vtable; - } - return device; -} - -#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9486.h b/drivers/eeprom/painter/ili9xxx/qp_ili9486.h deleted file mode 100644 index 9976a78da4..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9486.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9486 configurables (add to your keyboard's config.h) - -#ifndef ILI9486_NUM_DEVICES -/** - * @def This controls the maximum number of ILI9486 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define ILI9486_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9486 device factories - -#ifdef QUANTUM_PAINTER_ILI9486_SPI_ENABLE -/** - * Factory method for an ILI9486 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_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); - -/** - * Factory method for an ILI9486 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_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); - -#endif // QUANTUM_PAINTER_ILI9486_SPI_ENABLE diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9488.c b/drivers/eeprom/painter/ili9xxx/qp_ili9488.c deleted file mode 100644 index 63deaf5f2e..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9488.c +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2021-2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_ili9488.h" -#include "qp_ili9xxx_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_ILI9488_SPI_ENABLE -# include -#endif // QUANTUM_PAINTER_ILI9488_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t ili9488_drivers[ILI9488_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -__attribute__((weak)) bool qp_ili9488_init(painter_device_t device, painter_rotation_t rotation) { - // clang-format off - const uint8_t ili9488_init_sequence[] = { - // Command, Delay, N, Data[N] - ILI9XXX_CMD_RESET, 120, 0, - ILI9XXX_SET_PGAMMA, 0, 15, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F, - ILI9XXX_SET_NGAMMA, 0, 15, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F, - ILI9XXX_SET_POWER_CTL_1, 0, 2, 0x17, 0x15, - ILI9XXX_SET_POWER_CTL_2, 0, 1, 0x41, - ILI9XXX_SET_VCOM_CTL_1, 0, 3, 0x00, 0x12, 0x80, - ILI9XXX_SET_PIX_FMT, 0, 1, 0x66, - ILI9XXX_SET_RGB_IF_SIG_CTL, 0, 1, 0x80, - ILI9XXX_SET_FRAME_CTL_NORMAL, 0, 1, 0xA0, - ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02, - ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0x02, 0x02, - ILI9XXX_SET_IMAGE_FUNCTION, 0, 1, 0x00, - ILI9XXX_SET_PUMP_RATIO_CTL, 0, 4, 0xA9, 0x51, 0x2C, 0x82, - ILI9XXX_CMD_SLEEP_OFF, 5, 0, - ILI9XXX_CMD_DISPLAY_ON, 20, 0 - }; - // clang-format on - qp_comms_bulk_command_sequence(device, ili9488_init_sequence, sizeof(ili9488_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MY, - [QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY, - [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX, - [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV, - }; - qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -const tft_panel_dc_reset_painter_driver_vtable_t ili9488_driver_vtable = { - .base = - { - .init = qp_ili9488_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb888, - .append_pixels = qp_tft_panel_append_pixels_rgb888, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ILI9XXX_CMD_DISPLAY_ON, - .display_off = ILI9XXX_CMD_DISPLAY_OFF, - .set_column_address = ILI9XXX_SET_COL_ADDR, - .set_row_address = ILI9XXX_SET_PAGE_ADDR, - .enable_writes = ILI9XXX_SET_MEM, - }, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_ILI9488_SPI_ENABLE - -// Factory function for creating a handle to the ILI9488 device -painter_device_t qp_ili9488_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) { - for (uint32_t i = 0; i < ILI9488_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &ili9488_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&ili9488_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.native_bits_per_pixel = 24; // RGB888 - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_ILI9488_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9488.h b/drivers/eeprom/painter/ili9xxx/qp_ili9488.h deleted file mode 100644 index da56f1090f..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9488.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9488 configurables (add to your keyboard's config.h) - -#ifndef ILI9488_NUM_DEVICES -/** - * @def This controls the maximum number of ILI9488 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define ILI9488_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9488 device factories - -#ifdef QUANTUM_PAINTER_ILI9488_SPI_ENABLE -/** - * Factory method for an ILI9488 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_ili9488_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); -#endif // QUANTUM_PAINTER_ILI9488_SPI_ENABLE diff --git a/drivers/eeprom/painter/ili9xxx/qp_ili9xxx_opcodes.h b/drivers/eeprom/painter/ili9xxx/qp_ili9xxx_opcodes.h deleted file mode 100644 index 906f6cd772..0000000000 --- a/drivers/eeprom/painter/ili9xxx/qp_ili9xxx_opcodes.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ILI9xxx command opcodes -#define ILI9XXX_CMD_NOP 0x00 // No operation -#define ILI9XXX_CMD_RESET 0x01 // Software reset -#define ILI9XXX_GET_ID_INFO 0x04 // Get ID information -#define ILI9XXX_GET_STATUS 0x09 // Get status -#define ILI9XXX_GET_PWR_MODE 0x0A // Get power mode -#define ILI9XXX_GET_MADCTL 0x0B // Get MADCTL -#define ILI9XXX_GET_PIX_FMT 0x0C // Get pixel format -#define ILI9XXX_GET_IMG_FMT 0x0D // Get image format -#define ILI9XXX_GET_SIG_MODE 0x0E // Get signal mode -#define ILI9XXX_GET_SELF_DIAG 0x0F // Get self-diagnostics -#define ILI9XXX_CMD_SLEEP_ON 0x10 // Enter sleep mode -#define ILI9XXX_CMD_SLEEP_OFF 0x11 // Exist sleep mode -#define ILI9XXX_CMD_PARTIAL_ON 0x12 // Enter partial mode -#define ILI9XXX_CMD_PARTIAL_OFF 0x13 // Exit partial mode -#define ILI9XXX_CMD_INVERT_OFF 0x20 // Exit inverted mode -#define ILI9XXX_CMD_INVERT_ON 0x21 // Enter inverted mode -#define ILI9XXX_SET_GAMMA 0x26 // Set gamma params -#define ILI9XXX_CMD_DISPLAY_OFF 0x28 // Disable display -#define ILI9XXX_CMD_DISPLAY_ON 0x29 // Enable display -#define ILI9XXX_SET_COL_ADDR 0x2A // Set column address -#define ILI9XXX_SET_PAGE_ADDR 0x2B // Set page address -#define ILI9XXX_SET_MEM 0x2C // Set memory -#define ILI9XXX_SET_COLOR 0x2D // Set color -#define ILI9XXX_GET_MEM 0x2E // Get memory -#define ILI9XXX_SET_PARTIAL_AREA 0x30 // Set partial area -#define ILI9XXX_SET_VSCROLL 0x33 // Set vertical scroll def -#define ILI9XXX_CMD_TEARING_ON 0x34 // Tearing line enabled -#define ILI9XXX_CMD_TEARING_OFF 0x35 // Tearing line disabled -#define ILI9XXX_SET_MEM_ACS_CTL 0x36 // Set mem access ctl -#define ILI9XXX_SET_VSCROLL_ADDR 0x37 // Set vscroll start addr -#define ILI9XXX_CMD_IDLE_OFF 0x38 // Exit idle mode -#define ILI9XXX_CMD_IDLE_ON 0x39 // Enter idle mode -#define ILI9XXX_SET_PIX_FMT 0x3A // Set pixel format -#define ILI9XXX_SET_MEM_CONT 0x3C // Set memory continue -#define ILI9XXX_GET_MEM_CONT 0x3E // Get memory continue -#define ILI9XXX_SET_TEAR_SCANLINE 0x44 // Set tearing scanline -#define ILI9XXX_GET_TEAR_SCANLINE 0x45 // Get tearing scanline -#define ILI9XXX_SET_BRIGHTNESS 0x51 // Set brightness -#define ILI9XXX_GET_BRIGHTNESS 0x52 // Get brightness -#define ILI9XXX_SET_DISPLAY_CTL 0x53 // Set display ctl -#define ILI9XXX_GET_DISPLAY_CTL 0x54 // Get display ctl -#define ILI9XXX_SET_CABC 0x55 // Set CABC -#define ILI9XXX_GET_CABC 0x56 // Get CABC -#define ILI9XXX_SET_CABC_MIN 0x5E // Set CABC min -#define ILI9XXX_GET_CABC_MIN 0x5F // Set CABC max -#define ILI9XXX_GET_ID1 0xDA // Get ID1 -#define ILI9XXX_GET_ID2 0xDB // Get ID2 -#define ILI9XXX_GET_ID3 0xDC // Get ID3 -#define ILI9XXX_SET_RGB_IF_SIG_CTL 0xB0 // RGB IF signal ctl -#define ILI9XXX_SET_FRAME_CTL_NORMAL 0xB1 // Set frame ctl (normal) -#define ILI9XXX_SET_FRAME_CTL_IDLE 0xB2 // Set frame ctl (idle) -#define ILI9XXX_SET_FRAME_CTL_PARTIAL 0xB3 // Set frame ctl (partial) -#define ILI9XXX_SET_INVERSION_CTL 0xB4 // Set inversion ctl -#define ILI9XXX_SET_BLANKING_PORCH_CTL 0xB5 // Set blanking porch ctl -#define ILI9XXX_SET_FUNCTION_CTL 0xB6 // Set function ctl -#define ILI9XXX_SET_ENTRY_MODE 0xB7 // Set entry mode -#define ILI9XXX_SET_LIGHT_CTL_1 0xB8 // Set backlight ctl 1 -#define ILI9XXX_SET_LIGHT_CTL_2 0xB9 // Set backlight ctl 2 -#define ILI9XXX_SET_LIGHT_CTL_3 0xBA // Set backlight ctl 3 -#define ILI9XXX_SET_LIGHT_CTL_4 0xBB // Set backlight ctl 4 -#define ILI9XXX_SET_LIGHT_CTL_5 0xBC // Set backlight ctl 5 -#define ILI9XXX_SET_LIGHT_CTL_7 0xBE // Set backlight ctl 7 -#define ILI9XXX_SET_LIGHT_CTL_8 0xBF // Set backlight ctl 8 -#define ILI9XXX_SET_POWER_CTL_1 0xC0 // Set power ctl 1 -#define ILI9XXX_SET_POWER_CTL_2 0xC1 // Set power ctl 2 -#define ILI9XXX_SET_POWER_CTL_3 0xC2 // Set power ctl 3 -#define ILI9XXX_SET_VCOM_CTL_1 0xC5 // Set VCOM ctl 1 -#define ILI9XXX_SET_VCOM_CTL_2 0xC7 // Set VCOM ctl 2 -#define ILI9XXX_POWER_CTL_A 0xCB // Set power control A -#define ILI9XXX_POWER_CTL_B 0xCF // Set power control B -#define ILI9XXX_DRV_TIMING_CTL_A 0xE8 // Set driver timing control A -#define ILI9XXX_DRV_TIMING_CTL_B 0xEA // Set driver timing control B -#define ILI9XXX_POWER_ON_SEQ_CTL 0xED // Set Power on sequence control -#define ILI9XXX_SET_NVMEM 0xD0 // Set NVMEM data -#define ILI9XXX_GET_NVMEM_KEY 0xD1 // Get NVMEM protect key -#define ILI9XXX_GET_NVMEM_STATUS 0xD2 // Get NVMEM status -#define ILI9XXX_GET_ID4 0xD3 // Get ID4 -#define ILI9XXX_SET_PGAMMA 0xE0 // Set positive gamma -#define ILI9XXX_SET_NGAMMA 0xE1 // Set negative gamma -#define ILI9XXX_SET_DGAMMA_CTL_1 0xE2 // Set digital gamma ctl 1 -#define ILI9XXX_SET_DGAMMA_CTL_2 0xE3 // Set digital gamma ctl 2 -#define ILI9XXX_SET_IMAGE_FUNCTION 0xE9 // Set image function -#define ILI9XXX_ENABLE_3_GAMMA 0xF2 // Enable 3 gamma -#define ILI9XXX_SET_IF_CTL 0xF6 // Set interface control -#define ILI9XXX_SET_PUMP_RATIO_CTL 0xF7 // Set pump ratio control - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// MADCTL Flags -#define ILI9XXX_MADCTL_MY 0b10000000 -#define ILI9XXX_MADCTL_MX 0b01000000 -#define ILI9XXX_MADCTL_MV 0b00100000 -#define ILI9XXX_MADCTL_ML 0b00010000 -#define ILI9XXX_MADCTL_RGB 0b00000000 -#define ILI9XXX_MADCTL_BGR 0b00001000 -#define ILI9XXX_MADCTL_MH 0b00000100 diff --git a/drivers/eeprom/painter/oled_panel/qp_oled_panel.c b/drivers/eeprom/painter/oled_panel/qp_oled_panel.c deleted file mode 100644 index eefee3f13f..0000000000 --- a/drivers/eeprom/painter/oled_panel/qp_oled_panel.c +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "color.h" -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_draw.h" -#include "qp_oled_panel.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter API implementations - -// Power control -bool qp_oled_panel_power(painter_device_t device, bool power_on) { - painter_driver_t * driver = (painter_driver_t *)device; - oled_panel_painter_driver_vtable_t *vtable = (oled_panel_painter_driver_vtable_t *)driver->driver_vtable; - qp_comms_command(device, power_on ? vtable->opcodes.display_on : vtable->opcodes.display_off); - return true; -} - -// Screen clear -bool qp_oled_panel_clear(painter_device_t device) { - painter_driver_t *driver = (painter_driver_t *)device; - driver->driver_vtable->init(device, driver->rotation); // Re-init the display - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Surface passthru -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -bool qp_oled_panel_passthru_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) { - oled_panel_painter_device_t *driver = (oled_panel_painter_device_t *)device; - return driver->surface.base.validate_ok && driver->surface.base.driver_vtable->pixdata(&driver->surface.base, pixel_data, native_pixel_count); -} - -bool qp_oled_panel_passthru_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) { - oled_panel_painter_device_t *driver = (oled_panel_painter_device_t *)device; - return driver->surface.base.validate_ok && driver->surface.base.driver_vtable->viewport(&driver->surface.base, left, top, right, bottom); -} - -bool qp_oled_panel_passthru_palette_convert(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) { - oled_panel_painter_device_t *driver = (oled_panel_painter_device_t *)device; - return driver->surface.base.validate_ok && driver->surface.base.driver_vtable->palette_convert(&driver->surface.base, palette_size, palette); -} - -bool qp_oled_panel_passthru_append_pixels(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) { - oled_panel_painter_device_t *driver = (oled_panel_painter_device_t *)device; - return driver->surface.base.validate_ok && driver->surface.base.driver_vtable->append_pixels(&driver->surface.base, target_buffer, palette, pixel_offset, pixel_count, palette_indices); -} - -bool qp_oled_panel_passthru_append_pixdata(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte) { - oled_panel_painter_device_t *driver = (oled_panel_painter_device_t *)device; - return driver->surface.base.validate_ok && driver->surface.base.driver_vtable->append_pixdata(&driver->surface.base, target_buffer, pixdata_offset, pixdata_byte); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Flush helpers -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void qp_oled_panel_page_column_flush_rot0(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer) { - painter_driver_t * driver = (painter_driver_t *)device; - oled_panel_painter_driver_vtable_t *vtable = (oled_panel_painter_driver_vtable_t *)driver->driver_vtable; - - // TODO: account for offset_x/y in base driver - int min_page = dirty->t / 8; - int max_page = dirty->b / 8; - int min_column = dirty->l; - int max_column = dirty->r; - - for (int page = min_page; page <= max_page; ++page) { - int cols_required = max_column - min_column + 1; - uint8_t column_data[cols_required]; - memset(column_data, 0, cols_required); - for (int x = min_column; x <= max_column; ++x) { - uint16_t data_offset = x - min_column; - for (int y = 0; y < 8; ++y) { - uint32_t pixel_num = ((page * 8) + y) * driver->panel_width + x; - uint32_t byte_offset = pixel_num / 8; - uint8_t bit_offset = pixel_num % 8; - column_data[data_offset] |= ((framebuffer[byte_offset] & (1 << bit_offset)) >> bit_offset) << y; - } - } - - int actual_page = page; - int start_column = min_column; - qp_comms_command(device, vtable->opcodes.set_page | actual_page); - qp_comms_command(device, vtable->opcodes.set_column_lsb | (start_column & 0x0F)); - qp_comms_command(device, vtable->opcodes.set_column_msb | (start_column & 0xF0) >> 4); - qp_comms_send(device, column_data, cols_required); - } -} - -void qp_oled_panel_page_column_flush_rot90(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer) { - painter_driver_t * driver = (painter_driver_t *)device; - oled_panel_painter_driver_vtable_t *vtable = (oled_panel_painter_driver_vtable_t *)driver->driver_vtable; - - // TODO: account for offset_x/y in base driver - int num_columns = driver->panel_width; - int min_page = dirty->l / 8; - int max_page = dirty->r / 8; - int min_column = dirty->t; - int max_column = dirty->b; - - for (int page = min_page; page <= max_page; ++page) { - int cols_required = max_column - min_column + 1; - uint8_t column_data[cols_required]; - memset(column_data, 0, cols_required); - for (int y = min_column; y <= max_column; ++y) { - uint16_t data_offset = cols_required - 1 - (y - min_column); - for (int x = 0; x < 8; ++x) { - uint32_t pixel_num = y * driver->panel_height + ((page * 8) + x); - uint32_t byte_offset = pixel_num / 8; - uint8_t bit_offset = pixel_num % 8; - column_data[data_offset] |= ((framebuffer[byte_offset] & (1 << bit_offset)) >> bit_offset) << x; - } - } - - int actual_page = page; - int start_column = num_columns - 1 - max_column; - qp_comms_command(device, vtable->opcodes.set_page | actual_page); - qp_comms_command(device, vtable->opcodes.set_column_lsb | (start_column & 0x0F)); - qp_comms_command(device, vtable->opcodes.set_column_msb | (start_column & 0xF0) >> 4); - qp_comms_send(device, column_data, cols_required); - } -} - -void qp_oled_panel_page_column_flush_rot180(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer) { - painter_driver_t * driver = (painter_driver_t *)device; - oled_panel_painter_driver_vtable_t *vtable = (oled_panel_painter_driver_vtable_t *)driver->driver_vtable; - - // TODO: account for offset_x/y in base driver - int num_pages = driver->panel_height / 8; - int num_columns = driver->panel_width; - int min_page = dirty->t / 8; - int max_page = dirty->b / 8; - int min_column = dirty->l; - int max_column = dirty->r; - - for (int page = min_page; page <= max_page; ++page) { - int cols_required = max_column - min_column + 1; - uint8_t column_data[cols_required]; - memset(column_data, 0, cols_required); - for (int x = min_column; x <= max_column; ++x) { - uint16_t data_offset = cols_required - 1 - (x - min_column); - for (int y = 0; y < 8; ++y) { - uint32_t pixel_num = ((page * 8) + y) * driver->panel_width + x; - uint32_t byte_offset = pixel_num / 8; - uint8_t bit_offset = pixel_num % 8; - column_data[data_offset] |= ((framebuffer[byte_offset] & (1 << bit_offset)) >> bit_offset) << (7 - y); - } - } - - int actual_page = num_pages - 1 - page; - int start_column = num_columns - 1 - max_column; - qp_comms_command(device, vtable->opcodes.set_page | actual_page); - qp_comms_command(device, vtable->opcodes.set_column_lsb | (start_column & 0x0F)); - qp_comms_command(device, vtable->opcodes.set_column_msb | (start_column & 0xF0) >> 4); - qp_comms_send(device, column_data, cols_required); - } -} - -void qp_oled_panel_page_column_flush_rot270(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer) { - painter_driver_t * driver = (painter_driver_t *)device; - oled_panel_painter_driver_vtable_t *vtable = (oled_panel_painter_driver_vtable_t *)driver->driver_vtable; - - // TODO: account for offset_x/y in base driver - int num_pages = driver->panel_height / 8; - int min_page = dirty->l / 8; - int max_page = dirty->r / 8; - int min_column = dirty->t; - int max_column = dirty->b; - - for (int page = min_page; page <= max_page; ++page) { - int cols_required = max_column - min_column + 1; - uint8_t column_data[cols_required]; - memset(column_data, 0, cols_required); - for (int y = min_column; y <= max_column; ++y) { - uint16_t data_offset = y - min_column; - for (int x = 0; x < 8; ++x) { - uint32_t pixel_num = y * driver->panel_height + ((page * 8) + x); - uint32_t byte_offset = pixel_num / 8; - uint8_t bit_offset = pixel_num % 8; - column_data[data_offset] |= ((framebuffer[byte_offset] & (1 << bit_offset)) >> bit_offset) << (7 - x); - } - } - - int actual_page = num_pages - 1 - page; - int start_column = min_column; - qp_comms_command(device, vtable->opcodes.set_page | actual_page); - qp_comms_command(device, vtable->opcodes.set_column_lsb | (start_column & 0x0F)); - qp_comms_command(device, vtable->opcodes.set_column_msb | (start_column & 0xF0) >> 4); - qp_comms_send(device, column_data, cols_required); - } -} diff --git a/drivers/eeprom/painter/oled_panel/qp_oled_panel.h b/drivers/eeprom/painter/oled_panel/qp_oled_panel.h deleted file mode 100644 index ccc7ab9204..0000000000 --- a/drivers/eeprom/painter/oled_panel/qp_oled_panel.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "color.h" -#include "qp_internal.h" -#include "qp_surface_internal.h" - -#ifdef QUANTUM_PAINTER_SPI_ENABLE -# include "qp_comms_spi.h" -#endif // QUANTUM_PAINTER_SPI_ENABLE - -#ifdef QUANTUM_PAINTER_I2C_ENABLE -# include "qp_comms_i2c.h" -#endif // QUANTUM_PAINTER_I2C_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common OLED panel implementation - -// Driver vtable with extras -typedef struct oled_panel_painter_driver_vtable_t { - painter_driver_vtable_t base; // must be first, so it can be cast to/from the painter_driver_vtable_t* type - - // Opcodes for normal display operation - struct { - uint8_t display_on; - uint8_t display_off; - uint8_t set_page; - uint8_t set_column_lsb; - uint8_t set_column_msb; - } opcodes; -} oled_panel_painter_driver_vtable_t; - -// Device definition -typedef struct oled_panel_painter_device_t { - painter_driver_t base; // must be first, so it can be cast to/from the painter_device_t* type - - union { -#ifdef QUANTUM_PAINTER_SPI_ENABLE - // SPI-based configurables - qp_comms_spi_dc_reset_config_t spi_dc_reset_config; -#endif // QUANTUM_PAINTER_SPI_ENABLE -#ifdef QUANTUM_PAINTER_I2C_ENABLE - // I2C-based configurables - qp_comms_i2c_config_t i2c_config; -#endif // QUANTUM_PAINTER_I2C_ENABLE - }; - - surface_painter_device_t surface; -} oled_panel_painter_device_t; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Forward declarations for injecting into concrete driver vtables - -bool qp_oled_panel_power(painter_device_t device, bool power_on); -bool qp_oled_panel_clear(painter_device_t device); - -bool qp_oled_panel_passthru_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count); -bool qp_oled_panel_passthru_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom); -bool qp_oled_panel_passthru_palette_convert(painter_device_t device, int16_t palette_size, qp_pixel_t *palette); -bool qp_oled_panel_passthru_append_pixels(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices); -bool qp_oled_panel_passthru_append_pixdata(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte); - -// Helpers for flushing data from the dirty region to the correct location on the OLED -void qp_oled_panel_page_column_flush_rot0(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer); -void qp_oled_panel_page_column_flush_rot90(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer); -void qp_oled_panel_page_column_flush_rot180(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer); -void qp_oled_panel_page_column_flush_rot270(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer); diff --git a/drivers/eeprom/painter/sh1106/qp_sh1106.c b/drivers/eeprom/painter/sh1106/qp_sh1106.c deleted file mode 100644 index 4117115aec..0000000000 --- a/drivers/eeprom/painter/sh1106/qp_sh1106.c +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_oled_panel.h" -#include "qp_sh1106.h" -#include "qp_sh1106_opcodes.h" -#include "qp_surface.h" -#include "qp_surface_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver storage -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef struct sh1106_device_t { - oled_panel_painter_device_t oled; - - uint8_t framebuffer[SURFACE_REQUIRED_BUFFER_BYTE_SIZE(128, 64, 1)]; -} sh1106_device_t; - -static sh1106_device_t sh1106_drivers[SH1106_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter API implementations - -// Initialisation -__attribute__((weak)) bool qp_sh1106_init(painter_device_t device, painter_rotation_t rotation) { - sh1106_device_t *driver = (sh1106_device_t *)device; - - // Change the surface geometry based on the panel rotation - if (rotation == QP_ROTATION_90 || rotation == QP_ROTATION_270) { - driver->oled.surface.base.panel_width = driver->oled.base.panel_height; - driver->oled.surface.base.panel_height = driver->oled.base.panel_width; - } else { - driver->oled.surface.base.panel_width = driver->oled.base.panel_width; - driver->oled.surface.base.panel_height = driver->oled.base.panel_height; - } - - // Init the internal surface - if (!qp_init(&driver->oled.surface.base, QP_ROTATION_0)) { - qp_dprintf("Failed to init internal surface in qp_sh1106_init\n"); - return false; - } - - // clang-format off - uint8_t sh1106_init_sequence[] = { - // Command, Delay, N, Data[N] - SH1106_SET_MUX_RATIO, 0, 1, 0x3F, - SH1106_DISPLAY_OFFSET, 0, 1, 0x00, - SH1106_DISPLAY_START_LINE, 0, 0, - SH1106_SET_SEGMENT_REMAP_INV, 0, 0, - SH1106_COM_SCAN_DIR_DEC, 0, 0, - SH1106_COM_PADS_HW_CFG, 0, 1, 0x12, - SH1106_SET_CONTRAST, 0, 1, 0x7F, - SH1106_ALL_ON_RESUME, 0, 0, - SH1106_NON_INVERTING_DISPLAY, 0, 0, - SH1106_SET_OSC_DIVFREQ, 0, 1, 0x80, - SH1106_SET_CHARGE_PUMP, 0, 1, 0x14, - SH1106_DISPLAY_ON, 0, 0, - }; - // clang-format on - - // If the display height is anything other than the default 64 pixels, change SH1106_SET_MUX_RATIO data byte to the correct value - if (driver->oled.base.panel_height != 64) { - sh1106_init_sequence[3] = driver->oled.base.panel_height - 1; - } - - // For 128x32 or 96x16 displays, change SH1106_COM_PADS_HW_CFG data byte from alternative (0x12) to sequential (0x02) configuration - if (driver->oled.base.panel_height <= 32) { - sh1106_init_sequence[20] = 0x02; - } - - qp_comms_bulk_command_sequence(device, sh1106_init_sequence, sizeof(sh1106_init_sequence)); - return true; -} - -// Screen flush -bool qp_sh1106_flush(painter_device_t device) { - sh1106_device_t *driver = (sh1106_device_t *)device; - - if (!driver->oled.surface.dirty.is_dirty) { - return true; - } - - switch (driver->oled.base.rotation) { - default: - case QP_ROTATION_0: - qp_oled_panel_page_column_flush_rot0(device, &driver->oled.surface.dirty, driver->framebuffer); - break; - case QP_ROTATION_90: - qp_oled_panel_page_column_flush_rot90(device, &driver->oled.surface.dirty, driver->framebuffer); - break; - case QP_ROTATION_180: - qp_oled_panel_page_column_flush_rot180(device, &driver->oled.surface.dirty, driver->framebuffer); - break; - case QP_ROTATION_270: - qp_oled_panel_page_column_flush_rot270(device, &driver->oled.surface.dirty, driver->framebuffer); - break; - } - - // Clear the dirty area - qp_flush(&driver->oled.surface); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const oled_panel_painter_driver_vtable_t sh1106_driver_vtable = { - .base = - { - .init = qp_sh1106_init, - .power = qp_oled_panel_power, - .clear = qp_oled_panel_clear, - .flush = qp_sh1106_flush, - .pixdata = qp_oled_panel_passthru_pixdata, - .viewport = qp_oled_panel_passthru_viewport, - .palette_convert = qp_oled_panel_passthru_palette_convert, - .append_pixels = qp_oled_panel_passthru_append_pixels, - .append_pixdata = qp_oled_panel_passthru_append_pixdata, - }, - .opcodes = - { - .display_on = SH1106_DISPLAY_ON, - .display_off = SH1106_DISPLAY_OFF, - .set_page = SH1106_PAGE_ADDR, - .set_column_lsb = SH1106_SETCOLUMN_LSB, - .set_column_msb = SH1106_SETCOLUMN_MSB, - }, -}; - -#ifdef QUANTUM_PAINTER_SH1106_SPI_ENABLE -// Factory function for creating a handle to the SH1106 device -painter_device_t qp_sh1106_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) { - for (uint32_t i = 0; i < SH1106_NUM_DEVICES; ++i) { - sh1106_device_t *driver = &sh1106_drivers[i]; - if (!driver->oled.base.driver_vtable) { - painter_device_t surface = qp_make_mono1bpp_surface_advanced(&driver->oled.surface, 1, panel_width, panel_height, driver->framebuffer); - if (!surface) { - return NULL; - } - - // Setup the OLED device - driver->oled.base.driver_vtable = (const painter_driver_vtable_t *)&sh1106_driver_vtable; - driver->oled.base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->oled.base.native_bits_per_pixel = 1; // 1bpp mono - driver->oled.base.panel_width = panel_width; - driver->oled.base.panel_height = panel_height; - driver->oled.base.rotation = QP_ROTATION_0; - driver->oled.base.offset_x = 0; - driver->oled.base.offset_y = 0; - - // SPI and other pin configuration - driver->oled.base.comms_config = &driver->oled.spi_dc_reset_config; - driver->oled.spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->oled.spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->oled.spi_dc_reset_config.spi_config.lsb_first = false; - driver->oled.spi_dc_reset_config.spi_config.mode = spi_mode; - driver->oled.spi_dc_reset_config.dc_pin = dc_pin; - driver->oled.spi_dc_reset_config.reset_pin = reset_pin; - driver->oled.spi_dc_reset_config.command_params_uses_command_pin = true; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(sh1106_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_SH1106_SPI_ENABLE - -#ifdef QUANTUM_PAINTER_SH1106_I2C_ENABLE -// Factory function for creating a handle to the SH1106 device -painter_device_t qp_sh1106_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address) { - for (uint32_t i = 0; i < SH1106_NUM_DEVICES; ++i) { - sh1106_device_t *driver = &sh1106_drivers[i]; - if (!driver->oled.base.driver_vtable) { - // Instantiate the surface, intentional swap of width/high due to transpose - painter_device_t surface = qp_make_mono1bpp_surface_advanced(&driver->oled.surface, 1, panel_width, panel_height, driver->framebuffer); - if (!surface) { - return NULL; - } - - // Setup the OLED device - driver->oled.base.driver_vtable = (const painter_driver_vtable_t *)&sh1106_driver_vtable; - driver->oled.base.comms_vtable = (const painter_comms_vtable_t *)&i2c_comms_cmddata_vtable; - driver->oled.base.native_bits_per_pixel = 1; // 1bpp mono - driver->oled.base.panel_width = panel_width; - driver->oled.base.panel_height = panel_height; - driver->oled.base.rotation = QP_ROTATION_0; - driver->oled.base.offset_x = 0; - driver->oled.base.offset_y = 0; - - // I2C configuration - driver->oled.base.comms_config = &driver->oled.i2c_config; - driver->oled.i2c_config.chip_address = i2c_address; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(sh1106_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_SH1106_I2C_ENABLE diff --git a/drivers/eeprom/painter/sh1106/qp_sh1106.h b/drivers/eeprom/painter/sh1106/qp_sh1106.h deleted file mode 100644 index 6c325dba4b..0000000000 --- a/drivers/eeprom/painter/sh1106/qp_sh1106.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter SH1106 configurables (add to your keyboard's config.h) - -#if defined(QUANTUM_PAINTER_SH1106_SPI_ENABLE) && !defined(SH1106_NUM_SPI_DEVICES) -/** - * @def This controls the maximum number of SPI SH1106 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define SH1106_NUM_SPI_DEVICES 1 -#else -# define SH1106_NUM_SPI_DEVICES 0 -#endif - -#if defined(QUANTUM_PAINTER_SH1106_I2C_ENABLE) && !defined(SH1106_NUM_I2C_DEVICES) -/** - * @def This controls the maximum number of I2C SH1106 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define SH1106_NUM_I2C_DEVICES 1 -#else -# define SH1106_NUM_I2C_DEVICES 0 -#endif - -#define SH1106_NUM_DEVICES ((SH1106_NUM_SPI_DEVICES) + (SH1106_NUM_I2C_DEVICES)) - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter SH1106 device factories - -#ifdef QUANTUM_PAINTER_SH1106_SPI_ENABLE - -/** - * Factory method for an SH1106 SPI LCD device. - * - * @param panel_width[in] the width of the display in pixels (usually 128) - * @param panel_height[in] the height of the display in pixels (usually 64) - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_sh1106_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); - -#endif // QUANTUM_PAINTER_SH1106_SPI_ENABLE - -#ifdef QUANTUM_PAINTER_SH1106_I2C_ENABLE - -/** - * Factory method for an SH1106 I2C LCD device. - * - * @param panel_width[in] the width of the display in pixels (usually 128) - * @param panel_height[in] the height of the display in pixels (usually 64) - * @param i2c_address[in] the I2C address to use - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_sh1106_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address); - -#endif // QUANTUM_PAINTER_SH1106_I2C_ENABLE diff --git a/drivers/eeprom/painter/sh1106/qp_sh1106_opcodes.h b/drivers/eeprom/painter/sh1106/qp_sh1106_opcodes.h deleted file mode 100644 index bf86ba4c2c..0000000000 --- a/drivers/eeprom/painter/sh1106/qp_sh1106_opcodes.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#define SH1106_DISPLAY_ON 0xAF -#define SH1106_DISPLAY_OFF 0xAE -#define SH1106_SET_OSC_DIVFREQ 0xD5 -#define SH1106_SET_MUX_RATIO 0xA8 -#define SH1106_DISPLAY_OFFSET 0xD3 -#define SH1106_DISPLAY_START_LINE 0x40 -#define SH1106_SET_CHARGE_PUMP 0x8D -#define SH1106_SET_SEGMENT_REMAP_NORMAL 0xA0 -#define SH1106_SET_SEGMENT_REMAP_INV 0xA1 -#define SH1106_COM_SCAN_DIR_INC 0xC0 -#define SH1106_COM_SCAN_DIR_DEC 0xC8 -#define SH1106_COM_PADS_HW_CFG 0xDA -#define SH1106_SET_CONTRAST 0x81 -#define SH1106_SET_PRECHARGE_PERIOD 0xD9 -#define SH1106_VCOM_DESELECT_LEVEL 0xDB -#define SH1106_ALL_ON_RESUME 0xA4 -#define SH1106_NON_INVERTING_DISPLAY 0xA6 -#define SH1106_DEACTIVATE_SCROLL 0x2E - -#define SH1106_SETCOLUMN_LSB 0x00 -#define SH1106_SETCOLUMN_MSB 0x10 -#define SH1106_PAGE_ADDR 0xB0 diff --git a/drivers/eeprom/painter/ssd1351/qp_ssd1351.c b/drivers/eeprom/painter/ssd1351/qp_ssd1351.c deleted file mode 100644 index 3270a362c2..0000000000 --- a/drivers/eeprom/painter/ssd1351/qp_ssd1351.c +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2021-2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_ssd1351.h" -#include "qp_ssd1351_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_SSD1351_SPI_ENABLE -# include "qp_comms_spi.h" -#endif // QUANTUM_PAINTER_SSD1351_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t ssd1351_drivers[SSD1351_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -__attribute__((weak)) bool qp_ssd1351_init(painter_device_t device, painter_rotation_t rotation) { - tft_panel_dc_reset_painter_device_t *driver = (tft_panel_dc_reset_painter_device_t *)device; - - // clang-format off - const uint8_t ssd1351_init_sequence[] = { - // Command, Delay, N, Data[N] - SSD1351_COMMANDLOCK, 5, 1, 0x12, - SSD1351_COMMANDLOCK, 5, 1, 0xB1, - SSD1351_DISPLAYOFF, 5, 0, - SSD1351_CLOCKDIV, 5, 1, 0xF1, - SSD1351_MUXRATIO, 5, 1, 0x7F, - SSD1351_DISPLAYOFFSET, 5, 1, 0x00, - SSD1351_SETGPIO, 5, 1, 0x00, - SSD1351_FUNCTIONSELECT, 5, 1, 0x01, - SSD1351_PRECHARGE, 5, 1, 0x32, - SSD1351_VCOMH, 5, 1, 0x05, - SSD1351_NORMALDISPLAY, 5, 0, - SSD1351_CONTRASTABC, 5, 3, 0xC8, 0x80, 0xC8, - SSD1351_CONTRASTMASTER, 5, 1, 0x0F, - SSD1351_SETVSL, 5, 3, 0xA0, 0xB5, 0x55, - SSD1351_PRECHARGE2, 5, 1, 0x01, - SSD1351_DISPLAYON, 5, 0, - }; - // clang-format on - qp_comms_bulk_command_sequence(device, ssd1351_init_sequence, sizeof(ssd1351_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MY, - [QP_ROTATION_90] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MX | SSD1351_MADCTL_MY | SSD1351_MADCTL_MV, - [QP_ROTATION_180] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MX, - [QP_ROTATION_270] = SSD1351_MADCTL_BGR | SSD1351_MADCTL_MV, - }; - qp_comms_command_databyte(device, SSD1351_SETREMAP, madctl[rotation]); - qp_comms_command_databyte(device, SSD1351_STARTLINE, (rotation == QP_ROTATION_0 || rotation == QP_ROTATION_90) ? driver->base.panel_height : 0); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -const tft_panel_dc_reset_painter_driver_vtable_t ssd1351_driver_vtable = { - .base = - { - .init = qp_ssd1351_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 1, - .swap_window_coords = true, - .opcodes = - { - .display_on = SSD1351_DISPLAYON, - .display_off = SSD1351_DISPLAYOFF, - .set_column_address = SSD1351_SETCOLUMN, - .set_row_address = SSD1351_SETROW, - .enable_writes = SSD1351_WRITERAM, - }, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_SSD1351_SPI_ENABLE - -// Factory function for creating a handle to the SSD1351 device -painter_device_t qp_ssd1351_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) { - for (uint32_t i = 0; i < SSD1351_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &ssd1351_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&ssd1351_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - driver->base.native_bits_per_pixel = 16; // RGB565 - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_SSD1351_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/ssd1351/qp_ssd1351.h b/drivers/eeprom/painter/ssd1351/qp_ssd1351.h deleted file mode 100644 index 0045c4926b..0000000000 --- a/drivers/eeprom/painter/ssd1351/qp_ssd1351.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter SSD1351 configurables (add to your keyboard's config.h) - -#ifndef SSD1351_NUM_DEVICES -/** - * @def This controls the maximum number of SSD1351 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define SSD1351_NUM_DEVICES 1 -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter SSD1351 device factories - -#ifdef QUANTUM_PAINTER_SSD1351_SPI_ENABLE -/** - * Factory method for an SSD1351 SPI OLED device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_ssd1351_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); -#endif // QUANTUM_PAINTER_SSD1351_SPI_ENABLE diff --git a/drivers/eeprom/painter/ssd1351/qp_ssd1351_opcodes.h b/drivers/eeprom/painter/ssd1351/qp_ssd1351_opcodes.h deleted file mode 100644 index ca8e2bf77e..0000000000 --- a/drivers/eeprom/painter/ssd1351/qp_ssd1351_opcodes.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter SSD1351 command opcodes - -// System function commands -#define SSD1351_SETCOLUMN 0x15 -#define SSD1351_SETROW 0x75 -#define SSD1351_WRITERAM 0x5C -#define SSD1351_READRAM 0x5D -#define SSD1351_SETREMAP 0xA0 -#define SSD1351_STARTLINE 0xA1 -#define SSD1351_DISPLAYOFFSET 0xA2 -#define SSD1351_DISPLAYALLOFF 0xA4 -#define SSD1351_DISPLAYALLON 0xA5 -#define SSD1351_NORMALDISPLAY 0xA6 -#define SSD1351_INVERTDISPLAY 0xA7 -#define SSD1351_FUNCTIONSELECT 0xAB -#define SSD1351_DISPLAYOFF 0xAE -#define SSD1351_DISPLAYON 0xAF -#define SSD1351_PRECHARGE 0xB1 -#define SSD1351_DISPLAYENHANCE 0xB2 -#define SSD1351_CLOCKDIV 0xB3 -#define SSD1351_SETVSL 0xB4 -#define SSD1351_SETGPIO 0xB5 -#define SSD1351_PRECHARGE2 0xB6 -#define SSD1351_SETGRAY 0xB8 -#define SSD1351_USELUT 0xB9 -#define SSD1351_PRECHARGELEVEL 0xBB -#define SSD1351_VCOMH 0xBE -#define SSD1351_CONTRASTABC 0xC1 -#define SSD1351_CONTRASTMASTER 0xC7 -#define SSD1351_MUXRATIO 0xCA -#define SSD1351_COMMANDLOCK 0xFD -#define SSD1351_HORIZSCROLL 0x96 -#define SSD1351_STOPSCROLL 0x9E -#define SSD1351_STARTSCROLL 0x9F - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SETREMAP (MADCTL) Flags -#define SSD1351_MADCTL_MY 0b00010000 -#define SSD1351_MADCTL_MX 0b00000010 -#define SSD1351_MADCTL_MV 0b00000001 -#define SSD1351_MADCTL_RGB 0b01100000 -#define SSD1351_MADCTL_BGR 0b01100100 diff --git a/drivers/eeprom/painter/st77xx/qp_st7735.c b/drivers/eeprom/painter/st77xx/qp_st7735.c deleted file mode 100644 index 1db0d01dcb..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st7735.c +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// Copyright 2021-2023 Nick Brassel (@tzarc) -// Copyright 2022 David Hoelscher (@customMK) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_st7735.h" -#include "qp_st77xx_opcodes.h" -#include "qp_st7735_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_ST7735_SPI_ENABLE -# include "qp_comms_spi.h" -#endif // QUANTUM_PAINTER_ST7735_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t st7735_drivers[ST7735_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Automatic viewport offsets - -#ifndef ST7735_NO_AUTOMATIC_OFFSETS -static inline void st7735_automatic_viewport_offsets(painter_device_t device, painter_rotation_t rotation) { - painter_driver_t *driver = (painter_driver_t *)device; - - // clang-format off - const struct { - uint16_t offset_x; - uint16_t offset_y; - } rotation_offsets_80x160[] = { - [QP_ROTATION_0] = { .offset_x = 24, .offset_y = 0 }, - [QP_ROTATION_90] = { .offset_x = 0, .offset_y = 24 }, - [QP_ROTATION_180] = { .offset_x = 24, .offset_y = 0 }, - [QP_ROTATION_270] = { .offset_x = 0, .offset_y = 24 }, - }; - // clang-format on - - if (driver->panel_width == 80 && driver->panel_height == 160) { - driver->offset_x = rotation_offsets_80x160[rotation].offset_x; - driver->offset_y = rotation_offsets_80x160[rotation].offset_y; - } -} -#endif // ST7735_NO_AUTOMATIC_OFFSETS - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -__attribute__((weak)) bool qp_st7735_init(painter_device_t device, painter_rotation_t rotation) { - // clang-format off - const uint8_t st7735_init_sequence[] = { - // Command, Delay, N, Data[N] - ST77XX_CMD_RESET, 120, 0, - ST77XX_CMD_SLEEP_OFF, 5, 0, - ST77XX_SET_PIX_FMT, 0, 1, 0x55, - ST77XX_CMD_INVERT_OFF, 0, 0, - ST77XX_CMD_NORMAL_ON, 0, 0, - ST7735_SET_PGAMMA, 0, 16, 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, - ST7735_SET_NGAMMA, 0, 16, 0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, - ST77XX_CMD_DISPLAY_ON, 20, 0 - }; - // clang-format on - qp_comms_bulk_command_sequence(device, st7735_init_sequence, sizeof(st7735_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = ST77XX_MADCTL_BGR, - [QP_ROTATION_90] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MX | ST77XX_MADCTL_MV, - [QP_ROTATION_180] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MX | ST77XX_MADCTL_MY, - [QP_ROTATION_270] = ST77XX_MADCTL_BGR | ST77XX_MADCTL_MV | ST77XX_MADCTL_MY, - }; - qp_comms_command_databyte(device, ST77XX_SET_MADCTL, madctl[rotation]); - -#ifndef ST7735_NO_AUTOMATIC_VIEWPORT_OFFSETS - st7735_automatic_viewport_offsets(device, rotation); -#endif // ST7735_NO_AUTOMATIC_VIEWPORT_OFFSETS - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -const tft_panel_dc_reset_painter_driver_vtable_t st7735_driver_vtable = { - .base = - { - .init = qp_st7735_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ST77XX_CMD_DISPLAY_ON, - .display_off = ST77XX_CMD_DISPLAY_OFF, - .set_column_address = ST77XX_SET_COL_ADDR, - .set_row_address = ST77XX_SET_ROW_ADDR, - .enable_writes = ST77XX_SET_MEM, - }, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_ST7735_SPI_ENABLE - -// Factory function for creating a handle to the ST7735 device -painter_device_t qp_st7735_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) { - for (uint32_t i = 0; i < ST7735_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &st7735_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&st7735_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - driver->base.native_bits_per_pixel = 16; // RGB565 - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_ST7735_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/st77xx/qp_st7735.h b/drivers/eeprom/painter/st77xx/qp_st7735.h deleted file mode 100644 index e65b7ca706..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st7735.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// Copyright 2021 Nick Brassel (@tzarc) -// Copyright 2022 David Hoelscher (@customMK) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST7735 configurables (add to your keyboard's config.h) - -#ifndef ST7735_NUM_DEVICES -/** - * @def This controls the maximum number of ST7735 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define ST7735_NUM_DEVICES 1 -#endif - -// Additional configuration options to be copied to your keyboard's config.h (don't change here): - -// If you know exactly which offsets should be used on your panel with respect to selected rotation, then this config -// option allows you to save some flash space -- you'll need to invoke qp_set_viewport_offsets() instead from your keyboard. -// #define ST7735_NO_AUTOMATIC_VIEWPORT_OFFSETS - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST7735 device factories - -#ifdef QUANTUM_PAINTER_ST7735_SPI_ENABLE -/** - * Factory method for an ST7735 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_st7735_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); -#endif // QUANTUM_PAINTER_ST7735_SPI_ENABLE diff --git a/drivers/eeprom/painter/st77xx/qp_st7735_opcodes.h b/drivers/eeprom/painter/st77xx/qp_st7735_opcodes.h deleted file mode 100644 index f390d113c5..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st7735_opcodes.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2022 David Hoelscher (@customMK) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST7735 additional command opcodes - -// Panel Function Commands -#define ST7735_SET_FRAME_RATE_CTL_1 0xB1 // Set frame rate control 1 -#define ST7735_SET_FRAME_RATE_CTL_2 0xB2 // Set frame rate control 2 -#define ST7735_SET_FRAME_RATE_CTL_3 0xB3 // Set frame rate control 3 -#define ST7735_SET_INVERSION_CTL 0xB4 // Set inversion mode control -#define ST7735_SET_DISPLAY_CTL 0xB6 // Set display control 5 -#define ST7735_SET_POWER_CTL_1 0xC0 // Set GVDD -#define ST7735_SET_POWER_CTL_2 0xC1 // Set VGH and VGL -#define ST7735_SET_POWER_CTL_3 0xC2 // Set normal mode op amp current -#define ST7735_SET_POWER_CTL_4 0xC3 // Set idle mode op amp current -#define ST7735_SET_POWER_CTL_5 0xC4 // Set partial mode op amp current -#define ST7735_SET_VCOM_CTL 0xC5 // Set VCOM voltages -#define ST7735_SET_VCOM_OFFSET_CTL 0xC7 // Set VCOM offset ctl -#define ST7735_SET_LCD_ID 0xD1 // Set LCD module version -#define ST7735_SET_PROJECT_ID 0xD2 // Set product project ID -#define ST7735_SET_POWER_CTL_6 0xFC // Set partial+idle op amp current -#define ST7735_SET_NVMEM_CTL_STATUS 0xD9 // EEPROM Control Status -#define ST7735_SET_NVMEM_READ_CMD 0xCC // EEPROM Read Command -#define ST7735_SET_NVMEM_WRITE_CMD 0xDF // EEPROM Write Command -#define ST7735_SET_PGAMMA 0xE0 // Set positive gamma -#define ST7735_SET_NGAMMA 0xE1 // Set negative gamma -#define ST7735_SET_EXTENSION_ENABLE 0xF0 // Enable extension command -#define ST7735_SET_VCOM_DELAY 0xFF // Set VCOM delay time diff --git a/drivers/eeprom/painter/st77xx/qp_st7789.c b/drivers/eeprom/painter/st77xx/qp_st7789.c deleted file mode 100644 index 855a9cc0c8..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st7789.c +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// Copyright 2021-2023 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_st7789.h" -#include "qp_st77xx_opcodes.h" -#include "qp_st7789_opcodes.h" -#include "qp_tft_panel.h" - -#ifdef QUANTUM_PAINTER_ST7789_SPI_ENABLE -# include "qp_comms_spi.h" -#endif // QUANTUM_PAINTER_ST7789_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common - -// Driver storage -tft_panel_dc_reset_painter_device_t st7789_drivers[ST7789_NUM_DEVICES] = {0}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Automatic viewport offsets - -#ifndef ST7789_NO_AUTOMATIC_OFFSETS -static inline void st7789_automatic_viewport_offsets(painter_device_t device, painter_rotation_t rotation) { - painter_driver_t *driver = (painter_driver_t *)device; - - // clang-format off - const struct { - uint16_t offset_x; - uint16_t offset_y; - } rotation_offsets_240x240[] = { - [QP_ROTATION_0] = { .offset_x = 0, .offset_y = 0 }, - [QP_ROTATION_90] = { .offset_x = 0, .offset_y = 0 }, - [QP_ROTATION_180] = { .offset_x = 0, .offset_y = 80 }, - [QP_ROTATION_270] = { .offset_x = 80, .offset_y = 0 }, - }; - // clang-format on - - if (driver->panel_width == 240 && driver->panel_height == 240) { - driver->offset_x = rotation_offsets_240x240[rotation].offset_x; - driver->offset_y = rotation_offsets_240x240[rotation].offset_y; - } -} -#endif // ST7789_NO_AUTOMATIC_OFFSETS - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Initialization - -__attribute__((weak)) bool qp_st7789_init(painter_device_t device, painter_rotation_t rotation) { - // clang-format off - const uint8_t st7789_init_sequence[] = { - // Command, Delay, N, Data[N] - ST77XX_CMD_RESET, 120, 0, - ST77XX_CMD_SLEEP_OFF, 5, 0, - ST77XX_SET_PIX_FMT, 0, 1, 0x55, - ST77XX_CMD_INVERT_ON, 0, 0, - ST77XX_CMD_NORMAL_ON, 0, 0, - ST77XX_CMD_DISPLAY_ON, 20, 0 - }; - // clang-format on - qp_comms_bulk_command_sequence(device, st7789_init_sequence, sizeof(st7789_init_sequence)); - - // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) - const uint8_t madctl[] = { - [QP_ROTATION_0] = ST77XX_MADCTL_RGB, - [QP_ROTATION_90] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MX | ST77XX_MADCTL_MV, - [QP_ROTATION_180] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MX | ST77XX_MADCTL_MY, - [QP_ROTATION_270] = ST77XX_MADCTL_RGB | ST77XX_MADCTL_MV | ST77XX_MADCTL_MY, - }; - qp_comms_command_databyte(device, ST77XX_SET_MADCTL, madctl[rotation]); - -#ifndef ST7789_NO_AUTOMATIC_VIEWPORT_OFFSETS - st7789_automatic_viewport_offsets(device, rotation); -#endif // ST7789_NO_AUTOMATIC_VIEWPORT_OFFSETS - - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Driver vtable - -const tft_panel_dc_reset_painter_driver_vtable_t st7789_driver_vtable = { - .base = - { - .init = qp_st7789_init, - .power = qp_tft_panel_power, - .clear = qp_tft_panel_clear, - .flush = qp_tft_panel_flush, - .pixdata = qp_tft_panel_pixdata, - .viewport = qp_tft_panel_viewport, - .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped, - .append_pixels = qp_tft_panel_append_pixels_rgb565, - .append_pixdata = qp_tft_panel_append_pixdata, - }, - .num_window_bytes = 2, - .swap_window_coords = false, - .opcodes = - { - .display_on = ST77XX_CMD_DISPLAY_ON, - .display_off = ST77XX_CMD_DISPLAY_OFF, - .set_column_address = ST77XX_SET_COL_ADDR, - .set_row_address = ST77XX_SET_ROW_ADDR, - .enable_writes = ST77XX_SET_MEM, - }, -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SPI - -#ifdef QUANTUM_PAINTER_ST7789_SPI_ENABLE - -// Factory function for creating a handle to the ST7789 device -painter_device_t qp_st7789_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) { - for (uint32_t i = 0; i < ST7789_NUM_DEVICES; ++i) { - tft_panel_dc_reset_painter_device_t *driver = &st7789_drivers[i]; - if (!driver->base.driver_vtable) { - driver->base.driver_vtable = (const painter_driver_vtable_t *)&st7789_driver_vtable; - driver->base.comms_vtable = (const painter_comms_vtable_t *)&spi_comms_with_dc_vtable; - driver->base.panel_width = panel_width; - driver->base.panel_height = panel_height; - driver->base.rotation = QP_ROTATION_0; - driver->base.offset_x = 0; - driver->base.offset_y = 0; - driver->base.native_bits_per_pixel = 16; // RGB565 - - // SPI and other pin configuration - driver->base.comms_config = &driver->spi_dc_reset_config; - driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin; - driver->spi_dc_reset_config.spi_config.divisor = spi_divisor; - driver->spi_dc_reset_config.spi_config.lsb_first = false; - driver->spi_dc_reset_config.spi_config.mode = spi_mode; - driver->spi_dc_reset_config.dc_pin = dc_pin; - driver->spi_dc_reset_config.reset_pin = reset_pin; - driver->spi_dc_reset_config.command_params_uses_command_pin = false; - - if (!qp_internal_register_device((painter_device_t)driver)) { - memset(driver, 0, sizeof(tft_panel_dc_reset_painter_device_t)); - return NULL; - } - - return (painter_device_t)driver; - } - } - return NULL; -} - -#endif // QUANTUM_PAINTER_ST7789_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/drivers/eeprom/painter/st77xx/qp_st7789.h b/drivers/eeprom/painter/st77xx/qp_st7789.h deleted file mode 100644 index 03d618cae4..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st7789.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "gpio.h" -#include "qp_internal.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST7789 configurables (add to your keyboard's config.h) - -#ifndef ST7789_NUM_DEVICES -/** - * @def This controls the maximum number of ST7789 devices that Quantum Painter can communicate with at any one time. - * Increasing this number allows for multiple displays to be used. - */ -# define ST7789_NUM_DEVICES 1 -#endif - -// Additional configuration options to be copied to your keyboard's config.h (don't change here): - -// If you know exactly which offsets should be used on your panel with respect to selected rotation, then this config -// option allows you to save some flash space -- you'll need to invoke qp_set_viewport_offsets() instead from your keyboard. -// #define ST7789_NO_AUTOMATIC_VIEWPORT_OFFSETS - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST7789 device factories - -#ifdef QUANTUM_PAINTER_ST7789_SPI_ENABLE -/** - * Factory method for an ST7789 SPI LCD device. - * - * @param panel_width[in] the width of the display panel - * @param panel_height[in] the height of the display panel - * @param chip_select_pin[in] the GPIO pin used for SPI chip select - * @param dc_pin[in] the GPIO pin used for D/C control - * @param reset_pin[in] the GPIO pin used for RST - * @param spi_divisor[in] the SPI divisor to use when communicating with the display - * @param spi_mode[in] the SPI mode to use when communicating with the display - * @return the device handle used with all drawing routines in Quantum Painter - */ -painter_device_t qp_st7789_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); -#endif // QUANTUM_PAINTER_ST7789_SPI_ENABLE diff --git a/drivers/eeprom/painter/st77xx/qp_st7789_opcodes.h b/drivers/eeprom/painter/st77xx/qp_st7789_opcodes.h deleted file mode 100644 index 4b46f994b4..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st7789_opcodes.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST7789 additional command opcodes - -// System function commands -#define ST7789_GET_SELF_DIAG 0x0F // Get self-diagnostic result -#define ST7789_SET_VERT_SCRL 0x33 // Set vertical scroll definition -#define ST7789_SET_VERT_SCRL_ADDR 0x37 // SEt Vertical scroll start address -#define ST7789_SET_MEM_CONT 0x3C // Memory Write continue -#define ST7789_GET_MEM_CONT 0x3E // Memory Read continue -#define ST7789_SET_TEAR_LINE 0x44 // Set tear scanline -#define ST7789_GET_TEAR_LINE 0x45 // Get tear scanline -#define ST7789_SET_BRIGHTNESS 0x51 // Set display brightness -#define ST7789_GET_BRIGHTNESS 0x52 // Get display brightness -#define ST7789_SET_CTRL 0x53 // Set CTRL display -#define ST7789_GET_CTRL 0x54 // Get CTRL display value -#define ST7789_SET_CAB_COLOR 0x55 // Set content adaptive brightness control and color enhancement -#define ST7789_GET_CAB_COLOR 0x56 // Get content adaptive brightness control and color enhancement -#define ST7789_SET_CAB_BRIGHTNESS 0x5E // Set content adaptive minimum brightness -#define ST7789_GET_CAB_BRIGHTNESS 0x5F // Get content adaptive minimum brightness -#define ST7789_GET_ABC_SELF_DIAG 0x68 // Get Auto brightness control self diagnostics - -// Panel Function Commands -#define ST7789_SET_RAM_CTL 0xB0 // Set RAM control -#define ST7789_SET_RGB_CTL 0xB1 // Set RGB control -#define ST7789_SET_PORCH_CTL 0xB2 // Set Porch control -#define ST7789_SET_FRAME_RATE_CTL_1 0xB3 // Set frame rate control 1 -#define ST7789_SET_PARTIAL_CTL 0xB5 // Set Partial control -#define ST7789_SET_GATE_CTL 0xB7 // Set gate control -#define ST7789_SET_GATE_ON_TIMING 0xB8 // Set gate on timing adjustment -#define ST7789_SET_DIGITAL_GAMMA_ON 0xBA // Enable digital gamma -#define ST7789_SET_VCOM 0xBB // Set VCOM -#define ST7789_SET_POWER_SAVE 0xBC // Set power saving mode -#define ST7789_SET_DISP_OFF_POWER 0xBD // Set display off power saving -#define ST7789_SET_LCM_CTL 0xC0 // Set LCM control -#define ST7789_SET_IDS 0xC1 // Set IDs -#define ST7789_SET_VDV_VRH_ON 0xC2 // Set VDV and VRH command enable -#define ST7789_SET_VRH 0xC3 // Set VRH -#define ST7789_SET_VDV 0xC4 // Set VDV -#define ST7789_SET_VCOM_OFFSET 0xC5 // Set VCOM offset ctl -#define ST7789_SET_FRAME_RATE_CTL_2 0xC6 // Set frame rate control 2 -#define ST7789_SET_CABC_CTL 0xC7 // Set CABC Control -#define ST7789_GET_REG_1 0xC8 // Get register value selection1 -#define ST7789_GET_REG_2 0xCA // Get register value selection2 -#define ST7789_SET_PWM_FREQ 0xCC // Set PWM frequency -#define ST7789_SET_POWER_CTL_1 0xD0 // Set power ctl 1 -#define ST7789_SET_VAP_VAN_ON 0xD2 // Enable VAP/VAN signal output -#define ST7789_SET_CMD2_ENABLE 0xDF // Enable command 2 -#define ST7789_SET_PGAMMA 0xE0 // Set positive gamma -#define ST7789_SET_NGAMMA 0xE1 // Set negative gamma -#define ST7789_SET_DIGITAL_GAMMA_RED 0xE2 // Set digital gamma lookup table for red -#define ST7789_SET_DIGITAL_GAMMA_BLUE 0xE3 // Get digital gamma lookup table for blue -#define ST7789_SET_GATE_CTL_2 0xE4 // Set gate control 2 -#define ST7789_SET_SPI2_ENABLE 0xE7 // Enable SPI2 -#define ST7789_SET_POWER_CTL_2 0xE8 // Set power ctl 2 -#define ST7789_SET_EQ_TIME_CTL 0xE9 // Set equalize time control -#define ST7789_SET_PROG_CTL 0xEC // Set program control -#define ST7789_SET_PROG_MODE_ENABLE 0xFA // Set program mode enable -#define ST7789_SET_NVMEM 0xFC // Set NVMEM data -#define ST7789_SET_PROG_ACTION 0xFE // Set program action diff --git a/drivers/eeprom/painter/st77xx/qp_st77xx_opcodes.h b/drivers/eeprom/painter/st77xx/qp_st77xx_opcodes.h deleted file mode 100644 index c01e2b21e6..0000000000 --- a/drivers/eeprom/painter/st77xx/qp_st77xx_opcodes.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 Paul Cotter (@gr1mr3aver) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter ST77XX command opcodes - -// System function commands -#define ST77XX_CMD_NOP 0x00 // No operation -#define ST77XX_CMD_RESET 0x01 // Software reset -#define ST77XX_GET_ID_INFO 0x04 // Get ID information -#define ST77XX_GET_STATUS 0x09 // Get status -#define ST77XX_GET_PWR_MODE 0x0A // Get power mode -#define ST77XX_GET_MADCTL 0x0B // Get mem access ctl -#define ST77XX_GET_PIX_FMT 0x0C // Get pixel format -#define ST77XX_GET_IMG_FMT 0x0D // Get image format -#define ST77XX_GET_SIG_MODE 0x0E // Get signal mode -#define ST77XX_CMD_SLEEP_ON 0x10 // Enter sleep mode -#define ST77XX_CMD_SLEEP_OFF 0x11 // Exist sleep mode -#define ST77XX_CMD_PARTIAL_ON 0x12 // Enter partial mode -#define ST77XX_CMD_NORMAL_ON 0x13 // Exit partial mode -#define ST77XX_CMD_INVERT_OFF 0x20 // Exit inverted mode -#define ST77XX_CMD_INVERT_ON 0x21 // Enter inverted mode -#define ST77XX_SET_GAMMA 0x26 // Set gamma params -#define ST77XX_CMD_DISPLAY_OFF 0x28 // Disable display -#define ST77XX_CMD_DISPLAY_ON 0x29 // Enable display -#define ST77XX_SET_COL_ADDR 0x2A // Set column address -#define ST77XX_SET_ROW_ADDR 0x2B // Set page (row) address -#define ST77XX_SET_MEM 0x2C // Set memory -#define ST77XX_GET_MEM 0x2E // Get memory -#define ST77XX_SET_PARTIAL_AREA 0x30 // Set partial area -#define ST77XX_CMD_TEARING_OFF 0x34 // Tearing line disabled -#define ST77XX_CMD_TEARING_ON 0x35 // Tearing line enabled -#define ST77XX_SET_MADCTL 0x36 // Set mem access ctl -#define ST77XX_CMD_IDLE_OFF 0x38 // Exit idle mode -#define ST77XX_CMD_IDLE_ON 0x39 // Enter idle mode -#define ST77XX_SET_PIX_FMT 0x3A // Set pixel format -#define ST77XX_GET_ID1 0xDA // Get ID1 -#define ST77XX_GET_ID2 0xDB // Get ID2 -#define ST77XX_GET_ID3 0xDC // Get ID3 - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// MADCTL Flags -#define ST77XX_MADCTL_MY 0b10000000 -#define ST77XX_MADCTL_MX 0b01000000 -#define ST77XX_MADCTL_MV 0b00100000 -#define ST77XX_MADCTL_ML 0b00010000 -#define ST77XX_MADCTL_RGB 0b00000000 -#define ST77XX_MADCTL_BGR 0b00001000 -#define ST77XX_MADCTL_MH 0b00000100 diff --git a/drivers/eeprom/painter/tft_panel/qp_tft_panel.c b/drivers/eeprom/painter/tft_panel/qp_tft_panel.c deleted file mode 100644 index 16dba9d6a6..0000000000 --- a/drivers/eeprom/painter/tft_panel/qp_tft_panel.c +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "color.h" -#include "qp_internal.h" -#include "qp_comms.h" -#include "qp_draw.h" -#include "qp_tft_panel.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Quantum Painter API implementations - -// Power control -bool qp_tft_panel_power(painter_device_t device, bool power_on) { - painter_driver_t * driver = (painter_driver_t *)device; - tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable; - qp_comms_command(device, power_on ? vtable->opcodes.display_on : vtable->opcodes.display_off); - return true; -} - -// Screen clear -bool qp_tft_panel_clear(painter_device_t device) { - painter_driver_t *driver = (painter_driver_t *)device; - driver->driver_vtable->init(device, driver->rotation); // Re-init the LCD - return true; -} - -// Screen flush -bool qp_tft_panel_flush(painter_device_t device) { - // No-op, as there's no framebuffer in RAM for this device. - return true; -} - -// Viewport to draw to -bool qp_tft_panel_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) { - painter_driver_t * driver = (painter_driver_t *)device; - tft_panel_dc_reset_painter_driver_vtable_t *vtable = (tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable; - - // Fix up the drawing location if required - left += driver->offset_x; - right += driver->offset_x; - top += driver->offset_y; - bottom += driver->offset_y; - - // Check if we need to manually swap the window coordinates based on whether or not we're in a sideways rotation - if (vtable->swap_window_coords && (driver->rotation == QP_ROTATION_90 || driver->rotation == QP_ROTATION_270)) { - uint16_t temp; - - temp = left; - left = top; - top = temp; - - temp = right; - right = bottom; - bottom = temp; - } - - if (vtable->num_window_bytes == 1) { - // Set up the x-window - uint8_t xbuf[2] = {left & 0xFF, right & 0xFF}; - qp_comms_command_databuf(device, vtable->opcodes.set_column_address, xbuf, sizeof(xbuf)); - - // Set up the y-window - uint8_t ybuf[2] = {top & 0xFF, bottom & 0xFF}; - qp_comms_command_databuf(device, vtable->opcodes.set_row_address, ybuf, sizeof(ybuf)); - } else if (vtable->num_window_bytes == 2) { - // Set up the x-window - uint8_t xbuf[4] = {left >> 8, left & 0xFF, right >> 8, right & 0xFF}; - qp_comms_command_databuf(device, vtable->opcodes.set_column_address, xbuf, sizeof(xbuf)); - - // Set up the y-window - uint8_t ybuf[4] = {top >> 8, top & 0xFF, bottom >> 8, bottom & 0xFF}; - qp_comms_command_databuf(device, vtable->opcodes.set_row_address, ybuf, sizeof(ybuf)); - } - - // Lock in the window - qp_comms_command(device, vtable->opcodes.enable_writes); - return true; -} - -// Stream pixel data to the current write position in GRAM -bool qp_tft_panel_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) { - painter_driver_t *driver = (painter_driver_t *)device; - qp_comms_send(device, pixel_data, native_pixel_count * driver->native_bits_per_pixel / 8); - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Convert supplied palette entries into their native equivalents - -bool qp_tft_panel_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) { - for (int16_t i = 0; i < palette_size; ++i) { - RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v}); - uint16_t rgb565 = (((uint16_t)rgb.r) >> 3) << 11 | (((uint16_t)rgb.g) >> 2) << 5 | (((uint16_t)rgb.b) >> 3); - palette[i].rgb565 = __builtin_bswap16(rgb565); - } - return true; -} - -bool qp_tft_panel_palette_convert_rgb888(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) { - for (int16_t i = 0; i < palette_size; ++i) { - RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v}); - palette[i].rgb888.r = rgb.r; - palette[i].rgb888.g = rgb.g; - palette[i].rgb888.b = rgb.b; - } - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Append pixels to the target location, keyed by the pixel index - -bool qp_tft_panel_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) { - uint16_t *buf = (uint16_t *)target_buffer; - for (uint32_t i = 0; i < pixel_count; ++i) { - buf[pixel_offset + i] = palette[palette_indices[i]].rgb565; - } - return true; -} - -bool qp_tft_panel_append_pixels_rgb888(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) { - for (uint32_t i = 0; i < pixel_count; ++i) { - target_buffer[(pixel_offset + i) * 3 + 0] = palette[palette_indices[i]].rgb888.r; - target_buffer[(pixel_offset + i) * 3 + 1] = palette[palette_indices[i]].rgb888.g; - target_buffer[(pixel_offset + i) * 3 + 2] = palette[palette_indices[i]].rgb888.b; - } - return true; -} - -bool qp_tft_panel_append_pixdata(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte) { - target_buffer[pixdata_offset] = pixdata_byte; - return true; -} diff --git a/drivers/eeprom/painter/tft_panel/qp_tft_panel.h b/drivers/eeprom/painter/tft_panel/qp_tft_panel.h deleted file mode 100644 index 3b184f2eba..0000000000 --- a/drivers/eeprom/painter/tft_panel/qp_tft_panel.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2021 Nick Brassel (@tzarc) -// SPDX-License-Identifier: GPL-2.0-or-later -#pragma once - -#include "color.h" -#include "qp_internal.h" - -#ifdef QUANTUM_PAINTER_SPI_ENABLE -# include "qp_comms_spi.h" -#endif // QUANTUM_PAINTER_SPI_ENABLE - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Common TFT panel implementation using D/C, and RST pins. - -// Driver vtable with extras -typedef struct tft_panel_dc_reset_painter_driver_vtable_t { - painter_driver_vtable_t base; // must be first, so it can be cast to/from the painter_driver_vtable_t* type - - // Number of bytes for transmitting x/y coordinates - uint8_t num_window_bytes; - - // Whether or not the x/y coords should be swapped on 90/270 rotation - bool swap_window_coords; - - // Opcodes for normal display operation - struct { - uint8_t display_on; - uint8_t display_off; - uint8_t set_column_address; - uint8_t set_row_address; - uint8_t enable_writes; - } opcodes; -} tft_panel_dc_reset_painter_driver_vtable_t; - -// Device definition -typedef struct tft_panel_dc_reset_painter_device_t { - painter_driver_t base; // must be first, so it can be cast to/from the painter_device_t* type - - union { -#ifdef QUANTUM_PAINTER_SPI_ENABLE - // SPI-based configurables - qp_comms_spi_dc_reset_config_t spi_dc_reset_config; -#endif // QUANTUM_PAINTER_SPI_ENABLE - - // TODO: I2C/parallel etc. - }; -} tft_panel_dc_reset_painter_device_t; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Forward declarations for injecting into concrete driver vtables - -bool qp_tft_panel_power(painter_device_t device, bool power_on); -bool qp_tft_panel_clear(painter_device_t device); -bool qp_tft_panel_flush(painter_device_t device); -bool qp_tft_panel_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom); -bool qp_tft_panel_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count); - -bool qp_tft_panel_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette); -bool qp_tft_panel_palette_convert_rgb888(painter_device_t device, int16_t palette_size, qp_pixel_t *palette); - -bool qp_tft_panel_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices); -bool qp_tft_panel_append_pixels_rgb888(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices); - -bool qp_tft_panel_append_pixdata(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte);