Communicate Rx available antenna mode to the Tx (#3039)
[ExpressLRS.git] / src / lib / LBT / LBT.cpp
blob07de4700cf1e86b51718af25d2daf21c8c691548
1 #if defined(Regulatory_Domain_EU_CE_2400)
2 #include "common.h"
3 #include "logging.h"
4 #include "LBT.h"
6 LQCALC<100> LBTSuccessCalc;
7 static uint32_t rxStartTime;
9 bool LBTEnabled = false;
10 static uint32_t validRSSIdelayUs = 0;
12 static uint32_t ICACHE_RAM_ATTR SpreadingFactorToRSSIvalidDelayUs(
13 SX1280_RadioLoRaSpreadingFactors_t SF,
14 uint8_t radio_type
17 // The necessary wait time from RX start to valid instant RSSI reading
18 // changes with the spreading factor setting.
19 // The worst case necessary wait time is TX->RX switch time + Lora symbol time
20 // This assumes the radio switches from either TX, RX or FS (Freq Synth mode)
21 // TX to RX switch time is 60us for sx1280
22 // Lora symbol time for the relevant spreading factors is:
23 // SF5: 39.4us
24 // SF6: 78.8us
25 // SF7: 157.6us
26 // SF8: 315.2us
27 // However, by measuring when the RSSI reading is stable and valid, it was found that
28 // actual necessary wait times are:
29 // SF5 ~100us (60us + SF5 symbol time)
30 // SF6 ~141us (60us + SF6 symbol time)
31 // SF7 ~218us (60us + SF7 symbol time)
32 // SF8 ~376us (60us + SF8 symbol time) Empirical testing shows 480us to be the sweet-spot
34 if (radio_type == RADIO_TYPE_SX128x_LORA)
36 switch(SF)
38 case SX1280_LORA_SF5: return 100;
39 case SX1280_LORA_SF6: return 141;
40 case SX1280_LORA_SF7: return 218;
41 case SX1280_LORA_SF8: return 480;
42 default: return 480;
45 else if (radio_type == RADIO_TYPE_SX128x_FLRC)
47 return 60 + 20; // switching time (60us) + 20us settling time (seems fine when testing)
49 else
51 ERRLN("LBT not support on this radio type");
52 return 0;
56 static int8_t ICACHE_RAM_ATTR PowerEnumToLBTLimit(PowerLevels_e txPower, uint8_t radio_type)
58 // Calculated from EN 300 328, adjusted for 800kHz BW for sx1280
59 // TL = -70 dBm/MHz + 10*log10(0.8MHz) + 10 × log10 (100 mW / Pout) (Pout in mW e.i.r.p.)
60 // This threshold should be offset with a #define config for each HW that corrects for antenna gain,
61 // different RF frontends.
62 // TODO: Maybe individual adjustment offset for differences in
63 // rssi reading between bandwidth setting is also necessary when other BW than 0.8MHz are used.
65 if (radio_type == RADIO_TYPE_SX128x_LORA)
67 switch(txPower)
69 case PWR_10mW: return -61 + LBT_RSSI_THRESHOLD_OFFSET_DB;
70 case PWR_25mW: return -65 + LBT_RSSI_THRESHOLD_OFFSET_DB;
71 case PWR_50mW: return -68 + LBT_RSSI_THRESHOLD_OFFSET_DB;
72 case PWR_100mW: return -71 + LBT_RSSI_THRESHOLD_OFFSET_DB;
73 // Values above 100mW are not relevant, default to 100mW threshold
74 default: return -71 + LBT_RSSI_THRESHOLD_OFFSET_DB;
77 else if (radio_type == RADIO_TYPE_SX128x_FLRC)
79 switch(txPower)
81 case PWR_10mW: return -63 + LBT_RSSI_THRESHOLD_OFFSET_DB;
82 case PWR_25mW: return -67 + LBT_RSSI_THRESHOLD_OFFSET_DB;
83 case PWR_50mW: return -70 + LBT_RSSI_THRESHOLD_OFFSET_DB;
84 case PWR_100mW: return -73 + LBT_RSSI_THRESHOLD_OFFSET_DB;
85 // Values above 100mW are not relevant, default to 100mW threshold
86 default: return -73 + LBT_RSSI_THRESHOLD_OFFSET_DB;
89 else
91 ERRLN("LBT not support on this radio type");
92 return 0;
96 void ICACHE_RAM_ATTR SetClearChannelAssessmentTime(void)
98 if (!LBTEnabled)
99 return;
101 rxStartTime = micros();
102 validRSSIdelayUs = SpreadingFactorToRSSIvalidDelayUs((SX1280_RadioLoRaSpreadingFactors_t)ExpressLRS_currAirRate_Modparams->sf, ExpressLRS_currAirRate_Modparams->radio_type);
104 #if defined(TARGET_TX)
105 Radio.RXnb(SX1280_MODE_RX, validRSSIdelayUs);
106 #endif
109 SX12XX_Radio_Number_t ICACHE_RAM_ATTR ChannelIsClear(SX12XX_Radio_Number_t radioNumber)
111 if (radioNumber == SX12XX_Radio_NONE)
112 return SX12XX_Radio_NONE;
114 LBTSuccessCalc.inc(); // Increment count for every channel check
116 if (!LBTEnabled)
118 LBTSuccessCalc.add();
119 return SX12XX_Radio_All;
122 // Read rssi after waiting the minimum RSSI valid delay.
123 // If this function is called long enough after RX enable,
124 // this will always be ok on first try as is the case for TX.
126 // TODO: Better way than busypolling this for RX?
127 // this loop should only run for RX, where listen before talk RX is started right after FHSS hop
128 // so there is no dead-time to run RX before telemetry TX is supposed to happen.
129 // if flipping the logic, so telemetry TX happens right before FHSS hop, then TX-side ends up with polling here instead?
130 // Maybe it could be skipped if there was only TX of telemetry happening when FHSShop does not happen.
131 // Then RX for LBT could stay enabled from last received packet, and RSSI would be valid instantly.
132 // But for now, FHSShops and telemetry rates does not divide evenly, so telemetry will some times happen
133 // right after FHSS and we need wait here.
135 uint32_t elapsed = micros() - rxStartTime;
136 if(elapsed < validRSSIdelayUs)
138 delayMicroseconds(validRSSIdelayUs - elapsed);
141 int8_t rssiInst1 = 0;
142 int8_t rssiInst2 = 0;
143 SX12XX_Radio_Number_t clearChannelsMask = SX12XX_Radio_NONE;
144 int8_t rssiCutOff = PowerEnumToLBTLimit((PowerLevels_e)POWERMGNT::currPower(), ExpressLRS_currAirRate_Modparams->radio_type);
146 if (radioNumber & SX12XX_Radio_1)
148 rssiInst1 = Radio.GetRssiInst(SX12XX_Radio_1);
149 if(rssiInst1 < rssiCutOff)
151 clearChannelsMask |= SX12XX_Radio_1;
155 if (radioNumber & SX12XX_Radio_2)
157 rssiInst2 = Radio.GetRssiInst(SX12XX_Radio_2);
158 if(rssiInst2 < rssiCutOff)
160 clearChannelsMask |= SX12XX_Radio_2;
164 // Useful to debug if and how long the rssi wait is, and rssi threshold rssiCutOff
165 // DBGLN("wait: %d, cutoff: %d, rssi: %d %d, %s", validRSSIdelayUs - elapsed, rssiCutOff, rssiInst1, rssiInst2, clearChannelsMask ? "clear" : "in use");
167 if(clearChannelsMask)
169 LBTSuccessCalc.add(); // Add success only when actually preparing for TX
172 return clearChannelsMask;
174 #endif