sl-firmware 00c97bd902 feat(rc): CRSF/ELRS RC integration — telemetry uplink + channel fix (Issue #103)
## Summary
- config.h: CH1[0]=steer, CH2[1]=throttle (was CH4/CH3); CRSF_FAILSAFE_MS→500ms
- include/battery.h + src/battery.c: ADC3 Vbat reading on PC1 (11:1 divider)
  battery_read_mv(), battery_estimate_pct() for 3S/4S auto-detection
- include/crsf.h + src/crsf.c: CRSF telemetry TX uplink
  crsf_send_battery() — type 0x08, voltage/current/SoC to ELRS TX module
  crsf_send_flight_mode() — type 0x21, "ARMED\0"/"DISARM\0" for handset OSD
- src/main.c: battery_init() after crsf_init(); 1Hz telemetry tick calls
  crsf_send_battery(vbat_mv, 0, soc_pct) + crsf_send_flight_mode(armed)
- test/test_crsf_frames.py: 28 pytest tests — CRC8-DVB-S2, battery frame
  layout/encoding, flight-mode frame, battery_estimate_pct SoC math

Existing (already complete from crsf-elrs branch):
  CRSF frame decoder UART4 420000 baud DMA circular + IDLE interrupt
  Mode manager: RC↔autonomous blend, CH6 3-pos switch, 500ms smooth transition
  Failsafe in main.c: disarm if crsf_state.last_rx_ms stale > CRSF_FAILSAFE_MS
  CH5 arm switch with ARMING_HOLD_MS interlock + edge detection
  RC override: mode_manager blends steer/speed per mode (CH6)

Closes #103

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 08:35:39 -05:00

70 lines
2.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 0100 % */
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 (1721811) 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 0100 % (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 */