This version is the one to be submitted as a part the Hackster.io contest, Unleash Invisible Intelligence

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRa.cpp Source File

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;