32 #ifdef PIOS_INCLUDE_IBUS
35 #define PIOS_IBUS_CHANNELS 10
37 #define PIOS_IBUS_BUFLEN (1 + 1 + PIOS_IBUS_CHANNELS * 2 + 8 + 2)
38 #define PIOS_IBUS_SYNCBYTE 0x20
39 #define PIOS_IBUS_MAGIC 0x84fd9a39
44 struct pios_ibus_dev {
50 uint16_t channel_data[PIOS_IBUS_CHANNELS];
51 uint8_t rx_buf[PIOS_IBUS_BUFLEN];
58 static struct pios_ibus_dev *PIOS_IBus_Alloc(
void);
64 static bool PIOS_IBus_Validate(
const struct pios_ibus_dev *dev);
71 static int32_t PIOS_IBus_Read(uintptr_t
id, uint8_t channel);
77 static void PIOS_IBus_SetAllChannels(
struct pios_ibus_dev *dev, uint16_t
value);
87 static uint16_t PIOS_IBus_Receive(uintptr_t context, uint8_t *buf, uint16_t buf_len,
88 uint16_t *headroom,
bool *task_woken);
93 static void PIOS_IBus_ResetBuffer(
struct pios_ibus_dev *dev);
98 static void PIOS_IBus_UnpackFrame(
struct pios_ibus_dev *dev);
103 static void PIOS_IBus_Supervisor(uintptr_t context);
107 .
read = PIOS_IBus_Read,
111 static struct pios_ibus_dev *PIOS_IBus_Alloc(
void)
117 memset(dev, 0,
sizeof(*dev));
118 dev->magic = PIOS_IBUS_MAGIC;
123 static bool PIOS_IBus_Validate(
const struct pios_ibus_dev *dev)
125 return dev && dev->magic == PIOS_IBUS_MAGIC;
131 struct pios_ibus_dev *dev = PIOS_IBus_Alloc();
136 *ibus_id = (uintptr_t)dev;
143 (driver->
bind_rx_cb)(uart_id, PIOS_IBus_Receive, *ibus_id);
148 static int32_t PIOS_IBus_Read(uintptr_t context, uint8_t channel)
150 if (channel > PIOS_IBUS_CHANNELS)
153 struct pios_ibus_dev *dev = (
struct pios_ibus_dev *)context;
154 if (!PIOS_IBus_Validate(dev))
157 return dev->channel_data[channel];
160 static void PIOS_IBus_SetAllChannels(
struct pios_ibus_dev *dev, uint16_t
value)
162 for (
int i = 0;
i < PIOS_IBUS_CHANNELS;
i++)
163 dev->channel_data[
i] = value;
166 static uint16_t PIOS_IBus_Receive(uintptr_t context, uint8_t *buf, uint16_t buf_len,
167 uint16_t *headroom,
bool *task_woken)
169 struct pios_ibus_dev *dev = (
struct pios_ibus_dev *)context;
170 if (!PIOS_IBus_Validate(dev))
173 for (
int i = 0;
i < buf_len;
i++) {
174 if (dev->buf_pos == 0 && buf[
i] != PIOS_IBUS_SYNCBYTE)
177 dev->rx_buf[dev->buf_pos++] = buf[
i];
178 if (dev->buf_pos <= PIOS_IBUS_BUFLEN - 2)
179 dev->checksum -= buf[
i];
180 else if (dev->buf_pos == PIOS_IBUS_BUFLEN)
181 PIOS_IBus_UnpackFrame(dev);
187 *headroom = PIOS_IBUS_BUFLEN - dev->buf_pos;
208 static void PIOS_IBus_ResetBuffer(
struct pios_ibus_dev *dev)
210 dev->checksum = 0xffff;
214 static void PIOS_IBus_UnpackFrame(
struct pios_ibus_dev *dev)
216 uint16_t rxsum = dev->rx_buf[PIOS_IBUS_BUFLEN - 1] << 8 |
217 dev->rx_buf[PIOS_IBUS_BUFLEN - 2];
218 if (dev->checksum != rxsum)
221 uint16_t *chan = (uint16_t *)&dev->rx_buf[2];
222 for (
int i = 0;
i < PIOS_IBUS_CHANNELS;
i++)
223 dev->channel_data[
i] = *chan++;
225 dev->failsafe_timer = 0;
228 PIOS_IBus_ResetBuffer(dev);
231 static void PIOS_IBus_Supervisor(uintptr_t context)
233 struct pios_ibus_dev *dev = (
struct pios_ibus_dev *)context;
236 if (++dev->rx_timer > 3)
237 PIOS_IBus_ResetBuffer(dev);
240 if (++dev->failsafe_timer > 156)
244 #endif // PIOS_INCLUDE_IBUS
int32_t(* read)(uintptr_t id, uint8_t channel)
int PIOS_IBus_Init(uintptr_t *ibus_id, const struct pios_com_driver *driver, uintptr_t uart_id)
Initialises the IBus Rx driver with a serial port.
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
void * PIOS_malloc_no_dma(size_t size)
const struct pios_rcvr_driver pios_ibus_rcvr_driver
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
#define PIOS_Assert(test)