Waveshare ships two hardware revisions under "ESP32-S3-Touch-AMOLED-1.8":
the original (SH8601 display + FT3168 touch @0x38) and a later one
(CO5300 display + CST816 touch @0x15). On the later board the SH8601
driver left the panel blank and the FT3168 probe spammed
ESP_ERR_INVALID_STATE because nothing answers at 0x38.
Detect the revision at boot by probing the touch address and pick the
matching drivers, so one binary drives both boards:
- board_rev.{h}/board_init.cpp: probe 0x15 (CST816) vs 0x38 (FT3168)
- display.cpp: instantiate Arduino_CO5300 or Arduino_SH8601 behind a
shared Arduino_OLED*; CO5300 gets a 16px column offset to center the
368-wide image (verified on hardware)
- touch.cpp: one FocalTech-style reader (regs 0x02..0x06) for both
chips, address chosen by revision
- board.h: add CST816_ADDR 0x15
- CLAUDE.md: document the dual revision
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
34 lines
1013 B
C++
34 lines
1013 B
C++
#include "board.h"
|
|
#include "board_rev.h"
|
|
#include "io_expander.h"
|
|
#include <Arduino.h>
|
|
#include <Wire.h>
|
|
|
|
// AMOLED-1.8 also needs the XCA9554 IO expander up first — the display
|
|
// and touch controllers stay in reset until EXIO0..1 go HIGH.
|
|
|
|
static BoardRev g_rev = REV_SH8601_FT3168;
|
|
|
|
BoardRev board_rev(void) { return g_rev; }
|
|
|
|
static bool i2c_present(uint8_t addr) {
|
|
Wire.beginTransmission(addr);
|
|
return Wire.endTransmission() == 0;
|
|
}
|
|
|
|
extern "C" void board_init(void) {
|
|
Wire.begin(IIC_SDA, IIC_SCL);
|
|
io_expander_init();
|
|
delay(10); // let the touch controller exit reset before probing
|
|
|
|
// Detect the panel revision by which touch controller answers. CST816
|
|
// (0x15) ships on the CO5300 panel; FT3168 (0x38) on the original SH8601.
|
|
if (i2c_present(CST816_ADDR)) {
|
|
g_rev = REV_CO5300_CST816;
|
|
Serial.println("Board revision: CO5300 + CST816");
|
|
} else {
|
|
g_rev = REV_SH8601_FT3168;
|
|
Serial.println("Board revision: SH8601 + FT3168");
|
|
}
|
|
}
|