33 #ifdef PIOS_INCLUDE_CROSSFIRE
37 #define CRSF_LEN_IDX 2
38 #define CRSF_HEADER_IDX 3
44 #define CRSF_CRCFIELD(frame) (frame.payload[frame.length - CRSF_CRC_LEN - CRSF_TYPE_LEN])
47 #define PIOS_CROSSFIRE_MAGIC 0xcdf19cf5
52 struct pios_crossfire_dev {
56 uint16_t failsafe_timer;
57 uint8_t bytes_expected;
73 uintptr_t telem_com_id;
76 uint32_t time_frame_start;
83 static struct pios_crossfire_dev *PIOS_Crossfire_Alloc(
void);
89 static bool PIOS_Crossfire_Validate(
const struct pios_crossfire_dev *dev);
96 static int32_t PIOS_Crossfire_Read(uintptr_t
id, uint8_t channel);
102 static void PIOS_Crossfire_SetAllChannels(
struct pios_crossfire_dev *dev, uint16_t
value);
112 static uint16_t PIOS_Crossfire_Receive(uintptr_t context, uint8_t *buf, uint16_t buf_len,
113 uint16_t *headroom,
bool *task_woken);
118 static void PIOS_Crossfire_ResetBuffer(
struct pios_crossfire_dev *dev);
123 static bool PIOS_Crossfire_UnpackFrame(
struct pios_crossfire_dev *dev);
128 static void PIOS_Crossfire_Supervisor(uintptr_t context);
132 .
read = PIOS_Crossfire_Read,
136 static struct pios_crossfire_dev *PIOS_Crossfire_Alloc(
void)
138 struct pios_crossfire_dev *dev =
PIOS_malloc_no_dma(
sizeof(
struct pios_crossfire_dev));
142 memset(dev, 0,
sizeof(*dev));
143 dev->magic = PIOS_CROSSFIRE_MAGIC;
148 static bool PIOS_Crossfire_Validate(
const struct pios_crossfire_dev *dev)
150 return dev && dev->magic == PIOS_CROSSFIRE_MAGIC;
156 struct pios_crossfire_dev *dev = PIOS_Crossfire_Alloc();
161 *crsf_id = (uintptr_t)dev;
162 dev->usart_id = usart_id;
163 dev->usart_driver = driver;
165 PIOS_Crossfire_ResetBuffer(dev);
175 (driver->
bind_rx_cb)(usart_id, PIOS_Crossfire_Receive, *crsf_id);
182 struct pios_crossfire_dev *dev = (
struct pios_crossfire_dev*)crsf_id;
185 if(!PIOS_Crossfire_Validate(dev))
191 static int32_t PIOS_Crossfire_Read(uintptr_t context, uint8_t channel)
196 struct pios_crossfire_dev *dev = (
struct pios_crossfire_dev *)context;
197 if (!PIOS_Crossfire_Validate(dev))
200 return dev->channel_data[channel];
203 static void PIOS_Crossfire_SetAllChannels(
struct pios_crossfire_dev *dev, uint16_t
value)
206 dev->channel_data[
i] = value;
209 static uint16_t PIOS_Crossfire_Receive(uintptr_t context, uint8_t *buf, uint16_t buf_len,
210 uint16_t *headroom,
bool *task_woken)
212 struct pios_crossfire_dev *dev = (
struct pios_crossfire_dev *)context;
214 if (!PIOS_Crossfire_Validate(dev))
217 if(dev->buf_pos == 0) {
221 for (
int i = 0;
i < buf_len;
i++) {
223 if(dev->buf_pos >= dev->bytes_expected)
226 dev->u.rx_buf[dev->buf_pos++] = buf[
i];
228 if(dev->buf_pos == CRSF_LEN_IDX) {
234 dev->bytes_expected = 0;
239 if (dev->buf_pos == dev->bytes_expected) {
241 if(PIOS_Crossfire_UnpackFrame(dev)) {
255 if(task_woken) *task_woken =
false;
259 if(headroom) *headroom = 0;
260 if(task_woken) *task_woken =
false;
264 static void PIOS_Crossfire_ResetBuffer(
struct pios_crossfire_dev *dev)
270 static bool PIOS_Crossfire_UnpackFrame(
struct pios_crossfire_dev *dev)
282 if(crc == CRSF_CRCFIELD(dev->u.frame)) {
284 uint8_t *s = dev->u.frame.payload;
285 uint16_t *
d = dev->channel_data;
287 #define F(v,s) (((v) >> (s)) & 0x7ff)
290 d[0] =
F(s[0] | s[1] << 8, 0);
291 d[1] =
F(s[1] | s[2] << 8, 3);
292 d[2] =
F(s[2] | s[3] << 8 | s[4] << 16, 6);
293 d[3] =
F(s[4] | s[5] << 8, 1);
294 d[4] =
F(s[5] | s[6] << 8, 4);
295 d[5] =
F(s[6] | s[7] << 8 | s[8] << 16, 7);
296 d[6] =
F(s[8] | s[9] << 8, 2);
297 d[7] =
F(s[9] | s[10] << 8, 5);
300 d[8] =
F(s[11] | s[12] << 8, 0);
301 d[9] =
F(s[12] | s[13] << 8, 3);
302 d[10] =
F(s[13] | s[14] << 8 | s[15] << 16, 6);
303 d[11] =
F(s[15] | s[16] << 8, 1);
304 d[12] =
F(s[16] | s[17] << 8, 4);
305 d[13] =
F(s[17] | s[18] << 8 | s[19] << 16, 7);
306 d[14] =
F(s[19] | s[20] << 8, 2);
307 d[15] =
F(s[20] | s[21] << 8, 5);
310 dev->failsafe_timer = 0;
312 PIOS_Crossfire_ResetBuffer(dev);
318 PIOS_Crossfire_ResetBuffer(dev);
322 static void PIOS_Crossfire_Supervisor(uintptr_t context)
324 struct pios_crossfire_dev *dev = (
struct pios_crossfire_dev *)context;
332 if (++dev->rx_timer > 1)
333 PIOS_Crossfire_ResetBuffer(dev);
336 if (++dev->failsafe_timer > 156)
342 struct pios_crossfire_dev *dev = (
struct pios_crossfire_dev*)crsf_id;
346 if(!PIOS_Crossfire_Validate(dev))
351 if(!dev->telem_com_id || !buf)
372 struct pios_crossfire_dev *dev = (
struct pios_crossfire_dev*)crsf_id;
374 if(!PIOS_Crossfire_Validate(dev))
378 return dev->failsafe_timer > 156;
381 #endif // PIOS_INCLUDE_CROSSFIRE
int PIOS_Crossfire_SendTelemetry(uintptr_t crsf_id, uint8_t *buf, uint8_t bytes)
uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
Subtract raw time from now and convert to us.
int32_t(* read)(uintptr_t id, uint8_t channel)
#define CRSF_FRAME_RCCHANNELS
COM layer functions header.
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
void * PIOS_malloc_no_dma(size_t size)
#define CRSF_MAX_FRAMELEN
void PIOS_RCVR_ActiveFromISR()
int PIOS_Crossfire_InitTelemetry(uintptr_t crsf_id)
#define CRSF_TIMING_MAXFRAME
uint8_t PIOS_CRC_updateCRC_TBS(uint8_t crc, const uint8_t *data, int32_t length)
#define CRSF_TIMING_FRAMEDISTANCE
PIOS_COM_SendBuffer(shub_global->frsky_port, shub_global->serial_buf, msg_length)
#define CRSF_PAYLOAD_RCCHANNELS
int PIOS_Crossfire_Init(uintptr_t *crsf_id, const struct pios_com_driver *driver, uintptr_t uart_id)
Initialises the TBS Crossfire Rx driver with a serial port.
const struct pios_rcvr_driver pios_crossfire_rcvr_driver
int32_t PIOS_COM_Init(uintptr_t *com_id, const struct pios_com_driver *driver, uintptr_t lower_id, uint16_t rx_buffer_len, uint16_t tx_buffer_len)
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
bool PIOS_Crossfire_IsFailsafed()
#define PIOS_Assert(test)
#define PIOS_CROSSFIRE_CHANNELS
uint32_t PIOS_DELAY_GetRaw()
Get the raw delay timer, useful for timing.