Add LD7032 support to QP. (#20828)

Co-authored-by: Nick Brassel <nick@tzarc.org>
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
This commit is contained in:
Dasky 2024-09-18 12:44:33 +01:00 committed by GitHub
parent 7983f7409b
commit 49e339ba8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 591 additions and 1 deletions

View File

@ -28,6 +28,8 @@ Supported devices:
| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9341_spi` |
| ILI9486 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9486_spi` |
| ILI9488 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ili9488_spi` |
| LD7032 (SPI) | Monochrome OLED | 128x40 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ld7032_spi` |
| LD7032 (I2C) | Monochrome OLED | 128x40 | I2C | `QUANTUM_PAINTER_DRIVERS += ld7032_i2c` |
| SSD1351 | RGB OLED | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += ssd1351_spi` |
| ST7735 | RGB LCD | 132x162, 80x160 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7735_spi` |
| ST7789 | RGB LCD | 240x320, 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS += st7789_spi` |
@ -478,6 +480,40 @@ Native color format mono2 is compatible with SH1106
SSD1306 and SH1106 are almost entirely identical, to the point of being indisinguishable by Quantum Painter. Enable SH1106 support in Quantum Painter and create SH1106 devices in firmware to perform drawing operations on SSD1306 displays.
==== LD7032
Enabling support for the LD7032 in Quantum Painter is done by adding the following to `rules.mk`:
```make
QUANTUM_PAINTER_ENABLE = yes
# For SPI:
QUANTUM_PAINTER_DRIVERS += ld7032_spi
# For I2C:
QUANTUM_PAINTER_DRIVERS += ld7032_i2c
```
Creating a SH1106 device in firmware can then be done with the following APIs:
```c
// SPI-based LD7032:
painter_device_t qp_ld7032_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);
// I2C-based LD7032:
painter_device_t qp_ld7032_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address);
```
The device handle returned from the `qp_ld7032_make_???_device` function can be used to perform all other drawing operations.
The maximum number of displays of each type can be configured by changing the following in your `config.h` (default is 1):
```c
// 3 SPI displays:
#define LD7032_NUM_SPI_DEVICES 3
// 3 I2C displays:
#define LD7032_NUM_I2C_DEVICES 3
```
Native color format mono2 is compatible with LD7032.
:::::
===== Surface

View File

@ -0,0 +1,411 @@
// Copyright 2023 Nick Brassel (@tzarc)
// Copyright 2023 Dasky (@daskygit)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "qp_internal.h"
#include "qp_comms.h"
#include "qp_oled_panel.h"
#include "qp_ld7032.h"
#include "qp_ld7032_opcodes.h"
#include "qp_surface.h"
#include "qp_surface_internal.h"
typedef void (*ld7032_driver_comms_send_command_and_data_func)(painter_device_t device, uint8_t cmd, uint8_t data);
typedef uint32_t (*ld7032_driver_comms_send_command_and_databuf_func)(painter_device_t device, uint8_t cmd, const void *data, uint32_t byte_count);
typedef struct ld7032_comms_with_command_vtable_t {
painter_comms_vtable_t base; // must be first, so this object can be cast from the painter_comms_vtable_t* type
painter_driver_comms_send_command_func send_command;
painter_driver_comms_bulk_command_sequence bulk_command_sequence;
ld7032_driver_comms_send_command_and_data_func send_command_data;
ld7032_driver_comms_send_command_and_databuf_func send_command_databuf;
} ld7032_comms_with_command_vtable_t;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LD7032 Internal API
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ld7032_comms_i2c_send_command_and_data(painter_device_t device, uint8_t cmd, uint8_t data) {
uint8_t buf[2] = {cmd, data};
qp_comms_i2c_send_data(device, buf, 2);
}
void ld7032_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] = command;
memcpy(&buf[1], &sequence[i + 3], num_bytes);
qp_comms_i2c_send_data(device, buf, num_bytes + 1);
if (delay > 0) {
wait_ms(delay);
}
i += (3 + num_bytes);
}
}
uint32_t ld7032_comms_i2c_send_command_and_databuf(painter_device_t device, uint8_t cmd, const void *data, uint32_t byte_count) {
uint8_t buf[byte_count + 1];
memset(buf, 0, sizeof(buf));
buf[0] = cmd;
memcpy(&buf[1], data, byte_count);
return qp_comms_send(device, buf, byte_count + 1);
}
// Power control
bool qp_ld7032_power(painter_device_t device, bool power_on) {
painter_driver_t * driver = (painter_driver_t *)device;
ld7032_comms_with_command_vtable_t *comms_vtable = (ld7032_comms_with_command_vtable_t *)driver->comms_vtable;
comms_vtable->send_command_data(device, LD7032_DISP_ON_OFF, power_on ? 0x01 : 0x00);
return true;
}
// Screen clear
bool qp_ld7032_clear(painter_device_t device) {
qp_rect(device, 0, 0, 127, 127, 0, 0, 0, true); // clear memory
painter_driver_t *driver = (painter_driver_t *)device;
driver->driver_vtable->init(device, driver->rotation); // Re-init the display
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Flush helpers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ld7032_flush_0(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer, bool inverted) {
painter_driver_t * driver = (painter_driver_t *)device;
ld7032_comms_with_command_vtable_t *comms_vtable = (ld7032_comms_with_command_vtable_t *)driver->comms_vtable;
int x_start = dirty->l >> 3;
int x_end = dirty->r >> 3;
int y_start = dirty->t;
int y_end = dirty->b;
int x_length = (x_end - x_start) + 1;
uint8_t x_view_offset = driver->offset_x >> 3;
uint8_t y_view_offset = driver->offset_y;
for (int y_pos = y_start; y_pos <= y_end; y_pos++) {
int y_new_pos = y_pos;
if (inverted) {
y_new_pos = y_end - y_pos;
}
uint8_t packet[x_length];
memcpy(packet, &framebuffer[(y_pos * (driver->panel_width >> 3)) + x_start], x_length);
uint8_t x_write_start = MIN(x_start + x_view_offset, (128 >> 3));
uint8_t x_write_end = MIN(x_end + x_view_offset, (128 >> 3));
uint8_t y_write_start = MIN(y_new_pos + y_view_offset, 39);
uint8_t y_write_end = MIN(y_new_pos + y_view_offset, 39);
comms_vtable->send_command_data(device, LD7032_X_BOX_ADR_START, x_write_start);
comms_vtable->send_command_data(device, LD7032_X_BOX_ADR_END, x_write_end);
comms_vtable->send_command_data(device, LD7032_Y_BOX_ADR_START, y_write_start);
comms_vtable->send_command_data(device, LD7032_Y_BOX_ADR_END, y_write_end);
comms_vtable->send_command_databuf(device, LD7032_DATA_RW, packet, x_length);
}
}
void ld7032_flush_90(painter_device_t device, surface_dirty_data_t *dirty, const uint8_t *framebuffer, bool inverted) {
painter_driver_t * driver = (painter_driver_t *)device;
ld7032_comms_with_command_vtable_t *comms_vtable = (ld7032_comms_with_command_vtable_t *)driver->comms_vtable;
int x_start = dirty->t >> 3;
int x_end = dirty->b >> 3;
int y_start = dirty->l;
int y_end = dirty->r;
int x_length = (x_end - x_start) + 1;
uint8_t x_view_offset = driver->offset_x >> 3;
uint8_t y_view_offset = driver->offset_y;
for (int y_pos = y_start; y_pos <= y_end; y_pos++) {
int y_new_pos = y_pos;
if (inverted) {
y_new_pos = y_end - y_pos;
}
uint8_t packet[x_length];
memset(packet, 0, sizeof(packet));
int count = 0;
for (int x_pos = x_start; x_pos <= x_end; x_pos++) {
for (int x = 0; x < 8; ++x) {
uint32_t pixel_num = (((x_pos << 3) + x) * driver->panel_height) + y_pos;
uint32_t byte_offset = pixel_num / 8;
uint8_t bit_offset = pixel_num % 8;
packet[count] |= ((framebuffer[byte_offset] & (1 << bit_offset)) >> bit_offset) << x;
}
count++;
}
uint8_t x_width = (driver->panel_width >> 3) - 1;
uint8_t x_write_start = MAX((int)x_width - x_end - x_view_offset, 0);
uint8_t x_write_end = MAX((int)x_width - x_start - x_view_offset, 0);
uint8_t y_write_start = MIN(y_new_pos + y_view_offset, 39);
uint8_t y_write_end = MIN(y_new_pos + y_view_offset, 39);
comms_vtable->send_command_data(device, LD7032_X_BOX_ADR_START, x_write_start);
comms_vtable->send_command_data(device, LD7032_X_BOX_ADR_END, x_write_end);
comms_vtable->send_command_data(device, LD7032_Y_BOX_ADR_START, y_write_start);
comms_vtable->send_command_data(device, LD7032_Y_BOX_ADR_END, y_write_end);
comms_vtable->send_command_databuf(device, LD7032_DATA_RW, packet, x_length);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver storage
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct ld7032_device_t {
oled_panel_painter_device_t oled;
uint8_t framebuffer[SURFACE_REQUIRED_BUFFER_BYTE_SIZE(128, 40, 1)];
} ld7032_device_t;
static ld7032_device_t ld7032_drivers[LD7032_NUM_DEVICES] = {0};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter API implementations
// Initialisation
__attribute__((weak)) bool qp_ld7032_init(painter_device_t device, painter_rotation_t rotation) {
ld7032_device_t *driver = (ld7032_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_ld7032_init\n");
return false;
}
// clang-format off
const uint8_t ld7032_init_sequence[] = {
// Command, Delay, N, Data[N]
LD7032_DISP_STBY_ON_OFF, 0, 1, 0x00,
LD7032_DISP_ON_OFF, 0, 1, 0x00,
LD7032_DFRAME, 0, 1, 0x05,
//LD7032_WRITE_DIRECTION, 0, 1, 0b00001000, // 0 Right, 1 Up, 2 Vertical, 3 Bit Order, 4-7 Unused
LD7032_DISP_DIRECTION, 0, 1, 0x00,
LD7032_PEAK_WIDTH, 0, 1, 0x1F,
LD7032_PEAK_DELAY, 0, 1, 0x05,
LD7032_SCAN_MODE, 0, 1, 0x01,
LD7032_DOT_CURRENT, 0, 1, 0x1f,
LD7032_VDD_SEL, 0, 1, 0x01,
};
// clang-format on
qp_comms_bulk_command_sequence(device, ld7032_init_sequence, sizeof(ld7032_init_sequence));
uint8_t display_y_start = 40 - driver->oled.base.panel_height;
uint8_t display_x_start = (128 - driver->oled.base.panel_width) / 2;
// clang-format off
uint8_t ld7032_memory_setup[] = {
// Command, Delay, N, Data[N]
LD7032_DISP_SIZE_X, 0, 2, 0x00, 0x7F,
LD7032_DISP_SIZE_Y, 0, 2, 0x00, 0x27,
LD7032_X_DISP_START, 0, 1, 0x0,
LD7032_Y_DISP_START, 0, 1, 0x0,
};
// clang-format on
ld7032_memory_setup[3] = display_x_start;
ld7032_memory_setup[4] = display_x_start + driver->oled.base.panel_width - 1;
ld7032_memory_setup[8] = display_y_start;
ld7032_memory_setup[9] = display_y_start + driver->oled.base.panel_height - 1;
ld7032_memory_setup[13] = ld7032_memory_setup[4] + 1;
ld7032_memory_setup[17] = driver->oled.base.panel_height;
qp_comms_bulk_command_sequence(device, ld7032_memory_setup, sizeof(ld7032_memory_setup));
uint8_t write_direction = 0;
switch (rotation) {
default:
case QP_ROTATION_0:
write_direction = 0b00001000;
break;
case QP_ROTATION_90:
write_direction = 0b00000001;
break;
case QP_ROTATION_180:
write_direction = 0b00000001;
break;
case QP_ROTATION_270:
write_direction = 0b00001000;
break;
}
painter_driver_t * pdriver = (painter_driver_t *)device;
ld7032_comms_with_command_vtable_t *comms_vtable = (ld7032_comms_with_command_vtable_t *)pdriver->comms_vtable;
comms_vtable->send_command_data(device, LD7032_WRITE_DIRECTION, write_direction);
qp_ld7032_power(device, true);
return true;
}
// Screen flush
bool qp_ld7032_flush(painter_device_t device) {
ld7032_device_t *driver = (ld7032_device_t *)device;
if (!driver->oled.surface.dirty.is_dirty) {
return true;
}
switch (driver->oled.base.rotation) {
default:
case QP_ROTATION_0:
ld7032_flush_0(device, &driver->oled.surface.dirty, driver->framebuffer, false);
break;
case QP_ROTATION_180:
ld7032_flush_0(device, &driver->oled.surface.dirty, driver->framebuffer, true);
break;
case QP_ROTATION_90:
ld7032_flush_90(device, &driver->oled.surface.dirty, driver->framebuffer, false);
break;
case QP_ROTATION_270:
ld7032_flush_90(device, &driver->oled.surface.dirty, driver->framebuffer, true);
break;
}
// Clear the dirty area
qp_flush(&driver->oled.surface);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Driver vtable
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const painter_driver_vtable_t ld7032_driver_vtable = {
.init = qp_ld7032_init,
.power = qp_ld7032_power,
.clear = qp_ld7032_clear,
.flush = qp_ld7032_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,
};
#ifdef QUANTUM_PAINTER_LD7032_SPI_ENABLE
const ld7032_comms_with_command_vtable_t ld7032_spi_comms_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,
.send_command_data = qp_comms_command_databyte,
.send_command_databuf = qp_comms_command_databuf,
.bulk_command_sequence = qp_comms_spi_dc_reset_bulk_command_sequence,
};
// Factory function for creating a handle to the LD7032 device
painter_device_t qp_ld7032_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 < LD7032_NUM_DEVICES; ++i) {
ld7032_device_t *driver = &ld7032_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 *)&ld7032_driver_vtable;
driver->oled.base.comms_vtable = (const painter_comms_vtable_t *)&ld7032_spi_comms_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(ld7032_device_t));
return NULL;
}
return (painter_device_t)driver;
}
}
return NULL;
}
#endif // QUANTUM_PAINTER_LD7032_SPI_ENABLE
#ifdef QUANTUM_PAINTER_LD7032_I2C_ENABLE
const ld7032_comms_with_command_vtable_t ld7032_i2c_comms_vtable = {
.base =
{
.comms_init = qp_comms_i2c_init,
.comms_start = qp_comms_i2c_start,
.comms_send = qp_comms_i2c_send_data,
.comms_stop = qp_comms_i2c_stop,
},
.send_command = NULL,
.send_command_data = ld7032_comms_i2c_send_command_and_data,
.send_command_databuf = ld7032_comms_i2c_send_command_and_databuf,
.bulk_command_sequence = ld7032_comms_i2c_bulk_command_sequence,
};
// Factory function for creating a handle to the LD7032 device
painter_device_t qp_ld7032_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address) {
for (uint32_t i = 0; i < LD7032_NUM_DEVICES; ++i) {
ld7032_device_t *driver = &ld7032_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 *)&ld7032_driver_vtable;
driver->oled.base.comms_vtable = (const painter_comms_vtable_t *)&ld7032_i2c_comms_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(ld7032_device_t));
return NULL;
}
return (painter_device_t)driver;
}
}
return NULL;
}
#endif // QUANTUM_PAINTER_LD7032_SPI_ENABLE

View File

@ -0,0 +1,66 @@
// Copyright 2023 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "gpio.h"
#include "qp_internal.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter LD7032 configurables (add to your keyboard's config.h)
#if defined(QUANTUM_PAINTER_LD7032_SPI_ENABLE) && !defined(LD7032_NUM_SPI_DEVICES)
/**
* @def This controls the maximum number of SPI LD7032 devices that Quantum Painter can communicate with at any one time.
* Increasing this number allows for multiple displays to be used.
*/
# define LD7032_NUM_SPI_DEVICES 1
#else
# define LD7032_NUM_SPI_DEVICES 0
#endif
#if defined(QUANTUM_PAINTER_LD7032_I2C_ENABLE) && !defined(LD7032_NUM_I2C_DEVICES)
/**
* @def This controls the maximum number of I2C LD7032 devices that Quantum Painter can communicate with at any one time.
* Increasing this number allows for multiple displays to be used.
*/
# define LD7032_NUM_I2C_DEVICES 1
#else
# define LD7032_NUM_I2C_DEVICES 0
#endif
#define LD7032_NUM_DEVICES ((LD7032_NUM_SPI_DEVICES) + (LD7032_NUM_I2C_DEVICES))
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter LD7032 device factories
#ifdef QUANTUM_PAINTER_LD7032_SPI_ENABLE
/**
* Factory method for an LD7032 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_ld7032_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_LD7032_SPI_ENABLE
#ifdef QUANTUM_PAINTER_LD7032_I2C_ENABLE
/**
* Factory method for an LD7032 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_ld7032_make_i2c_device(uint16_t panel_width, uint16_t panel_height, uint8_t i2c_address);
#endif // QUANTUM_PAINTER_LD7032_I2C_ENABLE

View File

@ -0,0 +1,45 @@
// Copyright 2023 Dasky (@daskygit)
// SPDX-License-Identifier: GPL-2.0-or-later
typedef enum {
LD7032_SOFTRES = 0x01,
LD7032_DISP_ON_OFF = 0x02,
LD7032_DATA_RW = 0x08,
LD7032_DISP_DIRECTION = 0x09,
LD7032_IFMODE = 0x0D,
LD7032_PEAK_WIDTH = 0x10,
LD7032_DOT_CURRENT = 0x12,
LD7032_SCAN_MODE = 0x13,
LD7032_DISP_STBY_ON_OFF = 0x14,
LD7032_PEAK_DELAY = 0x16,
LD7032_ROW_SCAN = 0x17,
LD7032_PRE_C_WIDTH = 0x18,
LD7032_DFRAME = 0x1A,
LD7032_DATA_REVERSE = 0x1C,
LD7032_WRITE_DIRECTION = 0x1D,
LD7032_READREG = 0x20,
LD7032_DISP_SIZE_X = 0x30,
LD7032_DISP_SIZE_Y = 0x32,
LD7032_X_BOX_ADR_START = 0x34,
LD7032_X_BOX_ADR_END = 0x35,
LD7032_Y_BOX_ADR_START = 0x36,
LD7032_Y_BOX_ADR_END = 0x37,
LD7032_X_DISP_START = 0x38,
LD7032_Y_DISP_START = 0x39,
LD7032_XTALK_EN = 0x3A,
LD7032_XTALK_REF = 0x3B,
LD7032_AGING_EN = 0x3C,
LD7032_VDD_SEL = 0x3D,
LD7032_TESTCNT0 = 0x3E,
LD7032_VCC_R_SEL = 0x3F,
LD7032_PRE_C_SELECT = 0x44,
LD7032_ROW_OVERLAP = 0x48,
LD7032_S_SLEEP_TIMER = 0xC0,
LD7032_S_SLEEP_START = 0xC2,
LD7032_S_STEP_TIMER = 0xC3,
LD7032_S_STEP_UNIT = 0xC4,
LD7032_S_CONDITION = 0xCC,
LD7032_S_START_STOP = 0xCD,
LD7032_S_SELECT = 0xCE,
LD7032_TESTCNT1 = 0xF0, //-0xFF
} ld7032_opcodes;

View File

@ -557,6 +557,12 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai
# define SH1106_NUM_DEVICES 0
#endif // QUANTUM_PAINTER_SH1106_ENABLE
#ifdef QUANTUM_PAINTER_LD7032_ENABLE
# include "qp_ld7032.h"
#else // QUANTUM_PAINTER_LD7032_ENABLE
# define LD7032_NUM_DEVICES 0
#endif // QUANTUM_PAINTER_LD7032_ENABLE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter Extras

View File

@ -19,6 +19,7 @@ enum {
+ (GC9107_NUM_DEVICES) // GC9107
+ (SSD1351_NUM_DEVICES) // SSD1351
+ (SH1106_NUM_DEVICES) // SH1106
+ (LD7032_NUM_DEVICES) // LD7032
};
static painter_device_t qp_devices[QP_NUM_DEVICES] = {NULL};

View File

@ -17,7 +17,9 @@ VALID_QUANTUM_PAINTER_DRIVERS := \
gc9107_spi \
ssd1351_spi \
sh1106_i2c \
sh1106_spi
sh1106_spi \
ld7032_i2c \
ld7032_spi
#-------------------------------------------------------------------------------
@ -182,6 +184,29 @@ define handle_quantum_painter_driver
$(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
$(DRIVER_PATH)/painter/sh1106/qp_sh1106.c
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ld7032_spi)
QUANTUM_PAINTER_NEEDS_SURFACE := yes
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
OPT_DEFS += -DQUANTUM_PAINTER_LD7032_ENABLE -DQUANTUM_PAINTER_LD7032_SPI_ENABLE
COMMON_VPATH += \
$(DRIVER_PATH)/painter/oled_panel \
$(DRIVER_PATH)/painter/ld7032
SRC += \
$(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
$(DRIVER_PATH)/painter/ld7032/qp_ld7032.c
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ld7032_i2c)
QUANTUM_PAINTER_NEEDS_SURFACE := yes
QUANTUM_PAINTER_NEEDS_COMMS_I2C := yes
OPT_DEFS += -DQUANTUM_PAINTER_LD7032_ENABLE -DQUANTUM_PAINTER_LD7032_I2C_ENABLE
COMMON_VPATH += \
$(DRIVER_PATH)/painter/oled_panel \
$(DRIVER_PATH)/painter/ld7032
SRC += \
$(DRIVER_PATH)/painter/oled_panel/qp_oled_panel.c \
$(DRIVER_PATH)/painter/ld7032/qp_ld7032.c
endif
endef