-
-
Notifications
You must be signed in to change notification settings - Fork 40.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ST7735 driver to Quantum Painter (#17848)
- Loading branch information
1 parent
09ea5f6
commit 2bdd73f
Showing
6 changed files
with
264 additions
and
2 deletions.
There are no files selected for viewing
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
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,144 @@ | ||
// Copyright 2021 Paul Cotter (@gr1mr3aver) | ||
// Copyright 2021 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) { | ||
struct painter_driver_t *driver = (struct 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 | ||
|
||
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, | ||
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 struct 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, | ||
}, | ||
.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 struct painter_driver_vtable_t *)&st7735_driver_vtable; | ||
driver->base.comms_vtable = (const struct 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; | ||
return (painter_device_t)driver; | ||
} | ||
} | ||
return NULL; | ||
} | ||
|
||
#endif // QUANTUM_PAINTER_ST7735_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,45 @@ | ||
// 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 |
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,31 @@ | ||
// 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 |
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
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