[SX127x] Sync with LoRaLib v7.0.0

This commit is contained in:
jgromes 2018-10-31 17:44:47 +01:00
parent ac2193ad72
commit 6cd42ca3e1
23 changed files with 416 additions and 140 deletions

View file

@ -7,12 +7,7 @@
if the LoRa channel is free, or if you should start if the LoRa channel is free, or if you should start
receiving a message. receiving a message.
Other modules from SX127x family can also be used. Other modules from SX127x/RFM9x 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;
*/ */
// include the library // include the library

View file

@ -11,12 +11,7 @@
- sync word - sync word
- preamble length - preamble length
Other modules from SX127x family can also be used. Other modules from SX127x/RFM9x 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;
*/ */
// include the library // include the library
@ -73,13 +68,13 @@ void loop() {
// print the RSSI (Received Signal Strength Indicator) // print the RSSI (Received Signal Strength Indicator)
// of the last received packet // of the last received packet
Serial.print("[SX1278] RSSI:\t\t"); Serial.print("[SX1278] RSSI:\t\t");
Serial.print(lora.lastPacketRSSI); Serial.print(lora.getRSSI());
Serial.println(" dBm"); Serial.println(" dBm");
// print the SNR (Signal-to-Noise Ratio) // print the SNR (Signal-to-Noise Ratio)
// of the last received packet // of the last received packet
Serial.print("[SX1278] SNR:\t\t"); Serial.print("[SX1278] SNR:\t\t");
Serial.print(lora.lastPacketSNR); Serial.print(lora.getSNR());
Serial.println(" dBm"); Serial.println(" dBm");
// print frequency error // print frequency error

View file

@ -12,12 +12,7 @@
- coding rate - coding rate
- sync word - sync word
Other modules from SX127x family can also be used. Other modules from SX127x/RFM9x 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;
*/ */
// include the library // include the library
@ -124,12 +119,12 @@ void loop() {
// print RSSI (Received Signal Strength Indicator) // print RSSI (Received Signal Strength Indicator)
Serial.print("RSSI:\t\t"); Serial.print("RSSI:\t\t");
Serial.print(lora.lastPacketRSSI); Serial.print(lora.getRSSI());
Serial.println(" dBm"); Serial.println(" dBm");
// print SNR (Signal-to-Noise Ratio) // print SNR (Signal-to-Noise Ratio)
Serial.print("SNR:\t\t"); Serial.print("SNR:\t\t");
Serial.print(lora.lastPacketSNR); Serial.print(lora.getSNR());
Serial.println(" dBm"); Serial.println(" dBm");
// print frequency error // print frequency error

View file

@ -10,6 +10,8 @@
- coding rate - coding rate
- sync word - sync word
- output power during transmission - output power during transmission
Other modules from SX127x/RFM9x family can also be used.
*/ */
// include the library // include the library
@ -18,18 +20,8 @@
// SX1278 module is in slot A on the shield // SX1278 module is in slot A on the shield
SX1278 loraSX1278 = Kite.ModuleA; SX1278 loraSX1278 = Kite.ModuleA;
// create another instance of LoRa class using SX1272 module and user-specified pinout // SX1272 module is in slot B on the shield
// NSS pin: 6 SX1272 loraSX1272 = Kite.ModuleB;
// 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);
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
@ -54,28 +46,7 @@ void setup() {
while (true); while (true);
} }
// initialize the second LoRa instance with non-default settings // initialize the second LoRa instance with
// 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
// non-default settings // non-default settings
// this LoRa link will have high data rate, // this LoRa link will have high data rate,
// but lower range // but lower range

View file

@ -7,12 +7,7 @@
- null-terminated char array (C-string) - null-terminated char array (C-string)
- arbitrary binary data (byte array) - arbitrary binary data (byte array)
Other modules from SX127x family can also be used. Other modules from SX127x/RFM9x 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;
*/ */
// include the library // include the library
@ -64,7 +59,7 @@ void loop() {
// print measured data rate // print measured data rate
Serial.print("Datarate:\t"); Serial.print("Datarate:\t");
Serial.print(lora.dataRate); Serial.print(lora.getDataRate());
Serial.println(" bps"); Serial.println(" bps");
} else if (state == ERR_PACKET_TOO_LONG) { } else if (state == ERR_PACKET_TOO_LONG) {

View file

@ -8,12 +8,7 @@
- null-terminated char array (C-string) - null-terminated char array (C-string)
- arbitrary binary data (byte array) - arbitrary binary data (byte array)
Other modules from SX127x family can also be used. Other modules from SX127x/RFM9x 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;
*/ */
// include the library // include the library
@ -98,6 +93,10 @@ void loop() {
0x78, 0xAB, 0xCD, 0xEF}; 0x78, 0xAB, 0xCD, 0xEF};
int state = lora.transmit(byteArr, 8); 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) { if (state != ERR_NONE) {
Serial.print(F("failed, code ")); Serial.print(F("failed, code "));

View file

@ -14,6 +14,10 @@ ESP8266 KEYWORD1
HC05 KEYWORD1 HC05 KEYWORD1
JDY08 KEYWORD1 JDY08 KEYWORD1
RF69 KEYWORD1 RF69 KEYWORD1
RFM95 KEYWORD1
RFM96 KEYWORD1
RFM97 KEYWORD1
RFM98 KEYWORD1
SX1231 KEYWORD1 SX1231 KEYWORD1
SX1272 KEYWORD1 SX1272 KEYWORD1
SX1273 KEYWORD1 SX1273 KEYWORD1
@ -37,34 +41,43 @@ ModuleA KEYWORD2
ModuleB KEYWORD2 ModuleB KEYWORD2
Module KEYWORD2 Module KEYWORD2
# SX1272/73/76/77/78/79 + RF69 # SX127x/RFM9x + RF69
dataRate KEYWORD2
lastPacketRSSI KEYWORD2
begin KEYWORD2 begin KEYWORD2
beginFSK KEYWORD2
transmit KEYWORD2 transmit KEYWORD2
receive KEYWORD2 receive KEYWORD2
scanChannel KEYWORD2
sleep KEYWORD2 sleep KEYWORD2
standby KEYWORD2 standby KEYWORD2
transmitDirect KEYWORD2
receiveDirect KEYWORD2
packetMode KEYWORD2
setDio0Action KEYWORD2
setDio1Action KEYWORD2
startTransmit KEYWORD2
startReceive KEYWORD2
readData KEYWORD2
setBandwidth KEYWORD2 setBandwidth KEYWORD2
setSpreadingFactor KEYWORD2 setSpreadingFactor KEYWORD2
setCodingRate KEYWORD2 setCodingRate KEYWORD2
setFrequency KEYWORD2 setFrequency KEYWORD2
setSyncWord KEYWORD2 setSyncWord KEYWORD2
setOutputPower KEYWORD2 setOutputPower KEYWORD2
listen KEYWORD2 setCurrentLimit KEYWORD2
onReceive KEYWORD2 setPreambleLength KEYWORD2
readData KEYWORD2 setGain KEYWORD2
transmitDirect KEYWORD2 getFrequencyError KEYWORD2
receiveDirect KEYWORD2 getRSSI KEYWORD2
packetMode KEYWORD2 getSNR KEYWORD2
getDataRate KEYWORD2
# RF69-specific
setBitRate KEYWORD2 setBitRate KEYWORD2
setRxBandwidth KEYWORD2 setRxBandwidth KEYWORD2
setFrequencyDeviation KEYWORD2 setFrequencyDeviation KEYWORD2
setNodeAddress KEYWORD2 setNodeAddress KEYWORD2
setBroadcastAddress KEYWORD2 setBroadcastAddress KEYWORD2
disableAddressFiltering KEYWORD2 disableAddressFiltering KEYWORD2
# RF69-specific
setAESKey KEYWORD2 setAESKey KEYWORD2
enableAES KEYWORD2 enableAES KEYWORD2
disableAES KEYWORD2 disableAES KEYWORD2

View file

@ -8,6 +8,10 @@
#include "modules/HC05.h" #include "modules/HC05.h"
#include "modules/JDY08.h" #include "modules/JDY08.h"
#include "modules/RF69.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/SX1231.h"
#include "modules/SX1272.h" #include "modules/SX1272.h"
#include "modules/SX1273.h" #include "modules/SX1273.h"

View file

@ -107,7 +107,7 @@ int16_t Module::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
return(maskedValue); 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)) { if((msb > 7) || (lsb > 7) || (lsb > msb)) {
return(ERR_INVALID_BIT_RANGE); 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); uint8_t newValue = (currentValue & ~mask) | (value & mask);
SPIwriteRegister(reg, newValue); SPIwriteRegister(reg, newValue);
// some registers need a bit of time to process the change // check register value each millisecond until check interval is reached
// e.g. SX127X_REG_OP_MODE // some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE)
delay(20); uint32_t start = micros();
uint8_t readValue = 0;
// check if the write was successful while(micros() - start < (checkInterval * 1000)) {
uint8_t readValue = SPIreadRegister(reg); readValue = SPIreadRegister(reg);
if(readValue != newValue) { if(readValue == newValue) {
DEBUG_PRINTLN(); // check passed, we can stop the loop
DEBUG_PRINT_STR("address:\t0x"); return(ERR_NONE);
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);
} }
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) { void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {

View file

@ -28,7 +28,7 @@ class Module {
bool ATsendData(uint8_t* data, uint32_t len); bool ATsendData(uint8_t* data, uint32_t len);
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0); 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); void SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
uint8_t SPIreadRegister(uint8_t reg); uint8_t SPIreadRegister(uint8_t reg);

View file

@ -60,7 +60,7 @@
#define ERR_NONE 0 #define ERR_NONE 0
#define ERR_UNKNOWN -1 #define ERR_UNKNOWN -1
// SX1278/SX1272/RF69 status codes // SX127x/RFM9x/RF69 status codes
#define ERR_CHIP_NOT_FOUND -2 #define ERR_CHIP_NOT_FOUND -2
#define ERR_EEPROM_NOT_INITIALIZED -3 #define ERR_EEPROM_NOT_INITIALIZED -3
#define ERR_PACKET_TOO_LONG -4 #define ERR_PACKET_TOO_LONG -4

62
src/modules/RFM95.cpp Normal file
View file

@ -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));
}

