Hardware Abstraction Layer, permitting any LoRa application to use any LoRa radio chip
Dependents: alarm_slave alarm_master lora_p2p lorawan1v1 ... more
radio_sx127x.cpp
00001 #include "radio.h" 00002 #ifdef SX127x_H 00003 00004 #ifdef DEVICE_LPTICKER 00005 LowPowerTimer Radio::lpt; 00006 LowPowerTimeout TxTimeoutEvent; 00007 #else 00008 Timer Radio::lpt; 00009 Timeout TxTimeoutEvent; 00010 #endif 00011 00012 #if (MBED_MAJOR_VERSION < 6) 00013 volatile us_timestamp_t Radio::irqAt; 00014 #else 00015 using namespace std::chrono; 00016 LowPowerClock::time_point Radio::irqAt; 00017 #endif 00018 00019 void Radio::Sleep() 00020 { 00021 radio.set_opmode(RF_OPMODE_SLEEP); 00022 } 00023 00024 void Radio::Standby() 00025 { 00026 radio.set_opmode(RF_OPMODE_STANDBY); 00027 } 00028 00029 bool Radio::CheckRfFrequency(unsigned hz) 00030 { 00031 return true; 00032 } 00033 00034 void Radio::SetChannel(unsigned hz) 00035 { 00036 radio.set_frf_MHz(hz / 1000000.0); 00037 } 00038 00039 float Radio::getFrfMHz() 00040 { 00041 return radio.get_frf_MHz(); 00042 } 00043 00044 void SX1272OnTimeoutIrq( void ) 00045 { 00046 Radio::radio.set_opmode(RF_OPMODE_STANDBY); 00047 } 00048 00049 void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us) 00050 { 00051 fsk.enable(true); 00052 fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2); 00053 fsk.RegPktConfig2.bits.DataModePacket = 0; // continuous mode 00054 radio.write_u16(REG_FSK_PACKETCONFIG2, fsk.RegPktConfig2.word); 00055 fsk.set_tx_fdev_hz(0); // unmodulated carrier, aka dead carrier 00056 SetChannel(hz); 00057 set_tx_dbm(dbm); 00058 00059 if (timeout_us != 0) { 00060 #if (MBED_MAJOR_VERSION < 6) 00061 TxTimeoutEvent.attach_us(SX1272OnTimeoutIrq, timeout_us); 00062 #else 00063 TxTimeoutEvent.attach(SX1272OnTimeoutIrq, microseconds(timeout_us)); 00064 #endif 00065 } 00066 00067 radio.set_opmode(RF_OPMODE_TRANSMITTER); 00068 } 00069 00070 #define LORA_MAC_PRIVATE_SYNCWORD 0x12 00071 #define LORA_MAC_PUBLIC_SYNCWORD 0x34 00072 void Radio::SetPublicNetwork(bool en) 00073 { 00074 radio.write_reg(REG_LR_SYNC_BYTE, en ? LORA_MAC_PUBLIC_SYNCWORD : LORA_MAC_PRIVATE_SYNCWORD); 00075 } 00076 00077 uint32_t Radio::Random(void) 00078 { 00079 uint32_t ret = 0; 00080 unsigned i; 00081 00082 radio.set_opmode(RF_OPMODE_RECEIVER); 00083 for (i = 0; i < 32; i++) { 00084 uint32_t r; 00085 wait_us(3000); 00086 r = radio.read_reg(REG_LR_WIDEBAND_RSSI); 00087 r <<= ((i & 7) << 2); 00088 ret ^= r; 00089 } 00090 00091 return ret; 00092 } 00093 00094 void Radio::LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ) 00095 { 00096 lora.RegPreamble = preambleLen; 00097 radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble); 00098 00099 if (radio.type == SX1276) { 00100 lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn = fixLen; 00101 lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn = crcOn; 00102 radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); 00103 } else if (radio.type == SX1272) { 00104 lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn = fixLen; 00105 lora.RegModemConfig.sx1272bits.RxPayloadCrcOn = crcOn; 00106 } 00107 00108 radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet); 00109 00110 lora.invert_tx(invIQ); 00111 lora.invert_rx(invIQ); 00112 } 00113 00114 void Radio::GFSKModemConfig(unsigned bps, unsigned bw_hz, unsigned fdev_hz) 00115 { 00116 if (radio.RegOpMode.bits.LongRangeMode) 00117 fsk.enable(false); 00118 00119 fsk.set_bitrate(bps); 00120 00121 fsk.set_rx_dcc_bw_hz(bw_hz, 0); 00122 fsk.set_rx_dcc_bw_hz(bw_hz * 1.5, 1); 00123 00124 fsk.set_tx_fdev_hz(fdev_hz); 00125 } 00126 00127 00128 void Radio::GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn) 00129 { 00130 if (radio.RegOpMode.bits.LongRangeMode) 00131 fsk.enable(false); 00132 00133 radio.write_u16(REG_FSK_PREAMBLEMSB, preambleLen); 00134 00135 fsk.RegPktConfig1.bits.PacketFormatVariable = fixLen ? 0 : 1; 00136 fsk.RegPktConfig1.bits.CrcOn = crcOn; 00137 radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet); 00138 } 00139 00140 void Radio::SetLoRaSymbolTimeout(uint16_t symbs) 00141 { 00142 if (!radio.RegOpMode.bits.LongRangeMode) 00143 lora.enable(); 00144 00145 radio.write_reg(REG_LR_SYMBTIMEOUTLSB, symbs & 0xff); 00146 symbs >>= 8; 00147 lora.RegModemConfig2.sx1272bits.SymbTimeoutMsb = symbs; 00148 radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); 00149 } 00150 00151 void Radio::LoRaModemConfig(unsigned bwKHz, uint8_t sf, uint8_t coderate) 00152 { 00153 float sp; 00154 if (!radio.RegOpMode.bits.LongRangeMode) 00155 lora.enable(); 00156 00157 lora.RegModemConfig2.sx1276bits.SpreadingFactor = sf; 00158 radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); 00159 00160 lora.setBw_KHz(bwKHz); 00161 00162 if (radio.type == SX1276) { 00163 lora.RegModemConfig.sx1276bits.CodingRate = coderate; 00164 00165 sp = lora.get_symbol_period(); 00166 if (sp > 16) 00167 lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; 00168 else 00169 lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; 00170 00171 radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet); 00172 } else if (radio.type == SX1272) { 00173 lora.RegModemConfig.sx1272bits.CodingRate = coderate; 00174 00175 if (lora.get_symbol_period() > 16) 00176 lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 1; 00177 else 00178 lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 0; 00179 } 00180 radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet); 00181 } 00182 00183 void Radio::SetRxMaxPayloadLength(uint8_t max) 00184 { 00185 if (radio.RegOpMode.bits.LongRangeMode) 00186 radio.write_reg(REG_LR_RX_MAX_PAYLOADLENGTH, max); 00187 else 00188 radio.write_reg(REG_FSK_PAYLOADLENGTH, max); 00189 } 00190 00191 void Radio::SetFixedPayloadLength(uint8_t len) 00192 { 00193 lora.RegPayloadLength = len; 00194 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); 00195 } 00196 00197 const RadioEvents_t* RadioEvents; 00198 00199 00200 volatile struct pe { 00201 uint8_t dio0 : 1; 00202 uint8_t dio1 : 1; 00203 uint8_t txing : 1; 00204 } pinEvent; 00205 00206 void 00207 Radio::dio0UserContext() 00208 { 00209 service_action_e act = lora.service(); 00210 00211 if (!pinEvent.txing) { 00212 if (act == SERVICE_READ_FIFO && RadioEvents->RxDone) { 00213 int8_t rssi; 00214 float snr = lora.RegPktSnrValue / 4.0; 00215 00216 rssi = lora.get_pkt_rssi(); 00217 if (snr < 0) 00218 rssi += snr; 00219 RadioEvents->RxDone(lora.RegRxNbBytes, rssi, snr); 00220 } 00221 } else if (act == SERVICE_TX_DONE) { 00222 if (RadioEvents->TxDone_botHalf) 00223 RadioEvents->TxDone_botHalf(); 00224 } 00225 } 00226 00227 void Radio::dio0isr() 00228 { 00229 #if (MBED_MAJOR_VERSION < 6) 00230 irqAt = lpt.read_us(); 00231 #else 00232 irqAt = LowPowerClock::now(); 00233 #endif 00234 00235 if (RadioEvents->DioPin_top_half) 00236 RadioEvents->DioPin_top_half(); 00237 00238 if (pinEvent.txing) { 00239 /* TxDone handling requires low latency */ 00240 if (RadioEvents->TxDone_topHalf) 00241 RadioEvents->TxDone_topHalf(); // TODO in callback read irqAt for timestamp of interrupt 00242 00243 } 00244 00245 pinEvent.dio0 = 1; 00246 } 00247 00248 void Radio::dio1UserContext() 00249 { 00250 lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); 00251 00252 if (RadioEvents->RxTimeout) 00253 RadioEvents->RxTimeout(); 00254 00255 radio.write_reg(REG_LR_IRQFLAGS, 0x80); // ensure RxTimeout is cleared 00256 } 00257 00258 void Radio::dio1isr() 00259 { 00260 pinEvent.dio1 = 1; 00261 00262 if (RadioEvents->DioPin_top_half) 00263 RadioEvents->DioPin_top_half(); 00264 } 00265 00266 void Radio::Init(const RadioEvents_t* e, unsigned spi_hz) 00267 { 00268 radio.m_spi.frequency(spi_hz); 00269 00270 while (radio.dio0.read() || radio.dio1.read()) { 00271 radio.write_reg(REG_LR_IRQFLAGS, 0xff); // clear stagnant interrupt 00272 } 00273 dio0.rise(dio0isr); 00274 dio1.rise(dio1isr); 00275 00276 radio.rf_switch = rfsw_callback; 00277 boardInit(); 00278 00279 RadioEvents = e; 00280 lpt.start(); 00281 } 00282 00283 float Radio::GetRssiInst() 00284 { 00285 return lora.get_current_rssi(); 00286 } 00287 00288 int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh) 00289 { 00290 if (radio.RegOpMode.bits.Mode == RF_OPMODE_SLEEP) { 00291 radio.set_opmode(RF_OPMODE_STANDBY); 00292 wait_us(1000); 00293 } 00294 radio.write_reg(REG_LR_IRQFLAGS, 0x08); // ensure TxDone is cleared 00295 lora.RegPayloadLength = size; 00296 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); 00297 00298 if (maxListenTime > 0) { 00299 int rssi; 00300 us_timestamp_t startAt, chFreeAt, now; 00301 lora.start_rx(RF_OPMODE_RECEIVER); 00302 #if (MBED_MAJOR_VERSION < 6) 00303 startAt = lpt.read_us(); 00304 #else 00305 startAt = LowPowerClock::now().time_since_epoch().count(); 00306 #endif 00307 Lstart: 00308 do { 00309 #if (MBED_MAJOR_VERSION < 6) 00310 now = lpt.read_us(); 00311 #else 00312 now = LowPowerClock::now().time_since_epoch().count(); 00313 #endif 00314 if ((now - startAt) > maxListenTime) { 00315 return -1; 00316 } 00317 rssi = lora.get_current_rssi(); 00318 } while (rssi > rssiThresh); 00319 #if (MBED_MAJOR_VERSION < 6) 00320 chFreeAt = lpt.read_us(); 00321 #else 00322 chFreeAt = LowPowerClock::now().time_since_epoch().count(); 00323 #endif 00324 do { 00325 #if (MBED_MAJOR_VERSION < 6) 00326 now = lpt.read_us(); 00327 #else 00328 now = LowPowerClock::now().time_since_epoch().count(); 00329 #endif 00330 rssi = lora.get_current_rssi(); 00331 if (rssi > rssiThresh) { 00332 goto Lstart; 00333 } 00334 } while ((now - chFreeAt) < channelFreeTime); 00335 } 00336 00337 lora.start_tx(size); 00338 pinEvent.txing = 1; 00339 00340 return 0; 00341 } 00342 00343 void Radio::Rx(unsigned timeout) 00344 { 00345 if (timeout == 0) { 00346 lora.start_rx(RF_OPMODE_RECEIVER); 00347 } else { 00348 lora.start_rx(RF_OPMODE_RECEIVER_SINGLE); 00349 } 00350 00351 pinEvent.txing = 0; 00352 } 00353 00354 00355 void Radio::ocp(uint8_t ma) 00356 { 00357 if (ma < 130) 00358 radio.RegOcp.bits.OcpTrim = (ma - 45) / 5; 00359 else 00360 radio.RegOcp.bits.OcpTrim = (ma + 30) / 10; 00361 radio.write_reg(REG_OCP, radio.RegOcp.octet); 00362 00363 radio.RegOcp.octet = radio.read_reg(REG_OCP); 00364 if (radio.RegOcp.bits.OcpTrim < 16) 00365 ma = 45 + (5 * radio.RegOcp.bits.OcpTrim); 00366 else if (radio.RegOcp.bits.OcpTrim < 28) 00367 ma = (10 * radio.RegOcp.bits.OcpTrim) - 30; 00368 else 00369 ma = 240; 00370 } 00371 00372 00373 #if 0 00374 void Radio::PrintStatus() 00375 { 00376 #ifdef MAC_DEBUG 00377 radio.RegOpMode.octet = radio.read_reg(REG_OPMODE); 00378 switch (radio.RegOpMode.bits.Mode) { 00379 case RF_OPMODE_SLEEP: printf("SLEEP "); break; 00380 case RF_OPMODE_STANDBY: printf("STBY "); break; 00381 case RF_OPMODE_SYNTHESIZER_TX: printf("FSTX "); break; 00382 case RF_OPMODE_TRANSMITTER: printf("TX "); break; 00383 case RF_OPMODE_SYNTHESIZER_RX: printf("FSRX "); break; 00384 case RF_OPMODE_RECEIVER: printf("RXC "); break; 00385 case RF_OPMODE_RECEIVER_SINGLE: printf("RXS "); break; 00386 case RF_OPMODE_CAD: printf("CAD "); break; 00387 } 00388 00389 printf("dio:%u:%u opmode:%02x %.2fMHz sf%ubw%u ", radio.dio0.read(), radio.dio1.read(), radio.RegOpMode.octet, radio.get_frf_MHz(), lora.getSf(), lora.getBw()); 00390 lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); 00391 printf("irqFlags:%02x\r\n", lora.RegIrqFlags.octet); 00392 #endif /* MAC_DEBUG */ 00393 } 00394 #endif /* if 0 */ 00395 00396 #ifdef DUTY_ENABLE 00397 us_timestamp_t 00398 Radio::TimeOnAir(RadioModems_t m, uint8_t pktLen) 00399 { 00400 uint32_t airTime = 0; 00401 00402 switch (m) 00403 { 00404 case MODEM_FSK: 00405 { 00406 /* TODO 00407 airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen + 00408 ( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) + 00409 ( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) + 00410 ( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) + 00411 pktLen + 00412 ( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) / 00413 SX1272.Settings.Fsk.Datarate ) * 1e3 ); 00414 */ 00415 } 00416 break; 00417 case MODEM_LORA: 00418 { 00419 double bw = 0.0; 00420 uint8_t fixLen, bandwidth, LowDatarateOptimize, coderate, crcOn ; 00421 if (radio.type == SX1276) { 00422 coderate = lora.RegModemConfig.sx1276bits.CodingRate; 00423 LowDatarateOptimize = lora.RegModemConfig3.sx1276bits.LowDataRateOptimize; 00424 fixLen = lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn; 00425 bandwidth = lora.RegModemConfig.sx1276bits.Bw - 7; 00426 crcOn = lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn; 00427 } else if (radio.type == SX1272) { 00428 coderate = lora.RegModemConfig.sx1272bits.CodingRate; 00429 LowDatarateOptimize = lora.RegModemConfig.sx1272bits.LowDataRateOptimize; 00430 fixLen = lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn; 00431 bandwidth = lora.RegModemConfig.sx1272bits.Bw; 00432 crcOn = lora.RegModemConfig.sx1272bits.RxPayloadCrcOn; 00433 } else 00434 return 0; 00435 00436 switch( bandwidth ) 00437 { 00438 case 0: // 125 kHz 00439 bw = 125;//ms: 125e3; 00440 break; 00441 case 1: // 250 kHz 00442 bw = 250;//ms:250e3; 00443 break; 00444 case 2: // 500 kHz 00445 bw = 500;//ms:500e3; 00446 break; 00447 } 00448 00449 // Symbol rate : time for one symbol (secs) 00450 double rs = bw / ( 1 << lora.RegModemConfig2.sx1276bits.SpreadingFactor ); 00451 double ts = 1 / rs; 00452 // time of preamble 00453 double tPreamble; 00454 tPreamble = (lora.RegPreamble + 4.25 ) * ts; 00455 // Symbol length of payload and time 00456 double tmp = ceil( ( 8 * pktLen - 4 * lora.RegModemConfig2.sx1276bits.SpreadingFactor + 00457 28 + 16 * crcOn - 00458 ( fixLen ? 20 : 0 ) ) / 00459 ( double )( 4 * ( lora.RegModemConfig2.sx1276bits.SpreadingFactor - 00460 ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * 00461 ( coderate + 4 ); 00462 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); 00463 double tPayload = nPayload * ts; 00464 // Time on air 00465 double tOnAir = tPreamble + tPayload; 00466 // return ms secs 00467 airTime = floor( tOnAir * 1e3 + 0.999 ); 00468 } 00469 break; 00470 } 00471 return airTime; 00472 00473 } 00474 #endif /* DUTY_ENABLE */ 00475 00476 void Radio::service() 00477 { 00478 if (pinEvent.dio0) { 00479 dio0UserContext(); 00480 pinEvent.txing = 0; 00481 pinEvent.dio0 = 0; 00482 } else if (radio.dio0.read()) { 00483 /* fail: missed interrupt */ 00484 dio0isr(); 00485 } 00486 00487 if (pinEvent.dio1) { 00488 dio1UserContext(); 00489 pinEvent.dio1 = 0; 00490 } 00491 } 00492 00493 uint32_t Radio::lora_toa_us( uint8_t pktLen ) 00494 { 00495 uint32_t airTime = 0; 00496 uint8_t chipBW = Radio::lora.getBw(); 00497 double bwKHz; 00498 uint8_t LowDataRateOptimize; 00499 bool FixLen; 00500 uint8_t crcOn; 00501 uint16_t preambleLen = Radio::radio.read_u16(REG_LR_PREAMBLEMSB); 00502 00503 Radio::lora.RegModemConfig2.octet = Radio::radio.read_reg(REG_LR_MODEMCONFIG2); 00504 Radio::lora.RegModemConfig.octet = Radio::radio.read_reg(REG_LR_MODEMCONFIG); 00505 00506 if (Radio::radio.type == SX1276) { 00507 chipBW -= 7; 00508 Radio::lora.RegModemConfig3.octet = Radio::radio.read_reg(REG_LR_MODEMCONFIG3); 00509 LowDataRateOptimize = Radio::lora.RegModemConfig3.sx1276bits.LowDataRateOptimize; 00510 FixLen = Radio::lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn; 00511 crcOn = Radio::lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn; 00512 } else if (Radio::radio.type == SX1272) { 00513 LowDataRateOptimize = Radio::lora.RegModemConfig.sx1272bits.LowDataRateOptimize; 00514 FixLen = Radio::lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn; 00515 crcOn = Radio::lora.RegModemConfig.sx1272bits.RxPayloadCrcOn; 00516 } else 00517 return 0; 00518 00519 switch (chipBW) { 00520 case 0: bwKHz = 125; break; 00521 case 1: bwKHz = 250; break; 00522 case 2: bwKHz = 500; break; 00523 default: return 0; 00524 } 00525 00526 // Symbol rate : time for one symbol (secs) 00527 double rs = bwKHz / ( 1 << Radio::lora.RegModemConfig2.sx1276bits.SpreadingFactor ); 00528 double ts = 1 / rs; 00529 // time of preamble 00530 double tPreamble = ( preambleLen + 4.25 ) * ts; 00531 // Symbol length of payload and time 00532 double tmp = ceil( ( 8 * pktLen - 4 * Radio::lora.RegModemConfig2.sx1276bits.SpreadingFactor + 00533 28 + 16 * crcOn - 00534 ( FixLen ? 20 : 0 ) ) / 00535 ( double )( 4 * ( Radio::lora.RegModemConfig2.sx1276bits.SpreadingFactor - 00536 ( ( LowDataRateOptimize > 0 ) ? 2 : 0 ) ) ) ) * 00537 ( Radio::lora.getCodingRate(false) + 4 ); 00538 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); 00539 double tPayload = nPayload * ts; 00540 // Time on air 00541 double tOnAir = tPreamble + tPayload; 00542 // return microseconds 00543 airTime = floor( tOnAir * 1000 + 0.999 ); 00544 00545 return airTime; 00546 } 00547 #endif /* ..SX127x_H */ 00548
Generated on Wed Jul 13 2022 17:56:01 by 1.7.2