Initial commit.

This commit is contained in:
conky
2026-08-31 15:45:58 +03:00
commit ec9805b01a
22 changed files with 1536 additions and 0 deletions

104
AGENTS.md Normal file
View File

@@ -0,0 +1,104 @@
# AGENTS.md
PlatformIO / Arduino-framework firmware for a NUCLEO-F042K6 reading two MS5611
barometers (one I2C, one SPI) and emitting validated CSV over the ST-LINK VCP.
See `README.md` for wiring tables, CSV format and status codes.
## Commands
```sh
pio run # build (the only real verification gate)
pio run -t upload # flash over ST-LINK
pio device monitor # 115200 baud
pio run -t clean
```
There is one env, `nucleo_f042k6`. No lint, format, or typecheck step exists.
**Always read the size report at the end of `pio run`.** It is the acceptance
criterion for any change (see below). Current: flash 88.8% (29108 / 32768),
RAM 32.6% (2004 / 6144).
## Flash budget is the dominant constraint
3.6 KB of flash headroom. This shapes almost every design decision here, and it
is the single easiest thing to break without noticing.
`-flto` and `-fsingle-precision-constant` in `platformio.ini` are load-bearing.
Verified: building without them overflows `FLASH` by **7252 bytes** and fails to
link. Both MS5611 driver libraries write their compensation maths with unsuffixed
double literals, which otherwise links the double soft-float helpers.
Consequences for new code:
- Never introduce `double`, unsuffixed floating literals, or `<math.h>` calls on
doubles. Use `float` and `f`-suffixed constants.
- Never call `Serial.print(someFloat, digits)` — it resolves to
`Print::print(double, int)` and pulls in soft-float. `main.cpp::printFixed2()`
exists solely to format floats via scaled integers; use it.
- Wrap string literals in `F()` so they stay in flash.
- No `String`, no `new`/`delete`. `~BaroChannel()` is deliberately non-virtual
and `protected` to keep a destructor slot out of the vtable and avoid linking
`operator delete`. Do not "fix" this into a virtual destructor.
- `lib_deps` pin exact driver tags (`MS5611#0.5.2`, `MS5611_SPI#0.4.3`). Bumping
them can blow the budget; rebuild and check size if you do.
## Architecture
- `include/config.h` — every pin, address, rate, threshold and validation limit.
Change hardware behaviour **here**, not in the `.cpp` files.
- `include/baro_channel.h` / `src/baro_channel.cpp``BaroChannel`, the shared
state machine: init + PROM/CRC handshake, per-poll validation, error streaks,
re-init, and the 1 s error LED pulse. Five pure-virtual `driver*()` hooks are
the only per-bus surface.
- `src/baro_i2c.cpp` / `src/baro_spi.cpp` — one concrete subclass each, plus a
file-static instance exposed through `baroI2cChannel()` / `baroSpiChannel()`.
- `src/ms5611_crc.cpp` — standalone PROM CRC-4 (AN520).
- `src/main.cpp``setup()`/`loop()`, CSV formatting, 10 Hz report scheduling.
**The two-file split is mandatory, not stylistic.** `MS5611.h` and
`MS5611_SPI.h` each define their own `enum osr_t` and `MS5611_READ_OK`, so they
cannot be included in the same translation unit. `baro_channel.h` therefore
includes neither driver header, and the channels are handed out via accessor
functions. Do not merge these TUs or hoist a driver include into the header.
## Conventions that differ from defaults
- **millis() rollover safety**: deadline comparisons use a signed difference —
`if ((int32_t)(now - deadline) >= 0)`. Never write `now >= deadline`.
- **`poll()` blocks** for ~2 ADC conversions (~5 ms/sensor at OSR 1024).
`main.cpp` re-reads `millis()` after polling before evaluating LED and report
deadlines. Preserve that if you touch the loop.
- **Validation belongs in `BaroChannel`, not the drivers.** Neither library
checks the PROM CRC, and `MS5611::read()` returns `MS5611_READ_OK` for an ADC
read taken before the conversion completed (which yields 0). Do not simplify
the range / stale / all-zero-PROM checks away by trusting driver return codes.
- Style is Allman braces, 2-space indent, `_camelCase` private members, `// `
(two spaces) block comments. There is **no `.clang-format`** in the repo —
running `clang-format` would reformat everything into LLVM style. Don't.
- `SPI` and `I2C` appear in `lib_deps`, but the code uses `Wire` directly and
nothing includes the third-party `I2C` library.
## Testing
There is no automated test suite. `test/` holds only the stock PlatformIO
README, and `pio test` collects 0 cases. Do not claim tests pass.
`ms5611_crc.{h,cpp}` is intentionally free of Arduino headers so it can be
exercised on the host:
```sh
clang++ -std=c++17 -Wall -Wextra -c src/ms5611_crc.cpp -Iinclude -o /tmp/crc.o
```
The differential check against the NuttX reference described in `README.md` was
a host-side exercise and is not committed.
Anything beyond the CRC needs real hardware: build, flash, and watch the CSV
stream. Unplugging a sensor is the quick way to exercise the error paths
(`ERR_INIT` / `ERR_CRC`, LED pulse, auto re-init after 10 consecutive failures).
## Notes
`.pio/`, `.omo/`, `.junie/` and `.idea/` are gitignored tooling state, not
project sources.