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

Committer:
gov1
Date:
Tue Jul 31 16:30:32 2018 +0000
Revision:
0:a761fba7f8a8
complete version with emer. batt low check

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gov1 0:a761fba7f8a8 1 #include <LoRa.h>
gov1 0:a761fba7f8a8 2
gov1 0:a761fba7f8a8 3 // registers
gov1 0:a761fba7f8a8 4 #define REG_FIFO 0x00
gov1 0:a761fba7f8a8 5 #define REG_OP_MODE 0x01
gov1 0:a761fba7f8a8 6 #define REG_FRF_MSB 0x06
gov1 0:a761fba7f8a8 7 #define REG_FRF_MID 0x07
gov1 0:a761fba7f8a8 8 #define REG_FRF_LSB 0x08
gov1 0:a761fba7f8a8 9 #define REG_PA_CONFIG 0x09
gov1 0:a761fba7f8a8 10 #define REG_LNA 0x0c
gov1 0:a761fba7f8a8 11 #define REG_FIFO_ADDR_PTR 0x0d
gov1 0:a761fba7f8a8 12 #define REG_FIFO_TX_BASE_ADDR 0x0e
gov1 0:a761fba7f8a8 13 #define REG_FIFO_RX_BASE_ADDR 0x0f
gov1 0:a761fba7f8a8 14 #define REG_FIFO_RX_CURRENT_ADDR 0x10
gov1 0:a761fba7f8a8 15 #define REG_IRQ_FLAGS 0x12
gov1 0:a761fba7f8a8 16 #define REG_RX_NB_BYTES 0x13
gov1 0:a761fba7f8a8 17 #define REG_PKT_RSSI_VALUE 0x1a
gov1 0:a761fba7f8a8 18 #define REG_PKT_SNR_VALUE 0x1b
gov1 0:a761fba7f8a8 19 #define REG_MODEM_CONFIG_1 0x1d
gov1 0:a761fba7f8a8 20 #define REG_MODEM_CONFIG_2 0x1e
gov1 0:a761fba7f8a8 21 #define REG_PREAMBLE_MSB 0x20
gov1 0:a761fba7f8a8 22 #define REG_PREAMBLE_LSB 0x21
gov1 0:a761fba7f8a8 23 #define REG_PAYLOAD_LENGTH 0x22
gov1 0:a761fba7f8a8 24 #define REG_MODEM_CONFIG_3 0x26
gov1 0:a761fba7f8a8 25 #define REG_RSSI_WIDEBAND 0x2c
gov1 0:a761fba7f8a8 26 #define REG_DETECTION_OPTIMIZE 0x31
gov1 0:a761fba7f8a8 27 #define REG_DETECTION_THRESHOLD 0x37
gov1 0:a761fba7f8a8 28 #define REG_SYNC_WORD 0x39
gov1 0:a761fba7f8a8 29 #define REG_DIO_MAPPING_1 0x40
gov1 0:a761fba7f8a8 30 #define REG_VERSION 0x42
gov1 0:a761fba7f8a8 31
gov1 0:a761fba7f8a8 32 // modes
gov1 0:a761fba7f8a8 33 #define MODE_LONG_RANGE_MODE 0x80
gov1 0:a761fba7f8a8 34 #define MODE_SLEEP 0x00
gov1 0:a761fba7f8a8 35 #define MODE_STDBY 0x01
gov1 0:a761fba7f8a8 36 #define MODE_TX 0x03
gov1 0:a761fba7f8a8 37 #define MODE_RX_CONTINUOUS 0x05
gov1 0:a761fba7f8a8 38 #define MODE_RX_SINGLE 0x06
gov1 0:a761fba7f8a8 39
gov1 0:a761fba7f8a8 40 // PA config
gov1 0:a761fba7f8a8 41 #define PA_BOOST 0x80
gov1 0:a761fba7f8a8 42
gov1 0:a761fba7f8a8 43 // IRQ masks
gov1 0:a761fba7f8a8 44 #define IRQ_TX_DONE_MASK 0x08
gov1 0:a761fba7f8a8 45 #define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
gov1 0:a761fba7f8a8 46 #define IRQ_RX_DONE_MASK 0x40
gov1 0:a761fba7f8a8 47
gov1 0:a761fba7f8a8 48 #define MAX_PKT_LENGTH 255
gov1 0:a761fba7f8a8 49
gov1 0:a761fba7f8a8 50 SPI _spi(P5_1, P5_2, P5_0);
gov1 0:a761fba7f8a8 51
gov1 0:a761fba7f8a8 52 LoRaClass::LoRaClass() :
gov1 0:a761fba7f8a8 53 spi(_spi),
gov1 0:a761fba7f8a8 54 _ss(LORA_DEFAULT_SS_PIN ), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
gov1 0:a761fba7f8a8 55 _frequency(0),
gov1 0:a761fba7f8a8 56 _packetIndex(0),
gov1 0:a761fba7f8a8 57 _implicitHeaderMode(0),
gov1 0:a761fba7f8a8 58 _onReceive(NULL)
gov1 0:a761fba7f8a8 59 {
gov1 0:a761fba7f8a8 60 // overide Stream timeout value
gov1 0:a761fba7f8a8 61 //setTimeout(0);
gov1 0:a761fba7f8a8 62 }
gov1 0:a761fba7f8a8 63
gov1 0:a761fba7f8a8 64 int LoRaClass::begin(long frequency)
gov1 0:a761fba7f8a8 65 {
gov1 0:a761fba7f8a8 66 // perform reset
gov1 0:a761fba7f8a8 67 _reset = 0;
gov1 0:a761fba7f8a8 68 wait(0.010);
gov1 0:a761fba7f8a8 69 _reset = 1;
gov1 0:a761fba7f8a8 70 wait(0.010);
gov1 0:a761fba7f8a8 71
gov1 0:a761fba7f8a8 72 // set SS high
gov1 0:a761fba7f8a8 73 _ss = 1;
gov1 0:a761fba7f8a8 74
gov1 0:a761fba7f8a8 75 // check version
gov1 0:a761fba7f8a8 76 uint8_t version = readRegister(REG_VERSION);
gov1 0:a761fba7f8a8 77 if (version != 0x12) {
gov1 0:a761fba7f8a8 78 return 0;
gov1 0:a761fba7f8a8 79 }
gov1 0:a761fba7f8a8 80
gov1 0:a761fba7f8a8 81 // put in sleep mode
gov1 0:a761fba7f8a8 82 sleep();
gov1 0:a761fba7f8a8 83
gov1 0:a761fba7f8a8 84 // set frequency
gov1 0:a761fba7f8a8 85 setFrequency(frequency);
gov1 0:a761fba7f8a8 86
gov1 0:a761fba7f8a8 87 // set base addresses
gov1 0:a761fba7f8a8 88 writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
gov1 0:a761fba7f8a8 89 writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
gov1 0:a761fba7f8a8 90
gov1 0:a761fba7f8a8 91 // set LNA boost
gov1 0:a761fba7f8a8 92 writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
gov1 0:a761fba7f8a8 93
gov1 0:a761fba7f8a8 94 // set auto AGC
gov1 0:a761fba7f8a8 95 writeRegister(REG_MODEM_CONFIG_3, 0x04);
gov1 0:a761fba7f8a8 96
gov1 0:a761fba7f8a8 97 // set output power to 17 dBm
gov1 0:a761fba7f8a8 98 setTxPower(17);
gov1 0:a761fba7f8a8 99
gov1 0:a761fba7f8a8 100 // put in standby mode
gov1 0:a761fba7f8a8 101 idle();
gov1 0:a761fba7f8a8 102
gov1 0:a761fba7f8a8 103 return 1;
gov1 0:a761fba7f8a8 104 }
gov1 0:a761fba7f8a8 105
gov1 0:a761fba7f8a8 106 void LoRaClass::end()
gov1 0:a761fba7f8a8 107 {
gov1 0:a761fba7f8a8 108 // put in sleep mode
gov1 0:a761fba7f8a8 109 sleep();
gov1 0:a761fba7f8a8 110 }
gov1 0:a761fba7f8a8 111
gov1 0:a761fba7f8a8 112 int LoRaClass::beginPacket(int implicitHeader)
gov1 0:a761fba7f8a8 113 {
gov1 0:a761fba7f8a8 114 // put in standby mode
gov1 0:a761fba7f8a8 115 idle();
gov1 0:a761fba7f8a8 116
gov1 0:a761fba7f8a8 117 if (implicitHeader) {
gov1 0:a761fba7f8a8 118 implicitHeaderMode();
gov1 0:a761fba7f8a8 119 } else {
gov1 0:a761fba7f8a8 120 explicitHeaderMode();
gov1 0:a761fba7f8a8 121 }
gov1 0:a761fba7f8a8 122
gov1 0:a761fba7f8a8 123 // reset FIFO address and paload length
gov1 0:a761fba7f8a8 124 writeRegister(REG_FIFO_ADDR_PTR, 0);
gov1 0:a761fba7f8a8 125 writeRegister(REG_PAYLOAD_LENGTH, 0);
gov1 0:a761fba7f8a8 126
gov1 0:a761fba7f8a8 127 return 1;
gov1 0:a761fba7f8a8 128 }
gov1 0:a761fba7f8a8 129
gov1 0:a761fba7f8a8 130 int LoRaClass::endPacket()
gov1 0:a761fba7f8a8 131 {
gov1 0:a761fba7f8a8 132 // put in TX mode
gov1 0:a761fba7f8a8 133 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
gov1 0:a761fba7f8a8 134
gov1 0:a761fba7f8a8 135 // wait for TX done
gov1 0:a761fba7f8a8 136 while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0);
gov1 0:a761fba7f8a8 137
gov1 0:a761fba7f8a8 138 // clear IRQ's
gov1 0:a761fba7f8a8 139 writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
gov1 0:a761fba7f8a8 140
gov1 0:a761fba7f8a8 141 return 1;
gov1 0:a761fba7f8a8 142 }
gov1 0:a761fba7f8a8 143
gov1 0:a761fba7f8a8 144 int LoRaClass::parsePacket(int size)
gov1 0:a761fba7f8a8 145 {
gov1 0:a761fba7f8a8 146 int packetLength = 0;
gov1 0:a761fba7f8a8 147 int irqFlags = readRegister(REG_IRQ_FLAGS);
gov1 0:a761fba7f8a8 148
gov1 0:a761fba7f8a8 149 if (size > 0) {
gov1 0:a761fba7f8a8 150 implicitHeaderMode();
gov1 0:a761fba7f8a8 151
gov1 0:a761fba7f8a8 152 writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
gov1 0:a761fba7f8a8 153 } else {
gov1 0:a761fba7f8a8 154 explicitHeaderMode();
gov1 0:a761fba7f8a8 155 }
gov1 0:a761fba7f8a8 156
gov1 0:a761fba7f8a8 157 // clear IRQ's
gov1 0:a761fba7f8a8 158 writeRegister(REG_IRQ_FLAGS, irqFlags);
gov1 0:a761fba7f8a8 159
gov1 0:a761fba7f8a8 160 if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
gov1 0:a761fba7f8a8 161 // received a packet
gov1 0:a761fba7f8a8 162 _packetIndex = 0;
gov1 0:a761fba7f8a8 163
gov1 0:a761fba7f8a8 164 // read packet length
gov1 0:a761fba7f8a8 165 if (_implicitHeaderMode) {
gov1 0:a761fba7f8a8 166 packetLength = readRegister(REG_PAYLOAD_LENGTH);
gov1 0:a761fba7f8a8 167 } else {
gov1 0:a761fba7f8a8 168 packetLength = readRegister(REG_RX_NB_BYTES);
gov1 0:a761fba7f8a8 169 }
gov1 0:a761fba7f8a8 170
gov1 0:a761fba7f8a8 171 // set FIFO address to current RX address
gov1 0:a761fba7f8a8 172 writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
gov1 0:a761fba7f8a8 173
gov1 0:a761fba7f8a8 174 // put in standby mode
gov1 0:a761fba7f8a8 175 idle();
gov1 0:a761fba7f8a8 176 } else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
gov1 0:a761fba7f8a8 177 // not currently in RX mode
gov1 0:a761fba7f8a8 178
gov1 0:a761fba7f8a8 179 // reset FIFO address
gov1 0:a761fba7f8a8 180 writeRegister(REG_FIFO_ADDR_PTR, 0);
gov1 0:a761fba7f8a8 181
gov1 0:a761fba7f8a8 182 // put in single RX mode
gov1 0:a761fba7f8a8 183 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
gov1 0:a761fba7f8a8 184 }
gov1 0:a761fba7f8a8 185
gov1 0:a761fba7f8a8 186 return packetLength;
gov1 0:a761fba7f8a8 187 }
gov1 0:a761fba7f8a8 188
gov1 0:a761fba7f8a8 189 int LoRaClass::packetRssi()
gov1 0:a761fba7f8a8 190 {
gov1 0:a761fba7f8a8 191 return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868E6 ? 164 : 157));
gov1 0:a761fba7f8a8 192 }
gov1 0:a761fba7f8a8 193
gov1 0:a761fba7f8a8 194 float LoRaClass::packetSnr()
gov1 0:a761fba7f8a8 195 {
gov1 0:a761fba7f8a8 196 return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25;
gov1 0:a761fba7f8a8 197 }
gov1 0:a761fba7f8a8 198
gov1 0:a761fba7f8a8 199 int LoRaClass::_putc(int value)
gov1 0:a761fba7f8a8 200 {
gov1 0:a761fba7f8a8 201 char buf = (char) value;
gov1 0:a761fba7f8a8 202 size_t size = sizeof(buf);
gov1 0:a761fba7f8a8 203 int currentLength = readRegister(REG_PAYLOAD_LENGTH);
gov1 0:a761fba7f8a8 204
gov1 0:a761fba7f8a8 205 // check size
gov1 0:a761fba7f8a8 206 if ((currentLength + size) > MAX_PKT_LENGTH) {
gov1 0:a761fba7f8a8 207 size = MAX_PKT_LENGTH - currentLength;
gov1 0:a761fba7f8a8 208 }
gov1 0:a761fba7f8a8 209
gov1 0:a761fba7f8a8 210 writeRegister(REG_FIFO, buf);
gov1 0:a761fba7f8a8 211
gov1 0:a761fba7f8a8 212 // update length
gov1 0:a761fba7f8a8 213 writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
gov1 0:a761fba7f8a8 214
gov1 0:a761fba7f8a8 215 return (int) buf;
gov1 0:a761fba7f8a8 216 }
gov1 0:a761fba7f8a8 217
gov1 0:a761fba7f8a8 218 int LoRaClass::available()
gov1 0:a761fba7f8a8 219 {
gov1 0:a761fba7f8a8 220 return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
gov1 0:a761fba7f8a8 221 }
gov1 0:a761fba7f8a8 222
gov1 0:a761fba7f8a8 223 int LoRaClass::_getc()
gov1 0:a761fba7f8a8 224 {
gov1 0:a761fba7f8a8 225 if (!available()) {
gov1 0:a761fba7f8a8 226 return -1;
gov1 0:a761fba7f8a8 227 }
gov1 0:a761fba7f8a8 228
gov1 0:a761fba7f8a8 229 _packetIndex++;
gov1 0:a761fba7f8a8 230
gov1 0:a761fba7f8a8 231 return readRegister(REG_FIFO);
gov1 0:a761fba7f8a8 232 }
gov1 0:a761fba7f8a8 233
gov1 0:a761fba7f8a8 234 int LoRaClass::peek()
gov1 0:a761fba7f8a8 235 {
gov1 0:a761fba7f8a8 236 if (!available()) {
gov1 0:a761fba7f8a8 237 return -1;
gov1 0:a761fba7f8a8 238 }
gov1 0:a761fba7f8a8 239
gov1 0:a761fba7f8a8 240 // store current FIFO address
gov1 0:a761fba7f8a8 241 int currentAddress = readRegister(REG_FIFO_ADDR_PTR);
gov1 0:a761fba7f8a8 242
gov1 0:a761fba7f8a8 243 // read
gov1 0:a761fba7f8a8 244 uint8_t b = readRegister(REG_FIFO);
gov1 0:a761fba7f8a8 245
gov1 0:a761fba7f8a8 246 // restore FIFO address
gov1 0:a761fba7f8a8 247 writeRegister(REG_FIFO_ADDR_PTR, currentAddress);
gov1 0:a761fba7f8a8 248
gov1 0:a761fba7f8a8 249 return b;
gov1 0:a761fba7f8a8 250 }
gov1 0:a761fba7f8a8 251
gov1 0:a761fba7f8a8 252 void LoRaClass::onReceive(void(*callback)(int))
gov1 0:a761fba7f8a8 253 {
gov1 0:a761fba7f8a8 254 _onReceive = callback;
gov1 0:a761fba7f8a8 255
gov1 0:a761fba7f8a8 256 if (callback) {
gov1 0:a761fba7f8a8 257 writeRegister(REG_DIO_MAPPING_1, 0x00);
gov1 0:a761fba7f8a8 258
gov1 0:a761fba7f8a8 259 //attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING);
gov1 0:a761fba7f8a8 260 _dio0.rise(&LoRaClass::onDio0Rise);
gov1 0:a761fba7f8a8 261 } else {
gov1 0:a761fba7f8a8 262 //detachInterrupt(digitalPinToInterrupt(_dio0));
gov1 0:a761fba7f8a8 263 _dio0.rise(NULL);
gov1 0:a761fba7f8a8 264 }
gov1 0:a761fba7f8a8 265 }
gov1 0:a761fba7f8a8 266
gov1 0:a761fba7f8a8 267 void LoRaClass::receive(int size)
gov1 0:a761fba7f8a8 268 {
gov1 0:a761fba7f8a8 269 if (size > 0) {
gov1 0:a761fba7f8a8 270 implicitHeaderMode();
gov1 0:a761fba7f8a8 271
gov1 0:a761fba7f8a8 272 writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
gov1 0:a761fba7f8a8 273 } else {
gov1 0:a761fba7f8a8 274 explicitHeaderMode();
gov1 0:a761fba7f8a8 275 }
gov1 0:a761fba7f8a8 276
gov1 0:a761fba7f8a8 277 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
gov1 0:a761fba7f8a8 278 }
gov1 0:a761fba7f8a8 279
gov1 0:a761fba7f8a8 280 void LoRaClass::idle()
gov1 0:a761fba7f8a8 281 {
gov1 0:a761fba7f8a8 282 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
gov1 0:a761fba7f8a8 283 }
gov1 0:a761fba7f8a8 284
gov1 0:a761fba7f8a8 285 void LoRaClass::sleep()
gov1 0:a761fba7f8a8 286 {
gov1 0:a761fba7f8a8 287 writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
gov1 0:a761fba7f8a8 288 }
gov1 0:a761fba7f8a8 289
gov1 0:a761fba7f8a8 290 void LoRaClass::setTxPower(int level, int outputPin)
gov1 0:a761fba7f8a8 291 {
gov1 0:a761fba7f8a8 292 if (PA_OUTPUT_RFO_PIN == outputPin) {
gov1 0:a761fba7f8a8 293 // RFO
gov1 0:a761fba7f8a8 294 if (level < 0) {
gov1 0:a761fba7f8a8 295 level = 0;
gov1 0:a761fba7f8a8 296 } else if (level > 14) {
gov1 0:a761fba7f8a8 297 level = 14;
gov1 0:a761fba7f8a8 298 }
gov1 0:a761fba7f8a8 299
gov1 0:a761fba7f8a8 300 writeRegister(REG_PA_CONFIG, 0x70 | level);
gov1 0:a761fba7f8a8 301 } else {
gov1 0:a761fba7f8a8 302 // PA BOOST
gov1 0:a761fba7f8a8 303 if (level < 2) {
gov1 0:a761fba7f8a8 304 level = 2;
gov1 0:a761fba7f8a8 305 } else if (level > 17) {
gov1 0:a761fba7f8a8 306 level = 17;
gov1 0:a761fba7f8a8 307 }
gov1 0:a761fba7f8a8 308
gov1 0:a761fba7f8a8 309 writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
gov1 0:a761fba7f8a8 310 }
gov1 0:a761fba7f8a8 311 }
gov1 0:a761fba7f8a8 312
gov1 0:a761fba7f8a8 313 void LoRaClass::setFrequency(long frequency)
gov1 0:a761fba7f8a8 314 {
gov1 0:a761fba7f8a8 315 _frequency = frequency;
gov1 0:a761fba7f8a8 316
gov1 0:a761fba7f8a8 317 uint64_t frf = ((uint64_t)frequency << 19) / 32000000;
gov1 0:a761fba7f8a8 318
gov1 0:a761fba7f8a8 319 writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
gov1 0:a761fba7f8a8 320 writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
gov1 0:a761fba7f8a8 321 writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
gov1 0:a761fba7f8a8 322 }
gov1 0:a761fba7f8a8 323
gov1 0:a761fba7f8a8 324 void LoRaClass::setSpreadingFactor(int sf)
gov1 0:a761fba7f8a8 325 {
gov1 0:a761fba7f8a8 326 if (sf < 6) {
gov1 0:a761fba7f8a8 327 sf = 6;
gov1 0:a761fba7f8a8 328 } else if (sf > 12) {
gov1 0:a761fba7f8a8 329 sf = 12;
gov1 0:a761fba7f8a8 330 }
gov1 0:a761fba7f8a8 331
gov1 0:a761fba7f8a8 332 if (sf == 6) {
gov1 0:a761fba7f8a8 333 writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
gov1 0:a761fba7f8a8 334 writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
gov1 0:a761fba7f8a8 335 } else {
gov1 0:a761fba7f8a8 336 writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
gov1 0:a761fba7f8a8 337 writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
gov1 0:a761fba7f8a8 338 }
gov1 0:a761fba7f8a8 339
gov1 0:a761fba7f8a8 340 writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
gov1 0:a761fba7f8a8 341 }
gov1 0:a761fba7f8a8 342
gov1 0:a761fba7f8a8 343 void LoRaClass::setSignalBandwidth(long sbw)
gov1 0:a761fba7f8a8 344 {
gov1 0:a761fba7f8a8 345 int bw;
gov1 0:a761fba7f8a8 346
gov1 0:a761fba7f8a8 347 if (sbw <= 7.8E3) {
gov1 0:a761fba7f8a8 348 bw = 0;
gov1 0:a761fba7f8a8 349 } else if (sbw <= 10.4E3) {
gov1 0:a761fba7f8a8 350 bw = 1;
gov1 0:a761fba7f8a8 351 } else if (sbw <= 15.6E3) {
gov1 0:a761fba7f8a8 352 bw = 2;
gov1 0:a761fba7f8a8 353 } else if (sbw <= 20.8E3) {
gov1 0:a761fba7f8a8 354 bw = 3;
gov1 0:a761fba7f8a8 355 } else if (sbw <= 31.25E3) {
gov1 0:a761fba7f8a8 356 bw = 4;
gov1 0:a761fba7f8a8 357 } else if (sbw <= 41.7E3) {
gov1 0:a761fba7f8a8 358 bw = 5;
gov1 0:a761fba7f8a8 359 } else if (sbw <= 62.5E3) {
gov1 0:a761fba7f8a8 360 bw = 6;
gov1 0:a761fba7f8a8 361 } else if (sbw <= 125E3) {
gov1 0:a761fba7f8a8 362 bw = 7;
gov1 0:a761fba7f8a8 363 } else if (sbw <= 250E3) {
gov1 0:a761fba7f8a8 364 bw = 8;
gov1 0:a761fba7f8a8 365 } else /*if (sbw <= 250E3)*/ {
gov1 0:a761fba7f8a8 366 bw = 9;
gov1 0:a761fba7f8a8 367 }
gov1 0:a761fba7f8a8 368
gov1 0:a761fba7f8a8 369 writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4));
gov1 0:a761fba7f8a8 370 }
gov1 0:a761fba7f8a8 371
gov1 0:a761fba7f8a8 372 void LoRaClass::setCodingRate4(int denominator)
gov1 0:a761fba7f8a8 373 {
gov1 0:a761fba7f8a8 374 if (denominator < 5) {
gov1 0:a761fba7f8a8 375 denominator = 5;
gov1 0:a761fba7f8a8 376 } else if (denominator > 8) {
gov1 0:a761fba7f8a8 377 denominator = 8;
gov1 0:a761fba7f8a8 378 }
gov1 0:a761fba7f8a8 379
gov1 0:a761fba7f8a8 380 int cr = denominator - 4;
gov1 0:a761fba7f8a8 381
gov1 0:a761fba7f8a8 382 writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1));
gov1 0:a761fba7f8a8 383 }
gov1 0:a761fba7f8a8 384
gov1 0:a761fba7f8a8 385 void LoRaClass::setPreambleLength(long length)
gov1 0:a761fba7f8a8 386 {
gov1 0:a761fba7f8a8 387 writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8));
gov1 0:a761fba7f8a8 388 writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0));
gov1 0:a761fba7f8a8 389 }
gov1 0:a761fba7f8a8 390
gov1 0:a761fba7f8a8 391 void LoRaClass::setSyncWord(int sw)
gov1 0:a761fba7f8a8 392 {
gov1 0:a761fba7f8a8 393 writeRegister(REG_SYNC_WORD, sw);
gov1 0:a761fba7f8a8 394 }
gov1 0:a761fba7f8a8 395
gov1 0:a761fba7f8a8 396 void LoRaClass::enableCrc()
gov1 0:a761fba7f8a8 397 {
gov1 0:a761fba7f8a8 398 writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04);
gov1 0:a761fba7f8a8 399 }
gov1 0:a761fba7f8a8 400
gov1 0:a761fba7f8a8 401 void LoRaClass::disableCrc()
gov1 0:a761fba7f8a8 402 {
gov1 0:a761fba7f8a8 403 writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb);
gov1 0:a761fba7f8a8 404 }
gov1 0:a761fba7f8a8 405
gov1 0:a761fba7f8a8 406 uint8_t LoRaClass::random()
gov1 0:a761fba7f8a8 407 {
gov1 0:a761fba7f8a8 408 return readRegister(REG_RSSI_WIDEBAND);
gov1 0:a761fba7f8a8 409 }
gov1 0:a761fba7f8a8 410
gov1 0:a761fba7f8a8 411 void LoRaClass::dumpRegisters(Stream& out)
gov1 0:a761fba7f8a8 412 {
gov1 0:a761fba7f8a8 413 for (int i = 0; i < 128; i++) {
gov1 0:a761fba7f8a8 414 out.printf("0x%x: 0x%x", i, readRegister(i));
gov1 0:a761fba7f8a8 415 }
gov1 0:a761fba7f8a8 416 }
gov1 0:a761fba7f8a8 417
gov1 0:a761fba7f8a8 418 void LoRaClass::explicitHeaderMode()
gov1 0:a761fba7f8a8 419 {
gov1 0:a761fba7f8a8 420 _implicitHeaderMode = 0;
gov1 0:a761fba7f8a8 421
gov1 0:a761fba7f8a8 422 writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
gov1 0:a761fba7f8a8 423 }
gov1 0:a761fba7f8a8 424
gov1 0:a761fba7f8a8 425 void LoRaClass::implicitHeaderMode()
gov1 0:a761fba7f8a8 426 {
gov1 0:a761fba7f8a8 427 _implicitHeaderMode = 1;
gov1 0:a761fba7f8a8 428
gov1 0:a761fba7f8a8 429 writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
gov1 0:a761fba7f8a8 430 }
gov1 0:a761fba7f8a8 431
gov1 0:a761fba7f8a8 432 void LoRaClass::handleDio0Rise()
gov1 0:a761fba7f8a8 433 {
gov1 0:a761fba7f8a8 434 int irqFlags = readRegister(REG_IRQ_FLAGS);
gov1 0:a761fba7f8a8 435
gov1 0:a761fba7f8a8 436 // clear IRQ's
gov1 0:a761fba7f8a8 437 writeRegister(REG_IRQ_FLAGS, irqFlags);
gov1 0:a761fba7f8a8 438
gov1 0:a761fba7f8a8 439 if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
gov1 0:a761fba7f8a8 440 // received a packet
gov1 0:a761fba7f8a8 441 _packetIndex = 0;
gov1 0:a761fba7f8a8 442
gov1 0:a761fba7f8a8 443 // read packet length
gov1 0:a761fba7f8a8 444 int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES);
gov1 0:a761fba7f8a8 445
gov1 0:a761fba7f8a8 446 // set FIFO address to current RX address
gov1 0:a761fba7f8a8 447 writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
gov1 0:a761fba7f8a8 448
gov1 0:a761fba7f8a8 449 if (_onReceive) {
gov1 0:a761fba7f8a8 450 _onReceive(packetLength);
gov1 0:a761fba7f8a8 451 }
gov1 0:a761fba7f8a8 452
gov1 0:a761fba7f8a8 453 // reset FIFO address
gov1 0:a761fba7f8a8 454 writeRegister(REG_FIFO_ADDR_PTR, 0);
gov1 0:a761fba7f8a8 455 }
gov1 0:a761fba7f8a8 456 }
gov1 0:a761fba7f8a8 457
gov1 0:a761fba7f8a8 458 uint8_t LoRaClass::readRegister(uint8_t address)
gov1 0:a761fba7f8a8 459 {
gov1 0:a761fba7f8a8 460 return singleTransfer(address & 0x7f, 0x00);
gov1 0:a761fba7f8a8 461 }
gov1 0:a761fba7f8a8 462
gov1 0:a761fba7f8a8 463 void LoRaClass::writeRegister(uint8_t address, uint8_t value)
gov1 0:a761fba7f8a8 464 {
gov1 0:a761fba7f8a8 465 singleTransfer(address | 0x80, value);
gov1 0:a761fba7f8a8 466 }
gov1 0:a761fba7f8a8 467
gov1 0:a761fba7f8a8 468 uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
gov1 0:a761fba7f8a8 469 {
gov1 0:a761fba7f8a8 470 uint8_t response;
gov1 0:a761fba7f8a8 471
gov1 0:a761fba7f8a8 472 _ss = 0;
gov1 0:a761fba7f8a8 473
gov1 0:a761fba7f8a8 474 spi.write(address);
gov1 0:a761fba7f8a8 475 response = spi.write(value);
gov1 0:a761fba7f8a8 476
gov1 0:a761fba7f8a8 477 _ss = 1;
gov1 0:a761fba7f8a8 478
gov1 0:a761fba7f8a8 479 return response;
gov1 0:a761fba7f8a8 480 }
gov1 0:a761fba7f8a8 481
gov1 0:a761fba7f8a8 482 void LoRaClass::onDio0Rise()
gov1 0:a761fba7f8a8 483 {
gov1 0:a761fba7f8a8 484 LoRa.handleDio0Rise();
gov1 0:a761fba7f8a8 485 }
gov1 0:a761fba7f8a8 486
gov1 0:a761fba7f8a8 487 LoRaClass LoRa;