dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_omnip.c
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  */
27 
28 /* Project Includes */
29 #include "pios.h"
30 #include "pios_omnip.h"
31 #include "pios_sensors.h"
32 
33 #if defined(PIOS_INCLUDE_OMNIP)
34 
35 #define PIOS_OMNIP_DEV_MAGIC 0x506e6d4f /* 'OmnP' */
36 
37 /* TODO: Consider a supervisor that marks statuses invalid if
38  * stuff has not been received for some time. (XXX, SAFETY)
39  */
40 #define RX_BUF_LEN 30
41 struct omnip_dev_s {
42  uint32_t magic;
43 
44  char line_buffer[RX_BUF_LEN];
45  int line_pos;
46 
47  int num_received;
48  int num_invalid;
49 
50  struct pios_queue *queue;
51 
52  struct pios_sensor_rangefinder_data rf_data;
53 };
54 
55 static void PIOS_OMNIP_ProcessMessage(omnip_dev_t dev)
56 {
57  char *endptr;
58 
59  dev->rf_data.velocity = strtof(dev->line_buffer, &endptr);
60 
61  if (endptr == dev->line_buffer) {
62  goto fail;
63  }
64 
65  dev->rf_data.velocity_status = true;
66  dev->rf_data.range_status = false;
67 
68  if (*endptr == ',') {
69  /* Neat! Expect a range too */
70 
71  endptr++;
72 
73  char *begin = endptr;
74 
75  dev->rf_data.range = strtof(begin, &endptr);
76 
77  if (endptr == begin) {
78  goto fail;
79  }
80 
81  dev->rf_data.range_status = true;
82  }
83 
84  dev->line_pos = 0;
85  dev->num_received++;
86 
87 #if 0
88  printf("Passing on ranging data; vel=[%0.3f]%s range=[%0.3f]%s\n",
89  dev->rf_data.velocity,
90  dev->rf_data.velocity_status ? "" : "(INVALID)",
91  dev->rf_data.range,
92  dev->rf_data.range_status ? "" : "(INVALID)");
93 #endif
94 
95  /* Only process/send-on after the first couple of valid messages,
96  * in case there is stuff in the buffer or our configuration messages
97  * had not taken effect yet.
98  */
99  if (dev->num_received > 2) {
100  PIOS_Queue_Send(dev->queue, &dev->rf_data, 0);
101  }
102 
103  return;
104 
105 fail:
106  dev->line_pos = 0;
107  dev->num_invalid++;
108 
109  //printf("failed cnt=%d-- %s\n", dev->num_invalid, dev->line_buffer);
110 }
111 
112 static void PIOS_OMNIP_UpdateState(omnip_dev_t dev, uint8_t c)
113 {
114  if (c == '\r') {
115  /* Completion of message. */
116 
117  if ((dev->line_pos > 0) && (dev->line_pos < RX_BUF_LEN)) {
118  dev->line_buffer[dev->line_pos] = 0;
119 
120  PIOS_OMNIP_ProcessMessage(dev);
121  } else {
122  dev->num_invalid++;
123 
124  dev->line_pos = 0;
125  }
126  } else if (c == '\n') {
127  /* Ignore \n at the beginning because of \r\n line separation.
128  * Otherwise, mark that we are not interested in this invalid
129  * line.
130  */
131 
132  if (dev->line_pos != 0) {
133  dev->line_pos = RX_BUF_LEN;
134  }
135  } else {
136  if (dev->line_pos < RX_BUF_LEN) {
137  dev->line_buffer[dev->line_pos] = (char) c;
138  dev->line_pos++;
139  }
140  }
141 }
142 
143 /* Comm byte received callback */
144 static uint16_t PIOS_OMNIP_RxInCallback(uintptr_t context,
145  uint8_t *buf,
146  uint16_t buf_len,
147  uint16_t *headroom,
148  bool *need_yield)
149 {
150  omnip_dev_t dev = (omnip_dev_t) context;
151 
152  PIOS_Assert(dev->magic == PIOS_OMNIP_DEV_MAGIC);
153 
154  /* process byte(s) and clear receive timer */
155  for (uint8_t i = 0; i < buf_len; i++) {
156  PIOS_OMNIP_UpdateState(dev, buf[i]);
157  }
158 
159  /* Always signal that we can accept whatever bytes they have to give */
160  if (headroom)
161  *headroom = 100;
162 
163  /* We never need a yield */
164  *need_yield = false;
165 
166  /* Always indicate that all bytes were consumed */
167  return buf_len;
168 }
169 
170 /* Initialise OmniPreSense interface */
171 int32_t PIOS_OMNIP_Init(omnip_dev_t *dev,
172  const struct pios_com_driver *driver,
173  uintptr_t lower_id)
174 {
175  *dev = PIOS_malloc_no_dma(sizeof(**dev));
176 
177  if (!*dev) {
178  return -1;
179  }
180 
181  **dev = (struct omnip_dev_s) {
182  .magic = PIOS_OMNIP_DEV_MAGIC,
183  };
184 
185  (*dev)->queue = PIOS_Queue_Create(2,
186  sizeof(struct pios_sensor_rangefinder_data));
187 
188  if (!(*dev)->queue) {
189  return -2;
190  }
191 
193 
194  /* XXX send a couple of simple initialization messages to set format */
195 
196  /* Set comm driver callback */
197  (driver->bind_rx_cb)(lower_id, PIOS_OMNIP_RxInCallback, (uintptr_t) *dev);
198 
199  return 0;
200 }
201 
202 #endif /* PIOS_INCLUDE_OMNIP */
203 
struct pios_queue * PIOS_Queue_Create(size_t queue_length, size_t item_size)
Definition: pios_queue.c:47
Main PiOS header to include all the compiled in PiOS options.
bool PIOS_Queue_Send(struct pios_queue *queuep, const void *itemp, uint32_t timeout_ms)
Definition: pios_queue.c:141
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
Pios sensor structure for generic rangefinder data.
Definition: pios_sensors.h:70
int32_t PIOS_SENSORS_Register(enum pios_sensor_type type, struct pios_queue *queue)
Register a queue-based sensor with the PIOS_SENSORS interface.
Definition: pios_sensors.c:82
int32_t PIOS_OMNIP_Init(omnip_dev_t *dev, const struct pios_com_driver *driver, uintptr_t lower_id)
Allocate and initialise OMNIP device.
uint8_t i
Definition: msp_messages.h:97
uint32_t magic
struct omnip_dev_s * omnip_dev_t
Definition: pios_omnip.h:33
int printf(const char *format,...)
static struct pios_queue * queue
Definition: actuator.c:82
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
Definition: pios_com.h:47
Generic interface for sensors.
#define PIOS_Assert(test)
Definition: pios_debug.h:52