#ifndef CRSF_H
#define CRSF_H

#include <stdint.h>
#include <stdbool.h>

/*
 * 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)
 *   capacity_mah : remaining battery capacity in mAh (Issue #325, coulomb counter)
 *   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)
 * capacity unit: mAh (3-byte big-endian, max 16.7M mAh)
 */
void crsf_send_battery(uint32_t voltage_mv, uint32_t capacity_mah,
                       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 */
