Files
anvil/templates/basic
Eric Ratliff 706f420aaa feat: Layer 2 device library system with TMP36 reference driver
Add embedded device library registry with full lifecycle management,
automated test integration, and pin assignment workflow.

Library system:
- Library registry embedded in binary via include_dir! (same as templates)
- library.toml metadata format: name, version, bus type, pins, provided files
- anvil add <name> extracts headers to lib/drivers/<name>/, test files to test/
- anvil remove <name> cleans up all files, config entries, and include paths
- anvil lib lists installed libraries with status
- anvil lib --available shows registry with student-friendly wiring summary
- [libraries] section in .anvil.toml tracks installed libraries and versions
- CMake auto-discovers lib/drivers/*/ for include paths at configure time

TMP36 analog temperature sensor (reference implementation):
- TempSensor abstract interface (readCelsius/readFahrenheit/readRaw)
- Tmp36Analog: real hardware impl via Hal::analogRead with configurable Vref
- Tmp36Mock: programmable values, read counting, no hardware needed
- Tmp36Sim: deterministic noise via seeded LCG for repeatable system tests
- test_tmp36.cpp: 21 Google Test cases covering mock, analog, sim, polymorphism
- TMP36 formula: voltage_mV = raw * Vref_mV / 1024, temp_C = (mV - 500) / 10

Automated test integration:
- Library test files (test_*.cpp) route to test/ during extraction
- CMakeLists.txt auto-discovers test_*.cpp via GLOB, builds each as own target
- anvil remove cleans up test files alongside driver headers
- Zero manual CMake editing: add library, run test --clean, tests appear

Pin assignment integration:
- anvil add <name> --pin A0 does extract + pin assignment in one step
- Without --pin, prints step-by-step wiring guidance with copy-paste commands
- anvil pin --audit flags installed libraries with unassigned pins
- Audit works even with zero existing pin assignments (fixed early-return bug)
- LibraryMeta helpers: wiring_summary(), pin_roles(), default_mode()
- Bus-aware guidance: analog pins, I2C bus registration, SPI with CS selection

UX improvements:
- anvil lib --available shows "Needs: 1 analog pin (e.g. A0)" not raw metadata
- anvil add prints app code example, test code example, and next step
- anvil pin --audit prints exact commands to resolve missing library pins
- anvil remove shows test file deletion in output

Files added:
- libraries/tmp36/library.toml
- libraries/tmp36/src/tmp36.h, tmp36_analog.h, tmp36_mock.h, tmp36_sim.h
- libraries/tmp36/src/test_tmp36.cpp
- src/library/mod.rs

Files modified:
- src/lib.rs, src/main.rs, src/commands/mod.rs
- src/commands/lib.rs (add/remove/list/list_available with --pin support)
- src/commands/pin.rs (audit library pin warnings, print_library_pin_warnings)
- src/project/config.rs (libraries HashMap field)
- templates/basic/test/CMakeLists.txt.tmpl (driver + test auto-discovery)

Tests: 254 total (89 unit + 165 integration)
- 12 library/mod.rs unit tests (registry, extraction, helpers)
- 2 commands/lib.rs unit tests (class name derivation)
- 30+ new integration tests covering library lifecycle, pin integration,
  audit flows, file routing, CMake discovery, config roundtrips, ASCII
  compliance, polymorphism contracts, and idempotent add/remove cycles
2026-02-21 13:14:43 -06:00
..
2026-02-19 10:23:16 -06:00
2026-02-19 10:23:16 -06:00
2026-02-19 13:29:06 -06:00
2026-02-18 20:36:57 -06:00
2026-02-19 10:23:16 -06:00
2026-02-19 10:23:16 -06:00

# {{PROJECT_NAME}}

Arduino project generated by [Anvil](https://github.com/nexusworkshops/anvil) v{{ANVIL_VERSION}}.

This project is self-contained. After creation, it only needs `arduino-cli`
in PATH -- the Anvil binary is not required for day-to-day work.

## Quick Start

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)
./monitor.sh --watch        # persistent monitor (reconnects after reset)
./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
```

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

```
{{PROJECT_NAME}}/
    {{PROJECT_NAME}}/
        {{PROJECT_NAME}}.ino       Entry point (setup + loop)
    lib/
        hal/
            hal.h                  Hardware abstraction interface
            hal_arduino.h          Real hardware implementation
        app/
            {{PROJECT_NAME}}_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)
```

## Architecture

All hardware access goes through the `Hal` interface. The app code
(`lib/app/`) depends only on `Hal`, never on `Arduino.h` directly.
This means the app can be compiled and tested on the host without
any Arduino hardware.

Two HAL implementations:
- `ArduinoHal` -- passthroughs to real hardware (used in the .ino)
- `MockHal` -- Google Mock for verifying exact call sequences in tests

## Configuration

### .anvil.toml (tracked by git)

Shared project settings:

```toml
[build]
fqbn = "arduino:avr:uno"
warnings = "more"
include_dirs = ["lib/hal", "lib/app"]
extra_flags = ["-Werror"]

[monitor]
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
- For host tests: `cmake`, `g++` (or `clang++`), `git`
- Install everything at once: `anvil setup`