dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_ibus.c
Go to the documentation of this file.
1 
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, see <http://www.gnu.org/licenses/>
24  *
25  * Additional note on redistribution: The copyright and license notices above
26  * must be maintained in each individual source file that is a derivative work
27  * of this source file; otherwise redistribution is prohibited.
28  */
29 
30 #include "pios_ibus.h"
31 
32 #ifdef PIOS_INCLUDE_IBUS
33 
34 // private
35 #define PIOS_IBUS_CHANNELS 10
36 // 1 sync byte, 1 unknown byte, 10x channels (uint16_t), 8 unknown bytes, 2 crc bytes
37 #define PIOS_IBUS_BUFLEN (1 + 1 + PIOS_IBUS_CHANNELS * 2 + 8 + 2)
38 #define PIOS_IBUS_SYNCBYTE 0x20
39 #define PIOS_IBUS_MAGIC 0x84fd9a39
40 
44 struct pios_ibus_dev {
45  uint32_t magic;
46  int buf_pos;
47  int rx_timer;
48  int failsafe_timer;
49  uint16_t checksum;
50  uint16_t channel_data[PIOS_IBUS_CHANNELS];
51  uint8_t rx_buf[PIOS_IBUS_BUFLEN];
52 };
53 
58 static struct pios_ibus_dev *PIOS_IBus_Alloc(void);
64 static bool PIOS_IBus_Validate(const struct pios_ibus_dev *dev);
71 static int32_t PIOS_IBus_Read(uintptr_t id, uint8_t channel);
77 static void PIOS_IBus_SetAllChannels(struct pios_ibus_dev *dev, uint16_t value);
87 static uint16_t PIOS_IBus_Receive(uintptr_t context, uint8_t *buf, uint16_t buf_len,
88  uint16_t *headroom, bool *task_woken);
93 static void PIOS_IBus_ResetBuffer(struct pios_ibus_dev *dev);
98 static void PIOS_IBus_UnpackFrame(struct pios_ibus_dev *dev);
103 static void PIOS_IBus_Supervisor(uintptr_t context);
104 
105 // public
107  .read = PIOS_IBus_Read,
108 };
109 
110 
111 static struct pios_ibus_dev *PIOS_IBus_Alloc(void)
112 {
113  struct pios_ibus_dev *dev = PIOS_malloc_no_dma(sizeof(struct pios_ibus_dev));
114  if (!dev)
115  return NULL;
116 
117  memset(dev, 0, sizeof(*dev));
118  dev->magic = PIOS_IBUS_MAGIC;
119 
120  return dev;
121 }
122 
123 static bool PIOS_IBus_Validate(const struct pios_ibus_dev *dev)
124 {
125  return dev && dev->magic == PIOS_IBUS_MAGIC;
126 }
127 
128 int PIOS_IBus_Init(uintptr_t *ibus_id, const struct pios_com_driver *driver,
129  uintptr_t uart_id)
130 {
131  struct pios_ibus_dev *dev = PIOS_IBus_Alloc();
132 
133  if (!dev)
134  return -1;
135 
136  *ibus_id = (uintptr_t)dev;
137 
138  PIOS_IBus_SetAllChannels(dev, PIOS_RCVR_INVALID);
139 
140  if (!PIOS_RTC_RegisterTickCallback(PIOS_IBus_Supervisor, *ibus_id))
141  PIOS_Assert(0);
142 
143  (driver->bind_rx_cb)(uart_id, PIOS_IBus_Receive, *ibus_id);
144 
145  return 0;
146 }
147 
148 static int32_t PIOS_IBus_Read(uintptr_t context, uint8_t channel)
149 {
150  if (channel > PIOS_IBUS_CHANNELS)
151  return PIOS_RCVR_INVALID;
152 
153  struct pios_ibus_dev *dev = (struct pios_ibus_dev *)context;
154  if (!PIOS_IBus_Validate(dev))
155  return PIOS_RCVR_NODRIVER;
156 
157  return dev->channel_data[channel];
158 }
159 
160 static void PIOS_IBus_SetAllChannels(struct pios_ibus_dev *dev, uint16_t value)
161 {
162  for (int i = 0; i < PIOS_IBUS_CHANNELS; i++)
163  dev->channel_data[i] = value;
164 }
165 
166 static uint16_t PIOS_IBus_Receive(uintptr_t context, uint8_t *buf, uint16_t buf_len,
167  uint16_t *headroom, bool *task_woken)
168 {
169  struct pios_ibus_dev *dev = (struct pios_ibus_dev *)context;
170  if (!PIOS_IBus_Validate(dev))
171  goto out_fail;
172 
173  for (int i = 0; i < buf_len; i++) {
174  if (dev->buf_pos == 0 && buf[i] != PIOS_IBUS_SYNCBYTE)
175  continue;
176 
177  dev->rx_buf[dev->buf_pos++] = buf[i];
178  if (dev->buf_pos <= PIOS_IBUS_BUFLEN - 2)
179  dev->checksum -= buf[i];
180  else if (dev->buf_pos == PIOS_IBUS_BUFLEN)
181  PIOS_IBus_UnpackFrame(dev);
182  }
183 
184  dev->rx_timer = 0;
185 
186  if (headroom) {
187  *headroom = PIOS_IBUS_BUFLEN - dev->buf_pos;
188  }
189 
190  if (task_woken) {
191  *task_woken = false;
192  }
193 
194  return buf_len;
195 
196 out_fail:
197  if (headroom) {
198  *headroom = 0;
199  }
200 
201  if (task_woken) {
202  *task_woken = false;
203  }
204 
205  return 0;
206 }
207 
208 static void PIOS_IBus_ResetBuffer(struct pios_ibus_dev *dev)
209 {
210  dev->checksum = 0xffff;
211  dev->buf_pos = 0;
212 }
213 
214 static void PIOS_IBus_UnpackFrame(struct pios_ibus_dev *dev)
215 {
216  uint16_t rxsum = dev->rx_buf[PIOS_IBUS_BUFLEN - 1] << 8 |
217  dev->rx_buf[PIOS_IBUS_BUFLEN - 2];
218  if (dev->checksum != rxsum)
219  goto out_fail;
220 
221  uint16_t *chan = (uint16_t *)&dev->rx_buf[2];
222  for (int i = 0; i < PIOS_IBUS_CHANNELS; i++)
223  dev->channel_data[i] = *chan++;
224 
225  dev->failsafe_timer = 0;
226 
227 out_fail:
228  PIOS_IBus_ResetBuffer(dev);
229 }
230 
231 static void PIOS_IBus_Supervisor(uintptr_t context)
232 {
233  struct pios_ibus_dev *dev = (struct pios_ibus_dev *)context;
234  PIOS_Assert(PIOS_IBus_Validate(dev));
235 
236  if (++dev->rx_timer > 3)
237  PIOS_IBus_ResetBuffer(dev);
238 
239  /* ~250ms to failsafe. */
240  if (++dev->failsafe_timer > 156)
241  PIOS_IBus_SetAllChannels(dev, PIOS_RCVR_TIMEOUT);
242 }
243 
244 #endif // PIOS_INCLUDE_IBUS
245 
int32_t(* read)(uintptr_t id, uint8_t channel)
Definition: pios_rcvr.h:35
int PIOS_IBus_Init(uintptr_t *ibus_id, const struct pios_com_driver *driver, uintptr_t uart_id)
Initialises the IBus Rx driver with a serial port.
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
Definition: pios_delay.c:185
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
const struct pios_rcvr_driver pios_ibus_rcvr_driver
uint8_t i
Definition: msp_messages.h:97
uint16_t value
Definition: storm32bgc.c:155
uint32_t magic
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
Definition: pios_com.h:47
#define PIOS_Assert(test)
Definition: pios_debug.h:52