Add OSD_STATE_GROUP_ELEMENTS state to osdUpdate() and optimise DMA vs polled MAX7456...
[betaflight.git] / src / main / rx / expresslrs_common.c
blob2516d4fa793fb86b8d6bbabdd9eff7169342644e
1 /*
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)
8 * any later version.
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/>.
22 * Based on https://github.com/ExpressLRS/ExpressLRS
23 * Thanks to AlessandroAU, original creator of the ExpressLRS project.
26 #include <string.h>
27 #include "platform.h"
29 #ifdef USE_RX_EXPRESSLRS
31 #include "build/build_config.h"
32 #include "common/utils.h"
33 #include "common/maths.h"
34 #include "rx/crsf.h"
35 #include "rx/expresslrs_common.h"
36 #include "drivers/rx/rx_sx127x.h"
37 #include "drivers/rx/rx_sx1280.h"
39 STATIC_UNIT_TESTED uint16_t crc14tab[ELRS_CRC_LEN] = {0};
41 static uint8_t volatile FHSSptr = 0;
42 STATIC_UNIT_TESTED uint8_t FHSSsequence[ELRS_NR_SEQUENCE_ENTRIES] = {0};
43 static const uint32_t *FHSSfreqs;
44 static uint8_t numFreqs = 0; // The number of FHSS frequencies in the table
45 static uint8_t seqCount = 0;
46 static uint8_t syncChannel = 0;
48 #define MS_TO_US(ms) (ms * 1000)
50 // Regarding failsafe timeout values:
51 // @CapnBry - Higher rates shorter timeout. Usually it runs 1-1.5 seconds with complete sync 500Hz.
52 // 250Hz is 2-5s. 150Hz 2.5s. 50Hz stays in sync all 5 seconds of my test.
53 // The failsafe timeout values come from the ELRS project's ExpressLRS_AirRateConfig definitions.
54 elrsModSettings_t airRateConfig[][ELRS_RATE_MAX] = {
55 #ifdef USE_RX_SX127X
57 {0, RATE_200HZ, SX127x_BW_500_00_KHZ, SX127x_SF_6, SX127x_CR_4_7, 5000, TLM_RATIO_1_64, 4, 8},
58 {1, RATE_100HZ, SX127x_BW_500_00_KHZ, SX127x_SF_7, SX127x_CR_4_7, 10000, TLM_RATIO_1_64, 4, 8},
59 {2, RATE_50HZ, SX127x_BW_500_00_KHZ, SX127x_SF_8, SX127x_CR_4_7, 20000, TLM_RATIO_NO_TLM, 4, 10},
60 {3, RATE_25HZ, SX127x_BW_500_00_KHZ, SX127x_SF_9, SX127x_CR_4_7, 40000, TLM_RATIO_NO_TLM, 2, 10}
62 #endif
63 #ifdef USE_RX_SX1280
65 {0, RATE_500HZ, SX1280_LORA_BW_0800, SX1280_LORA_SF5, SX1280_LORA_CR_LI_4_6, 2000, TLM_RATIO_1_128, 4, 12},
66 {1, RATE_250HZ, SX1280_LORA_BW_0800, SX1280_LORA_SF6, SX1280_LORA_CR_LI_4_7, 4000, TLM_RATIO_1_64, 4, 14},
67 {2, RATE_150HZ, SX1280_LORA_BW_0800, SX1280_LORA_SF7, SX1280_LORA_CR_LI_4_7, 6666, TLM_RATIO_1_32, 4, 12},
68 {3, RATE_50HZ, SX1280_LORA_BW_0800, SX1280_LORA_SF9, SX1280_LORA_CR_LI_4_6, 20000, TLM_RATIO_NO_TLM, 2, 12}
70 #endif
71 #if !defined(USE_RX_SX127X) && !defined(USE_RX_SX1280)
72 {{0}},
73 #endif
76 elrsRfPerfParams_t rfPerfConfig[][ELRS_RATE_MAX] = {
77 #ifdef USE_RX_SX127X
79 {0, RATE_200HZ, -112, 4380, 3000, 2500, 600, 5000},
80 {1, RATE_100HZ, -117, 8770, 3500, 2500, 600, 5000},
81 {2, RATE_50HZ, -120, 17540, 4000, 2500, 600, 5000},
82 {3, RATE_25HZ, -123, 17540, 6000, 4000, 0, 5000}
84 #endif
85 #ifdef USE_RX_SX1280
87 {0, RATE_500HZ, -105, 1665, 2500, 2500, 3, 5000},
88 {1, RATE_250HZ, -108, 3300, 3000, 2500, 6, 5000},
89 {2, RATE_150HZ, -112, 5871, 3500, 2500, 10, 5000},
90 {3, RATE_50HZ, -117, 18443, 4000, 2500, 0, 5000}
92 #endif
93 #if !defined(USE_RX_SX127X) && !defined(USE_RX_SX1280)
94 {{0}},
95 #endif
98 #ifdef USE_RX_SX127X
99 const uint32_t FHSSfreqsAU433[] = {
100 FREQ_HZ_TO_REG_VAL_900(433420000),
101 FREQ_HZ_TO_REG_VAL_900(433920000),
102 FREQ_HZ_TO_REG_VAL_900(434420000)};
104 const uint32_t FHSSfreqsAU915[] = {
105 FREQ_HZ_TO_REG_VAL_900(915500000),
106 FREQ_HZ_TO_REG_VAL_900(916100000),
107 FREQ_HZ_TO_REG_VAL_900(916700000),
108 FREQ_HZ_TO_REG_VAL_900(917300000),
110 FREQ_HZ_TO_REG_VAL_900(917900000),
111 FREQ_HZ_TO_REG_VAL_900(918500000),
112 FREQ_HZ_TO_REG_VAL_900(919100000),
113 FREQ_HZ_TO_REG_VAL_900(919700000),
115 FREQ_HZ_TO_REG_VAL_900(920300000),
116 FREQ_HZ_TO_REG_VAL_900(920900000),
117 FREQ_HZ_TO_REG_VAL_900(921500000),
118 FREQ_HZ_TO_REG_VAL_900(922100000),
120 FREQ_HZ_TO_REG_VAL_900(922700000),
121 FREQ_HZ_TO_REG_VAL_900(923300000),
122 FREQ_HZ_TO_REG_VAL_900(923900000),
123 FREQ_HZ_TO_REG_VAL_900(924500000),
125 FREQ_HZ_TO_REG_VAL_900(925100000),
126 FREQ_HZ_TO_REG_VAL_900(925700000),
127 FREQ_HZ_TO_REG_VAL_900(926300000),
128 FREQ_HZ_TO_REG_VAL_900(926900000)};
130 /* Frequency bands taken from https://wetten.overheid.nl/BWBR0036378/2016-12-28#Bijlagen
131 * Note: these frequencies fall in the license free H-band, but in combination with 500kHz
132 * LoRa modem bandwidth used by ExpressLRS (EU allows up to 125kHz modulation BW only) they
133 * will never pass RED certification and they are ILLEGAL to use.
135 * Therefore we simply maximize the usage of available spectrum so laboratory testing of the software won't disturb existing
136 * 868MHz ISM band traffic too much.
138 const uint32_t FHSSfreqsEU868[] = {
139 FREQ_HZ_TO_REG_VAL_900(863275000), // band H1, 863 - 865MHz, 0.1% duty cycle or CSMA techniques, 25mW EIRP
140 FREQ_HZ_TO_REG_VAL_900(863800000),
141 FREQ_HZ_TO_REG_VAL_900(864325000),
142 FREQ_HZ_TO_REG_VAL_900(864850000),
143 FREQ_HZ_TO_REG_VAL_900(865375000), // Band H2, 865 - 868.6MHz, 1.0% dutycycle or CSMA, 25mW EIRP
144 FREQ_HZ_TO_REG_VAL_900(865900000),
145 FREQ_HZ_TO_REG_VAL_900(866425000),
146 FREQ_HZ_TO_REG_VAL_900(866950000),
147 FREQ_HZ_TO_REG_VAL_900(867475000),
148 FREQ_HZ_TO_REG_VAL_900(868000000),
149 FREQ_HZ_TO_REG_VAL_900(868525000), // Band H3, 868.7-869.2MHz, 0.1% dutycycle or CSMA, 25mW EIRP
150 FREQ_HZ_TO_REG_VAL_900(869050000),
151 FREQ_HZ_TO_REG_VAL_900(869575000)};
154 * India currently delicensed the 865-867 MHz band with a maximum of 1W Transmitter power,
155 * 4Watts Effective Radiated Power and 200Khz carrier bandwidth as per
156 * https://dot.gov.in/sites/default/files/Delicensing%20in%20865-867%20MHz%20band%20%5BGSR%20564%20%28E%29%5D_0.pdf .
157 * There is currently no mention of Direct-sequence spread spectrum,
158 * So these frequencies are a subset of Regulatory_Domain_EU_868 frequencies.
160 const uint32_t FHSSfreqsIN866[] = {
161 FREQ_HZ_TO_REG_VAL_900(865375000),
162 FREQ_HZ_TO_REG_VAL_900(865900000),
163 FREQ_HZ_TO_REG_VAL_900(866425000),
164 FREQ_HZ_TO_REG_VAL_900(866950000)};
166 /* Frequency band G, taken from https://wetten.overheid.nl/BWBR0036378/2016-12-28#Bijlagen
167 * Note: As is the case with the 868Mhz band, these frequencies only comply to the license free portion
168 * of the spectrum, nothing else. As such, these are likely illegal to use.
170 const uint32_t FHSSfreqsEU433[] = {
171 FREQ_HZ_TO_REG_VAL_900(433100000),
172 FREQ_HZ_TO_REG_VAL_900(433925000),
173 FREQ_HZ_TO_REG_VAL_900(434450000)};
175 /* Very definitely not fully checked. An initial pass at increasing the hops
177 const uint32_t FHSSfreqsFCC915[] = {
178 FREQ_HZ_TO_REG_VAL_900(903500000),
179 FREQ_HZ_TO_REG_VAL_900(904100000),
180 FREQ_HZ_TO_REG_VAL_900(904700000),
181 FREQ_HZ_TO_REG_VAL_900(905300000),
183 FREQ_HZ_TO_REG_VAL_900(905900000),
184 FREQ_HZ_TO_REG_VAL_900(906500000),
185 FREQ_HZ_TO_REG_VAL_900(907100000),
186 FREQ_HZ_TO_REG_VAL_900(907700000),
188 FREQ_HZ_TO_REG_VAL_900(908300000),
189 FREQ_HZ_TO_REG_VAL_900(908900000),
190 FREQ_HZ_TO_REG_VAL_900(909500000),
191 FREQ_HZ_TO_REG_VAL_900(910100000),
193 FREQ_HZ_TO_REG_VAL_900(910700000),
194 FREQ_HZ_TO_REG_VAL_900(911300000),
195 FREQ_HZ_TO_REG_VAL_900(911900000),
196 FREQ_HZ_TO_REG_VAL_900(912500000),
198 FREQ_HZ_TO_REG_VAL_900(913100000),
199 FREQ_HZ_TO_REG_VAL_900(913700000),
200 FREQ_HZ_TO_REG_VAL_900(914300000),
201 FREQ_HZ_TO_REG_VAL_900(914900000),
203 FREQ_HZ_TO_REG_VAL_900(915500000), // as per AU..
204 FREQ_HZ_TO_REG_VAL_900(916100000),
205 FREQ_HZ_TO_REG_VAL_900(916700000),
206 FREQ_HZ_TO_REG_VAL_900(917300000),
208 FREQ_HZ_TO_REG_VAL_900(917900000),
209 FREQ_HZ_TO_REG_VAL_900(918500000),
210 FREQ_HZ_TO_REG_VAL_900(919100000),
211 FREQ_HZ_TO_REG_VAL_900(919700000),
213 FREQ_HZ_TO_REG_VAL_900(920300000),
214 FREQ_HZ_TO_REG_VAL_900(920900000),
215 FREQ_HZ_TO_REG_VAL_900(921500000),
216 FREQ_HZ_TO_REG_VAL_900(922100000),
218 FREQ_HZ_TO_REG_VAL_900(922700000),
219 FREQ_HZ_TO_REG_VAL_900(923300000),
220 FREQ_HZ_TO_REG_VAL_900(923900000),
221 FREQ_HZ_TO_REG_VAL_900(924500000),
223 FREQ_HZ_TO_REG_VAL_900(925100000),
224 FREQ_HZ_TO_REG_VAL_900(925700000),
225 FREQ_HZ_TO_REG_VAL_900(926300000),
226 FREQ_HZ_TO_REG_VAL_900(926900000)};
227 #endif
228 #ifdef USE_RX_SX1280
229 const uint32_t FHSSfreqsISM2400[] = {
230 FREQ_HZ_TO_REG_VAL_24(2400400000),
231 FREQ_HZ_TO_REG_VAL_24(2401400000),
232 FREQ_HZ_TO_REG_VAL_24(2402400000),
233 FREQ_HZ_TO_REG_VAL_24(2403400000),
234 FREQ_HZ_TO_REG_VAL_24(2404400000),
236 FREQ_HZ_TO_REG_VAL_24(2405400000),
237 FREQ_HZ_TO_REG_VAL_24(2406400000),
238 FREQ_HZ_TO_REG_VAL_24(2407400000),
239 FREQ_HZ_TO_REG_VAL_24(2408400000),
240 FREQ_HZ_TO_REG_VAL_24(2409400000),
242 FREQ_HZ_TO_REG_VAL_24(2410400000),
243 FREQ_HZ_TO_REG_VAL_24(2411400000),
244 FREQ_HZ_TO_REG_VAL_24(2412400000),
245 FREQ_HZ_TO_REG_VAL_24(2413400000),
246 FREQ_HZ_TO_REG_VAL_24(2414400000),
248 FREQ_HZ_TO_REG_VAL_24(2415400000),
249 FREQ_HZ_TO_REG_VAL_24(2416400000),
250 FREQ_HZ_TO_REG_VAL_24(2417400000),
251 FREQ_HZ_TO_REG_VAL_24(2418400000),
252 FREQ_HZ_TO_REG_VAL_24(2419400000),
254 FREQ_HZ_TO_REG_VAL_24(2420400000),
255 FREQ_HZ_TO_REG_VAL_24(2421400000),
256 FREQ_HZ_TO_REG_VAL_24(2422400000),
257 FREQ_HZ_TO_REG_VAL_24(2423400000),
258 FREQ_HZ_TO_REG_VAL_24(2424400000),
260 FREQ_HZ_TO_REG_VAL_24(2425400000),
261 FREQ_HZ_TO_REG_VAL_24(2426400000),
262 FREQ_HZ_TO_REG_VAL_24(2427400000),
263 FREQ_HZ_TO_REG_VAL_24(2428400000),
264 FREQ_HZ_TO_REG_VAL_24(2429400000),
266 FREQ_HZ_TO_REG_VAL_24(2430400000),
267 FREQ_HZ_TO_REG_VAL_24(2431400000),
268 FREQ_HZ_TO_REG_VAL_24(2432400000),
269 FREQ_HZ_TO_REG_VAL_24(2433400000),
270 FREQ_HZ_TO_REG_VAL_24(2434400000),
272 FREQ_HZ_TO_REG_VAL_24(2435400000),
273 FREQ_HZ_TO_REG_VAL_24(2436400000),
274 FREQ_HZ_TO_REG_VAL_24(2437400000),
275 FREQ_HZ_TO_REG_VAL_24(2438400000),
276 FREQ_HZ_TO_REG_VAL_24(2439400000),
278 FREQ_HZ_TO_REG_VAL_24(2440400000),
279 FREQ_HZ_TO_REG_VAL_24(2441400000),
280 FREQ_HZ_TO_REG_VAL_24(2442400000),
281 FREQ_HZ_TO_REG_VAL_24(2443400000),
282 FREQ_HZ_TO_REG_VAL_24(2444400000),
284 FREQ_HZ_TO_REG_VAL_24(2445400000),
285 FREQ_HZ_TO_REG_VAL_24(2446400000),
286 FREQ_HZ_TO_REG_VAL_24(2447400000),
287 FREQ_HZ_TO_REG_VAL_24(2448400000),
288 FREQ_HZ_TO_REG_VAL_24(2449400000),
290 FREQ_HZ_TO_REG_VAL_24(2450400000),
291 FREQ_HZ_TO_REG_VAL_24(2451400000),
292 FREQ_HZ_TO_REG_VAL_24(2452400000),
293 FREQ_HZ_TO_REG_VAL_24(2453400000),
294 FREQ_HZ_TO_REG_VAL_24(2454400000),
296 FREQ_HZ_TO_REG_VAL_24(2455400000),
297 FREQ_HZ_TO_REG_VAL_24(2456400000),
298 FREQ_HZ_TO_REG_VAL_24(2457400000),
299 FREQ_HZ_TO_REG_VAL_24(2458400000),
300 FREQ_HZ_TO_REG_VAL_24(2459400000),
302 FREQ_HZ_TO_REG_VAL_24(2460400000),
303 FREQ_HZ_TO_REG_VAL_24(2461400000),
304 FREQ_HZ_TO_REG_VAL_24(2462400000),
305 FREQ_HZ_TO_REG_VAL_24(2463400000),
306 FREQ_HZ_TO_REG_VAL_24(2464400000),
308 FREQ_HZ_TO_REG_VAL_24(2465400000),
309 FREQ_HZ_TO_REG_VAL_24(2466400000),
310 FREQ_HZ_TO_REG_VAL_24(2467400000),
311 FREQ_HZ_TO_REG_VAL_24(2468400000),
312 FREQ_HZ_TO_REG_VAL_24(2469400000),
314 FREQ_HZ_TO_REG_VAL_24(2470400000),
315 FREQ_HZ_TO_REG_VAL_24(2471400000),
316 FREQ_HZ_TO_REG_VAL_24(2472400000),
317 FREQ_HZ_TO_REG_VAL_24(2473400000),
318 FREQ_HZ_TO_REG_VAL_24(2474400000),
320 FREQ_HZ_TO_REG_VAL_24(2475400000),
321 FREQ_HZ_TO_REG_VAL_24(2476400000),
322 FREQ_HZ_TO_REG_VAL_24(2477400000),
323 FREQ_HZ_TO_REG_VAL_24(2478400000),
324 FREQ_HZ_TO_REG_VAL_24(2479400000)};
325 #endif
327 void generateCrc14Table(void)
329 uint16_t crc;
330 for (uint16_t i = 0; i < ELRS_CRC_LEN; i++) {
331 crc = i << (14 - 8);
332 for (uint8_t j = 0; j < 8; j++) {
333 crc = (crc << 1) ^ ((crc & 0x2000) ? ELRS_CRC14_POLY : 0);
335 crc14tab[i] = crc;
339 uint16_t calcCrc14(uint8_t *data, uint8_t len, uint16_t crc)
341 while (len--) {
342 crc = (crc << 8) ^ crc14tab[((crc >> 6) ^ (uint16_t) *data++) & 0x00FF];
344 return crc & 0x3FFF;
347 static void initializeFHSSFrequencies(const elrsFreqDomain_e dom) {
348 switch (dom) {
349 #ifdef USE_RX_SX127X
350 case AU433:
351 FHSSfreqs = FHSSfreqsAU433;
352 numFreqs = sizeof(FHSSfreqsAU433) / sizeof(uint32_t);
353 break;
354 case AU915:
355 FHSSfreqs = FHSSfreqsAU915;
356 numFreqs = sizeof(FHSSfreqsAU915) / sizeof(uint32_t);
357 break;
358 case EU433:
359 FHSSfreqs = FHSSfreqsEU433;
360 numFreqs = sizeof(FHSSfreqsEU433) / sizeof(uint32_t);
361 break;
362 case EU868:
363 FHSSfreqs = FHSSfreqsEU868;
364 numFreqs = sizeof(FHSSfreqsEU868) / sizeof(uint32_t);
365 break;
366 case IN866:
367 FHSSfreqs = FHSSfreqsIN866;
368 numFreqs = sizeof(FHSSfreqsIN866) / sizeof(uint32_t);
369 break;
370 case FCC915:
371 FHSSfreqs = FHSSfreqsFCC915;
372 numFreqs = sizeof(FHSSfreqsFCC915) / sizeof(uint32_t);
373 break;
374 #endif
375 #ifdef USE_RX_SX1280
376 case ISM2400:
377 FHSSfreqs = FHSSfreqsISM2400;
378 numFreqs = sizeof(FHSSfreqsISM2400) / sizeof(uint32_t);
379 break;
380 #endif
381 default:
382 FHSSfreqs = NULL;
383 numFreqs = 0;
387 uint32_t getInitialFreq(const int32_t freqCorrection)
389 return FHSSfreqs[syncChannel] - freqCorrection;
392 uint8_t getFHSSNumEntries(void)
394 return numFreqs;
397 uint8_t FHSSgetCurrIndex(void)
399 return FHSSptr;
402 void FHSSsetCurrIndex(const uint8_t value)
404 FHSSptr = value % seqCount;
407 uint32_t FHSSgetNextFreq(const int32_t freqCorrection)
409 FHSSptr = (FHSSptr + 1) % seqCount;
410 return FHSSfreqs[FHSSsequence[FHSSptr]] - freqCorrection;
413 static uint32_t seed = 0;
415 // returns 0 <= x < max where max < 256
416 static uint8_t rngN(const uint8_t max)
418 const uint32_t m = 2147483648;
419 const uint32_t a = 214013;
420 const uint32_t c = 2531011;
421 seed = (a * seed + c) % m;
422 return (seed >> 16) % max;
426 Requirements:
427 1. 0 every n hops
428 2. No two repeated channels
429 3. Equal occurance of each (or as even as possible) of each channel
430 4. Pseudorandom
432 Approach:
433 Fill the sequence array with the sync channel every FHSS_FREQ_CNT
434 Iterate through the array, and for each block, swap each entry in it with
435 another random entry, excluding the sync channel.
438 void FHSSrandomiseFHSSsequence(const uint8_t UID[], const elrsFreqDomain_e dom)
440 seed = ((long)UID[2] << 24) + ((long)UID[3] << 16) + ((long)UID[4] << 8) + UID[5];
442 initializeFHSSFrequencies(dom);
444 seqCount = (256 / MAX(numFreqs, 1)) * numFreqs;
446 syncChannel = numFreqs / 2;
448 // initialize the sequence array
449 for (uint8_t i = 0; i < seqCount; i++) {
450 if (i % numFreqs == 0) {
451 FHSSsequence[i] = syncChannel;
452 } else if (i % numFreqs == syncChannel) {
453 FHSSsequence[i] = 0;
454 } else {
455 FHSSsequence[i] = i % numFreqs;
459 for (uint8_t i = 0; i < seqCount; i++) {
460 // if it's not the sync channel
461 if (i % numFreqs != 0) {
462 uint8_t offset = (i / numFreqs) * numFreqs; // offset to start of current block
463 uint8_t rand = rngN(numFreqs - 1) + 1; // random number between 1 and numFreqs
465 // switch this entry and another random entry in the same block
466 uint8_t temp = FHSSsequence[i];
467 FHSSsequence[i] = FHSSsequence[offset + rand];
468 FHSSsequence[offset + rand] = temp;
473 uint8_t tlmRatioEnumToValue(const elrsTlmRatio_e enumval)
475 switch (enumval) {
476 case TLM_RATIO_NO_TLM:
477 return 1;
478 break;
479 case TLM_RATIO_1_2:
480 return 2;
481 break;
482 case TLM_RATIO_1_4:
483 return 4;
484 break;
485 case TLM_RATIO_1_8:
486 return 8;
487 break;
488 case TLM_RATIO_1_16:
489 return 16;
490 break;
491 case TLM_RATIO_1_32:
492 return 32;
493 break;
494 case TLM_RATIO_1_64:
495 return 64;
496 break;
497 case TLM_RATIO_1_128:
498 return 128;
499 break;
500 default:
501 return 0;
505 uint16_t rateEnumToHz(const elrsRfRate_e eRate)
507 switch (eRate) {
508 case RATE_500HZ: return 500;
509 case RATE_250HZ: return 250;
510 case RATE_200HZ: return 200;
511 case RATE_150HZ: return 150;
512 case RATE_100HZ: return 100;
513 case RATE_50HZ: return 50;
514 case RATE_25HZ: return 25;
515 case RATE_4HZ: return 4;
516 default: return 1;
520 uint16_t txPowerIndexToValue(const uint8_t index)
522 switch (index) {
523 case 0: return 0;
524 case 1: return 10;
525 case 2: return 25;
526 case 3: return 100;
527 case 4: return 500;
528 case 5: return 1000;
529 case 6: return 2000;
530 case 7: return 250;
531 case 8: return 50;
532 default: return 0;
536 #define ELRS_LQ_DEPTH 4 //100 % 32
538 typedef struct linkQuality_s {
539 uint32_t array[ELRS_LQ_DEPTH];
540 uint8_t value;
541 uint8_t index;
542 uint32_t mask;
543 } linkQuality_t;
545 static linkQuality_t lq;
547 void lqIncrease(void)
549 if (lqPeriodIsSet()) {
550 return;
552 lq.array[lq.index] |= lq.mask;
553 lq.value += 1;
556 void lqNewPeriod(void)
558 lq.mask <<= 1;
559 if (lq.mask == 0) {
560 lq.mask = (1 << 0);
561 lq.index += 1;
564 // At idx N / 32 and bit N % 32, wrap back to idx=0, bit=0
565 if ((lq.index == 3) && (lq.mask & (1 << ELRS_LQ_DEPTH))) {
566 lq.index = 0;
567 lq.mask = (1 << 0);
570 if ((lq.array[lq.index] & lq.mask) != 0) {
571 lq.array[lq.index] &= ~lq.mask;
572 lq.value -= 1;
576 uint8_t lqGet(void)
578 return lq.value;
581 bool lqPeriodIsSet(void)
583 return lq.array[lq.index] & lq.mask;
586 void lqReset(void)
588 memset(&lq, 0, sizeof(lq));
589 lq.mask = (1 << 0);
592 uint16_t convertSwitch1b(const uint16_t val)
594 return val ? 2000 : 1000;
597 // 3b to decode 7 pos switches
598 uint16_t convertSwitch3b(const uint16_t val)
600 switch (val) {
601 case 0:
602 return 1000;
603 case 1:
604 return 1275;
605 case 2:
606 return 1425;
607 case 3:
608 return 1575;
609 case 4:
610 return 1725;
611 case 5:
612 return 2000;
613 default:
614 return 1500;
618 uint16_t convertSwitchNb(const uint16_t val, const uint16_t max)
620 return (val > max) ? 1500 : val * 1000 / max + 1000;
623 uint16_t convertAnalog(const uint16_t val)
625 return CRSF_RC_CHANNEL_SCALE_LEGACY * val + 881;
628 uint8_t hybridWideNonceToSwitchIndex(const uint8_t nonce)
630 // Returns the sequence (0 to 7, then 0 to 7 rotated left by 1):
631 // 0, 1, 2, 3, 4, 5, 6, 7,
632 // 1, 2, 3, 4, 5, 6, 7, 0
633 // Because telemetry can occur on every 2, 4, 8, 16, 32, 64, 128th packet
634 // this makes sure each of the 8 values is sent at least once every 16 packets
635 // regardless of the TLM ratio
636 // Index 7 also can never fall on a telemetry slot
637 return ((nonce & 0x07) + ((nonce >> 3) & 0x01)) % 8;
640 #endif /* USE_RX_EXPRESSLRS */