Communicate Rx available antenna mode to the Tx (#3039)
[ExpressLRS.git] / src / lib / SX127xDriver / SX127x.cpp
blobb5bf3162627c404c730cb1749587ab5f12dd9ca1
1 #include "SX127x.h"
2 #include "logging.h"
3 #include "RFAMP_hal.h"
5 SX127xHal hal;
6 SX127xDriver *SX127xDriver::instance = NULL;
8 RFAMP_hal RFAMP;
10 const uint8_t SX127x_AllowedSyncwords[105] =
11 {0, 5, 6, 7, 11, 12, 13, 15, 18,
12 21, 23, 26, 29, 30, 31, 33, 34,
13 37, 38, 39, 40, 42, 44, 50, 51,
14 54, 55, 57, 58, 59, 61, 63, 65,
15 67, 68, 71, 77, 78, 79, 80, 82,
16 84, 86, 89, 92, 94, 96, 97, 99,
17 101, 102, 105, 106, 109, 111, 113, 115,
18 117, 118, 119, 121, 122, 124, 126, 127,
19 129, 130, 138, 143, 161, 170, 172, 173,
20 175, 180, 181, 182, 187, 190, 191, 192,
21 193, 196, 199, 201, 204, 205, 208, 209,
22 212, 213, 219, 220, 221, 223, 227, 229,
23 235, 239, 240, 242, 243, 246, 247, 255};
25 //////////////////////////////////////////////
27 SX127xDriver::SX127xDriver(): SX12xxDriverCommon()
29 instance = this;
30 // default values from datasheet
31 currSyncWord = SX127X_SYNC_WORD;
32 currBW =SX127x_BW_125_00_KHZ;
33 currSF = SX127x_SF_7;
34 currCR = SX127x_CR_4_5;
35 currOpmode = SX127x_OPMODE_SLEEP;
36 ModFSKorLoRa = SX127x_OPMODE_LORA;
37 // Dummy default values which are overwritten during setup
38 currPreambleLen = 0;
39 PayloadLength = 8;
40 currFreq = 0;
41 headerExplMode = false;
42 crcEnabled = false;
43 lowFrequencyMode = SX1278_HIGH_FREQ;
44 lastSuccessfulPacketRadio = SX12XX_Radio_1;
47 bool SX127xDriver::Begin(uint32_t minimumFrequency, uint32_t maximumFrequency)
49 hal.init();
50 hal.IsrCallback_1 = &SX127xDriver::IsrCallback_1;
51 hal.IsrCallback_2 = &SX127xDriver::IsrCallback_2;
53 hal.reset();
54 DBGLN("SX127x Begin");
56 RFAMP.init();
58 // currFreq must be set before calling Radio.Begin so that lowFrequencyMode can be set correctly.
59 if (currFreq < (uint32_t)((double)525000000 / (double)FREQ_STEP))
61 lowFrequencyMode = SX1278_LOW_FREQ;
62 DBGLN("Setting 'lowFrequencyMode' used for 433MHz.");
65 SetMode(SX127x_OPMODE_STANDBY, SX12XX_Radio_All);
67 if (!DetectChip(SX12XX_Radio_1))
69 return false;
72 if (GPIO_PIN_NSS_2 != UNDEF_PIN)
74 if (!DetectChip(SX12XX_Radio_2))
76 return false;
80 ConfigLoraDefaults();
81 // Force the next power update, and use the defaults for RFO_HF or PA_BOOST
82 pwrCurrent = PWRPENDING_NONE;
83 if (POWER_OUTPUT_VALUES2 == nullptr)
85 if (OPT_USE_SX1276_RFO_HF)
87 SetOutputPower(SX127X_MAX_OUTPUT_POWER_RFO_HF);
89 else
91 SetOutputPower(SX127X_MAX_OUTPUT_POWER);
94 CommitOutputPower();
96 return true;
99 void SX127xDriver::End()
101 SetMode(SX127x_OPMODE_SLEEP, SX12XX_Radio_All);
102 hal.end();
103 RFAMP.TXRXdisable();
104 RemoveCallbacks();
107 void SX127xDriver::cwRepeat(SX12XX_Radio_Number_t radioNumber)
109 uint8_t dummy[0] = {};
111 ClearIrqFlags(radioNumber);
113 hal.writeRegister(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDR_MAX, radioNumber);
114 hal.writeRegister(SX127X_REG_FIFO, dummy, 0, radioNumber);
116 SetMode(SX127x_OPMODE_TX, radioNumber);
119 void SX127xDriver::startCWTest(uint32_t freq, SX12XX_Radio_Number_t radioNumber)
121 SetPreambleLength(8);
122 SetSpreadingFactor(SX127x_SF_9);
123 SetBandwidthCodingRate(SX127x_BW_125_00_KHZ, SX127x_CR_4_5);
124 SetFrequencyHz(freq, SX12XX_Radio_All);
125 if (freq > 900000000)
127 hal.writeRegister(0x01, 0x80, radioNumber);
128 hal.writeRegister(0x44, 0x7B, radioNumber);
129 hal.writeRegister(0x3D, 0xA1, radioNumber);
130 hal.writeRegister(0x36, 0x01, radioNumber);
131 hal.writeRegister(0x1e, 0x08, radioNumber);
132 hal.writeRegister(0x45, 0xDF, radioNumber);
133 hal.writeRegister(0x46, 0x03, radioNumber);
134 hal.writeRegister(0x4D, 0x87, radioNumber);
135 hal.writeRegister(0x52, 0x60, radioNumber);
137 else
139 hal.writeRegister(0x01, 0x88, radioNumber);
140 hal.writeRegister(0x3D, 0xA1, radioNumber);
141 hal.writeRegister(0x36, 0x01, radioNumber);
142 hal.writeRegister(0x1e, 0x08, radioNumber);
145 RFAMP.TXenable(radioNumber);
146 hal.writeRegister(SX127X_REG_PA_CONFIG, pwrCurrent, radioNumber);
148 cwRepeat(radioNumber);
151 void SX127xDriver::ConfigLoraDefaults()
153 hal.writeRegister(SX127X_REG_OP_MODE, SX127x_OPMODE_SLEEP, SX12XX_Radio_All);
154 hal.writeRegister(SX127X_REG_OP_MODE, ModFSKorLoRa, SX12XX_Radio_All); //must be written in sleep mode
155 SetMode(SX127x_OPMODE_STANDBY, SX12XX_Radio_All);
157 hal.writeRegister(SX127X_REG_PAYLOAD_LENGTH, PayloadLength, SX12XX_Radio_All);
158 SetSyncWord(currSyncWord);
159 hal.writeRegister(SX127X_REG_FIFO_TX_BASE_ADDR, SX127X_FIFO_TX_BASE_ADDR_MAX, SX12XX_Radio_All);
160 hal.writeRegister(SX127X_REG_FIFO_RX_BASE_ADDR, SX127X_FIFO_RX_BASE_ADDR_MAX, SX12XX_Radio_All);
161 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.
162 hal.writeRegister(SX127X_REG_LNA, SX127X_LNA_BOOST_ON, SX12XX_Radio_All);
163 hal.writeRegister(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_ON | SX1278_LOW_DATA_RATE_OPT_OFF, SX12XX_Radio_All);
164 hal.writeRegisterBits(SX127X_REG_OCP, SX127X_OCP_ON | SX127X_OCP_150MA, SX127X_OCP_MASK, SX12XX_Radio_All); //150ma max current
165 SetPreambleLength(SX127X_PREAMBLE_LENGTH_LSB);
168 void SX127xDriver::SetBandwidthCodingRate(SX127x_Bandwidth bw, SX127x_CodingRate cr)
170 if ((currBW != bw) || (currCR != cr))
172 if (currSF == SX127x_SF_6) // set SF6 optimizations
174 hal.writeRegister(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX127x_HEADER_IMPL_MODE, SX12XX_Radio_All);
175 SetCRCMode(false);
177 else
179 if (headerExplMode)
181 hal.writeRegister(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX127x_HEADER_EXPL_MODE, SX12XX_Radio_All);
183 else
185 hal.writeRegister(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX127x_HEADER_IMPL_MODE, SX12XX_Radio_All);
187 SetCRCMode(crcEnabled);
190 #if !defined(RADIO_SX1272) //does not apply to SX1272
191 if (bw == SX127x_BW_500_00_KHZ)
193 // Errata 2.1 Sensitivity Optimization with a 500 kHz Bandwidth https://www.semtech.com/products/wireless-rf/lora-connect/sx1276
194 hal.writeRegister(0x36, 0x02, SX12XX_Radio_All);
195 hal.writeRegister(0x3a, lowFrequencyMode ? 0x7F : 0x64, SX12XX_Radio_All);
198 // Errata 2.3 Receiver Spurious Reception of a LoRa Signal - https://www.semtech.com/products/wireless-rf/lora-connect/sx1276
199 hal.writeRegisterBits(SX127X_REG_DETECT_OPTIMIZE, 0x80, 0x80, SX12XX_Radio_All);
201 else
203 // Errata 2.1 Sensitivity Optimization with a 500 kHz Bandwidth https://www.semtech.com/products/wireless-rf/lora-connect/sx1276
204 hal.writeRegister(0x36, 0x03, SX12XX_Radio_All);
206 // Errata 2.3 Receiver Spurious Reception of a LoRa Signal - https://www.semtech.com/products/wireless-rf/lora-connect/sx1276
207 // !!! Note - Registers 0x2F and 0x30 also need to be corrected if ELRS every uses other BW. Check errata. !!!
208 hal.writeRegisterBits(SX127X_REG_DETECT_OPTIMIZE, 0x00, 0x80, SX12XX_Radio_All);
210 #endif
212 currCR = cr;
213 currBW = bw;
217 void SX127xDriver::SetCRCMode(bool on)
219 if(on)
221 #if defined(RADIO_SX1272)
222 hal.writeRegisterBits(SX127X_REG_MODEM_CONFIG_1, SX1272_RX_CRC_MODE_ON, SX1272_RX_CRC_MODE_MASK, SX12XX_Radio_All);
223 #else
224 hal.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_ON, SX1278_RX_CRC_MODE_MASK, SX12XX_Radio_All);
225 #endif
227 else
229 #if defined(RADIO_SX1272)
230 hal.writeRegisterBits(SX127X_REG_MODEM_CONFIG_1, SX1272_RX_CRC_MODE_OFF, SX1272_RX_CRC_MODE_MASK, SX12XX_Radio_All);
231 #else
232 hal.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_OFF, SX1278_RX_CRC_MODE_MASK, SX12XX_Radio_All);
233 #endif
237 bool SyncWordOk(uint8_t syncWord)
239 for (unsigned int i = 0; i < sizeof(SX127x_AllowedSyncwords); i++)
241 if (syncWord == SX127x_AllowedSyncwords[i])
243 return true;
246 return false;
249 void SX127xDriver::SetSyncWord(uint8_t syncWord)
251 uint8_t _syncWord = syncWord;
253 while (SyncWordOk(_syncWord) == false)
255 _syncWord++;
258 if(syncWord != _syncWord){
259 DBGLN("Using syncword: %d instead of: %d", _syncWord, syncWord);
262 hal.writeRegister(SX127X_REG_SYNC_WORD, _syncWord, SX12XX_Radio_All);
263 currSyncWord = _syncWord;
266 /***
267 * @brief: Schedule an output power change after the next transmit
268 * The radio must be in SX127x_OPMODE_STANDBY to change the power
269 ***/
270 void SX127xDriver::SetOutputPower(uint8_t Power)
272 uint8_t pwrNew;
273 Power &= SX127X_PA_POWER_MASK;
275 if (OPT_USE_SX1276_RFO_HF)
277 pwrNew = SX127X_PA_SELECT_RFO | Power;
279 else
281 pwrNew = SX127X_PA_SELECT_BOOST | Power;
284 if ((pwrPending == PWRPENDING_NONE && pwrCurrent != pwrNew) || pwrPending != pwrNew)
286 pwrPending = pwrNew;
290 void ICACHE_RAM_ATTR SX127xDriver::CommitOutputPower()
292 if (pwrPending == PWRPENDING_NONE)
293 return;
295 pwrCurrent = pwrPending & 0xFF;
296 pwrPending = PWRPENDING_NONE;
297 hal.writeRegister(SX127X_REG_PA_CONFIG, pwrCurrent, SX12XX_Radio_All);
300 void SX127xDriver::SetPreambleLength(uint8_t PreambleLen)
302 if (currPreambleLen != PreambleLen)
304 hal.writeRegister(SX127X_REG_PREAMBLE_LSB, PreambleLen, SX12XX_Radio_All);
305 currPreambleLen = PreambleLen;
309 void SX127xDriver::SetSpreadingFactor(SX127x_SpreadingFactor sf)
311 if (currSF != sf)
313 hal.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2, sf | SX127X_TX_MODE_SINGLE, SX127X_SPREADING_FACTOR_MASK | SX127X_TX_MODE_MASK, SX12XX_Radio_All);
314 if (sf == SX127x_SF_6)
316 hal.writeRegisterBits(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, SX127X_DETECT_OPTIMIZE_SF_MASK, SX12XX_Radio_All);
317 hal.writeRegister(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6, SX12XX_Radio_All);
319 else
321 hal.writeRegisterBits(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, SX127X_DETECT_OPTIMIZE_SF_MASK, SX12XX_Radio_All);
322 hal.writeRegister(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12, SX12XX_Radio_All);
324 currSF = sf;
328 void ICACHE_RAM_ATTR SX127xDriver::SetFrequencyHz(uint32_t freq, SX12XX_Radio_Number_t radioNumber)
330 int32_t regfreq = ((uint32_t)((double)freq / (double)FREQ_STEP));
332 SetFrequencyReg(regfreq, radioNumber);
335 void ICACHE_RAM_ATTR SX127xDriver::SetFrequencyReg(uint32_t regfreq, SX12XX_Radio_Number_t radioNumber)
337 currFreq = regfreq;
338 SetMode(SX127x_OPMODE_STANDBY, radioNumber);
340 uint8_t FRQ_MSB = (uint8_t)((regfreq >> 16) & 0xFF);
341 uint8_t FRQ_MID = (uint8_t)((regfreq >> 8) & 0xFF);
342 uint8_t FRQ_LSB = (uint8_t)(regfreq & 0xFF);
344 WORD_ALIGNED_ATTR uint8_t outbuff[3] = {FRQ_MSB, FRQ_MID, FRQ_LSB}; //check speedup
346 hal.writeRegister(SX127X_REG_FRF_MSB, outbuff, sizeof(outbuff), radioNumber);
349 void ICACHE_RAM_ATTR SX127xDriver::SetRxTimeoutUs(uint32_t interval)
351 timeoutSymbols = 0; // no timeout i.e. use continuous mode
352 if (interval)
354 unsigned int spread = 0;
355 switch (currSF)
357 case SX127x_SF_6:
358 spread = 6;
359 break;
360 case SX127x_SF_7:
361 spread = 7;
362 break;
363 case SX127x_SF_8:
364 spread = 8;
365 break;
366 case SX127x_SF_9:
367 spread = 9;
368 break;
369 case SX127x_SF_10:
370 spread = 10;
371 break;
372 case SX127x_SF_11:
373 spread = 11;
374 break;
375 case SX127x_SF_12:
376 spread = 12;
377 break;
379 uint32_t symbolTimeUs = ((uint32_t)(1 << spread)) * 1000000 / GetCurrBandwidth();
380 timeoutSymbols = interval / symbolTimeUs;
381 hal.writeRegisterBits(SX127X_REG_SYMB_TIMEOUT_MSB, timeoutSymbols >> 8, SX127X_REG_SYMB_TIMEOUT_MSB_MASK, SX12XX_Radio_All); // set the timeout MSB
382 hal.writeRegister(SX127X_REG_SYMB_TIMEOUT_LSB, timeoutSymbols & 0xFF, SX12XX_Radio_All);
383 DBGLN("SetRxTimeout(%u), symbolTime=%uus symbols=%u", interval, (uint32_t)symbolTimeUs, timeoutSymbols);
387 bool SX127xDriver::DetectChip(SX12XX_Radio_Number_t radioNumber)
389 DBG("Detecting radio %x... ", radioNumber);
390 uint8_t i = 0;
391 bool flagFound = false;
392 while ((i < 3) && !flagFound)
394 uint8_t version = hal.readRegister(SX127X_REG_VERSION, radioNumber);
395 DBG("%x", version);
396 if (version == SX127X_VERSION)
398 flagFound = true;
400 else
402 DBGLN(" not found! (%d of 3 tries) REG_VERSION == 0x%x", i+1, version);
403 delay(200);
404 i++;
408 if (!flagFound)
410 DBGLN(" not found!");
411 return false;
413 else
415 DBGLN(" found! (match by REG_VERSION == 0x%x", SX127X_VERSION);
417 return true;
420 /////////////////////////////////////TX functions/////////////////////////////////////////
422 void ICACHE_RAM_ATTR SX127xDriver::TXnbISR()
424 currOpmode = SX127x_OPMODE_STANDBY; //goes into standby after transmission
425 //TXdoneMicros = micros();
426 // The power level must be changed when in SX127x_OPMODE_STANDBY, so this lags power
427 // changes by at most 1 packet, but does not interrupt any pending RX/TX
428 CommitOutputPower();
429 TXdoneCallback();
432 void ICACHE_RAM_ATTR SX127xDriver::TXnb(uint8_t * data, uint8_t size, bool sendGeminiBuffer, uint8_t * dataGemini, SX12XX_Radio_Number_t radioNumber)
434 // if (currOpmode == SX127x_OPMODE_TX)
435 // {
436 // DBGLN("abort TX");
437 // return; // we were already TXing so abort. this should never happen!!!
438 // }
440 transmittingRadio = radioNumber;
442 SetMode(SX127x_OPMODE_STANDBY, SX12XX_Radio_All);
444 if (radioNumber == SX12XX_Radio_NONE)
446 return;
449 #if defined(DEBUG_RCVR_SIGNAL_STATS)
450 if (radioNumber == SX12XX_Radio_All || radioNumber == SX12XX_Radio_1)
452 instance->rxSignalStats[0].telem_count++;
454 if (radioNumber == SX12XX_Radio_All || radioNumber == SX12XX_Radio_2)
456 instance->rxSignalStats[1].telem_count++;
458 #endif
460 RFAMP.TXenable(radioNumber);
461 hal.writeRegister(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDR_MAX, radioNumber);
462 if (sendGeminiBuffer)
464 hal.writeRegister(SX127X_REG_FIFO, data, size, SX12XX_Radio_1);
465 hal.writeRegister(SX127X_REG_FIFO, dataGemini, size, SX12XX_Radio_2);
467 else
469 hal.writeRegister(SX127X_REG_FIFO, data, size, radioNumber);
472 SetMode(SX127x_OPMODE_TX, radioNumber);
475 ///////////////////////////////////RX Functions Non-Blocking///////////////////////////////////////////
477 bool ICACHE_RAM_ATTR SX127xDriver::RXnbISR(SX12XX_Radio_Number_t radioNumber)
479 uint8_t const FIFOaddr = hal.readRegister(SX127X_REG_FIFO_RX_CURRENT_ADDR, radioNumber);
480 hal.writeRegister(SX127X_REG_FIFO_ADDR_PTR, FIFOaddr, radioNumber);
481 hal.readRegister(SX127X_REG_FIFO, RXdataBuffer, PayloadLength, radioNumber);
483 if (timeoutSymbols)
485 // From page 42 of the datasheet rev 7
486 // In Rx Single mode, the device will return to Standby mode as soon as the interrupt occurs
487 currOpmode = SX127x_OPMODE_STANDBY;
490 return RXdoneCallback(SX12XX_RX_OK);
493 void ICACHE_RAM_ATTR SX127xDriver::RXnb()
495 RFAMP.RXenable();
497 if (timeoutSymbols)
499 SetMode(SX127x_OPMODE_RXSINGLE, SX12XX_Radio_All);
501 else
503 SetMode(SX127x_OPMODE_RXCONTINUOUS, SX12XX_Radio_All);
507 void ICACHE_RAM_ATTR SX127xDriver::CheckForSecondPacket()
509 SX12XX_Radio_Number_t radio[2] = {SX12XX_Radio_1, SX12XX_Radio_2};
510 uint8_t processingRadioIdx = (instance->processingPacketRadio == SX12XX_Radio_1) ? 0 : 1;
511 uint8_t secondRadioIdx = !processingRadioIdx;
513 // processingRadio always passed the sanity check here
514 gotRadio[processingRadioIdx] = true;
515 gotRadio[secondRadioIdx] = false;
517 hasSecondRadioGotData = false;
519 if (GPIO_PIN_NSS_2 != UNDEF_PIN)
521 uint16_t secondIrqStatus = instance->GetIrqFlags(radio[secondRadioIdx]);
522 if(secondIrqStatus & SX127X_CLEAR_IRQ_FLAG_RX_DONE)
524 uint8_t const FIFOaddr = hal.readRegister(SX127X_REG_FIFO_RX_CURRENT_ADDR, radio[secondRadioIdx]);
525 hal.writeRegister(SX127X_REG_FIFO_ADDR_PTR, FIFOaddr, radio[secondRadioIdx]);
526 hal.readRegister(SX127X_REG_FIFO, RXdataBufferSecond, PayloadLength, radio[secondRadioIdx]);
528 hasSecondRadioGotData = true;
533 void ICACHE_RAM_ATTR SX127xDriver::GetLastPacketStats()
535 SX12XX_Radio_Number_t radio[2] = {SX12XX_Radio_1, SX12XX_Radio_2};
536 uint8_t processingRadioIdx = (instance->processingPacketRadio == SX12XX_Radio_1) ? 0 : 1;
537 uint8_t secondRadioIdx = !processingRadioIdx;
539 int8_t rssi[2];
540 int8_t snr[2];
542 gotRadio[secondRadioIdx] = hasSecondRadioGotData;
543 #if defined(DEBUG_RCVR_SIGNAL_STATS)
544 if(!hasSecondRadioGotData)
546 instance->rxSignalStats[secondRadioIdx].fail_count++;
548 #endif
550 for (uint8_t i = 0; i < 2; i++)
552 if (gotRadio[i])
554 rssi[i] = GetLastPacketRSSI(radio[i]);
555 snr[i] = GetLastPacketSNRRaw(radio[i]);
556 // https://www.mouser.com/datasheet/2/761/sx1276-1278113.pdf
557 // Section 3.5.5 (page 87)
558 int8_t negOffset = (snr[i] < 0) ? (snr[i] / RADIO_SNR_SCALE) : 0;
559 rssi[i] += negOffset;
561 // If radio # is 0, update LastPacketRSSI, otherwise LastPacketRSSI2
562 (i == 0) ? LastPacketRSSI = rssi[i] : LastPacketRSSI2 = rssi[i];
563 // Update whatever SNRs we have
564 LastPacketSNRRaw = snr[i];
568 // by default, set the last successful packet radio to be the current processing radio (which got a successful packet)
569 instance->lastSuccessfulPacketRadio = instance->processingPacketRadio;
571 // when both radio got the packet, use the better RSSI one
572 if (gotRadio[0] && gotRadio[1])
574 LastPacketSNRRaw = instance->fuzzy_snr(snr[0], snr[1], instance->FuzzySNRThreshold);
575 // Update the last successful packet radio to be the one with better signal strength
576 instance->lastSuccessfulPacketRadio = (rssi[0] > rssi[1]) ? radio[0] : radio[1];
579 #if defined(DEBUG_RCVR_SIGNAL_STATS)
580 // stat updates
581 for (uint8_t i = 0; i < 2; i++)
583 if (gotRadio[i])
585 instance->rxSignalStats[i].irq_count++;
586 instance->rxSignalStats[i].rssi_sum += rssi[i];
587 instance->rxSignalStats[i].snr_sum += snr[i];
588 if (snr[i] > instance->rxSignalStats[i].snr_max)
590 instance->rxSignalStats[i].snr_max = snr[i];
592 LastPacketSNRRaw = snr[i];
595 if (gotRadio[0] || gotRadio[1])
597 instance->irq_count_or++;
599 if (gotRadio[0] && gotRadio[1])
601 instance->irq_count_both++;
603 #endif
606 void ICACHE_RAM_ATTR SX127xDriver::SetMode(SX127x_RadioOPmodes mode, SX12XX_Radio_Number_t radioNumber)
609 Comment out since it is difficult to keep track of dual radios.
610 When checking SPI it is also useful to see every possible SPI transaction to make sure it fits when required.
612 // if (mode == currOpmode)
613 // {
614 // return;
615 // }
617 hal.writeRegister(SX127X_REG_OP_MODE, mode | lowFrequencyMode, radioNumber);
618 currOpmode = mode;
621 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)
623 Config(bw, sf, cr, freq, preambleLen, currSyncWord, InvertIQ, _PayloadLength, interval);
626 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)
628 PayloadLength = _PayloadLength;
629 ConfigLoraDefaults();
630 SetPreambleLength(preambleLen);
631 SetSpreadingFactor((SX127x_SpreadingFactor)sf);
632 SetBandwidthCodingRate((SX127x_Bandwidth)bw, (SX127x_CodingRate)cr);
633 SetFrequencyReg(freq);
634 SetRxTimeoutUs(interval);
637 uint32_t ICACHE_RAM_ATTR SX127xDriver::GetCurrBandwidth()
639 switch (currBW)
641 case SX127x_BW_125_00_KHZ:
642 return 125E3;
643 case SX127x_BW_250_00_KHZ:
644 return 250E3;
645 case SX127x_BW_500_00_KHZ:
646 return 500E3;
648 return -1;
651 uint32_t ICACHE_RAM_ATTR SX127xDriver::GetCurrBandwidthNormalisedShifted() // this is basically just used for speedier calc of the freq offset, pre compiled for 32mhz xtal
654 switch (currBW)
656 case SX127x_BW_125_00_KHZ:
657 return 64;
658 case SX127x_BW_250_00_KHZ:
659 return 32;
660 case SX127x_BW_500_00_KHZ:
661 return 16;
663 return -1;
667 * Set the PPMcorrection register to adjust data rate to frequency error
668 * @param offset is in Hz or FREQ_STEP (FREQ_HZ_TO_REG_VAL) units, whichever
669 * was used to SetFrequencyHz/SetFrequencyReg
671 void ICACHE_RAM_ATTR SX127xDriver::SetPPMoffsetReg(int32_t offset, SX12XX_Radio_Number_t radioNumber)
673 int8_t offsetPPM = (offset * 1000000 / currFreq) * 95 / 100;
674 hal.writeRegister(SX127x_PPMOFFSET, (uint8_t)offsetPPM, radioNumber);
677 bool ICACHE_RAM_ATTR SX127xDriver::GetFrequencyErrorbool(SX12XX_Radio_Number_t radioNumber)
679 return (hal.readRegister(SX127X_REG_FEI_MSB, radioNumber) & 0b1000) >> 3; // returns true if pos freq error, neg if false
682 int32_t ICACHE_RAM_ATTR SX127xDriver::GetFrequencyError()
685 WORD_ALIGNED_ATTR uint8_t reg[3] = {0x0, 0x0, 0x0};
686 hal.readRegister(SX127X_REG_FEI_MSB, reg, sizeof(reg), processingPacketRadio);
688 uint32_t RegFei = ((reg[0] & 0b0111) << 16) + (reg[1] << 8) + reg[2];
690 int32_t intFreqError = RegFei;
692 if ((reg[0] & 0b1000) >> 3)
694 intFreqError -= 524288; // Sign bit is on
697 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
698 fErrorHZ >>= 4;
700 return fErrorHZ;
703 uint8_t ICACHE_RAM_ATTR SX127xDriver::UnsignedGetLastPacketRSSI(SX12XX_Radio_Number_t radioNumber)
705 return hal.readRegister(SX127X_REG_PKT_RSSI_VALUE, radioNumber);
708 int8_t ICACHE_RAM_ATTR SX127xDriver::GetLastPacketRSSI(SX12XX_Radio_Number_t radioNumber)
710 return ((lowFrequencyMode ? -164 : -157) + hal.readRegister(SX127X_REG_PKT_RSSI_VALUE, radioNumber));
713 int8_t ICACHE_RAM_ATTR SX127xDriver::GetCurrRSSI(SX12XX_Radio_Number_t radioNumber)
715 return ((lowFrequencyMode ? -164 : -157) + hal.readRegister(SX127X_REG_RSSI_VALUE, radioNumber));
718 int8_t ICACHE_RAM_ATTR SX127xDriver::GetLastPacketSNRRaw(SX12XX_Radio_Number_t radioNumber)
720 return (int8_t)hal.readRegister(SX127X_REG_PKT_SNR_VALUE, radioNumber);
723 uint8_t ICACHE_RAM_ATTR SX127xDriver::GetIrqFlags(SX12XX_Radio_Number_t radioNumber)
725 return hal.readRegister(SX127X_REG_IRQ_FLAGS, radioNumber);
728 void ICACHE_RAM_ATTR SX127xDriver::ClearIrqFlags(SX12XX_Radio_Number_t radioNumber)
730 hal.writeRegister(SX127X_REG_IRQ_FLAGS, SX127X_CLEAR_IRQ_FLAG_ALL, radioNumber);
733 void ICACHE_RAM_ATTR SX127xDriver::IsrCallback_1()
735 instance->IsrCallback(SX12XX_Radio_1);
738 void ICACHE_RAM_ATTR SX127xDriver::IsrCallback_2()
740 instance->IsrCallback(SX12XX_Radio_2);
743 void ICACHE_RAM_ATTR SX127xDriver::IsrCallback(SX12XX_Radio_Number_t radioNumber)
745 instance->processingPacketRadio = radioNumber;
746 SX12XX_Radio_Number_t irqClearRadio = radioNumber;
748 uint8_t irqStatus = instance->GetIrqFlags(radioNumber);
749 if (irqStatus & SX127X_CLEAR_IRQ_FLAG_TX_DONE)
751 RFAMP.TXRXdisable();
752 instance->TXnbISR();
753 irqClearRadio = SX12XX_Radio_All;
755 else if (irqStatus & SX127X_CLEAR_IRQ_FLAG_RX_DONE)
757 if (instance->RXnbISR(radioNumber))
759 irqClearRadio = SX12XX_Radio_All;
761 #if defined(DEBUG_RCVR_SIGNAL_STATS)
762 else
764 instance->rxSignalStats[(radioNumber == SX12XX_Radio_1) ? 0 : 1].fail_count++;
766 #endif
768 else if (irqStatus == SX127X_CLEAR_IRQ_FLAG_NONE)
770 return;
773 instance->ClearIrqFlags(irqClearRadio);
776 // int16_t MeasureNoiseFloor() TODO disabled for now
777 // {
778 // int NUM_READS = RSSI_FLOOR_NUM_READS * FHSSgetChannelCount();
779 // float returnval = 0;
781 // for (uint32_t freq = 0; freq < FHSSgetChannelCount(); freq++)
782 // {
783 // FHSSsetCurrIndex(freq);
784 // Radio.SetMode(SX127X_CAD);
786 // for (int i = 0; i < RSSI_FLOOR_NUM_READS; i++)
787 // {
788 // returnval = returnval + Radio.GetCurrRSSI();
789 // delay(5);
790 // }
791 // }
792 // returnval = returnval / NUM_READS;
793 // return (returnval);
794 // }
796 // uint8_t SX127xDriver::RunCAD() TODO
797 // {
798 // SetMode(SX127X_STANDBY);
800 // hal.writeRegisterBits(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
802 // SetMode(SX127X_CAD);
803 // ClearIrqFlags();
805 // uint32_t startTime = millis();
807 // while (!digitalRead(SX127x_dio0))
808 // {
809 // if (millis() > (startTime + 500))
810 // {
811 // return (CHANNEL_FREE);
812 // }
813 // else
814 // {
815 // //yield();
816 // if (digitalRead(SX127x_dio1))
817 // {
818 // ClearIrqFlags();
819 // return (PREAMBLE_DETECTED);
820 // }
821 // }
822 // }
824 // ClearIrqFlags();
825 // return (CHANNEL_FREE);
826 // }