6 SX127xDriver
*SX127xDriver::instance
= NULL
;
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()
30 // default values from datasheet
31 currSyncWord
= SX127X_SYNC_WORD
;
32 currBW
=SX127x_BW_125_00_KHZ
;
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
41 headerExplMode
= false;
43 lowFrequencyMode
= SX1278_HIGH_FREQ
;
44 lastSuccessfulPacketRadio
= SX12XX_Radio_1
;
47 bool SX127xDriver::Begin(uint32_t minimumFrequency
, uint32_t maximumFrequency
)
50 hal
.IsrCallback_1
= &SX127xDriver::IsrCallback_1
;
51 hal
.IsrCallback_2
= &SX127xDriver::IsrCallback_2
;
54 DBGLN("SX127x Begin");
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
))
72 if (GPIO_PIN_NSS_2
!= UNDEF_PIN
)
74 if (!DetectChip(SX12XX_Radio_2
))
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
);
91 SetOutputPower(SX127X_MAX_OUTPUT_POWER
);
99 void SX127xDriver::End()
101 SetMode(SX127x_OPMODE_SLEEP
, SX12XX_Radio_All
);
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
);
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
);
181 hal
.writeRegister(SX127X_REG_MODEM_CONFIG_1
, bw
| cr
| SX127x_HEADER_EXPL_MODE
, SX12XX_Radio_All
);
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
);
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
);
217 void SX127xDriver::SetCRCMode(bool 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
);
224 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2
, SX1278_RX_CRC_MODE_ON
, SX1278_RX_CRC_MODE_MASK
, SX12XX_Radio_All
);
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
);
232 hal
.writeRegisterBits(SX127X_REG_MODEM_CONFIG_2
, SX1278_RX_CRC_MODE_OFF
, SX1278_RX_CRC_MODE_MASK
, SX12XX_Radio_All
);
237 bool SyncWordOk(uint8_t syncWord
)
239 for (unsigned int i
= 0; i
< sizeof(SX127x_AllowedSyncwords
); i
++)
241 if (syncWord
== SX127x_AllowedSyncwords
[i
])
249 void SX127xDriver::SetSyncWord(uint8_t syncWord
)
251 uint8_t _syncWord
= syncWord
;
253 while (SyncWordOk(_syncWord
) == false)
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
;
267 * @brief: Schedule an output power change after the next transmit
268 * The radio must be in SX127x_OPMODE_STANDBY to change the power
270 void SX127xDriver::SetOutputPower(uint8_t Power
)
273 Power
&= SX127X_PA_POWER_MASK
;
275 if (OPT_USE_SX1276_RFO_HF
)
277 pwrNew
= SX127X_PA_SELECT_RFO
| Power
;
281 pwrNew
= SX127X_PA_SELECT_BOOST
| Power
;
284 if ((pwrPending
== PWRPENDING_NONE
&& pwrCurrent
!= pwrNew
) || pwrPending
!= pwrNew
)
290 void ICACHE_RAM_ATTR
SX127xDriver::CommitOutputPower()
292 if (pwrPending
== PWRPENDING_NONE
)
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
)
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
);
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
);
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
)
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
354 unsigned int spread
= 0;
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
);
391 bool flagFound
= false;
392 while ((i
< 3) && !flagFound
)
394 uint8_t version
= hal
.readRegister(SX127X_REG_VERSION
, radioNumber
);
396 if (version
== SX127X_VERSION
)
402 DBGLN(" not found! (%d of 3 tries) REG_VERSION == 0x%x", i
+1, version
);
410 DBGLN(" not found!");
415 DBGLN(" found! (match by REG_VERSION == 0x%x", SX127X_VERSION
);
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
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)
436 // DBGLN("abort TX");
437 // return; // we were already TXing so abort. this should never happen!!!
440 transmittingRadio
= radioNumber
;
442 SetMode(SX127x_OPMODE_STANDBY
, SX12XX_Radio_All
);
444 if (radioNumber
== SX12XX_Radio_NONE
)
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
++;
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
);
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
);
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()
499 SetMode(SX127x_OPMODE_RXSINGLE
, SX12XX_Radio_All
);
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
;
542 gotRadio
[secondRadioIdx
] = hasSecondRadioGotData
;
543 #if defined(DEBUG_RCVR_SIGNAL_STATS)
544 if(!hasSecondRadioGotData
)
546 instance
->rxSignalStats
[secondRadioIdx
].fail_count
++;
550 for (uint8_t i
= 0; i
< 2; 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)
581 for (uint8_t i
= 0; i
< 2; 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
++;
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)
617 hal
.writeRegister(SX127X_REG_OP_MODE
, mode
| lowFrequencyMode
, radioNumber
);
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()
641 case SX127x_BW_125_00_KHZ
:
643 case SX127x_BW_250_00_KHZ
:
645 case SX127x_BW_500_00_KHZ
:
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
656 case SX127x_BW_125_00_KHZ
:
658 case SX127x_BW_250_00_KHZ
:
660 case SX127x_BW_500_00_KHZ
:
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
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
)
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)
764 instance
->rxSignalStats
[(radioNumber
== SX12XX_Radio_1
) ? 0 : 1].fail_count
++;
768 else if (irqStatus
== SX127X_CLEAR_IRQ_FLAG_NONE
)
773 instance
->ClearIrqFlags(irqClearRadio
);
776 // int16_t MeasureNoiseFloor() TODO disabled for now
778 // int NUM_READS = RSSI_FLOOR_NUM_READS * FHSSgetChannelCount();
779 // float returnval = 0;
781 // for (uint32_t freq = 0; freq < FHSSgetChannelCount(); freq++)
783 // FHSSsetCurrIndex(freq);
784 // Radio.SetMode(SX127X_CAD);
786 // for (int i = 0; i < RSSI_FLOOR_NUM_READS; i++)
788 // returnval = returnval + Radio.GetCurrRSSI();
792 // returnval = returnval / NUM_READS;
793 // return (returnval);
796 // uint8_t SX127xDriver::RunCAD() TODO
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);
805 // uint32_t startTime = millis();
807 // while (!digitalRead(SX127x_dio0))
809 // if (millis() > (startTime + 500))
811 // return (CHANNEL_FREE);
816 // if (digitalRead(SX127x_dio1))
819 // return (PREAMBLE_DETECTED);
825 // return (CHANNEL_FREE);