From b5d1169392ff220604b0b41793cbe2b25cf5232e Mon Sep 17 00:00:00 2001 From: blue Date: Thu, 11 Jun 2026 14:14:16 -0400 Subject: [PATCH] Rename: product -> "Resound"; firmware roles -> hud/sink/broadcaster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Product name BikeAudio -> "Resound" (the device isn't bike-specific — works at home, backyard, camping, parties, group rides). This is the A2DP advertise name the phone connects to: sink.start("Resound"). All banners/comments + README updated. (After reflashing the sink, the phone must forget "BikeAudio" and connect to "Resound".) Firmware vocabulary clarified (the old hub/sink/source was confusing — "source" read backwards since those boards SEND audio): hub_s3.cpp / env hub_s3 -> hud.cpp / env hud board_sink.cpp -> sink.cpp (env sink) board_source.cpp -> broadcaster.cpp (envs broadcaster_headset 0x11, broadcaster_speaker1 0x10, broadcaster_guest 0x12) hub_proto.h -> bus_proto.h default_envs = sink + the three broadcasters. All envs build clean. Co-Authored-By: Claude Opus 4.8 (1M context) --- README_RELAY.md | 4 +- platformio.ini | 68 +++++++++++------------ src/{board_source.cpp => broadcaster.cpp} | 8 +-- src/{hub_proto.h => bus_proto.h} | 2 +- src/{hub_s3.cpp => hud.cpp} | 6 +- src/{board_sink.cpp => sink.cpp} | 10 ++-- 6 files changed, 48 insertions(+), 50 deletions(-) rename src/{board_source.cpp => broadcaster.cpp} (98%) rename src/{hub_proto.h => bus_proto.h} (96%) rename src/{hub_s3.cpp => hud.cpp} (99%) rename src/{board_sink.cpp => sink.cpp} (90%) diff --git a/README_RELAY.md b/README_RELAY.md index 8de3ca2..71a7af8 100644 --- a/README_RELAY.md +++ b/README_RELAY.md @@ -1,4 +1,4 @@ -# BikeAudio — 3-board Bluetooth relay +# Resound — 3-board Bluetooth relay Relays iPhone audio to **two** Bluetooth speakers (JBL Charge 5 + Cardo "Tangerine EDGE") at the same time. @@ -89,7 +89,7 @@ B and C start reading it. 1. Put the **JBL** and **Cardo** in pairing mode. 2. Power Board B and Board C — each connects to its speaker by name (auto-reconnects on later power-ups). -3. Power Board A; on the iPhone, connect to **"BikeAudio"**. +3. Power Board A; on the iPhone, connect to **"Resound"**. 4. Play audio — both speakers should output together. ## Known limitations diff --git a/platformio.ini b/platformio.ini index cddb2a0..af68461 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,17 +1,19 @@ -; BikeAudio — 3-board relay (iPhone -> Board A sink -> I2S -> Boards B/C sources -> JBL + Cardo) +; BikeAudio — split-board Bluetooth audio relay. ; -; One ESP32 cannot be an A2DP sink and source at once, and an A2DP source can -; reach only one speaker — so the work is split across three boards that share -; an I2S bus. See README.md for wiring and the flash order. +; Roles (one ESP32 can't be A2DP sink+source, and a source reaches one speaker, +; so the work is split across boards sharing an I2S audio bus + an I2C control bus): +; SINK - iPhone connects here (A2DP in) -> drives the I2S bus as master +; BROADCASTER - reads I2S -> A2DP-streams to ONE speaker (one per channel) +; HUD - ESP32-S3 round touch LCD; control panel over I2C ; -; Build all: pio run -; Build one board: pio run -e sink | -e source_jbl | -e source_cardo +; Channels are brand-agnostic: Headset / Speaker 1 / Guest (discovery picks the +; real device per channel). Build one: pio run -e sink | -e broadcaster_headset +; | -e broadcaster_speaker1 | -e broadcaster_guest | -e hud ; -; Common specs preserved from the original sketch: ESP32 Arduino core 2.0.x via -; espressif32 ~6.6.0, esp32dev, huge_app partition (BT stack), 115200 monitor. +; Audio boards: ESP32 core 2.0.x via espressif32 ~6.6.0, esp32dev, huge_app (BT stack). [platformio] -default_envs = sink, source_jbl, source_cardo +default_envs = sink, broadcaster_headset, broadcaster_speaker1, broadcaster_guest [env] platform = espressif32 @ ~6.6.0 @@ -24,47 +26,43 @@ lib_deps = https://github.com/pschatzmann/ESP32-A2DP#42601717cd70d5300c9b519f3c2bf1d64d77ea2b https://github.com/pschatzmann/arduino-audio-tools#64b64dcb9bde18a0a17766eeb6529c3a53d920a8 -; --- Board A: A2DP sink (iPhone) -> I2S master -------------------------------- +; --- SINK: A2DP sink (iPhone) -> I2S master ---------------------------------- [env:sink] -build_src_filter = + +build_src_filter = + -; --- Board B: I2S slave -> A2DP source -> JBL Charge 5 ------------------------ -[env:source_jbl] -build_src_filter = + -build_flags = '-DTARGET_SPEAKER="JBL Charge 5"' -DHUB_I2C_ADDR=0x10 - -; --- Board C: I2S slave -> A2DP source -> Cardo (Tangerine EDGE) -------------- -[env:source_cardo] -build_src_filter = + +; --- BROADCASTER "Headset" -> Cardo (I2C 0x11) ------------------------------- +[env:broadcaster_headset] +build_src_filter = + build_flags = '-DTARGET_SPEAKER="Tangerine EDGE"' -DHUB_I2C_ADDR=0x11 -; --- Board D: I2S slave -> A2DP source -> GUEST speaker (antenna board) ------- -; Occasional passenger speaker, furthest away (hence the onboard antenna). -; No hardcoded name — pick the speaker via the hub's scan UI (Phase 3). -[env:source_guest] -build_src_filter = + +; --- BROADCASTER "Speaker 1" -> JBL (I2C 0x10) ------------------------------- +[env:broadcaster_speaker1] +build_src_filter = + +build_flags = '-DTARGET_SPEAKER="JBL Charge 5"' -DHUB_I2C_ADDR=0x10 + +; --- BROADCASTER "Guest" -> antenna board, occasional passenger (I2C 0x12) --- +; No hardcoded device — pick the speaker via the HUD scan UI (discovery). +[env:broadcaster_guest] +build_src_filter = + build_flags = '-DTARGET_SPEAKER="Guest"' -DHUB_I2C_ADDR=0x12 -; --- 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] +; --- HUD: ESP32-S3-Touch-LCD-1.28 (round GC9A01 LCD + CST816S touch) ---------- +; Different chip (esp32s3); LVGL UI + I2C master to the audio boards. +; NOT in default_envs — build with: pio run -e hud +[env:hud] 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 = + +build_src_filter = + lib_deps = lovyan03/LovyanGFX@^1.1.16 lvgl/lvgl@^8.3.11 -; LVGL configured via build flags (LV_CONF_SKIP -> defaults + overrides), so -; there is no separate lv_conf.h to maintain. 16-bit colour, byte-swapped for -; the SPI panel; millis() tick; the big Montserrat fonts for glanceable text. -; NOTE: keep flag values free of shell-special chars (parens/spaces) — they go -; through a shell. LV_MEM_SIZE as a plain int; tick driven via lv_tick_inc() in -; loop() (no LV_TICK_CUSTOM, which needs a parenthesised millis() expr). +; LVGL via build flags (LV_CONF_SKIP -> defaults + overrides); no lv_conf.h. +; Keep flag values free of shell-special chars (parens/spaces). Tick via +; lv_tick_inc() in loop() (no LV_TICK_CUSTOM, which needs a parenthesised expr). build_flags = -DLV_CONF_SKIP=1 -DLV_COLOR_DEPTH=16 diff --git a/src/board_source.cpp b/src/broadcaster.cpp similarity index 98% rename from src/board_source.cpp rename to src/broadcaster.cpp index 4150ad7..e99e1f0 100644 --- a/src/board_source.cpp +++ b/src/broadcaster.cpp @@ -1,5 +1,5 @@ /** - * BikeAudio — Boards B & C : I2S SLAVE -> [FIFO delay] -> A2DP SOURCE + * Resound — Boards B & C : I2S SLAVE -> [FIFO delay] -> A2DP SOURCE * * Reads PCM from the shared I2S bus (clocked by Board A) into a FIFO, and an * A2DP source drains the FIFO to one Bluetooth speaker. The FIFO sits a fixed @@ -24,10 +24,10 @@ #include #include -#include "hub_proto.h" +#include "bus_proto.h" #ifndef TARGET_SPEAKER -#define TARGET_SPEAKER "BikeAudio-Speaker" +#define TARGET_SPEAKER "Resound-Speaker" #endif // I2C slave address (which speaker this board controls). Set per-env via build @@ -305,7 +305,7 @@ void on_conn_state(esp_a2d_connection_state_t state, void *obj) { void setup() { Serial.begin(115200); delay(500); - Serial.printf("=== BikeAudio Source -> '%s' (FIFO delay, %ums cushion) ===\n", + Serial.printf("=== Resound Source -> '%s' (FIFO delay, %ums cushion) ===\n", TARGET_SPEAKER, BASE_DELAY_MS); prefs.begin("bikeaudio", false); diff --git a/src/hub_proto.h b/src/bus_proto.h similarity index 96% rename from src/hub_proto.h rename to src/bus_proto.h index f36b66a..eb13620 100644 --- a/src/hub_proto.h +++ b/src/bus_proto.h @@ -1,5 +1,5 @@ /** - * BikeAudio — control-bus protocol shared by the S3 hub (I2C master) and the + * Resound — control-bus protocol shared by the S3 hub (I2C master) and the * source Boards B/C (I2C slaves). Included by both hub_s3.cpp and board_source.cpp. * * Bus: I2C. Hub = master. Each source board = a slave at a fixed address. diff --git a/src/hub_s3.cpp b/src/hud.cpp similarity index 99% rename from src/hub_s3.cpp rename to src/hud.cpp index b3b6bc9..313a69e 100644 --- a/src/hub_s3.cpp +++ b/src/hud.cpp @@ -1,5 +1,5 @@ /** - * BikeAudio — Hub (ESP32-S3-Touch-LCD-1.28) : PHASE 3 discovery + control + * Resound — Hub (ESP32-S3-Touch-LCD-1.28) : PHASE 3 discovery + control * * Round GC9A01 LCD + CST816S touch, wired as an I2C MASTER to the source * boards. Three brand-agnostic channels are controlled (discovery picks the @@ -41,7 +41,7 @@ #include #include #include -#include "hub_proto.h" +#include "bus_proto.h" class LGFX : public lgfx::LGFX_Device { lgfx::Panel_GC9A01 _panel; @@ -861,7 +861,7 @@ static void poll_timer_cb(lv_timer_t *t) { void setup() { Serial.begin(115200); delay(300); - Serial.println("=== BikeAudio Hub — S3 LVGL UI ==="); + Serial.println("=== Resound Hub — S3 LVGL UI ==="); // Control bus: I2C master to the source boards on Wire1 (peripheral 1). // Peripheral 0 is used by the LovyanGFX CST816S touch (GPIO6/7). diff --git a/src/board_sink.cpp b/src/sink.cpp similarity index 90% rename from src/board_sink.cpp rename to src/sink.cpp index f5b67bd..b60d341 100644 --- a/src/board_sink.cpp +++ b/src/sink.cpp @@ -1,8 +1,8 @@ /** - * BikeAudio — Board A : A2DP SINK -> I2S MASTER + * Resound — Board A : A2DP SINK -> I2S MASTER * * Part of the 3-board relay. The iPhone connects to this board over Bluetooth - * (A2DP name "BikeAudio"). This board decodes the audio to PCM and clocks it + * (A2DP name "Resound"). This board decodes the audio to PCM and clocks it * out on a shared I2S bus as the MASTER. Boards B and C (A2DP sources) listen * to this same bus as slaves and stream it to the JBL / Cardo speakers. * @@ -64,7 +64,7 @@ void on_conn_state(esp_a2d_connection_state_t state, void *obj) { void setup() { Serial.begin(115200); delay(500); - Serial.println("=== BikeAudio Board A — A2DP SINK -> I2S master ==="); + Serial.println("=== Resound Board A — A2DP SINK -> I2S master ==="); start_i2s(44100); @@ -72,9 +72,9 @@ void setup() { sink.set_stream_reader(write_pcm_to_i2s, false); sink.set_on_connection_state_changed(on_conn_state); sink.set_auto_reconnect(true); - sink.start("BikeAudio"); + sink.start("Resound"); - Serial.println("[SINK] Advertising 'BikeAudio' — connect from iPhone"); + Serial.println("[SINK] Advertising 'Resound' — connect from iPhone"); } void loop() {