34 #if 0 // enable non-verbose debugging 35 #define CRSF_DEBUG PX4_WARN 37 #define CRSF_DEBUG(...) 40 #if 0 // verbose debugging. Careful when enabling: it leads to too much output, causing dropped bytes 41 #define CRSF_VERBOSE PX4_WARN 43 #define CRSF_VERBOSE(...) 54 #define MIN(a,b) (((a)<(b))?(a):(b)) 55 #define MAX(a,b) (((a)>(b))?(a):(b)) 58 #define CRSF_BAUDRATE 420000 60 #define CRSF_SYNC_BYTE 0xC8 104 #pragma pack(push, 1) 139 static bool crsf_parse_buffer(uint16_t *values, uint16_t *num_values, uint16_t max_channels);
141 static uint8_t
crc8_dvb_s2(uint8_t crc, uint8_t a);
152 tcgetattr(uart_fd, &t);
154 t.c_cflag &= ~(CSTOPB | PARENB);
155 return tcsetattr(uart_fd, TCSANOW, &t);
166 bool crsf_parse(
const uint64_t now,
const uint8_t *frame,
unsigned len, uint16_t *values,
167 uint16_t *num_values, uint16_t max_channels)
170 uint8_t *crsf_frame_ptr = (uint8_t *)&crsf_frame;
180 if (current_len == 0) {
181 CRSF_DEBUG(
"========== parser bug: no progress (%i) ===========", len);
184 CRSF_DEBUG(
"crsf_frame_ptr[%i]: 0x%x", i, (
int)crsf_frame_ptr[i]);
188 current_frame_position = 0;
194 frame += current_len;
209 for (
int i = 0; i < 8; ++i) {
211 crc = (crc << 1) ^ 0xD5;
225 for (
int i = 0; i < len; ++i) {
252 static constexpr
float scale = (2012.f - 988.f) / (1811.
f - 172.
f);
253 static constexpr
float offset = 988.f - 172.f * scale;
254 return (scale * chan_value) + offset;
259 uint8_t *crsf_frame_ptr = (uint8_t *)&crsf_frame;
267 unsigned frame_offset = i - 1;
268 CRSF_VERBOSE(
"RC channels found at offset %i", frame_offset);
271 if (frame_offset != 0) {
272 memmove(crsf_frame_ptr, crsf_frame_ptr + frame_offset, current_frame_position - frame_offset);
273 current_frame_position -= frame_offset;
287 crsf_frame_ptr[i] = crsf_frame_ptr[
sizeof(
crsf_frame_t) - current_frame_position + i];
306 if (current_frame_length >
sizeof(
crsf_frame_t) || current_frame_length < 4) {
310 CRSF_DEBUG(
"Frame too long/bogus (%i, type=%i) -> unsync", current_frame_length, crsf_frame.
type);
331 *num_values =
MIN(max_channels, 16);
374 CRSF_DEBUG(
"Got Non-RC frame (len=%i, type=%i)", current_frame_length, crsf_frame.
type);
382 memmove(crsf_frame_ptr, crsf_frame_ptr + current_frame_length,
current_frame_position - current_frame_length);
397 buf[offset++] = value;
405 buf[offset] = value >> 8;
406 buf[offset + 1] = value & 0xff;
415 buf[offset] = value >> 16;
416 buf[offset + 1] = (value >> 8) & 0xff;
417 buf[offset + 2] = value & 0xff;
427 buf[offset] = value >> 24;
428 buf[offset + 1] = (value >> 16) & 0xff;
429 buf[offset + 2] = (value >> 8) & 0xff;
430 buf[offset + 3] = value & 0xff;
459 return write(uart_fd, buf, offset) == offset;
463 uint16_t gps_heading, uint16_t altitude, uint8_t num_satellites)
475 return write(uart_fd, buf, offset) == offset;
487 return write(uart_fd, buf, offset) == offset;
492 const int max_length = 16;
493 int length = strlen(flight_mode) + 1;
495 if (length > max_length) {
499 uint8_t buf[max_length + 4];
502 memcpy(buf + offset, flight_mode, length);
506 return write(uart_fd, buf, offset) == offset;
static uint8_t crc8_dvb_s2_buf(uint8_t *buf, int len)
bool crsf_send_telemetry_gps(int uart_fd, int32_t latitude, int32_t longitude, uint16_t groundspeed, uint16_t gps_heading, uint16_t altitude, uint8_t num_satellites)
Send telemetry GPS information.
bool crsf_send_telemetry_battery(int uart_fd, uint16_t voltage, uint16_t current, int fuel, uint8_t remaining)
Send telemetry battery information.
uint8_t payload[CRSF_PAYLOAD_SIZE_MAX+1]
payload data including 1 byte CRC at end
static void write_frame_crc(uint8_t *buf, int &offset, int buf_size)
static unsigned current_frame_position
static uint8_t crc8_dvb_s2(uint8_t crc, uint8_t a)
bool crsf_parse(const uint64_t now, const uint8_t *frame, unsigned len, uint16_t *values, uint16_t *num_values, uint16_t max_channels)
Parse the CRSF protocol and extract RC channel data.
bool crsf_send_telemetry_attitude(int uart_fd, int16_t pitch, int16_t roll, int16_t yaw)
Send telemetry Attitude information.
uint8_t crsf_frame_CRC(const crsf_frame_t &frame)
High-resolution timer with callouts and timekeeping.
__EXPORT rc_decode_buf_t rc_decode_buf
static void write_uint24_t(uint8_t *buf, int &offset, int value)
write an uint24_t value to a buffer at a given offset and increment the offset
static void write_frame_header(uint8_t *buf, int &offset, crsf_frame_type_t type, uint8_t payload_size)
int crsf_config(int uart_fd)
Configure an UART port to be used for CRSF.
static crsf_parser_state_t parser_state
static crsf_frame_t & crsf_frame
static void write_uint8_t(uint8_t *buf, int &offset, uint8_t value)
write an uint8_t value to a buffer at a given offset and increment the offset
static void write_uint16_t(uint8_t *buf, int &offset, uint16_t value)
write an uint16_t value to a buffer at a given offset and increment the offset
#define CRSF_VERBOSE(...)
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
static void write(bootloader_app_shared_t *pshared)
static bool crsf_parse_buffer(uint16_t *values, uint16_t *num_values, uint16_t max_channels)
parse the current crsf_frame buffer
crsf_frame_header_t header
static uint16_t convert_channel_value(unsigned chan_value)
Convert from RC to PWM value.
RC protocol definition for CSRF (TBS Crossfire).
11 bits per channel * 16 channels = 22 bytes.
bool crsf_send_telemetry_flight_mode(int uart_fd, const char *flight_mode)
Send telemetry Flight Mode information.
static void write_int32_t(uint8_t *buf, int &offset, int32_t value)
write an int32_t value to a buffer at a given offset and increment the offset