Hardware Abstraction Layer, permitting any LoRa application to use any LoRa radio chip
Dependents: alarm_slave alarm_master lora_p2p lorawan1v1 ... more
radio_sx128x.cpp
00001 #include "radio.h" 00002 #ifdef SX128x_H 00003 #include "SPIu.h" 00004 #include <float.h> 00005 00006 #ifdef DEVICE_LPTICKER 00007 LowPowerTimer Radio::lpt; 00008 #else 00009 Timer Radio::lpt; 00010 #endif 00011 00012 #if (MBED_MAJOR_VERSION < 6) 00013 volatile us_timestamp_t Radio::irqAt; 00014 #else 00015 LowPowerClock::time_point Radio::irqAt; 00016 #endif 00017 00018 #ifdef TARGET_FF_ARDUINO /* pins of SX126xDVK1xAS board */ 00019 #define NRST_PIN A0 00020 SPIu spi(D11, D12, D13); // mosi, miso, sclk 00021 // spi, nss, busy, dio1 00022 SX128x Radio::radio(spi, D7, D3, D5, NRST_PIN); 00023 00024 #define LED_ON 1 00025 #define LED_OFF 0 00026 DigitalOut tx_led(A4); 00027 DigitalOut rx_led(A5); 00028 00029 00030 DigitalOut ant_sw(A3); 00031 DigitalOut cps(D6); // SE2436L 00032 00033 bool fe_enable; // SE2436L 00034 00035 void Radio::chipModeChange() 00036 { 00037 if (radio.chipMode == CHIPMODE_NONE) { 00038 cps = 0; 00039 tx_led = LED_OFF; 00040 rx_led = LED_OFF; 00041 } else if (radio.chipMode == CHIPMODE_TX) { 00042 cps = fe_enable; 00043 tx_led = LED_ON; 00044 rx_led = LED_OFF; 00045 } else if (radio.chipMode == CHIPMODE_RX) { 00046 cps = fe_enable; 00047 tx_led = LED_OFF; 00048 rx_led = LED_ON; 00049 } 00050 } 00051 #endif /* TARGET_FF_ARDUINO */ 00052 00053 #ifdef TARGET_FF_MORPHO 00054 DigitalOut pc3(PC_3); // debug RX indication, for nucleo boards 00055 #define RX_INDICATION pc3 00056 #endif /* TARGET_FF_MORPHO */ 00057 00058 00059 PacketParams_t Radio::ppGFSK; 00060 PacketParams_t Radio::ppLORA; 00061 PacketParams_t Radio::ppFLRC; 00062 00063 ModulationParams_t Radio::mpBLE_GFSK; 00064 ModulationParams_t Radio::mpFLRC; 00065 ModulationParams_t Radio::mpLORA; 00066 00067 const RadioEvents_t* RadioEvents; 00068 00069 unsigned Radio::symbolPeriodUs; 00070 unsigned Radio::nSymbs; 00071 unsigned Radio::rxTimeoutMs; 00072 00073 void Radio::readChip() 00074 { 00075 uint8_t reg8; 00076 00077 reg8 = radio.readReg(REG_ADDR_PKTCTRL0, 1); 00078 ppGFSK.gfskFLRC.HeaderType = reg8 & 0x20; 00079 ppFLRC.gfskFLRC.HeaderType = reg8 & 0x20; 00080 00081 reg8 = radio.readReg(REG_ADDR_PKTCTRL1, 1); 00082 ppGFSK.gfskFLRC.PreambleLength = reg8 & 0x70; 00083 ppFLRC.gfskFLRC.PreambleLength = reg8 & 0x70; 00084 ppGFSK.gfskFLRC.SyncWordLength = reg8 & 0x0e; 00085 ppFLRC.gfskFLRC.SyncWordLength = reg8 & 0x06; 00086 if (ppFLRC.gfskFLRC.SyncWordLength == 0x06) 00087 ppFLRC.gfskFLRC.SyncWordLength = FLRC_SYNC_WORD_LEN_P32S; 00088 00089 reg8 = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_CTRL, 1); 00090 ppGFSK.gfskFLRC.SyncWordMatch = reg8 & 0x70; 00091 ppFLRC.gfskFLRC.SyncWordMatch = reg8 & 0x70; 00092 00093 reg8 = radio.readReg(REG_ADDR_PAYLOAD_LEN, 1); 00094 ppGFSK.gfskFLRC.PayloadLength = reg8; 00095 ppFLRC.gfskFLRC.PayloadLength = reg8; 00096 00097 reg8 = radio.readReg(REG_ADDR_PKT_TX_HEADER, 1); // TODO hi bit of payload length 00098 //ppBLE.ble.ConnectionState = reg8 & 0xe0; 00099 //ppBLE.ble.BleTestPayload = reg8 & 0x1c; 00100 00101 reg8 = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1); 00102 //ppBLE.ble.CrcLength = reg8 & 0x30; 00103 //ppBLE.ble.Whitening = reg8 & 0x08; 00104 ppGFSK.gfskFLRC.CRCLength = reg8 & 0x30; 00105 ppFLRC.gfskFLRC.CRCLength = reg8 & 0x30; 00106 ppGFSK.gfskFLRC.Whitening = reg8 & 0x08; 00107 ppFLRC.gfskFLRC.Whitening = reg8 & 0x08; 00108 00109 { 00110 LoRaPktPar0_t LoRaPktPar0; 00111 LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1); 00112 switch (LoRaPktPar0.bits.modem_bw) { 00113 case 2: mpLORA.lora.bandwidth = LORA_BW_200; break; 00114 case 3: mpLORA.lora.bandwidth = LORA_BW_400; break; 00115 case 4: mpLORA.lora.bandwidth = LORA_BW_800; break; 00116 case 5: mpLORA.lora.bandwidth = LORA_BW_1600; break; 00117 } 00118 mpLORA.lora.spreadingFactor = LoRaPktPar0.bits.modem_sf << 4; 00119 } 00120 00121 { 00122 LoRaPktPar1_t LoRaPktPar1; 00123 LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1); 00124 mpLORA.lora.codingRate = LoRaPktPar1.bits.coding_rate; 00125 ppLORA.lora.InvertIQ = LoRaPktPar1.octet & LORA_IQ_STD; // LoRaPktPar1.bits.rxinvert_iq 00126 ppLORA.lora.HeaderType = LoRaPktPar1.bits.implicit_header ? IMPLICIT_HEADER : EXPLICIT_HEADER; 00127 // LoRaPktPar1.bits.ppm_offset 00128 } 00129 00130 { 00131 LoRaPreambleReg_t LoRaPreambleReg; 00132 LoRaPreambleReg.octet = radio.readReg(REG_ADDR_LORA_PREAMBLE, 1); 00133 ppLORA.lora.PreambleLength = LoRaPreambleReg.bits.preamble_symb1_nb * (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp); 00134 } 00135 ppLORA.lora.PayloadLength = radio.readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1); 00136 00137 { 00138 LoRaLrCtl_t LoRaLrCtl; 00139 LoRaLrCtl.octet = radio.readReg(REG_ADDR_LORA_LRCTL, 1); 00140 ppLORA.lora.crc = LoRaLrCtl.octet & 0x20; // LoRaLrCtl.bits.crc_en 00141 } 00142 00143 { 00144 RegRxBw_t RegRxBw; 00145 unsigned bps; 00146 FloraPreambleHi_t FloraPreambleHi; 00147 float mi, fdev_hz; 00148 unsigned freqDev; 00149 FskModDfH_t FskModDfH; 00150 FskModDfH.octet = radio.readReg(REG_ADDR_FSK_MODDFH, 1); 00151 freqDev = FskModDfH.bits.freqDev; 00152 freqDev <<= 8; 00153 freqDev |= radio.readReg(REG_ADDR_FSK_MODDFL, 1); 00154 fdev_hz = freqDev * PLL_STEP_HZ; 00155 00156 FloraPreambleHi.octet = radio.readReg(REG_ADDR_FLORA_PREAMBLE_HI, 1); 00157 switch (FloraPreambleHi.bits.data_rate) { 00158 case 0: 00159 bps = 2.0e6; 00160 //mpFLRC.flrc.bitrateBandwidth = ??; // 2.6 00161 break; 00162 case 1: 00163 bps = 1.6e6; 00164 //mpFLRC.flrc.bitrateBandwidth = ??; // 2.08 00165 break; 00166 case 2: 00167 bps = 1.0e6; 00168 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_300_BW_1_2; // 1.3 00169 break; 00170 case 3: 00171 bps = 0.8e6; 00172 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_000_BW_1_2; // 1.04 00173 break; 00174 case 4: 00175 bps = 0.5e6; 00176 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_650_BW_0_6; // 0.65 00177 break; 00178 case 5: 00179 bps = 0.4e6; 00180 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_520_BW_0_6; // 0.52 00181 break; 00182 case 6: 00183 bps = 0.25e6; 00184 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_325_BW_0_3; // 0.325 00185 break; 00186 case 7: 00187 bps = 0.125e6; 00188 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_260_BW_0_3; // 0.26 00189 break; 00190 } 00191 00192 mi = (fdev_hz * 2.0) / bps; 00193 if (mi > 0.35) { 00194 mi -= 0.5; 00195 mi /= 0.25; 00196 mpBLE_GFSK.gfskBle.ModulationIndex = ((uint8_t)mi) + 1; 00197 } else 00198 mpBLE_GFSK.gfskBle.ModulationIndex = 0; 00199 00200 RegRxBw.octet = radio.readReg(REG_ADDR_RXBW, 1); 00201 00202 switch (RegRxBw.bits.bw) { 00203 case 0: 00204 if (FloraPreambleHi.bits.data_rate == 0) 00205 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_2_000_BW_2_4; 00206 if (FloraPreambleHi.bits.data_rate == 1) 00207 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_600_BW_2_4; 00208 if (FloraPreambleHi.bits.data_rate == 2) 00209 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_2_4; 00210 if (FloraPreambleHi.bits.data_rate == 3) 00211 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_2_4; 00212 break; 00213 case 1: 00214 if (FloraPreambleHi.bits.data_rate == 2) 00215 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_1_2; 00216 if (FloraPreambleHi.bits.data_rate == 3) 00217 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_1_2; 00218 if (FloraPreambleHi.bits.data_rate == 4) 00219 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_1_2; 00220 if (FloraPreambleHi.bits.data_rate == 5) 00221 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_1_2; 00222 break; 00223 case 2: 00224 if (FloraPreambleHi.bits.data_rate == 4) 00225 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_0_6; 00226 if (FloraPreambleHi.bits.data_rate == 5) 00227 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_0_6; 00228 if (FloraPreambleHi.bits.data_rate == 6) 00229 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_6; 00230 break; 00231 case 3: 00232 if (FloraPreambleHi.bits.data_rate == 6) 00233 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_3; 00234 if (FloraPreambleHi.bits.data_rate == 7) 00235 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_125_BW_0_3; 00236 break; 00237 } 00238 mpBLE_GFSK.gfskBle.bitrateBandwidth = reg8; 00239 } 00240 00241 { 00242 FskCfg_t FskCfg; 00243 FskCfg.octet = radio.readReg(REG_ADDR_FSK_CFG, 1); 00244 mpBLE_GFSK.gfskBle.ModulationShaping = FskCfg.bits.gf_bt << 4; 00245 mpFLRC.flrc.ModulationShaping = mpBLE_GFSK.gfskBle.ModulationShaping; 00246 } 00247 00248 { 00249 PktBitStreamCtrl_t PktBitStreamCtrl; 00250 PktBitStreamCtrl.octet = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1); 00251 mpFLRC.flrc.CodingRate = PktBitStreamCtrl.octet & 0x06; // PktBitStreamCtrl.bits.flora_coding_rate 00252 } 00253 00254 } 00255 00256 void Radio:: diox_top_half() 00257 { 00258 #if (MBED_MAJOR_VERSION < 6) 00259 irqAt = lpt.read_us(); 00260 #else 00261 irqAt = LowPowerClock::now(); 00262 #endif 00263 00264 if (RadioEvents->DioPin_top_half) 00265 RadioEvents->DioPin_top_half(); 00266 00267 if (radio.chipMode == CHIPMODE_TX) { 00268 /* TxDone handling requires low latency */ 00269 if (RadioEvents->TxDone_topHalf) { 00270 RadioEvents->TxDone_topHalf(); 00271 } 00272 } else { 00273 #ifdef RX_INDICATION 00274 RX_INDICATION = 0; 00275 #endif 00276 } 00277 } 00278 00279 void Radio::rxDone(uint8_t size, const pktStatus_t* pktStatus) 00280 { 00281 float rssi, snr; 00282 00283 if (pktStatus->ble_gfsk_flrc.sync.syncAddrsCode == 0) { 00284 int8_t s = pktStatus->lora.snr; 00285 rssi = -pktStatus->lora.rssiSync / 2.0; 00286 snr = s / 4.0; 00287 } else { 00288 rssi = -pktStatus->ble_gfsk_flrc.rssiSync / 2.0; 00289 snr = FLT_MIN; 00290 } 00291 00292 RadioEvents->RxDone(size, rssi, snr); 00293 } 00294 00295 void Radio::timeout_callback(bool tx) 00296 { 00297 if (!tx) { 00298 if (RadioEvents->RxTimeout) 00299 RadioEvents->RxTimeout(); 00300 #ifdef RX_INDICATION 00301 RX_INDICATION = 0; 00302 #endif 00303 } // else TODO tx timeout 00304 } 00305 00306 void Radio::txDoneBottom() 00307 { 00308 if (RadioEvents->TxDone_botHalf) 00309 RadioEvents->TxDone_botHalf(); 00310 } 00311 00312 void Radio::Init(const RadioEvents_t* e, unsigned spi_hz) 00313 { 00314 uint64_t sa; 00315 00316 radio.txDone = txDoneBottom; 00317 radio.rxDone = rxDone; 00318 radio.timeout = timeout_callback; 00319 radio.chipModeChange = chipModeChange; 00320 radio.diox_topHalf = diox_top_half; 00321 00322 spi.frequency(spi_hz); 00323 readChip(); 00324 00325 radio.setRegulator(0); // default to LDO 00326 00327 sa = 0xc194c1; 00328 radio.setSyncAddr(1, sa); 00329 00330 RadioEvents = e; 00331 lpt.start(); 00332 00333 fe_enable = true; 00334 00335 radio.periodBase = 2; // 1ms resolution 00336 nSymbs = 8; 00337 } 00338 00339 float Radio::GetRssiInst() 00340 { 00341 uint8_t buf[2]; 00342 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00343 return buf[1] / -2.0; 00344 } 00345 00346 int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh) 00347 { 00348 uint8_t buf[8]; 00349 uint8_t pktType = radio.getPacketType(); 00350 00351 if (pktType == PACKET_TYPE_LORA) { 00352 ppLORA.lora.PayloadLength = size; 00353 radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf); 00354 } else if (pktType == PACKET_TYPE_GFSK) { 00355 ppGFSK.gfskFLRC.PayloadLength = size; 00356 radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf); 00357 } 00358 00359 if (maxListenTime > 0) { 00360 int rssi; 00361 us_timestamp_t startAt, chFreeAt, now; 00362 radio.start_rx(-1); 00363 #if (MBED_MAJOR_VERSION < 6) 00364 startAt = lpt.read_us(); 00365 #else 00366 startAt = LowPowerClock::now().time_since_epoch().count(); 00367 #endif 00368 Lstart: 00369 do { 00370 #if (MBED_MAJOR_VERSION < 6) 00371 now = lpt.read_us(); 00372 #else 00373 now = LowPowerClock::now().time_since_epoch().count(); 00374 #endif 00375 if ((now - startAt) > maxListenTime) { 00376 return -1; 00377 } 00378 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00379 rssi = buf[1] / -2; 00380 } while (rssi > rssiThresh); 00381 #if (MBED_MAJOR_VERSION < 6) 00382 chFreeAt = lpt.read_us(); 00383 #else 00384 chFreeAt = LowPowerClock::now().time_since_epoch().count(); 00385 #endif 00386 do { 00387 #if (MBED_MAJOR_VERSION < 6) 00388 now = lpt.read_us(); 00389 #else 00390 now = LowPowerClock::now().time_since_epoch().count(); 00391 #endif 00392 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00393 rssi = buf[1] / -2; 00394 if (rssi > rssiThresh) { 00395 goto Lstart; 00396 } 00397 } while ((now - chFreeAt) < channelFreeTime); 00398 } 00399 00400 radio.start_tx(size, 4000); 00401 00402 return 0; 00403 } 00404 00405 void Radio::service() 00406 { 00407 radio.service(); 00408 } 00409 00410 bool Radio::CheckRfFrequency(unsigned hz) 00411 { 00412 return true; 00413 } 00414 00415 void Radio::Sleep() 00416 { 00417 radio.setSleep(true); 00418 } 00419 00420 void Radio::SetPublicNetwork(bool en) 00421 { 00422 /* uint16_t ppg; 00423 00424 if (en) 00425 ppg = 0x3444; 00426 else 00427 ppg = 0x1424; 00428 00429 radio.writeReg(REG_ADDR_LORA_SYNC, ppg, 2); 00430 */ 00431 } 00432 00433 uint32_t Radio::lora_toa_us( uint8_t pktLen ) 00434 { 00435 double bwKHz; 00436 LoRaPktPar0_t LoRaPktPar0; 00437 LoRaLrCtl_t LoRaLrCtl; 00438 LoRaPktPar1_t LoRaPktPar1; 00439 uint8_t LowDatarateOptimize; 00440 00441 { 00442 LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1); 00443 LowDatarateOptimize = LoRaPktPar1.bits.ppm_offset ? 1 : 0; 00444 ppLORA.lora.HeaderType = LoRaPktPar1.bits.implicit_header ? IMPLICIT_HEADER : EXPLICIT_HEADER; 00445 ppLORA.lora.InvertIQ = LoRaPktPar1.octet & LORA_IQ_STD; // LoRaPktPar1.bits.rxinvert_iq 00446 mpLORA.lora.codingRate = LoRaPktPar1.bits.coding_rate; 00447 } 00448 00449 { 00450 LoRaLrCtl.octet = radio.readReg(REG_ADDR_LORA_LRCTL, 1); 00451 ppLORA.lora.crc = LoRaLrCtl.octet & 0x20; // LoRaLrCtl.bits.crc_en 00452 } 00453 00454 { 00455 LoRaPreambleReg_t LoRaPreambleReg; 00456 LoRaPreambleReg.octet = radio.readReg(REG_ADDR_LORA_PREAMBLE, 1); 00457 ppLORA.lora.PreambleLength = LoRaPreambleReg.bits.preamble_symb1_nb * (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp); 00458 } 00459 00460 { 00461 LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1); 00462 switch (LoRaPktPar0.bits.modem_bw) { 00463 case 0: bwKHz = 50; break; 00464 case 1: bwKHz = 100; break; 00465 case 2: mpLORA.lora.bandwidth = LORA_BW_200; bwKHz = 200; break; 00466 case 3: mpLORA.lora.bandwidth = LORA_BW_400; bwKHz = 400; break; 00467 case 4: mpLORA.lora.bandwidth = LORA_BW_800; bwKHz = 800; break; 00468 case 5: mpLORA.lora.bandwidth = LORA_BW_1600; bwKHz = 1600; break; 00469 default: bwKHz = 0; break; 00470 } 00471 mpLORA.lora.spreadingFactor = LoRaPktPar0.bits.modem_sf << 4; 00472 } 00473 00474 // Symbol rate : time for one symbol (secs) 00475 double rs = bwKHz / (1 << LoRaPktPar0.bits.modem_sf); 00476 double ts = 1 / rs; 00477 // time of preamble 00478 // 00479 double tPreamble = ( ppLORA.lora.PreambleLength + 4.25 ) * ts; 00480 // Symbol length of payload and time 00481 00482 double tmp = ceil( ( 8 * pktLen - 4 * LoRaPktPar0.bits.modem_sf + 00483 28 + 16 * LoRaLrCtl.bits.crc_en - 00484 ( LoRaPktPar1.bits.implicit_header ? 20 : 0 ) ) / 00485 ( double )( 4 * ( LoRaPktPar0.bits.modem_sf - 00486 ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * 00487 ( LoRaPktPar1.bits.coding_rate + 4 ); 00488 00489 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); 00490 double tPayload = nPayload * ts; 00491 // Time on air 00492 double tOnAir = tPreamble + tPayload; 00493 // return microseconds 00494 return floor( tOnAir * 1000 + 0.999 ); 00495 } 00496 00497 void Radio::GFSKModemConfig(unsigned bps, unsigned bw_hz, unsigned fdev_hz) 00498 { 00499 uint8_t u8; 00500 float mi, Mbps = bps / 1000000.0; 00501 00502 if (Mbps > 1.6) { 00503 /* 2.0Mbps */ 00504 u8 = GFSK_BLE_BR_2_000_BW_2_4; 00505 } else if (Mbps > 1.0) { 00506 /* 1.6Mbps */ 00507 u8 = GFSK_BLE_BR_1_600_BW_2_4; 00508 } else if (Mbps > 0.8) { 00509 /* 1.0Mbps */ 00510 /*if (bwMHz > 1.2) 00511 u8 = GFSK_BLE_BR_1_000_BW_2_4; 00512 else*/ 00513 u8 = GFSK_BLE_BR_1_000_BW_1_2; 00514 } else if (Mbps > 0.5) { 00515 /* 0.8Mbps */ 00516 /*if (bwMHz > 1.2) 00517 u8 = GFSK_BLE_BR_0_800_BW_2_4; 00518 else*/ 00519 u8 = GFSK_BLE_BR_0_800_BW_1_2; 00520 } else if (Mbps > 0.4) { 00521 /* 0.5Mbps */ 00522 /*if (bwMHz > 0.6) 00523 u8 = GFSK_BLE_BR_0_500_BW_1_2; 00524 else*/ 00525 u8 = GFSK_BLE_BR_0_500_BW_0_6; 00526 } else if (Mbps > 0.25) { 00527 /* 0.4Mbps */ 00528 /*if (bwMHz > 0.6) 00529 u8 = GFSK_BLE_BR_0_400_BW_1_2; 00530 else*/ 00531 u8 = GFSK_BLE_BR_0_400_BW_0_6; 00532 } else if (Mbps > 0.125) { 00533 /* 0.25Mbps */ 00534 /*if (bwMHz > 0.3) 00535 u8 = GFSK_BLE_BR_0_250_BW_0_6; 00536 else*/ 00537 u8 = GFSK_BLE_BR_0_250_BW_0_3; 00538 } else { 00539 /* 0.125Mbps */ 00540 u8 = GFSK_BLE_BR_0_125_BW_0_3; 00541 } 00542 00543 mpBLE_GFSK.gfskBle.bitrateBandwidth = u8; 00544 00545 mpBLE_GFSK.gfskBle.ModulationShaping = BT_OFF; 00546 00547 mi = (fdev_hz * 2.0) / bps; 00548 if (mi > 0.35) { 00549 mi -= 0.5; 00550 mi /= 0.25; 00551 mpBLE_GFSK.gfskBle.ModulationIndex = ((uint8_t)mi) + 1; 00552 } else 00553 mpBLE_GFSK.gfskBle.ModulationIndex = 0; 00554 00555 radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpBLE_GFSK.buf); 00556 } 00557 00558 void Radio::GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn) 00559 { 00560 ppGFSK.gfskFLRC.PreambleLength = (preambleLen - 4) / 4; 00561 ppGFSK.gfskFLRC.PreambleLength <<= 4; 00562 ppGFSK.gfskFLRC.SyncWordLength = (3 - 1) << 1; // 3 byte 0xc194c1 00563 ppGFSK.gfskFLRC.HeaderType = fixLen ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH; 00564 ppGFSK.gfskFLRC.CRCLength = crcOn ? RADIO_CRC_2_BYTES : RADIO_CRC_OFF; 00565 00566 // TODO ppGFSK.gfskFLRC.PayloadLength = ; 00567 00568 radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf); 00569 } 00570 00571 void Radio::SetLoRaSymbolTimeout(uint16_t symbs) 00572 { 00573 nSymbs = symbs; 00574 rxTimeoutMs = nSymbs * (symbolPeriodUs / 1000.0); 00575 } 00576 00577 void Radio::LoRaModemConfig(unsigned bwKHz, uint8_t sf, uint8_t cr) 00578 { 00579 if (radio.getPacketType() != PACKET_TYPE_LORA) 00580 radio.setPacketType(PACKET_TYPE_LORA); 00581 00582 if (bwKHz > 800) 00583 mpLORA.lora.bandwidth = LORA_BW_1600; 00584 else if (bwKHz > 400) 00585 mpLORA.lora.bandwidth = LORA_BW_800; 00586 else if (bwKHz > 200) 00587 mpLORA.lora.bandwidth = LORA_BW_400; 00588 else if (bwKHz > 100) 00589 mpLORA.lora.bandwidth = LORA_BW_200; 00590 else if (bwKHz > 50) 00591 mpLORA.lora.bandwidth = LORA_BW_100; 00592 else 00593 mpLORA.lora.bandwidth = LORA_BW_50; 00594 00595 mpLORA.lora.codingRate = cr; 00596 00597 mpLORA.lora.spreadingFactor = sf << 4; 00598 00599 radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpLORA.buf); 00600 00601 symbolPeriodUs = (1 << sf) / (bwKHz / 1000.0); // bw in MHz gives microseconds 00602 rxTimeoutMs = nSymbs * (symbolPeriodUs / 1000.0); 00603 } 00604 00605 void Radio::LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ) 00606 { 00607 if (radio.getPacketType() != PACKET_TYPE_LORA) 00608 radio.setPacketType(PACKET_TYPE_LORA); 00609 00610 ppLORA.lora.PreambleLength = preambleLen; 00611 ppLORA.lora.HeaderType = fixLen ? IMPLICIT_HEADER : EXPLICIT_HEADER; 00612 ppLORA.lora.crc = crcOn ? LORA_CRC_ENABLE : LORA_CRC_DISABLE; 00613 ppLORA.lora.InvertIQ = invIQ ? LORA_IQ_INVERTED : LORA_IQ_STD; 00614 00615 radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf); 00616 } 00617 00618 void Radio::SetChannel(unsigned hz) 00619 { 00620 radio.setMHz(hz / 1000000.0); 00621 } 00622 00623 uint32_t Radio::Random(void) 00624 { 00625 uint8_t buf[2]; 00626 uint32_t ret = 0; 00627 unsigned n; 00628 00629 radio.start_rx(-1); 00630 00631 for (n = 0; n < 8; n++) { 00632 uint32_t r, s; 00633 wait_us(5000); 00634 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf); 00635 r = buf[1]; 00636 s = n * 4; 00637 r <<= s; 00638 ret ^= r; 00639 } 00640 00641 radio.setStandby(STDBY_RC); 00642 00643 return ret; 00644 } 00645 00646 void Radio::Rx(unsigned timeout) 00647 { 00648 #ifdef RX_INDICATION 00649 RX_INDICATION = 1; 00650 #endif 00651 if (timeout == 0) 00652 radio.start_rx(0); // continuous rx 00653 else { 00654 radio.start_rx(rxTimeoutMs); 00655 } 00656 } 00657 00658 void Radio::Standby() 00659 { 00660 radio.setStandby(STDBY_RC); 00661 } 00662 00663 #define TX_PWR_OFFSET 18 00664 void Radio::set_tx_dbm(int8_t dbm) 00665 { 00666 if (dbm == PA_OFF_DBM) { 00667 /* TODO: shut off PA */ 00668 radio.set_tx_dbm(0); 00669 } else { 00670 /* power range -18dBm to +13dBm */ 00671 radio.set_tx_dbm(dbm + TX_PWR_OFFSET); 00672 } 00673 } 00674 00675 void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us) 00676 { 00677 SetChannel(hz); 00678 radio.set_tx_dbm(dbm); 00679 radio.xfer(OPCODE_SET_TX_CARRIER, 0, 0, NULL); 00680 } 00681 00682 void Radio::SetRxMaxPayloadLength(uint8_t max) 00683 { 00684 uint8_t pktType = radio.getPacketType(); 00685 00686 if (pktType == PACKET_TYPE_GFSK) 00687 ppGFSK.gfskFLRC.PayloadLength = max; 00688 else if (pktType == PACKET_TYPE_LORA) 00689 ppLORA.lora.PayloadLength = max; 00690 } 00691 00692 #endif /* ..SX126x_H */
Generated on Sat Feb 6 2021 00:35:15 by
