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.