dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_sbus.c
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  */
30 
31 /* Project Includes */
32 #include "pios.h"
33 #include "pios_sbus_priv.h"
34 
35 #if defined(PIOS_INCLUDE_SBUS)
36 
37 /* Forward Declarations */
38 static int32_t PIOS_SBus_Get(uintptr_t rcvr_id, uint8_t channel);
39 static uint16_t PIOS_SBus_RxInCallback(uintptr_t context,
40  uint8_t *buf,
41  uint16_t buf_len,
42  uint16_t *headroom,
43  bool *need_yield);
44 static void PIOS_SBus_Supervisor(uintptr_t sbus_id);
45 
46 
47 /* Local Variables */
49  .read = PIOS_SBus_Get,
50 };
51 
52 enum pios_sbus_dev_magic {
53  PIOS_SBUS_DEV_MAGIC = 0x53427573,
54 };
55 
56 struct pios_sbus_state {
57  uint16_t channel_data[PIOS_SBUS_NUM_INPUTS];
58  uint8_t received_data[SBUS_FRAME_LENGTH - 2];
59  uint8_t receive_timer;
60  uint8_t failsafe_timer;
61  uint8_t byte_count;
62 };
63 
64 struct pios_sbus_dev {
65  enum pios_sbus_dev_magic magic;
66  struct pios_sbus_state state;
67 };
68 
69 /* Allocate S.Bus device descriptor */
70 static struct pios_sbus_dev *PIOS_SBus_Alloc(void)
71 {
72  struct pios_sbus_dev *sbus_dev;
73 
74  sbus_dev = (struct pios_sbus_dev *)PIOS_malloc(sizeof(*sbus_dev));
75  if (!sbus_dev) return(NULL);
76 
77  sbus_dev->magic = PIOS_SBUS_DEV_MAGIC;
78  return(sbus_dev);
79 }
80 
81 /* Validate S.Bus device descriptor */
82 static bool PIOS_SBus_Validate(struct pios_sbus_dev *sbus_dev)
83 {
84  return (sbus_dev->magic == PIOS_SBUS_DEV_MAGIC);
85 }
86 
87 /* Reset channels in case of lost signal or explicit failsafe receiver flag */
88 static void PIOS_SBus_ResetChannels(struct pios_sbus_state *state)
89 {
90  for (int i = 0; i < PIOS_SBUS_NUM_INPUTS; i++) {
91  state->channel_data[i] = PIOS_RCVR_TIMEOUT;
92  }
93 }
94 
95 /* Reset S.Bus receiver state */
96 static void PIOS_SBus_ResetState(struct pios_sbus_state *state)
97 {
98  state->failsafe_timer = 0;
99  state->receive_timer = 0;
100  state->byte_count = 0;
101  PIOS_SBus_ResetChannels(state);
102 }
103 
104 /* Initialise S.Bus receiver interface */
105 int32_t PIOS_SBus_Init(uintptr_t *sbus_id,
106  const struct pios_com_driver *driver,
107  uintptr_t lower_id)
108 {
109  PIOS_DEBUG_Assert(sbus_id);
111  PIOS_DEBUG_Assert(driver);
112 
113  struct pios_sbus_dev *sbus_dev;
114 
115  sbus_dev = (struct pios_sbus_dev *)PIOS_SBus_Alloc();
116  if (!sbus_dev) return -1;
117 
118  PIOS_SBus_ResetState(&(sbus_dev->state));
119 
120  *sbus_id = (uintptr_t)sbus_dev;
121 
122  (driver->bind_rx_cb)(lower_id, PIOS_SBus_RxInCallback, *sbus_id);
123 
124  if (!PIOS_RTC_RegisterTickCallback(PIOS_SBus_Supervisor, *sbus_id)) {
126  }
127 
128  return 0;
129 }
130 
138 static int32_t PIOS_SBus_Get(uintptr_t rcvr_id, uint8_t channel)
139 {
140  struct pios_sbus_dev *sbus_dev = (struct pios_sbus_dev *)rcvr_id;
141 
142  if (!PIOS_SBus_Validate(sbus_dev))
143  return PIOS_RCVR_INVALID;
144 
145  /* return error if channel is not available */
146  if (channel >= PIOS_SBUS_NUM_INPUTS) {
147  return PIOS_RCVR_INVALID;
148  }
149 
150  return sbus_dev->state.channel_data[channel];
151 }
152 
158 static void PIOS_SBus_UnrollChannels(struct pios_sbus_state *state)
159 {
160  uint8_t *s = state->received_data;
161  uint16_t *d = state->channel_data;
162 
163 #define F(v,s) (((v) >> (s)) & 0x7ff)
164 
165  /* unroll channels 1-8 */
166  d[0] = F(s[0] | s[1] << 8, 0);
167  d[1] = F(s[1] | s[2] << 8, 3);
168  d[2] = F(s[2] | s[3] << 8 | s[4] << 16, 6);
169  d[3] = F(s[4] | s[5] << 8, 1);
170  d[4] = F(s[5] | s[6] << 8, 4);
171  d[5] = F(s[6] | s[7] << 8 | s[8] << 16, 7);
172  d[6] = F(s[8] | s[9] << 8, 2);
173  d[7] = F(s[9] | s[10] << 8, 5);
174 
175  /* unroll channels 9-16 */
176  d[8] = F(s[11] | s[12] << 8, 0);
177  d[9] = F(s[12] | s[13] << 8, 3);
178  d[10] = F(s[13] | s[14] << 8 | s[15] << 16, 6);
179  d[11] = F(s[15] | s[16] << 8, 1);
180  d[12] = F(s[16] | s[17] << 8, 4);
181  d[13] = F(s[17] | s[18] << 8 | s[19] << 16, 7);
182  d[14] = F(s[19] | s[20] << 8, 2);
183  d[15] = F(s[20] | s[21] << 8, 5);
184 
185  /* unroll discrete channels 17 and 18 */
186  d[16] = (s[22] & SBUS_FLAG_DC1) ? SBUS_VALUE_MAX : SBUS_VALUE_MIN;
187  d[17] = (s[22] & SBUS_FLAG_DC2) ? SBUS_VALUE_MAX : SBUS_VALUE_MIN;
188 }
189 
190 /* Update decoder state processing input byte from the S.Bus stream */
191 static void PIOS_SBus_UpdateState(struct pios_sbus_state *state, uint8_t b)
192 {
193  if (state->byte_count == 0) {
194  if (b == SBUS_SOF_BYTE) {
195  /* do not store the SOF byte */
196  state->byte_count++;
197  }
198  /* Otherwise discard this byte. */
199  return;
200  }
201 
202  /* do not store last frame byte as well */
203  if (state->byte_count < SBUS_FRAME_LENGTH - 1) {
204  /* store next byte */
205  state->received_data[state->byte_count - 1] = b;
206  state->byte_count++;
207  } else {
209  /* full frame received */
210  uint8_t flags = state->received_data[SBUS_FRAME_LENGTH - 3];
211  if (flags & SBUS_FLAG_FL) {
212  /* frame lost, do not update */
213  } else if (flags & SBUS_FLAG_FS) {
214  /* failsafe flag active */
215  PIOS_SBus_ResetChannels(state);
216  } else {
217  /* data looking good */
218  PIOS_SBus_UnrollChannels(state);
219  state->failsafe_timer = 0;
221  }
222  } else {
223  /* discard whole frame */
224  }
225 
226  /* prepare for the next frame */
227  state->byte_count = 0;
228  }
229 }
230 
231 /* Comm byte received callback */
232 static uint16_t PIOS_SBus_RxInCallback(uintptr_t context,
233  uint8_t *buf,
234  uint16_t buf_len,
235  uint16_t *headroom,
236  bool *need_yield)
237 {
238  struct pios_sbus_dev *sbus_dev = (struct pios_sbus_dev *)context;
239 
240  bool valid = PIOS_SBus_Validate(sbus_dev);
241  PIOS_Assert(valid);
242 
243  struct pios_sbus_state *state = &(sbus_dev->state);
244 
245  /* process byte(s) and clear receive timer */
246  for (uint8_t i = 0; i < buf_len; i++) {
247  PIOS_SBus_UpdateState(state, buf[i]);
248  }
249 
250  state->receive_timer = 0;
251 
252  /* Always signal that we can accept another frame */
253  if (headroom)
254  *headroom = SBUS_FRAME_LENGTH;
255 
256  /* We never need a yield */
257  *need_yield = false;
258 
259  /* Always indicate that all bytes were consumed */
260  return buf_len;
261 }
262 
274 static void PIOS_SBus_Supervisor(uintptr_t sbus_id)
275 {
276  struct pios_sbus_dev *sbus_dev = (struct pios_sbus_dev *)sbus_id;
277 
278  bool valid = PIOS_SBus_Validate(sbus_dev);
279  PIOS_Assert(valid);
280 
281  struct pios_sbus_state *state = &(sbus_dev->state);
282 
283  /* An appropriate gap of at least 3.2ms causes us to go back to
284  * expecting start of frame. */
285  if (++state->receive_timer > 2) {
286  state->byte_count = 0;
287  state->receive_timer = 0;
288  }
289 
290  /* Activate failsafe if no frames have arrived in ~250ms. */
291  if (++state->failsafe_timer > 156) {
292  PIOS_SBus_ResetChannels(state);
293  state->failsafe_timer = 0;
294  }
295 }
296 
297 #endif /* PIOS_INCLUDE_SBUS */
298 
float F[NUMX][NUMX]
Definition: insgps14state.c:63
int32_t(* read)(uintptr_t id, uint8_t channel)
Definition: pios_rcvr.h:35
Main PiOS header to include all the compiled in PiOS options.
int32_t PIOS_SBus_Init(uintptr_t *sbus_id, const struct pios_com_driver *driver, uintptr_t lower_id)
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
#define SBUS_R7008SB_EOF_COUNTER_MASK
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
const struct pios_rcvr_driver pios_sbus_rcvr_driver
#define SBUS_SOF_BYTE
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
Definition: pios_delay.c:185
uint16_t flags
Definition: uavtalk_priv.h:52
#define SBUS_FLAG_DC2
void PIOS_RCVR_ActiveFromISR()
#define PIOS_SBUS_NUM_INPUTS
Definition: pios_board.h:204
#define SBUS_VALUE_MIN
#define SBUS_FLAG_FS
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
#define SBUS_FLAG_DC1
#define SBUS_FLAG_FL
uint8_t i
Definition: msp_messages.h:97
uint8_t d
Definition: msp_messages.h:98
#define SBUS_VALUE_MAX
uint32_t magic
#define SBUS_R7008SB_EOF_BYTE
Futaba S.Bus Private structures.
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
Definition: pios_com.h:47
#define SBUS_FRAME_LENGTH
#define SBUS_EOF_BYTE
#define PIOS_Assert(test)
Definition: pios_debug.h:52
enum arena_state state