Merge pull request #69 from skie97/fix/c6-co5300-display

This commit is contained in:
Hermann Björgvin
2026-06-08 16:46:23 +00:00
committed by GitHub
4 changed files with 46 additions and 39 deletions
+1 -1
View File
@@ -170,7 +170,7 @@ build_flags =
-DLV_USE_SNAPSHOT=0
lib_deps =
; 1.6.4+ required for Arduino_SH8601 (this board uses SH8601, not CO5300)
; this board uses the CO5300 (same controller as the S3 2.16); Arduino_CO5300
moononournation/GFX Library for Arduino@^1.6.4
lewisxhe/SensorLib@^0.2.6
lewisxhe/XPowersLib@^0.2.7
@@ -3,9 +3,9 @@
// Waveshare ESP32-C6-Touch-AMOLED-2.16.
//
// Despite the matching "2.16" model number, this board is hardware-
// distinct from the S3 AMOLED-2.16: it uses an SH8601 panel (same driver
// family as the AMOLED-1.8), a CST9217 touch controller, and the C6 SoC's
// own GPIO map. There is no PSRAM. AXP2101 PMU and QMI8658 IMU carry over.
// distinct from the S3 AMOLED-2.16: it shares the CO5300 panel controller
// but uses a CST9217 touch controller and the C6 SoC's own GPIO map. There
// is no PSRAM. AXP2101 PMU and QMI8658 IMU carry over.
//
// Pin assignments verified against the official Waveshare XiaoZhi BSP at
// waveshareteam/ESP32-C6-Touch-AMOLED-2.16 (XiaoZhi config.h) and the
@@ -16,14 +16,14 @@
#define LCD_WIDTH 480
#define LCD_HEIGHT 480
// ---- QSPI display pins (SH8601) ----
// ---- QSPI display pins (CO5300) ----
#define LCD_CS 15
#define LCD_SCLK 0
#define LCD_SDIO0 1
#define LCD_SDIO1 2
#define LCD_SDIO2 3
#define LCD_SDIO3 4
// LCD reset is not wired to a MCU GPIO on this board — the SH8601 relies
// LCD reset is not wired to a MCU GPIO on this board — the CO5300 relies
// on its internal power-on reset. The Arduino_GFX driver gets
// GFX_NOT_DEFINED for reset.
@@ -3,49 +3,52 @@
#include <Arduino.h>
#include <Arduino_GFX_Library.h>
// C6 AMOLED-2.16 uses an SH8601 panel — same driver family as the
// AMOLED-1.8 port. LCD reset is not wired to any MCU GPIO; the SH8601
// boots from its internal POR. Rotation is disabled (no PSRAM headroom
// for the strip buffer).
// C6 AMOLED-2.16 uses a CO5300 AMOLED panel (per the Waveshare
// ESP32-C6-Touch-AMOLED-2.16 spec) — the same controller as the S3
// AMOLED-2.16 sibling, so we drive it with Arduino_CO5300 and reuse that
// class's vendor-correct init rather than the SH8601 class + a hand-patched
// sequence. LCD reset is not wired to any MCU GPIO; the panel boots from its
// internal power-on reset (rst = GFX_NOT_DEFINED). Rotation is disabled (no
// PSRAM headroom for a rotation strip).
static Arduino_DataBus* bus = nullptr;
static Arduino_SH8601* gfx = nullptr;
static Arduino_CO5300* gfx = nullptr;
void display_hal_init(void) {
bus = new Arduino_ESP32QSPI(
LCD_CS, LCD_SCLK, LCD_SDIO0, LCD_SDIO1, LCD_SDIO2, LCD_SDIO3);
gfx = new Arduino_SH8601(
bus, GFX_NOT_DEFINED, 0, LCD_WIDTH, LCD_HEIGHT);
// CO5300 constructor: (bus, rst, rotation, w, h, col_off1..2, row_off1..2).
// No reset GPIO on this board; the 480-wide panel is full-width so all
// offsets are 0 — matches the S3 AMOLED-2.16 instantiation.
gfx = new Arduino_CO5300(
bus, GFX_NOT_DEFINED, 0 /* rotation disabled */,
LCD_WIDTH, LCD_HEIGHT, 0, 0, 0, 0);
}
// Vendor-specific init commands from the Waveshare C6-2.16 BSP
// (02_Example/Arduino-v3.3.3/09_LVGL_V9_Test/bsp_lvgl_port.cpp in the
// waveshareteam/ESP32-C6-Touch-AMOLED-2.16 repo). The stock Arduino_GFX
// SH8601 init does SLPOUT + NORON + INVOFF + PIXFMT + DISPON + brightness,
// which is enough for the AMOLED-1.8 panel but leaves this 2.16 panel
// dark. The page-switch sequence (0xFE 0x20 ... 0xFE 0x00) writes two
// panel-specific manufacturer registers (0x19 and 0x1C) that gate the
// driving voltages — without them the panel stays black even with the
// rails up and the reset pulse applied.
static void send_vendor_init(Arduino_DataBus* b) {
// Arduino_CO5300::begin() already issues SLPOUT, SPI-mode control, pixel
// format, brightness-control, DISPON and a default MADCTL. The ONLY thing it
// does not set is this panel's manufacturer page-0x20 driving-voltage
// registers (0x19/0x1C) — without them the panel stays black even with the
// rails up. Set just those; everything else the SH8601-era hack also wrote
// (0xC4/0x36/0x53/0x51/0x63/0x29) is now covered by the class init.
//
// Note: we deliberately do NOT restore the old MADCTL 0x30 (MV transpose).
// The CO5300 class default (rotation-0, MADCTL 0x00) orients the panel with
// the USB port on the side, which is the preferred desk orientation for this
// board.
static void send_panel_driving_init(Arduino_DataBus* b) {
b->beginWrite();
b->writeC8D8(0xFE, 0x20); // enter manufacturer command page 0x20
b->writeC8D8(0x19, 0x10); // panel driving
b->writeC8D8(0x1C, 0xA0); // panel driving
b->writeC8D8(0x19, 0x10); // panel driving voltage
b->writeC8D8(0x1C, 0xA0); // panel driving voltage
b->writeC8D8(0xFE, 0x00); // back to user command page
b->writeC8D8(0xC4, 0x80); // SPI mode control
b->writeC8D8(0x36, 0x30); // MADCTL (BSP value)
b->writeC8D8(0x53, 0x20); // CTRL display 1 (brightness control on)
b->writeC8D8(0x51, 0xFF); // brightness = max
b->writeC8D8(0x63, 0xFF); // HBM brightness = max
b->writeCommand(0x29); // DISPON (idempotent — stock init already did this)
b->endWrite();
delay(20);
}
void display_hal_begin(void) {
gfx->begin();
send_vendor_init(bus); // patch up panel-specific regs the stock init misses
send_panel_driving_init(bus); // panel-specific regs the class init omits
gfx->fillScreen(0x0000);
gfx->setBrightness(200);
}
@@ -67,8 +70,7 @@ void display_hal_tick(void) {
// No rotation cycle on this board.
}
// Mirrors the CO5300/SH8601 even-alignment pattern from the other ports.
// Harmless on SH8601, kept for consistency.
// CO5300 requires even-aligned flush regions.
void display_hal_round_area(int32_t* x1, int32_t* y1, int32_t* x2, int32_t* y2) {
*x1 = *x1 & ~1;
*y1 = *y1 & ~1;
@@ -22,11 +22,16 @@ void touch_hal_init(void) {
return;
}
touch.setMaxCoordinates(LCD_WIDTH, LCD_HEIGHT);
// C6 2.16 panel mapping (verified empirically): the CST9217's raw
// axes are swapped relative to the SH8601 raster AND X is mirrored.
// Matches the Waveshare BSP, which reads y = raw_byte1, x = W - raw_byte2.
touch.setSwapXY(true);
touch.setMirrorXY(true, false);
// C6 2.16 panel mapping. The original values (swap=true, mirrorX=true)
// were calibrated to the old display orientation that force-wrote MADCTL
// 0x30 (MV transpose + ML). The display now runs at the CO5300 class
// default (MADCTL 0x00 — USB-port-on-the-side orientation), so the touch
// mapping is re-derived to match. SensorLib applies swap then mirror
// (TouchDrvInterface::updateXY); tap-tested on C6 hardware, the raw
// CST9217 coordinates map straight through in this orientation — no swap,
// no mirror.
touch.setSwapXY(false);
touch.setMirrorXY(false, false);
pinMode(TP_INT, INPUT_PULLUP);
attachInterrupt(TP_INT, touch_isr, FALLING);
Serial.println("Touch init OK");