6 SX127xDriver
*SX127xDriver::instance
= NULL
;
10 #ifdef USE_SX1276_RFO_HF
11 #ifndef OPT_USE_SX1276_RFO_HF
12 #define OPT_USE_SX1276_RFO_HF true
15 #define OPT_USE_SX1276_RFO_HF false
18 const uint8_t SX127x_AllowedSyncwords
[105] =
19 {0, 5, 6, 7, 11, 12, 13, 15, 18,
20 21, 23, 26, 29, 30, 31, 33, 34,
21 37, 38, 39, 40, 42, 44, 50, 51,
22 54, 55, 57, 58, 59, 61, 63, 65,
23 67, 68, 71, 77, 78, 79, 80, 82,
24 84, 86, 89, 92, 94, 96, 97, 99,
25 101, 102, 105, 106, 109, 111, 113, 115,
26 117, 118, 119, 121, 122, 124, 126, 127,
27 129, 130, 138, 143, 161, 170, 172, 173,
28 175, 180, 181, 182, 187, 190, 191, 192,
29 193, 196, 199, 201, 204, 205, 208, 209,
30 212, 213, 219, 220, 221, 223, 227, 229,
31 235, 239, 240, 242, 243, 246, 247, 255};
33 //////////////////////////////////////////////
35 SX127xDriver::SX127xDriver(): SX12xxDriverCommon()
38 // default values from datasheet
39 currSyncWord
= SX127X_SYNC_WORD
;
40 currBW
=SX127x_BW_125_00_KHZ
;
42 currCR
= SX127x_CR_4_5
;
43 currOpmode
= SX127x_OPMODE_SLEEP
;
44 ModFSKorLoRa
= SX127x_OPMODE_LORA
;
45 // Dummy default values which are overwritten during setup
49 headerExplMode
= false;
51 lowFrequencyMode
= SX1278_HIGH_FREQ
;
52 lastSuccessfulPacketRadio
= SX12XX_Radio_1
;
55 bool SX127xDriver::Begin()
58 hal
.IsrCallback_1
= &SX127xDriver::IsrCallback_1
;
59 hal
.IsrCallback_2
= &SX127xDriver::IsrCallback_2
;
62 DBGLN("SX127x Begin");
66 // currFreq must be set before calling Radio.Begin so that lowFrequencyMode can be set correctly.
67 if (currFreq
< (uint32_t)((double)525000000 / (double)FREQ_STEP
))
69 lowFrequencyMode
= SX1278_LOW_FREQ
;
70 DBGLN("Setting 'lowFrequencyMode' used for 433MHz.");
73 SetMode(SX127x_OPMODE_STANDBY
, SX12XX_Radio_All
);
75 if (!DetectChip(SX12XX_Radio_1
))
80 if (GPIO_PIN_NSS_2
!= UNDEF_PIN
)
82 if (!DetectChip(SX12XX_Radio_2
))
89 // Force the next power update
90 pwrCurrent
= PWRPENDING_NONE
;
97 void SX127xDriver::End()
99 SetMode(SX127x_OPMODE_SLEEP
, SX12XX_Radio_All
);
105 void SX127xDriver::ConfigLoraDefaults()
107 hal
.writeRegister(SX127X_REG_OP_MODE
, SX127x_OPMODE_SLEEP
, SX12XX_Radio_All
);
108 hal
.writeRegister(SX127X_REG_OP_MODE
, ModFSKorLoRa
, SX12XX_Radio_All
); //must be written in sleep mode
109 SetMode(SX127x_OPMODE_STANDBY
, SX12XX_Radio_All
);
111 hal
.writeRegister(SX127X_REG_PAYLOAD_LENGTH
, PayloadLength
, SX12XX_Radio_All
);
112 SetSyncWord(currSyncWord
);
113 hal
.writeRegister(SX127X_REG_FIFO_TX_BASE_ADDR
, SX127X_FIFO_TX_BASE_ADDR_MAX
, SX12XX_Radio_All
);
114 hal
.writeRegister(SX127X_REG_FIFO_RX_BASE_ADDR
, SX127X_FIFO_RX_BASE_ADDR_MAX
, SX12XX_Radio_All
);
115 hal
.writeRegisterBits(SX127X_REG_DIO_MAPPING_1
, SX127X_DIO0_RXTX_DONE
, SX127X_DIO0_MASK
, SX12XX_Radio_All
); //undocumented "hack", looking at Table 18 from datasheet SX127X_REG_DIO_MAPPING_1 = 11 appears to be unspported by infact it generates an intterupt on both RXdone and TXdone, this saves switching modes.
116 hal
.writeRegister(SX127X_REG_LNA
, SX127X_LNA_BOOST_ON
, SX12XX_Radio_All
);
117 hal
.writeRegister(SX1278_REG_MODEM_CONFIG_3
, SX1278_AGC_AUTO_ON
| SX1278_LOW_DATA_RATE_OPT_OFF
, SX12XX_Radio_All
);
118 hal
.writeRegisterBits(SX127X_REG_OCP
, SX127X_OCP_ON
| SX127X_OCP_150MA
, SX127X_OCP_MASK
, SX12XX_Radio_All
); //150ma max current
119 SetPreambleLength(SX127X_PREAMBLE_LENGTH_LSB
);
122 void SX127xDriver::SetBandwidthCodingRate(SX127x_Bandwidth bw
, SX127x_CodingRate cr
)
124 if ((currBW
!= bw
) || (currCR
!= cr
))
126 if (currSF
== SX127x_SF_6
) // set SF6 optimizations
128 hal
.writeRegister(SX127X_REG_MODEM_CONFIG_1
, bw
| cr
| SX127x_HEADER_IMPL_MODE
, SX12XX_Radio_All
);
135 hal
.writeRegister(SX127X_REG_MODEM_CONFIG_1
, bw
| cr
| SX127x_HEADER_EXPL_MODE
, SX12XX_Radio_All
);
139 hal
.writeRegister(SX127X_REG_MODEM_CONFIG_1
, bw
| cr
| SX127x_HEADER_IMPL_MODE
, SX12XX_Radio_All
);
141 SetCRCMode(crcEnabled
);
144 #if !defined(RADIO_SX1272) //does not apply to SX1272
145 if (bw
== SX127x_BW_500_00_KHZ
)
147 //data-sheet errata recommendation http://caxapa.ru/thumbs/972894/SX1276_77_8_ErrataNote_1.1_STD.pdf
148 hal
.writeRegister(0x36, 0x02, SX12XX_Radio_All
);
149 hal
.writeRegister(0x3a, lowFrequencyMode
? 0x7F : 0x64, SX12XX_Radio_All
);
153 hal
.writeRegister(0x36, 0x03, SX12XX_Radio_All
);
162 void SX127xDriver::SetCRCMode(bool on
)
166 #if defined(RADIO_SX1272)
167 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_1
, SX1272_RX_CRC_MODE_ON
, SX1272_RX_CRC_MODE_MASK
, SX12XX_Radio_All
);
169 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2
, SX1278_RX_CRC_MODE_ON
, SX1278_RX_CRC_MODE_MASK
, SX12XX_Radio_All
);
174 #if defined(RADIO_SX1272)
175 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_1
, SX1272_RX_CRC_MODE_OFF
, SX1272_RX_CRC_MODE_MASK
, SX12XX_Radio_All
);
177 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2
, SX1278_RX_CRC_MODE_OFF
, SX1278_RX_CRC_MODE_MASK
, SX12XX_Radio_All
);
182 bool SyncWordOk(uint8_t syncWord
)
184 for (unsigned int i
= 0; i
< sizeof(SX127x_AllowedSyncwords
); i
++)
186 if (syncWord
== SX127x_AllowedSyncwords
[i
])
194 void SX127xDriver::SetSyncWord(uint8_t syncWord
)
196 uint8_t _syncWord
= syncWord
;
198 while (SyncWordOk(_syncWord
) == false)
203 if(syncWord
!= _syncWord
){
204 DBGLN("Using syncword: %d instead of: %d", _syncWord
, syncWord
);
207 hal
.writeRegister(SX127X_REG_SYNC_WORD
, _syncWord
, SX12XX_Radio_All
);
208 currSyncWord
= _syncWord
;
212 * @brief: Schedule an output power change after the next transmit
213 * The radio must be in SX127x_OPMODE_STANDBY to change the power
215 void SX127xDriver::SetOutputPower(uint8_t Power
)
218 if (OPT_USE_SX1276_RFO_HF
)
220 pwrNew
= SX127X_PA_SELECT_RFO
| SX127X_MAX_OUTPUT_POWER_RFO_HF
| Power
;
224 pwrNew
= SX127X_PA_SELECT_BOOST
| SX127X_MAX_OUTPUT_POWER
| Power
;
227 if ((pwrPending
== PWRPENDING_NONE
&& pwrCurrent
!= pwrNew
) || pwrPending
!= pwrNew
)
233 void ICACHE_RAM_ATTR
SX127xDriver::CommitOutputPower()
235 if (pwrPending
== PWRPENDING_NONE
)
238 pwrCurrent
= pwrPending
;
239 pwrPending
= PWRPENDING_NONE
;
240 hal
.writeRegister(SX127X_REG_PA_CONFIG
, pwrCurrent
, SX12XX_Radio_All
);
243 void SX127xDriver::SetPreambleLength(uint8_t PreambleLen
)
245 if (currPreambleLen
!= PreambleLen
)
247 hal
.writeRegister(SX127X_REG_PREAMBLE_LSB
, PreambleLen
, SX12XX_Radio_All
);
248 currPreambleLen
= PreambleLen
;
252 void SX127xDriver::SetSpreadingFactor(SX127x_SpreadingFactor sf
)
256 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2
, sf
| SX127X_TX_MODE_SINGLE
, SX127X_SPREADING_FACTOR_MASK
| SX127X_TX_MODE_MASK
, SX12XX_Radio_All
);
257 if (sf
== SX127x_SF_6
)
259 hal
.writeRegisterBits(SX127X_REG_DETECT_OPTIMIZE
, SX127X_DETECT_OPTIMIZE_SF_6
, SX127X_DETECT_OPTIMIZE_SF_MASK
, SX12XX_Radio_All
);
260 hal
.writeRegister(SX127X_REG_DETECTION_THRESHOLD
, SX127X_DETECTION_THRESHOLD_SF_6
, SX12XX_Radio_All
);
264 hal
.writeRegisterBits(SX127X_REG_DETECT_OPTIMIZE
, SX127X_DETECT_OPTIMIZE_SF_7_12
, SX127X_DETECT_OPTIMIZE_SF_MASK
, SX12XX_Radio_All
);
265 hal
.writeRegister(SX127X_REG_DETECTION_THRESHOLD
, SX127X_DETECTION_THRESHOLD_SF_7_12
, SX12XX_Radio_All
);
271 void ICACHE_RAM_ATTR
SX127xDriver::SetFrequencyHz(uint32_t freq
, SX12XX_Radio_Number_t radioNumber
)
273 int32_t regfreq
= ((uint32_t)((double)freq
/ (double)FREQ_STEP
));
275 SetFrequencyReg(regfreq
, radioNumber
);
278 void ICACHE_RAM_ATTR
SX127xDriver::SetFrequencyReg(uint32_t regfreq
, SX12XX_Radio_Number_t radioNumber
)
281 SetMode(SX127x_OPMODE_STANDBY
, radioNumber
);
283 uint8_t FRQ_MSB
= (uint8_t)((regfreq
>> 16) & 0xFF);
284 uint8_t FRQ_MID
= (uint8_t)((regfreq
>> 8) & 0xFF);
285 uint8_t FRQ_LSB
= (uint8_t)(regfreq
& 0xFF);
287 WORD_ALIGNED_ATTR
uint8_t outbuff
[3] = {FRQ_MSB
, FRQ_MID
, FRQ_LSB
}; //check speedup
289 hal
.writeRegister(SX127X_REG_FRF_MSB
, outbuff
, sizeof(outbuff
), radioNumber
);
292 void ICACHE_RAM_ATTR
SX127xDriver::SetRxTimeoutUs(uint32_t interval
)
294 timeoutSymbols
= 0; // no timeout i.e. use continuous mode
297 unsigned int spread
= 0;
322 uint32_t symbolTimeUs
= ((uint32_t)(1 << spread
)) * 1000000 / GetCurrBandwidth();
323 timeoutSymbols
= interval
/ symbolTimeUs
;
324 hal
.writeRegisterBits(SX127X_REG_SYMB_TIMEOUT_MSB
, timeoutSymbols
>> 8, SX127X_REG_SYMB_TIMEOUT_MSB_MASK
, SX12XX_Radio_All
); // set the timeout MSB
325 hal
.writeRegister(SX127X_REG_SYMB_TIMEOUT_LSB
, timeoutSymbols
& 0xFF, SX12XX_Radio_All
);
326 DBGLN("SetRxTimeout(%u), symbolTime=%uus symbols=%u", interval
, (uint32_t)symbolTimeUs
, timeoutSymbols
)
330 bool SX127xDriver::DetectChip(SX12XX_Radio_Number_t radioNumber
)
332 DBG("Detecting radio %x... ", radioNumber
);
334 bool flagFound
= false;
335 while ((i
< 3) && !flagFound
)
337 uint8_t version
= hal
.readRegister(SX127X_REG_VERSION
, radioNumber
);
339 if (version
== SX127X_VERSION
)
345 DBGLN(" not found! (%d of 3 tries) REG_VERSION == 0x%x", i
+1, version
);
353 DBGLN(" not found!");
358 DBGLN(" found! (match by REG_VERSION == 0x%x", SX127X_VERSION
);
363 /////////////////////////////////////TX functions/////////////////////////////////////////
365 void ICACHE_RAM_ATTR
SX127xDriver::TXnbISR()
367 currOpmode
= SX127x_OPMODE_STANDBY
; //goes into standby after transmission
368 //TXdoneMicros = micros();
369 // The power level must be changed when in SX127x_OPMODE_STANDBY, so this lags power
370 // changes by at most 1 packet, but does not interrupt any pending RX/TX
375 void ICACHE_RAM_ATTR
SX127xDriver::TXnb(uint8_t * data
, uint8_t size
, SX12XX_Radio_Number_t radioNumber
)
377 // if (currOpmode == SX127x_OPMODE_TX)
379 // DBGLN("abort TX");
380 // return; // we were already TXing so abort. this should never happen!!!
382 SetMode(SX127x_OPMODE_STANDBY
, SX12XX_Radio_All
);
384 if (radioNumber
== SX12XX_Radio_Default
)
386 radioNumber
= lastSuccessfulPacketRadio
;
389 RFAMP
.TXenable(radioNumber
);
390 hal
.writeRegister(SX127X_REG_FIFO_ADDR_PTR
, SX127X_FIFO_TX_BASE_ADDR_MAX
, radioNumber
);
391 hal
.writeRegister(SX127X_REG_FIFO
, data
, size
, radioNumber
);
393 SetMode(SX127x_OPMODE_TX
, radioNumber
);
396 ///////////////////////////////////RX Functions Non-Blocking///////////////////////////////////////////
398 bool ICACHE_RAM_ATTR
SX127xDriver::RXnbISR(SX12XX_Radio_Number_t radioNumber
)
400 uint8_t const FIFOaddr
= hal
.readRegister(SX127X_REG_FIFO_RX_CURRENT_ADDR
, radioNumber
);
401 hal
.writeRegister(SX127X_REG_FIFO_ADDR_PTR
, FIFOaddr
, radioNumber
);
402 hal
.readRegister(SX127X_REG_FIFO
, RXdataBuffer
, PayloadLength
, radioNumber
);
406 // From page 42 of the datasheet rev 7
407 // In Rx Single mode, the device will return to Standby mode as soon as the interrupt occurs
408 currOpmode
= SX127x_OPMODE_STANDBY
;
411 return RXdoneCallback(SX12XX_RX_OK
);
414 void ICACHE_RAM_ATTR
SX127xDriver::RXnb()
420 SetMode(SX127x_OPMODE_RXSINGLE
, SX12XX_Radio_All
);
424 SetMode(SX127x_OPMODE_RXCONTINUOUS
, SX12XX_Radio_All
);
428 void ICACHE_RAM_ATTR
SX127xDriver::GetLastPacketStats()
430 LastPacketRSSI
= GetLastPacketRSSI();
431 LastPacketSNRRaw
= GetLastPacketSNRRaw();
432 // https://www.mouser.com/datasheet/2/761/sx1276-1278113.pdf
433 // Section 3.5.5 (page 87)
434 int8_t negOffset
= (LastPacketSNRRaw
< 0) ? (LastPacketSNRRaw
/ RADIO_SNR_SCALE
) : 0;
435 LastPacketRSSI
+= negOffset
;
438 void ICACHE_RAM_ATTR
SX127xDriver::SetMode(SX127x_RadioOPmodes mode
, SX12XX_Radio_Number_t radioNumber
)
441 Comment out since it is difficult to keep track of dual radios.
442 When checking SPI it is also useful to see every possible SPI transaction to make sure it fits when required.
444 // if (mode == currOpmode)
449 hal
.writeRegister(SX127X_REG_OP_MODE
, mode
| lowFrequencyMode
, radioNumber
);
453 void SX127xDriver::Config(uint8_t bw
, uint8_t sf
, uint8_t cr
, uint32_t freq
, uint8_t preambleLen
, bool InvertIQ
, uint8_t _PayloadLength
, uint32_t interval
)
455 Config(bw
, sf
, cr
, freq
, preambleLen
, currSyncWord
, InvertIQ
, _PayloadLength
, interval
);
458 void SX127xDriver::Config(uint8_t bw
, uint8_t sf
, uint8_t cr
, uint32_t freq
, uint8_t preambleLen
, uint8_t syncWord
, bool InvertIQ
, uint8_t _PayloadLength
, uint32_t interval
)
460 PayloadLength
= _PayloadLength
;
461 ConfigLoraDefaults();
462 SetPreambleLength(preambleLen
);
463 SetSpreadingFactor((SX127x_SpreadingFactor
)sf
);
464 SetBandwidthCodingRate((SX127x_Bandwidth
)bw
, (SX127x_CodingRate
)cr
);
465 SetFrequencyReg(freq
);
466 SetRxTimeoutUs(interval
);
469 uint32_t ICACHE_RAM_ATTR
SX127xDriver::GetCurrBandwidth()
473 case SX127x_BW_7_80_KHZ
:
475 case SX127x_BW_10_40_KHZ
:
477 case SX127x_BW_15_60_KHZ
:
479 case SX127x_BW_20_80_KHZ
:
481 case SX127x_BW_31_25_KHZ
:
483 case SX127x_BW_41_70_KHZ
:
485 case SX127x_BW_62_50_KHZ
:
487 case SX127x_BW_125_00_KHZ
:
489 case SX127x_BW_250_00_KHZ
:
491 case SX127x_BW_500_00_KHZ
:
497 uint32_t ICACHE_RAM_ATTR
SX127xDriver::GetCurrBandwidthNormalisedShifted() // this is basically just used for speedier calc of the freq offset, pre compiled for 32mhz xtal
502 case SX127x_BW_7_80_KHZ
:
504 case SX127x_BW_10_40_KHZ
:
506 case SX127x_BW_15_60_KHZ
:
508 case SX127x_BW_20_80_KHZ
:
510 case SX127x_BW_31_25_KHZ
:
512 case SX127x_BW_41_70_KHZ
:
514 case SX127x_BW_62_50_KHZ
:
516 case SX127x_BW_125_00_KHZ
:
518 case SX127x_BW_250_00_KHZ
:
520 case SX127x_BW_500_00_KHZ
:
527 * Set the PPMcorrection register to adjust data rate to frequency error
528 * @param offset is in Hz or FREQ_STEP (FREQ_HZ_TO_REG_VAL) units, whichever
529 * was used to SetFrequencyHz/SetFrequencyReg
531 void ICACHE_RAM_ATTR
SX127xDriver::SetPPMoffsetReg(int32_t offset
)
533 int8_t offsetPPM
= (offset
* 1e6
/ currFreq
) * 95 / 100;
534 hal
.writeRegister(SX127x_PPMOFFSET
, (uint8_t)offsetPPM
, processingPacketRadio
);
537 bool ICACHE_RAM_ATTR
SX127xDriver::GetFrequencyErrorbool()
539 return (hal
.readRegister(SX127X_REG_FEI_MSB
, processingPacketRadio
) & 0b1000) >> 3; // returns true if pos freq error, neg if false
542 int32_t ICACHE_RAM_ATTR
SX127xDriver::GetFrequencyError()
545 WORD_ALIGNED_ATTR
uint8_t reg
[3] = {0x0, 0x0, 0x0};
546 hal
.readRegister(SX127X_REG_FEI_MSB
, reg
, sizeof(reg
), processingPacketRadio
);
548 uint32_t RegFei
= ((reg
[0] & 0b0111) << 16) + (reg
[1] << 8) + reg
[2];
550 int32_t intFreqError
= RegFei
;
552 if ((reg
[0] & 0b1000) >> 3)
554 intFreqError
-= 524288; // Sign bit is on
557 int32_t fErrorHZ
= (intFreqError
>> 3) * (SX127xDriver::GetCurrBandwidthNormalisedShifted()); // bit shift hackery so we don't have to use floaty bois; the >> 3 is intentional and is a simplification of the formula on page 114 of sx1276 datasheet
563 uint8_t ICACHE_RAM_ATTR
SX127xDriver::UnsignedGetLastPacketRSSI(SX12XX_Radio_Number_t radioNumber
)
565 return hal
.readRegister(SX127X_REG_PKT_RSSI_VALUE
, radioNumber
);
568 int8_t ICACHE_RAM_ATTR
SX127xDriver::GetLastPacketRSSI()
570 return ((lowFrequencyMode
? -164 : -157) + hal
.readRegister(SX127X_REG_PKT_RSSI_VALUE
, processingPacketRadio
));
573 int8_t ICACHE_RAM_ATTR
SX127xDriver::GetCurrRSSI(SX12XX_Radio_Number_t radioNumber
)
575 return ((lowFrequencyMode
? -164 : -157) + hal
.readRegister(SX127X_REG_RSSI_VALUE
, radioNumber
));
578 int8_t ICACHE_RAM_ATTR
SX127xDriver::GetLastPacketSNRRaw()
580 return (int8_t)hal
.readRegister(SX127X_REG_PKT_SNR_VALUE
, processingPacketRadio
);
583 uint8_t ICACHE_RAM_ATTR
SX127xDriver::GetIrqFlags(SX12XX_Radio_Number_t radioNumber
)
585 return hal
.readRegister(SX127X_REG_IRQ_FLAGS
, radioNumber
);
588 void ICACHE_RAM_ATTR
SX127xDriver::ClearIrqFlags(SX12XX_Radio_Number_t radioNumber
)
590 hal
.writeRegister(SX127X_REG_IRQ_FLAGS
, SX127X_CLEAR_IRQ_FLAG_ALL
, radioNumber
);
593 void ICACHE_RAM_ATTR
SX127xDriver::IsrCallback_1()
595 instance
->IsrCallback(SX12XX_Radio_1
);
598 void ICACHE_RAM_ATTR
SX127xDriver::IsrCallback_2()
600 instance
->IsrCallback(SX12XX_Radio_2
);
603 void ICACHE_RAM_ATTR
SX127xDriver::IsrCallback(SX12XX_Radio_Number_t radioNumber
)
605 instance
->processingPacketRadio
= radioNumber
;
606 SX12XX_Radio_Number_t irqClearRadio
= radioNumber
;
608 uint8_t irqStatus
= instance
->GetIrqFlags(radioNumber
);
609 if (irqStatus
& SX127X_CLEAR_IRQ_FLAG_TX_DONE
)
613 irqClearRadio
= SX12XX_Radio_All
;
615 else if (irqStatus
& SX127X_CLEAR_IRQ_FLAG_RX_DONE
)
617 if (instance
->RXnbISR(radioNumber
))
619 instance
->lastSuccessfulPacketRadio
= radioNumber
;
620 irqClearRadio
= SX12XX_Radio_All
;
624 else if (irqStatus
== SX127X_CLEAR_IRQ_FLAG_NONE
)
629 instance
->ClearIrqFlags(irqClearRadio
);
632 // int16_t MeasureNoiseFloor() TODO disabled for now
634 // int NUM_READS = RSSI_FLOOR_NUM_READS * FHSSgetChannelCount();
635 // float returnval = 0;
637 // for (uint32_t freq = 0; freq < FHSSgetChannelCount(); freq++)
639 // FHSSsetCurrIndex(freq);
640 // Radio.SetMode(SX127X_CAD);
642 // for (int i = 0; i < RSSI_FLOOR_NUM_READS; i++)
644 // returnval = returnval + Radio.GetCurrRSSI();
648 // returnval = returnval / NUM_READS;
649 // return (returnval);
652 // uint8_t SX127xDriver::RunCAD() TODO
654 // SetMode(SX127X_STANDBY);
656 // hal.writeRegisterBits(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
658 // SetMode(SX127X_CAD);
661 // uint32_t startTime = millis();
663 // while (!digitalRead(SX127x_dio0))
665 // if (millis() > (startTime + 500))
667 // return (CHANNEL_FREE);
672 // if (digitalRead(SX127x_dio1))
675 // return (PREAMBLE_DETECTED);
681 // return (CHANNEL_FREE);