dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_openlrs_rcvr.c
Go to the documentation of this file.
1 
15 /*
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24  * for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, see <http://www.gnu.org/licenses/>
28  */
29 
30 #include "pios.h"
31 
32 #ifdef PIOS_INCLUDE_OPENLRS
33 
34 #include "pios_openlrs_priv.h"
35 
36 #include <uavobjectmanager.h>
37 #include <pios_openlrs_priv.h>
38 #include <pios_openlrs_rcvr_priv.h>
39 
40 #include <uavtalkreceiver.h>
41 
42 #define PIOS_OPENLRS_RCVR_TIMEOUT_MS 100
43 
44 /* Provide a RCVR driver */
45 static int32_t PIOS_OpenLRS_Rcvr_Get(uintptr_t rcvr_id, uint8_t channel);
46 static void PIOS_OpenLRS_Rcvr_Supervisor(uintptr_t ppm_id);
47 
49  .read = PIOS_OpenLRS_Rcvr_Get,
50 };
51 
52 /* Local Variables */
53 enum pios_openlrs_rcvr_dev_magic {
54  PIOS_OPENLRS_RCVR_DEV_MAGIC = 0x07ac9e2144ff5329,
55 };
56 
57 struct pios_openlrs_rcvr_dev {
58  enum pios_openlrs_rcvr_dev_magic magic;
59  int16_t channels[OPENLRS_PPM_NUM_CHANNELS];
60  uint8_t supv_timer;
61  bool fresh;
62 };
63 
64 static bool PIOS_OpenLRS_Rcvr_Validate(struct pios_openlrs_rcvr_dev
65  *openlrs_rcvr_dev)
66 {
67  return openlrs_rcvr_dev->magic == PIOS_OPENLRS_RCVR_DEV_MAGIC;
68 }
69 
70 static struct pios_openlrs_rcvr_dev *PIOS_OpenLRS_Rcvr_alloc(void)
71 {
72  struct pios_openlrs_rcvr_dev *openlrs_rcvr_dev;
73 
74  openlrs_rcvr_dev =
75  (struct pios_openlrs_rcvr_dev *)
76  PIOS_malloc(sizeof(*openlrs_rcvr_dev));
77  if (!openlrs_rcvr_dev) {
78  return NULL;
79  }
80 
81  openlrs_rcvr_dev->magic = PIOS_OPENLRS_RCVR_DEV_MAGIC;
82  openlrs_rcvr_dev->fresh = false;
83  openlrs_rcvr_dev->supv_timer = 0;
84 
85  return openlrs_rcvr_dev;
86 }
87 
88 extern int32_t PIOS_OpenLRS_Rcvr_Init(uintptr_t *openlrs_rcvr_id,
89  pios_openlrs_t openlrs_id)
90 {
91  struct pios_openlrs_rcvr_dev *openlrs_rcvr_dev;
92 
93  /* Allocate the device structure */
94  openlrs_rcvr_dev =
95  (struct pios_openlrs_rcvr_dev *)PIOS_OpenLRS_Rcvr_alloc();
96  if (!openlrs_rcvr_dev) {
97  return -1;
98  }
99 
100  /* Register uavobj callback */
101 
102  *openlrs_rcvr_id = (uintptr_t) openlrs_rcvr_dev;
103  PIOS_OpenLRS_RegisterRcvr(openlrs_id, *openlrs_rcvr_id);
104 
105  /* Register the failsafe timer callback. */
107  (PIOS_OpenLRS_Rcvr_Supervisor, *openlrs_rcvr_id)) {
109  }
110 
111  return 0;
112 }
113 
119 int32_t PIOS_OpenLRS_Rcvr_UpdateChannels(uintptr_t openlrs_rcvr_id, int16_t *channels)
120 {
121  /* Recover our device context */
122  struct pios_openlrs_rcvr_dev *openlrs_rcvr_dev =
123  (struct pios_openlrs_rcvr_dev *)openlrs_rcvr_id;
124 
125  if (!PIOS_OpenLRS_Rcvr_Validate(openlrs_rcvr_dev)) {
126  /* Invalid device specified */
127  return -1;
128  }
129 
130  for (int i = 0; i < OPENLRS_PPM_NUM_CHANNELS; i++) {
131  openlrs_rcvr_dev->channels[i] = channels[i];
132  }
133 
134  // This is a task, not an ISR.
136 
137  // let supervisor know we have new data
138  openlrs_rcvr_dev->fresh = true;
139 
140 #ifdef PIPXTREME
141  /* We're a RX on pipx. This means that the channel data should go
142  * over a radio link. Update the UAVTalkReceiver object, as that's
143  * the only use for the channel data.
144  */
145 
146  UAVTalkReceiverData urcvr = {};
147 
148  for (int i = 0; (i < UAVTALKRECEIVER_CHANNEL_NUMELEM) &&
149  (i < OPENLRS_PPM_NUM_CHANNELS) ; i++) {
150  urcvr.Channel[i] = channels[i];
151  }
152 
153  UAVTalkReceiverSet(&urcvr);
154 #endif
155 
156  return 0;
157 }
158 
166 static int32_t PIOS_OpenLRS_Rcvr_Get(uintptr_t openlrs_rcvr_id, uint8_t channel)
167 {
168  if (channel >= OPENLRS_PPM_NUM_CHANNELS) {
169  /* channel is out of range */
170  return PIOS_RCVR_INVALID;
171  }
172 
173  /* Recover our device context */
174  struct pios_openlrs_rcvr_dev *openlrs_rcvr_dev =
175  (struct pios_openlrs_rcvr_dev *)openlrs_rcvr_id;
176 
177  if (!PIOS_OpenLRS_Rcvr_Validate(openlrs_rcvr_dev)) {
178  /* Invalid device specified */
179  return PIOS_RCVR_INVALID;
180  }
181 
182  return openlrs_rcvr_dev->channels[channel];
183 }
184 
185 static void PIOS_OpenLRS_Rcvr_Supervisor(uintptr_t openlrs_rcvr_id)
186 {
187  /* Recover our device context */
188  struct pios_openlrs_rcvr_dev *openlrs_rcvr_dev =
189  (struct pios_openlrs_rcvr_dev *)openlrs_rcvr_id;
190 
191  if (!PIOS_OpenLRS_Rcvr_Validate(openlrs_rcvr_dev)) {
192  /* Invalid device specified */
193  return;
194  }
195 
196  /*
197  * RTC runs at 625Hz.
198  */
199  if (++(openlrs_rcvr_dev->supv_timer) <
200  (PIOS_OPENLRS_RCVR_TIMEOUT_MS * 1000 / 625)) {
201  return;
202  }
203  openlrs_rcvr_dev->supv_timer = 0;
204 
205  if (!openlrs_rcvr_dev->fresh) {
206  for (int32_t i = 0; i < OPENLRS_PPM_NUM_CHANNELS; i++) {
207  openlrs_rcvr_dev->channels[i] = PIOS_RCVR_TIMEOUT;
208  }
209 
210  }
211 
212  openlrs_rcvr_dev->fresh = false;
213 }
214 
215 #endif /* PIOS_INCLUDE_OPENLRS */
216 
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.
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
int32_t PIOS_OpenLRS_Rcvr_UpdateChannels(uintptr_t openlrs_rcvr_id, int16_t *channels)
bool PIOS_RTC_RegisterTickCallback(void(*fn)(uintptr_t id), uintptr_t data)
Definition: pios_delay.c:185
const struct pios_rcvr_driver pios_openlrs_rcvr_driver
uint8_t i
Definition: msp_messages.h:97
uint32_t magic
void PIOS_RCVR_Active()
Implements an OpenLRS driver for the RFM22B.
int32_t PIOS_OpenLRS_Rcvr_Init(uintptr_t *openlrs_rcvr_id, pios_openlrs_t openlrs_id)