diff --git a/platformio.ini b/platformio.ini index 735c581..fa10c3d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -37,3 +37,16 @@ build_flags = '-DTARGET_SPEAKER="JBL Charge 5"' [env:source_cardo] build_src_filter = + build_flags = '-DTARGET_SPEAKER="Tangerine EDGE"' + +; --- Hub: ESP32-S3-Touch-LCD-1.28 (round GC9A01 LCD + CST816S touch) ---------- +; Different chip (esp32s3) from the relay boards. Drives the UI; later the +; wired control bus to Boards B/C. NOT in default_envs — build with -e hub_s3. +[env:hub_s3] +platform = espressif32 @ ~6.6.0 +board = esp32-s3-devkitc-1 +framework = arduino +board_upload.flash_size = 4MB +board_build.partitions = default.csv +monitor_speed = 115200 +build_src_filter = + +lib_deps = lovyan03/LovyanGFX@^1.1.16 diff --git a/src/hub_s3.cpp b/src/hub_s3.cpp new file mode 100644 index 0000000..8adff75 --- /dev/null +++ b/src/hub_s3.cpp @@ -0,0 +1,102 @@ +/** + * BikeAudio — Hub (ESP32-S3-Touch-LCD-1.28) : PHASE 1 bring-up + * + * First light: drive the round GC9A01 LCD + backlight, and read the CST816S + * touch, to prove the board before building the GUI. No control bus / GUI yet. + * + * Board pins (Waveshare ESP32-S3-Touch-LCD-1.28): + * GC9A01 SPI: SCLK=10 MOSI=11 MISO=12 CS=9 DC=8 RST=14 backlight=2 + * CST816S touch (I2C): SDA=6 SCL=7 (polled; INT left unused) + * + * Build: pio run -e hub_s3 | flash: esp32s3, bootloader@0x0 + */ + +#define LGFX_USE_V1 +#include +#include + +class LGFX : public lgfx::LGFX_Device { + lgfx::Panel_GC9A01 _panel; + lgfx::Bus_SPI _bus; + lgfx::Light_PWM _light; + lgfx::Touch_CST816S _touch; +public: + LGFX() { + { auto c = _bus.config(); + c.spi_host = SPI2_HOST; + c.spi_mode = 0; + c.freq_write = 40000000; + c.pin_sclk = 10; + c.pin_mosi = 11; + c.pin_miso = 12; + c.pin_dc = 8; + _bus.config(c); _panel.setBus(&_bus); } + + { auto c = _panel.config(); + c.pin_cs = 9; + c.pin_rst = 14; + c.panel_width = 240; + c.panel_height = 240; + c.offset_x = 0; + c.offset_y = 0; + c.readable = false; + c.invert = true; // GC9A01 typically needs inversion + c.rgb_order = false; + _panel.config(c); } + + { auto c = _light.config(); + c.pin_bl = 2; + c.freq = 12000; + c.pwm_channel = 7; + _light.config(c); _panel.setLight(&_light); } + + { auto c = _touch.config(); + c.i2c_port = 0; + c.pin_sda = 6; + c.pin_scl = 7; + c.pin_int = -1; // poll over I2C (avoid INT-pin ambiguity) + c.pin_rst = -1; + c.i2c_addr = 0x15; + c.freq = 400000; + c.x_min = 0; c.x_max = 239; c.y_min = 0; c.y_max = 239; + _touch.config(c); _panel.setTouch(&_touch); } + + setPanel(&_panel); + } +}; + +LGFX lcd; + +void setup() { + Serial.begin(115200); + delay(300); + Serial.println("=== BikeAudio Hub — S3 round LCD first light ==="); + + lcd.init(); + lcd.setRotation(0); + lcd.setBrightness(200); + lcd.fillScreen(TFT_BLACK); + lcd.drawCircle(120, 120, 118, TFT_DARKGREY); + lcd.setTextColor(TFT_CYAN, TFT_BLACK); + lcd.setTextDatum(middle_center); + lcd.drawString("BikeAudio", 120, 100, &fonts::FreeSansBold18pt7b); + lcd.setTextColor(TFT_WHITE, TFT_BLACK); + lcd.drawString("hub: first light", 120, 140, &fonts::Font2); + lcd.drawString("touch me", 120, 160, &fonts::Font2); + Serial.println("[LCD] drawn; touch to draw dots"); +} + +void loop() { + int32_t x, y; + if (lcd.getTouch(&x, &y)) { + lcd.fillCircle(x, y, 5, TFT_RED); + Serial.printf("[TOUCH] %d, %d\n", x, y); + } + + static unsigned long last = 0; + if (millis() - last > 5000) { + Serial.printf("[hub] alive heap=%u psram=%u\n", ESP.getFreeHeap(), ESP.getFreePsram()); + last = millis(); + } + delay(15); +}