diff --git a/docs/BUILD.md b/docs/BUILD.md new file mode 100644 index 0000000..40cdd08 --- /dev/null +++ b/docs/BUILD.md @@ -0,0 +1,146 @@ +# Build and deploy + +Target: Windows, Arduino IDE 2.x, board package **esp32-bluepad32 4.1.0**, +original ESP32 (WROOM/WROVER). S3/C3/C6/H2 have no Bluetooth Classic, so a PS4 +pad will not pair with them. + +## 1. Install the board package + +Preferences -> Additional board manager URLs, add: + +``` +https://raw.githubusercontent.com/ricardoquesada/esp32-arduino-lib-builder/master/bluepad32_files/package_esp32_bluepad32_index.json +``` + +Boards Manager -> install **esp32_bluepad32**. Then Tools -> Board -> +**esp32_bluepad32** -> ESP32 Dev Module. + +Picking the board out of the normal `esp32` package is what gives you +`fatal error: Bluepad32.h: No such file or directory`. Bluepad32 is a +replacement board package, not a Library Manager entry, and adding it as a ZIP +library will not work. + +Do **not** install Legoino or NimBLE-Arduino. If either ends up in the build you +are back to two Bluetooth host stacks fighting over one radio, which is the +whole problem this project exists to avoid. + +## 2. Put the BTstack headers on the include path + +Package 4.1.0 ships the BTstack and Bluepad32 headers under +`tools\sdk\\include\`, but does not add them to the compiler's include +path. Without this step you get: + +``` +fatal error: btstack.h: No such file or directory +``` + +4.1.0 is built on the arduino-esp32 **2.x** layout, so there is no +`flags\includes` file to edit (that only exists on core 3.x). The include paths +live in `compiler.cpreprocessor.flags` in `platform.txt`. Rather than edit that +file, drop a `platform.local.txt` beside it — Arduino reads it as an override, +the original stays untouched, and rolling back is deleting one file. + +In PowerShell: + +```powershell +$plat = "$env:LOCALAPPDATA\Arduino15\packages\esp32-bluepad32\hardware\esp32\4.1.0" + +$flags = 'compiler.cpreprocessor.flags={compiler.cpreprocessor.flags.{build.mcu}} ' + + '"-I{compiler.sdk.path}/{build.memory_type}/include" ' + + '"-I{compiler.sdk.path}/include/btstack/src" ' + + '"-I{compiler.sdk.path}/include/btstack/include" ' + + '"-I{compiler.sdk.path}/include/btstack/platform/freertos" ' + + '"-I{compiler.sdk.path}/include/bluepad32/include"' + +$flags | Out-File "$plat\platform.local.txt" -Encoding ascii +Get-Content "$plat\platform.local.txt" +``` + +It has to be a **single line**. The `Get-Content` at the end is there to confirm +it did not wrap. + +The first two tokens restate what `platform.txt` already had — the override +replaces the whole value, so they have to be repeated. `{compiler.sdk.path}` +resolves to `tools\sdk\`, so these entries work for every MCU in the +package, not just esp32. + +What each added path is for: + +| Path | Provides | +| --- | --- | +| `btstack/src` | `btstack.h`, `gatt_client.h`, `btstack_run_loop.h` | +| `btstack/include` | `btstack_config.h` — separate directory, and BTstack includes it from `btstack.h`, so missing it gives you a confusing second error right after fixing the first | +| `btstack/platform/freertos` | the ESP32 run loop implementation | +| `bluepad32/include` | `uni.h`, if you later want the `uni_bt_allowlist` API | + +Duplicate `-I` flags are harmless, so it does not matter if +`bluepad32/include` was already covered. + +Two things to know about this edit: + +* A Bluepad32 package update **wipes it**. Keep a copy of `platform.local.txt` + somewhere outside `Arduino15` — there is one in `docs/` here. +* A malformed value breaks compilation for *every* ESP32 sketch on the machine, + not just this one. If things go strange, delete the file. + +## 3. Board settings + +* Board: ESP32 Dev Module (under esp32_bluepad32) +* Partition Scheme: **Huge APP (3MB No OTA/1MB SPIFFS)**. BTstack with both + transports plus the GATT client does not fit the default partition table. +* Upload speed 921600 is fine; drop to 115200 if uploads fail. + +## 4. Before flashing + +After creating `platform.local.txt`, fully quit the Arduino IDE — closing the +sketch window is not enough, it has to re-read the platform — and clear the +build cache: + +```powershell +Remove-Item "$env:LOCALAPPDATA\Temp\arduino\sketches\*" -Recurse -Force -ErrorAction SilentlyContinue +``` + +Then set your two hub addresses in `HUB_ADDR_STR` at the top of the sketch and +compile. + +## 5. First run + +1. Power both hubs and press their green buttons so they are advertising. +2. Flash, open Serial Monitor at 115200. +3. Expect `Connecting hubs, then opening for the gamepad`. Each hub's LED goes + green as it is claimed. +4. Once both are up you get `Hubs up - put the PS4 pad in pairing mode`. Hold + SHARE + PS on the controller until the light bar flashes. +5. Onboard LED on GPIO2 goes solid when the pad and both hubs are all connected. + +The order matters and is deliberate: gamepad discovery stays off until the hubs +are connected, so Bluepad32's inquiry and LE scan are not running at the same +time as our LE create-connection. + +## Troubleshooting + +**A missing header from `btstack/3rd-party`.** Add another `-I` line for that +directory and redo step 4. + +**Hubs never connect, no LE connection-complete in the log.** In order of +likelihood: the hubs went back to sleep (they time out after a couple of minutes +— press the buttons again); the addresses are wrong; or the address type is +wrong. For the last one, switch `HUB_ADDR_TYPE` to `BD_ADDR_TYPE_LE_RANDOM`. + +**One hub connects, the other never does.** Expected if the first one is stuck +mid-discovery. `serviceHubConnections()` only runs one at a time by design; +check `gActive` is being released. + +**Motors stutter, or a hub drops off after a few seconds.** Commands are going +out faster than the hub can absorb. Raise `MOTOR_MIN_GAP_MS`. + +**Random crashes at unrelated places.** Almost certainly a BTstack call added to +`loop()`. BTstack is not thread-safe and `loop()` is not the BTstack thread — +see the header comment in the sketch. + +Turn on verbose BTstack logging before guessing at any of it. Nearly every +failure mode here surfaces as a specific HCI event you can read. + +--- + +Created by: Jess Rogerson (yelling commands at Claude.AI)