Developer Setup — Windows + Devcontainer

This guide takes you from a fresh Windows PC to building and flashing the firmware and building and deploying the Android app, using the project's VS Code devcontainer (which ships the whole firmware + React Native toolchain).

It covers the Windows → devcontainer route. macOS/Linux hosts use the same devcontainer; only the USB-forwarding step (3) differs.

The flashing steps below assume no J-Link programmer (the common case). If you do have a SEGGER J-Link, there's a faster path noted in step 5. Recovering a board that won't boot is covered separately in Firmware Recovery.


What you'll need


1. Install host prerequisites (one-time)

Install on Windows:

  1. Docker Desktop with the WSL 2 backend (enable WSL 2 integration in Docker Desktop settings).
  2. Visual Studio Code + the Dev Containers extension (ms-vscode-remote.remote-containers).
  3. Git.
  4. usbipd-win (forwards USB devices into the container):
    winget install usbipd

2. Clone the repo and open it in the devcontainer

Easiest — one click from the firmware README's Open in Dev Containers badge (clones into a container volume). Or manually:

git clone https://github.com/skalldri/rgb-sunglasses.git

Open the folder in VS Code → when prompted, "Reopen in Container" (or run Dev Containers: Reopen in Container from the command palette).

The first container build downloads the toolchain image and runs the setup (npm install for the app, J-Link tooling, etc.) — this takes a while. When it finishes you have a shell with west, mcumgr, the Android SDK, and everything else preinstalled.


3. Forward USB devices into the container

The board's serial ports (and, later, the J-Link) reach the container from Windows via usbipd. Full details and troubleshooting are in .devcontainer/USB.md; the short version:

Once, in an elevated PowerShell (with the board plugged in):

.\.devcontainer\scripts\usbip-bind.ps1

This binds the board (2fe3:0001), its DFU-mode device (2fe3:0100), and a J-Link (1366:0101) if present. Binding is persistent across reboots. After binding, the container's startup automatically attaches and loads the needed WSL kernel modules, so you normally only ever do this once.

Verify inside the container:

.devcontainer/scripts/check-hardware.sh

You should see the dev board detected with two serial ports (ttyACM0 = shell, ttyACM1 = MCUmgr).

The phone does not use usbipd — the app step (6) connects to it over wireless ADB instead.


4. Build the firmware

One command (defaults to the proto0 board → fw/build):

fw/scripts/build-fw.sh

The first build is a full from-scratch configure (it builds the network-core image, MCUboot, and the app), so it takes noticeably longer than the incremental builds after it. (The legacy DK board is no longer buildable from main — its board support lives on the dk-support branch.)


Your board already ships running firmware, so you can update it over USB with MCUmgr — no J-Link needed. Plug the board in and run:

fw/scripts/mcumgr-flash.sh

This finds the MCUmgr serial port, uploads your freshly built app image (showing a progress bar as it goes), and reboots the board into it. That's the whole loop: edit → build-fw.shmcumgr-flash.sh.

Confirm it worked over the serial shell — connect with fw/scripts/fw-shell.sh and run kernel version / kernel uptime.


6. Build and deploy the Android app

BLE only works on a physical Android phone. The container talks to it over wireless ADB (no USB passthrough needed).

a. Install JS dependencies (once, and after dependency changes):

cd app && npm install

b. Connect the phone over wireless ADB (Android 11+):

  1. On the phone: Settings → Developer Options → Wireless Debugging → turn it on.
  2. Tap Pair device with pairing code; note the IP, pair port, and 6-digit code.
  3. In the container:
    adb pair <phone-ip>:<pair-port>       # enter the 6-digit code
  4. Back on the Wireless Debugging screen, read the debug IP:port (different from the pair port) and connect:
    adb connect <phone-ip>:<debug-port>

Confirm with adb devices (it should list your phone). Wireless pairing is remembered by the phone; on later sessions just re-run adb connect <phone-ip>:<debug-port>.

c. Build, install, and run (run this as a long-lived command — it also starts Metro):

app/scripts/launch-app.sh --device "<phone model name>"

Use the phone's model name (e.g. Pixel_9_Pro), not the ADB ip:port. With exactly one device connected you can omit --device and it'll auto-select. launch-app.sh handles the .dev app-id detail and runs the native build; after it's up, editing .ts/.tsx files fast-refreshes on the phone.

Prefer the raw command? cd app && npx expo run:android --device "<model name>" --app-id com.autom8ed.rgbsunglassesapp.dev — the --app-id is required (this project installs a side-by-side .dev build). See app/README.md.

d. Pair the phone to the glasses over Bluetooth. Open the app, accept the permission prompts, and tap Connect on the detected RGB Sunglasses device. When Android asks to pair, the glasses' LED panel scrolls a 6-digit passkey — enter it to complete pairing. Full walkthrough: Proto0 User Guide.


You're set up

The day-to-day loops are:

Where to go next

Notes