28 #if defined(PIOS_INCLUDE_HSUM)
30 #if !defined(PIOS_INCLUDE_RTC)
31 #error PIOS_INCLUDE_RTC must be used to use HSUM
78 #define HSUM_HEADER_LENGTH 3
79 #define HSUM_CRC_LENGTH 2
80 #define HSUM_MAX_CHANNELS_PER_FRAME 32
81 #define HSUM_OVERHEAD_LENGTH (HSUM_HEADER_LENGTH+HSUM_CRC_LENGTH)
82 #define HSUM_MAX_FRAME_LENGTH (HSUM_MAX_CHANNELS_PER_FRAME*2+HSUM_OVERHEAD_LENGTH)
84 #define HSUM_GRAUPNER_ID 0xA8
85 #define HSUM_STATUS_LIVING_SUMH 0x00
86 #define HSUM_STATUS_LIVING_SUMD 0x01
87 #define HSUM_STATUS_FAILSAFE 0x81
90 static int32_t PIOS_HSUM_Get(uintptr_t rcvr_id, uint8_t channel);
91 static uint16_t PIOS_HSUM_RxInCallback(uintptr_t context,
96 static void PIOS_HSUM_Supervisor(uintptr_t hsum_id);
100 .
read = PIOS_HSUM_Get,
103 enum pios_hsum_dev_magic {
104 PIOS_HSUM_DEV_MAGIC = 0x4853554D,
107 struct pios_hsum_state {
109 uint8_t received_data[HSUM_MAX_FRAME_LENGTH];
110 uint8_t receive_timer;
111 uint8_t failsafe_timer;
113 uint8_t tx_connected;
115 uint8_t frame_length;
118 struct pios_hsum_dev {
119 enum pios_hsum_dev_magic
magic;
120 const struct pios_hsum_cfg *
cfg;
122 struct pios_hsum_state
state;
126 static struct pios_hsum_dev *PIOS_HSUM_Alloc(
void)
128 struct pios_hsum_dev *hsum_dev;
130 hsum_dev = (
struct pios_hsum_dev *)
PIOS_malloc(
sizeof(*hsum_dev));
134 hsum_dev->magic = PIOS_HSUM_DEV_MAGIC;
139 static bool PIOS_HSUM_Validate(
struct pios_hsum_dev *hsum_dev)
141 return (hsum_dev->magic == PIOS_HSUM_DEV_MAGIC);
145 static void PIOS_HSUM_ResetChannels(
struct pios_hsum_dev *hsum_dev)
147 struct pios_hsum_state *
state = &(hsum_dev->state);
154 static void PIOS_HSUM_ResetState(
struct pios_hsum_dev *hsum_dev)
156 struct pios_hsum_state *state = &(hsum_dev->state);
157 state->receive_timer = 0;
158 state->failsafe_timer = 0;
159 state->frame_found = 0;
160 state->tx_connected = 0;
161 PIOS_HSUM_ResetChannels(hsum_dev);
169 static int PIOS_HSUM_UnrollChannels(
struct pios_hsum_dev *hsum_dev)
171 struct pios_hsum_state *state = &(hsum_dev->state);
174 uint8_t vendor = state->received_data[0];
175 uint8_t
status = state->received_data[1];
176 if (vendor != HSUM_GRAUPNER_ID)
181 case HSUM_STATUS_LIVING_SUMH:
182 case HSUM_STATUS_LIVING_SUMD:
183 case HSUM_STATUS_FAILSAFE:
188 uint8_t *s = &(state->received_data[0]);
189 int len = state->byte_count - 2;
190 for (
int n = 0; n < len; n++) {
191 crc ^= (uint16_t)s[n] << 8;
192 for (
int i = 0;
i < 8;
i++)
193 crc = (crc & 0x8000) ? (crc << 1) ^ 0x1021 : (crc << 1);
195 if (crc ^ (((uint16_t)s[len] << 8) | s[len + 1]))
202 uint8_t *s = &(state->received_data[0]);
203 int len = state->byte_count - 1;
204 for (
int n = 0; n < len; n++)
211 state->tx_connected |= (status != HSUM_STATUS_FAILSAFE);
219 if (!(state->tx_connected)) {
221 PIOS_HSUM_ResetChannels(hsum_dev);
226 uint8_t n_channels = state->received_data[2];
227 uint8_t *s = &(state->received_data[3]);
230 for (
int i = 0;
i < HSUM_MAX_CHANNELS_PER_FRAME;
i++) {
231 if (
i < n_channels) {
232 word = ((uint16_t)s[0] << 8) | s[1];
233 s +=
sizeof(uint16_t);
236 state->channel_data[
i] = word;
254 static void PIOS_HSUM_UpdateState(
struct pios_hsum_dev *hsum_dev, uint8_t byte)
256 struct pios_hsum_state *state = &(hsum_dev->state);
257 if (state->frame_found) {
259 if (state->byte_count < HSUM_MAX_FRAME_LENGTH) {
261 state->received_data[state->byte_count++] = byte;
262 if (state->byte_count == HSUM_HEADER_LENGTH) {
264 state->frame_length = HSUM_OVERHEAD_LENGTH + 2 * byte;
266 if (state->byte_count == state->frame_length) {
268 if (!PIOS_HSUM_UnrollChannels(hsum_dev))
270 state->failsafe_timer = 0;
272 state->frame_found = 0;
287 struct pios_hsum_dev *hsum_dev;
289 hsum_dev = (
struct pios_hsum_dev *)PIOS_HSUM_Alloc();
294 hsum_dev->proto = proto;
296 PIOS_HSUM_ResetState(hsum_dev);
298 *hsum_id = (uintptr_t)hsum_dev;
301 (driver->
bind_rx_cb)(lower_id, PIOS_HSUM_RxInCallback, *hsum_id);
311 static uint16_t PIOS_HSUM_RxInCallback(uintptr_t context,
317 struct pios_hsum_dev *hsum_dev = (
struct pios_hsum_dev *)context;
319 bool valid = PIOS_HSUM_Validate(hsum_dev);
323 for (uint8_t
i = 0;
i < buf_len;
i++) {
324 PIOS_HSUM_UpdateState(hsum_dev, buf[
i]);
325 hsum_dev->state.receive_timer = 0;
330 *headroom = HSUM_MAX_FRAME_LENGTH;
346 static int32_t PIOS_HSUM_Get(uintptr_t rcvr_id, uint8_t channel)
348 struct pios_hsum_dev *hsum_dev = (
struct pios_hsum_dev *)rcvr_id;
350 if (!PIOS_HSUM_Validate(hsum_dev))
358 return hsum_dev->state.channel_data[channel];
373 static void PIOS_HSUM_Supervisor(uintptr_t hsum_id)
375 struct pios_hsum_dev *hsum_dev = (
struct pios_hsum_dev *)hsum_id;
377 bool valid = PIOS_HSUM_Validate(hsum_dev);
380 struct pios_hsum_state *state = &(hsum_dev->state);
383 if (++state->receive_timer > 4) {
384 state->frame_found = 1;
385 state->byte_count = 0;
386 state->receive_timer = 0;
387 state->frame_length = HSUM_MAX_FRAME_LENGTH;
391 if (++state->failsafe_timer > 156) {
392 PIOS_HSUM_ResetChannels(hsum_dev);
393 state->failsafe_timer = 0;
394 state->tx_connected = 0;
const struct pios_rcvr_driver pios_hsum_rcvr_driver
int32_t(* read)(uintptr_t id, uint8_t channel)
#define PIOS_HSUM_NUM_INPUTS
#define PIOS_DEBUG_Assert(test)
void * PIOS_malloc(size_t size)
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
void PIOS_RCVR_ActiveFromISR()
static struct flyingpicmd_cfg_fa cfg
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
#define PIOS_Assert(test)
int32_t PIOS_HSUM_Init(uintptr_t *hsum_id, const struct pios_com_driver *driver, uintptr_t lower_id, enum pios_hsum_proto proto)