REVONANO Milestones update
[librepilot.git] / flight / pios / common / pios_oplinkrcvr.c
blob5c967c10526205a4f58d30b37b55c7f725097b6c
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_OPLinkRCVR OPLink Receiver Input Functions
6 * @brief Code to read the channels within the OPLinkReceiver UAVObject
7 * @{
9 * @file pios_opinkrcvr.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
11 * @brief GCS Input functions (STM32 dependent)
12 * @see The GNU Public License (GPL) Version 3
14 *****************************************************************************/
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.
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.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <pios.h>
33 #ifdef PIOS_INCLUDE_OPLINKRCVR
35 #include <uavobjectmanager.h>
36 #include <oplinkreceiver.h>
37 #include <oplinkstatus.h>
38 #include <pios_oplinkrcvr_priv.h>
40 static OPLinkReceiverData oplinkreceiverdata;
42 /* Provide a RCVR driver */
43 static int32_t PIOS_OPLinkRCVR_Get(uint32_t rcvr_id, uint8_t channel);
44 static void PIOS_oplinkrcvr_Supervisor(uint32_t ppm_id);
45 static uint8_t PIOS_OPLinkRCVR_Quality_Get(uint32_t oplinkrcvr_id);
47 const struct pios_rcvr_driver pios_oplinkrcvr_rcvr_driver = {
48 .read = PIOS_OPLinkRCVR_Get,
49 .get_quality = PIOS_OPLinkRCVR_Quality_Get
52 /* Local Variables */
53 enum pios_oplinkrcvr_dev_magic {
54 PIOS_OPLINKRCVR_DEV_MAGIC = 0x07ab9e2544cf5029,
57 struct pios_oplinkrcvr_dev {
58 enum pios_oplinkrcvr_dev_magic magic;
60 uint8_t supv_timer;
61 bool Fresh;
64 static struct pios_oplinkrcvr_dev *global_oplinkrcvr_dev;
66 static bool PIOS_oplinkrcvr_validate(struct pios_oplinkrcvr_dev *oplinkrcvr_dev)
68 return oplinkrcvr_dev->magic == PIOS_OPLINKRCVR_DEV_MAGIC;
71 #if defined(PIOS_INCLUDE_FREERTOS)
72 static struct pios_oplinkrcvr_dev *PIOS_oplinkrcvr_alloc(void)
74 struct pios_oplinkrcvr_dev *oplinkrcvr_dev;
76 oplinkrcvr_dev = (struct pios_oplinkrcvr_dev *)pios_malloc(sizeof(*oplinkrcvr_dev));
77 if (!oplinkrcvr_dev) {
78 return NULL;
81 oplinkrcvr_dev->magic = PIOS_OPLINKRCVR_DEV_MAGIC;
82 oplinkrcvr_dev->Fresh = false;
83 oplinkrcvr_dev->supv_timer = 0;
85 /* The update callback cannot receive the device pointer, so set it in a global */
86 global_oplinkrcvr_dev = oplinkrcvr_dev;
88 return oplinkrcvr_dev;
90 #else
91 static struct pios_oplinkrcvr_dev pios_oplinkrcvr_devs[PIOS_OPLINKRCVR_MAX_DEVS];
92 static uint8_t pios_oplinkrcvr_num_devs;
93 static struct pios_oplinkrcvr_dev *PIOS_oplinkrcvr_alloc(void)
95 struct pios_oplinkrcvr_dev *oplinkrcvr_dev;
97 if (pios_oplinkrcvr_num_devs >= PIOS_OPLINKRCVR_MAX_DEVS) {
98 return NULL;
101 oplinkrcvr_dev = &pios_oplinkrcvr_devs[pios_oplinkrcvr_num_devs++];
102 oplinkrcvr_dev->magic = PIOS_OPLINKRCVR_DEV_MAGIC;
103 oplinkrcvr_dev->Fresh = false;
104 oplinkrcvr_dev->supv_timer = 0;
106 global_oplinkrcvr_dev = oplinkrcvr_dev;
108 return oplinkrcvr_dev;
110 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
112 static void oplinkreceiver_updated(UAVObjEvent *ev)
114 struct pios_oplinkrcvr_dev *oplinkrcvr_dev = global_oplinkrcvr_dev;
116 if (ev->obj == OPLinkReceiverHandle()) {
117 OPLinkReceiverGet(&oplinkreceiverdata);
118 oplinkrcvr_dev->Fresh = true;
122 extern int32_t PIOS_OPLinkRCVR_Init(__attribute__((unused)) uint32_t *oplinkrcvr_id)
124 struct pios_oplinkrcvr_dev *oplinkrcvr_dev;
126 /* Allocate the device structure */
127 oplinkrcvr_dev = (struct pios_oplinkrcvr_dev *)PIOS_oplinkrcvr_alloc();
128 if (!oplinkrcvr_dev) {
129 return -1;
132 for (uint8_t i = 0; i < OPLINKRECEIVER_CHANNEL_NUMELEM; i++) {
133 /* Flush channels */
134 oplinkreceiverdata.Channel[i] = PIOS_RCVR_TIMEOUT;
137 /* Register uavobj callback */
138 OPLinkReceiverConnectCallback(oplinkreceiver_updated);
140 /* Register the failsafe timer callback. */
141 if (!PIOS_RTC_RegisterTickCallback(PIOS_oplinkrcvr_Supervisor, (uint32_t)oplinkrcvr_dev)) {
142 PIOS_DEBUG_Assert(0);
145 return 0;
149 * Get the value of an input channel
150 * \param[in] channel Number of the channel desired (zero based)
151 * \output PIOS_RCVR_INVALID channel not available
152 * \output PIOS_RCVR_TIMEOUT failsafe condition or missing receiver
153 * \output >=0 channel value
155 static int32_t PIOS_OPLinkRCVR_Get(__attribute__((unused)) uint32_t rcvr_id, uint8_t channel)
157 if (channel >= OPLINKRECEIVER_CHANNEL_NUMELEM) {
158 /* channel is out of range */
159 return PIOS_RCVR_INVALID;
162 return oplinkreceiverdata.Channel[channel];
165 static void PIOS_oplinkrcvr_Supervisor(uint32_t oplinkrcvr_id)
167 /* Recover our device context */
168 struct pios_oplinkrcvr_dev *oplinkrcvr_dev = (struct pios_oplinkrcvr_dev *)oplinkrcvr_id;
170 if (!PIOS_oplinkrcvr_validate(oplinkrcvr_dev)) {
171 /* Invalid device specified */
172 return;
176 * RTC runs at 625Hz.
178 if (++(oplinkrcvr_dev->supv_timer) < (PIOS_OPLINK_RCVR_TIMEOUT_MS * 1000 / 625)) {
179 return;
181 oplinkrcvr_dev->supv_timer = 0;
183 if (!oplinkrcvr_dev->Fresh) {
184 for (int32_t i = 0; i < OPLINKRECEIVER_CHANNEL_NUMELEM; i++) {
185 oplinkreceiverdata.Channel[i] = PIOS_RCVR_TIMEOUT;
189 oplinkrcvr_dev->Fresh = false;
192 static uint8_t PIOS_OPLinkRCVR_Quality_Get(__attribute__((unused)) uint32_t oplinkrcvr_id)
194 uint8_t oplink_quality;
196 OPLinkStatusLinkQualityGet(&oplink_quality);
198 /* link_status is in the range 0-128, so scale to a % */
199 return oplink_quality * 100 / 128;
202 #endif /* PIOS_INCLUDE_OPLINKRCVR */
205 * @}
206 * @}