dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
radiocombridge.c
Go to the documentation of this file.
1 
18 /*
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful, but
25  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
26  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27  * for more details.
28  *
29  * You should have received a copy of the GNU General Public License along
30  * with this program; if not, see <http://www.gnu.org/licenses/>
31  *
32  * Additional note on redistribution: The copyright and license notices above
33  * must be maintained in each individual source file that is a derivative work
34  * of this source file; otherwise redistribution is prohibited.
35  */
36 
37 // ****************
38 
39 #include <openpilot.h>
40 #include <eventdispatcher.h>
41 #include <objectpersistence.h>
42 #include <radiocombridgestats.h>
43 #include "hwtaulink.h"
44 #include <uavtalk.h>
45 #include <uavtalk_priv.h>
46 #if defined(PIOS_INCLUDE_FLASH_EEPROM)
47 #include <pios_eeprom.h>
48 #endif
49 
50 // these objects are parsed locally for relaying to taranis
51 #include "flightbatterystate.h"
52 #include "flightstatus.h"
53 #include "positionactual.h"
54 #include "velocityactual.h"
55 #include "baroaltitude.h"
56 #include "modulesettings.h"
57 
58 #include "pios_thread.h"
59 #include "pios_queue.h"
60 
61 #include <pios_hal.h>
62 
63 #include <uavtalkreceiver.h>
64 
65 // ****************
66 // Private constants
67 
68 #define STACK_SIZE_BYTES 600
69 #define TASK_PRIORITY PIOS_THREAD_PRIO_LOW
70 #define MAX_RETRIES 2
71 #define MAX_PORT_DELAY 200
72 #define COMSTATS_INJECT 400
73 #define RETRY_TIMEOUT_MS 150
74 #define USB_ACTIVITY_TIMEOUT_MS 6000
75 
76 // ****************
77 // Private types
78 
79 typedef struct {
80  // The task handles.
81  struct pios_thread *telemetryRxTaskHandle;
82  struct pios_thread *radioRxTaskHandle;
83 
84  // The UAVTalk connection on the com side.
87 
88  volatile bool have_port;
90 
91 // ****************
92 // Private functions
93 
94 static void telemetryRxTask(void *parameters);
95 static void radioRxTask(void *parameters);
96 static int32_t UAVTalkSendHandler(void *ctx, uint8_t * buf, int32_t length);
97 static int32_t RadioSendHandler(void *ctx, uint8_t * buf, int32_t length);
98 
99 static void ProcessLocalStream(UAVTalkConnection inConnectionHandle,
100  UAVTalkConnection outConnectionHandle,
101  uint8_t rxbyte);
102 static void ProcessRadioStream(UAVTalkConnection inConnectionHandle,
103  UAVTalkConnection outConnectionHandle,
104  uint8_t rxbyte);
105 
106 // ****************
107 // Private variables
108 
110 
111 static void NewReceiverData(const UAVObjEvent *ev,
112  void *ctx, void *obj, int len)
113 {
114  (void) ctx; (void) obj; (void) len;
115 
116  /* Selected local objects get crammed over the telem link. */
117 
118  // Temporarily disabled, while work on airside radio continues XXX
119 // UAVTalkSendObject(data->telemUAVTalkCon, ev->obj, ev->instId,
120 // false);
121 }
122 
123 #if defined(PIOS_COM_TELEM_USB)
124 
130 static bool processUsbActivity(bool seen_active)
131 {
132  static volatile uint32_t usb_last_active;
133 
134  if (seen_active) {
135  usb_last_active = PIOS_Thread_Systime();
136 
137  return true;
138  }
139 
140  if (usb_last_active) {
141  if (!PIOS_Thread_Period_Elapsed(usb_last_active,
143  return true;
144  } else {
145  /* "Latch" expiration so it doesn't become true
146  * again.
147  */
148  usb_last_active = 0;
149  }
150  }
151 
152  return false;
153 }
154 #endif // PIOS_COM_TELEM_USB
155 
159 static uintptr_t getComPort()
160 {
161 #if defined(PIOS_COM_TELEM_USB)
163  /* Let's further qualify this. If there's anything spooled
164  * up for RX, bump the activity time.
165  */
166 
168 
169  if (processUsbActivity(rx_pending)) {
170  return PIOS_COM_TELEM_USB;
171  }
172 
174  return PIOS_COM_TELEM_USB;
175  }
176  }
177 #endif /* PIOS_COM_TELEM_USB */
178 
180  return PIOS_COM_TELEM_SER;
181 
182  return 0;
183 }
184 
190 static int32_t RadioComBridgeStart(void)
191 {
192  if (data) {
193  // Watchdog must be registered before starting tasks
194 #ifdef PIOS_INCLUDE_WDG
197 #endif
198 
199  // Start the primary tasks for receiving/sending UAVTalk
200  // packets from the GCS. The main telemetry subsystem
201  // gets the local ports first (and we trust it to
202  // configure them for us).
203  data->telemetryRxTaskHandle =
204  PIOS_Thread_Create(telemetryRxTask, "telemetryRxTask",
206 
207  data->radioRxTaskHandle =
208  PIOS_Thread_Create(radioRxTask, "radioRxTask",
210 
211  UAVTalkReceiverConnectCallback(NewReceiverData);
212 
213  return 0;
214  }
215 
216  return -1;
217 }
218 
224 static int32_t RadioComBridgeInitialize(void)
225 {
226  // allocate and initialize the static data storage only if module is enabled
227  data = PIOS_malloc(sizeof(RadioComBridgeData));
228  if (!data) {
229  return -1;
230  }
231  // Initialize the UAVObjects that we use
232  if (RadioComBridgeStatsInitialize() == -1) {
233  return -1;
234  }
235 
236  if ((FlightBatteryStateInitialize() == -1) ||
237  (FlightStatusInitialize() == -1) ||
238  (PositionActualInitialize() == -1) ||
239  (VelocityActualInitialize() == -1) ||
240  (BaroAltitudeInitialize() == -1)) {
241  return -1;
242  }
243 
244  // Initialise UAVTalk
246  NULL, NULL, NULL);
248  NULL, NULL, NULL);
249  if (data->telemUAVTalkCon == 0 || data->radioUAVTalkCon == 0) {
250  return -1;
251  }
252 
253  return 0;
254 }
255 
257 
262 {
263  UAVTalkStats telemetryUAVTalkStats;
264  UAVTalkStats radioUAVTalkStats;
265  RadioComBridgeStatsData radioComBridgeStats;
266 
267  // Get telemetry stats
268  UAVTalkGetStats(data->telemUAVTalkCon, &telemetryUAVTalkStats);
269 
270  // Get radio stats
271  UAVTalkGetStats(data->radioUAVTalkCon, &radioUAVTalkStats);
272 
273  // Get stats object data
274  RadioComBridgeStatsGet(&radioComBridgeStats);
275 
276  // Update stats object
277  radioComBridgeStats.TelemetryTxBytes +=
278  telemetryUAVTalkStats.txBytes;
279  radioComBridgeStats.TelemetryTxFailures +=
280  telemetryUAVTalkStats.txErrors;
281 
282  radioComBridgeStats.TelemetryRxBytes +=
283  telemetryUAVTalkStats.rxBytes;
284  radioComBridgeStats.TelemetryRxFailures +=
285  telemetryUAVTalkStats.rxErrors;
286  radioComBridgeStats.TelemetryRxCrcErrors +=
287  telemetryUAVTalkStats.rxCRC;
288 
289  radioComBridgeStats.RadioTxBytes += radioUAVTalkStats.txBytes;
290  radioComBridgeStats.RadioTxFailures += radioUAVTalkStats.txErrors;
291 
292  radioComBridgeStats.RadioRxBytes += radioUAVTalkStats.rxBytes;
293  radioComBridgeStats.RadioRxFailures += radioUAVTalkStats.rxErrors;
294  radioComBridgeStats.RadioRxCrcErrors += radioUAVTalkStats.rxCRC;
295 
296  // Update stats object data
297  RadioComBridgeStatsSet(&radioComBridgeStats);
298 }
299 
306  void *parameters)
307 {
308  uint32_t time_since_inject = PIOS_Thread_Systime();
309 
310  // Task loop
311  while (1) {
312 #ifdef PIOS_INCLUDE_WDG
314 #endif
315  if (PIOS_COM_RADIOBRIDGE &&
317  uint8_t serial_data[32];
318  uint16_t bytes_to_process =
320  serial_data,
321  sizeof(serial_data),
323  if (bytes_to_process > 0) {
324  // Pass the data through the UAVTalk parser.
325  for (uint8_t i = 0;
326  i < bytes_to_process; i++) {
328  data->telemUAVTalkCon,
329  serial_data[i]);
330  }
331  }
332 
333  /* periodically inject ComBridgeStats to downstream */
334  if (PIOS_Thread_Period_Elapsed(time_since_inject,
335  COMSTATS_INJECT)) {
336  time_since_inject = PIOS_Thread_Systime();
337 
339 
341  RadioComBridgeStatsHandle(),
342  0, false);
343  }
344  } else {
345  /* hand port to telemetry */
346  data->have_port = false;
348  telemetry_set_inhibit(false);
349  }
350  }
351 }
352 
359  void *parameters)
360 {
361  // Task loop
362  while (1) {
363  uint32_t inputPort = getComPort();
364 
365 #ifdef PIOS_INCLUDE_WDG
367 #endif
368 
370  (!data->have_port)) {
371 #ifndef PIPXTREME
373  continue;
374 #else
375  /* PIPXtreme telemetry never touches serial
376  * port for safety, so we can continue to
377  * use it happily.
378  */
379  inputPort = PIOS_COM_TELEM_SER;
380 #endif
381  }
382 
383  if (inputPort) {
384  uint8_t serial_data[32];
385  uint16_t bytes_to_process =
386  PIOS_COM_ReceiveBuffer(inputPort, serial_data,
387  sizeof(serial_data),
389 
390  if (bytes_to_process > 0) {
391  if (inputPort == PIOS_COM_TELEM_USB) {
392  processUsbActivity(true);
393  }
394 
395  for (uint8_t i = 0; i < bytes_to_process;
396  i++) {
398  data->telemUAVTalkCon,
399  data->radioUAVTalkCon,
400  serial_data[i]);
401  }
402  }
403  } else {
405  }
406  }
407 }
408 
417 static int32_t UAVTalkSendHandler(void *ctx, uint8_t * buf, int32_t length)
418 {
419  (void) ctx;
420 
421  int32_t ret;
422  uint32_t outputPort = getComPort();
423 
424  if (outputPort) {
425  ret = PIOS_COM_SendBufferStallTimeout(outputPort, buf, length,
427  } else {
428  ret = -1;
429  }
430 
431  return ret;
432 }
433 
442 static int32_t RadioSendHandler(void *ctx, uint8_t * buf, int32_t length)
443 {
444  (void) ctx;
445 
446  uint32_t outputPort = PIOS_COM_RADIOBRIDGE;
447 
448  // Don't send any data unless the radio port is available.
449  if (outputPort && PIOS_COM_Available(outputPort)) {
450  return PIOS_COM_SendBufferStallTimeout(outputPort, buf, length,
452  } else {
453  return -1;
454  }
455 }
456 
457 #define MetaObjectId(x) (x+1)
458 
465 static void ProcessLocalStream(UAVTalkConnection inConnectionHandle,
466  UAVTalkConnection outConnectionHandle,
467  uint8_t rxbyte)
468 {
469  // Keep reading until we receive a completed packet.
471  UAVTalkProcessInputStreamQuiet(inConnectionHandle, rxbyte);
472 
473  if (state == UAVTALK_STATE_COMPLETE) {
475 
476  uint32_t objId = UAVTalkGetPacketObjId(inConnectionHandle);
477  switch (objId) {
478  // Ignore object...
479  // These objects are shadowed and are not sent over the
480  // transmitted over the radio link.
481  // - HWTauLink : No reconfiguring remote HW over radio
482  // link
483  // - UAVTalkReceiver : We generate this ourselves on
484  // the RX side and shouldn't forward it.
485  case HWTAULINK_OBJID:
486  case MetaObjectId(HWTAULINK_OBJID):
487  case UAVTALKRECEIVER_OBJID:
488  case MetaObjectId(UAVTALKRECEIVER_OBJID):
489  return;
490  default:
491  break;
492  }
493 
494  // all packets are transparently relayed to the remote modem
495  // Incidentally this means that we fail requests for the
496  // radio stats and only telemeter them, but I consider this
497  // okee-dokee.
498  UAVTalkRelayPacket(inConnectionHandle, outConnectionHandle);
499  }
500 }
501 
509 static void ProcessRadioStream(UAVTalkConnection inConnectionHandle,
510  UAVTalkConnection outConnectionHandle,
511  uint8_t rxbyte)
512 {
513  // Keep reading until we receive a completed packet.
515  UAVTalkProcessInputStreamQuiet(inConnectionHandle, rxbyte);
516 
517  if (state == UAVTALK_STATE_COMPLETE) {
518  if (!data->have_port) {
519  telemetry_set_inhibit(true);
520  data->have_port = true;
521  }
522 
523  // We only want to unpack certain objects from the remote modem
524  // Similarly we only want to relay certain objects to the telemetry port
525  uint32_t objId = UAVTalkGetPacketObjId(inConnectionHandle);
526  switch (objId) {
527  case HWTAULINK_OBJID:
528  case MetaObjectId(HWTAULINK_OBJID):
529  case UAVTALKRECEIVER_OBJID:
530  case MetaObjectId(UAVTALKRECEIVER_OBJID):
531  break;
532  case FLIGHTBATTERYSTATE_OBJID:
533  case FLIGHTSTATUS_OBJID:
534  case POSITIONACTUAL_OBJID:
535  case VELOCITYACTUAL_OBJID:
536  case BAROALTITUDE_OBJID:
537  // process / store locally for relaying to taranis
538  UAVTalkReceiveObject(inConnectionHandle);
539  UAVTalkRelayPacket(inConnectionHandle, outConnectionHandle);
540  break;
541  default:
542  // all other packets are relayed to the telemetry port
543  UAVTalkRelayPacket(inConnectionHandle,
544  outConnectionHandle);
545  break;
546  }
547  }
548 }
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
static int32_t RadioSendHandler(void *ctx, uint8_t *buf, int32_t length)
struct pios_thread * telemetryRxTaskHandle
static uintptr_t getComPort()
static void NewReceiverData(const UAVObjEvent *ev, void *ctx, void *obj, int len)
#define STACK_SIZE_BYTES
uint32_t rxErrors
Definition: uavtalk.h:49
#define TASK_PRIORITY
UAVTalkConnection radioUAVTalkCon
void UAVTalkGetStats(UAVTalkConnection connection, UAVTalkStats *stats)
Definition: uavtalk.c:93
static void ProcessLocalStream(UAVTalkConnection inConnectionHandle, UAVTalkConnection outConnectionHandle, uint8_t rxbyte)
Process a byte of data received on the telemetry stream.
static void updateRadioComBridgeStats()
#define RETRY_TIMEOUT_MS
bool PIOS_WDG_RegisterFlag(uint16_t flag_requested)
Register a module against the watchdog.
Definition: pios_wdg.c:86
bool PIOS_WDG_UpdateFlag(uint16_t flag)
Function called by modules to indicate they are still running.
Definition: pios_wdg.c:102
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
uint32_t rxCRC
Definition: uavtalk.h:50
struct pios_thread * radioRxTaskHandle
#define PIOS_COM_TELEM_USB
Definition: pios_board.h:114
static RadioComBridgeData * data
uint32_t txBytes
Definition: uavtalk.h:42
MODULE_INITCALL(RadioComBridgeInitialize, RadioComBridgeStart)
uint8_t length
uint32_t rxBytes
Definition: uavtalk.h:43
#define PIOS_LED_RX
Definition: pios_board.h:89
void * UAVTalkConnection
Definition: uavtalk.h:53
#define PIOS_WDG_TELEMETRY
Definition: pios_board.h:79
#define PIOS_COM_TELEM_SER
Definition: pios_hal.h:58
#define USB_ACTIVITY_TIMEOUT_MS
static void radioRxTask(void *parameters)
UAVTalkConnection UAVTalkInitialize(void *ctx, UAVTalkOutputCb outputStream, UAVTalkAckCb ackCallback, UAVTalkReqCb reqCallback, UAVTalkFileCb fileCallback)
Definition: uavtalk.c:59
static bool processUsbActivity(bool seen_active)
#define PIOS_WDG_RADIORX
Definition: pios_board.h:80
uint16_t PIOS_COM_ReceiveBuffer(uintptr_t com_id, uint8_t *buf, uint16_t buf_len, uint32_t timeout_ms)
Private include file of the UAVTalk library.
UAVTalkConnection telemUAVTalkCon
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
Definition: pios_thread.c:89
Event dispatcher, distributes object events as callbacks. Alternative to using tasks and queues...
#define MetaObjectId(x)
uint8_t i
Definition: msp_messages.h:97
bool PIOS_Thread_Period_Elapsed(const uint32_t prev_systime, const uint32_t increment_ms)
Determine if a period has elapsed since a datum.
Definition: pios_thread.c:281
#define COMSTATS_INJECT
uint16_t PIOS_COM_GetNumReceiveBytesPending(uintptr_t com_id)
volatile bool have_port
Tracking statistics for a UAVTalk connection.
Definition: uavtalk.h:41
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
void PIOS_ANNUNC_Toggle(uint32_t annunc_id)
static void telemetryRxTask(void *parameters)
int32_t UAVTalkSendObject(UAVTalkConnection connection, UAVObjHandle obj, uint16_t instId, uint8_t acked)
Definition: uavtalk.c:120
UAVTalkRxState
Definition: uavtalk.h:55
UAVTalkRxState UAVTalkProcessInputStreamQuiet(UAVTalkConnection connection, uint8_t rxbyte)
Definition: uavtalk.c:180
#define PIOS_COM_RADIOBRIDGE
Definition: pios_board.h:168
static int32_t RadioComBridgeInitialize(void)
Initialise the module.
Includes PiOS and core architecture components.
uint8_t unused[4]
Definition: bl_messages.h:70
int32_t UAVTalkReceiveObject(UAVTalkConnection connectionHandle)
Definition: uavtalk.c:531
#define MAX_PORT_DELAY
int32_t PIOS_COM_SendBufferStallTimeout(uintptr_t com_id, const uint8_t *buffer, uint16_t len, uint32_t max_ms)
void telemetry_set_inhibit(bool inhibit)
Definition: telemetry.c:981
int32_t UAVTalkRelayPacket(UAVTalkConnection inConnectionHandle, UAVTalkConnection outConnectionHandle)
Definition: uavtalk.c:451
uint32_t txErrors
Definition: uavtalk.h:48
Include file of the UAVTalk library.
static int32_t RadioComBridgeStart(void)
Start the module.
uint32_t UAVTalkGetPacketObjId(UAVTalkConnection connection)
Definition: uavtalk.c:550
static int32_t UAVTalkSendHandler(void *ctx, uint8_t *buf, int32_t length)
Transmit data buffer to the com port.
bool PIOS_COM_Available(uintptr_t com_id)
static void ProcessRadioStream(UAVTalkConnection inConnectionHandle, UAVTalkConnection outConnectionHandle, uint8_t rxbyte)
Process a byte of data received on the radio data stream.
enum arena_state state