Hardware Abstraction Layer, permitting any LoRa application to use any LoRa radio chip
Dependents: alarm_slave alarm_master lora_p2p lorawan1v1 ... more
radio_sx126x.cpp
00001 #include "radio.h" 00002 #ifdef SX126x_H 00003 #include "SPIu.h" 00004 00005 #ifdef DEVICE_LPTICKER 00006 LowPowerTimer Radio::lpt; 00007 #else 00008 Timer Radio::lpt; 00009 #endif 00010 00011 #if (MBED_MAJOR_VERSION < 6) 00012 volatile us_timestamp_t Radio::irqAt; 00013 #else 00014 LowPowerClock::time_point Radio::irqAt; 00015 #endif 00016 00017 bool Radio::paOff; 00018 00019 #ifdef TARGET_FF_ARDUINO 00020 #ifdef TARGET_DISCO_L072CZ_LRWAN1 00021 /* murata type1SJ */ 00022 SPIu spi(PB_15, PB_14, PB_13); // mosi, miso, sclk 00023 //spi, nss, busy, dio1 00024 SX126x Radio::radio(spi, PB_12, PC_2, PB_0); 00025 00026 DigitalOut antswPower(PA_15); 00027 void Radio::chipModeChange() { } 00028 const uint8_t chipType = CHIP_TYPE_SX1262; 00029 #else 00030 /* sx126x arduino shield */ 00031 SPIu spi(D11, D12, D13); // mosi, miso, sclk 00032 //spi, nss, busy, dio1 00033 SX126x Radio::radio(spi, D7, D3, D5); 00034 00035 DigitalOut antswPower(D8); 00036 AnalogIn xtalSel(A3); 00037 00038 DigitalIn Radio::chipType(A2); 00039 00040 #define PINNAME_NRST A0 00041 00042 #define LED_ON 1 00043 #define LED_OFF 0 00044 DigitalOut tx_led(A4); 00045 DigitalOut rx_led(A5); 00046 00047 void Radio::chipModeChange() 00048 { 00049 if (radio.chipMode == CHIPMODE_NONE) { 00050 tx_led = LED_OFF; 00051 rx_led = LED_OFF; 00052 } else if (radio.chipMode == CHIPMODE_TX) { 00053 tx_led = LED_ON; 00054 rx_led = LED_OFF; 00055 } else if (radio.chipMode == CHIPMODE_RX) { 00056 tx_led = LED_OFF; 00057 rx_led = LED_ON; 00058 } 00059 } 00060 #endif /* !TARGET_DISCO_L072CZ_LRWAN1 */ 00061 #endif /* TARGET_FF_ARDUINO */ 00062 00063 const RadioEvents_t* RadioEvents; 00064 PacketParams_t Radio::pp; 00065 RadioModems_t Radio::_m_; 00066 uint8_t Radio::loraTimeoutSymbols; 00067 00068 #if defined(TARGET_FF_MORPHO) && !defined(TARGET_DISCO_L072CZ_LRWAN1) 00069 DigitalOut pc3(PC_3); // debug RX indication, for nucleo boards 00070 #define RX_INDICATION pc3 00071 #endif /* TARGET_FF_MORPHO */ 00072 00073 void Radio::Rx(unsigned timeout) 00074 { 00075 antswPower = 1; 00076 00077 { 00078 uint8_t buf[8]; 00079 IrqFlags_t irqEnable; 00080 irqEnable.word = 0; 00081 irqEnable.bits.RxDone = 1; 00082 irqEnable.bits.Timeout = 1; 00083 00084 buf[0] = irqEnable.word >> 8; // enable bits 00085 buf[1] = irqEnable.word; // enable bits 00086 buf[2] = irqEnable.word >> 8; // dio1 00087 buf[3] = irqEnable.word; // dio1 00088 buf[4] = 0; // dio2 00089 buf[5] = 0; // dio2 00090 buf[6] = 0; // dio3 00091 buf[7] = 0; // dio3 00092 radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf); 00093 } 00094 00095 #ifdef RX_INDICATION 00096 RX_INDICATION = 1; 00097 #endif 00098 if (timeout == 0) { 00099 uint8_t symbs = 0; 00100 if (radio.getPacketType() == PACKET_TYPE_LORA) // shut off timeout 00101 radio.xfer(OPCODE_SET_LORA_SYMBOL_TIMEOUT, 1, 0, &symbs); 00102 00103 radio.start_rx(RX_TIMEOUT_CONTINUOUS); 00104 } else { 00105 if (radio.getPacketType() == PACKET_TYPE_LORA) 00106 radio.xfer(OPCODE_SET_LORA_SYMBOL_TIMEOUT, 1, 0, &loraTimeoutSymbols); 00107 00108 radio.start_rx(timeout * RC_TICKS_PER_US); 00109 } 00110 } 00111 00112 void Radio::Standby() 00113 { 00114 radio.setStandby(STBY_RC); // STBY_XOSC 00115 00116 antswPower = 0; 00117 } 00118 00119 void Radio::Sleep() 00120 { 00121 radio.setSleep(true, false); 00122 00123 antswPower = 0; 00124 } 00125 00126 void Radio::set_tx_dbm(int8_t dbm) 00127 { 00128 unsigned v = radio.readReg(REG_ADDR_ANACTRL16, 1); 00129 00130 if (dbm == PA_OFF_DBM) { 00131 /* bench test: prevent overloading receiving station (very low tx power) */ 00132 if ((v & 0x10) == 0) { 00133 v |= 0x10; 00134 radio.writeReg(REG_ADDR_ANACTRL16, v, 1); 00135 } 00136 paOff = true; 00137 } else { 00138 radio.set_tx_dbm(chipType == CHIP_TYPE_SX1262, dbm); 00139 if (v & 0x10) { 00140 v &= ~0x10; 00141 radio.writeReg(REG_ADDR_ANACTRL16, v, 1); 00142 } 00143 paOff = false; 00144 } 00145 } 00146 00147 void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us) 00148 { 00149 SetChannel(hz); 00150 radio.set_tx_dbm(chipType == CHIP_TYPE_SX1262, dbm); 00151 radio.xfer(OPCODE_SET_TX_CARRIER, 0, 0, NULL); 00152 } 00153 00154 uint32_t Radio::Random(void) 00155 { 00156 uint32_t ret; 00157 00158 radio.start_rx(RX_TIMEOUT_CONTINUOUS); 00159 00160 ret = radio.readReg(REG_ADDR_RANDOM, 4); 00161 00162 Standby(); 00163 00164 return ret; 00165 } 00166 00167 bool Radio::CheckRfFrequency(unsigned hz) 00168 { 00169 return true; 00170 } 00171 00172 void Radio::SetChannel(unsigned hz) 00173 { 00174 radio.setMHz(hz / 1000000.0); 00175 } 00176 00177 float Radio::getFrfMHz() 00178 { 00179 return radio.getMHz(); 00180 } 00181 00182 void Radio::LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ) 00183 { 00184 if (radio.getPacketType() != PACKET_TYPE_LORA) 00185 radio.setPacketType(PACKET_TYPE_LORA); 00186 00187 pp.lora.PreambleLengthHi = preambleLen >> 8; 00188 pp.lora.PreambleLengthLo = preambleLen; 00189 pp.lora.HeaderType = fixLen; 00190 pp.lora.CRCType = crcOn; 00191 pp.lora.InvertIQ = invIQ; 00192 00193 radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, pp.buf); 00194 } 00195 00196 void Radio::GFSKModemConfig(unsigned bps, unsigned bw_hz, unsigned fdev_hz) 00197 { 00198 ModulationParams_t mp; 00199 uint32_t u32; 00200 00201 if (radio.getPacketType() != PACKET_TYPE_GFSK) 00202 radio.setPacketType(PACKET_TYPE_GFSK); 00203 00204 u32 = 32 * (XTAL_FREQ_HZ / bps); 00205 mp.gfsk.bitrateHi = u32 >> 16; // param1 00206 mp.gfsk.bitrateMid = u32 >> 8; // param2 00207 mp.gfsk.bitrateLo = u32; // param3 00208 mp.gfsk.PulseShape = GFSK_SHAPE_BT1_0; // param4 00209 // param5: 00210 if (bw_hz < 5800) 00211 mp.gfsk.bandwidth = GFSK_RX_BW_4800; 00212 else if (bw_hz < 7300) 00213 mp.gfsk.bandwidth = GFSK_RX_BW_5800; 00214 else if (bw_hz < 9700) 00215 mp.gfsk.bandwidth = GFSK_RX_BW_7300; 00216 else if (bw_hz < 11700) 00217 mp.gfsk.bandwidth = GFSK_RX_BW_9700; 00218 else if (bw_hz < 14600) 00219 mp.gfsk.bandwidth = GFSK_RX_BW_11700; 00220 else if (bw_hz < 19500) 00221 mp.gfsk.bandwidth = GFSK_RX_BW_14600; 00222 else if (bw_hz < 23400) 00223 mp.gfsk.bandwidth = GFSK_RX_BW_19500; 00224 else if (bw_hz < 29300) 00225 mp.gfsk.bandwidth = GFSK_RX_BW_23400; 00226 else if (bw_hz < 39000) 00227 mp.gfsk.bandwidth = GFSK_RX_BW_29300; 00228 else if (bw_hz < 46900) 00229 mp.gfsk.bandwidth = GFSK_RX_BW_39000; 00230 else if (bw_hz < 58600) 00231 mp.gfsk.bandwidth = GFSK_RX_BW_46900; 00232 else if (bw_hz < 78200) 00233 mp.gfsk.bandwidth = GFSK_RX_BW_58600; 00234 else if (bw_hz < 93800) 00235 mp.gfsk.bandwidth = GFSK_RX_BW_78200; 00236 else if (bw_hz < 117300) 00237 mp.gfsk.bandwidth = GFSK_RX_BW_93800; 00238 else if (bw_hz < 156200) 00239 mp.gfsk.bandwidth = GFSK_RX_BW_117300; 00240 else if (bw_hz < 187200) 00241 mp.gfsk.bandwidth = GFSK_RX_BW_156200; 00242 else if (bw_hz < 234300) 00243 mp.gfsk.bandwidth = GFSK_RX_BW_187200; 00244 else if (bw_hz < 312000) 00245 mp.gfsk.bandwidth = GFSK_RX_BW_234300; 00246 else if (bw_hz < 373600) 00247 mp.gfsk.bandwidth = GFSK_RX_BW_312000; 00248 else if (bw_hz < 467000) 00249 mp.gfsk.bandwidth = GFSK_RX_BW_373600; 00250 else 00251 mp.gfsk.bandwidth = GFSK_RX_BW_467000; 00252 00253 if (fdev_hz > 0) { 00254 u32 = fdev_hz / FREQ_STEP; 00255 mp.gfsk.fdevHi = u32 >> 16; // param6 00256 mp.gfsk.fdevMid = u32 >> 8; // param7 00257 mp.gfsk.fdevLo = u32; // param8 00258 } 00259 00260 radio.xfer(OPCODE_SET_MODULATION_PARAMS, 8, 0, mp.buf); 00261 } 00262 00263 void Radio::GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn) 00264 { 00265 if (radio.getPacketType() != PACKET_TYPE_GFSK) 00266 radio.setPacketType(PACKET_TYPE_GFSK); 00267 00268 pp.gfsk.PreambleLengthHi = preambleLen >> 8; 00269 pp.gfsk.PreambleLengthLo = preambleLen; 00270 pp.gfsk.PreambleDetectorLength = GFSK_PREAMBLE_DETECTOR_LENGTH_16BITS; 00271 pp.gfsk.SyncWordLength = 24; // 0xC194C1 00272 pp.gfsk.AddrComp = 0; 00273 pp.gfsk.PacketType = fixLen; 00274 if (crcOn) 00275 pp.gfsk.CRCType = GFSK_CRC_2_BYTE; 00276 else 00277 pp.gfsk.CRCType = GFSK_CRC_OFF; 00278 00279 //TODO pp.gfsk.PayloadLength = ; 00280 00281 radio.xfer(OPCODE_SET_PACKET_PARAMS, 8, 0, pp.buf); 00282 } 00283 00284 void Radio::LoRaModemConfig(unsigned bwKHz, uint8_t sf, uint8_t cr) 00285 { 00286 ModulationParams_t mp; 00287 float khz, sp; 00288 00289 if (radio.getPacketType() != PACKET_TYPE_LORA) 00290 radio.setPacketType(PACKET_TYPE_LORA); 00291 00292 if (bwKHz > 250) { 00293 mp.lora.bandwidth = LORA_BW_500; 00294 khz = 500; 00295 } else if (bwKHz > 125) { 00296 mp.lora.bandwidth = LORA_BW_250; 00297 khz = 250; 00298 } else if (bwKHz > 63) { 00299 mp.lora.bandwidth = LORA_BW_125; 00300 khz = 125; 00301 } else if (bwKHz > 42) { 00302 mp.lora.bandwidth = LORA_BW_62; 00303 khz = 62.5; 00304 } else if (bwKHz > 32) { 00305 mp.lora.bandwidth = LORA_BW_41; 00306 khz = 41.67; 00307 } else if (bwKHz > 21) { 00308 mp.lora.bandwidth = LORA_BW_31; 00309 khz = 31.25; 00310 } else if (bwKHz > 16) { 00311 mp.lora.bandwidth = LORA_BW_20; 00312 khz = 20.83; 00313 } else if (bwKHz > 11) { 00314 mp.lora.bandwidth = LORA_BW_15; 00315 khz = 15.625; 00316 } else if (bwKHz > 11) { 00317 mp.lora.bandwidth = LORA_BW_10; 00318 khz = 10.42; 00319 } else { 00320 mp.lora.bandwidth = LORA_BW_7; 00321 khz = 7.81; 00322 } 00323 00324 mp.lora.spreadingFactor = sf; 00325 mp.lora.codingRate = cr; 00326 00327 sp = (1 << mp.lora.spreadingFactor) / khz; 00328 /* TCXO dependent */ 00329 if (sp > 16) 00330 mp.lora.LowDatarateOptimize = 1; // param4 00331 else 00332 mp.lora.LowDatarateOptimize = 0; // param4 00333 00334 radio.xfer(OPCODE_SET_MODULATION_PARAMS, 4, 0, mp.buf); 00335 00336 } 00337 00338 void Radio::SetLoRaSymbolTimeout(uint16_t symbs) 00339 { 00340 if (radio.getPacketType() != PACKET_TYPE_LORA) 00341 radio.setPacketType(PACKET_TYPE_LORA); 00342 00343 loraTimeoutSymbols = symbs; 00344 radio.xfer(OPCODE_SET_LORA_SYMBOL_TIMEOUT, 1, 0, &loraTimeoutSymbols); 00345 } 00346 00347 float Radio::GetRssiInst() 00348 { 00349 uint8_t buf[8]; 00350 00351 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00352 return buf[1] / -2.0; 00353 } 00354 00355 int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh) 00356 { 00357 uint8_t buf[8]; 00358 uint8_t pktType = radio.getPacketType(); 00359 00360 buf[0] = 0; // TX base address 00361 buf[1] = 0; // RX base address 00362 radio.xfer(OPCODE_SET_BUFFER_BASE_ADDR, 2, 0, buf); 00363 00364 if (pktType == PACKET_TYPE_GFSK) { 00365 pp.gfsk.PayloadLength = size; 00366 radio.xfer(OPCODE_SET_PACKET_PARAMS, 8, 0, pp.buf); 00367 } else if (pktType == PACKET_TYPE_LORA) { 00368 pp.lora.PayloadLength = size; 00369 radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, pp.buf); 00370 } 00371 00372 { 00373 IrqFlags_t irqEnable; 00374 irqEnable.word = 0; 00375 irqEnable.bits.TxDone = 1; 00376 irqEnable.bits.Timeout = 1; 00377 00378 buf[0] = irqEnable.word >> 8; // enable bits 00379 buf[1] = irqEnable.word; // enable bits 00380 buf[2] = irqEnable.word >> 8; // dio1 00381 buf[3] = irqEnable.word; // dio1 00382 buf[4] = 0; // dio2 00383 buf[5] = 0; // dio2 00384 buf[6] = 0; // dio3 00385 buf[7] = 0; // dio3 00386 radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf); 00387 } 00388 00389 antswPower = 1; 00390 00391 if (maxListenTime > 0) { 00392 int rssi; 00393 us_timestamp_t startAt, chFreeAt, now; 00394 uint8_t symbs = 0; 00395 00396 radio.xfer(OPCODE_SET_LORA_SYMBOL_TIMEOUT, 1, 0, &symbs); 00397 00398 radio.start_rx(RX_TIMEOUT_CONTINUOUS); 00399 #if (MBED_MAJOR_VERSION < 6) 00400 startAt = lpt.read_us(); 00401 #else 00402 startAt = LowPowerClock::now().time_since_epoch().count(); 00403 #endif 00404 Lstart: 00405 do { 00406 #if (MBED_MAJOR_VERSION < 6) 00407 now = lpt.read_us(); 00408 #else 00409 now = LowPowerClock::now().time_since_epoch().count(); 00410 #endif 00411 if ((now - startAt) > maxListenTime) { 00412 return -1; 00413 } 00414 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00415 rssi = buf[1] / -2; 00416 } while (rssi > rssiThresh); 00417 #if (MBED_MAJOR_VERSION < 6) 00418 chFreeAt = lpt.read_us(); 00419 #else 00420 chFreeAt = LowPowerClock::now().time_since_epoch().count(); 00421 #endif 00422 do { 00423 #if (MBED_MAJOR_VERSION < 6) 00424 now = lpt.read_us(); 00425 #else 00426 now = LowPowerClock::now().time_since_epoch().count(); 00427 #endif 00428 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00429 rssi = buf[1] / -2; 00430 if (rssi > rssiThresh) { 00431 goto Lstart; 00432 } 00433 } while ((now - chFreeAt) < channelFreeTime); 00434 } 00435 00436 if (paOff) { 00437 unsigned v = radio.readReg(REG_ADDR_ANACTRL16, 1); 00438 if ((v & 0x10) == 0) { 00439 v |= 0x10; 00440 radio.writeReg(REG_ADDR_ANACTRL16, v, 1); 00441 } 00442 } 00443 radio.start_tx(size); 00444 00445 return 0; 00446 } // ..Send() 00447 00448 void Radio::SetRxMaxPayloadLength(uint8_t max) 00449 { 00450 uint8_t pktType = radio.getPacketType(); 00451 00452 if (pktType == PACKET_TYPE_GFSK) { 00453 pp.gfsk.PayloadLength = max; 00454 radio.xfer(OPCODE_SET_PACKET_PARAMS, 8, 0, pp.buf); 00455 } else if (pktType == PACKET_TYPE_LORA) { 00456 pp.lora.PayloadLength = max; 00457 radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, pp.buf); 00458 } 00459 } 00460 00461 void Radio::dio1_top_half() 00462 { 00463 #if (MBED_MAJOR_VERSION < 6) 00464 irqAt = lpt.read_us(); 00465 #else 00466 irqAt = LowPowerClock::now(); 00467 #endif 00468 00469 if (RadioEvents->DioPin_top_half) 00470 RadioEvents->DioPin_top_half(); 00471 00472 if (radio.chipMode == CHIPMODE_TX) { 00473 /* TxDone handling requires low latency */ 00474 if (RadioEvents->TxDone_topHalf) { 00475 RadioEvents->TxDone_topHalf(); 00476 } 00477 } else { 00478 #ifdef RX_INDICATION 00479 RX_INDICATION = 0; 00480 #endif 00481 } 00482 } 00483 00484 void Radio::timeout_callback(bool tx) 00485 { 00486 if (!tx) { 00487 if (RadioEvents->RxTimeout) 00488 RadioEvents->RxTimeout(); 00489 #ifdef RX_INDICATION 00490 RX_INDICATION = 0; 00491 #endif 00492 } // else TODO tx timeout 00493 } 00494 00495 void Radio::rx_done(uint8_t size, float rssi, float snr) 00496 { 00497 RadioEvents->RxDone(size, rssi, snr); 00498 } 00499 00500 void Radio::txDoneBottom() 00501 { 00502 if (RadioEvents->TxDone_botHalf) 00503 RadioEvents->TxDone_botHalf(); 00504 } 00505 00506 void to_big_endian24(uint32_t in, uint8_t *out) 00507 { 00508 out[2] = in & 0xff; 00509 in >>= 8; 00510 out[1] = in & 0xff; 00511 in >>= 8; 00512 out[0] = in & 0xff; 00513 } 00514 00515 void Radio::Init(const RadioEvents_t* e, unsigned spi_hz) 00516 { 00517 radio.txDone = txDoneBottom; 00518 radio.rxDone = rx_done; 00519 radio.timeout = timeout_callback; 00520 radio.chipModeChange = chipModeChange; 00521 radio.dio1_topHalf = dio1_top_half; 00522 00523 RadioEvents = e; 00524 lpt.start(); 00525 00526 spi.frequency(spi_hz); 00527 radio.SetDIO2AsRfSwitchCtrl(1); 00528 #ifdef TARGET_DISCO_L072CZ_LRWAN1 00529 /* murata type1SJ */ 00530 { 00531 unsigned tcxoDelayTicks = 3200; 00532 uint8_t buf[4]; 00533 00534 radio.hw_reset(PB_1); 00535 ThisThread::sleep_for(50); 00536 00537 buf[0] = 1; // 1 = 1.7v 00538 to_big_endian24(tcxoDelayTicks, buf+1); 00539 00540 radio.xfer(OPCODE_SET_DIO3_AS_TCXO_CTRL, 4, 0, buf); 00541 } 00542 #endif 00543 } 00544 00545 void Radio::service() 00546 { 00547 radio.service(); 00548 } 00549 00550 void Radio::SetPublicNetwork(bool en) 00551 { 00552 uint16_t ppg; 00553 00554 if (en) 00555 ppg = 0x3444; 00556 else 00557 ppg = 0x1424; 00558 00559 radio.writeReg(REG_ADDR_LORA_SYNC, ppg, 2); 00560 } 00561 00562 uint32_t Radio::lora_toa_us( uint8_t pktLen ) 00563 { 00564 double bwKHz; 00565 unsigned preambleLen; 00566 ModulationParams_t mp; 00567 00568 { 00569 loraConfig1_t conf1; 00570 conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1); 00571 mp.lora.LowDatarateOptimize = conf1.bits.ppm_offset; 00572 pp.lora.HeaderType = conf1.bits.implicit_header; 00573 pp.lora.InvertIQ = conf1.bits.rx_invert_iq; 00574 mp.lora.codingRate = conf1.bits.tx_coding_rate; 00575 } 00576 00577 { 00578 loraConfig2_t conf2; 00579 conf2.octet = radio.readReg(REG_ADDR_LORA_CONFIG2, 1); 00580 pp.lora.CRCType = conf2.bits.tx_payload_crc16_en; 00581 } 00582 00583 00584 { 00585 uint32_t val; 00586 val = radio.readReg(REG_ADDR_LORA_PREAMBLE_SYMBNB, 2); 00587 pp.lora.PreambleLengthHi = val >> 8; 00588 pp.lora.PreambleLengthLo = val; 00589 } 00590 00591 preambleLen = (pp.lora.PreambleLengthHi << 8) + pp.lora.PreambleLengthLo; 00592 00593 { 00594 loraConfig0_t conf0; 00595 conf0.octet = radio.readReg(REG_ADDR_LORA_CONFIG0, 1); 00596 mp.lora.spreadingFactor = conf0.bits.modem_sf; 00597 mp.lora.bandwidth = conf0.bits.modem_bw; 00598 } 00599 00600 switch (mp.lora.bandwidth) { 00601 case LORA_BW_7: bwKHz = 7.81; break; 00602 case LORA_BW_10: bwKHz = 10.42; break; 00603 case LORA_BW_15: bwKHz = 15.625; break; 00604 case LORA_BW_20: bwKHz = 20.83; break; 00605 case LORA_BW_31: bwKHz = 31.25; break; 00606 case LORA_BW_41: bwKHz = 41.67; break; 00607 case LORA_BW_62: bwKHz = 62.5; break; 00608 case LORA_BW_125: bwKHz = 125; break; 00609 case LORA_BW_250: bwKHz = 250; break; 00610 case LORA_BW_500: bwKHz = 500; break; 00611 default: bwKHz = 0; break; 00612 } 00613 00614 // Symbol rate : time for one symbol (secs) 00615 double rs = bwKHz / ( 1 << mp.lora.spreadingFactor ); 00616 double ts = 1 / rs; 00617 // time of preamble 00618 double tPreamble = ( preambleLen + 4.25 ) * ts; 00619 // Symbol length of payload and time 00620 00621 double tmp = ceil( ( 8 * pktLen - 4 * mp.lora.spreadingFactor + 00622 28 + 16 * pp.lora.CRCType - 00623 ( pp.lora.HeaderType ? 20 : 0 ) ) / 00624 ( double )( 4 * ( mp.lora.spreadingFactor - 00625 ( ( mp.lora.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * 00626 ( mp.lora.codingRate + 4 ); 00627 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); 00628 double tPayload = nPayload * ts; 00629 // Time on air 00630 double tOnAir = tPreamble + tPayload; 00631 // return microseconds 00632 return floor( tOnAir * 1000 + 0.999 ); 00633 } 00634 00635 #if 0 00636 void Radio::PrintStatus() 00637 { 00638 /* uint8_t buf[4]; 00639 status_t status; 00640 IrqFlags_t irqFlags; 00641 radio.xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf); 00642 irqFlags.word = buf[1] << 8; 00643 irqFlags.word |= buf[2]; 00644 00645 printf("dio1:%u irqFlags:%04x\r\n", radio.getDIO1(), irqFlags.word); 00646 radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet); 00647 radio.PrintChipStatus(status);*/ 00648 { 00649 loraConfig1_t conf1; 00650 conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1); 00651 printf("ldro%u %s %s cr%u\r\n", 00652 conf1.bits.ppm_offset, 00653 conf1.bits.implicit_header ? "fixed" : "var", 00654 conf1.bits.rx_invert_iq ? "inv" : "std", 00655 conf1.bits.tx_coding_rate 00656 ); 00657 } 00658 00659 { 00660 loraConfig2_t conf2; 00661 conf2.octet = radio.readReg(REG_ADDR_LORA_CONFIG2, 1); 00662 printf("crc16en:%u ", conf2.bits.tx_payload_crc16_en); 00663 } 00664 00665 00666 { 00667 uint32_t val; 00668 val = radio.readReg(REG_ADDR_LORA_PREAMBLE_SYMBNB, 2); 00669 printf("prelen %lu ", val); 00670 } 00671 00672 { 00673 loraConfig0_t conf0; 00674 conf0.octet = radio.readReg(REG_ADDR_LORA_CONFIG0, 1); 00675 printf("sf%u, bw%u ", conf0.bits.modem_sf, conf0.bits.modem_bw); 00676 } 00677 00678 printf("%.3fMHz\r\n", radio.getMHz()); 00679 } 00680 #endif /* if 0 */ 00681 00682 #endif /* ..SX126x_H */
Generated on Wed Jul 13 2022 17:56:01 by 1.7.2