3737#include <oplinkstatus.h>
3838#include <pios_oplinkrcvr_priv.h>
3939
40+ // Put receiver in failsafe if not updated within timeout
41+ #define PIOS_OPLINK_RCVR_TIMEOUT_MS 100
4042
4143/* Provide a RCVR driver */
4244static int32_t PIOS_OPLinkRCVR_Get (uint32_t rcvr_id , uint8_t channel );
@@ -60,11 +62,14 @@ struct pios_oplinkrcvr_dev {
6062 bool Fresh ;
6163};
6264
65+ static struct pios_oplinkrcvr_dev * global_oplinkrcvr_dev ;
66+
6367static bool PIOS_oplinkrcvr_validate (struct pios_oplinkrcvr_dev * oplinkrcvr_dev )
6468{
6569 return oplinkrcvr_dev -> magic == PIOS_OPLINKRCVR_DEV_MAGIC ;
6670}
6771
72+ #if defined(PIOS_INCLUDE_RFM22B )
6873static void PIOS_oplinkrcvr_ppm_callback (uint32_t oplinkrcvr_id , const int16_t * channels )
6974{
7075 /* Recover our device context */
@@ -78,10 +83,21 @@ static void PIOS_oplinkrcvr_ppm_callback(uint32_t oplinkrcvr_id, const int16_t *
7883 for (uint8_t i = 0 ; i < OPLINKRECEIVER_CHANNEL_NUMELEM ; ++ i ) {
7984 oplinkrcvr_dev -> oplinkreceiverdata .Channel [i ] = (i < RFM22B_PPM_NUM_CHANNELS ) ? channels [i ] : PIOS_RCVR_TIMEOUT ;
8085 }
86+
87+ // Update the RSSI and quality fields.
88+ int8_t rssi ;
89+ OPLinkStatusRSSIGet (& rssi );
90+ oplinkrcvr_dev -> oplinkreceiverdata .RSSI = rssi ;
91+ uint16_t quality ;
92+ OPLinkStatusLinkQualityGet (& quality );
93+ // Link quality is 0-128, so scale it down to 0-100
94+ oplinkrcvr_dev -> oplinkreceiverdata .LinkQuality = quality * 100 / 128 ;
95+
8196 OPLinkReceiverSet (& oplinkrcvr_dev -> oplinkreceiverdata );
8297
8398 oplinkrcvr_dev -> Fresh = true;
8499}
100+ #endif /* PIOS_INCLUDE_RFM22B */
85101
86102#if defined(PIOS_INCLUDE_FREERTOS )
87103static struct pios_oplinkrcvr_dev * PIOS_oplinkrcvr_alloc (void )
@@ -97,6 +113,9 @@ static struct pios_oplinkrcvr_dev *PIOS_oplinkrcvr_alloc(void)
97113 oplinkrcvr_dev -> Fresh = false;
98114 oplinkrcvr_dev -> supv_timer = 0 ;
99115
116+ /* The update callback cannot receive the device pointer, so set it in a global */
117+ global_oplinkrcvr_dev = oplinkrcvr_dev ;
118+
100119 return oplinkrcvr_dev ;
101120}
102121#else
@@ -119,7 +138,21 @@ static struct pios_oplinkrcvr_dev *PIOS_oplinkrcvr_alloc(void)
119138}
120139#endif /* if defined(PIOS_INCLUDE_FREERTOS) */
121140
141+ static void oplinkreceiver_updated (UAVObjEvent * ev )
142+ {
143+ struct pios_oplinkrcvr_dev * oplinkrcvr_dev = global_oplinkrcvr_dev ;
144+
145+ if (ev -> obj == OPLinkReceiverHandle ()) {
146+ OPLinkReceiverGet (& oplinkrcvr_dev -> oplinkreceiverdata );
147+ oplinkrcvr_dev -> Fresh = true;
148+ }
149+ }
150+
151+ #if defined(PIOS_INCLUDE_RFM22B )
122152extern int32_t PIOS_OPLinkRCVR_Init (uint32_t * oplinkrcvr_id , uint32_t rfm22b_id )
153+ #else
154+ extern int32_t PIOS_OPLinkRCVR_Init (uint32_t * oplinkrcvr_id )
155+ #endif
123156{
124157 struct pios_oplinkrcvr_dev * oplinkrcvr_dev ;
125158
@@ -134,8 +167,13 @@ extern int32_t PIOS_OPLinkRCVR_Init(uint32_t *oplinkrcvr_id, uint32_t rfm22b_id)
134167 oplinkrcvr_dev -> oplinkreceiverdata .Channel [i ] = PIOS_RCVR_TIMEOUT ;
135168 }
136169
170+ #if defined(PIOS_INCLUDE_RFM22B )
137171 /* Register ppm callback */
138172 PIOS_RFM22B_SetPPMCallback (rfm22b_id , PIOS_oplinkrcvr_ppm_callback , (uint32_t )oplinkrcvr_dev );
173+ #endif
174+
175+ /* Updates could come over the telemetry channel, so register uavobj callback */
176+ OPLinkReceiverConnectCallback (oplinkreceiver_updated );
139177
140178 /* Register the failsafe timer callback. */
141179 if (!PIOS_RTC_RegisterTickCallback (PIOS_oplinkrcvr_Supervisor , (uint32_t )oplinkrcvr_dev )) {
@@ -199,14 +237,17 @@ static void PIOS_oplinkrcvr_Supervisor(uint32_t oplinkrcvr_id)
199237 oplinkrcvr_dev -> Fresh = false;
200238}
201239
202- static uint8_t PIOS_OPLinkRCVR_Quality_Get (__attribute__(( unused )) uint32_t oplinkrcvr_id )
240+ static uint8_t PIOS_OPLinkRCVR_Quality_Get (uint32_t oplinkrcvr_id )
203241{
204- uint16_t oplink_quality ;
242+ /* Recover our device context */
243+ struct pios_oplinkrcvr_dev * oplinkrcvr_dev = (struct pios_oplinkrcvr_dev * )oplinkrcvr_id ;
205244
206- OPLinkStatusLinkQualityGet (& oplink_quality );
245+ if (!PIOS_oplinkrcvr_validate (oplinkrcvr_dev )) {
246+ /* Invalid device specified */
247+ return 0 ;
248+ }
207249
208- /* link_status is in the range 0-128, so scale to a % */
209- return oplink_quality * 100 / 128 ;
250+ return oplinkrcvr_dev -> oplinkreceiverdata .LinkQuality ;
210251}
211252
212253#endif /* PIOS_INCLUDE_OPLINKRCVR */
0 commit comments