Greg Voronin
/
gammaCanary02
This version is the one to be submitted as a part the Hackster.io contest, Unleash Invisible Intelligence
Embed:
(wiki syntax)
Show/hide line numbers
LoRa.cpp
00001 #include <LoRa.h> 00002 00003 // registers 00004 #define REG_FIFO 0x00 00005 #define REG_OP_MODE 0x01 00006 #define REG_FRF_MSB 0x06 00007 #define REG_FRF_MID 0x07 00008 #define REG_FRF_LSB 0x08 00009 #define REG_PA_CONFIG 0x09 00010 #define REG_LNA 0x0c 00011 #define REG_FIFO_ADDR_PTR 0x0d 00012 #define REG_FIFO_TX_BASE_ADDR 0x0e 00013 #define REG_FIFO_RX_BASE_ADDR 0x0f 00014 #define REG_FIFO_RX_CURRENT_ADDR 0x10 00015 #define REG_IRQ_FLAGS 0x12 00016 #define REG_RX_NB_BYTES 0x13 00017 #define REG_PKT_RSSI_VALUE 0x1a 00018 #define REG_PKT_SNR_VALUE 0x1b 00019 #define REG_MODEM_CONFIG_1 0x1d 00020 #define REG_MODEM_CONFIG_2 0x1e 00021 #define REG_PREAMBLE_MSB 0x20 00022 #define REG_PREAMBLE_LSB 0x21 00023 #define REG_PAYLOAD_LENGTH 0x22 00024 #define REG_MODEM_CONFIG_3 0x26 00025 #define REG_RSSI_WIDEBAND 0x2c 00026 #define REG_DETECTION_OPTIMIZE 0x31 00027 #define REG_DETECTION_THRESHOLD 0x37 00028 #define REG_SYNC_WORD 0x39 00029 #define REG_DIO_MAPPING_1 0x40 00030 #define REG_VERSION 0x42 00031 00032 // modes 00033 #define MODE_LONG_RANGE_MODE 0x80 00034 #define MODE_SLEEP 0x00 00035 #define MODE_STDBY 0x01 00036 #define MODE_TX 0x03 00037 #define MODE_RX_CONTINUOUS 0x05 00038 #define MODE_RX_SINGLE 0x06 00039 00040 // PA config 00041 #define PA_BOOST 0x80 00042 00043 // IRQ masks 00044 #define IRQ_TX_DONE_MASK 0x08 00045 #define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20 00046 #define IRQ_RX_DONE_MASK 0x40 00047 00048 #define MAX_PKT_LENGTH 255 00049 00050 SPI _spi(P5_1, P5_2, P5_0); 00051 00052 LoRaClass::LoRaClass() : 00053 spi(_spi), 00054 _ss(LORA_DEFAULT_SS_PIN ), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), 00055 _frequency(0), 00056 _packetIndex(0), 00057 _implicitHeaderMode(0), 00058 _onReceive(NULL) 00059 { 00060 // overide Stream timeout value 00061 //setTimeout(0); 00062 } 00063 00064 int LoRaClass::begin(long frequency) 00065 { 00066 // perform reset 00067 _reset = 0; 00068 wait(0.010); 00069 _reset = 1; 00070 wait(0.010); 00071 00072 // set SS high 00073 _ss = 1; 00074 00075 // check version 00076 uint8_t version = readRegister(REG_VERSION); 00077 if (version != 0x12) { 00078 return 0; 00079 } 00080 00081 // put in sleep mode 00082 sleep(); 00083 00084 // set frequency 00085 setFrequency(frequency); 00086 00087 // set base addresses 00088 writeRegister(REG_FIFO_TX_BASE_ADDR, 0); 00089 writeRegister(REG_FIFO_RX_BASE_ADDR, 0); 00090 00091 // set LNA boost 00092 writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03); 00093 00094 // set auto AGC 00095 writeRegister(REG_MODEM_CONFIG_3, 0x04); 00096 00097 // set output power to 17 dBm 00098 setTxPower(17); 00099 00100 // put in standby mode 00101 idle(); 00102 00103 return 1; 00104 } 00105 00106 void LoRaClass::end() 00107 { 00108 // put in sleep mode 00109 sleep(); 00110 } 00111 00112 int LoRaClass::beginPacket(int implicitHeader) 00113 { 00114 // put in standby mode 00115 idle(); 00116 00117 if (implicitHeader) { 00118 implicitHeaderMode(); 00119 } else { 00120 explicitHeaderMode(); 00121 } 00122 00123 // reset FIFO address and paload length 00124 writeRegister(REG_FIFO_ADDR_PTR, 0); 00125 writeRegister(REG_PAYLOAD_LENGTH, 0); 00126 00127 return 1; 00128 } 00129 00130 int LoRaClass::endPacket() 00131 { 00132 // put in TX mode 00133 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX); 00134 00135 // wait for TX done 00136 while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0); 00137 00138 // clear IRQ's 00139 writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); 00140 00141 return 1; 00142 } 00143 00144 int LoRaClass::parsePacket(int size) 00145 { 00146 int packetLength = 0; 00147 int irqFlags = readRegister(REG_IRQ_FLAGS); 00148 00149 if (size > 0) { 00150 implicitHeaderMode(); 00151 00152 writeRegister(REG_PAYLOAD_LENGTH, size & 0xff); 00153 } else { 00154 explicitHeaderMode(); 00155 } 00156 00157 // clear IRQ's 00158 writeRegister(REG_IRQ_FLAGS, irqFlags); 00159 00160 if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) { 00161 // received a packet 00162 _packetIndex = 0; 00163 00164 // read packet length 00165 if (_implicitHeaderMode) { 00166 packetLength = readRegister(REG_PAYLOAD_LENGTH); 00167 } else { 00168 packetLength = readRegister(REG_RX_NB_BYTES); 00169 } 00170 00171 // set FIFO address to current RX address 00172 writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR)); 00173 00174 // put in standby mode 00175 idle(); 00176 } else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) { 00177 // not currently in RX mode 00178 00179 // reset FIFO address 00180 writeRegister(REG_FIFO_ADDR_PTR, 0); 00181 00182 // put in single RX mode 00183 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE); 00184 } 00185 00186 return packetLength; 00187 } 00188 00189 int LoRaClass::packetRssi() 00190 { 00191 return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868E6 ? 164 : 157)); 00192 } 00193 00194 float LoRaClass::packetSnr() 00195 { 00196 return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25; 00197 } 00198 00199 int LoRaClass::_putc(int value) 00200 { 00201 char buf = (char) value; 00202 size_t size = sizeof(buf); 00203 int currentLength = readRegister(REG_PAYLOAD_LENGTH); 00204 00205 // check size 00206 if ((currentLength + size) > MAX_PKT_LENGTH) { 00207 size = MAX_PKT_LENGTH - currentLength; 00208 } 00209 00210 writeRegister(REG_FIFO, buf); 00211 00212 // update length 00213 writeRegister(REG_PAYLOAD_LENGTH, currentLength + size); 00214 00215 return (int) buf; 00216 } 00217 00218 int LoRaClass::available() 00219 { 00220 return (readRegister(REG_RX_NB_BYTES) - _packetIndex); 00221 } 00222 00223 int LoRaClass::_getc() 00224 { 00225 if (!available()) { 00226 return -1; 00227 } 00228 00229 _packetIndex++; 00230 00231 return readRegister(REG_FIFO); 00232 } 00233 00234 int LoRaClass::peek() 00235 { 00236 if (!available()) { 00237 return -1; 00238 } 00239 00240 // store current FIFO address 00241 int currentAddress = readRegister(REG_FIFO_ADDR_PTR); 00242 00243 // read 00244 uint8_t b = readRegister(REG_FIFO); 00245 00246 // restore FIFO address 00247 writeRegister(REG_FIFO_ADDR_PTR, currentAddress); 00248 00249 return b; 00250 } 00251 00252 void LoRaClass::onReceive(void(*callback)(int)) 00253 { 00254 _onReceive = callback; 00255 00256 if (callback) { 00257 writeRegister(REG_DIO_MAPPING_1, 0x00); 00258 00259 //attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING); 00260 _dio0.rise(&LoRaClass::onDio0Rise); 00261 } else { 00262 //detachInterrupt(digitalPinToInterrupt(_dio0)); 00263 _dio0.rise(NULL); 00264 } 00265 } 00266 00267 void LoRaClass::receive(int size) 00268 { 00269 if (size > 0) { 00270 implicitHeaderMode(); 00271 00272 writeRegister(REG_PAYLOAD_LENGTH, size & 0xff); 00273 } else { 00274 explicitHeaderMode(); 00275 } 00276 00277 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS); 00278 } 00279 00280 void LoRaClass::idle() 00281 { 00282 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY); 00283 } 00284 00285 void LoRaClass::sleep() 00286 { 00287 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP); 00288 } 00289 00290 void LoRaClass::setTxPower(int level, int outputPin) 00291 { 00292 if (PA_OUTPUT_RFO_PIN == outputPin) { 00293 // RFO 00294 if (level < 0) { 00295 level = 0; 00296 } else if (level > 14) { 00297 level = 14; 00298 } 00299 00300 writeRegister(REG_PA_CONFIG, 0x70 | level); 00301 } else { 00302 // PA BOOST 00303 if (level < 2) { 00304 level = 2; 00305 } else if (level > 17) { 00306 level = 17; 00307 } 00308 00309 writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2)); 00310 } 00311 } 00312 00313 void LoRaClass::setFrequency(long frequency) 00314 { 00315 _frequency = frequency; 00316 00317 uint64_t frf = ((uint64_t)frequency << 19) / 32000000; 00318 00319 writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16)); 00320 writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8)); 00321 writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0)); 00322 } 00323 00324 void LoRaClass::setSpreadingFactor(int sf) 00325 { 00326 if (sf < 6) { 00327 sf = 6; 00328 } else if (sf > 12) { 00329 sf = 12; 00330 } 00331 00332 if (sf == 6) { 00333 writeRegister(REG_DETECTION_OPTIMIZE, 0xc5); 00334 writeRegister(REG_DETECTION_THRESHOLD, 0x0c); 00335 } else { 00336 writeRegister(REG_DETECTION_OPTIMIZE, 0xc3); 00337 writeRegister(REG_DETECTION_THRESHOLD, 0x0a); 00338 } 00339 00340 writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0)); 00341 } 00342 00343 void LoRaClass::setSignalBandwidth(long sbw) 00344 { 00345 int bw; 00346 00347 if (sbw <= 7.8E3) { 00348 bw = 0; 00349 } else if (sbw <= 10.4E3) { 00350 bw = 1; 00351 } else if (sbw <= 15.6E3) { 00352 bw = 2; 00353 } else if (sbw <= 20.8E3) { 00354 bw = 3; 00355 } else if (sbw <= 31.25E3) { 00356 bw = 4; 00357 } else if (sbw <= 41.7E3) { 00358 bw = 5; 00359 } else if (sbw <= 62.5E3) { 00360 bw = 6; 00361 } else if (sbw <= 125E3) { 00362 bw = 7; 00363 } else if (sbw <= 250E3) { 00364 bw = 8; 00365 } else /*if (sbw <= 250E3)*/ { 00366 bw = 9; 00367 } 00368 00369 writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4)); 00370 } 00371 00372 void LoRaClass::setCodingRate4(int denominator) 00373 { 00374 if (denominator < 5) { 00375 denominator = 5; 00376 } else if (denominator > 8) { 00377 denominator = 8; 00378 } 00379 00380 int cr = denominator - 4; 00381 00382 writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1)); 00383 } 00384 00385 void LoRaClass::setPreambleLength(long length) 00386 { 00387 writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8)); 00388 writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0)); 00389 } 00390 00391 void LoRaClass::setSyncWord(int sw) 00392 { 00393 writeRegister(REG_SYNC_WORD, sw); 00394 } 00395 00396 void LoRaClass::enableCrc() 00397 { 00398 writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04); 00399 } 00400 00401 void LoRaClass::disableCrc() 00402 { 00403 writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb); 00404 } 00405 00406 uint8_t LoRaClass::random() 00407 { 00408 return readRegister(REG_RSSI_WIDEBAND); 00409 } 00410 00411 void LoRaClass::dumpRegisters(Stream& out) 00412 { 00413 for (int i = 0; i < 128; i++) { 00414 out.printf("0x%x: 0x%x", i, readRegister(i)); 00415 } 00416 } 00417 00418 void LoRaClass::explicitHeaderMode() 00419 { 00420 _implicitHeaderMode = 0; 00421 00422 writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe); 00423 } 00424 00425 void LoRaClass::implicitHeaderMode() 00426 { 00427 _implicitHeaderMode = 1; 00428 00429 writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01); 00430 } 00431 00432 void LoRaClass::handleDio0Rise() 00433 { 00434 int irqFlags = readRegister(REG_IRQ_FLAGS); 00435 00436 // clear IRQ's 00437 writeRegister(REG_IRQ_FLAGS, irqFlags); 00438 00439 if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) { 00440 // received a packet 00441 _packetIndex = 0; 00442 00443 // read packet length 00444 int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES); 00445 00446 // set FIFO address to current RX address 00447 writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR)); 00448 00449 if (_onReceive) { 00450 _onReceive(packetLength); 00451 } 00452 00453 // reset FIFO address 00454 writeRegister(REG_FIFO_ADDR_PTR, 0); 00455 } 00456 } 00457 00458 uint8_t LoRaClass::readRegister(uint8_t address) 00459 { 00460 return singleTransfer(address & 0x7f, 0x00); 00461 } 00462 00463 void LoRaClass::writeRegister(uint8_t address, uint8_t value) 00464 { 00465 singleTransfer(address | 0x80, value); 00466 } 00467 00468 uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value) 00469 { 00470 uint8_t response; 00471 00472 _ss = 0; 00473 00474 spi.write(address); 00475 response = spi.write(value); 00476 00477 _ss = 1; 00478 00479 return response; 00480 } 00481 00482 void LoRaClass::onDio0Rise() 00483 { 00484 LoRa.handleDio0Rise(); 00485 } 00486 00487 LoRaClass LoRa;
Generated on Sat Jul 23 2022 17:25:27 by 1.7.2