2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
29 #include "build/build_config.h"
30 #include "build/debug.h"
32 #include "common/maths.h"
33 #include "common/utils.h"
34 #include "common/filter.h"
36 #include "config/config.h"
37 #include "config/config_reset.h"
38 #include "config/feature.h"
40 #include "drivers/adc.h"
41 #include "drivers/rx/rx_pwm.h"
42 #include "drivers/time.h"
44 #include "fc/rc_controls.h"
45 #include "fc/rc_modes.h"
46 #include "fc/runtime_config.h"
49 #include "flight/failsafe.h"
51 #include "io/serial.h"
54 #include "pg/pg_ids.h"
61 #include "rx/spektrum.h"
68 #include "rx/jetiexbus.h"
71 #include "rx/rx_spi.h"
72 #include "rx/targetcustomserial.h"
73 #include "rx/msp_override.h"
76 const char rcChannelLetters
[] = "AERT12345678abcdefgh";
78 static uint16_t rssi
= 0; // range: [0;1023]
79 static uint16_t rssiRaw
= 0; // range: [0;1023]
80 static timeUs_t lastRssiSmoothingUs
= 0;
81 #ifdef USE_RX_RSSI_DBM
82 static int8_t activeAntenna
;
83 static int16_t rssiDbm
= CRSF_RSSI_MIN
; // range: [-130,0]
84 static int16_t rssiDbmRaw
= CRSF_RSSI_MIN
; // range: [-130,0]
85 #endif //USE_RX_RSSI_DBM
87 static int16_t rsnr
= CRSF_SNR_MIN
; // range: [-30,20]
88 static int16_t rsnrRaw
= CRSF_SNR_MIN
; // range: [-30,20]
90 static timeUs_t lastMspRssiUpdateUs
= 0;
92 static pt1Filter_t frameErrFilter
;
93 static pt1Filter_t rssiFilter
;
94 #ifdef USE_RX_RSSI_DBM
95 static pt1Filter_t rssiDbmFilter
;
96 #endif //USE_RX_RSSI_DBM
98 static pt1Filter_t rsnrFilter
;
101 #ifdef USE_RX_LINK_QUALITY_INFO
102 static uint16_t linkQuality
= 0;
103 static uint8_t rfMode
= 0;
106 #ifdef USE_RX_LINK_UPLINK_POWER
107 static uint16_t uplinkTxPwrMw
= 0; //Uplink Tx power in mW
110 #define RSSI_ADC_DIVISOR (4096 / 1024)
111 #define RSSI_OFFSET_SCALING (1024 / 100.0f)
113 rssiSource_e rssiSource
;
114 linkQualitySource_e linkQualitySource
;
116 static bool rxDataProcessingRequired
= false;
117 static bool auxiliaryProcessingRequired
= false;
119 static bool rxSignalReceived
= false;
120 static bool rxFlightChannelsValid
= false;
121 static uint8_t rxChannelCount
;
123 static timeUs_t needRxSignalBefore
= 0;
124 static timeUs_t suspendRxSignalUntil
= 0;
125 static uint8_t skipRxSamples
= 0;
127 static float rcRaw
[MAX_SUPPORTED_RC_CHANNEL_COUNT
]; // last received raw value, as it comes
128 float rcData
[MAX_SUPPORTED_RC_CHANNEL_COUNT
]; // scaled, modified, checked and constrained values
129 uint32_t validRxSignalTimeout
[MAX_SUPPORTED_RC_CHANNEL_COUNT
];
131 #define MAX_INVALID_PULSE_TIME_MS 300 // hold time in milliseconds after bad channel or Rx link loss
132 // will not be actioned until the nearest multiple of 100ms
133 #define PPM_AND_PWM_SAMPLE_COUNT 3
135 #define DELAY_20_MS (20 * 1000) // 20ms in us
136 #define DELAY_100_MS (100 * 1000) // 100ms in us
137 #define DELAY_1500_MS (1500 * 1000) // 1.5 seconds in us
138 #define SKIP_RC_SAMPLES_ON_RESUME 2 // flush 2 samples to drop wrong measurements (timing independent)
140 rxRuntimeState_t rxRuntimeState
;
141 static uint8_t rcSampleIndex
= 0;
143 PG_REGISTER_ARRAY_WITH_RESET_FN(rxChannelRangeConfig_t
, NON_AUX_CHANNEL_COUNT
, rxChannelRangeConfigs
, PG_RX_CHANNEL_RANGE_CONFIG
, 0);
144 void pgResetFn_rxChannelRangeConfigs(rxChannelRangeConfig_t
*rxChannelRangeConfigs
)
146 // set default calibration to full range and 1:1 mapping
147 for (int i
= 0; i
< NON_AUX_CHANNEL_COUNT
; i
++) {
148 rxChannelRangeConfigs
[i
].min
= PWM_RANGE_MIN
;
149 rxChannelRangeConfigs
[i
].max
= PWM_RANGE_MAX
;
153 PG_REGISTER_ARRAY_WITH_RESET_FN(rxFailsafeChannelConfig_t
, MAX_SUPPORTED_RC_CHANNEL_COUNT
, rxFailsafeChannelConfigs
, PG_RX_FAILSAFE_CHANNEL_CONFIG
, 0);
154 void pgResetFn_rxFailsafeChannelConfigs(rxFailsafeChannelConfig_t
*rxFailsafeChannelConfigs
)
156 for (int i
= 0; i
< MAX_SUPPORTED_RC_CHANNEL_COUNT
; i
++) {
157 rxFailsafeChannelConfigs
[i
].mode
= (i
< NON_AUX_CHANNEL_COUNT
) ? RX_FAILSAFE_MODE_AUTO
: RX_FAILSAFE_MODE_HOLD
;
158 rxFailsafeChannelConfigs
[i
].step
= (i
== THROTTLE
)
159 ? CHANNEL_VALUE_TO_RXFAIL_STEP(RX_MIN_USEC
)
160 : CHANNEL_VALUE_TO_RXFAIL_STEP(RX_MID_USEC
);
164 void resetAllRxChannelRangeConfigurations(rxChannelRangeConfig_t
*rxChannelRangeConfig
)
166 // set default calibration to full range and 1:1 mapping
167 for (int i
= 0; i
< NON_AUX_CHANNEL_COUNT
; i
++) {
168 rxChannelRangeConfig
->min
= PWM_RANGE_MIN
;
169 rxChannelRangeConfig
->max
= PWM_RANGE_MAX
;
170 rxChannelRangeConfig
++;
174 static float nullReadRawRC(const rxRuntimeState_t
*rxRuntimeState
, uint8_t channel
)
176 UNUSED(rxRuntimeState
);
179 return PPM_RCVR_TIMEOUT
;
182 static uint8_t nullFrameStatus(rxRuntimeState_t
*rxRuntimeState
)
184 UNUSED(rxRuntimeState
);
186 return RX_FRAME_PENDING
;
189 static bool nullProcessFrame(const rxRuntimeState_t
*rxRuntimeState
)
191 UNUSED(rxRuntimeState
);
196 STATIC_UNIT_TESTED
bool isPulseValid(uint16_t pulseDuration
)
198 return pulseDuration
>= rxConfig()->rx_min_usec
&&
199 pulseDuration
<= rxConfig()->rx_max_usec
;
203 static bool serialRxInit(const rxConfig_t
*rxConfig
, rxRuntimeState_t
*rxRuntimeState
)
205 bool enabled
= false;
206 switch (rxRuntimeState
->serialrxProvider
) {
207 #ifdef USE_SERIALRX_SRXL2
209 enabled
= srxl2RxInit(rxConfig
, rxRuntimeState
);
212 #ifdef USE_SERIALRX_SPEKTRUM
214 case SERIALRX_SPEKTRUM1024
:
215 case SERIALRX_SPEKTRUM2048
:
216 enabled
= spektrumInit(rxConfig
, rxRuntimeState
);
219 #ifdef USE_SERIALRX_SBUS
221 enabled
= sbusInit(rxConfig
, rxRuntimeState
);
224 #ifdef USE_SERIALRX_SUMD
226 enabled
= sumdInit(rxConfig
, rxRuntimeState
);
229 #ifdef USE_SERIALRX_SUMH
231 enabled
= sumhInit(rxConfig
, rxRuntimeState
);
234 #ifdef USE_SERIALRX_XBUS
235 case SERIALRX_XBUS_MODE_B
:
236 case SERIALRX_XBUS_MODE_B_RJ01
:
237 enabled
= xBusInit(rxConfig
, rxRuntimeState
);
240 #ifdef USE_SERIALRX_IBUS
242 enabled
= ibusInit(rxConfig
, rxRuntimeState
);
245 #ifdef USE_SERIALRX_JETIEXBUS
246 case SERIALRX_JETIEXBUS
:
247 enabled
= jetiExBusInit(rxConfig
, rxRuntimeState
);
250 #ifdef USE_SERIALRX_CRSF
252 enabled
= crsfRxInit(rxConfig
, rxRuntimeState
);
255 #ifdef USE_SERIALRX_GHST
257 enabled
= ghstRxInit(rxConfig
, rxRuntimeState
);
260 #ifdef USE_SERIALRX_TARGET_CUSTOM
261 case SERIALRX_TARGET_CUSTOM
:
262 enabled
= targetCustomSerialRxInit(rxConfig
, rxRuntimeState
);
265 #ifdef USE_SERIALRX_FPORT
267 enabled
= fportRxInit(rxConfig
, rxRuntimeState
);
280 if (featureIsEnabled(FEATURE_RX_PARALLEL_PWM
)) {
281 rxRuntimeState
.rxProvider
= RX_PROVIDER_PARALLEL_PWM
;
282 } else if (featureIsEnabled(FEATURE_RX_PPM
)) {
283 rxRuntimeState
.rxProvider
= RX_PROVIDER_PPM
;
284 } else if (featureIsEnabled(FEATURE_RX_SERIAL
)) {
285 rxRuntimeState
.rxProvider
= RX_PROVIDER_SERIAL
;
286 } else if (featureIsEnabled(FEATURE_RX_MSP
)) {
287 rxRuntimeState
.rxProvider
= RX_PROVIDER_MSP
;
288 } else if (featureIsEnabled(FEATURE_RX_SPI
)) {
289 rxRuntimeState
.rxProvider
= RX_PROVIDER_SPI
;
291 rxRuntimeState
.rxProvider
= RX_PROVIDER_NONE
;
293 rxRuntimeState
.serialrxProvider
= rxConfig()->serialrx_provider
;
294 rxRuntimeState
.rcReadRawFn
= nullReadRawRC
;
295 rxRuntimeState
.rcFrameStatusFn
= nullFrameStatus
;
296 rxRuntimeState
.rcProcessFrameFn
= nullProcessFrame
;
297 rxRuntimeState
.lastRcFrameTimeUs
= 0;
300 uint32_t now
= millis();
301 for (int i
= 0; i
< MAX_SUPPORTED_RC_CHANNEL_COUNT
; i
++) {
302 rcData
[i
] = rxConfig()->midrc
;
303 validRxSignalTimeout
[i
] = now
+ MAX_INVALID_PULSE_TIME_MS
;
306 rcData
[THROTTLE
] = (featureIsEnabled(FEATURE_3D
)) ? rxConfig()->midrc
: rxConfig()->rx_min_usec
;
308 // Initialize ARM switch to OFF position when arming via switch is defined
309 // TODO - move to rc_mode.c
310 for (int i
= 0; i
< MAX_MODE_ACTIVATION_CONDITION_COUNT
; i
++) {
311 const modeActivationCondition_t
*modeActivationCondition
= modeActivationConditions(i
);
312 if (modeActivationCondition
->modeId
== BOXARM
&& IS_RANGE_USABLE(&modeActivationCondition
->range
)) {
313 // ARM switch is defined, determine an OFF value
315 if (modeActivationCondition
->range
.startStep
> 0) {
316 value
= MODE_STEP_TO_CHANNEL_VALUE((modeActivationCondition
->range
.startStep
- 1));
318 value
= MODE_STEP_TO_CHANNEL_VALUE((modeActivationCondition
->range
.endStep
+ 1));
320 // Initialize ARM AUX channel to OFF value
321 rcData
[modeActivationCondition
->auxChannelIndex
+ NON_AUX_CHANNEL_COUNT
] = value
;
325 switch (rxRuntimeState
.rxProvider
) {
330 case RX_PROVIDER_SERIAL
:
332 const bool enabled
= serialRxInit(rxConfig(), &rxRuntimeState
);
334 rxRuntimeState
.rcReadRawFn
= nullReadRawRC
;
335 rxRuntimeState
.rcFrameStatusFn
= nullFrameStatus
;
343 case RX_PROVIDER_MSP
:
344 rxMspInit(rxConfig(), &rxRuntimeState
);
350 case RX_PROVIDER_SPI
:
352 const bool enabled
= rxSpiInit(rxSpiConfig(), &rxRuntimeState
);
354 rxRuntimeState
.rcReadRawFn
= nullReadRawRC
;
355 rxRuntimeState
.rcFrameStatusFn
= nullFrameStatus
;
362 #if defined(USE_RX_PWM) || defined(USE_RX_PPM)
363 case RX_PROVIDER_PPM
:
364 case RX_PROVIDER_PARALLEL_PWM
:
365 rxPwmInit(rxConfig(), &rxRuntimeState
);
372 if (featureIsEnabled(FEATURE_RSSI_ADC
)) {
373 rssiSource
= RSSI_SOURCE_ADC
;
376 if (rxConfig()->rssi_channel
> 0) {
377 rssiSource
= RSSI_SOURCE_RX_CHANNEL
;
380 // Setup source frame RSSI filtering to take averaged values every FRAME_ERR_RESAMPLE_US
381 pt1FilterInit(&frameErrFilter
, pt1FilterGain(GET_FRAME_ERR_LPF_FREQUENCY(rxConfig()->rssi_src_frame_lpf_period
), FRAME_ERR_RESAMPLE_US
* 1e-6f
));
383 // Configurable amount of filtering to remove excessive jumpiness of the values on the osd
384 float k
= (256.0f
- rxConfig()->rssi_smoothing
) / 256.0f
;
386 pt1FilterInit(&rssiFilter
, k
);
388 #ifdef USE_RX_RSSI_DBM
389 pt1FilterInit(&rssiDbmFilter
, k
);
390 #endif //USE_RX_RSSI_DBM
393 pt1FilterInit(&rsnrFilter
, k
);
396 rxChannelCount
= MIN(rxConfig()->max_aux_channel
+ NON_AUX_CHANNEL_COUNT
, rxRuntimeState
.channelCount
);
399 bool rxIsReceivingSignal(void)
401 return rxSignalReceived
;
404 bool rxAreFlightChannelsValid(void)
406 return rxFlightChannelsValid
;
409 void suspendRxSignal(void)
411 #if defined(USE_RX_PWM) || defined(USE_RX_PPM)
412 if (rxRuntimeState
.rxProvider
== RX_PROVIDER_PARALLEL_PWM
|| rxRuntimeState
.rxProvider
== RX_PROVIDER_PPM
) {
413 suspendRxSignalUntil
= micros() + DELAY_1500_MS
; // 1.5s
414 skipRxSamples
= SKIP_RC_SAMPLES_ON_RESUME
;
417 failsafeOnRxSuspend(DELAY_1500_MS
); // 1.5s
420 void resumeRxSignal(void)
422 #if defined(USE_RX_PWM) || defined(USE_RX_PPM)
423 if (rxRuntimeState
.rxProvider
== RX_PROVIDER_PARALLEL_PWM
|| rxRuntimeState
.rxProvider
== RX_PROVIDER_PPM
) {
424 suspendRxSignalUntil
= micros();
425 skipRxSamples
= SKIP_RC_SAMPLES_ON_RESUME
;
428 failsafeOnRxResume();
431 #ifdef USE_RX_LINK_QUALITY_INFO
432 #define LINK_QUALITY_SAMPLE_COUNT 16
434 STATIC_UNIT_TESTED
uint16_t updateLinkQualitySamples(uint16_t value
)
436 static uint16_t samples
[LINK_QUALITY_SAMPLE_COUNT
];
437 static uint8_t sampleIndex
= 0;
438 static uint16_t sum
= 0;
440 sum
+= value
- samples
[sampleIndex
];
441 samples
[sampleIndex
] = value
;
442 sampleIndex
= (sampleIndex
+ 1) % LINK_QUALITY_SAMPLE_COUNT
;
443 return sum
/ LINK_QUALITY_SAMPLE_COUNT
;
446 void rxSetRfMode(uint8_t rfModeValue
)
448 rfMode
= rfModeValue
;
452 static void setLinkQuality(bool validFrame
, timeDelta_t currentDeltaTimeUs
)
454 static uint16_t rssiSum
= 0;
455 static uint16_t rssiCount
= 0;
456 static timeDelta_t resampleTimeUs
= 0;
458 #ifdef USE_RX_LINK_QUALITY_INFO
459 if (linkQualitySource
== LQ_SOURCE_NONE
) {
460 // calculate new sample mean
461 linkQuality
= updateLinkQualitySamples(validFrame
? LINK_QUALITY_MAX_VALUE
: 0);
465 if (rssiSource
== RSSI_SOURCE_FRAME_ERRORS
) {
466 resampleTimeUs
+= currentDeltaTimeUs
;
467 rssiSum
+= validFrame
? RSSI_MAX_VALUE
: 0;
470 if (resampleTimeUs
>= FRAME_ERR_RESAMPLE_US
) {
471 setRssi(rssiSum
/ rssiCount
, rssiSource
);
474 resampleTimeUs
-= FRAME_ERR_RESAMPLE_US
;
479 void setLinkQualityDirect(uint16_t linkqualityValue
)
481 #ifdef USE_RX_LINK_QUALITY_INFO
482 linkQuality
= linkqualityValue
;
484 UNUSED(linkqualityValue
);
488 #ifdef USE_RX_LINK_UPLINK_POWER
489 void rxSetUplinkTxPwrMw(uint16_t uplinkTxPwrMwValue
)
491 uplinkTxPwrMw
= uplinkTxPwrMwValue
;
495 bool rxUpdateCheck(timeUs_t currentTimeUs
, timeDelta_t currentDeltaTimeUs
)
497 UNUSED(currentTimeUs
);
498 UNUSED(currentDeltaTimeUs
);
500 return taskUpdateRxMainInProgress() || rxDataProcessingRequired
|| auxiliaryProcessingRequired
;
503 FAST_CODE_NOINLINE
void rxFrameCheck(timeUs_t currentTimeUs
, timeDelta_t currentDeltaTimeUs
)
505 bool signalReceived
= false;
506 bool useDataDrivenProcessing
= true;
507 timeDelta_t needRxSignalMaxDelayUs
= DELAY_100_MS
;
509 DEBUG_SET(DEBUG_RX_SIGNAL_LOSS
, 2, MIN(2000, currentDeltaTimeUs
/ 100));
511 if (taskUpdateRxMainInProgress()) {
512 // no need to check for new data as a packet is being processed already
516 switch (rxRuntimeState
.rxProvider
) {
520 #if defined(USE_RX_PWM) || defined(USE_RX_PPM)
521 case RX_PROVIDER_PPM
:
522 if (isPPMDataBeingReceived()) {
523 signalReceived
= true;
524 resetPPMDataReceivedState();
528 case RX_PROVIDER_PARALLEL_PWM
:
529 if (isPWMDataBeingReceived()) {
530 signalReceived
= true;
531 useDataDrivenProcessing
= false;
536 case RX_PROVIDER_SERIAL
:
537 case RX_PROVIDER_MSP
:
538 case RX_PROVIDER_SPI
:
539 case RX_PROVIDER_UDP
:
541 const uint8_t frameStatus
= rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
);
542 DEBUG_SET(DEBUG_RX_SIGNAL_LOSS
, 1, (frameStatus
& RX_FRAME_FAILSAFE
));
543 signalReceived
= (frameStatus
& RX_FRAME_COMPLETE
) && !(frameStatus
& (RX_FRAME_FAILSAFE
| RX_FRAME_DROPPED
));
544 setLinkQuality(signalReceived
, currentDeltaTimeUs
);
545 auxiliaryProcessingRequired
|= (frameStatus
& RX_FRAME_PROCESSING_REQUIRED
);
551 if (signalReceived
) {
552 // true only when a new packet arrives
553 needRxSignalBefore
= currentTimeUs
+ needRxSignalMaxDelayUs
;
554 rxSignalReceived
= true; // immediately process packet data
555 if (useDataDrivenProcessing
) {
556 rxDataProcessingRequired
= true;
557 // process the new Rx packet when it arrives
560 // watch for next packet
561 if (cmpTimeUs(currentTimeUs
, needRxSignalBefore
) > 0) {
562 // initial time to signalReceived failure is 100ms, then we check every 100ms
563 rxSignalReceived
= false;
564 needRxSignalBefore
= currentTimeUs
+ needRxSignalMaxDelayUs
;
565 // review and process rcData values every 100ms in case failsafe changed them
566 rxDataProcessingRequired
= true;
570 #if defined(USE_RX_MSP_OVERRIDE)
571 if (IS_RC_MODE_ACTIVE(BOXMSPOVERRIDE
) && rxConfig()->msp_override_channels_mask
&& rxConfig()->msp_override_failsafe
) {
572 if (rxMspOverrideFrameStatus() & RX_FRAME_COMPLETE
) {
573 rxSignalReceived
= true;
574 rxDataProcessingRequired
= true;
575 needRxSignalBefore
= currentTimeUs
+ needRxSignalMaxDelayUs
;
580 DEBUG_SET(DEBUG_FAILSAFE
, 1, rxSignalReceived
);
581 DEBUG_SET(DEBUG_RX_SIGNAL_LOSS
, 0, rxSignalReceived
);
584 #if defined(USE_RX_PWM) || defined(USE_RX_PPM)
585 static uint16_t calculateChannelMovingAverage(uint8_t chan
, uint16_t sample
)
587 static int16_t rcSamples
[MAX_SUPPORTED_RX_PARALLEL_PWM_OR_PPM_CHANNEL_COUNT
][PPM_AND_PWM_SAMPLE_COUNT
];
588 static int16_t rcDataMean
[MAX_SUPPORTED_RX_PARALLEL_PWM_OR_PPM_CHANNEL_COUNT
];
589 static bool rxSamplesCollected
= false;
591 const uint8_t currentSampleIndex
= rcSampleIndex
% PPM_AND_PWM_SAMPLE_COUNT
;
593 // update the recent samples and compute the average of them
594 rcSamples
[chan
][currentSampleIndex
] = sample
;
596 // avoid returning an incorrect average which would otherwise occur before enough samples
597 if (!rxSamplesCollected
) {
598 if (rcSampleIndex
< PPM_AND_PWM_SAMPLE_COUNT
) {
601 rxSamplesCollected
= true;
604 rcDataMean
[chan
] = 0;
605 for (int sampleIndex
= 0; sampleIndex
< PPM_AND_PWM_SAMPLE_COUNT
; sampleIndex
++) {
606 rcDataMean
[chan
] += rcSamples
[chan
][sampleIndex
];
608 return rcDataMean
[chan
] / PPM_AND_PWM_SAMPLE_COUNT
;
612 static uint16_t getRxfailValue(uint8_t channel
)
614 const rxFailsafeChannelConfig_t
*channelFailsafeConfig
= rxFailsafeChannelConfigs(channel
);
615 const bool boxFailsafeSwitchIsOn
= IS_RC_MODE_ACTIVE(BOXFAILSAFE
);
617 switch (channelFailsafeConfig
->mode
) {
618 case RX_FAILSAFE_MODE_AUTO
:
623 return rxConfig()->midrc
;
625 if (featureIsEnabled(FEATURE_3D
) && !IS_RC_MODE_ACTIVE(BOX3D
) && !flight3DConfig()->switched_mode3d
) {
626 return rxConfig()->midrc
;
628 return rxConfig()->rx_min_usec
;
634 case RX_FAILSAFE_MODE_INVALID
:
635 case RX_FAILSAFE_MODE_HOLD
:
636 if (boxFailsafeSwitchIsOn
) {
637 return rcRaw
[channel
]; // current values are allowed through on held channels with switch induced failsafe
639 return rcData
[channel
]; // last good value
641 case RX_FAILSAFE_MODE_SET
:
642 return RXFAIL_STEP_TO_CHANNEL_VALUE(channelFailsafeConfig
->step
);
646 STATIC_UNIT_TESTED
float applyRxChannelRangeConfiguraton(float sample
, const rxChannelRangeConfig_t
*range
)
648 // Avoid corruption of channel with a value of PPM_RCVR_TIMEOUT
649 if (sample
== PPM_RCVR_TIMEOUT
) {
650 return PPM_RCVR_TIMEOUT
;
653 sample
= scaleRangef(sample
, range
->min
, range
->max
, PWM_RANGE_MIN
, PWM_RANGE_MAX
);
654 // out of range channel values are now constrained after the validity check in detectAndApplySignalLossBehaviour()
658 static void readRxChannelsApplyRanges(void)
660 for (int channel
= 0; channel
< rxChannelCount
; channel
++) {
662 const uint8_t rawChannel
= channel
< RX_MAPPABLE_CHANNEL_COUNT
? rxConfig()->rcmap
[channel
] : channel
;
664 // sample the channel
666 #if defined(USE_RX_MSP_OVERRIDE)
667 if (rxConfig()->msp_override_channels_mask
) {
668 sample
= rxMspOverrideReadRawRc(&rxRuntimeState
, rxConfig(), rawChannel
);
672 sample
= rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, rawChannel
);
675 // apply the rx calibration
676 if (channel
< NON_AUX_CHANNEL_COUNT
) {
677 sample
= applyRxChannelRangeConfiguraton(sample
, rxChannelRangeConfigs(channel
));
680 rcRaw
[channel
] = sample
;
684 void detectAndApplySignalLossBehaviour(void)
686 const uint32_t currentTimeMs
= millis();
687 const bool boxFailsafeSwitchIsOn
= IS_RC_MODE_ACTIVE(BOXFAILSAFE
);
688 rxFlightChannelsValid
= rxSignalReceived
&& !boxFailsafeSwitchIsOn
;
689 // rxFlightChannelsValid is false after 100ms of no packets, or as soon as use the BOXFAILSAFE switch is actioned
690 // rxFlightChannelsValid is true the instant we get a good packet or the BOXFAILSAFE switch is reverted
691 // can also go false with good packets but where one flight channel is bad > 300ms (PPM type receiver error)
693 for (int channel
= 0; channel
< rxChannelCount
; channel
++) {
694 float sample
= rcRaw
[channel
]; // sample has latest RC value, rcData has last 'accepted valid' value
695 const bool thisChannelValid
= rxFlightChannelsValid
&& isPulseValid(sample
);
696 // if the whole packet is bad, or BOXFAILSAFE switch is actioned, consider all channels bad
697 if (thisChannelValid
) {
698 // reset the invalid pulse period timer for every good channel
699 validRxSignalTimeout
[channel
] = currentTimeMs
+ MAX_INVALID_PULSE_TIME_MS
;
702 if (failsafeIsActive()) {
703 // we are in failsafe Stage 2, whether Rx loss or BOXFAILSAFE induced
704 // pass valid incoming flight channel values to FC,
705 // so that GPS Rescue can get the 30% requirement for termination of the rescue
706 if (channel
< NON_AUX_CHANNEL_COUNT
) {
707 if (!thisChannelValid
) {
708 if (channel
== THROTTLE
) {
709 sample
= failsafeConfig()->failsafe_throttle
;
710 // stage 2 failsafe throttle value. In GPS Rescue Flight mode, gpsRescueGetThrottle overrides, late in mixer.c
712 sample
= rxConfig()->midrc
;
716 // set aux channels as per Stage 1 failsafe hold/set values, allow all for Failsafe and GPS rescue MODE switches
717 sample
= getRxfailValue(channel
);
720 // we are normal, or in failsafe stage 1
721 if (boxFailsafeSwitchIsOn
) {
722 // BOXFAILSAFE active, but not in stage 2 yet, use stage 1 values
723 sample
= getRxfailValue(channel
);
724 // set channels to Stage 1 values immediately failsafe switch is activated
725 } else if (!thisChannelValid
) {
726 // everything is normal but this channel was invalid
727 if (cmp32(currentTimeMs
, validRxSignalTimeout
[channel
]) < 0) {
728 // first 300ms of Stage 1 failsafe
729 sample
= rcData
[channel
];
730 // HOLD last valid value on bad channel/s for MAX_INVALID_PULSE_TIME_MS (300ms)
732 // remaining Stage 1 failsafe period after 300ms
733 if (channel
< NON_AUX_CHANNEL_COUNT
) {
734 rxFlightChannelsValid
= false;
735 // declare signal lost after 300ms of any one bad flight channel
737 sample
= getRxfailValue(channel
);
738 // set channels that are invalid for more than 300ms to Stage 1 values
741 // everything is normal, ie rcData[channel] will be set to rcRaw(channel) via 'sample'
744 sample
= constrainf(sample
, PWM_PULSE_MIN
, PWM_PULSE_MAX
);
746 #if defined(USE_RX_PWM) || defined(USE_RX_PPM)
747 if (rxRuntimeState
.rxProvider
== RX_PROVIDER_PARALLEL_PWM
|| rxRuntimeState
.rxProvider
== RX_PROVIDER_PPM
) {
748 // smooth output for PWM and PPM using moving average
749 rcData
[channel
] = calculateChannelMovingAverage(channel
, sample
);
754 // set rcData to either validated incoming values, or failsafe-modified values
755 rcData
[channel
] = sample
;
759 if (rxFlightChannelsValid
) {
760 failsafeOnValidDataReceived();
761 // --> start the timer to exit stage 2 failsafe 100ms after losing all packets or the BOXFAILSAFE switch is actioned
763 failsafeOnValidDataFailed();
764 // -> start stage 1 timer to enter stage2 failsafe the instant we get a good packet or the BOXFAILSAFE switch is reverted
767 DEBUG_SET(DEBUG_RX_SIGNAL_LOSS
, 3, rcData
[THROTTLE
]);
770 bool calculateRxChannelsAndUpdateFailsafe(timeUs_t currentTimeUs
)
772 if (auxiliaryProcessingRequired
) {
773 rxRuntimeState
.rcProcessFrameFn(&rxRuntimeState
);
774 auxiliaryProcessingRequired
= false;
777 if (!rxDataProcessingRequired
) {
781 rxDataProcessingRequired
= false;
783 // only proceed when no more samples to skip and suspend period is over
784 if (skipRxSamples
|| currentTimeUs
<= suspendRxSignalUntil
) {
785 if (currentTimeUs
> suspendRxSignalUntil
) {
792 readRxChannelsApplyRanges(); // returns rcRaw
793 detectAndApplySignalLossBehaviour(); // returns rcData
800 void parseRcChannels(const char *input
, rxConfig_t
*rxConfig
)
802 for (const char *c
= input
; *c
; c
++) {
803 const char *s
= strchr(rcChannelLetters
, *c
);
804 if (s
&& (s
< rcChannelLetters
+ RX_MAPPABLE_CHANNEL_COUNT
)) {
805 rxConfig
->rcmap
[s
- rcChannelLetters
] = c
- input
;
810 void setRssiDirect(uint16_t newRssi
, rssiSource_e source
)
812 if (source
!= rssiSource
) {
820 void setRssi(uint16_t rssiValue
, rssiSource_e source
)
822 if (source
!= rssiSource
) {
827 if (source
== RSSI_SOURCE_FRAME_ERRORS
) {
828 rssiRaw
= pt1FilterApply(&frameErrFilter
, rssiValue
);
834 void setRssiMsp(uint8_t newMspRssi
)
836 if (rssiSource
== RSSI_SOURCE_NONE
) {
837 rssiSource
= RSSI_SOURCE_MSP
;
840 if (rssiSource
== RSSI_SOURCE_MSP
) {
841 rssi
= ((uint16_t)newMspRssi
) << 2;
842 lastMspRssiUpdateUs
= micros();
846 static void updateRSSIPWM(void)
848 // Read value of AUX channel as rssi
849 int16_t pwmRssi
= rcData
[rxConfig()->rssi_channel
- 1];
851 // Range of rawPwmRssi is [1000;2000]. rssi should be in [0;1023];
852 setRssiDirect(scaleRange(constrain(pwmRssi
, PWM_RANGE_MIN
, PWM_RANGE_MAX
), PWM_RANGE_MIN
, PWM_RANGE_MAX
, 0, RSSI_MAX_VALUE
), RSSI_SOURCE_RX_CHANNEL
);
855 static void updateRSSIADC(timeUs_t currentTimeUs
)
858 UNUSED(currentTimeUs
);
860 static uint32_t rssiUpdateAt
= 0;
862 if ((int32_t)(currentTimeUs
- rssiUpdateAt
) < 0) {
865 rssiUpdateAt
= currentTimeUs
+ DELAY_20_MS
;
867 const uint16_t adcRssiSample
= adcGetChannel(ADC_RSSI
);
868 uint16_t rssiValue
= adcRssiSample
/ RSSI_ADC_DIVISOR
;
870 setRssi(rssiValue
, RSSI_SOURCE_ADC
);
874 void updateRSSI(timeUs_t currentTimeUs
)
876 switch (rssiSource
) {
877 case RSSI_SOURCE_RX_CHANNEL
:
880 case RSSI_SOURCE_ADC
:
881 updateRSSIADC(currentTimeUs
);
883 case RSSI_SOURCE_MSP
:
884 if (cmpTimeUs(micros(), lastMspRssiUpdateUs
) > DELAY_1500_MS
) { // 1.5s
892 if (cmpTimeUs(currentTimeUs
, lastRssiSmoothingUs
) > 250000) { // 0.25s
893 lastRssiSmoothingUs
= currentTimeUs
;
895 if (lastRssiSmoothingUs
!= currentTimeUs
) { // avoid div by 0
896 float k
= (256.0f
- rxConfig()->rssi_smoothing
) / 256.0f
;
897 float factor
= ((currentTimeUs
- lastRssiSmoothingUs
) / 1000000.0f
) / (1.0f
/ 4.0f
);
898 float k2
= (k
* factor
) / ((k
* factor
) - k
+ 1);
900 if (rssi
!= rssiRaw
) {
901 pt1FilterUpdateCutoff(&rssiFilter
, k2
);
902 rssi
= pt1FilterApply(&rssiFilter
, rssiRaw
);
905 #ifdef USE_RX_RSSI_DBM
906 if (rssiDbm
!= rssiDbmRaw
) {
907 pt1FilterUpdateCutoff(&rssiDbmFilter
, k2
);
908 rssiDbm
= pt1FilterApply(&rssiDbmFilter
, rssiDbmRaw
);
910 #endif //USE_RX_RSSI_DBM
913 if (rsnr
!= rsnrRaw
) {
914 pt1FilterUpdateCutoff(&rsnrFilter
, k2
);
915 rsnr
= pt1FilterApply(&rsnrFilter
, rsnrRaw
);
919 lastRssiSmoothingUs
= currentTimeUs
;
924 uint16_t getRssi(void)
926 uint16_t rssiValue
= rssi
;
928 // RSSI_Invert option
929 if (rxConfig()->rssi_invert
) {
930 rssiValue
= RSSI_MAX_VALUE
- rssiValue
;
933 return rxConfig()->rssi_scale
/ 100.0f
* rssiValue
+ rxConfig()->rssi_offset
* RSSI_OFFSET_SCALING
;
936 uint8_t getRssiPercent(void)
938 return scaleRange(getRssi(), 0, RSSI_MAX_VALUE
, 0, 100);
941 #ifdef USE_RX_RSSI_DBM
942 int16_t getRssiDbm(void)
947 void setRssiDbm(int16_t rssiDbmValue
, rssiSource_e source
)
949 if (source
!= rssiSource
) {
953 rssiDbmRaw
= rssiDbmValue
;
956 void setRssiDbmDirect(int16_t newRssiDbm
, rssiSource_e source
)
958 if (source
!= rssiSource
) {
962 rssiDbm
= newRssiDbm
;
963 rssiDbmRaw
= newRssiDbm
;
966 int8_t getActiveAntenna(void)
968 return activeAntenna
;
971 void setActiveAntenna(int8_t antenna
)
973 activeAntenna
= antenna
;
976 #endif //USE_RX_RSSI_DBM
979 int16_t getRsnr(void)
984 void setRsnr(int16_t rsnrValue
)
989 void setRsnrDirect(int16_t newRsnr
)
996 #ifdef USE_RX_LINK_QUALITY_INFO
997 uint16_t rxGetLinkQuality(void)
1002 uint8_t rxGetRfMode(void)
1007 uint16_t rxGetLinkQualityPercent(void)
1009 return (linkQualitySource
== LQ_SOURCE_NONE
) ? scaleRange(linkQuality
, 0, LINK_QUALITY_MAX_VALUE
, 0, 100) : linkQuality
;
1013 #ifdef USE_RX_LINK_UPLINK_POWER
1014 uint16_t rxGetUplinkTxPwrMw(void)
1016 return uplinkTxPwrMw
;
1020 bool isRssiConfigured(void)
1022 return rssiSource
!= RSSI_SOURCE_NONE
;
1025 timeDelta_t
rxGetFrameDelta(timeDelta_t
*frameAgeUs
)
1027 static timeUs_t previousFrameTimeUs
= 0;
1028 static timeDelta_t frameTimeDeltaUs
= 0;
1030 if (rxRuntimeState
.rcFrameTimeUsFn
) {
1031 const timeUs_t frameTimeUs
= rxRuntimeState
.rcFrameTimeUsFn();
1033 *frameAgeUs
= cmpTimeUs(micros(), frameTimeUs
);
1035 const timeDelta_t deltaUs
= cmpTimeUs(frameTimeUs
, previousFrameTimeUs
);
1037 frameTimeDeltaUs
= deltaUs
;
1038 previousFrameTimeUs
= frameTimeUs
;
1042 return frameTimeDeltaUs
;
1045 timeUs_t
rxFrameTimeUs(void)
1047 return rxRuntimeState
.lastRcFrameTimeUs
;