28 #if defined(PIOS_INCLUDE_SRXL)
30 #if !defined(PIOS_INCLUDE_RTC)
31 #error PIOS_INCLUDE_RTC must be used to use SRXL
39 enum pios_srxl_magic {
40 PIOS_SRXL_MAGIC = 0xda8e23be
44 PIOS_SRXL_SYNC_MULTIPLEX12 = 0xA1,
45 PIOS_SRXL_SYNC_MULTIPLEX16 = 0xA2,
46 PIOS_SRXL_SYNC_WEATRONIC16 = 0xA6,
49 struct pios_srxl_frame_multiplex12 {
55 struct pios_srxl_frame_multiplex16 {
61 struct pios_srxl_frame_weatronic16 {
71 #define PIOS_SRXL_RXBUF_LEN (40)
73 struct pios_srxl_dev {
74 enum pios_srxl_magic
magic;
76 uint8_t rx_buffer[PIOS_SRXL_RXBUF_LEN];
77 uint8_t rx_buffer_pos;
79 uint32_t failsafe_timer;
89 static struct pios_srxl_dev *PIOS_SRXL_AllocDev(
void);
95 static bool PIOS_SRXL_ValidateDev(
struct pios_srxl_dev *dev);
101 static void PIOS_SRXL_UpdateCRC(
struct pios_srxl_dev *dev, uint8_t
value);
111 static uint16_t PIOS_SRXL_RxCallback(uintptr_t context, uint8_t *buf,
112 uint16_t buf_len, uint16_t *headroom,
bool *task_woken);
117 static void PIOS_SRXL_ParseFrame(
struct pios_srxl_dev *dev);
123 static void PIOS_SRXL_ResetChannels(
struct pios_srxl_dev *dev, uint16_t val);
129 static int32_t PIOS_SRXL_Read(uintptr_t
id, uint8_t channel);
134 void PIOS_SRXL_Supervisor(uintptr_t
id);
140 .
read = PIOS_SRXL_Read
148 if (!driver || !lower_id)
150 struct pios_srxl_dev *dev = PIOS_SRXL_AllocDev();
154 *srxl_id = (uintptr_t)dev;
156 (driver->
bind_rx_cb)(lower_id, PIOS_SRXL_RxCallback, *srxl_id);
165 static struct pios_srxl_dev *PIOS_SRXL_AllocDev(
void)
167 struct pios_srxl_dev *dev =
PIOS_malloc(
sizeof(*dev));
171 dev->magic = PIOS_SRXL_MAGIC;
176 static bool PIOS_SRXL_ValidateDev(
struct pios_srxl_dev *dev)
178 if (dev != NULL && dev->magic == PIOS_SRXL_MAGIC)
183 static void PIOS_SRXL_UpdateCRC(
struct pios_srxl_dev *dev, uint8_t
value)
185 if (!PIOS_SRXL_ValidateDev(dev))
189 dev->crc = dev->crc ^ (int16_t)value << 8;
190 for(i = 0; i < 8; i++)
192 if(dev->crc & 0x8000)
193 dev->crc = dev->crc << 1^0x1021;
195 dev->crc = dev->crc << 1;
199 static uint16_t PIOS_SRXL_RxCallback(uintptr_t context, uint8_t *buf,
200 uint16_t buf_len, uint16_t *headroom,
bool *task_woken)
202 struct pios_srxl_dev *dev = (
struct pios_srxl_dev *)context;
203 if (!PIOS_SRXL_ValidateDev(dev))
207 uint16_t consumed = 0;
209 for (
int i = 0; i < buf_len; i++) {
210 if (dev->rx_buffer_pos == 0) {
212 if (buf[i] == PIOS_SRXL_SYNC_MULTIPLEX12) {
213 dev->frame_length =
sizeof(
struct pios_srxl_frame_multiplex12);
214 }
else if (buf[i] == PIOS_SRXL_SYNC_MULTIPLEX16) {
215 dev->frame_length =
sizeof(
struct pios_srxl_frame_multiplex16);
216 }
else if (buf[i] == PIOS_SRXL_SYNC_WEATRONIC16) {
217 dev->frame_length =
sizeof(
struct pios_srxl_frame_weatronic16);
222 dev->rx_buffer[dev->rx_buffer_pos++] = buf[
i];
223 PIOS_SRXL_UpdateCRC(dev, buf[i]);
224 if (dev->rx_buffer_pos == dev->frame_length)
225 PIOS_SRXL_ParseFrame(dev);
230 *headroom = PIOS_SRXL_RXBUF_LEN - dev->rx_buffer_pos;
236 static void PIOS_SRXL_ParseFrame(
struct pios_srxl_dev *dev)
238 if (!PIOS_SRXL_ValidateDev(dev))
242 bool failsafe =
false;
244 switch (dev->rx_buffer[0]) {
245 case PIOS_SRXL_SYNC_MULTIPLEX16:
247 struct pios_srxl_frame_multiplex16 *frame =
248 (
struct pios_srxl_frame_multiplex16 *)dev->rx_buffer;
249 for (
int i = 0; i < 16; i++)
253 case PIOS_SRXL_SYNC_MULTIPLEX12:
255 struct pios_srxl_frame_multiplex12 *frame =
256 (
struct pios_srxl_frame_multiplex12 *)dev->rx_buffer;
257 for (
int i = 0; i < 12; i++)
261 case PIOS_SRXL_SYNC_WEATRONIC16:
263 struct pios_srxl_frame_weatronic16 *frame =
264 (
struct pios_srxl_frame_weatronic16 *)dev->rx_buffer;
265 for (
int i = 0; i < 16; i++) {
266 int16_t value = 2000 +
BE16_TO_CPU(frame->chan[i]);
267 if (value < 0 || value > 4000)
270 dev->channels[
i] = (uint16_t)value;
272 failsafe = (frame->status & 0x10) > 0;
280 dev->failsafe_timer = 0;
285 dev->rx_buffer_pos = 0;
288 static int32_t PIOS_SRXL_Read(uintptr_t
id, uint8_t channel)
290 struct pios_srxl_dev *dev = (
struct pios_srxl_dev *)
id;
291 if (!PIOS_SRXL_ValidateDev(dev))
293 return dev->channels[channel];
296 static void PIOS_SRXL_ResetChannels(
struct pios_srxl_dev *dev, uint16_t val)
298 if (!PIOS_SRXL_ValidateDev(dev))
301 for (
int i = 0; i <
NELEMENTS(dev->channels); i++)
302 dev->channels[i] = val;
305 void PIOS_SRXL_Supervisor(uintptr_t
id)
307 struct pios_srxl_dev *dev = (
struct pios_srxl_dev *)
id;
308 if (!PIOS_SRXL_ValidateDev(dev))
317 if (++dev->rx_timer >= 5)
318 dev->rx_buffer_pos = 0;
319 if (++dev->failsafe_timer >= 158)
323 DONT_BUILD_IF(
sizeof(
struct pios_srxl_frame_multiplex12) > PIOS_SRXL_RXBUF_LEN, SRXLBufferSize);
324 DONT_BUILD_IF(
sizeof(
struct pios_srxl_frame_multiplex16) > PIOS_SRXL_RXBUF_LEN, SRXLBufferSize);
325 DONT_BUILD_IF(
sizeof(
struct pios_srxl_frame_weatronic16) > PIOS_SRXL_RXBUF_LEN, SRXLBufferSize);
int32_t(* read)(uintptr_t id, uint8_t channel)
Main PiOS header to include all the compiled in PiOS options.
#define PIOS_DEBUG_Assert(test)
void * PIOS_malloc(size_t size)
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
int32_t PIOS_SRXL_Init(uintptr_t *serial_id, const struct pios_com_driver *driver, uintptr_t lower_id)
Initialize a new SRXL device.
void PIOS_RCVR_ActiveFromISR()
#define PIOS_SRXL_MAX_CHANNELS
#define DONT_BUILD_IF(COND, MSG)
Includes PiOS and core architecture components.
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
const struct pios_rcvr_driver pios_srxl_rcvr_driver