- Firmware: rewrite obu-firmware TX loop to be serial-driven (no on-chip timer), add promiscuous RX + GeoNetworking/BTP unwrap (gn_unwrap.c), add binary UART framing to the phone (serial_link.c/.h). Drop local cam_encode() - CAM is now built on the phone. - Kotlin: byte-exact UPER CAM encoder/decoder ported from cam.c (BitWriter/BitReader/CamUperCodec), matching SerialFrame codec, real UsbSerialTransport (usb-serial-for-android), CamTransmitLoop (1Hz base rate, event/geofence boost, ESP32-C5-only), wired into CamUseCaseRepository for RX and TripRecordingService for TX. - Add V2X message retention: persist all CAM (own+remote) to Room while recording, drop otherwise (DB v2 -> v3 migration). - Add jitpack repo + usb-serial-for-android dependency. Fixes: UsbSerialTransport now uses SerialInputOutputManager.start()/stop() (this lib version manages its own thread internally) instead of manual Runnable/Thread submission, which didn't compile.
64 lines
3.6 KiB
C
64 lines
3.6 KiB
C
#ifndef SERIAL_LINK_H
|
|
#define SERIAL_LINK_H
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
|
|
// Binary framing for the phone <-> ESP32-C5 link (Phase 03). Deliberately NOT the same UART as
|
|
// the ESP-IDF console/ESP_LOG output (UART0, see sdkconfig CONFIG_ESP_CONSOLE_UART_NUM=0) -
|
|
// mixing binary frames with human-readable log text on one wire would corrupt both. This runs
|
|
// on a dedicated UART (see SERIAL_LINK_UART_NUM / TX / RX pins below - CHANGE THESE to match
|
|
// your board's actual wiring from the USB-C connector's UART bridge to ESP32-C5 GPIOs).
|
|
//
|
|
// Frame format (both directions, symmetric):
|
|
// [0xAA][0x55][type:1][length:2 LE][payload: length bytes][crc16:2 LE]
|
|
// CRC16 is CRC-16/CCITT-FALSE (poly 0x1021, init 0xFFFF, no reflect, no xorout), computed over
|
|
// type + length + payload only (not the two sync bytes). Same algorithm must be used on the
|
|
// Kotlin side (see app SerialFrame.kt) - frames that don't checksum are silently dropped.
|
|
//
|
|
// Direction / types:
|
|
// SERIAL_MSG_CAM_TX (0x01), phone -> ESP32: payload is a raw CAM UPER byte string, already
|
|
// built by the phone (position/speed/heading/yaw rate baked in). On receipt the ESP32
|
|
// immediately GeoNetworking-wraps and transmits it - this IS the transmit clock now, there
|
|
// is no independent on-chip timer. See main.c's rx-driven tx path.
|
|
// SERIAL_MSG_CAM_RX (0x02), ESP32 -> phone: payload is [rssi:1 signed][CAM UPER bytes...] - a
|
|
// CAM received over the air, already stripped of its 802.11/LLC-SNAP/GeoNetworking/BTP-B
|
|
// framing by gn_unwrap.c. The phone never sees raw 802.11 frames. No station id is carried
|
|
// separately - CAM's own ItsPduHeader.stationID (the first field inside the UPER bytes) is
|
|
// already the meaningful identifier; see gn_unwrap.h for why a second one isn't added here.
|
|
// SERIAL_MSG_STATUS (0x03), ESP32 -> phone: 1-byte heartbeat (0 = ok), sent periodically so
|
|
// the phone can distinguish "link idle" from "link dead" independent of CAM traffic.
|
|
#define SERIAL_MSG_CAM_TX 0x01
|
|
#define SERIAL_MSG_CAM_RX 0x02
|
|
#define SERIAL_MSG_STATUS 0x03
|
|
|
|
// CHANGE THESE to match your board's actual USB-C -> UART bridge wiring. UART0 is already
|
|
// claimed by the console/ESP_LOG; picking UART1 here to stay clear of it. These are common
|
|
// free GPIOs on ESP32-C5 devkits but are NOT guaranteed free on your specific board - check
|
|
// your schematic before flashing.
|
|
#define SERIAL_LINK_UART_NUM 1
|
|
#define SERIAL_LINK_TX_GPIO 4
|
|
#define SERIAL_LINK_RX_GPIO 5
|
|
#define SERIAL_LINK_BAUD 115200
|
|
|
|
// Max CAM payload this link will carry. cam.c sizes its own encode buffer at 96 bytes; 160
|
|
// gives headroom for the RX path's extra station_id+rssi prefix plus margin.
|
|
#define SERIAL_LINK_MAX_PAYLOAD 160
|
|
|
|
// Initializes the dedicated UART and its background RX-framing task. Call once from app_main,
|
|
// after nvs/event loop init. `on_cam_tx` is invoked (from the RX task's context - keep it fast,
|
|
// it blocks the next frame's parsing) whenever a complete, checksummed SERIAL_MSG_CAM_TX frame
|
|
// arrives from the phone.
|
|
typedef void (*serial_link_cam_tx_cb_t)(const uint8_t *cam_uper, int cam_len);
|
|
void serial_link_init(serial_link_cam_tx_cb_t on_cam_tx);
|
|
|
|
// Sends a SERIAL_MSG_CAM_RX frame to the phone: rssi + the CAM UPER bytes gn_unwrap.c extracted
|
|
// from an over-the-air frame. Returns true if the frame was written to the UART (not an
|
|
// end-to-end ack - the phone may still drop it, e.g. serial buffer overrun).
|
|
bool serial_link_send_cam_rx(int8_t rssi, const uint8_t *cam_uper, int cam_len);
|
|
|
|
// Sends a 1-byte SERIAL_MSG_STATUS heartbeat frame.
|
|
bool serial_link_send_status(uint8_t status);
|
|
|
|
#endif
|