27
src/modules/RFM95.h Normal file
View file

@ -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

62
src/modules/RFM96.cpp Normal file
View file

@ -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));
}

29
src/modules/RFM96.h Normal file
View file

@ -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

39
src/modules/RFM97.cpp Normal file
View file

@ -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);
}

21
src/modules/RFM97.h Normal file
View file

@ -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

View file

@ -91,8 +91,12 @@ int16_t SX1272::setFrequency(float freq) {
return(ERR_INVALID_FREQUENCY); return(ERR_INVALID_FREQUENCY);
} }
// set frequency // set frequency and if successful, save the new setting
return(SX127x::setFrequencyRaw(freq)); int16_t state = SX127x::setFrequencyRaw(freq);
if(state == ERR_NONE) {
SX127x::_freq = freq;
}
return(state);
} }
int16_t SX1272::setBandwidth(float bw) { int16_t SX1272::setBandwidth(float bw) {
@ -253,6 +257,24 @@ int16_t SX1272::setGain(uint8_t gain) {
return(state); 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) { int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) {
// set mode to standby // set mode to standby
int16_t state = SX127x::standby(); int16_t state = SX127x::standby();
@ -300,7 +322,7 @@ int16_t SX1272::config() {
// calculate symbol length and set low datarate optimization, if needed // calculate symbol length and set low datarate optimization, if needed
uint16_t base = 1; uint16_t base = 1;
float symbolLength = (float)(base << _sf) / (float)_bw; 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); state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else { } else {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0); state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0);

View file

@ -99,6 +99,7 @@ class SX1272: public SX127x {
int16_t setCodingRate(uint8_t cr); int16_t setCodingRate(uint8_t cr);
int16_t setOutputPower(int8_t power); int16_t setOutputPower(int8_t power);
int16_t setGain(uint8_t gain); int16_t setGain(uint8_t gain);
int8_t getRSSI();
protected: protected:
int16_t setBandwidthRaw(uint8_t newBandwidth); int16_t setBandwidthRaw(uint8_t newBandwidth);

View file

@ -147,8 +147,12 @@ int16_t SX1278::setFrequency(float freq) {
} }
} }
// set frequency // set frequency and if successful, save the new setting
return(SX127x::setFrequencyRaw(freq)); int16_t state = SX127x::setFrequencyRaw(freq);
if(state == ERR_NONE) {
SX127x::_freq = freq;
}
return(state);
} }
int16_t SX1278::setBandwidth(float bw) { int16_t SX1278::setBandwidth(float bw) {
@ -323,6 +327,31 @@ int16_t SX1278::setGain(uint8_t gain) {
return(state); 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) { int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) {
// set mode to standby // set mode to standby
int16_t state = SX127x::standby(); int16_t state = SX127x::standby();
@ -370,7 +399,7 @@ int16_t SX1278::config() {
// calculate symbol length and set low datarate optimization, if needed // calculate symbol length and set low datarate optimization, if needed
uint16_t base = 1; uint16_t base = 1;
float symbolLength = (float)(base << _sf) / (float)_bw; 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); state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 0, 0);
} else { } else {
state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_OFF, 0, 0); state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_OFF, 0, 0);

