forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GC9xxx LCD family drivers (GC9107 and GC9A01) (qmk#23091)
Co-authored-by: Nick Brassel <nick@tzarc.org> Co-authored-by: jack <0x6A73@pm.me> Co-authored-by: Joel Challis <git@zvecr.com> Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com> Co-authored-by: rookiebwoy <81021475+rookiebwoy@users.noreply.github.com> Fixup boardsource/equals (qmk#23106) Fix make clean test:os_detection (qmk#23112) Fix make clean test:os_detection (qmk#23112)" Fixup boardsource/equals (qmk#23106)"
- Loading branch information
Showing
11 changed files
with
490 additions
and
133 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright 2024 Fernando Birra | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#include "qp_internal.h" | ||
#include "qp_comms.h" | ||
#include "qp_gc9107.h" | ||
#include "qp_gc9xxx_opcodes.h" | ||
#include "qp_gc9107_opcodes.h" | ||
#include "qp_tft_panel.h" | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Driver storage | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
tft_panel_dc_reset_painter_device_t gc9107_drivers[GC9107_NUM_DEVICES] = {0}; | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Initialization | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
__attribute__((weak)) bool qp_gc9107_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 gc9107_init_sequence[] = { | ||
GC9XXX_SET_INTER_REG_ENABLE1, 5, 0, | ||
GC9XXX_SET_INTER_REG_ENABLE2, 5, 0, | ||
GC9107_SET_FUNCTION_CTL6, 0, 1, GC9107_ALLOW_SET_COMPLEMENT_RGB | 0x08 | GC9107_ALLOW_SET_FRAMERATE, | ||
GC9107_SET_COMPLEMENT_RGB, 0, 1, GC9107_COMPLEMENT_WITH_LSB, | ||
0xAB, 0, 1, 0x0E, | ||
GC9107_SET_FRAME_RATE, 0, 1, 0x19, | ||
GC9XXX_SET_PIXEL_FORMAT, 0, 1, GC9107_PIXEL_FORMAT_16_BPP_IFPF, | ||
GC9XXX_CMD_SLEEP_OFF, 120, 0, | ||
GC9XXX_CMD_DISPLAY_ON, 20, 0 | ||
}; | ||
|
||
// clang-format on | ||
qp_comms_bulk_command_sequence(device, gc9107_init_sequence, sizeof(gc9107_init_sequence)); | ||
|
||
// Configure the rotation (i.e. the ordering and direction of memory writes in GRAM) | ||
const uint8_t madctl[] = { | ||
[QP_ROTATION_0] = GC9XXX_MADCTL_BGR, | ||
[QP_ROTATION_90] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MV, | ||
[QP_ROTATION_180] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MX | GC9XXX_MADCTL_MY, | ||
[QP_ROTATION_270] = GC9XXX_MADCTL_BGR | GC9XXX_MADCTL_MV | GC9XXX_MADCTL_MY, | ||
}; | ||
qp_comms_command_databyte(device, GC9XXX_SET_MEM_ACS_CTL, madctl[rotation]); | ||
|
||
return true; | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Driver vtable | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
const tft_panel_dc_reset_painter_driver_vtable_t gc9107_driver_vtable = { | ||
.base = | ||
{ | ||
.init = qp_gc9107_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 = GC9XXX_CMD_DISPLAY_ON, | ||
.display_off = GC9XXX_CMD_DISPLAY_OFF, | ||
.set_column_address = GC9XXX_SET_COL_ADDR, | ||
.set_row_address = GC9XXX_SET_ROW_ADDR, | ||
.enable_writes = GC9XXX_SET_MEM, | ||
}, | ||
}; | ||
|
||
#ifdef QUANTUM_PAINTER_GC9107_SPI_ENABLE | ||
// Factory function for creating a handle to the GC9107 device | ||
painter_device_t qp_gc9107_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 < GC9107_NUM_DEVICES; ++i) { | ||
tft_panel_dc_reset_painter_device_t *driver = &gc9107_drivers[i]; | ||
if (!driver->base.driver_vtable) { | ||
driver->base.driver_vtable = (const painter_driver_vtable_t *)&gc9107_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 = 2; | ||
driver->base.offset_y = 1; | ||
|
||
// 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_GC9107_SPI_ENABLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright 2024 Fernando Birra (@gr1mr3aver) | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#pragma once | ||
|
||
#include "gpio.h" | ||
#include "qp_internal.h" | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Quantum Painter GC9107 configurables (add to your keyboard's config.h) | ||
|
||
#ifndef GC9107_NUM_DEVICES | ||
/** | ||
* @def This controls the maximum number of GC9107 devices that Quantum Painter can communicate with at any one time. | ||
* Increasing this number allows for multiple displays to be used. | ||
*/ | ||
# define GC9107_NUM_DEVICES 1 | ||
#endif | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Quantum Painter GC9107 device factories | ||
|
||
#ifdef QUANTUM_PAINTER_GC9107_SPI_ENABLE | ||
/** | ||
* Factory method for an GC9107 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_gc9107_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_GC9107_SPI_ENABLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2024 Fernando Birra | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
#pragma once | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Quantum Painter GC9107 command opcodes | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#define GC9107_GET_POWER_MODE 0x0A // Get power mode | ||
#define GC9107_GET_MADCTL 0x0B // Get MADCTL | ||
#define GC9107_GET_PIXEL_FMT 0x0C // Get pixel format | ||
#define GC9107_GET_IMAGE_FMT 0x0D // Get image format | ||
#define GC9107_GET_SIGNAL_MODE 0x0E // Get signal mode | ||
#define GC9107_GET_DIAG_RESULT 0x0F // Get self-diagnostic results | ||
|
||
#define GC9107_SET_FRAME_RATE 0xA8 // Set frame rate | ||
#define GC9107_SET_COMPLEMENT_RGB 0xAC // Set complement Principle RGB | ||
#define GC9107_SET_BLANK_PORCH 0xAD // Set blank porch control, 0;front_porch[6:0],0;back_porch[6:0] | ||
#define GC9107_SET_FUNCTION_CTL1 0xB1 // Set access to AVDD_VCL_CLK and VGH_VGL_CLK commands | ||
#define GC9107_SET_FUNCTION_CTL2 0xB2 // Set access to VGH, VGH control commands | ||
#define GC9107_SET_FUNCTION_CTL3 0xB3 // Set access to Gamma control commands | ||
#define GC9107_SET_DISPLAY_INVERSION 0xB4 // Set Display Inversion control | ||
#define GC9107_SET_FUNCTION_CTL6 0xB6 // Set access to commands SET_FRAME_RATE, SET_COMPLEMENT_RGB and SET_BLANK_PORCH | ||
#define GC9107_SET_CUSTOM_ID_INFO 0xD3 // Set customized display id information | ||
#define GC9107_AVDD_VCL_CLK 0xE3 // AVDD_CLK | ||
#define GC9107_SET_VGH 0xE8 // Set VGH | ||
#define GC9107_SET_VGL 0xE9 // Set VGL | ||
#define GC9107_SET_VGH_VGL_CLK 0xEA // Set VGH and VGL clock divisors | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// GC9107 Parameter constants | ||
|
||
// Parameter values for | ||
// GC9107_SET_PIXEL_FORMAT | ||
#define GC9107_PIXEL_FORMAT_12_BPP_IFPF (0b001 << 0) // 12 bits per pixel | ||
#define GC9107_PIXEL_FORMAT_16_BPP_IFPF (0b101 << 0) // 16 bits per pixel | ||
#define GC9107_PIXEL_FORMAT_18_BPP_IFPB (0b110 << 0) // 18 bits per pixel | ||
|
||
// Parameter values for | ||
// GC9107_SET_COMPLEMENT_RGB | ||
#define GC9107_COMPLEMENT_WITH_0 0x00 // R0 <- B0 <- 0, except if data is FFh | ||
#define GC9107_COMPLEMENT_WITH_1 0x40 // R0 <- B0 <- 1, except if data is 00h | ||
#define GC9107_COMPLEMENT_WITH_MSB 0x80 // R0 <- R5, B0 <- B5 | ||
#define GC9107_COMPLEMENT_WITH_LSB 0xC0 // R0 <- B0 <- G0 | ||
// Parameter masks for | ||
// GC9107_SET_FUNCTION_CTL1 | ||
#define GC9107_ALLOW_AVDD_VCL_CLK 0b00001000 // Allow AVDD_VCL_CLK command | ||
// Parameter masks for | ||
// GC9107_SET_FUNCTION_CTL2 | ||
#define GC9107_ALLOW_SET_VGH 0b00000001 // Allow GC9107_SET_VGH | ||
#define GC9107_ALLOW_SET_VGL 0b00000010 // Allow GC9107_SET_VGL | ||
#define GC9107_ALLOW_SET_VGH_VGL_CLK 0b00000100 // Allow GC9107_SET_VGH_VGL_CLK | ||
// Parameter masks for | ||
// GC9107_SET_FUNCTION_CTL3 | ||
#define GC9107_ALLOW_SET_GAMMA1 0b00000001 // Allow GC9107_SET_GAMMA1 | ||
#define GC9107_ALLOW_SET_GAMMA2 0b00000010 // Allow GC9107_SET_GAMMA2 | ||
// Parameter mask for | ||
// GC9107_SET_FUNCTION_CTL6 | ||
#define GC9107_ALLOW_SET_FRAMERATE 0b000000001 // Allow GC9107_SET_FRAME_RATE | ||
#define GC9107_ALLOW_SET_COMPLEMENT_RGB 0b000010000 // Allow GC9107_SET_COMPLEMENT_RGB | ||
#define GC9107_ALLOW_SET_BLANK_PORCH 0b000100000 // Allow GFC9107_SET_BLANK_PORCH | ||
// Parameter values for | ||
// AVDD_CLK_AD part (Most significant nibble) | ||
#define GC9107_AVDD_CLK_AD_2T 0x00 | ||
#define GC9107_AVDD_CLK_AD_3T 0x10 | ||
#define GC9107_AVDD_CLK_AD_4T 0x20 | ||
#define GC9107_AVDD_CLK_AD_5T 0x30 | ||
#define GC9107_AVDD_CLK_AD_6T 0x40 | ||
#define GC9107_AVDD_CLK_AD_7T 0x50 | ||
#define GC9107_AVDD_CLK_AD_8T 0x60 | ||
#define GC9107_AVDD_CLK_AD_9T 0x70 | ||
// Parameter values for | ||
// VCL_CLK_AD part (Least significant nibble) | ||
#define GC9107_VCL_CLK_AD_2T 0x00 | ||
#define GC9107_VCL_CLK_AD_3T 0x01 | ||
#define GC9107_VCL_CLK_AD_4T 0x02 | ||
#define GC9107_VCL_CLK_AD_5T 0x03 | ||
#define GC9107_VCL_CLK_AD_6T 0x04 | ||
#define GC9107_VCL_CLK_AD_7T 0x05 | ||
#define GC9107_VCL_CLK_AD_8T 0x06 | ||
#define GC9107_VCL_CLK_AD_9T 0x07 | ||
// Parameter values for | ||
// GC9107_SET_VGH | ||
#define GC9107_VGH_P100 0x20 // +10 V | ||
#define GC9107_VGH_P110 0x21 // +11 V | ||
#define GC9107_VGH_P120 0x22 // +12 V | ||
#define GC9107_VGH_P130 0x23 // +13 V | ||
#define GC9107_VGH_P140 0x24 // +14 V | ||
#define GC9107_VGH_P150 0x25 // +15 V | ||
// Parameter values for | ||
// GC9107_SET_VGL | ||
#define VGL_N_075 0x40 // -7.5 V | ||
#define VGL_N_085 0x41 // -8.5 V | ||
#define VGL_N_095 0x42 // -9.5 V | ||
#define VGL_N_100 0x43 // -10.0 V | ||
#define VGL_N_105 0x44 // -10.5 V | ||
#define VGL_N_110 0x45 // -11.0 V | ||
#define VGL_N_120 0x46 // -12.0 V | ||
#define VGL_N_130 0x47 // -13.0 V | ||
// Parameter masks for | ||
// GC9107_SET_VGH_VGL_CLK (VGH Divisor) | ||
#define GC9107_VGH_CLK_DIV_2 0x00 // Clock divisor = 2 -> 6.0 Mhz | ||
#define GC9107_VGH_CLK_DIV_3 0x10 // Clock divisor = 3 -> 4.0 Mhz | ||
#define GC9107_VGH_CLK_DIV_4 0x20 // Clock divisor = 4 -> 3.0 Mhz | ||
#define GC9107_VGH_CLK_DIV_5 0x30 // Clock divisor = 5 -> 2.4 Mhz | ||
#define GC9107_VGH_CLK_DIV_6 0x40 // Clock divisor = 6 -> 2.0 Mhz | ||
#define GC9107_VGH_CLK_DIV_7 0x50 // Clock divisor = 7 -> 1.7 Mhz | ||
#define GC9107_VGH_CLK_DIV_8 0x60 // Clock divisor = 8 -> 1.5 Mhz | ||
#define GC9107_VGH_CLK_DIV_9 0x70 // Clock divisor = 9 -> 1.3 Mhz | ||
#define GC9107_VGH_CLK_DIV_10 0x80 // Clock divisor = 10 -> 1.2 Mhz | ||
#define GC9107_VGH_CLK_DIV_12 0x90 // Clock divisor = 12 -> 1.0 Mhz | ||
#define GC9107_VGH_CLK_DIV_15 0xA0 // Clock divisor = 15 -> 0.8 Mhz | ||
#define GC9107_VGH_CLK_DIV_20 0xB0 // Clock divisor = 20 -> 0.6 Mhz | ||
#define GC9107_VGH_CLK_DIV_24 0xC0 // Clock divisor = 24 -> 0.5 Mhz | ||
#define GC9107_VGH_CLK_DIV_30 0xD0 // Clock divisor = 30 -> 0.4 Mhz | ||
#define GC9107_VGH_CLK_DIV_40 0xE0 // Clock divisor = 40 -> 0.3 Mhz | ||
#define GC9107_VGH_CLK_DIV_60 0xE0 // Clock divisor = 40 -> 0.2 Mhz | ||
// Parameter masks for | ||
// GC9107_SET_VGH_VGL_CLK (VGL Divisor) | ||
#define GC9107_VGL_CLK_DIV_2 0x00 // Clock divisor = 2 -> 6.0 Mhz | ||
#define GC9107_VGL_CLK_DIV_3 0x01 // Clock divisor = 3 -> 4.0 Mhz | ||
#define GC9107_VGL_CLK_DIV_4 0x02 // Clock divisor = 4 -> 3.0 Mhz | ||
#define GC9107_VGL_CLK_DIV_5 0x03 // Clock divisor = 5 -> 2.4 Mhz | ||
#define GC9107_VGL_CLK_DIV_6 0x04 // Clock divisor = 6 -> 2.0 Mhz | ||
#define GC9107_VGL_CLK_DIV_7 0x05 // Clock divisor = 7 -> 1.7 Mhz | ||
#define GC9107_VGL_CLK_DIV_8 0x06 // Clock divisor = 8 -> 1.5 Mhz | ||
#define GC9107_VGL_CLK_DIV_9 0x07 // Clock divisor = 9 -> 1.3 Mhz | ||
#define GC9107_VGL_CLK_DIV_10 0x08 // Clock divisor = 10 -> 1.2 Mhz | ||
#define GC9107_VGL_CLK_DIV_12 0x09 // Clock divisor = 12 -> 1.0 Mhz | ||
#define GC9107_VGL_CLK_DIV_15 0x0A // Clock divisor = 15 -> 0.8 Mhz | ||
#define GC9107_VGL_CLK_DIV_20 0x0B // Clock divisor = 20 -> 0.6 Mhz | ||
#define GC9107_VGL_CLK_DIV_24 0x0C // Clock divisor = 24 -> 0.5 Mhz | ||
#define GC9107_VGL_CLK_DIV_30 0x0D // Clock divisor = 30 -> 0.4 Mhz | ||
#define GC9107_VGL_CLK_DIV_40 0x0E // Clock divisor = 40 -> 0.3 Mhz | ||
#define GC9107_VGL_CLK_DIV_60 0x0E // Clock divisor = 40 -> 0.2 Mhz |
Oops, something went wrong.