2026-08-11 14:50:35 +02:00
|
|
|
# OBU transmit firmware - Phase 2 (in progress: HLN-SV DENM beacon)
|
|
|
|
|
|
|
|
|
|
Started. See `docs/04-transmit-setup.md` in the project root for build/flash
|
|
|
|
|
steps and how to validate this against your own sniffer.
|
|
|
|
|
|
|
|
|
|
## Toolchain: use a dedicated terminal (ESP-IDF 5.5.4)
|
|
|
|
|
|
|
|
|
|
This project builds against the **global** ESP-IDF 5.5.4, NOT the 6.1 checkout
|
|
|
|
|
that `obu-firmware` uses. Keep one terminal per toolchain and never export both
|
|
|
|
|
in the same window - the second export inherits the first's
|
|
|
|
|
`IDF_PYTHON_ENV_PATH` and then fails every dependency check (`click`,
|
|
|
|
|
`esptool`, `cryptography`, ... "not met"). That is env-var bleed, not a broken
|
|
|
|
|
install: do **not** run `install.bat` to "fix" it, that damages one of the two
|
|
|
|
|
environments.
|
|
|
|
|
|
|
|
|
|
| Terminal | Export | Project |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| Transmitter | `C:\Espressif\frameworks\esp-idf-v5.5.4\export.ps1` | this one |
|
|
|
|
|
| OBU | `...\micrOBU_workspace\its-g5-receiver-firmware\esp-idf\export.ps1` | `obu-firmware` |
|
|
|
|
|
|
|
|
|
|
If a terminal has already been used for the other IDF, clear the state first:
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
$env:IDF_PYTHON_ENV_PATH = $null; $env:IDF_PATH = $null
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Also note `build/` here was regenerated from scratch (its CMake cache still
|
|
|
|
|
referenced an older source path under `micrOBU_workspace/v2x-obu-esp32c5/`,
|
|
|
|
|
which makes `idf.py fullclean` refuse to run). If that error reappears, delete
|
|
|
|
|
`build/` manually rather than fighting it.
|
|
|
|
|
|
|
|
|
|
## CAM encoding
|
|
|
|
|
|
|
|
|
|
`main/cam.c` IS compiled here (unlike `obu-firmware`'s copy, which is a
|
|
|
|
|
reference only). It must stay bit-identical to `obu-firmware/main/cam.c` and
|
|
|
|
|
the app's `CamUperCodec.kt` - all three encode the same wire format, and a
|
|
|
|
|
one-bit divergence in any of them is invisible on the bench but wrong against
|
|
|
|
|
real equipment. See the `CurvatureCalculationMode` comment in that file.
|
|
|
|
|
|
|
|
|
|
Implements one profile so far: **HLN-SV** (aftermarket stationary recovery
|
|
|
|
|
vehicle), causeCode 94 (stationaryVehicle), subCauseCode 0, active while the
|
|
|
|
|
hazard-light GPIO is grounded. No location/alacarte containers.
|
|
|
|
|
|
|
|
|
|
- `main/main.c` - entry point, the `phy_11p_set`/`phy_change_channel(5900,...)`
|
|
|
|
|
register hack, GPIO polling, TX loop
|
|
|
|
|
- `main/denm.c` / `.h` - ASN.1 UPER encoding of a minimal DENM
|
|
|
|
|
- `main/geonet.c` / `.h` - GeoNetworking Basic/Common/SHB headers + BTP-B
|
|
|
|
|
- `main/dot11p.c` / `.h` - 802.11 OCB (QoS Data, broadcast) frame + LLC/SNAP
|
|
|
|
|
|
|
|
|
|
Known gaps, tracked as TODOs in the source: no real GNSS (lat/long hardcoded
|
|
|
|
|
0), no real time source (detectionTime/referenceTime hardcoded 0, decodes as
|
|
|
|
|
2004-01-01), fixed (non-rotating) pseudonym MAC, SHB instead of GeoBroadcast
|
|
|
|
|
(no multi-hop forwarding), unsecured (no IEEE 1609.2 signing).
|
2026-09-14 13:33:47 +02:00
|
|
|
|
|
|
|
|
## Running it as a bench beacon
|
|
|
|
|
|
|
|
|
|
This firmware needs no phone: it beacons a CAM every second by itself
|
|
|
|
|
(`TX_INTERVAL_MS`) from station `0x0BADC0DE` (195936478), stationType 5
|
|
|
|
|
(passengerCar), at the hardcoded bench position, under the fixed MAC
|
|
|
|
|
`02:00:00:00:00:01`, on 5900 MHz. That makes it the quickest way to put known,
|
|
|
|
|
repeatable traffic on air, and it is how the 4-bit `yawRateConfidence` encoding
|
|
|
|
|
was confirmed over the air on 2026-09-14.
|
|
|
|
|
|
|
|
|
|
A board with only one USB-C port is fine. This firmware's console is on UART0,
|
|
|
|
|
so such a board shows no log output, but nothing here needs the console.
|
|
|
|
|
|
|
|
|
|
Flash it from the toolchain terminal (ESP-IDF 5.5.4, see the table above):
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
cd C:\Users\Ashin\AndroidStudioProjects\MicrOBU\obu-cam-transmistter
|
|
|
|
|
idf.py -p COM10 -b 921600 flash
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Or flash the existing build without any toolchain terminal:
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
cd obu-cam-transmistter\build
|
|
|
|
|
C:\Espressif\python_env\idf5.5_py3.11_env\Scripts\python.exe -m esptool --chip esp32c5 -p COM10 -b 921600 write_flash --flash_mode dio --flash_freq 80m --flash_size 2MB 0x2000 bootloader/bootloader.bin 0x8000 partition_table/partition-table.bin 0x10000 obu_firmware.bin
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
It starts beaconing as soon as it boots, so there is nothing to start by hand,
|
|
|
|
|
and unplugging it is how you stop it.
|
|
|
|
|
|
|
|
|
|
**It transmits under the same MAC as the phone's CAM pinger**, so on air the two
|
|
|
|
|
are told apart by station ID (195936478 here, 999999 for the pinger), never by
|
|
|
|
|
source address.
|
|
|
|
|
|
|
|
|
|
To see what it is sending, capture on the sniffer board and decode:
|
|
|
|
|
|
|
|
|
|
```powershell
|
2026-09-14 13:38:38 +02:00
|
|
|
cd capture
|
2026-09-14 13:33:47 +02:00
|
|
|
py -3.11 live_capture.py COM8
|
|
|
|
|
py -3.11 ..\obu-firmware\test\pcap_gn_tally.py recordings\capture_<timestamp>.pcap
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The tally lists it as SHB / port 2001 / lifetime `0x05`. For the message itself,
|
|
|
|
|
decode the payload with `asn1tools` against `asn1/cam_1_4_1.asn` +
|
|
|
|
|
`asn1/cdd_1_3_1_1.asn`; re-encoding must return the identical bytes. On
|
|
|
|
|
2026-09-14, 72 of 72 frames did.
|