Files

90 lines
2.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file protocol.c
* @brief AliceRC communication protocol implementation
*/
#include <string.h>
#include "protocol.h"
void protocol_init(void)
{
/* Nothing to initialize for now */
}
void protocol_pack_sbus(const uint16_t *channels, uint8_t *sbus_data)
{
memset(sbus_data, 0, 22);
/* Pack 16 × 11-bit channels into 22 bytes, little-endian bitstream */
for (int i = 0; i < SBUS_CHANNEL_COUNT; i++) {
uint16_t ch = channels[i] & 0x07FF; /* Mask to 11 bits */
int byte_idx = (i * SBUS_CHANNEL_BITS) / 8;
int bit_off = (i * SBUS_CHANNEL_BITS) % 8;
sbus_data[byte_idx] |= (ch << bit_off) & 0xFF;
sbus_data[byte_idx + 1] |= (ch >> (8 - bit_off)) & 0xFF;
if (bit_off > 5) {
/* 11-bit crosses 3-byte boundary when bit_off >= 6 */
sbus_data[byte_idx + 2] |= (ch >> (16 - bit_off)) & 0xFF;
}
}
}
void protocol_unpack_sbus(const uint8_t *sbus_data, uint16_t *channels)
{
for (int i = 0; i < SBUS_CHANNEL_COUNT; i++) {
int byte_idx = (i * SBUS_CHANNEL_BITS) / 8;
int bit_off = (i * SBUS_CHANNEL_BITS) % 8;
uint16_t ch = sbus_data[byte_idx] >> bit_off;
ch |= (uint16_t)(sbus_data[byte_idx + 1]) << (8 - bit_off);
if (bit_off > 5) {
ch |= (uint16_t)(sbus_data[byte_idx + 2]) << (16 - bit_off);
}
channels[i] = ch & 0x07FF;
}
}
void protocol_build_tx_payload(rf_tx_payload_t *payload,
const uint16_t *adc_channels,
uint8_t model_id,
uint8_t seq)
{
uint16_t sbus_channels[SBUS_CHANNEL_COUNT];
/* Convert 8 ADC channels to SBUS range, center the rest */
for (int i = 0; i < 8; i++) {
sbus_channels[i] = protocol_map_to_sbus(adc_channels[i]);
}
for (int i = 8; i < SBUS_CHANNEL_COUNT; i++) {
sbus_channels[i] = SBUS_CENTER;
}
/* Build payload */
memset(payload, 0, sizeof(rf_tx_payload_t));
payload->frame_id = FRAME_ID_CHANNELS;
payload->seq = seq;
payload->model_id = model_id;
payload->flags = 0;
protocol_pack_sbus(sbus_channels, payload->sbus_data);
}
void protocol_parse_telemetry(const rf_rx_telemetry_t *telemetry,
uint16_t *battery_mv)
{
if (telemetry->frame_id == FRAME_ID_TELEMETRY) {
/* Battery voltage is big-endian */
*battery_mv = (telemetry->battery_mv >> 8) |
(telemetry->battery_mv << 8);
}
}
uint16_t protocol_map_to_sbus(uint16_t adc_value)
{
/* Map 12-bit ADC (0-4095) to SBUS range (200-1844) */
uint32_t result = SBUS_MIN + ((uint32_t)adc_value * (SBUS_MAX - SBUS_MIN) / 4095);
if (result > SBUS_MAX) result = SBUS_MAX;
return (uint16_t)result;
}