View file

@ -108,6 +108,7 @@ class SX1278: public SX127x {
int16_t setCodingRate(uint8_t cr); int16_t setCodingRate(uint8_t cr);
int16_t setOutputPower(int8_t power); int16_t setOutputPower(int8_t power);
int16_t setGain(uint8_t gain); int16_t setGain(uint8_t gain);
int8_t getRSSI();
protected: protected:
int16_t setBandwidthRaw(uint8_t newBandwidth); int16_t setBandwidthRaw(uint8_t newBandwidth);
@ -118,7 +119,7 @@ class SX1278: public SX127x {
int16_t configFSK(); int16_t configFSK();
private: private:
}; };
#endif #endif

View file

@ -42,6 +42,9 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
// set preamble length // set preamble length
state = SX127x::setPreambleLength(preambleLength); state = SX127x::setPreambleLength(preambleLength);
// initalize internal variables
_dataRate = 0.0;
return(state); return(state);
} }
@ -128,14 +131,14 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
uint16_t base = 1; uint16_t base = 1;
float symbolLength = (float)(base << _sf) / (float)_bw; float symbolLength = (float)(base << _sf) / (float)_bw;
float de = 0; float de = 0;
if(symbolLength >= 0.016) { if(symbolLength >= 16.0) {
de = 1; de = 1;
} }
float ih = (float)_mod->SPIgetRegValue(SX127X_REG_MODEM_CONFIG_1, 0, 0); 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 crc = (float)(_mod->SPIgetRegValue(SX127X_REG_MODEM_CONFIG_2, 2, 2) >> 2);
float n_pre = (float)_mod->SPIgetRegValue(SX127X_REG_PREAMBLE_LSB); 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); 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 // set DIO mapping
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_TX_DONE, 7, 6); _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; uint32_t elapsed = millis() - start;
// update data rate // update data rate
dataRate = (len*8.0)/((float)elapsed/1000.0); _dataRate = (len*8.0)/((float)elapsed/1000.0);
// clear interrupt flags // clear interrupt flags
clearIRQFlags(); clearIRQFlags();
@ -295,11 +298,6 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
data[length] = 0; 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 // clear interrupt flags
clearIRQFlags(); clearIRQFlags();
@ -634,11 +632,6 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
data[length] = 0; 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 // clear interrupt flags
clearIRQFlags(); clearIRQFlags();
@ -787,6 +780,26 @@ float SX127x::getFrequencyError(bool autoCorrect) {
return(ERR_UNKNOWN); 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) { int16_t SX127x::setBitRate(float br) {
// check active modem // check active modem
if(getActiveModem() != SX127X_FSK_OOK) { if(getActiveModem() != SX127X_FSK_OOK) {
@ -832,7 +845,7 @@ int16_t SX127x::setFrequencyDeviation(float freqDev) {
return(state); return(state);
} }
// set frequency deviation from carrier frequency // set allowed frequency deviation
uint32_t base = 1; uint32_t base = 1;
uint32_t FDEV = (freqDev * (base << 19)) / 32000; uint32_t FDEV = (freqDev * (base << 19)) / 32000;
state = _mod->SPIsetRegValue(SX127X_REG_FDEV_MSB, (FDEV & 0xFF00) >> 8, 5, 0); state = _mod->SPIsetRegValue(SX127X_REG_FDEV_MSB, (FDEV & 0xFF00) >> 8, 5, 0);
@ -1043,7 +1056,7 @@ int16_t SX127x::config() {
int16_t SX127x::configFSK() { int16_t SX127x::configFSK() {
// set FSK modulation // 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) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -1119,7 +1132,7 @@ bool SX127x::findChip(uint8_t ver) {
} }
int16_t SX127x::setMode(uint8_t mode) { 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() { int16_t SX127x::getActiveModem() {
@ -1131,7 +1144,7 @@ int16_t SX127x::setActiveModem(uint8_t modem) {
int16_t state = setMode(SX127X_SLEEP); int16_t state = setMode(SX127X_SLEEP);
// set LoRa mode // 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 // set mode to STANDBY
state |= setMode(SX127X_STANDBY); state |= setMode(SX127X_STANDBY);

View file

@ -522,11 +522,6 @@ class SX127x: public PhysicalLayer {
// constructor // constructor
SX127x(Module* mod); SX127x(Module* mod);
// public member variables
float dataRate;
int8_t lastPacketRSSI;
float lastPacketSNR;
// basic methods // basic methods
int16_t begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength); 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); 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 setCurrentLimit(uint8_t currentLimit);
int16_t setPreambleLength(uint16_t preambleLength); int16_t setPreambleLength(uint16_t preambleLength);
float getFrequencyError(bool autoCorrect = false); float getFrequencyError(bool autoCorrect = false);
float getSNR();
float getDataRate();
int16_t setBitRate(float br); int16_t setBitRate(float br);
int16_t setFrequencyDeviation(float freqDev); int16_t setFrequencyDeviation(float freqDev);
int16_t setRxBandwidth(float rxBw); int16_t setRxBandwidth(float rxBw);
@ -572,6 +569,7 @@ class SX127x: public PhysicalLayer {
protected: protected:
Module* _mod; Module* _mod;
float _freq;
float _bw; float _bw;
uint8_t _sf; uint8_t _sf;
uint8_t _cr; uint8_t _cr;
@ -587,6 +585,8 @@ class SX127x: public PhysicalLayer {
int16_t directMode(); int16_t directMode();
private: private:
float _dataRate;
bool findChip(uint8_t ver); bool findChip(uint8_t ver);
int16_t setMode(uint8_t mode); int16_t setMode(uint8_t mode);
int16_t setActiveModem(uint8_t modem); int16_t setActiveModem(uint8_t modem);