#ifndef CRSF_H #define CRSF_H #include #include /* * CRSF/ExpressLRS RC receiver state. * * Updated from ISR context on every valid frame. * Read from main loop — values are naturally atomic (8/16-bit on Cortex-M). * last_rx_ms == 0 means no frame received yet (USB-only mode). */ typedef struct { uint16_t channels[16]; /* Raw CRSF values, 172 (988µs) – 1811 (2012µs) */ uint32_t last_rx_ms; /* HAL_GetTick() at last valid RC frame */ bool armed; /* CH5 arm switch: true when channels[4] > CRSF_ARM_THRESHOLD */ /* Link statistics (from 0x14 frames, optional) */ int8_t rssi_dbm; /* Uplink RSSI in dBm (negative, e.g. -85) */ uint8_t link_quality; /* Uplink link quality 0–100 % */ int8_t snr; /* Uplink SNR in dB */ } CRSFState; /* * crsf_init() — configure UART4 (PA0=TX, PA1=RX) at 420000 baud with * DMA1 circular RX and IDLE interrupt. Call once before safety_init(). */ void crsf_init(void); /* * crsf_parse_byte() — feed one byte into the frame parser. * Called automatically from DMA/IDLE ISR. Available for unit tests. */ void crsf_parse_byte(uint8_t byte); /* * crsf_to_range() — map raw CRSF value (172–1811) linearly to [min, max]. * Clamps at boundaries. Midpoint 992 → (min+max)/2. */ int16_t crsf_to_range(uint16_t val, int16_t min, int16_t max); /* * crsf_send_battery() — transmit CRSF battery-sensor telemetry frame (type 0x08) * back to the ELRS TX module over UART4 TX. Call at CRSF_TELEMETRY_HZ (1 Hz). * * voltage_mv : battery voltage in millivolts (e.g. 12600 for 3S full) * current_ma : current draw in milliamps (0 if no sensor) * remaining_pct: state-of-charge 0–100 % (255 = unknown) * * Frame: [0xC8][12][0x08][v16_hi][v16_lo][c16_hi][c16_lo][cap24×3][rem][CRC] * voltage unit: 100 mV (12600 mV → 126) * current unit: 100 mA */ void crsf_send_battery(uint32_t voltage_mv, uint32_t current_ma, uint8_t remaining_pct); /* * crsf_send_flight_mode() — transmit CRSF flight-mode frame (type 0x21) * for display on the pilot's handset OSD. * * armed: true → "ARMED\0" * false → "DISARM\0" */ void crsf_send_flight_mode(bool armed); extern volatile CRSFState crsf_state; #endif /* CRSF_H */