// clar200_bridge.ino — ESP32-C3 transparent USB <-> UART bridge // Purpose: talk to a Seagate F3 diagnostic terminal on an EMC CLAR200-locked // Exos X18 SAS drive, using the C3's native USB-CDC as the host side. // // Target board: ESP32-C3 (native USB-Serial-JTAG), e.g. C3 SuperMini / DevKitM-1. // Host port: /dev/ttyACM0 on steel141 (MAC 58:8c:81:ac:f0:4c). // // Build flag REQUIRED: "USB CDC On Boot: Enabled" (so `Serial` == USB-CDC, not UART0) // arduino-cli: append :CDCOnBoot=cdc to the FQBN (see firmware/flash.sh) // // Wiring (3.3 V, common ground, TX<->RX crossover): // ESP32-C3 GPIO4 (DRV_TX) ---> drive F3 RX // ESP32-C3 GPIO5 (DRV_RX) <--- drive F3 TX // ESP32-C3 GND ---- drive GND (mandatory) // Do NOT connect any VCC/5V to the drive header. Drive is powered by its own // SATA/SAS power. You only tap TX / RX / GND. // // Baud: Seagate F3 is 8N1. Family varies — this sketch boots at 38400 and lets // you change baud live without reflashing, via a `~` escape menu (see below). // // Live baud menu — type these AT THE START OF A LINE in your terminal: // ~1 -> 9600 ~2 -> 38400 (default) ~3 -> 115200 ~4 -> 460800 // ~? -> print current baud // Anything else is passed through transparently (binary-safe). #define DRV_TX 4 // ESP32-C3 GPIO -> drive RX #define DRV_RX 5 // ESP32-C3 GPIO <- drive TX #define LED_PIN 8 // most C3 boards: onboard LED on GPIO8 (active-low). Harmless if absent. static const uint32_t BAUDS[] = {9600, 38400, 115200, 460800}; static uint32_t curBaud = 38400; static void applyBaud(uint32_t b) { curBaud = b; Serial1.end(); Serial1.begin(curBaud, SERIAL_8N1, DRV_RX, DRV_TX); Serial.printf("\r\n[bridge] drive UART = %lu 8N1\r\n", (unsigned long)curBaud); } void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // LED on = bridge alive Serial.begin(115200); // USB-CDC; baud value is ignored over CDC delay(200); applyBaud(38400); Serial.print("\r\n[bridge] ESP32-C3 F3 bridge ready. ~1/~2/~3/~4 set baud, ~? shows it.\r\n"); } // Minimal line-start escape parser so `~N` switches baud but everything else // (including F3 binary) flows through untouched. static bool atLineStart = true; static bool inEscape = false; void loop() { // host -> drive while (Serial.available()) { int c = Serial.read(); if (inEscape) { inEscape = false; switch (c) { case '1': applyBaud(BAUDS[0]); break; case '2': applyBaud(BAUDS[1]); break; case '3': applyBaud(BAUDS[2]); break; case '4': applyBaud(BAUDS[3]); break; case '?': Serial.printf("\r\n[bridge] current = %lu\r\n", (unsigned long)curBaud); break; default: // not a menu key: emit the swallowed '~' then this char Serial1.write('~'); Serial1.write((uint8_t)c); } atLineStart = false; continue; } if (atLineStart && c == '~') { inEscape = true; continue; } Serial1.write((uint8_t)c); atLineStart = (c == '\n' || c == '\r'); } // drive -> host while (Serial1.available()) Serial.write((uint8_t)Serial1.read()); }