LAPDOG

Protocol

LapDog frames (USB and Bluetooth)

Every event is one small binary frame, identical on both transports, so a receiver needs a single parser:

  • USB: F: + hex + newline, mixed in with plain text replies and logs.
  • Bluetooth: the raw frame as manufacturer data in a legacy advert (company ID 0xFFFF for now).

A legacy advert carries 31 bytes. After the flags and manufacturer-data header, 24 are left, so a frame is at most 24 bytes and always fits in one advert.

Header

Byte Field
0 version (high nibble, currently 2) and type (low nibble)
1 seq: increments every frame, used to drop repeated adverts and USB/Bluetooth duplicates
2 pilot

Types

Multi-byte values are little-endian.

Type Body
1 LAP lap number (0 = start/holeshot), flags (best, final), lap time ms u32
2 ARMED mode, heat u16, lap limit, time limit s u16
3 DISARMED heat u16, laps completed, passes ignored
4 HEARTBEAT race stage, mode, heat u16, uptime ms u32
5 RACE race stage, race time ms u32 since GO
6 TEXT slot, part/parts, up to 19 bytes of text
7 IGNORED reason (1 too soon, 2 too long), ms u32, count this heat

TEXT carries the race messages: slots 0–17 are goggle OSD rows (the same text the goggles show), plus the event name and the heat prefix. Text longer than one frame is split into up to 15 parts with consecutive sequence numbers.

ESP-NOW (goggles and RacePanel)

On ESP-NOW, LapDog acts as an ELRS Backpack timer, the way RotorHazard's VRxC_ELRS plugin does on race days:

  • The sender MAC is your ELRS bind-phrase UID: the first six bytes of MD5("-DMY_BINDING_PHRASE=\"<phrase>\""), with the multicast bit cleared.
  • Messages are MSPv2 frames with function 0x00B6 (MSP_ELRS_SET_OSD): 0x02 clear, 0x03 row col 0 text… to place text, and 0x04 to display.
  • Rows: event 0, heat 2, race status 5, lap result 15 (e.g. L1:0:14.630 | BEST).
  • Always on a 2.4 GHz channel. Never 5 GHz ESP-NOW: Wi-Fi channels 149–165 overlap the FPV band and would hit your video right at the gate.

The encoder and decoder live in vrxc-msp, a small header-only library shared by LapDog and RacePanel so they can't drift apart.