File syn_sbus.c¶
File List > proto > syn_sbus.c
Go to the documentation of this file
#include "syntropic/proto/syn_sbus.h"
#include <string.h>
SYN_Status syn_sbus_init(SYN_SBUS_Parser *parser)
{
if (!parser) {
return SYN_INVALID_PARAM;
}
memset(parser, 0, sizeof(*parser));
return SYN_OK;
}
SYN_Status syn_sbus_decode_buffer(const uint8_t buf[SYN_SBUS_FRAME_SIZE], SYN_SBUS_Frame *frame)
{
if (!buf || !frame) {
return SYN_INVALID_PARAM;
}
if (buf[0] != SYN_SBUS_HEADER) {
return SYN_ERROR;
}
/* Unpack 16 11-bit channels from bytes 1..22 */
frame->channels[0] = (uint16_t)(((buf[1]) | (buf[2] << 8)) & 0x07FFU);
frame->channels[1] = (uint16_t)(((buf[2] >> 3) | (buf[3] << 5)) & 0x07FFU);
frame->channels[2] = (uint16_t)(((buf[3] >> 6) | (buf[4] << 2) | (buf[5] << 10)) & 0x07FFU);
frame->channels[3] = (uint16_t)(((buf[5] >> 1) | (buf[6] << 7)) & 0x07FFU);
frame->channels[4] = (uint16_t)(((buf[6] >> 4) | (buf[7] << 4)) & 0x07FFU);
frame->channels[5] = (uint16_t)(((buf[7] >> 7) | (buf[8] << 1) | (buf[9] << 9)) & 0x07FFU);
frame->channels[6] = (uint16_t)(((buf[9] >> 2) | (buf[10] << 6)) & 0x07FFU);
frame->channels[7] = (uint16_t)(((buf[10] >> 5) | (buf[11] << 3)) & 0x07FFU);
frame->channels[8] = (uint16_t)(((buf[12]) | (buf[13] << 8)) & 0x07FFU);
frame->channels[9] = (uint16_t)(((buf[13] >> 3) | (buf[14] << 5)) & 0x07FFU);
frame->channels[10] = (uint16_t)(((buf[14] >> 6) | (buf[15] << 2) | (buf[16] << 10)) & 0x07FFU);
frame->channels[11] = (uint16_t)(((buf[16] >> 1) | (buf[17] << 7)) & 0x07FFU);
frame->channels[12] = (uint16_t)(((buf[17] >> 4) | (buf[18] << 4)) & 0x07FFU);
frame->channels[13] = (uint16_t)(((buf[18] >> 7) | (buf[19] << 1) | (buf[20] << 9)) & 0x07FFU);
frame->channels[14] = (uint16_t)(((buf[20] >> 2) | (buf[21] << 6)) & 0x07FFU);
frame->channels[15] = (uint16_t)(((buf[21] >> 5) | (buf[22] << 3)) & 0x07FFU);
/* Flags in byte 23 */
uint8_t flags = buf[23];
frame->ch17 = (flags & 0x01U) != 0;
frame->ch18 = (flags & 0x02U) != 0;
frame->frame_loss = (flags & 0x04U) != 0;
frame->failsafe = (flags & 0x08U) != 0;
return SYN_OK;
}
SYN_Status syn_sbus_parse_byte(SYN_SBUS_Parser *parser, uint8_t byte, SYN_SBUS_Frame *frame)
{
if (!parser) {
return SYN_INVALID_PARAM;
}
/* Start of new frame */
if (parser->idx == 0) {
if (byte != SYN_SBUS_HEADER) {
return SYN_ERROR;
}
}
parser->buf[parser->idx++] = byte;
if (parser->idx >= SYN_SBUS_FRAME_SIZE) {
parser->idx = 0;
SYN_Status status = syn_sbus_decode_buffer(parser->buf, &parser->last_frame);
if (status == SYN_OK) {
parser->frames_received++;
if (parser->last_frame.frame_loss) {
parser->frame_loss_count++;
}
if (parser->last_frame.failsafe) {
parser->failsafe_count++;
}
if (frame) {
*frame = parser->last_frame;
}
return SYN_OK;
}
return status;
}
return SYN_BUSY;
}
uint16_t syn_sbus_raw_to_us(uint16_t raw_val)
{
if (raw_val < 172U) {
return 1000U;
}
if (raw_val > 1811U) {
return 2000U;
}
/*
* Linear interpolation:
* raw range: [172, 1811] -> span = 1639
* us range: [1000, 2000] -> span = 1000
* us = 1000 + ((raw_val - 172) * 1000) / 1639
*/
uint32_t val = (uint32_t)(raw_val - 172U);
uint32_t us = 1000U + ((val * 1000U) / 1639U);
return (uint16_t)us;
}