diff --git a/examples/SX127x_ChannelActivityDetection/SX127x_ChannelActivityDetection.ino b/examples/SX127x_ChannelActivityDetection/SX127x_ChannelActivityDetection.ino index 90835401..718b62d2 100644 --- a/examples/SX127x_ChannelActivityDetection/SX127x_ChannelActivityDetection.ino +++ b/examples/SX127x_ChannelActivityDetection/SX127x_ChannelActivityDetection.ino @@ -7,12 +7,7 @@ if the LoRa channel is free, or if you should start receiving a message. - Other modules from SX127x family can also be used. - SX1272 lora = Kite.ModuleA; - SX1273 lora = Kite.ModuleA; - SX1276 lora = Kite.ModuleA; - SX1277 lora = Kite.ModuleA; - SX1279 lora = Kite.ModuleA; + Other modules from SX127x/RFM9x family can also be used. */ // include the library diff --git a/examples/SX127x_Receive/SX127x_Receive.ino b/examples/SX127x_Receive/SX127x_Receive.ino index f7a50220..a98f33e9 100644 --- a/examples/SX127x_Receive/SX127x_Receive.ino +++ b/examples/SX127x_Receive/SX127x_Receive.ino @@ -11,12 +11,7 @@ - sync word - preamble length - Other modules from SX127x family can also be used. - SX1272 lora = Kite.ModuleA; - SX1273 lora = Kite.ModuleA; - SX1276 lora = Kite.ModuleA; - SX1277 lora = Kite.ModuleA; - SX1279 lora = Kite.ModuleA; + Other modules from SX127x/RFM9x family can also be used. */ // include the library @@ -73,13 +68,13 @@ void loop() { // print the RSSI (Received Signal Strength Indicator) // of the last received packet Serial.print("[SX1278] RSSI:\t\t"); - Serial.print(lora.lastPacketRSSI); + Serial.print(lora.getRSSI()); Serial.println(" dBm"); // print the SNR (Signal-to-Noise Ratio) // of the last received packet Serial.print("[SX1278] SNR:\t\t"); - Serial.print(lora.lastPacketSNR); + Serial.print(lora.getSNR()); Serial.println(" dBm"); // print frequency error diff --git a/examples/SX127x_ReceiveInterrupt/SX127x_ReceiveInterrupt.ino b/examples/SX127x_ReceiveInterrupt/SX127x_ReceiveInterrupt.ino index 6285e7d4..cf0efff0 100644 --- a/examples/SX127x_ReceiveInterrupt/SX127x_ReceiveInterrupt.ino +++ b/examples/SX127x_ReceiveInterrupt/SX127x_ReceiveInterrupt.ino @@ -12,12 +12,7 @@ - coding rate - sync word - Other modules from SX127x family can also be used. - SX1272 lora = Kite.ModuleA; - SX1273 lora = Kite.ModuleA; - SX1276 lora = Kite.ModuleA; - SX1277 lora = Kite.ModuleA; - SX1279 lora = Kite.ModuleA; + Other modules from SX127x/RFM9x family can also be used. */ // include the library @@ -124,12 +119,12 @@ void loop() { // print RSSI (Received Signal Strength Indicator) Serial.print("RSSI:\t\t"); - Serial.print(lora.lastPacketRSSI); + Serial.print(lora.getRSSI()); Serial.println(" dBm"); // print SNR (Signal-to-Noise Ratio) Serial.print("SNR:\t\t"); - Serial.print(lora.lastPacketSNR); + Serial.print(lora.getSNR()); Serial.println(" dBm"); // print frequency error diff --git a/examples/SX127x_Settings/SX127x_Settings.ino b/examples/SX127x_Settings/SX127x_Settings.ino index 3a53da12..f87c2298 100644 --- a/examples/SX127x_Settings/SX127x_Settings.ino +++ b/examples/SX127x_Settings/SX127x_Settings.ino @@ -10,6 +10,8 @@ - coding rate - sync word - output power during transmission + + Other modules from SX127x/RFM9x family can also be used. */ // include the library @@ -18,18 +20,8 @@ // SX1278 module is in slot A on the shield SX1278 loraSX1278 = Kite.ModuleA; -// create another instance of LoRa class using SX1272 module and user-specified pinout -// NSS pin: 6 -// DIO0 pin: 4 -// DIO1 pin: 5 -SX1272 loraSX1272 = new Module(6, 4, 5); - -// create third instance of LoRa class using SX1276 module and user-specified pinout -// we ran out of Uno digital pins, so here we use analog ones -// NSS pin: A0 -// DIO0 pin: A1 -// DIO1 pin: A2 -SX1276 loraSX1276 = new Module(A0, A1, A2); +// SX1272 module is in slot B on the shield +SX1272 loraSX1272 = Kite.ModuleB; void setup() { Serial.begin(9600); @@ -54,28 +46,7 @@ void setup() { while (true); } - // initialize the second LoRa instance with non-default settings - // this LoRa link will have maximum range, but very low data rate - Serial.print(F("[SX1276] Initializing ... ")); - // carrier frequency: 434.0 MHz - // bandwidth: 7.8 kHz - // spreading factor: 12 - // coding rate: 8 - // sync word: 0x13 - // output power: 17 dBm - // current limit: 100 mA - // preamble length: 8 symbols - // amplifier gain: 0 (automatic gain control) - state = loraSX1276.begin(434.0, 7.8, 12, 8, 0x13); - if (state == ERR_NONE) { - Serial.println(F("success!")); - } else { - Serial.print(F("failed, code ")); - Serial.println(state); - while (true); - } - - // initialize the third LoRa instance with + // initialize the second LoRa instance with // non-default settings // this LoRa link will have high data rate, // but lower range diff --git a/examples/SX127x_Transmit/SX127x_Transmit.ino b/examples/SX127x_Transmit/SX127x_Transmit.ino index f5881858..2f82c6db 100644 --- a/examples/SX127x_Transmit/SX127x_Transmit.ino +++ b/examples/SX127x_Transmit/SX127x_Transmit.ino @@ -7,12 +7,7 @@ - null-terminated char array (C-string) - arbitrary binary data (byte array) - Other modules from SX127x family can also be used. - SX1272 lora = Kite.ModuleA; - SX1273 lora = Kite.ModuleA; - SX1276 lora = Kite.ModuleA; - SX1277 lora = Kite.ModuleA; - SX1279 lora = Kite.ModuleA; + Other modules from SX127x/RFM9x family can also be used. */ // include the library @@ -64,7 +59,7 @@ void loop() { // print measured data rate Serial.print("Datarate:\t"); - Serial.print(lora.dataRate); + Serial.print(lora.getDataRate()); Serial.println(" bps"); } else if (state == ERR_PACKET_TOO_LONG) { diff --git a/examples/SX127x_TransmitInterrupt/SX127x_TransmitInterrupt.ino b/examples/SX127x_TransmitInterrupt/SX127x_TransmitInterrupt.ino index 18a49d30..e6abe241 100644 --- a/examples/SX127x_TransmitInterrupt/SX127x_TransmitInterrupt.ino +++ b/examples/SX127x_TransmitInterrupt/SX127x_TransmitInterrupt.ino @@ -8,12 +8,7 @@ - null-terminated char array (C-string) - arbitrary binary data (byte array) - Other modules from SX127x family can also be used. - SX1272 lora = Kite.ModuleA; - SX1273 lora = Kite.ModuleA; - SX1276 lora = Kite.ModuleA; - SX1277 lora = Kite.ModuleA; - SX1279 lora = Kite.ModuleA; + Other modules from SX127x/RFM9x family can also be used. */ // include the library @@ -98,6 +93,10 @@ void loop() { 0x78, 0xAB, 0xCD, 0xEF}; int state = lora.transmit(byteArr, 8); */ + + // NOTE: when using interrupt-driven transmit method, + // it is not possible to automatically measure + // transmission data rate using getDataRate() if (state != ERR_NONE) { Serial.print(F("failed, code ")); diff --git a/keywords.txt b/keywords.txt index d05cd39a..1a1b07a8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -14,6 +14,10 @@ ESP8266 KEYWORD1 HC05 KEYWORD1 JDY08 KEYWORD1 RF69 KEYWORD1 +RFM95 KEYWORD1 +RFM96 KEYWORD1 +RFM97 KEYWORD1 +RFM98 KEYWORD1 SX1231 KEYWORD1 SX1272 KEYWORD1 SX1273 KEYWORD1 @@ -37,34 +41,43 @@ ModuleA KEYWORD2 ModuleB KEYWORD2 Module KEYWORD2 -# SX1272/73/76/77/78/79 + RF69 -dataRate KEYWORD2 -lastPacketRSSI KEYWORD2 +# SX127x/RFM9x + RF69 begin KEYWORD2 +beginFSK KEYWORD2 transmit KEYWORD2 receive KEYWORD2 +scanChannel KEYWORD2 sleep KEYWORD2 standby KEYWORD2 +transmitDirect KEYWORD2 +receiveDirect KEYWORD2 +packetMode KEYWORD2 +setDio0Action KEYWORD2 +setDio1Action KEYWORD2 +startTransmit KEYWORD2 +startReceive KEYWORD2 +readData KEYWORD2 setBandwidth KEYWORD2 setSpreadingFactor KEYWORD2 setCodingRate KEYWORD2 setFrequency KEYWORD2 setSyncWord KEYWORD2 setOutputPower KEYWORD2 -listen KEYWORD2 -onReceive KEYWORD2 -readData KEYWORD2 -transmitDirect KEYWORD2 -receiveDirect KEYWORD2 -packetMode KEYWORD2 - -# RF69-specific +setCurrentLimit KEYWORD2 +setPreambleLength KEYWORD2 +setGain KEYWORD2 +getFrequencyError KEYWORD2 +getRSSI KEYWORD2 +getSNR KEYWORD2 +getDataRate KEYWORD2 setBitRate KEYWORD2 setRxBandwidth KEYWORD2 setFrequencyDeviation KEYWORD2 setNodeAddress KEYWORD2 setBroadcastAddress KEYWORD2 disableAddressFiltering KEYWORD2 + +# RF69-specific setAESKey KEYWORD2 enableAES KEYWORD2 disableAES KEYWORD2 diff --git a/src/KiteLib.h b/src/KiteLib.h index e2e8863f..35170761 100644 --- a/src/KiteLib.h +++ b/src/KiteLib.h @@ -8,6 +8,10 @@ #include "modules/HC05.h" #include "modules/JDY08.h" #include "modules/RF69.h" +#include "modules/RFM95.h" +#include "modules/RFM96.h" +#include "modules/RFM97.h" +#include "modules/RFM98.h" #include "modules/SX1231.h" #include "modules/SX1272.h" #include "modules/SX1273.h" diff --git a/src/Module.cpp b/src/Module.cpp index ecdd32a5..662a445e 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -107,7 +107,7 @@ int16_t Module::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) { return(maskedValue); } -int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb) { +int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval) { if((msb > 7) || (lsb > 7) || (lsb > msb)) { return(ERR_INVALID_BIT_RANGE); } @@ -117,36 +117,39 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t uint8_t newValue = (currentValue & ~mask) | (value & mask); SPIwriteRegister(reg, newValue); - // some registers need a bit of time to process the change - // e.g. SX127X_REG_OP_MODE - delay(20); - - // check if the write was successful - uint8_t readValue = SPIreadRegister(reg); - if(readValue != newValue) { - DEBUG_PRINTLN(); - DEBUG_PRINT_STR("address:\t0x"); - DEBUG_PRINTLN_HEX(reg); - DEBUG_PRINT_STR("bits:\t\t"); - DEBUG_PRINT(msb); - DEBUG_PRINT(' '); - DEBUG_PRINTLN(lsb); - DEBUG_PRINT_STR("value:\t\t0b"); - DEBUG_PRINTLN_BIN(value); - DEBUG_PRINT_STR("current:\t0b"); - DEBUG_PRINTLN_BIN(currentValue); - DEBUG_PRINT_STR("mask:\t\t0b"); - DEBUG_PRINTLN_BIN(mask); - DEBUG_PRINT_STR("new:\t\t0b"); - DEBUG_PRINTLN_BIN(newValue); - DEBUG_PRINT_STR("read:\t\t0b"); - DEBUG_PRINTLN_BIN(readValue); - DEBUG_PRINTLN(); - - return(ERR_SPI_WRITE_FAILED); + // check register value each millisecond until check interval is reached + // some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE) + uint32_t start = micros(); + uint8_t readValue = 0; + while(micros() - start < (checkInterval * 1000)) { + readValue = SPIreadRegister(reg); + if(readValue == newValue) { + // check passed, we can stop the loop + return(ERR_NONE); + } } - return(ERR_NONE); + // check failed, print debug info + DEBUG_PRINTLN(); + DEBUG_PRINT_STR("address:\t0x"); + DEBUG_PRINTLN_HEX(reg); + DEBUG_PRINT_STR("bits:\t\t"); + DEBUG_PRINT(msb); + DEBUG_PRINT(' '); + DEBUG_PRINTLN(lsb); + DEBUG_PRINT_STR("value:\t\t0b"); + DEBUG_PRINTLN_BIN(value); + DEBUG_PRINT_STR("current:\t0b"); + DEBUG_PRINTLN_BIN(currentValue); + DEBUG_PRINT_STR("mask:\t\t0b"); + DEBUG_PRINTLN_BIN(mask); + DEBUG_PRINT_STR("new:\t\t0b"); + DEBUG_PRINTLN_BIN(newValue); + DEBUG_PRINT_STR("read:\t\t0b"); + DEBUG_PRINTLN_BIN(readValue); + DEBUG_PRINTLN(); + + return(ERR_SPI_WRITE_FAILED); } void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) { diff --git a/src/Module.h b/src/Module.h index dc93b7bc..56977b60 100644 --- a/src/Module.h +++ b/src/Module.h @@ -28,7 +28,7 @@ class Module { bool ATsendData(uint8_t* data, uint32_t len); int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0); - int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0); + int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2); void SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes); uint8_t SPIreadRegister(uint8_t reg); diff --git a/src/TypeDef.h b/src/TypeDef.h index 8d7ad0cf..ebf6cf8a 100644 --- a/src/TypeDef.h +++ b/src/TypeDef.h @@ -60,7 +60,7 @@ #define ERR_NONE 0 #define ERR_UNKNOWN -1 -// SX1278/SX1272/RF69 status codes +// SX127x/RFM9x/RF69 status codes #define ERR_CHIP_NOT_FOUND -2 #define ERR_EEPROM_NOT_INITIALIZED -3 #define ERR_PACKET_TOO_LONG -4 diff --git a/src/modules/RFM95.cpp b/src/modules/RFM95.cpp new file mode 100644 index 00000000..812d928c --- /dev/null +++ b/src/modules/RFM95.cpp @@ -0,0 +1,62 @@ +#include "RFM95.h" + +RFM95::RFM95(Module* mod) : SX1278(mod) { + +} + +int16_t RFM95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) { + // execute common part + int16_t state = SX127x::begin(RFM95_CHIP_VERSION, syncWord, currentLimit, preambleLength); + if(state != ERR_NONE) { + return(state); + } + + // configure settings not accessible by API + state = config(); + if(state != ERR_NONE) { + return(state); + } + + // configure publicly accessible settings + state = setFrequency(freq); + if(state != ERR_NONE) { + return(state); + } + + state = setBandwidth(bw); + if(state != ERR_NONE) { + return(state); + } + + state = setSpreadingFactor(sf); + if(state != ERR_NONE) { + return(state); + } + + state = setCodingRate(cr); + if(state != ERR_NONE) { + return(state); + } + + state = setOutputPower(power); + if(state != ERR_NONE) { + return(state); + } + + state = setGain(gain); + if(state != ERR_NONE) { + return(state); + } + + return(state); +} + +int16_t RFM95::setFrequency(float freq) { + // check frequency range + if((freq < 868.0) || (freq > 915.0)) { + return(ERR_INVALID_FREQUENCY); + } + + // set frequency + return(SX127x::setFrequencyRaw(freq)); +} diff --git a/src/modules/RFM95.h b/src/modules/RFM95.h new file mode 100644 index 00000000..f90cc77b --- /dev/null +++ b/src/modules/RFM95.h @@ -0,0 +1,27 @@ +#ifndef _KITELIB_RFM95_H +#define _KITELIB_RFM95_H + +#include "TypeDef.h" +#include "Module.h" +#include "SX127x.h" +#include "SX1278.h" + +// SX127X_REG_VERSION +#define RFM95_CHIP_VERSION 0x11 + +class RFM95: public SX1278 { + public: + // constructor + RFM95(Module* mod); + + // basic methods + int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0); + + // configuration methods + int16_t setFrequency(float freq); + + private: + +}; + +#endif diff --git a/src/modules/RFM96.cpp b/src/modules/RFM96.cpp new file mode 100644 index 00000000..e346ee7c --- /dev/null +++ b/src/modules/RFM96.cpp @@ -0,0 +1,62 @@ +#include "RFM96.h" + +RFM96::RFM96(Module* mod) : SX1278(mod) { + +} + +int16_t RFM96::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit, uint16_t preambleLength, uint8_t gain) { + // execute common part + int16_t state = SX127x::begin(RFM9X_CHIP_VERSION, syncWord, currentLimit, preambleLength); + if(state != ERR_NONE) { + return(state); + } + + // configure settings not accessible by API + state = config(); + if(state != ERR_NONE) { + return(state); + } + + // configure publicly accessible settings + state = setFrequency(freq); + if(state != ERR_NONE) { + return(state); + } + + state = setBandwidth(bw); + if(state != ERR_NONE) { + return(state); + } + + state = setSpreadingFactor(sf); + if(state != ERR_NONE) { + return(state); + } + + state = setCodingRate(cr); + if(state != ERR_NONE) { + return(state); + } + + state = setOutputPower(power); + if(state != ERR_NONE) { + return(state); + } + + state = setGain(gain); + if(state != ERR_NONE) { + return(state); + } + + return(state); +} + +int16_t RFM96::setFrequency(float freq) { + // check frequency range + if((freq < 433.0) || (freq > 470.0)) { + return(ERR_INVALID_FREQUENCY); + } + + // set frequency + return(SX127x::setFrequencyRaw(freq)); +} diff --git a/src/modules/RFM96.h b/src/modules/RFM96.h new file mode 100644 index 00000000..bb7653b8 --- /dev/null +++ b/src/modules/RFM96.h @@ -0,0 +1,29 @@ +#ifndef _KITELIB_RFM96_H +#define _KITELIB_RFM96_H + +#include "TypeDef.h" +#include "Module.h" +#include "SX127x.h" +#include "SX1278.h" + +// SX127X_REG_VERSION +#define RFM9X_CHIP_VERSION 0x12 // according to datasheet, this should be 0x11, but all modules seem to have 0x12 + +class RFM96: public SX1278 { + public: + // constructor + RFM96(Module* mod); + + // basic methods + int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0); + + // configuration methods + int16_t setFrequency(float freq); + + private: + +}; + +using RFM98 = RFM96; + +#endif diff --git a/src/modules/RFM97.cpp b/src/modules/RFM97.cpp new file mode 100644 index 00000000..8299d654 --- /dev/null +++ b/src/modules/RFM97.cpp @@ -0,0 +1,39 @@ +#include "RFM97.h" + +RFM97::RFM97(Module* mod) : RFM95(mod) { + +}; + +int16_t RFM97::setSpreadingFactor(uint8_t sf) { + // check active modem + if(getActiveModem() != SX127X_LORA) { + return(ERR_WRONG_MODEM); + } + + uint8_t newSpreadingFactor; + + // check allowed spreading factor values + switch(sf) { + case 6: + newSpreadingFactor = SX127X_SF_6; + break; + case 7: + newSpreadingFactor = SX127X_SF_7; + break; + case 8: + newSpreadingFactor = SX127X_SF_8; + break; + case 9: + newSpreadingFactor = SX127X_SF_9; + break; + default: + return(ERR_INVALID_SPREADING_FACTOR); + } + + // set spreading factor and if successful, save the new setting + int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor); + if(state == ERR_NONE) { + SX127x::_sf = sf; + } + return(state); +} diff --git a/src/modules/RFM97.h b/src/modules/RFM97.h new file mode 100644 index 00000000..196796a3 --- /dev/null +++ b/src/modules/RFM97.h @@ -0,0 +1,21 @@ +#ifndef _KITELIB_RFM97_H +#define _KITELIB_RFM97_H + +#include "TypeDef.h" +#include "Module.h" +#include "SX127x.h" +#include "SX1278.h" +#include "RFM95.h" + +class RFM97: public RFM95 { + public: + // contructor + RFM97(Module* mod); + + // configuration methods + int16_t setSpreadingFactor(uint8_t sf); + + private: +}; + +#endif diff --git a/src/modules/SX1272.cpp b/src/modules/SX1272.cpp index a89bbdc6..d19d580e 100644 --- a/src/modules/SX1272.cpp +++ b/src/modules/SX1272.cpp @@ -91,8 +91,12 @@ int16_t SX1272::setFrequency(float freq) { return(ERR_INVALID_FREQUENCY); } - // set frequency - return(SX127x::setFrequencyRaw(freq)); + // set frequency and if successful, save the new setting + int16_t state = SX127x::setFrequencyRaw(freq); + if(state == ERR_NONE) { + SX127x::_freq = freq; + } + return(state); } int16_t SX1272::setBandwidth(float bw) { @@ -253,6 +257,24 @@ int16_t SX1272::setGain(uint8_t gain) { return(state); } +int8_t SX1272::getRSSI() { + // check active modem + if(getActiveModem() != SX127X_LORA) { + return(0); + } + + int8_t lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE); + + // spread-spectrum modulation signal can be received below noise floor + // check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value + float lastPacketSNR = SX127x::getSNR(); + if(lastPacketSNR < 0.0) { + lastPacketRSSI += lastPacketSNR; + } + + return(lastPacketRSSI); +} + int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) { // set mode to standby int16_t state = SX127x::standby(); @@ -300,7 +322,7 @@ int16_t SX1272::config() { // calculate symbol length and set low datarate optimization, if needed uint16_t base = 1; float symbolLength = (float)(base << _sf) / (float)_bw; - if(symbolLength >= 0.016) { + if(symbolLength >= 16.0) { state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0); } else { state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0); diff --git a/src/modules/SX1272.h b/src/modules/SX1272.h index 011ee851..cbea544c 100644 --- a/src/modules/SX1272.h +++ b/src/modules/SX1272.h @@ -99,6 +99,7 @@ class SX1272: public SX127x { int16_t setCodingRate(uint8_t cr); int16_t setOutputPower(int8_t power); int16_t setGain(uint8_t gain); + int8_t getRSSI(); protected: int16_t setBandwidthRaw(uint8_t newBandwidth); diff --git a/src/modules/SX1278.cpp b/src/modules/SX1278.cpp index 2341c054..c4d63e34 100644 --- a/src/modules/SX1278.cpp +++ b/src/modules/SX1278.cpp @@ -147,8 +147,12 @@ int16_t SX1278::setFrequency(float freq) { } } - // set frequency - return(SX127x::setFrequencyRaw(freq)); + // set frequency and if successful, save the new setting + int16_t state = SX127x::setFrequencyRaw(freq); + if(state == ERR_NONE) { + SX127x::_freq = freq; + } + return(state); } int16_t SX1278::setBandwidth(float bw) { @@ -323,6 +327,31 @@ int16_t SX1278::setGain(uint8_t gain) { return(state); } +int8_t SX1278::getRSSI() { + // check active modem + if(getActiveModem() != SX127X_LORA) { + return(0); + } + + int8_t lastPacketRSSI; + + // RSSI calculation uses different constant for low-frequency and high-frequency ports + if(_freq < 868.0) { + lastPacketRSSI = -164 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE); + } else { + lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE); + } + + // spread-spectrum modulation signal can be received below noise floor + // check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value + float lastPacketSNR = SX127x::getSNR(); + if(lastPacketSNR < 0.0) { + lastPacketRSSI += lastPacketSNR; + } + + return(lastPacketRSSI); +} + int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) { // set mode to standby int16_t state = SX127x::standby(); @@ -370,7 +399,7 @@ int16_t SX1278::config() { // calculate symbol length and set low datarate optimization, if needed uint16_t base = 1; float symbolLength = (float)(base << _sf) / (float)_bw; - if(symbolLength >= 0.016) { + if(symbolLength >= 16.0) { state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 0, 0); } else { state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_OFF, 0, 0); diff --git a/src/modules/SX1278.h b/src/modules/SX1278.h index 184c981d..19ec13c7 100644 --- a/src/modules/SX1278.h +++ b/src/modules/SX1278.h @@ -108,6 +108,7 @@ class SX1278: public SX127x { int16_t setCodingRate(uint8_t cr); int16_t setOutputPower(int8_t power); int16_t setGain(uint8_t gain); + int8_t getRSSI(); protected: int16_t setBandwidthRaw(uint8_t newBandwidth); @@ -118,7 +119,7 @@ class SX1278: public SX127x { int16_t configFSK(); private: - + }; #endif diff --git a/src/modules/SX127x.cpp b/src/modules/SX127x.cpp index cbf2afcc..17547525 100644 --- a/src/modules/SX127x.cpp +++ b/src/modules/SX127x.cpp @@ -42,6 +42,9 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi // set preamble length state = SX127x::setPreambleLength(preambleLength); + // initalize internal variables + _dataRate = 0.0; + return(state); } @@ -128,14 +131,14 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) { uint16_t base = 1; float symbolLength = (float)(base << _sf) / (float)_bw; float de = 0; - if(symbolLength >= 0.016) { + if(symbolLength >= 16.0) { de = 1; } float ih = (float)_mod->SPIgetRegValue(SX127X_REG_MODEM_CONFIG_1, 0, 0); float crc = (float)(_mod->SPIgetRegValue(SX127X_REG_MODEM_CONFIG_2, 2, 2) >> 2); float n_pre = (float)_mod->SPIgetRegValue(SX127X_REG_PREAMBLE_LSB); float n_pay = 8.0 + max(ceil((8.0 * (float)len - 4.0 * (float)_sf + 28.0 + 16.0 * crc - 20.0 * ih)/(4.0 * (float)_sf - 8.0 * de)) * (float)_cr, 0.0); - uint32_t timeout = ceil(symbolLength * (n_pre + n_pay + 4.25) * 1000.0); + uint32_t timeout = ceil(symbolLength * (n_pre + n_pay + 4.25) * 1.5); // set DIO mapping _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_TX_DONE, 7, 6); @@ -170,7 +173,7 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) { uint32_t elapsed = millis() - start; // update data rate - dataRate = (len*8.0)/((float)elapsed/1000.0); + _dataRate = (len*8.0)/((float)elapsed/1000.0); // clear interrupt flags clearIRQFlags(); @@ -295,11 +298,6 @@ int16_t SX127x::receive(uint8_t* data, size_t len) { data[length] = 0; } - // update RSSI and SNR - lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE); - int8_t rawSNR = (int8_t)_mod->SPIgetRegValue(SX127X_REG_PKT_SNR_VALUE); - lastPacketSNR = rawSNR / 4.0; - // clear interrupt flags clearIRQFlags(); @@ -634,11 +632,6 @@ int16_t SX127x::readData(uint8_t* data, size_t len) { data[length] = 0; } - // update RSSI and SNR - lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE); - int8_t rawSNR = (int8_t)_mod->SPIgetRegValue(SX127X_REG_PKT_SNR_VALUE); - lastPacketSNR = rawSNR / 4.0; - // clear interrupt flags clearIRQFlags(); @@ -787,6 +780,26 @@ float SX127x::getFrequencyError(bool autoCorrect) { return(ERR_UNKNOWN); } +float SX127x::getSNR() { + // check active modem + if(getActiveModem() != SX127X_LORA) { + return(0); + } + + // get SNR value + int8_t rawSNR = (int8_t)_mod->SPIgetRegValue(SX127X_REG_PKT_SNR_VALUE); + return(rawSNR / 4.0); +} + +float SX127x::getDataRate() { + // check active modem + if(getActiveModem() != SX127X_LORA) { + return(0); + } + + return(_dataRate); +} + int16_t SX127x::setBitRate(float br) { // check active modem if(getActiveModem() != SX127X_FSK_OOK) { @@ -832,7 +845,7 @@ int16_t SX127x::setFrequencyDeviation(float freqDev) { return(state); } - // set frequency deviation from carrier frequency + // set allowed frequency deviation uint32_t base = 1; uint32_t FDEV = (freqDev * (base << 19)) / 32000; state = _mod->SPIsetRegValue(SX127X_REG_FDEV_MSB, (FDEV & 0xFF00) >> 8, 5, 0); @@ -1043,7 +1056,7 @@ int16_t SX127x::config() { int16_t SX127x::configFSK() { // set FSK modulation - int16_t state = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX127X_MODULATION_FSK, 6, 5); + int16_t state = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX127X_MODULATION_FSK, 6, 5, 5); if(state != ERR_NONE) { return(state); } @@ -1119,7 +1132,7 @@ bool SX127x::findChip(uint8_t ver) { } int16_t SX127x::setMode(uint8_t mode) { - return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, mode, 2, 0)); + return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, mode, 2, 0, 5)); } int16_t SX127x::getActiveModem() { @@ -1131,7 +1144,7 @@ int16_t SX127x::setActiveModem(uint8_t modem) { int16_t state = setMode(SX127X_SLEEP); // set LoRa mode - state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, modem, 7, 7); + state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, modem, 7, 7, 5); // set mode to STANDBY state |= setMode(SX127X_STANDBY); diff --git a/src/modules/SX127x.h b/src/modules/SX127x.h index 9d9ecfdb..f2bc6cd7 100644 --- a/src/modules/SX127x.h +++ b/src/modules/SX127x.h @@ -522,11 +522,6 @@ class SX127x: public PhysicalLayer { // constructor SX127x(Module* mod); - // public member variables - float dataRate; - int8_t lastPacketRSSI; - float lastPacketSNR; - // basic methods int16_t begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength); int16_t beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit); @@ -557,6 +552,8 @@ class SX127x: public PhysicalLayer { int16_t setCurrentLimit(uint8_t currentLimit); int16_t setPreambleLength(uint16_t preambleLength); float getFrequencyError(bool autoCorrect = false); + float getSNR(); + float getDataRate(); int16_t setBitRate(float br); int16_t setFrequencyDeviation(float freqDev); int16_t setRxBandwidth(float rxBw); @@ -572,6 +569,7 @@ class SX127x: public PhysicalLayer { protected: Module* _mod; + float _freq; float _bw; uint8_t _sf; uint8_t _cr; @@ -587,6 +585,8 @@ class SX127x: public PhysicalLayer { int16_t directMode(); private: + float _dataRate; + bool findChip(uint8_t ver); int16_t setMode(uint8_t mode); int16_t setActiveModem(uint8_t modem);