diff --git a/include/LoRa.h b/include/LoRa.h index c65ce64..a957b7b 100644 --- a/include/LoRa.h +++ b/include/LoRa.h @@ -1,18 +1,40 @@ // Copyright (c) Sandeep Mistry. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Reimported from https://github.com/sandeepmistry/arduino-LoRa +// https://github.com/sandeepmistry/arduino-LoRa/commit/01bf044b769a2ab276b59fa8cb24e587b24fc787 + +// Added modemStatus() + + #ifndef LORA_H #define LORA_H #include #include -#define LORA_DEFAULT_SS_PIN 10 -#define LORA_DEFAULT_RESET_PIN 9 -#define LORA_DEFAULT_DIO0_PIN 2 - -#define PA_OUTPUT_RFO_PIN 0 -#define PA_OUTPUT_PA_BOOST_PIN 1 +#if defined(ARDUINO_SAMD_MKRWAN1300) +#define LORA_DEFAULT_SPI SPI1 +#define LORA_DEFAULT_SPI_FREQUENCY 200000 +#define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB +#define LORA_DEFAULT_RESET_PIN -1 +#define LORA_DEFAULT_DIO0_PIN -1 +#elif defined(ARDUINO_SAMD_MKRWAN1310) +#define LORA_DEFAULT_SPI SPI1 +#define LORA_DEFAULT_SPI_FREQUENCY 200000 +#define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB +#define LORA_DEFAULT_RESET_PIN -1 +#define LORA_DEFAULT_DIO0_PIN LORA_IRQ +#else +#define LORA_DEFAULT_SPI SPI +#define LORA_DEFAULT_SPI_FREQUENCY 8E6 +#define LORA_DEFAULT_SS_PIN 10 +#define LORA_DEFAULT_RESET_PIN 9 +#define LORA_DEFAULT_DIO0_PIN 2 +#endif + +#define PA_OUTPUT_RFO_PIN 0 +#define PA_OUTPUT_PA_BOOST_PIN 1 class LoRaClass : public Stream { public: @@ -22,14 +44,15 @@ class LoRaClass : public Stream { void end(); int beginPacket(int implicitHeader = false); - int endPacket(); + int endPacket(bool async = false); int parsePacket(int size = 0); int packetRssi(); - uint8_t packetRssiRaw(); float packetSnr(); long packetFrequencyError(); + int rssi(); + // from Print virtual size_t write(uint8_t byte); virtual size_t write(const uint8_t *buffer, size_t size); @@ -40,24 +63,32 @@ class LoRaClass : public Stream { virtual int peek(); virtual void flush(); +#ifndef ARDUINO_SAMD_MKRWAN1300 void onReceive(void(*callback)(int)); + void onTxDone(void(*callback)()); void receive(int size = 0); +#endif void idle(); void sleep(); void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN); - uint32_t getFrequency(); void setFrequency(long frequency); void setSpreadingFactor(int sf); - long getSignalBandwidth(); void setSignalBandwidth(long sbw); void setCodingRate4(int denominator); void setPreambleLength(long length); void setSyncWord(int sw); - uint8_t modemStatus(); void enableCrc(); void disableCrc(); + void enableInvertIQ(); + void disableInvertIQ(); + + void setOCP(uint8_t mA); // Over Current Protection control + + void setGain(uint8_t gain); // Set LNA gain + + uint8_t modemStatus(); // Added for KISSLoRaTNC // deprecated void crc() { enableCrc(); } @@ -66,6 +97,7 @@ class LoRaClass : public Stream { byte random(); void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN); + void setSPI(SPIClass& spi); void setSPIFrequency(uint32_t frequency); void dumpRegisters(Stream& out); @@ -75,6 +107,12 @@ class LoRaClass : public Stream { void implicitHeaderMode(); void handleDio0Rise(); + bool isTransmitting(); + + int getSpreadingFactor(); + long getSignalBandwidth(); + + void setLdoFlag(); uint8_t readRegister(uint8_t address); void writeRegister(uint8_t address, uint8_t value); @@ -84,6 +122,7 @@ class LoRaClass : public Stream { private: SPISettings _spiSettings; + SPIClass* _spi; int _ss; int _reset; int _dio0; @@ -91,8 +130,9 @@ class LoRaClass : public Stream { int _packetIndex; int _implicitHeaderMode; void (*_onReceive)(int); + void (*_onTxDone)(); }; extern LoRaClass LoRa; -#endif \ No newline at end of file +#endif diff --git a/src/LoRa.cpp b/src/LoRa.cpp index 2557d46..b679154 100644 --- a/src/LoRa.cpp +++ b/src/LoRa.cpp @@ -1,21 +1,21 @@ // Copyright (c) Sandeep Mistry. All rights reserved. -// Licensed under the MIT license. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// Modifications and additions copyright 2018 by Mark Qvist -// Obviously still under the MIT license. +// Reimported from https://github.com/sandeepmistry/arduino-LoRa +// https://github.com/sandeepmistry/arduino-LoRa/commit/01bf044b769a2ab276b59fa8cb24e587b24fc787 -// Further modifications and additions copyright 2020 by -// Steve Miller. Again, still under the MIT License. +// Added REG_MODEM_STAT and LoRaClass::modemStatus() -#include "LoRa.h" +#include -// Registers +// registers #define REG_FIFO 0x00 #define REG_OP_MODE 0x01 #define REG_FRF_MSB 0x06 #define REG_FRF_MID 0x07 #define REG_FRF_LSB 0x08 #define REG_PA_CONFIG 0x09 +#define REG_OCP 0x0b #define REG_LNA 0x0c #define REG_FIFO_ADDR_PTR 0x0d #define REG_FIFO_TX_BASE_ADDR 0x0e @@ -23,9 +23,10 @@ #define REG_FIFO_RX_CURRENT_ADDR 0x10 #define REG_IRQ_FLAGS 0x12 #define REG_RX_NB_BYTES 0x13 -#define REG_MODEM_STAT 0x18 +#define REG_MODEM_STAT 0x18 // Added for KISSLoRaTNC #define REG_PKT_SNR_VALUE 0x19 #define REG_PKT_RSSI_VALUE 0x1a +#define REG_RSSI_VALUE 0x1b #define REG_MODEM_CONFIG_1 0x1d #define REG_MODEM_CONFIG_2 0x1e #define REG_PREAMBLE_MSB 0x20 @@ -37,13 +38,15 @@ #define REG_FREQ_ERROR_LSB 0x2a #define REG_RSSI_WIDEBAND 0x2c #define REG_DETECTION_OPTIMIZE 0x31 +#define REG_INVERTIQ 0x33 #define REG_DETECTION_THRESHOLD 0x37 #define REG_SYNC_WORD 0x39 +#define REG_INVERTIQ2 0x3b #define REG_DIO_MAPPING_1 0x40 #define REG_VERSION 0x42 -#define REG_PA_DAC 0x4D +#define REG_PA_DAC 0x4d -// Modes +// modes #define MODE_LONG_RANGE_MODE 0x80 #define MODE_SLEEP 0x00 #define MODE_STDBY 0x01 @@ -51,29 +54,35 @@ #define MODE_RX_CONTINUOUS 0x05 #define MODE_RX_SINGLE 0x06 -// PA_CONFIG 0x09 -#define PA_SELECT 0x80 -#define PA_MAX_POWER 0x70 -#define PA_OUTPUT_POWER 0x0f - -// PA_DAC config -#define PA_DAC_DISABLE 0x04 -#define PA_DAC_ENABLE 0x07 +// PA config +#define PA_BOOST 0x80 // IRQ masks #define IRQ_TX_DONE_MASK 0x08 #define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20 #define IRQ_RX_DONE_MASK 0x40 +#define RF_MID_BAND_THRESHOLD 525E6 +#define RSSI_OFFSET_HF_PORT 157 +#define RSSI_OFFSET_LF_PORT 164 + #define MAX_PKT_LENGTH 255 +#if (ESP8266 || ESP32) + #define ISR_PREFIX ICACHE_RAM_ATTR +#else + #define ISR_PREFIX +#endif + LoRaClass::LoRaClass() : - _spiSettings(8E6, MSBFIRST, SPI_MODE0), + _spiSettings(LORA_DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0), + _spi(&LORA_DEFAULT_SPI), _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), _frequency(0), _packetIndex(0), _implicitHeaderMode(0), - _onReceive(NULL) + _onReceive(NULL), + _onTxDone(NULL) { // overide Stream timeout value setTimeout(0); @@ -81,9 +90,28 @@ LoRaClass::LoRaClass() : int LoRaClass::begin(long frequency) { +#if defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) + pinMode(LORA_IRQ_DUMB, OUTPUT); + digitalWrite(LORA_IRQ_DUMB, LOW); + + // Hardware reset + pinMode(LORA_BOOT0, OUTPUT); + digitalWrite(LORA_BOOT0, LOW); + + pinMode(LORA_RESET, OUTPUT); + digitalWrite(LORA_RESET, HIGH); + delay(200); + digitalWrite(LORA_RESET, LOW); + delay(200); + digitalWrite(LORA_RESET, HIGH); + delay(50); +#endif + // setup pins pinMode(_ss, OUTPUT); - + // set SS high + digitalWrite(_ss, HIGH); + if (_reset != -1) { pinMode(_reset, OUTPUT); @@ -95,7 +123,7 @@ int LoRaClass::begin(long frequency) } // start SPI - SPI.begin(); + _spi->begin(); // check version uint8_t version = readRegister(REG_VERSION); @@ -119,8 +147,8 @@ int LoRaClass::begin(long frequency) // set auto AGC writeRegister(REG_MODEM_CONFIG_3, 0x04); - // set output power to 2 dBm - setTxPower(2); + // set output power to 17 dBm + setTxPower(17); // put in standby mode idle(); @@ -128,185 +156,21 @@ int LoRaClass::begin(long frequency) return 1; } -void LoRaClass::setTxPower(int level, int outputPin) -{ - if (PA_OUTPUT_RFO_PIN == outputPin) { - // RFO - if (level < 0) { - level = 0; - } else if (level > 14) { - level = 14; - } - writeRegister(REG_PA_DAC, PA_DAC_DISABLE); - writeRegister(REG_PA_CONFIG, PA_MAX_POWER | level); - } else { - // PA BOOST - if (level < 2) { - level = 2; - } else if (level > 20) { - level = 20; - } - if (level > 17) { - writeRegister(REG_PA_DAC, PA_DAC_ENABLE); - level -= 3; - } else { - writeRegister(REG_PA_DAC, PA_DAC_DISABLE); - } - writeRegister(REG_PA_CONFIG, PA_SELECT | (level - 2)); - } -} - -void LoRaClass::setFrequency(long frequency) { - _frequency = frequency; - - uint32_t frf = ((uint64_t)frequency << 19) / 32000000; - - writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16)); - writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8)); - writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0)); -} - -uint32_t LoRaClass::getFrequency() { - uint8_t msb = readRegister(REG_FRF_MSB); - uint8_t mid = readRegister(REG_FRF_MID); - uint8_t lsb = readRegister(REG_FRF_LSB); - - uint32_t frf = ((uint32_t)msb << 16) | ((uint32_t)mid << 8) | (uint32_t)lsb; - uint64_t frm = (uint64_t)frf*32000000; - uint32_t frequency = (frm >> 19); - - return frequency; -} - -void LoRaClass::setSpreadingFactor(int sf) -{ - if (sf < 6) { - sf = 6; - } else if (sf > 12) { - sf = 12; - } - - if (sf == 6) { - writeRegister(REG_DETECTION_OPTIMIZE, 0xc5); - writeRegister(REG_DETECTION_THRESHOLD, 0x0c); - } else { - writeRegister(REG_DETECTION_OPTIMIZE, 0xc3); - writeRegister(REG_DETECTION_THRESHOLD, 0x0a); - } - - writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0)); -} - -long LoRaClass::getSignalBandwidth() -{ - byte bw = (readRegister(REG_MODEM_CONFIG_1) >> 4); - switch (bw) { - case 0: return 7.8E3; - case 1: return 10.4E3; - case 2: return 15.6E3; - case 3: return 20.8E3; - case 4: return 31.25E3; - case 5: return 41.7E3; - case 6: return 62.5E3; - case 7: return 125E3; - case 8: return 250E3; - case 9: return 500E3; - } - return 0; -} - -void LoRaClass::setSignalBandwidth(long sbw) -{ - int bw; - - if (sbw <= 7.8E3) { - bw = 0; - } else if (sbw <= 10.4E3) { - bw = 1; - } else if (sbw <= 15.6E3) { - bw = 2; - } else if (sbw <= 20.8E3) { - bw = 3; - } else if (sbw <= 31.25E3) { - bw = 4; - } else if (sbw <= 41.7E3) { - bw = 5; - } else if (sbw <= 62.5E3) { - bw = 6; - } else if (sbw <= 125E3) { - bw = 7; - } else if (sbw <= 250E3) { - bw = 8; - } else /*if (sbw <= 250E3)*/ { - bw = 9; - } - - writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4)); -} - -void LoRaClass::setCodingRate4(int denominator) -{ - if (denominator < 5) { - denominator = 5; - } else if (denominator > 8) { - denominator = 8; - } - - int cr = denominator - 4; - - writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1)); -} - -void LoRaClass::setPreambleLength(long length) -{ - writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8)); - writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0)); -} - -void LoRaClass::setSyncWord(int sw) -{ - writeRegister(REG_SYNC_WORD, sw); -} - -void LoRaClass::enableCrc() -{ - writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04); -} - -void LoRaClass::disableCrc() -{ - writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb); -} - -byte LoRaClass::random() -{ - return readRegister(REG_RSSI_WIDEBAND); -} - -void LoRaClass::setPins(int ss, int reset, int dio0) -{ - _ss = ss; - _reset = reset; - _dio0 = dio0; - -} - -void LoRaClass::setSPIFrequency(uint32_t frequency) -{ - _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); -} - void LoRaClass::end() { // put in sleep mode sleep(); // stop SPI - SPI.end(); + _spi->end(); } int LoRaClass::beginPacket(int implicitHeader) { + if (isTransmitting()) { + return 0; + } + // put in standby mode idle(); @@ -323,20 +187,39 @@ int LoRaClass::beginPacket(int implicitHeader) return 1; } -int LoRaClass::endPacket() +int LoRaClass::endPacket(bool async) { + + if ((async) && (_onTxDone)) + writeRegister(REG_DIO_MAPPING_1, 0x40); // DIO0 => TXDONE + // put in TX mode writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX); - // wait for TX done - while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) { - yield(); + if (!async) { + // wait for TX done + while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) { + yield(); + } + // clear IRQ's + writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); + } + + return 1; +} + +bool LoRaClass::isTransmitting() +{ + if ((readRegister(REG_OP_MODE) & MODE_TX) == MODE_TX) { + return true; } - // clear IRQ's - writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); + if (readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) { + // clear IRQ's + writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); + } - return 1; + return false; } int LoRaClass::parsePacket(int size) @@ -384,22 +267,9 @@ int LoRaClass::parsePacket(int size) return packetLength; } -uint8_t LoRaClass::modemStatus() { - return readRegister(REG_MODEM_STAT); -} - -uint8_t LoRaClass::packetRssiRaw() { - uint8_t pkt_rssi_value = readRegister(REG_PKT_RSSI_VALUE); - return pkt_rssi_value; -} - -int LoRaClass::packetRssi() { - int pkt_rssi = (int)readRegister(REG_PKT_RSSI_VALUE); - // TODO: change this to look at the actual model code - if (_frequency < 820E6) pkt_rssi -= 7; - pkt_rssi -= 157; - - return pkt_rssi; +int LoRaClass::packetRssi() +{ + return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < RF_MID_BAND_THRESHOLD ? RSSI_OFFSET_LF_PORT : RSSI_OFFSET_HF_PORT)); } float LoRaClass::packetSnr() @@ -426,6 +296,11 @@ long LoRaClass::packetFrequencyError() return static_cast(fError); } +int LoRaClass::rssi() +{ + return (readRegister(REG_RSSI_VALUE) - (_frequency < RF_MID_BAND_THRESHOLD ? RSSI_OFFSET_LF_PORT : RSSI_OFFSET_HF_PORT)); +} + size_t LoRaClass::write(uint8_t byte) { return write(&byte, sizeof(byte)); @@ -489,14 +364,31 @@ void LoRaClass::flush() { } +#ifndef ARDUINO_SAMD_MKRWAN1300 void LoRaClass::onReceive(void(*callback)(int)) { _onReceive = callback; if (callback) { pinMode(_dio0, INPUT); +#ifdef SPI_HAS_NOTUSINGINTERRUPT + SPI.usingInterrupt(digitalPinToInterrupt(_dio0)); +#endif + attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING); + } else { + detachInterrupt(digitalPinToInterrupt(_dio0)); +#ifdef SPI_HAS_NOTUSINGINTERRUPT + SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0)); +#endif + } +} + +void LoRaClass::onTxDone(void(*callback)()) +{ + _onTxDone = callback; - writeRegister(REG_DIO_MAPPING_1, 0x00); + if (callback) { + pinMode(_dio0, INPUT); #ifdef SPI_HAS_NOTUSINGINTERRUPT SPI.usingInterrupt(digitalPinToInterrupt(_dio0)); #endif @@ -511,6 +403,9 @@ void LoRaClass::onReceive(void(*callback)(int)) void LoRaClass::receive(int size) { + + writeRegister(REG_DIO_MAPPING_1, 0x00); // DIO0 => RXDONE + if (size > 0) { implicitHeaderMode(); @@ -521,6 +416,7 @@ void LoRaClass::receive(int size) writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS); } +#endif void LoRaClass::idle() { @@ -532,6 +428,249 @@ void LoRaClass::sleep() writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP); } +void LoRaClass::setTxPower(int level, int outputPin) +{ + if (PA_OUTPUT_RFO_PIN == outputPin) { + // RFO + if (level < 0) { + level = 0; + } else if (level > 14) { + level = 14; + } + + writeRegister(REG_PA_CONFIG, 0x70 | level); + } else { + // PA BOOST + if (level > 17) { + if (level > 20) { + level = 20; + } + + // subtract 3 from level, so 18 - 20 maps to 15 - 17 + level -= 3; + + // High Power +20 dBm Operation (Semtech SX1276/77/78/79 5.4.3.) + writeRegister(REG_PA_DAC, 0x87); + setOCP(140); + } else { + if (level < 2) { + level = 2; + } + //Default value PA_HF/LF or +17dBm + writeRegister(REG_PA_DAC, 0x84); + setOCP(100); + } + + writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2)); + } +} + +void LoRaClass::setFrequency(long frequency) +{ + _frequency = frequency; + + uint64_t frf = ((uint64_t)frequency << 19) / 32000000; + + writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16)); + writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8)); + writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0)); +} + +int LoRaClass::getSpreadingFactor() +{ + return readRegister(REG_MODEM_CONFIG_2) >> 4; +} + +void LoRaClass::setSpreadingFactor(int sf) +{ + if (sf < 6) { + sf = 6; + } else if (sf > 12) { + sf = 12; + } + + if (sf == 6) { + writeRegister(REG_DETECTION_OPTIMIZE, 0xc5); + writeRegister(REG_DETECTION_THRESHOLD, 0x0c); + } else { + writeRegister(REG_DETECTION_OPTIMIZE, 0xc3); + writeRegister(REG_DETECTION_THRESHOLD, 0x0a); + } + + writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0)); + setLdoFlag(); +} + +long LoRaClass::getSignalBandwidth() +{ + byte bw = (readRegister(REG_MODEM_CONFIG_1) >> 4); + + switch (bw) { + case 0: return 7.8E3; + case 1: return 10.4E3; + case 2: return 15.6E3; + case 3: return 20.8E3; + case 4: return 31.25E3; + case 5: return 41.7E3; + case 6: return 62.5E3; + case 7: return 125E3; + case 8: return 250E3; + case 9: return 500E3; + } + + return -1; +} + +void LoRaClass::setSignalBandwidth(long sbw) +{ + int bw; + + if (sbw <= 7.8E3) { + bw = 0; + } else if (sbw <= 10.4E3) { + bw = 1; + } else if (sbw <= 15.6E3) { + bw = 2; + } else if (sbw <= 20.8E3) { + bw = 3; + } else if (sbw <= 31.25E3) { + bw = 4; + } else if (sbw <= 41.7E3) { + bw = 5; + } else if (sbw <= 62.5E3) { + bw = 6; + } else if (sbw <= 125E3) { + bw = 7; + } else if (sbw <= 250E3) { + bw = 8; + } else /*if (sbw <= 250E3)*/ { + bw = 9; + } + + writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4)); + setLdoFlag(); +} + +void LoRaClass::setLdoFlag() +{ + // Section 4.1.1.5 + long symbolDuration = 1000 / ( getSignalBandwidth() / (1L << getSpreadingFactor()) ) ; + + // Section 4.1.1.6 + boolean ldoOn = symbolDuration > 16; + + uint8_t config3 = readRegister(REG_MODEM_CONFIG_3); + bitWrite(config3, 3, ldoOn); + writeRegister(REG_MODEM_CONFIG_3, config3); +} + +void LoRaClass::setCodingRate4(int denominator) +{ + if (denominator < 5) { + denominator = 5; + } else if (denominator > 8) { + denominator = 8; + } + + int cr = denominator - 4; + + writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1)); +} + +void LoRaClass::setPreambleLength(long length) +{ + writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8)); + writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0)); +} + +void LoRaClass::setSyncWord(int sw) +{ + writeRegister(REG_SYNC_WORD, sw); +} + +void LoRaClass::enableCrc() +{ + writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04); +} + +void LoRaClass::disableCrc() +{ + writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb); +} + +void LoRaClass::enableInvertIQ() +{ + writeRegister(REG_INVERTIQ, 0x66); + writeRegister(REG_INVERTIQ2, 0x19); +} + +void LoRaClass::disableInvertIQ() +{ + writeRegister(REG_INVERTIQ, 0x27); + writeRegister(REG_INVERTIQ2, 0x1d); +} + +void LoRaClass::setOCP(uint8_t mA) +{ + uint8_t ocpTrim = 27; + + if (mA <= 120) { + ocpTrim = (mA - 45) / 5; + } else if (mA <=240) { + ocpTrim = (mA + 30) / 10; + } + + writeRegister(REG_OCP, 0x20 | (0x1F & ocpTrim)); +} + +void LoRaClass::setGain(uint8_t gain) +{ + // check allowed range + if (gain > 6) { + gain = 6; + } + + // set to standby + idle(); + + // set gain + if (gain == 0) { + // if gain = 0, enable AGC + writeRegister(REG_MODEM_CONFIG_3, 0x04); + } else { + // disable AGC + writeRegister(REG_MODEM_CONFIG_3, 0x00); + + // clear Gain and set LNA boost + writeRegister(REG_LNA, 0x03); + + // set gain + writeRegister(REG_LNA, readRegister(REG_LNA) | (gain << 5)); + } +} + +byte LoRaClass::random() +{ + return readRegister(REG_RSSI_WIDEBAND); +} + +void LoRaClass::setPins(int ss, int reset, int dio0) +{ + _ss = ss; + _reset = reset; + _dio0 = dio0; +} + +void LoRaClass::setSPI(SPIClass& spi) +{ + _spi = &spi; +} + +void LoRaClass::setSPIFrequency(uint32_t frequency) +{ + _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); +} + void LoRaClass::dumpRegisters(Stream& out) { for (int i = 0; i < 128; i++) { @@ -564,21 +703,26 @@ void LoRaClass::handleDio0Rise() writeRegister(REG_IRQ_FLAGS, irqFlags); if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) { - // received a packet - _packetIndex = 0; - // read packet length - int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES); + if ((irqFlags & IRQ_RX_DONE_MASK) != 0) { + // received a packet + _packetIndex = 0; - // set FIFO address to current RX address - writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR)); + // read packet length + int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES); - if (_onReceive) { - _onReceive(packetLength); - } + // set FIFO address to current RX address + writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR)); - // reset FIFO address - writeRegister(REG_FIFO_ADDR_PTR, 0); + if (_onReceive) { + _onReceive(packetLength); + } + } + else if ((irqFlags & IRQ_TX_DONE_MASK) != 0) { + if (_onTxDone) { + _onTxDone(); + } + } } } @@ -598,19 +742,24 @@ uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value) digitalWrite(_ss, LOW); - SPI.beginTransaction(_spiSettings); - SPI.transfer(address); - response = SPI.transfer(value); - SPI.endTransaction(); + _spi->beginTransaction(_spiSettings); + _spi->transfer(address); + response = _spi->transfer(value); + _spi->endTransaction(); digitalWrite(_ss, HIGH); return response; } -void LoRaClass::onDio0Rise() +// Added for KISSLoRaTNC +uint8_t LoRaClass::modemStatus() { + return readRegister(REG_MODEM_STAT); +} + +ISR_PREFIX void LoRaClass::onDio0Rise() { LoRa.handleDio0Rise(); } -LoRaClass LoRa; \ No newline at end of file +LoRaClass LoRa;