diff --git a/.claude/skills/flash-re-bba-rb/SKILL.md b/.claude/skills/flash-re-bba-rb/SKILL.md new file mode 100644 index 0000000..8d557ef --- /dev/null +++ b/.claude/skills/flash-re-bba-rb/SKILL.md @@ -0,0 +1,116 @@ +--- +name: flash-re-bba-rb +description: Use when flashing the re-bba-rb board (GC BBA FPGA replacement) — programming the iCE40UP5K bitstream with iceprog and/or the FT2232H EEPROM product string ("re-BBA-rb") with pyftdi, from inside the WSL2 devcontainer. Covers USB passthrough prerequisites, best-seed bitstream selection, sudo/libusb access, and backup-first EEPROM programming. +--- + +# Flashing the re-bba-rb board + +The board is FT2232H (USB) → iCE40UP5K (FPGA) + W5100S (ethernet). Two flashable +targets, done **in this order**: + +1. **FPGA bitstream** via `iceprog` (MPSSE on FT2232H channel A) — the functional + flash. Do this first; it works with a blank EEPROM. +2. **FT2232H EEPROM** product string via `pyftdi` — cosmetic ("re-BBA-rb" instead + of "Dual RS232-HS"). Optional, do it only after the bitstream is proven. + +Both need USB access to the FT2232H (VID:PID `0403:6010`) from inside the +container. The `vscode` user reaches the root-owned `/dev/bus/usb` nodes via +passwordless `sudo`. + +## Prerequisites (once per session) + +1. **Container built with USB access.** `.devcontainer/` must have `--privileged`, + the `/dev/bus/usb` bind mount, `sudo`, `libusb-1.0-0`, `libftdi1-2`, and + `pyftdi`. If `.devcontainer/` was just edited, the user must **rebuild the + container** — those changes are baked at build/create time. +2. **Device attached to WSL2.** On the Windows host, as Administrator: + `.devcontainer/attach-icebreaker.ps1` (wraps `usbipd attach`). Attach before + or after container start — the bind mount is live, so a later attach still + appears. +3. **Confirm the device is visible from inside the container:** + ```bash + ls /dev/bus/usb/*/* # nodes must exist + sudo /opt/venv/bin/python -c "import usb.core,usb.backend.libusb1 as b; \ + print(usb.core.find(idVendor=0x0403, idProduct=0x6010, backend=b.get_backend()))" + ``` + A non-`None` device object means libusb can see it. If `/dev/bus/usb` is empty, + the device is not attached (fix on the Windows side) — see Troubleshooting. + +## Step 1 — Flash the FPGA bitstream + +The design's `capture` domain (54 MHz) closes on only a **minority of seeds** — +always sweep and flash the **best passing** seed, never the default seed-1 build. + +```bash +# Build all 8 seeds (from workspace root). Prints the best passing seed + path. +python -m exi_bba.synth --seeds 8 +``` +Note the reported best seed, e.g. `Best seed: 4 ... build/seed4/top.bin`. (As of +the last build: **seed 4, `build/seed4/top.bin`, capture 58.36 MHz**, 4/8 pass. +`build/` is on the host bind mount, so it survives container rebuilds.) + +Flash it (SRAM-less part → `iceprog` writes the SPI flash; the FPGA boots from +it): +```bash +sudo iceprog build/seed4/top.bin # substitute the reported best-seed path +``` +Expect `iceprog` to detect the FTDI, erase, write, and **verify OK**. If it says +"Can't find iCE FTDI USB device", the USB passthrough is not working — see +Troubleshooting. After a successful flash, power-cycle / re-plug to boot the new +image. + +`ICEPROG=/path/to/iceprog` overrides the binary if needed; the container's is on +`PATH`. + +## Step 2 — Program the FT2232H EEPROM (optional, cosmetic) + +Only after Step 1 verifies. This changes **descriptor strings only** — VID/PID +`0403:6010` and the dual-channel config are preserved, so `iceprog` and the +channel-B UART keep working. Values live in `hardware/re-bba-rb/flash_ftdi_eeprom.py` +(and mirror `hardware/re-bba-rb/ftdi_eeprom.conf`): manufacturer `hashru`, +product `re-BBA-rb`, serial `RBBARB001`. + +```bash +# Dry-run first: dumps a backup (eeprom-backup.bin) + prints the diff, no write. +sudo /opt/venv/bin/python hardware/re-bba-rb/flash_ftdi_eeprom.py + +# If the diff looks right, commit: +sudo /opt/venv/bin/python hardware/re-bba-rb/flash_ftdi_eeprom.py --commit +``` +The script always writes `hardware/re-bba-rb/eeprom-backup.bin` before staging +changes. After `--commit`, re-plug / re-attach USB so the host re-reads +descriptors; the unit then shows as **re-BBA-rb**. + +To restore the backup later, use `pyftdi`/`ftdi_eeprom` to write +`eeprom-backup.bin` back (raw image). + +## Troubleshooting + +- **`/dev/bus/usb` empty / device object is `None`** → not attached to WSL2. Run + `.devcontainer/attach-icebreaker.ps1` (admin) on Windows; check + `usbipd list` shows the FT2232H `Attached`. If the WSL2 kernel lacks usbfs, + `/dev/bus/usb` won't populate at all — update WSL (`wsl --update`). +- **`Permission denied` / `LIBUSB_ERROR_ACCESS`** → run the command under `sudo` + (the nodes are root-owned). Both `iceprog` and the pyftdi script need it. +- **`iceprog` can't find the device but `pyftdi` sees it (or vice-versa)** → a + kernel driver (`ftdi_sio`) may hold an interface. `iceprog`/`pyftdi` detach it + automatically under sudo; if stuck, `sudo modprobe -r ftdi_sio` (or re-attach + the device) and retry. +- **`iceprog` verify fails / flakey** → the drilled-out-via repair on this V1 + unit may have damaged a flash/CDONE/CRESET trace; check continuity of the SPI + flash lines and CRESET_B/CDONE to the FPGA before assuming gateware fault. +- **FPGA boots but the GC won't enumerate the BBA** → this is a *timing* seed + issue, not a flash issue. Re-flash the reported **best passing** seed (the + capture domain fails on ~half of seeds). See CLAUDE.md "Current Implementation + State". + +## Guardrails + +- **Bitstream before EEPROM** — the EEPROM string is cosmetic and never worth + risking before the board is functionally proven. +- **Never change VID/PID** in the EEPROM — `iceprog` and D2XX look for + `0403:6010`. The script/conf keep it; don't override. +- **Always flash the swept best-seed** `.bin`, never a no-`--seeds` seed-1 build + (capture timing fails on it). +- Keep the EEPROM backup (`eeprom-backup.bin`) until the string change is + confirmed good on the host. diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5a8eaea..ea14762 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -4,18 +4,24 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ git \ git-lfs \ + sudo \ python3 \ python3-venv \ python3-pip \ yosys \ nextpnr-ice40 \ fpga-icestorm \ + libusb-1.0-0 \ + libftdi1-2 \ nodejs npm \ graphviz \ poppler-utils \ kicad \ kicad-libraries \ && rm -rf /var/lib/apt/lists/* +# libusb-1.0-0 + libftdi1-2: USB backend for `iceprog` (FPGA flash) and `pyftdi` +# (FT2232H EEPROM). sudo: the /dev/bus/usb nodes are root-owned, so the vscode +# user flashes via `sudo` (NOPASSWD, configured below). # Debian marks the system Python as externally-managed (PEP 668), so install # project deps into a venv. /opt/venv is first on PATH, so `python`/`pip` resolve @@ -29,7 +35,12 @@ RUN npm install -g @anthropic-ai/claude-code COPY requirements.txt /tmp/requirements.txt RUN pip install --no-cache-dir -r /tmp/requirements.txt -RUN useradd -m -u 1000 -s /bin/bash vscode +# pyftdi: programs the FT2232H EEPROM (product string "re-BBA-rb") over libusb. +RUN pip install --no-cache-dir pyftdi + +RUN useradd -m -u 1000 -s /bin/bash vscode \ + && echo 'vscode ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/vscode \ + && chmod 0440 /etc/sudoers.d/vscode USER vscode diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b1eef0e..66b10a0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,8 +8,15 @@ "workspaceFolder": "/workspace", "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", "mounts": [ - "source=${localEnv:HOME}${localEnv:USERPROFILE}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached" + "source=${localEnv:HOME}${localEnv:USERPROFILE}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached", + "source=/dev/bus/usb,target=/dev/bus/usb,type=bind" ], + // --privileged + the /dev/bus/usb bind mount give libusb (iceprog, pyftdi) + // access to the FT2232H once it is usbipd-attached into WSL2. Attach the + // device on the Windows host BEFORE opening/rebuilding the container: + // .devcontainer/attach-icebreaker.ps1 (run as Administrator) + // New devices attached after start still appear (the bind mount is live). + "runArgs": ["--privileged"], "customizations": { "vscode": { "extensions": [ diff --git a/.gitignore b/.gitignore index 75d2f79..80a41be 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,10 @@ hardware/re-bba-rb/gerbers hardware/sp1_insert/gerbers *-bom.csv *-cpl.csv +*.rpt +# FT2232H EEPROM backup written by flash_ftdi_eeprom.py at runtime +hardware/re-bba-rb/eeprom-backup.bin +hardware/re-bba-rb/re-bba-rb-eeprom.bin # Editor / OS cruft .DS_Store diff --git a/CLAUDE.md b/CLAUDE.md index 427b4ec..383698e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,7 +22,12 @@ W5500 ethernet back-end". **Windows host + WSL2 devcontainer — USB flashing setup:** 1. Install `usbipd-win` (https://github.com/dorssel/usbipd-win/releases) 2. Run `.devcontainer/attach-icebreaker.ps1` as Administrator before opening the devcontainer -3. The devcontainer runs `--privileged` to pass through the USB device +3. The devcontainer runs `--privileged` AND bind-mounts `/dev/bus/usb` so libusb + (`iceprog`, `pyftdi`) can see the FT2232H; the `vscode` user flashes via + passwordless `sudo` (the USB nodes are root-owned). If you change + `.devcontainer/`, **rebuild the container** for it to take effect. +4. Flashing the re-bba-rb board (bitstream + FT2232H EEPROM) is documented as the + `flash-re-bba-rb` skill — see `.claude/skills/flash-re-bba-rb/SKILL.md`. **Local venv (outside devcontainer):** ```bash diff --git a/hardware/re-bba-rb/REVIEW.md b/hardware/re-bba-rb/REVIEW.md index 8877a0c..a6c51a2 100644 --- a/hardware/re-bba-rb/REVIEW.md +++ b/hardware/re-bba-rb/REVIEW.md @@ -74,8 +74,23 @@ datasheet extraction, WebSearch/WebFetch for parts and reference designs. change); TEST→GND, AGND→GND. - **EEPROM 93LC46B (U7)**: interface **was wrong** (DO+DI both direct to EEDATA) → fixed per DS Table 3.4: EE_DO net, R30 2.2k (C25879) to EE_DATA, - R31 10k (C25744) pull-up to 3V3, DI direct. 93LC46B = fixed 16-bit org = - correct for FT2232H. Verified in netlist. + R31 10k (C25744) pull-up to 3V3, DI direct. 93LC46B = fixed 16-bit org (that + part of the earlier verdict stands). **Interface wiring verified in netlist.** +- **⚠️ U7 PART IS UNDERSIZED — found at bring-up 2026-08-22 (overturns the old + "93LC46B = correct for FT2232H" note, which only checked ORG, not size).** + The 93LC46B is **1 Kbit = 128 bytes**; the FT2232H addresses a **256-byte** + EEPROM (`max_eeprom_size=256`) and its config does not fit in 128 B. FTDI + specs a **93LC56B (256 B)** or 93LC66B for the H-series — the 93LC46 is for the + FT232R / FT2232**D**. Empirical evidence (pyftdi on the repaired V1 unit): the + 128-byte chip mirrors into the upper half (`has_mirroring=True`); a config + write mirror-clobbers word 0x80→0x00 and **fails verify at word 0x02**; and + `set_property` indexes past byte 128. **Consequence:** the "re-BBA-rb" product + string CANNOT be stored on V1. **Not a functional defect** — with U7 left + blank the FT2232H uses ROM defaults ("Dual RS232-HS", 0403:6010), and iceprog + (bitstream flash — verified OK on this unit) + the channel-B UART work + normally. **Fix for a future rev:** fit a 93LC56B at U7 (same SOIC-8, fixed + 16-bit org, pin-compatible). Tooling: `hardware/re-bba-rb/flash_ftdi_eeprom.py` + detects the mirroring and refuses the write; `--erase` blanks U7. - **EE_CS pull-down (R43, 10 kΩ) — ADDED 2026-07-31.** FT2232H DS Table 3.4 states EECS/EECLK/EEDATA are all **"Tri-State during device reset"**, so CS floats while the FT2232H is in reset. The Microchip 93LC46B DS is explicit: @@ -102,7 +117,10 @@ datasheet extraction, WebSearch/WebFetch for parts and reference designs. CDONE=ADBUS6, CRESET=ADBUS7 (verified against iceprog.c; old ADBUS3/ACBUS0/ ACBUS1 now NC). R11/R12 10k pull-ups on CRESET/CDONE intact. - **EEPROM contents decision**: ship blank (default 0403:6010 = what iceprog - opens). Documented in TODO. + opens). Documented in TODO. **Update 2026-08-22:** on V1 this is now *forced* + blank, not just a choice — U7 (93LC46B) is too small to hold an FT2232H config + (see the U7-undersized note above), so the product string can't be programmed + until a 93LC56B is fitted. Blank is the correct, working state. ## 4. FPGA sheet (`Fpga.kicad_sch`) — FULLY REVIEWED, PASS diff --git a/hardware/re-bba-rb/TODO.md b/hardware/re-bba-rb/TODO.md index dccaf27..b722d00 100644 --- a/hardware/re-bba-rb/TODO.md +++ b/hardware/re-bba-rb/TODO.md @@ -358,6 +358,15 @@ Major work this session: ## Minor / BOM +- [ ] **U7 EEPROM undersized — swap 93LC46B → 93LC56B for V2 (found at bring-up + 2026-08-22).** The 93LC46B is 128 B; the FT2232H needs ≥256 B (93LC56B / + 93LC66B) to hold its config, so the "re-BBA-rb" USB product string can't be + programmed on V1 (write mirrors + fails verify — see REVIEW.md "U7 PART IS + UNDERSIZED"). **Not a functional blocker:** V1 ships with U7 blank → FT2232H + ROM defaults ("Dual RS232-HS", 0403:6010); iceprog bitstream flash (VERIFY + OK on the repaired unit) and the channel-B UART are unaffected. 93LC56B is + the same SOIC-8 / fixed-16-bit-org, pin-compatible drop-in. Pick a JLC part + (e.g. 93LC56BT-I/SN) when respinning. - [x] RSET_BG 12.4 k — ACCEPTED 2026-07-18 (closed, no change): datasheet says 12.3 kΩ, but that is an E192 value with no JLC Basic part — WIZnet's own reference synthesizes it as 12 k + 300 Ω. The 0.8 % diff --git a/hardware/re-bba-rb/flash_ftdi_eeprom.py b/hardware/re-bba-rb/flash_ftdi_eeprom.py new file mode 100644 index 0000000..04c54fb --- /dev/null +++ b/hardware/re-bba-rb/flash_ftdi_eeprom.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +"""Program the re-bba-rb FT2232H EEPROM so the unit enumerates as "re-BBA-rb". + +Uses pyftdi (libusb) — the in-container tool, since debian's libftdi1-2 ships +only the runtime lib, not the `ftdi_eeprom` binary. The intended descriptor +values mirror hardware/re-bba-rb/ftdi_eeprom.conf. + +SAFE BY DESIGN: + * Keeps the stock VID/PID 0403:6010 and the dual-channel config, so iceprog + (MPSSE on channel A) and the channel-B UART keep working unchanged — only + the descriptor STRINGS change. + * DRY-RUN BY DEFAULT: prints the diff and writes a raw backup, but does NOT + touch the EEPROM unless you pass --commit. + * Always dumps the current EEPROM to a backup file first. + +Usage (inside the rebuilt devcontainer, FT2232H usbipd-attached): + sudo /opt/venv/bin/python hardware/re-bba-rb/flash_ftdi_eeprom.py # dry-run + backup + sudo /opt/venv/bin/python hardware/re-bba-rb/flash_ftdi_eeprom.py --commit # write strings + sudo /opt/venv/bin/python hardware/re-bba-rb/flash_ftdi_eeprom.py --erase --commit # blank U7 + +⚠️ re-bba-rb V1 HARDWARE LIMITATION: U7 is a 93LC46B (128-byte / 1 Kbit) EEPROM, +which is TOO SMALL for the FT2232H — the H-series needs a 93LC56B (256 B) or +93LC66B (the 93LC46 is for the FT232R / FT2232D). The FT2232H config mirrors in +the 128-byte chip and the string write fails verify, so the "re-BBA-rb" product +string CANNOT be programmed on V1. This script therefore REFUSES the write when +it detects mirroring (use --force to override, --erase to blank U7). The board +is fully functional without it: it enumerates on ROM defaults ("Dual RS232-HS", +0403:6010) and iceprog + the channel-B UART work normally. Fix in a future rev +by fitting a 93LC56B at U7. + +Flash the FPGA bitstream FIRST and confirm iceprog works — the string is purely +cosmetic. Do NOT rely on reset_device(): it re-enumerates the FT2232H and drops +the usbipd attachment on WSL2 — re-attach with usbipd instead. +""" +import argparse +import sys +from pathlib import Path + +VID = 0x0403 +PID = 0x6010 +URL = f"ftdi://0x{VID:04x}:0x{PID:04x}/1" + +MANUFACTURER = "hashru" +PRODUCT = "re-BBA-rb" +SERIAL = "RBBARB001" + +BACKUP = Path(__file__).with_name("eeprom-backup.bin") + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--commit", action="store_true", + help="actually write the EEPROM (default: dry-run only)") + ap.add_argument("--erase", action="store_true", + help="blank U7 to 0xFF (FT2232H falls back to ROM defaults)") + ap.add_argument("--force", action="store_true", + help="attempt the string write even if U7 reports mirroring " + "(undersized 93LC46B) — will likely fail/corrupt") + ap.add_argument("--url", default=URL, help=f"pyftdi device URL (default {URL})") + args = ap.parse_args() + + try: + from pyftdi.eeprom import FtdiEeprom + except ImportError: + print("pyftdi not installed. In the devcontainer it is preinstalled; " + "otherwise: pip install pyftdi", file=sys.stderr) + return 2 + + eeprom = FtdiEeprom() + try: + eeprom.open(args.url) + except Exception as exc: # noqa: BLE001 - surface the real libusb error + print(f"Could not open {args.url}: {exc}", file=sys.stderr) + print("Is the FT2232H usbipd-attached, and are you running under sudo?", + file=sys.stderr) + return 1 + + # 1) Backup the current EEPROM image before any change. + try: + BACKUP.write_bytes(bytes(eeprom.data)) + print(f"Backed up current EEPROM ({len(eeprom.data)} bytes) -> {BACKUP}") + except Exception as exc: # noqa: BLE001 + print(f"WARNING: could not write backup ({exc}); aborting.", file=sys.stderr) + eeprom.close() + return 1 + + # --- Erase mode: blank U7 back to 0xFF (FT2232H then uses ROM defaults). --- + if args.erase: + return _erase(eeprom, args.commit) + + # ------------------------------------------------------------------ + # HARDWARE NOTE — U7 on re-bba-rb V1 is a 93LC46B (1 Kbit = 128 bytes). + # The FT2232H addresses a 256-byte EEPROM and its config does NOT fit in + # 128 bytes: pyftdi sees the 128-byte chip mirror into the upper half + # (has_mirroring=True), the config write mirror-clobbers word 0x80->0x00, + # and verify fails. FTDI specs a 93LC56B (256 B) / 93LC66B for the H-series + # (the 93LC46 is for the FT232R / FT2232D). So the product string CANNOT be + # stored on V1 — the board still works fine on ROM defaults ("Dual RS232-HS", + # 0403:6010; iceprog + the UART are unaffected). Refuse rather than + # half-write (which corrupts U7 and needs an --erase recovery). + # ------------------------------------------------------------------ + if eeprom.has_mirroring and not args.force: + print("\nREFUSING: U7 reports EEPROM mirroring — it is a 128-byte chip " + "(93LC46B), too small for the FT2232H's 256-byte config.\n" + "The 're-BBA-rb' product string cannot be stored on this board " + "(see the header comment / REVIEW.md). The board works fine on ROM " + "defaults. Use --erase to (re)blank U7; --force to attempt anyway.", + file=sys.stderr) + eeprom.close() + return 3 + + # Stage a COMPLETE FT2232H default config, then overlay our strings. + print(f"\nEEPROM currently blank: {eeprom.is_empty} — staging FT2232H defaults.") + eeprom.initialize() + + cfg = eeprom._config # decoded config dict (no public accessor in pyftdi 0.57) + print("\nCurrent (staged-base) descriptors:") + print(f" vendor_id = 0x{cfg.get('vendor_id', 0):04x}") + print(f" product_id = 0x{cfg.get('product_id', 0):04x}") + + # Stage the new strings (VID/PID/channel config untouched). + eeprom.set_manufacturer_name(MANUFACTURER) + eeprom.set_product_name(PRODUCT) + eeprom.set_serial_number(SERIAL) + + print("\nStaged descriptors:") + print(f" manufacturer = {MANUFACTURER!r}") + print(f" product = {PRODUCT!r}") + print(f" serial = {SERIAL!r}") + + if not args.commit: + print("\nDRY-RUN — nothing written. Re-run with --commit to program.") + eeprom.close() + return 0 + + try: + eeprom.commit(dry_run=False) + except Exception as exc: # noqa: BLE001 + print(f"\nWRITE FAILED ({exc}). U7 may be partially written — run with " + "--erase to blank it back to ROM-default fallback.", file=sys.stderr) + eeprom.close() + return 1 + eeprom.close() + # NOTE: do NOT call reset_device() — it re-enumerates the FT2232H, which + # drops the usbipd attachment on WSL2. Re-plug / re-attach manually instead. + print("\nEEPROM written. Re-attach USB (usbipd) so the host shows 're-BBA-rb'.") + return 0 + + +def _erase(eeprom, commit: bool) -> int: + """Blank U7 to 0xFF so the FT2232H falls back to ROM defaults. + + On the mirrored 128-byte chip pyftdi's 256-byte verify trips even though the + 0xFF writes land, so we loop and check the actual content instead of trusting + commit()'s verify. + """ + if not commit: + print("\n--erase DRY-RUN: would write 0xFF over U7. Add --commit to do it.") + eeprom.close() + return 0 + for attempt in range(5): + data = bytes(eeprom.data) + nonff = sum(1 for b in data if b != 0xFF) + print(f"erase attempt {attempt}: non-0xFF bytes = {nonff}") + if nonff == 0: + print("U7 is fully blank — FT2232H will use ROM defaults.") + eeprom.close() + return 0 + eeprom.erase(0xFF) + try: + eeprom.commit(dry_run=False) + except Exception as exc: # noqa: BLE001 - mirrored-chip verify trips; writes still land + print(f" (commit verify raised, expected on mirrored chip: {exc})") + # Re-read fresh next loop without reset_device() (which drops usbip). + eeprom.sync() + print("Could not fully blank U7 after retries — re-run --erase after re-attach.", + file=sys.stderr) + eeprom.close() + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/hardware/re-bba-rb/ftdi_eeprom.conf b/hardware/re-bba-rb/ftdi_eeprom.conf new file mode 100644 index 0000000..3f9c514 --- /dev/null +++ b/hardware/re-bba-rb/ftdi_eeprom.conf @@ -0,0 +1,45 @@ +# FT2232H EEPROM config for the re-bba-rb board (libftdi `ftdi_eeprom`). +# +# NOTE: the devcontainer does NOT ship the `ftdi_eeprom` binary (debian's +# libftdi1-2 is the runtime lib only). Inside the container program the EEPROM +# with the pyftdi script instead — it applies the SAME values as this file: +# sudo /opt/venv/bin/python hardware/re-bba-rb/flash_ftdi_eeprom.py --commit +# This .conf remains the value spec, and works as-is with `ftdi_eeprom` on a host +# that has the libftdi tools, or as a reference when using FT_PROG on Windows. +# +# Purpose: give the on-board FT2232H a product string so the unit shows up as +# "re-BBA-rb" instead of the generic "Dual RS232-HS". +# +# SAFE BY DESIGN — this KEEPS the stock VID/PID (0403:6010) and the default +# dual-channel config, so `iceprog` (MPSSE on interface A) and the channel-B +# UART keep working exactly as before. Only the descriptor strings change. +# +# ⚠️ Before writing: back up whatever is there (it should be blank/default): +# ftdi_eeprom --device i:0x0403:0x6010 --read-eeprom --to-file eeprom-backup.bin +# Then flash the bitstream FIRST and confirm iceprog works; program this +# EEPROM only after that's proven (the string is cosmetic). +# +# Program with: +# ftdi_eeprom --device i:0x0403:0x6010 --flash-eeprom ftdi_eeprom.conf +# (re-plug the USB afterwards so the host re-reads the descriptors.) + +vendor_id=0x0403 # KEEP 0403 — iceprog/D2XX look for this +product_id=0x6010 # KEEP 6010 — FT2232H default; iceprog looks for this +max_power=500 # mA; board draws well under this over USB + +manufacturer=hashru # <- your name/org; free text +product=re-BBA-rb # <- this is what makes it show as "re-BBA-rb" + +use_serial=true +serial=RBBARB001 # <- optional; bump per unit if you want unique serials + +# Bus-powered while flashing over USB (GC not attached). If you ever program +# it while powered from SP1 only, this is still fine — it's a hint to the host. +self_powered=false +remote_wakeup=false + +# Leave the two channels at their FT2232H defaults (UART/serial). MPSSE (used +# by iceprog) is a runtime mode on interface A and works regardless, so there +# is no need to set cha_type/chb_type here. + +filename=re-bba-rb-eeprom.bin # ftdi_eeprom writes the built image here too