Adding more servos
[inav.git] / src / main / rx / rx.c
blobf941eaebe20eb19927ea814b426c34c1ba113647
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdlib.h>
22 #include <string.h>
24 #include "platform.h"
26 #include "build/build_config.h"
27 #include "build/debug.h"
29 #include "common/maths.h"
30 #include "common/utils.h"
32 #include "programming/logic_condition.h"
34 #include "config/feature.h"
35 #include "config/parameter_group.h"
36 #include "config/parameter_group_ids.h"
39 #include "drivers/adc.h"
40 #include "drivers/serial.h"
41 #include "drivers/time.h"
43 #include "fc/config.h"
44 #include "fc/rc_controls.h"
45 #include "fc/rc_modes.h"
46 #include "fc/settings.h"
48 #include "flight/failsafe.h"
50 #include "io/serial.h"
52 #include "rx/rx.h"
53 #include "rx/crsf.h"
54 #include "rx/ibus.h"
55 #include "rx/jetiexbus.h"
56 #include "rx/fport.h"
57 #include "rx/fport2.h"
58 #include "rx/msp.h"
59 #include "rx/msp_override.h"
60 #include "rx/sbus.h"
61 #include "rx/spektrum.h"
62 #include "rx/srxl2.h"
63 #include "rx/sumd.h"
64 #include "rx/ghst.h"
65 #include "rx/mavlink.h"
66 #include "rx/sim.h"
68 const char rcChannelLetters[] = "AERT";
70 static uint16_t rssi = 0; // range: [0;1023]
71 static timeUs_t lastMspRssiUpdateUs = 0;
73 #define MSP_RSSI_TIMEOUT_US 1500000 // 1.5 sec
74 #define RX_LQ_INTERVAL_MS 200
75 #define RX_LQ_TIMEOUT_MS 1000
77 static rxLinkQualityTracker_e rxLQTracker;
78 static rssiSource_e activeRssiSource;
80 static bool rxDataProcessingRequired = false;
81 static bool auxiliaryProcessingRequired = false;
83 #if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
84 static bool mspOverrideDataProcessingRequired = false;
85 #endif
87 static bool rxSignalReceived = false;
88 static bool rxFlightChannelsValid = false;
89 static uint8_t rxChannelCount;
91 static timeUs_t rxNextUpdateAtUs = 0;
92 static timeUs_t needRxSignalBefore = 0;
93 static bool isRxSuspended = false;
95 static rcChannel_t rcChannels[MAX_SUPPORTED_RC_CHANNEL_COUNT];
97 rxLinkStatistics_t rxLinkStatistics;
98 rxRuntimeConfig_t rxRuntimeConfig;
99 static uint8_t rcSampleIndex = 0;
101 PG_REGISTER_WITH_RESET_TEMPLATE(rxConfig_t, rxConfig, PG_RX_CONFIG, 12);
103 #ifndef SERIALRX_PROVIDER
104 #define SERIALRX_PROVIDER 0
105 #endif
107 #ifndef DEFAULT_RX_TYPE
108 #define DEFAULT_RX_TYPE RX_TYPE_NONE
109 #endif
111 #define RX_MIN_USEX 885
112 PG_RESET_TEMPLATE(rxConfig_t, rxConfig,
113 .receiverType = DEFAULT_RX_TYPE,
114 .rcmap = {0, 1, 3, 2}, // Default to AETR map
115 .halfDuplex = SETTING_SERIALRX_HALFDUPLEX_DEFAULT,
116 .serialrx_provider = SERIALRX_PROVIDER,
117 #ifdef USE_SPEKTRUM_BIND
118 .spektrum_sat_bind = SETTING_SPEKTRUM_SAT_BIND_DEFAULT,
119 #endif
120 .serialrx_inverted = SETTING_SERIALRX_INVERTED_DEFAULT,
121 .mincheck = SETTING_MIN_CHECK_DEFAULT,
122 .maxcheck = SETTING_MAX_CHECK_DEFAULT,
123 .rx_min_usec = SETTING_RX_MIN_USEC_DEFAULT, // any of first 4 channels below this value will trigger rx loss detection
124 .rx_max_usec = SETTING_RX_MAX_USEC_DEFAULT, // any of first 4 channels above this value will trigger rx loss detection
125 .rssi_channel = SETTING_RSSI_CHANNEL_DEFAULT,
126 .rssiMin = SETTING_RSSI_MIN_DEFAULT,
127 .rssiMax = SETTING_RSSI_MAX_DEFAULT,
128 .sbusSyncInterval = SETTING_SBUS_SYNC_INTERVAL_DEFAULT,
129 .rcFilterFrequency = SETTING_RC_FILTER_LPF_HZ_DEFAULT,
130 .autoSmooth = SETTING_RC_FILTER_AUTO_DEFAULT,
131 .autoSmoothFactor = SETTING_RC_FILTER_SMOOTHING_FACTOR_DEFAULT,
132 #if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
133 .mspOverrideChannels = SETTING_MSP_OVERRIDE_CHANNELS_DEFAULT,
134 #endif
135 .rssi_source = SETTING_RSSI_SOURCE_DEFAULT,
136 #ifdef USE_SERIALRX_SRXL2
137 .srxl2_unit_id = SETTING_SRXL2_UNIT_ID_DEFAULT,
138 .srxl2_baud_fast = SETTING_SRXL2_BAUD_FAST_DEFAULT,
139 #endif
142 void resetAllRxChannelRangeConfigurations(void)
144 // set default calibration to full range and 1:1 mapping
145 for (int i = 0; i < NON_AUX_CHANNEL_COUNT; i++) {
146 rxChannelRangeConfigsMutable(i)->min = PWM_RANGE_MIN;
147 rxChannelRangeConfigsMutable(i)->max = PWM_RANGE_MAX;
151 PG_REGISTER_ARRAY_WITH_RESET_FN(rxChannelRangeConfig_t, NON_AUX_CHANNEL_COUNT, rxChannelRangeConfigs, PG_RX_CHANNEL_RANGE_CONFIG, 0);
153 void pgResetFn_rxChannelRangeConfigs(rxChannelRangeConfig_t *rxChannelRangeConfigs)
155 // set default calibration to full range and 1:1 mapping
156 for (int i = 0; i < NON_AUX_CHANNEL_COUNT; i++) {
157 rxChannelRangeConfigs[i].min = PWM_RANGE_MIN;
158 rxChannelRangeConfigs[i].max = PWM_RANGE_MAX;
162 static uint16_t nullReadRawRC(const rxRuntimeConfig_t *rxRuntimeConfig, uint8_t channel)
164 UNUSED(rxRuntimeConfig);
165 UNUSED(channel);
167 return 0;
170 static uint8_t nullFrameStatus(rxRuntimeConfig_t *rxRuntimeConfig)
172 UNUSED(rxRuntimeConfig);
173 return RX_FRAME_PENDING;
176 bool isRxPulseValid(uint16_t pulseDuration)
178 return pulseDuration >= rxConfig()->rx_min_usec &&
179 pulseDuration <= rxConfig()->rx_max_usec;
182 #ifdef USE_SERIAL_RX
183 bool serialRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
185 bool enabled = false;
186 switch (rxConfig->serialrx_provider) {
187 #ifdef USE_SERIALRX_SRXL2
188 case SERIALRX_SRXL2:
189 enabled = srxl2RxInit(rxConfig, rxRuntimeConfig);
190 break;
191 #endif
192 #ifdef USE_SERIALRX_SPEKTRUM
193 case SERIALRX_SPEKTRUM1024:
194 case SERIALRX_SPEKTRUM2048:
195 enabled = spektrumInit(rxConfig, rxRuntimeConfig);
196 break;
197 #endif
198 #ifdef USE_SERIALRX_SBUS
199 case SERIALRX_SBUS2:
200 case SERIALRX_SBUS:
201 enabled = sbusInit(rxConfig, rxRuntimeConfig);
202 break;
203 case SERIALRX_SBUS_FAST:
204 enabled = sbusInitFast(rxConfig, rxRuntimeConfig);
205 break;
206 #endif
207 #ifdef USE_SERIALRX_SUMD
208 case SERIALRX_SUMD:
209 enabled = sumdInit(rxConfig, rxRuntimeConfig);
210 break;
211 #endif
212 #ifdef USE_SERIALRX_IBUS
213 case SERIALRX_IBUS:
214 enabled = ibusInit(rxConfig, rxRuntimeConfig);
215 break;
216 #endif
217 #ifdef USE_SERIALRX_JETIEXBUS
218 case SERIALRX_JETIEXBUS:
219 enabled = jetiExBusInit(rxConfig, rxRuntimeConfig);
220 break;
221 #endif
222 #ifdef USE_SERIALRX_CRSF
223 case SERIALRX_CRSF:
224 enabled = crsfRxInit(rxConfig, rxRuntimeConfig);
225 break;
226 #endif
227 #ifdef USE_SERIALRX_FPORT
228 case SERIALRX_FPORT:
229 enabled = fportRxInit(rxConfig, rxRuntimeConfig);
230 break;
231 #endif
232 #ifdef USE_SERIALRX_FPORT2
233 case SERIALRX_FPORT2:
234 enabled = fport2RxInit(rxConfig, rxRuntimeConfig, false);
235 break;
236 case SERIALRX_FBUS:
237 enabled = fport2RxInit(rxConfig, rxRuntimeConfig, true);
238 break;
239 #endif
240 #ifdef USE_SERIALRX_GHST
241 case SERIALRX_GHST:
242 enabled = ghstRxInit(rxConfig, rxRuntimeConfig);
243 break;
244 #endif
245 #ifdef USE_SERIALRX_MAVLINK
246 case SERIALRX_MAVLINK:
247 enabled = mavlinkRxInit(rxConfig, rxRuntimeConfig);
248 break;
249 #endif
250 default:
251 enabled = false;
252 break;
254 return enabled;
256 #endif
258 void rxInit(void)
260 lqTrackerReset(&rxLQTracker);
262 rxRuntimeConfig.lqTracker = &rxLQTracker;
263 rxRuntimeConfig.rcReadRawFn = nullReadRawRC;
264 rxRuntimeConfig.rcFrameStatusFn = nullFrameStatus;
265 rxRuntimeConfig.rxSignalTimeout = DELAY_10_HZ;
266 rcSampleIndex = 0;
268 timeMs_t nowMs = millis();
270 for (int i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) {
271 rcChannels[i].raw = PWM_RANGE_MIDDLE;
272 rcChannels[i].data = PWM_RANGE_MIDDLE;
273 rcChannels[i].expiresAt = nowMs + MAX_INVALID_RX_PULSE_TIME;
276 rcChannels[THROTTLE].raw = (feature(FEATURE_REVERSIBLE_MOTORS)) ? PWM_RANGE_MIDDLE : rxConfig()->rx_min_usec;
277 rcChannels[THROTTLE].data = rcChannels[THROTTLE].raw;
279 // Initialize ARM switch to OFF position when arming via switch is defined
280 for (int i = 0; i < MAX_MODE_ACTIVATION_CONDITION_COUNT; i++) {
281 if (modeActivationConditions(i)->modeId == BOXARM && IS_RANGE_USABLE(&modeActivationConditions(i)->range)) {
282 // ARM switch is defined, determine an OFF value
283 uint16_t value;
284 if (modeActivationConditions(i)->range.startStep > 0) {
285 value = MODE_STEP_TO_CHANNEL_VALUE((modeActivationConditions(i)->range.startStep - 1));
286 } else {
287 value = MODE_STEP_TO_CHANNEL_VALUE((modeActivationConditions(i)->range.endStep + 1));
289 // Initialize ARM AUX channel to OFF value
290 rcChannel_t *armChannel = &rcChannels[modeActivationConditions(i)->auxChannelIndex + NON_AUX_CHANNEL_COUNT];
291 armChannel->raw = value;
292 armChannel->data = value;
296 switch (rxConfig()->receiverType) {
298 #ifdef USE_SERIAL_RX
299 case RX_TYPE_SERIAL:
300 if (!serialRxInit(rxConfig(), &rxRuntimeConfig)) {
301 rxConfigMutable()->receiverType = RX_TYPE_NONE;
302 rxRuntimeConfig.rcReadRawFn = nullReadRawRC;
303 rxRuntimeConfig.rcFrameStatusFn = nullFrameStatus;
305 break;
306 #endif
308 #ifdef USE_RX_MSP
309 case RX_TYPE_MSP:
310 rxMspInit(rxConfig(), &rxRuntimeConfig);
311 break;
312 #endif
314 #ifdef USE_RX_SIM
315 case RX_TYPE_SIM:
316 rxSimInit(rxConfig(), &rxRuntimeConfig);
317 break;
318 #endif
320 default:
321 case RX_TYPE_NONE:
322 rxConfigMutable()->receiverType = RX_TYPE_NONE;
323 rxRuntimeConfig.rcReadRawFn = nullReadRawRC;
324 rxRuntimeConfig.rcFrameStatusFn = nullFrameStatus;
325 break;
328 rxUpdateRSSISource();
330 #if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
331 if (rxConfig()->receiverType != RX_TYPE_MSP) {
332 mspOverrideInit();
334 #endif
336 rxChannelCount = MIN(MAX_SUPPORTED_RC_CHANNEL_COUNT, rxRuntimeConfig.channelCount);
339 void rxUpdateRSSISource(void)
341 activeRssiSource = RSSI_SOURCE_NONE;
343 if (rxConfig()->rssi_source == RSSI_SOURCE_NONE) {
344 return;
347 #if defined(USE_ADC)
348 if (rxConfig()->rssi_source == RSSI_SOURCE_ADC || rxConfig()->rssi_source == RSSI_SOURCE_AUTO) {
349 if (feature(FEATURE_RSSI_ADC)) {
350 activeRssiSource = RSSI_SOURCE_ADC;
351 return;
354 #endif
356 if (rxConfig()->rssi_source == RSSI_SOURCE_RX_CHANNEL || rxConfig()->rssi_source == RSSI_SOURCE_AUTO) {
357 if (rxConfig()->rssi_channel > 0) {
358 activeRssiSource = RSSI_SOURCE_RX_CHANNEL;
359 return;
363 if (rxConfig()->rssi_source == RSSI_SOURCE_RX_PROTOCOL || rxConfig()->rssi_source == RSSI_SOURCE_AUTO) {
364 activeRssiSource = RSSI_SOURCE_RX_PROTOCOL;
365 return;
369 uint8_t calculateChannelRemapping(const uint8_t *channelMap, uint8_t channelMapEntryCount, uint8_t channelToRemap)
371 if (channelToRemap < channelMapEntryCount) {
372 return channelMap[channelToRemap];
374 return channelToRemap;
377 bool rxIsReceivingSignal(void)
379 return rxSignalReceived;
382 bool rxAreFlightChannelsValid(void)
384 return rxFlightChannelsValid;
387 void suspendRxSignal(void)
389 failsafeOnRxSuspend();
390 isRxSuspended = true;
393 void resumeRxSignal(void)
395 isRxSuspended = false;
396 failsafeOnRxResume();
399 bool rxUpdateCheck(timeUs_t currentTimeUs, timeDelta_t currentDeltaTime)
401 UNUSED(currentDeltaTime);
403 if (rxSignalReceived) {
404 if (currentTimeUs >= needRxSignalBefore) {
405 rxSignalReceived = false;
409 const uint8_t frameStatus = rxRuntimeConfig.rcFrameStatusFn(&rxRuntimeConfig);
411 if (frameStatus & RX_FRAME_COMPLETE) {
412 // RX_FRAME_COMPLETE updated the failsafe status regardless
413 rxSignalReceived = (frameStatus & RX_FRAME_FAILSAFE) == 0;
414 needRxSignalBefore = currentTimeUs + rxRuntimeConfig.rxSignalTimeout;
415 rxDataProcessingRequired = true;
417 else if ((frameStatus & RX_FRAME_FAILSAFE) && rxSignalReceived) {
418 // All other receiver statuses are allowed to report failsafe, but not allowed to leave it
419 rxSignalReceived = false;
422 if (frameStatus & RX_FRAME_PROCESSING_REQUIRED) {
423 auxiliaryProcessingRequired = true;
426 if (cmpTimeUs(currentTimeUs, rxNextUpdateAtUs) > 0) {
427 rxDataProcessingRequired = true;
430 bool result = rxDataProcessingRequired || auxiliaryProcessingRequired;
432 #if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
433 if (rxConfig()->receiverType != RX_TYPE_MSP) {
434 mspOverrideDataProcessingRequired = mspOverrideUpdateCheck(currentTimeUs, currentDeltaTime);
435 result = result || mspOverrideDataProcessingRequired;
437 #endif
439 return result;
442 bool calculateRxChannelsAndUpdateFailsafe(timeUs_t currentTimeUs)
444 int16_t rcStaging[MAX_SUPPORTED_RC_CHANNEL_COUNT];
445 const timeMs_t currentTimeMs = millis();
447 #if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
448 if ((rxConfig()->receiverType != RX_TYPE_MSP) && mspOverrideDataProcessingRequired) {
449 mspOverrideCalculateChannels(currentTimeUs);
451 #endif
453 if (auxiliaryProcessingRequired) {
454 auxiliaryProcessingRequired = !rxRuntimeConfig.rcProcessFrameFn(&rxRuntimeConfig);
457 if (!rxDataProcessingRequired) {
458 return false;
461 rxDataProcessingRequired = false;
462 rxNextUpdateAtUs = currentTimeUs + DELAY_10_HZ;
464 // If RX is suspended, do not process any data
465 if (isRxSuspended) {
466 return true;
469 rxFlightChannelsValid = true;
471 // Read and process channel data
472 for (int channel = 0; channel < rxChannelCount; channel++) {
473 const uint8_t rawChannel = calculateChannelRemapping(rxConfig()->rcmap, REMAPPABLE_CHANNEL_COUNT, channel);
475 // sample the channel
476 uint16_t sample = (*rxRuntimeConfig.rcReadRawFn)(&rxRuntimeConfig, rawChannel);
478 // apply the rx calibration to flight channel
479 if (channel < NON_AUX_CHANNEL_COUNT && sample != 0) {
480 sample = scaleRange(sample, rxChannelRangeConfigs(channel)->min, rxChannelRangeConfigs(channel)->max, PWM_RANGE_MIN, PWM_RANGE_MAX);
481 sample = MIN(MAX(PWM_PULSE_MIN, sample), PWM_PULSE_MAX);
484 // Store as rxRaw
485 rcChannels[channel].raw = sample;
487 // Apply invalid pulse value logic
488 if (!isRxPulseValid(sample)) {
489 sample = rcChannels[channel].data; // hold channel, replace with old value
490 if ((currentTimeMs > rcChannels[channel].expiresAt) && (channel < NON_AUX_CHANNEL_COUNT)) {
491 rxFlightChannelsValid = false;
493 } else {
494 rcChannels[channel].expiresAt = currentTimeMs + MAX_INVALID_RX_PULSE_TIME;
497 // Save channel value
498 rcStaging[channel] = sample;
501 // Update channel input value if receiver is not in failsafe mode
502 // If receiver is in failsafe (not receiving signal or sending invalid channel values) - last good input values are retained
503 if (rxFlightChannelsValid && rxSignalReceived) {
504 for (int channel = 0; channel < rxChannelCount; channel++) {
505 rcChannels[channel].data = rcStaging[channel];
509 #if defined(USE_RX_MSP) && defined(USE_MSP_RC_OVERRIDE)
510 if (IS_RC_MODE_ACTIVE(BOXMSPRCOVERRIDE) && !mspOverrideIsInFailsafe()) {
511 mspOverrideChannels(rcChannels);
513 #endif
515 // Update failsafe
516 if (rxFlightChannelsValid && rxSignalReceived) {
517 failsafeOnValidDataReceived();
518 } else {
519 failsafeOnValidDataFailed();
522 rcSampleIndex++;
523 return true;
526 void parseRcChannels(const char *input)
528 for (const char *c = input; *c; c++) {
529 const char *s = strchr(rcChannelLetters, *c);
530 if (s && (s < rcChannelLetters + MAX_MAPPABLE_RX_INPUTS))
531 rxConfigMutable()->rcmap[s - rcChannelLetters] = c - input;
535 #define RSSI_SAMPLE_COUNT 16
537 static void setRSSIValue(uint16_t rssiValue, rssiSource_e source, bool filtered)
539 if (source != activeRssiSource) {
540 return;
543 static uint16_t rssiSamples[RSSI_SAMPLE_COUNT];
544 static uint8_t rssiSampleIndex = 0;
545 static unsigned sum = 0;
547 if (filtered) {
548 // Value is already filtered
549 rssi = rssiValue;
551 } else {
552 sum = sum + rssiValue;
553 sum = sum - rssiSamples[rssiSampleIndex];
554 rssiSamples[rssiSampleIndex] = rssiValue;
555 rssiSampleIndex = (rssiSampleIndex + 1) % RSSI_SAMPLE_COUNT;
557 int16_t rssiMean = sum / RSSI_SAMPLE_COUNT;
559 rssi = rssiMean;
562 // Apply min/max values
563 int rssiMin = rxConfig()->rssiMin * RSSI_VISIBLE_FACTOR;
564 int rssiMax = rxConfig()->rssiMax * RSSI_VISIBLE_FACTOR;
565 if (rssiMin > rssiMax) {
566 int tmp = rssiMax;
567 rssiMax = rssiMin;
568 rssiMin = tmp;
569 int delta = rssi >= rssiMin ? rssi - rssiMin : 0;
570 rssi = rssiMax >= delta ? rssiMax - delta : 0;
572 rssi = constrain(scaleRange(rssi, rssiMin, rssiMax, 0, RSSI_MAX_VALUE), 0, RSSI_MAX_VALUE);
575 void setRSSIFromMSP(uint8_t newMspRssi)
577 if (activeRssiSource == RSSI_SOURCE_NONE && (rxConfig()->rssi_source == RSSI_SOURCE_MSP || rxConfig()->rssi_source == RSSI_SOURCE_AUTO)) {
578 activeRssiSource = RSSI_SOURCE_MSP;
581 if (activeRssiSource == RSSI_SOURCE_MSP) {
582 rssi = ((uint16_t)newMspRssi) << 2;
583 lastMspRssiUpdateUs = micros();
587 static void updateRSSIFromChannel(void)
589 if (rxConfig()->rssi_channel > 0) {
590 int pwmRssi = rcChannels[rxConfig()->rssi_channel - 1].raw;
591 int rawRSSI = (uint16_t)((constrain(pwmRssi - 1000, 0, 1000) / 1000.0f) * (RSSI_MAX_VALUE * 1.0f));
592 setRSSIValue(rawRSSI, RSSI_SOURCE_RX_CHANNEL, false);
596 static void updateRSSIFromADC(void)
598 #ifdef USE_ADC
599 uint16_t rawRSSI = adcGetChannel(ADC_RSSI) / 4; // Reduce to [0;1023]
600 setRSSIValue(rawRSSI, RSSI_SOURCE_ADC, false);
601 #else
602 setRSSIValue(0, RSSI_SOURCE_ADC, false);
603 #endif
606 static void updateRSSIFromProtocol(void)
608 setRSSIValue(lqTrackerGet(&rxLQTracker), RSSI_SOURCE_RX_PROTOCOL, false);
611 void updateRSSI(timeUs_t currentTimeUs)
613 // Read RSSI
614 switch (activeRssiSource) {
615 case RSSI_SOURCE_ADC:
616 updateRSSIFromADC();
617 break;
618 case RSSI_SOURCE_RX_CHANNEL:
619 updateRSSIFromChannel();
620 break;
621 case RSSI_SOURCE_RX_PROTOCOL:
622 updateRSSIFromProtocol();
623 break;
624 case RSSI_SOURCE_MSP:
625 if (cmpTimeUs(currentTimeUs, lastMspRssiUpdateUs) > MSP_RSSI_TIMEOUT_US) {
626 rssi = 0;
628 break;
629 default:
630 rssi = 0;
631 break;
635 uint16_t getRSSI(void)
637 return rssi;
640 rssiSource_e getRSSISource(void)
642 return activeRssiSource;
645 int16_t rxGetChannelValue(unsigned channelNumber)
647 if (LOGIC_CONDITION_GLOBAL_FLAG(LOGIC_CONDITION_GLOBAL_FLAG_OVERRIDE_RC_CHANNEL)) {
648 return getRcChannelOverride(channelNumber, rcChannels[channelNumber].data);
649 } else {
650 return rcChannels[channelNumber].data;
654 void lqTrackerReset(rxLinkQualityTracker_e * lqTracker)
656 lqTracker->lastUpdatedMs = millis();
657 lqTracker->lqAccumulator = 0;
658 lqTracker->lqCount = 0;
659 lqTracker->lqValue = 0;
662 void lqTrackerAccumulate(rxLinkQualityTracker_e * lqTracker, uint16_t rawValue)
664 const timeMs_t currentTimeMs = millis();
666 if (((currentTimeMs - lqTracker->lastUpdatedMs) > RX_LQ_INTERVAL_MS) && lqTracker->lqCount) {
667 lqTrackerSet(lqTracker, lqTracker->lqAccumulator / lqTracker->lqCount);
668 lqTracker->lqAccumulator = 0;
669 lqTracker->lqCount = 0;
672 lqTracker->lqAccumulator += rawValue;
673 lqTracker->lqCount += 1;
676 void lqTrackerSet(rxLinkQualityTracker_e * lqTracker, uint16_t rawValue)
678 lqTracker->lqValue = rawValue;
679 lqTracker->lastUpdatedMs = millis();
682 uint16_t lqTrackerGet(rxLinkQualityTracker_e * lqTracker)
684 if ((millis() - lqTracker->lastUpdatedMs) > RX_LQ_TIMEOUT_MS) {
685 lqTracker->lqValue = 0;
688 return lqTracker->lqValue;