diff --git a/README.md b/README.md index ab5cc94..616a333 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,7 @@ Download the latest release binary for your platform: chmod +x anvil sudo mv anvil /usr/local/bin/ -# Windows -# Add anvil.exe to a directory in your PATH +# Windows -- add anvil.exe to a directory in your PATH ``` Then run first-time setup: @@ -32,88 +31,207 @@ anvil setup ``` This checks for `arduino-cli`, installs the `arduino:avr` core, and verifies -your system is ready. +your system is ready. If something is missing, Anvil tells you exactly what +to do. -## Quick Start +## Your First Project + +Create a project, plug in your board, and upload: ```bash -# Create a new project anvil new blink - -# Enter the project cd blink - -# Compile (verify only) -./build.sh - -# Compile and upload to board -./upload.sh - -# Compile, upload, and open serial monitor -./upload.sh --monitor - -# Run host-side tests (no board needed) -./test/run_tests.sh ``` -On Windows, use `build.bat`, `upload.bat`, `monitor.bat`, and -`test\run_tests.bat`. +On **Linux/macOS**: +```bash +./build.sh # compile only (verify) +./upload.sh # compile + upload to board +./upload.sh --monitor # compile, upload, open serial monitor +./monitor.sh # serial monitor (no compile) +./test/run_tests.sh # host-side unit tests (no board needed) +``` + +On **Windows**: +```bat +build REM compile only +upload REM compile + upload +upload --monitor REM compile, upload, open serial monitor +monitor REM serial monitor +test\run_tests REM host-side unit tests +``` + +Every script reads its settings from `.anvil.toml` in the project root. +You edit that file to change the board, baud rate, include paths, or +compiler flags. No Anvil binary required for any of this -- students clone +the repo, plug in a board, and run `upload`. + +## Telling Anvil Which Board to Use + +When you run `upload` without specifying a port, Anvil's scripts auto-detect +the board. They prefer USB serial ports over legacy motherboard COM ports, +which is usually the right thing. But if you have multiple boards plugged in, +or you want a consistent setup, you can pin a specific device. + +### See what's connected + +```bash +anvil devices +``` + +This lists every serial port with its board name, protocol, and -- for USB +devices -- its VID:PID identifier. The VID:PID is a pair of hex codes that +uniquely identifies the USB chip on your board (e.g. `0403:6001` for an FTDI, +`1a86:7523` for a CH340). + +### Save a default device + +```bash +anvil devices --set COM3 # save a specific port +anvil devices --set # auto-detect the best port and save it +``` + +Both forms write a `.anvil.local` file in your project directory. This file +stores the port name *and* the VID:PID of the device on that port. It looks +like this: + +```toml +# Machine-specific Anvil config (not tracked by git) +port = "COM3" +vid_pid = "0403:6001" +``` + +The `.anvil.local` file is gitignored by default. Each machine that works on +the project keeps its own copy with its own port assignment. + +### Why VID:PID matters + +On Windows, if you unplug a USB device and plug it back in to a different +port, it often gets a new COM number (COM3 becomes COM5). The VID:PID +doesn't change -- it's baked into the USB chip. When the scripts see a +VID:PID in `.anvil.local`, they search for that device on whatever port +it's currently on. If it moved, you'll see: + +``` +info Device 0403:6001 found on COM5 (moved from COM3) +``` + +No manual intervention needed. + +### Check what's saved + +```bash +anvil devices --get +``` + +This shows the saved port and VID:PID for the current project, whether the +device is currently connected, and whether it has moved to a different port. + +### Port resolution priority + +When the scripts need a port, they check in this order: + +1. **`-p` flag** -- `upload.bat -p COM3` always wins +2. **VID:PID** from `.anvil.local` -- finds the device regardless of port number +3. **Saved port** from `.anvil.local` -- fallback if VID:PID lookup fails +4. **Auto-detect** -- prefers USB serial over legacy COM ports + +### Specifying a project directory + +Both `--set` and `--get` default to the current directory, but you can point +them at another project: + +```bash +anvil devices --set COM3 -d ../other-project +anvil devices --get -d ../other-project +``` + +## Updating Project Scripts + +When you upgrade Anvil, your existing projects still have the old build +scripts. The `refresh` command updates them to the latest versions without +touching your source code, configuration, or test files: + +```bash +anvil refresh # check current project (dry run) +anvil refresh --force # overwrite differing scripts +anvil refresh ../other-project # check a different project +``` + +Refresh only replaces build infrastructure: `build.sh`, `build.bat`, +`upload.sh`, `upload.bat`, `monitor.sh`, `monitor.bat`, `_detect_port.ps1`, +and `test/run_tests.sh`, `test/run_tests.bat`. It never touches `.anvil.toml`, +`.anvil.local`, your `.ino` files, HAL headers, app code, mocks, or test +sources. ## What Anvil Does vs. What the Project Does -| Need Anvil for | Don't need Anvil for | -|-------------------------------|-------------------------------| -| `anvil new` (create project) | `./build.sh` (compile) | -| `anvil doctor` (diagnose) | `./upload.sh` (flash) | -| `anvil setup` (install core) | `./monitor.sh` (serial) | -| `anvil devices` (port scan) | `./test/run_tests.sh` (test) | +| Need Anvil for | Don't need Anvil for | +|---------------------------------|-------------------------------| +| `anvil new` (create project) | `./build.sh` (compile) | +| `anvil setup` (install core) | `./upload.sh` (flash) | +| `anvil doctor` (diagnose) | `./monitor.sh` (serial) | +| `anvil devices` (port scan) | `./test/run_tests.sh` (test) | +| `anvil refresh` (update scripts)| | -Once a project is created, Anvil is optional. Students clone the repo, -plug in a board, and run `./upload.sh`. +Once a project is created, Anvil is optional for daily work. ## Commands -| Command | Description | -|-------------------|------------------------------------------------| -| `anvil new NAME` | Create a new project with HAL and test scaffold | -| `anvil doctor` | Check system prerequisites | -| `anvil setup` | Install arduino-cli and AVR core | -| `anvil devices` | List connected boards and serial ports | -| `anvil build DIR` | Compile and upload a sketch (convenience) | -| `anvil upload DIR`| Upload cached build (convenience) | -| `anvil monitor` | Open serial monitor (convenience) | +| Command | Description | +|----------------------------------|------------------------------------------------| +| `anvil new NAME` | Create a new project with HAL and test scaffold | +| `anvil setup` | Install arduino-cli and AVR core | +| `anvil doctor` | Check system prerequisites | +| `anvil devices` | List connected boards and serial ports | +| `anvil devices --set [PORT]` | Save default port + VID:PID to .anvil.local | +| `anvil devices --get` | Show saved port for this project | +| `anvil refresh [DIR] [--force]` | Update project scripts to latest templates | -The `build`, `upload`, and `monitor` commands are convenience wrappers. -They do the same thing as the generated scripts. +## Project Structure -## Project Architecture - -Every Anvil project uses a Hardware Abstraction Layer (HAL): +Every generated project follows the same layout: ``` your-project/ - your-project/your-project.ino -- entry point - lib/hal/hal.h -- abstract interface - lib/hal/hal_arduino.h -- real hardware (Arduino.h) - lib/app/your-project_app.h -- app logic (testable) - test/mocks/mock_hal.h -- Google Mock HAL - test/test_unit.cpp -- unit tests - build.sh / build.bat -- compile - upload.sh / upload.bat -- compile + flash - monitor.sh / monitor.bat -- serial monitor - .anvil.toml -- project config + your-project/your-project.ino Entry point (setup + loop) + lib/ + hal/ + hal.h Hardware abstraction interface + hal_arduino.h Real hardware implementation + app/ + your-project_app.h Application logic (testable) + test/ + mocks/ + mock_hal.h Google Mock HAL + sim_hal.h Stateful simulator HAL + test_unit.cpp Unit tests + CMakeLists.txt Test build system + run_tests.sh / .bat Test runner + build.sh / build.bat Compile sketch + upload.sh / upload.bat Compile + upload to board + monitor.sh / monitor.bat Serial monitor + _detect_port.ps1 Port detection helper (Windows) + .anvil.toml Project config (tracked by git) + .anvil.local Machine-specific config (gitignored) ``` -The app code depends on `Hal`, never on `Arduino.h` directly. This means -your application logic compiles and runs on the host for testing. +All hardware access goes through the `Hal` interface in `lib/hal/hal.h`. +Application code in `lib/app/` depends only on `Hal`, never on `Arduino.h` +directly. This means the app logic compiles and runs on the host for testing +with Google Mock -- no board required. ## Configuration -Each project has an `.anvil.toml`: +### .anvil.toml (tracked by git) + +Shared project settings. Edit this to change the board, baud rate, or +compiler flags: ```toml [project] name = "blink" +anvil_version = "1.0.0" [build] fqbn = "arduino:avr:uno" @@ -125,6 +243,15 @@ extra_flags = ["-Werror"] baud = 115200 ``` +### .anvil.local (not tracked by git) + +Machine-specific settings, created by `anvil devices --set`: + +```toml +port = "COM3" +vid_pid = "0403:6001" +``` + ## Building from Source ```bash @@ -136,4 +263,4 @@ The release binary is at `target/release/anvil` (Linux) or ## License -MIT -- see [LICENSE](LICENSE). +MIT -- see [LICENSE](LICENSE). \ No newline at end of file diff --git a/templates/basic/README.md.tmpl b/templates/basic/README.md.tmpl index ba591aa..d4aa4ce 100644 --- a/templates/basic/README.md.tmpl +++ b/templates/basic/README.md.tmpl @@ -7,31 +7,42 @@ in PATH -- the Anvil binary is not required for day-to-day work. ## Quick Start +On **Linux/macOS**: ```bash -# Compile only (verify) -./build.sh - -# Compile and upload to board -./upload.sh - -# Compile, upload, and open serial monitor -./upload.sh --monitor - -# Open serial monitor (no compile) -./monitor.sh - -# Persistent monitor (reconnects after reset/replug) -./monitor.sh --watch - -# Run host-side unit tests (no board needed) -./test/run_tests.sh +./build.sh # compile only (verify) +./upload.sh # compile + upload to board +./upload.sh --monitor # compile, upload, open serial monitor +./monitor.sh # serial monitor (no compile) +./monitor.sh --watch # persistent monitor (reconnects after reset) +./test/run_tests.sh # host-side unit tests (no board needed) ``` -On Windows, use `build.bat`, `upload.bat`, `monitor.bat`, and -`test\run_tests.bat` instead. +On **Windows**: +```bat +build REM compile only +upload REM compile + upload +upload --monitor REM compile, upload, open serial monitor +monitor REM serial monitor +test\run_tests REM host-side unit tests +``` -All scripts read settings from `.anvil.toml` -- edit it to change -the board, baud rate, include paths, or compiler flags. +All scripts read settings from `.anvil.toml` and port config from +`.anvil.local` (if present). + +## Selecting a Board + +The scripts auto-detect your board when you run `upload` or `monitor`. +To save a specific device so it persists across sessions: + +```bash +anvil devices # see what's connected +anvil devices --set COM3 # save that port (also captures VID:PID) +anvil devices --get # check what's saved +``` + +This writes `.anvil.local`, which is gitignored. Each machine keeps its own. +The VID:PID is captured automatically so the scripts can find your device +even if the COM port number changes after a replug. ## Project Structure @@ -51,12 +62,13 @@ the board, baud rate, include paths, or compiler flags. sim_hal.h Stateful simulator HAL test_unit.cpp Unit tests CMakeLists.txt Test build system - run_tests.sh Test runner (Linux/Mac) - run_tests.bat Test runner (Windows) + run_tests.sh / .bat Test runner build.sh / build.bat Compile sketch upload.sh / upload.bat Compile + upload to board monitor.sh / monitor.bat Serial monitor - .anvil.toml Project configuration + _detect_port.ps1 Port detection helper (Windows) + .anvil.toml Project config (tracked by git) + .anvil.local Machine-specific config (gitignored) ``` ## Architecture @@ -72,7 +84,9 @@ Two HAL implementations: ## Configuration -Edit `.anvil.toml` to change board, baud rate, or build settings: +### .anvil.toml (tracked by git) + +Shared project settings: ```toml [build] @@ -85,6 +99,15 @@ extra_flags = ["-Werror"] baud = 115200 ``` +### .anvil.local (not tracked by git) + +Machine-specific port assignment, created by `anvil devices --set`: + +```toml +port = "COM3" +vid_pid = "0403:6001" +``` + ## Prerequisites - `arduino-cli` in PATH with `arduino:avr` core installed