Added support for all Semtech LoRa modules (SX1272/73/76/77/78/79)

This commit is contained in:
Jan Gromeš 2018-07-03 09:58:29 +02:00
parent c2b1826410
commit 8d8ab76f5a
20 changed files with 1272 additions and 1139 deletions

View file

@ -14,7 +14,11 @@ ESP8266 KEYWORD1
HC05 KEYWORD1 HC05 KEYWORD1
RF69 KEYWORD1 RF69 KEYWORD1
SX1272 KEYWORD1 SX1272 KEYWORD1
SX1273 KEYWORD1
SX1276 KEYWORD1
SX1277 KEYWORD1
SX1278 KEYWORD1 SX1278 KEYWORD1
SX1279 KEYWORD1
XBee KEYWORD1 XBee KEYWORD1
Bandwidth KEYWORD1 Bandwidth KEYWORD1
@ -39,8 +43,9 @@ getDestinationStr KEYWORD2
setSourceStr KEYWORD2 setSourceStr KEYWORD2
setDestinationStr KEYWORD2 setDestinationStr KEYWORD2
copyInto KEYWORD2 copyInto KEYWORD2
setPacketData KEYWORD2
# SX1278/SX1272 + RF69 # SX1272/73/76/77/78/79 + RF69
dataRate KEYWORD2 dataRate KEYWORD2
lastPacketRSSI KEYWORD2 lastPacketRSSI KEYWORD2
begin KEYWORD2 begin KEYWORD2
@ -51,6 +56,9 @@ standby KEYWORD2
setBandwidth KEYWORD2 setBandwidth KEYWORD2
setSpreadingFactor KEYWORD2 setSpreadingFactor KEYWORD2
setCodingRate KEYWORD2 setCodingRate KEYWORD2
setFrequency KEYWORD2
setSyncWord KEYWORD2
setOutputPower KEYWORD2
# ESP8266 # ESP8266
join KEYWORD2 join KEYWORD2
@ -74,31 +82,9 @@ setPanId KEYWORD2
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
BW_7_80_KHZ LITERAL1
BW_10_40_KHZ LITERAL1
BW_15_60_KHZ LITERAL1
BW_20_80_KHZ LITERAL1
BW_31_25_KHZ LITERAL1
BW_41_70_KHZ LITERAL1
BW_62_50_KHZ LITERAL1
BW_125_00_KHZ LITERAL1
BW_250_00_KHZ LITERAL1
BW_500_00_KHZ LITERAL1
SF_6 LITERAL1
SF_7 LITERAL1
SF_8 LITERAL1
SF_9 LITERAL1
SF_10 LITERAL1
SF_11 LITERAL1
SF_12 LITERAL1
CR_4_5 LITERAL1
CR_4_6 LITERAL1
CR_4_7 LITERAL1
CR_4_8 LITERAL1
ERR_NONE LITERAL1 ERR_NONE LITERAL1
ERR_UNKNOWN LITERAL1
ERR_CHIP_NOT_FOUND LITERAL1 ERR_CHIP_NOT_FOUND LITERAL1
ERR_EEPROM_NOT_INITIALIZED LITERAL1 ERR_EEPROM_NOT_INITIALIZED LITERAL1
ERR_PACKET_TOO_LONG LITERAL1 ERR_PACKET_TOO_LONG LITERAL1
@ -109,10 +95,19 @@ ERR_INVALID_BANDWIDTH LITERAL1
ERR_INVALID_SPREADING_FACTOR LITERAL1 ERR_INVALID_SPREADING_FACTOR LITERAL1
ERR_INVALID_CODING_RATE LITERAL1 ERR_INVALID_CODING_RATE LITERAL1
ERR_INVALID_BIT_RANGE LITERAL1 ERR_INVALID_BIT_RANGE LITERAL1
ERR_INVALID_FREQUENCY LITERAL1
ERR_INVALID_OUTPUT_POWER LITERAL1
PREAMBLE_DETECTED LITERAL1
CHANNEL_FREE LITERAL1
ERR_AT_FAILED LITERAL1 ERR_AT_FAILED LITERAL1
ERR_URL_MALFORMED LITERAL1 ERR_URL_MALFORMED LITERAL1
ERR_RESPONSE_MALFORMED_AT LITERAL1 ERR_RESPONSE_MALFORMED_AT LITERAL1
ERR_RESPONSE_MALFORMED LITERAL1 ERR_RESPONSE_MALFORMED LITERAL1
ERR_MQTT_CONN_VERSION_REJECTED LITERAL1
ERR_MQTT_CONN_ID_REJECTED LITERAL1
ERR_MQTT_CONN_SERVER_UNAVAILABLE LITERAL1
ERR_MQTT_CONN_BAD_USERNAME_PASSWORD LITERAL1
ERR_MQTT_CONN_NOT_AUTHORIZED LITERAL1
ERR_CMD_MODE_FAILED LITERAL1 ERR_CMD_MODE_FAILED LITERAL1

View file

@ -8,7 +8,11 @@
#include "modules/HC05.h" #include "modules/HC05.h"
#include "modules/RF69.h" #include "modules/RF69.h"
#include "modules/SX1272.h" #include "modules/SX1272.h"
#include "modules/SX1273.h"
#include "modules/SX1276.h"
#include "modules/SX1277.h"
#include "modules/SX1278.h" #include "modules/SX1278.h"
#include "modules/SX1279.h"
#include "modules/XBee.h" #include "modules/XBee.h"
#define KITE_CS_A 10 #define KITE_CS_A 10

View file

@ -136,8 +136,9 @@ uint8_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
} }
uint8_t currentValue = SPIreadRegister(reg); uint8_t currentValue = SPIreadRegister(reg);
uint8_t newValue = currentValue & ((0b11111111 << (msb + 1)) & (0b11111111 >> (8 - lsb))); uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb)));
SPIwriteRegister(reg, newValue | value); uint8_t newValue = (currentValue & ~mask) | (value & mask);
SPIwriteRegister(reg, newValue);
return(ERR_NONE); return(ERR_NONE);
} }

View file

@ -5,174 +5,177 @@ Packet::Packet(void) {
getLoRaAddress(src); getLoRaAddress(src);
uint8_t dest[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t dest[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t dat[240]; uint8_t* dat;
uint8_t len = 0; uint8_t len = 0;
init(src, dest, dat, len); init(src, dest, dat, len);
} }
Packet::Packet(const char dest[24], const char dat[240]) { Packet::Packet(const char* dest, const char* dat) {
uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0};
getLoRaAddress(src); getLoRaAddress(src);
uint8_t destTmp[8]; uint8_t destTmp[8];
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
destTmp[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]); char str[] = {dest[3*i], dest[3*i + 1]};
destTmp[i] = strtoul(str, NULL, 16);
} }
init(src, destTmp, dat); init(src, destTmp, dat);
} }
Packet::Packet(uint8_t dest[8], const char dat[240]) { Packet::Packet(uint8_t* dest, const char* dat) {
uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0};
getLoRaAddress(src); getLoRaAddress(src);
init(src, dest, dat); init(src, dest, dat);
} }
Packet::Packet(const char src[24], const char dest[24], const char dat[240]) { Packet::Packet(const char* src, const char* dest, const char* dat) {
uint8_t srcTmp[8]; uint8_t srcTmp[8];
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
srcTmp[i] = (parseByte(src[3*i]) << 4) | parseByte(src[3*i + 1]); char str[] = {src[3*i], src[3*i + 1]};
srcTmp[i] = strtoul(str, NULL, 16);
} }
uint8_t destTmp[8]; uint8_t destTmp[8];
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
destTmp[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]); char str[] = {dest[3*i], dest[3*i + 1]};
destTmp[i] = strtoul(str, NULL, 16);
} }
init(srcTmp, destTmp, dat); init(srcTmp, destTmp, dat);
} }
Packet::Packet(uint8_t src[8], uint8_t dest[8], const char dat[240]) { Packet::Packet(uint8_t* src, uint8_t* dest, const char* dat) {
init(src, dest, dat); init(src, dest, dat);
} }
Packet::Packet(const char dest[24], uint8_t* dat, uint8_t len) { Packet::Packet(const char* dest, uint8_t* dat, uint8_t len) {
uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0};
getLoRaAddress(src); getLoRaAddress(src);
uint8_t destTmp[8]; uint8_t destTmp[8];
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
destTmp[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]); char str[] = {dest[3*i], dest[3*i + 1]};
destTmp[i] = strtoul(str, NULL, 16);
} }
init(src, destTmp, dat, len); init(src, destTmp, dat, len);
} }
Packet::Packet(uint8_t dest[8], uint8_t* dat, uint8_t len) { Packet::Packet(uint8_t* dest, uint8_t* dat, uint8_t len) {
uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0};
getLoRaAddress(src); getLoRaAddress(src);
init(src, dest, dat, len); init(src, dest, dat, len);
} }
Packet::Packet(const char src[24], const char dest[24], uint8_t* dat, uint8_t len) { Packet::Packet(const char* src, const char* dest, uint8_t* dat, uint8_t len) {
uint8_t srcTmp[8]; uint8_t srcTmp[8];
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
srcTmp[i] = (parseByte(src[3*i]) << 4) | parseByte(src[3*i + 1]); char str[] = {src[3*i], src[3*i + 1]};
srcTmp[i] = strtoul(str, NULL, 16);
} }
uint8_t destTmp[8]; uint8_t destTmp[8];
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
destTmp[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]); char str[] = {dest[3*i], dest[3*i + 1]};
destTmp[i] = strtoul(str, NULL, 16);
} }
init(srcTmp, destTmp, dat, len); init(srcTmp, destTmp, dat, len);
} }
Packet::Packet(uint8_t src[8], uint8_t dest[8], uint8_t* dat, uint8_t len) { Packet::Packet(uint8_t* src, uint8_t* dest, uint8_t* dat, uint8_t len) {
init(src, dest, dat, len); init(src, dest, dat, len);
} }
void Packet::init(uint8_t src[8], uint8_t dest[8], const char dat[240]) { void Packet::init(uint8_t* src, uint8_t* dest, const char* dat) {
for(uint8_t i = 0; i < 8; i++) { init(src, dest, (uint8_t*)dat, strlen(dat));
source[i] = src[i];
destination[i] = dest[i];
}
length = 0;
for(uint8_t i = 0; i < 240; i++) {
data[i] = dat[i];
if(data[i] == '\0') {
length = i + 16;
break;
}
}
} }
void Packet::init(uint8_t src[8], uint8_t dest[8], uint8_t* dat, uint8_t len) { void Packet::init(uint8_t* src, uint8_t* dest, uint8_t* dat, uint8_t len) {
memcpy(source, src, 8);
memcpy(destination, dest, 8);
length = len + 16; length = len + 16;
for(uint8_t i = 0; i < 8; i++) { data = new char[len + 1];
source[i] = src[i]; memcpy(data, dat, len + 1);
destination[i] = dest[i]; }
}
for(uint8_t i = 0; i < length; i++) { String Packet::getSourceStr() {
data[i] = dat[i]; char charArray[24];
for(uint8_t i = 0; i < 8; i++) {
sprintf(charArray + 3*i, "%02X", source[i]);
charArray[3*i+2] = ':';
}
charArray[23] = '\0';
String str(charArray);
return(str);
}
String Packet::getDestinationStr() {
char charArray[24];
for(uint8_t i = 0; i < 8; i++) {
sprintf(charArray + 3*i, "%02X", destination[i]);
charArray[3*i+2] = ':';
}
charArray[23] = '\0';
String str(charArray);
return(str);
}
void Packet::setSourceStr(const char* src) {
for(uint8_t i = 0; i < 8; i++) {
char str[] = {src[3*i], src[3*i + 1]};
source[i] = strtoul(str, NULL, 16);
} }
} }
void Packet::getSourceStr(char src[24]) { void Packet::setDestinationStr(const char* dest) {
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
src[3*i] = reparseChar(source[i] >> 4); char str[] = {dest[3*i], dest[3*i + 1]};
src[3*i+1] = reparseChar(source[i] & 0x0F); destination[i] = strtoul(str, NULL, 16);
src[3*i+2] = ':';
}
src[23] = '\0';
}
void Packet::getDestinationStr(char dest[24]) {
for(uint8_t i = 0; i < 8; i++) {
dest[3*i] = reparseChar(destination[i] >> 4);
dest[3*i+1] = reparseChar(destination[i] & 0x0F);
dest[3*i+2] = ':';
}
dest[23] = '\0';
}
void Packet::setSourceStr(const char src[24]) {
for(uint8_t i = 0; i < 8; i++) {
source[i] = (parseByte(src[3*i]) << 4) | parseByte(src[3*i + 1]);
}
}
void Packet::setDestinationStr(const char dest[24]) {
for(uint8_t i = 0; i < 8; i++) {
destination[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]);
} }
} }
void Packet::copyInto(Packet& pack) { void Packet::copyInto(Packet& pack) {
for(uint8_t i = 0; i < 8; i++) { memcpy(pack.source, source, 8);
pack.source[i] = source[i]; memcpy(pack.destination, destination, 8);
pack.destination[i] = destination[i];
}
strcpy(pack.data, data); strcpy(pack.data, data);
} }
void Packet::getLoRaAddress(uint8_t addr[8]) { void Packet::setPacketData(char* charArray) {
char* newData = new char[strlen(charArray)];
length = strlen(charArray) + 16;
strcpy(newData, charArray);
delete[] data;
data = newData;
}
void Packet::setPacketData(String str) {
setPacketData((char*)str.c_str());
}
void Packet::setPacketData(float f, uint8_t decimals) {
int i = f;
float res = f - i;
if (res == 0) {
char charArray[16];
itoa(i, charArray, 10);
setPacketData(charArray);
} else {
String floatString = String(f, decimals);
setPacketData(floatString);
}
}
void Packet::getLoRaAddress(uint8_t* addr) {
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
addr[i] = EEPROM.read(i); addr[i] = EEPROM.read(i);
} }
} }
uint8_t Packet::parseByte(char c) {
if((c >= 48) && (c <= 57)) {
return(c - 48);
} else if((c >= 65) && (c <= 70)) {
return(c - 55);
} else if((c >= 97) && (c <= 102)) {
return(c - 87);
}
return(0);
}
char Packet::reparseChar(uint8_t b) {
if(b <= 9) {
return(b + 48);
} else if((b >= 10) && (b <= 16)) {
return(b + 55);
}
return(0);
}

View file

@ -1,5 +1,5 @@
#ifndef _LORALIB_PACKET_H #ifndef _KITELIB_PACKET_H
#define _LORALIB_PACKET_H #define _KITELIB_PACKET_H
#if ARDUINO >= 100 #if ARDUINO >= 100
#include "Arduino.h" #include "Arduino.h"
@ -12,36 +12,37 @@
class Packet { class Packet {
public: public:
Packet(void); Packet(void);
Packet(const char dest[24], const char dat[240]); Packet(const char* dest, const char* dat);
Packet(uint8_t dest[8], const char dat[240]); Packet(uint8_t* dest, const char* dat);
Packet(const char src[24], const char dest[24], const char dat[240]); Packet(const char* src, const char* dest, const char* dat);
Packet(uint8_t src[8], uint8_t dest[8], const char dat[240]); Packet(uint8_t* src, uint8_t* dest, const char* dat);
Packet(const char dest[24], uint8_t* dat, uint8_t len); Packet(const char* dest, uint8_t* dat, uint8_t len);
Packet(uint8_t dest[8], uint8_t* dat, uint8_t len); Packet(uint8_t* dest, uint8_t* dat, uint8_t len);
Packet(const char src[24], const char dest[24], uint8_t* dat, uint8_t len); Packet(const char* src, const char* dest, uint8_t* dat, uint8_t len);
Packet(uint8_t src[8], uint8_t dest[8], uint8_t* dat, uint8_t len); Packet(uint8_t* src, uint8_t* dest, uint8_t* dat, uint8_t len);
uint8_t source[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t source[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t destination[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t destination[8] = {0, 0, 0, 0, 0, 0, 0, 0};
char data[240]; char* data;
uint8_t length = 0; uint8_t length = 0;
void getSourceStr(char src[24]); String getSourceStr();
void getDestinationStr(char dest[24]); String getDestinationStr();
void setSourceStr(const char src[24]); void setSourceStr(const char* src);
void setDestinationStr(const char dest[24]); void setDestinationStr(const char* dest);
void copyInto(Packet& pack); void copyInto(Packet& pack);
private: void setPacketData(char* charArray);
void init(uint8_t src[8], uint8_t dest[8], const char dat[240]); void setPacketData(String str);
void init(uint8_t src[8], uint8_t dest[8], uint8_t* dat, uint8_t len); void setPacketData(float f, uint8_t decimals = 3);
void getLoRaAddress(uint8_t addr[8]);
uint8_t parseByte(char c); private:
char reparseChar(uint8_t b); void init(uint8_t* src, uint8_t* dest, const char* dat);
void init(uint8_t* src, uint8_t* dest, uint8_t* dat, uint8_t len);
void getLoRaAddress(uint8_t* addr);
}; };
#endif #endif

View file

@ -7,9 +7,9 @@
#include "WProgram.h" #include "WProgram.h"
#endif #endif
//#define DEBUG //#define KITELIB_DEBUG
/*#ifdef DEBUG #ifdef KITELIB_DEBUG
#define DEBUG_BEGIN(x) Serial.begin (x) #define DEBUG_BEGIN(x) Serial.begin (x)
#define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINT(x) Serial.print (x)
#define DEBUG_PRINT_DEC(x) Serial.print (x, DEC) #define DEBUG_PRINT_DEC(x) Serial.print (x, DEC)
@ -17,7 +17,7 @@
#define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINTLN(x) Serial.println (x)
#define DEBUG_PRINT_STR(x) Serial.print (F(x)) #define DEBUG_PRINT_STR(x) Serial.print (F(x))
#define DEBUG_PRINTLN_STR(x) Serial.println (F(x)) #define DEBUG_PRINTLN_STR(x) Serial.println (F(x))
#else*/ #else
#define DEBUG_BEGIN(x) #define DEBUG_BEGIN(x)
#define DEBUG_PRINT(x) #define DEBUG_PRINT(x)
#define DEBUG_PRINT_DEC(x) #define DEBUG_PRINT_DEC(x)
@ -25,58 +25,62 @@
#define DEBUG_PRINTLN(x) #define DEBUG_PRINTLN(x)
#define DEBUG_PRINT_STR(x) #define DEBUG_PRINT_STR(x)
#define DEBUG_PRINTLN_STR(x) #define DEBUG_PRINTLN_STR(x)
//#endif #endif
// Shield configuration // Shield configuration
#define USE_SPI 0x00 #define USE_SPI 0x00
#define USE_UART 0x01 #define USE_UART 0x01
#define USE_I2C 0x02 #define USE_I2C 0x02
#define INT_NONE 0x00 #define INT_NONE 0x00
#define INT_0 0x01 #define INT_0 0x01
#define INT_1 0x02 #define INT_1 0x02
#define INT_BOTH 0x03 #define INT_BOTH 0x03
// UART configuration // UART configuration
#define UART_STOPBIT_1 0x01 #define UART_STOPBIT_1 0x01
#define UART_STOPBIT_1_5 0x02 #define UART_STOPBIT_1_5 0x02
#define UART_STOPBIT_2 0x03 #define UART_STOPBIT_2 0x03
#define UART_PARITY_NONE 0x00 #define UART_PARITY_NONE 0x00
#define UART_PARITY_ODD 0x01 #define UART_PARITY_ODD 0x01
#define UART_PARITY_EVEN 0x02 #define UART_PARITY_EVEN 0x02
#define UART_FLOW_NONE 0x00 #define UART_FLOW_NONE 0x00
#define UART_FLOW_RTS 0x01 #define UART_FLOW_RTS 0x01
#define UART_FLOW_CTS 0x02 #define UART_FLOW_CTS 0x02
#define UART_FLOW_BOTH 0x03 #define UART_FLOW_BOTH 0x03
// Common error codes // Common status codes
#define ERR_NONE 0x00 #define ERR_NONE 0x00
#define ERR_UNKNOWN 0x63 // maximum error code value is 99, so that it does not interfere with HTTP status codes #define ERR_UNKNOWN 0x63 // maximum status code value is 99 DEC, so that it does not interfere with HTTP status codes
// SX1278/SX1272/RF69 error codes // SX1278/SX1272/RF69 status codes
#define ERR_CHIP_NOT_FOUND 0x01 #define ERR_CHIP_NOT_FOUND 0x01
#define ERR_EEPROM_NOT_INITIALIZED 0x02 #define ERR_EEPROM_NOT_INITIALIZED 0x02
#define ERR_PACKET_TOO_LONG 0x03 #define ERR_PACKET_TOO_LONG 0x03
#define ERR_TX_TIMEOUT 0x04 #define ERR_TX_TIMEOUT 0x04
#define ERR_RX_TIMEOUT 0x05 #define ERR_RX_TIMEOUT 0x05
#define ERR_CRC_MISMATCH 0x06 #define ERR_CRC_MISMATCH 0x06
#define ERR_INVALID_BANDWIDTH 0x07 #define ERR_INVALID_BANDWIDTH 0x07
#define ERR_INVALID_SPREADING_FACTOR 0x08 #define ERR_INVALID_SPREADING_FACTOR 0x08
#define ERR_INVALID_CODING_RATE 0x09 #define ERR_INVALID_CODING_RATE 0x09
#define ERR_INVALID_BIT_RANGE 0x10 #define ERR_INVALID_BIT_RANGE 0x0A
#define ERR_INVALID_FREQUENCY 0x0B
#define ERR_INVALID_OUTPUT_POWER 0x0C
#define PREAMBLE_DETECTED 0x0D
#define CHANNEL_FREE 0x0E
// ESP8266 error codes // ESP8266 status codes
#define ERR_AT_FAILED 0x01 #define ERR_AT_FAILED 0x01
#define ERR_URL_MALFORMED 0x02 #define ERR_URL_MALFORMED 0x02
#define ERR_RESPONSE_MALFORMED_AT 0x03 #define ERR_RESPONSE_MALFORMED_AT 0x03
#define ERR_RESPONSE_MALFORMED 0x04 #define ERR_RESPONSE_MALFORMED 0x04
#define ERR_MQTT_CONN_VERSION_REJECTED 0x05 #define ERR_MQTT_CONN_VERSION_REJECTED 0x05
#define ERR_MQTT_CONN_ID_REJECTED 0x06 #define ERR_MQTT_CONN_ID_REJECTED 0x06
#define ERR_MQTT_CONN_SERVER_UNAVAILABLE 0x07 #define ERR_MQTT_CONN_SERVER_UNAVAILABLE 0x07
#define MQTT_CONN_BAD_USERNAME_PASSWORD 0x08 #define ERR_MQTT_CONN_BAD_USERNAME_PASSWORD 0x08
#define ERR_MQTT_CONN_NOT_AUTHORIZED 0x09 #define ERR_MQTT_CONN_NOT_AUTHORIZED 0x09
// XBee error codes // XBee status codes
#define ERR_CMD_MODE_FAILED 0x02 #define ERR_CMD_MODE_FAILED 0x02
enum Slot {SlotA, SlotB}; enum Slot {SlotA, SlotB};

View file

@ -1,262 +1,55 @@
#include "SX1272.h" #include "SX1272.h"
SX1272::SX1272(Module* module) { SX1272::SX1272(Module* mod) : SX127x(mod) {
_mod = module;
} }
uint8_t SX1272::begin(Bandwidth bw, SpreadingFactor sf, CodingRate cr, uint16_t addrEeprom) { uint8_t SX1272::begin(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t addrEeprom) {
// copy LoRa modem settings uint8_t state = SX127x::begin(freq, bw, sf, cr, syncWord, addrEeprom);
_bw = bw; if(state != ERR_NONE) {
_sf = sf; return(state);
_cr = cr;
// ESP32-only: initialize EEPROM
#ifdef ESP32
if(!EEPROM.begin(9)) {
DEBUG_PRINTLN_STR("Unable to initialize EEPROM");
return(ERR_EEPROM_NOT_INITIALIZED);
}
#endif
// copy EEPROM start address
_addrEeprom = addrEeprom;
// check if the node has address
bool hasAddress = false;
for(uint16_t i = 0; i < 8; i++) {
if(EEPROM.read(_addrEeprom + i) != 255) {
hasAddress = true;
break;
}
} }
// generate new address return(config(freq, bw, sf, cr, syncWord));
if(!hasAddress) {
randomSeed(analogRead(5));
generateLoRaAdress();
}
#ifdef DEBUG
Serial.print("LoRa node address string: ");
#endif
for(uint8_t i = 0; i < 8; i++) {
_address[i] = EEPROM.read(i);
#ifdef DEBUG
Serial.print(_address[i], HEX);
if(i < 7) {
Serial.print(":");
} else {
Serial.println();
}
#endif
}
// set module properties
_mod->init(USE_SPI, INT_BOTH);
// try to find the SX1272 chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
uint8_t version = _mod->SPIreadRegister(SX1272_REG_VERSION);
if(version == 0x22) {
flagFound = true;
} else {
#ifdef DEBUG
Serial.print("SX1272 not found! (");
Serial.print(i + 1);
Serial.print(" of 10 tries) SX1272_REG_VERSION == ");
char buffHex[5];
sprintf(buffHex, "0x%02X", version);
Serial.print(buffHex);
Serial.println();
#endif
delay(1000);
i++;
}
}
if(!flagFound) {
DEBUG_PRINTLN_STR("No SX1272 found!");
SPI.end();
return(ERR_CHIP_NOT_FOUND);
} else {
DEBUG_PRINTLN_STR("Found SX1272! (match by SX1272_REG_VERSION == 0x12)");
}
// configure LoRa modem
return(config(_bw, _sf, _cr));
} }
uint8_t SX1272::transmit(Packet& pack) { uint8_t SX1272::setBandwidth(uint32_t bw) {
char buffer[256]; uint8_t state = SX1272::config(bw, _sf, _cr, _freq, _syncWord);
// copy packet source and destination addresses into buffer
for(uint8_t i = 0; i < 8; i++) {
buffer[i] = pack.source[i];
buffer[i+8] = pack.destination[i];
}
// copy packet data into buffer
for(uint8_t i = 0; i < pack.length; i++) {
buffer[i+16] = pack.data[i];
}
// set mode to standby
setMode(SX1272_STANDBY);
// set DIO pin mapping
_mod->SPIsetRegValue(SX1272_REG_DIO_MAPPING_1, SX1272_DIO0_TX_DONE, 7, 6);
// clear interrupt flags
clearIRQFlags();
// check overall packet length
if(pack.length > 256) {
return(ERR_PACKET_TOO_LONG);
}
// write packet to FIFO
_mod->SPIsetRegValue(SX1272_REG_PAYLOAD_LENGTH, pack.length);
_mod->SPIsetRegValue(SX1272_REG_FIFO_TX_BASE_ADDR, SX1272_FIFO_TX_BASE_ADDR_MAX);
_mod->SPIsetRegValue(SX1272_REG_FIFO_ADDR_PTR, SX1272_FIFO_TX_BASE_ADDR_MAX);
_mod->SPIwriteRegisterBurstStr(SX1272_REG_FIFO, buffer, pack.length);
// set mode to transmit
setMode(SX1272_TX);
// wait for transmission end
unsigned long start = millis();
while(!_mod->getInt0State()) {
DEBUG_PRINT('.');
}
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
}
uint8_t SX1272::receive(Packet& pack) {
char buffer[256];
uint32_t startTime = millis();
// set mode to standby
setMode(SX1272_STANDBY);
// set DIO pin mapping
_mod->SPIsetRegValue(SX1272_REG_DIO_MAPPING_1, SX1272_DIO0_RX_DONE | SX1272_DIO1_RX_TIMEOUT, 7, 4);
// clear interrupt flags
clearIRQFlags();
// set FIFO address pointers
_mod->SPIsetRegValue(SX1272_REG_FIFO_RX_BASE_ADDR, SX1272_FIFO_RX_BASE_ADDR_MAX);
_mod->SPIsetRegValue(SX1272_REG_FIFO_ADDR_PTR, SX1272_FIFO_RX_BASE_ADDR_MAX);
// set mode to receive
setMode(SX1272_RXSINGLE);
// wait for packet reception or timeout
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
clearIRQFlags();
return(ERR_RX_TIMEOUT);
}
}
// check received packet CRC
if(_mod->SPIgetRegValue(SX1272_REG_IRQ_FLAGS, 5, 5) == SX1272_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
return(ERR_CRC_MISMATCH);
}
// get header type
uint8_t headerMode = _mod->SPIgetRegValue(SX1272_REG_MODEM_CONFIG_1, 0, 0);
if(headerMode == SX1272_HEADER_EXPL_MODE) {
pack.length = _mod->SPIgetRegValue(SX1272_REG_RX_NB_BYTES);
}
// read packet from FIFO
_mod->SPIreadRegisterBurstStr(SX1272_REG_FIFO, pack.length, buffer);
// clear interrupt flags
clearIRQFlags();
// get packet source and destination addresses from buffer
for(uint8_t i = 0; i < 8; i++) {
pack.source[i] = buffer[i];
pack.destination[i] = buffer[i+8];
}
// get packet source and destination addresses from buffer
for(uint8_t i = 16; i < pack.length; i++) {
pack.data[i-16] = buffer[i];
}
pack.data[pack.length-16] = 0;
// measure overall datarate
uint32_t elapsedTime = millis() - startTime;
dataRate = (pack.length*8.0)/((float)elapsedTime/1000.0);
// get packet RSSI
lastPacketRSSI = getLastPacketRSSI();
return(ERR_NONE);
}
uint8_t SX1272::sleep() {
return(setMode(0b00000000));
}
uint8_t SX1272::standby() {
return(setMode(0b00000001));
}
uint8_t SX1272::setBandwidth(Bandwidth bw) {
uint8_t state = config(bw, _sf, _cr);
if(state == ERR_NONE) { if(state == ERR_NONE) {
_bw = bw; _bw = bw;
} }
return(state); return(state);
} }
uint8_t SX1272::setSpreadingFactor(SpreadingFactor sf) { uint8_t SX1272::setSpreadingFactor(uint8_t sf) {
uint8_t state = config(_bw, sf, _cr); uint8_t state = SX1272::config(_bw, sf, _cr, _freq, _syncWord);
if(state == ERR_NONE) { if(state == ERR_NONE) {
_sf = sf; _sf = sf;
} }
return(state); return(state);
} }
uint8_t SX1272::setCodingRate(CodingRate cr) { uint8_t SX1272::setCodingRate(uint8_t cr) {
uint8_t state = config(_bw, _sf, cr); uint8_t state = SX1272::config(_bw, _sf, cr, _freq, _syncWord);
if(state == ERR_NONE) { if(state == ERR_NONE) {
_cr = cr; _cr = cr;
} }
return(state); return(state);
} }
void SX1272::generateLoRaAdress() { uint8_t SX1272::config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord) {
for(uint8_t i = _addrEeprom; i < (_addrEeprom + 8); i++) {
EEPROM.write(i, (uint8_t)random(0, 256));
}
}
uint8_t SX1272::config(Bandwidth bw, SpreadingFactor sf, CodingRate cr) {
uint8_t status = ERR_NONE; uint8_t status = ERR_NONE;
uint8_t newBandwidth, newSpreadingFactor, newCodingRate; uint8_t newBandwidth, newSpreadingFactor, newCodingRate;
//check the supplied bw, cr and sf values // check the supplied BW, CR and SF values
switch(bw) { switch(bw) {
case BW_125_00_KHZ: case 125000:
newBandwidth = SX1272_BW_125_00_KHZ; newBandwidth = SX1272_BW_125_00_KHZ;
break; break;
case BW_250_00_KHZ: case 250000:
newBandwidth = SX1272_BW_250_00_KHZ; newBandwidth = SX1272_BW_250_00_KHZ;
break; break;
case BW_500_00_KHZ: case 500000:
newBandwidth = SX1272_BW_500_00_KHZ; newBandwidth = SX1272_BW_500_00_KHZ;
break; break;
default: default:
@ -264,130 +57,107 @@ uint8_t SX1272::config(Bandwidth bw, SpreadingFactor sf, CodingRate cr) {
} }
switch(sf) { switch(sf) {
case SF_6: case 6:
newSpreadingFactor = SX1272_SF_6; newSpreadingFactor = SX127X_SF_6;
break; break;
case SF_7: case 7:
newSpreadingFactor = SX1272_SF_7; newSpreadingFactor = SX127X_SF_7;
break; break;
case SF_8: case 8:
newSpreadingFactor = SX1272_SF_8; newSpreadingFactor = SX127X_SF_8;
break; break;
case SF_9: case 9:
newSpreadingFactor = SX1272_SF_9; newSpreadingFactor = SX127X_SF_9;
break; break;
case SF_10: case 10:
newSpreadingFactor = SX1272_SF_10; newSpreadingFactor = SX127X_SF_10;
break; break;
case SF_11: case 11:
newSpreadingFactor = SX1272_SF_11; newSpreadingFactor = SX127X_SF_11;
break; break;
case SF_12: case 12:
newSpreadingFactor = SX1272_SF_12; newSpreadingFactor = SX127X_SF_12;
break; break;
default: default:
return(ERR_INVALID_SPREADING_FACTOR); return(ERR_INVALID_SPREADING_FACTOR);
} }
switch(cr) { switch(cr) {
case CR_4_5: case 5:
newCodingRate = SX1272_CR_4_5; newCodingRate = SX1272_CR_4_5;
break; break;
case CR_4_6: case 6:
newCodingRate = SX1272_CR_4_6; newCodingRate = SX1272_CR_4_6;
break; break;
case CR_4_7: case 7:
newCodingRate = SX1272_CR_4_7; newCodingRate = SX1272_CR_4_7;
break; break;
case CR_4_8: case 8:
newCodingRate = SX1272_CR_4_8; newCodingRate = SX1272_CR_4_8;
break; break;
default: default:
return(ERR_INVALID_CODING_RATE); return(ERR_INVALID_CODING_RATE);
} }
// set mode to SLEEP if((freq < 137.0) || (freq > 525.0)) {
status = setMode(SX1272_SLEEP); return(ERR_INVALID_FREQUENCY);
}
// execute common part
status = SX1272::configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// set LoRa mode // configuration successful, save the new settings
status = _mod->SPIsetRegValue(SX1272_REG_OP_MODE, SX1272_LORA, 7, 7); _bw = bw;
if(status != ERR_NONE) { _sf = sf;
return(status); _cr = cr;
} _freq = freq;
// set carrier frequency return(ERR_NONE);
status = _mod->SPIsetRegValue(SX1272_REG_FRF_MSB, SX1272_FRF_MSB); }
status = _mod->SPIsetRegValue(SX1272_REG_FRF_MID, SX1272_FRF_MID);
status = _mod->SPIsetRegValue(SX1272_REG_FRF_LSB, SX1272_FRF_LSB); uint8_t SX1272::configCommon(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
// configure common registers
uint8_t status = SX127x::config(bw, sf, cr, freq, syncWord);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// output power configuration // output power configuration
status = _mod->SPIsetRegValue(SX1272_REG_PA_CONFIG, SX1272_PA_SELECT_BOOST | SX1272_OUTPUT_POWER); status = _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0);
status = _mod->SPIsetRegValue(SX1272_REG_OCP, SX1272_OCP_ON | SX1272_OCP_TRIM, 5, 0);
status = _mod->SPIsetRegValue(SX1272_REG_LNA, SX1272_LNA_GAIN_1 | SX1272_LNA_BOOST_ON);
status = _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX1272_PA_BOOST_ON, 2, 0);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// turn off frequency hopping // enable LNA gain setting by register
status = _mod->SPIsetRegValue(SX1272_REG_HOP_PERIOD, SX1272_HOP_PERIOD_OFF); status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_OFF, 2, 2);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// basic setting (bw, cr, sf, header mode and CRC) // set SF6 optimizations
if(newSpreadingFactor == SX1272_SF_6) { if(sf == SX127X_SF_6) {
status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_2, SX1272_SF_6 | SX1272_TX_MODE_SINGLE | SX1272_RX_CRC_MODE_OFF, 7, 2); status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1272_HEADER_IMPL_MODE | SX1272_RX_CRC_MODE_OFF, 7, 1);
status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_1, newBandwidth | newCodingRate | SX1272_HEADER_IMPL_MODE);
status = _mod->SPIsetRegValue(SX1272_REG_DETECT_OPTIMIZE, SX1272_DETECT_OPTIMIZE_SF_6, 2, 0);
status = _mod->SPIsetRegValue(SX1272_REG_DETECTION_THRESHOLD, SX1272_DETECTION_THRESHOLD_SF_6);
} else { } else {
status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_2, newSpreadingFactor | SX1272_TX_MODE_SINGLE | SX1272_RX_CRC_MODE_ON, 7, 2); status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1272_HEADER_EXPL_MODE | SX1272_RX_CRC_MODE_ON, 7, 1);
status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_1, newBandwidth | newCodingRate | SX1272_HEADER_EXPL_MODE);
status = _mod->SPIsetRegValue(SX1272_REG_DETECT_OPTIMIZE, SX1272_DETECT_OPTIMIZE_SF_7_12, 2, 0);
status = _mod->SPIsetRegValue(SX1272_REG_DETECTION_THRESHOLD, SX1272_DETECTION_THRESHOLD_SF_7_12);
} }
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// set default preamble length // calculate symbol length and set low datarate optimization, if needed
status = _mod->SPIsetRegValue(SX1272_REG_PREAMBLE_MSB, SX1272_PREAMBLE_LENGTH_MSB); uint16_t base = 1;
status = _mod->SPIsetRegValue(SX1272_REG_PREAMBLE_LSB, SX1272_PREAMBLE_LENGTH_LSB); float symbolLength = (float)(base << _sf) / (float)_bw;
if(symbolLength >= 0.016) {
status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else {
status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0);
}
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// set mode to STANDBY return(status);
status = setMode(SX1272_STANDBY);
if(status != ERR_NONE) {
return(status);
}
// save the new settings
_bw = bw;
_sf = sf;
_cr = cr;
return(ERR_NONE);
}
uint8_t SX1272::setMode(uint8_t mode) {
_mod->SPIsetRegValue(SX1272_REG_OP_MODE, mode, 2, 0);
return(ERR_NONE);
}
void SX1272::clearIRQFlags() {
_mod->SPIwriteRegister(SX1272_REG_IRQ_FLAGS, 0b11111111);
}
int8_t SX1272::getLastPacketRSSI() {
return(-164 + _mod->SPIgetRegValue(SX1272_REG_PKT_RSSI_VALUE));
} }

View file

@ -1,58 +1,11 @@
#ifndef _KITELIB_SX1272_H #ifndef _KITELIB_SX1272_H
#define _KITELIB_SX1272_H #define _KITELIB_SX1272_H
#include <EEPROM.h>
#include "TypeDef.h" #include "TypeDef.h"
#include "Module.h" #include "Module.h"
#include "Packet.h" #include "SX127x.h"
//SX1272 register map //SX1272 specific register map
#define SX1272_REG_FIFO 0x00
#define SX1272_REG_OP_MODE 0x01
#define SX1272_REG_FRF_MSB 0x06
#define SX1272_REG_FRF_MID 0x07
#define SX1272_REG_FRF_LSB 0x08
#define SX1272_REG_PA_CONFIG 0x09
#define SX1272_REG_PA_RAMP 0x0A
#define SX1272_REG_OCP 0x0B
#define SX1272_REG_LNA 0x0C
#define SX1272_REG_FIFO_ADDR_PTR 0x0D
#define SX1272_REG_FIFO_TX_BASE_ADDR 0x0E
#define SX1272_REG_FIFO_RX_BASE_ADDR 0x0F
#define SX1272_REG_FIFO_RX_CURRENT_ADDR 0x10
#define SX1272_REG_IRQ_FLAGS_MASK 0x11
#define SX1272_REG_IRQ_FLAGS 0x12
#define SX1272_REG_RX_NB_BYTES 0x13
#define SX1272_REG_RX_HEADER_CNT_VALUE_MSB 0x14
#define SX1272_REG_RX_HEADER_CNT_VALUE_LSB 0x15
#define SX1272_REG_RX_PACKET_CNT_VALUE_MSB 0x16
#define SX1272_REG_RX_PACKET_CNT_VALUE_LSB 0x17
#define SX1272_REG_MODEM_STAT 0x18
#define SX1272_REG_PKT_SNR_VALUE 0x19
#define SX1272_REG_PKT_RSSI_VALUE 0x1A
#define SX1272_REG_RSSI_VALUE 0x1B
#define SX1272_REG_HOP_CHANNEL 0x1C
#define SX1272_REG_MODEM_CONFIG_1 0x1D
#define SX1272_REG_MODEM_CONFIG_2 0x1E
#define SX1272_REG_SYMB_TIMEOUT_LSB 0x1F
#define SX1272_REG_PREAMBLE_MSB 0x20
#define SX1272_REG_PREAMBLE_LSB 0x21
#define SX1272_REG_PAYLOAD_LENGTH 0x22
#define SX1272_REG_MAX_PAYLOAD_LENGTH 0x23
#define SX1272_REG_HOP_PERIOD 0x24
#define SX1272_REG_FIFO_RX_BYTE_ADDR 0x25
#define SX1272_REG_FEI_MSB 0x28
#define SX1272_REG_FEI_MID 0x29
#define SX1272_REG_FEI_LSB 0x2A
#define SX1272_REG_RSSI_WIDEBAND 0x2C
#define SX1272_REG_DETECT_OPTIMIZE 0x31
#define SX1272_REG_INVERT_IQ 0x33
#define SX1272_REG_DETECTION_THRESHOLD 0x37
#define SX1272_REG_SYNC_WORD 0x39
#define SX1272_REG_DIO_MAPPING_1 0x40
#define SX1272_REG_DIO_MAPPING_2 0x41
#define SX1272_REG_VERSION 0x42
#define SX1272_REG_AGC_REF 0x43 #define SX1272_REG_AGC_REF 0x43
#define SX1272_REG_AGC_THRESH_1 0x44 #define SX1272_REG_AGC_THRESH_1 0x44
#define SX1272_REG_AGC_THRESH_2 0x45 #define SX1272_REG_AGC_THRESH_2 0x45
@ -66,47 +19,11 @@
#define SX1272_REG_BIT_RATE_FRAC 0x70 #define SX1272_REG_BIT_RATE_FRAC 0x70
//SX1272 LoRa modem settings //SX1272 LoRa modem settings
//SX1272_REG_OP_MODE MSB LSB DESCRIPTION
#define SX1272_FSK_OOK 0b00000000 // 7 7 FSK/OOK mode
#define SX1272_LORA 0b10000000 // 7 7 LoRa mode
#define SX1272_ACCESS_SHARED_REG_OFF 0b00000000 // 6 6 access LoRa registers (0x0D:0x3F) in LoRa mode
#define SX1272_ACCESS_SHARED_REG_ON 0b01000000 // 6 6 access FSK registers (0x0D:0x3F) in LoRa mode
#define SX1272_SLEEP 0b00000000 // 2 0 sleep
#define SX1272_STANDBY 0b00000001 // 2 0 standby
#define SX1272_FSTX 0b00000010 // 2 0 frequency synthesis TX
#define SX1272_TX 0b00000011 // 2 0 transmit
#define SX1272_FSRX 0b00000100 // 2 0 frequency synthesis RX
#define SX1272_RXCONTINUOUS 0b00000101 // 2 0 receive continuous
#define SX1272_RXSINGLE 0b00000110 // 2 0 receive single
#define SX1272_CAD 0b00000111 // 2 0 channel activity detection
//SX1272_REG_FRF_MSB + REG_FRF_MID + REG_FRF_LSB //SX1272_REG_FRF_MSB + REG_FRF_MID + REG_FRF_LSB
#define SX1272_FRF_MSB 0xE4 // 7 0 carrier frequency setting: f_RF = (F(XOSC) * FRF)/2^19 #define SX1272_FRF_MSB 0xE4 // 7 0 carrier frequency setting: f_RF = (F(XOSC) * FRF)/2^19
#define SX1272_FRF_MID 0xC0 // 7 0 where F(XOSC) = 32 MHz #define SX1272_FRF_MID 0xC0 // 7 0 where F(XOSC) = 32 MHz
#define SX1272_FRF_LSB 0x00 // 7 0 FRF = 3 byte value of FRF registers #define SX1272_FRF_LSB 0x00 // 7 0 FRF = 3 byte value of FRF registers
//SX1272_REG_PA_CONFIG
#define SX1272_PA_SELECT_RFO 0b00000000 // 7 7 RFIO pin output, power limited to +13 dBm
#define SX1272_PA_SELECT_BOOST 0b10000000 // 7 7 PA_BOOST pin output, power limited to +20 dBm
#define SX1272_OUTPUT_POWER 0b00001111 // 3 0 output power: P_out = -1 + OUTPUT_POWER [dBm] for PA_SELECT_BOOST
//SX1272_REG_OCP
#define SX1272_OCP_OFF 0b00000000 // 5 5 PA overload current protection disabled
#define SX1272_OCP_ON 0b00100000 // 5 5 PA overload current protection enabled
#define SX1272_OCP_TRIM 0b00001011 // 4 0 OCP current: I_max(OCP_TRIM = 0b1011) = 100 mA
//SX1272_REG_LNA
#define SX1272_LNA_GAIN_0 0b00000000 // 7 5 LNA gain setting: not used
#define SX1272_LNA_GAIN_1 0b00100000 // 7 5 max gain
#define SX1272_LNA_GAIN_2 0b01000000 // 7 5 .
#define SX1272_LNA_GAIN_3 0b01100000 // 7 5 .
#define SX1272_LNA_GAIN_4 0b10000000 // 7 5 .
#define SX1272_LNA_GAIN_5 0b10100000 // 7 5 .
#define SX1272_LNA_GAIN_6 0b11000000 // 7 5 min gain
#define SX1272_LNA_GAIN_7 0b11100000 // 7 5 not used
#define SX1272_LNA_BOOST_OFF 0b00000000 // 1 0 default LNA current
#define SX1272_LNA_BOOST_ON 0b00000011 // 1 0 150% LNA current
//SX1272_REG_MODEM_CONFIG_1 //SX1272_REG_MODEM_CONFIG_1
#define SX1272_BW_125_00_KHZ 0b00000000 // 7 6 bandwidth: 125 kHz #define SX1272_BW_125_00_KHZ 0b00000000 // 7 6 bandwidth: 125 kHz
#define SX1272_BW_250_00_KHZ 0b01000000 // 7 6 250 kHz #define SX1272_BW_250_00_KHZ 0b01000000 // 7 6 250 kHz
@ -123,109 +40,25 @@
#define SX1272_LOW_DATA_RATE_OPT_ON 0b00000001 // 0 0 low data rate optimization enabled, mandatory for SF 11 and 12 with BW 125 kHz #define SX1272_LOW_DATA_RATE_OPT_ON 0b00000001 // 0 0 low data rate optimization enabled, mandatory for SF 11 and 12 with BW 125 kHz
//SX1272_REG_MODEM_CONFIG_2 //SX1272_REG_MODEM_CONFIG_2
#define SX1272_SF_6 0b01100000 // 7 4 spreading factor: 64 chips/bit
#define SX1272_SF_7 0b01110000 // 7 4 128 chips/bit
#define SX1272_SF_8 0b10000000 // 7 4 256 chips/bit
#define SX1272_SF_9 0b10010000 // 7 4 512 chips/bit
#define SX1272_SF_10 0b10100000 // 7 4 1024 chips/bit
#define SX1272_SF_11 0b10110000 // 7 4 2048 chips/bit
#define SX1272_SF_12 0b11000000 // 7 4 4096 chips/bit
#define SX1272_TX_MODE_SINGLE 0b00000000 // 3 3 single TX
#define SX1272_TX_MODE_CONT 0b00001000 // 3 3 continuous TX
#define SX1272_AGC_AUTO_OFF 0b00000000 // 2 2 LNA gain set by REG_LNA #define SX1272_AGC_AUTO_OFF 0b00000000 // 2 2 LNA gain set by REG_LNA
#define SX1272_AGC_AUTO_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop #define SX1272_AGC_AUTO_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop
#define SX1272_RX_TIMEOUT_MSB 0b00000000 // 1 0
//SX1272_REG_SYMB_TIMEOUT_LSB class SX1272: public SX127x {
#define SX1272_RX_TIMEOUT_LSB 0b01100100 // 7 0 10 bit RX operation timeout
//SX1272_REG_PREAMBLE_MSB + REG_PREAMBLE_LSB
#define SX1272_PREAMBLE_LENGTH_MSB 0b00000000 // 7 0 2 byte preamble length setting: l_P = PREAMBLE_LENGTH + 4.25
#define SX1272_PREAMBLE_LENGTH_LSB 0b00001000 // 7 0 where l_p = preamble length
//SX1272_REG_DETECT_OPTIMIZE
#define SX1272_DETECT_OPTIMIZE_SF_6 0b00000101 // 2 0 SF6 detection optimization
#define SX1272_DETECT_OPTIMIZE_SF_7_12 0b00000011 // 2 0 SF7 to SF12 detection optimization
//SX1272_REG_DETECTION_THRESHOLD
#define SX1272_DETECTION_THRESHOLD_SF_6 0b00001100 // 7 0 SF6 detection threshold
#define SX1272_DETECTION_THRESHOLD_SF_7_12 0b00001010 // 7 0 SF7 to SF12 detection threshold
//SX1272_REG_PA_DAC
#define SX1272_PA_BOOST_OFF 0b00000100 // 2 0 PA_BOOST disabled
#define SX1272_PA_BOOST_ON 0b00000111 // 2 0 +20 dBm on PA_BOOST when OUTPUT_POWER = 0b1111
//SX1272_REG_HOP_PERIOD
#define SX1272_HOP_PERIOD_OFF 0b00000000 // 7 0 number of periods between frequency hops; 0 = disabled
#define SX1272_HOP_PERIOD_MAX 0b11111111 // 7 0
//SX1272_REG_DIO_MAPPING_1
#define SX1272_DIO0_RX_DONE 0b00000000 // 7 6
#define SX1272_DIO0_TX_DONE 0b01000000 // 7 6
#define SX1272_DIO0_CAD_DONE 0b10000000 // 7 6
#define SX1272_DIO1_RX_TIMEOUT 0b00000000 // 5 4
#define SX1272_DIO1_FHSS_CHANGE_CHANNEL 0b00010000 // 5 4
#define SX1272_DIO1_CAD_DETECTED 0b00100000 // 5 4
//SX1272_REG_IRQ_FLAGS
#define SX1272_CLEAR_IRQ_FLAG_RX_TIMEOUT 0b10000000 // 7 7 timeout
#define SX1272_CLEAR_IRQ_FLAG_RX_DONE 0b01000000 // 6 6 packet reception complete
#define SX1272_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR 0b00100000 // 5 5 payload CRC error
#define SX1272_CLEAR_IRQ_FLAG_VALID_HEADER 0b00010000 // 4 4 valid header received
#define SX1272_CLEAR_IRQ_FLAG_TX_DONE 0b00001000 // 3 3 payload transmission complete
#define SX1272_CLEAR_IRQ_FLAG_CAD_DONE 0b00000100 // 2 2 CAD complete
#define SX1272_CLEAR_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b00000010 // 1 1 FHSS change channel
#define SX1272_CLEAR_IRQ_FLAG_CAD_DETECTED 0b00000001 // 0 0 valid LoRa signal detected during CAD operation
//SX1272_REG_IRQ_FLAGS_MASK
#define SX1272_MASK_IRQ_FLAG_RX_TIMEOUT 0b01111111 // 7 7 timeout
#define SX1272_MASK_IRQ_FLAG_RX_DONE 0b10111111 // 6 6 packet reception complete
#define SX1272_MASK_IRQ_FLAG_PAYLOAD_CRC_ERROR 0b11011111 // 5 5 payload CRC error
#define SX1272_MASK_IRQ_FLAG_VALID_HEADER 0b11101111 // 4 4 valid header received
#define SX1272_MASK_IRQ_FLAG_TX_DONE 0b11110111 // 3 3 payload transmission complete
#define SX1272_MASK_IRQ_FLAG_CAD_DONE 0b11111011 // 2 2 CAD complete
#define SX1272_MASK_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b11111101 // 1 1 FHSS change channel
#define SX1272_MASK_IRQ_FLAG_CAD_DETECTED 0b11111110 // 0 0 valid LoRa signal detected during CAD operation
//SX1272_REG_FIFO_TX_BASE_ADDR
#define SX1272_FIFO_TX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for TX only
//SX1272_REG_FIFO_RX_BASE_ADDR
#define SX1272_FIFO_RX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for RX only
class SX1272 {
public: public:
SX1272(Module* module); SX1272(Module* mod);
float dataRate; uint8_t begin(float freq = 434.0, uint32_t bw = 125000, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, uint16_t addrEeprom = 0);
int8_t lastPacketRSSI;
uint8_t begin(Bandwidth bw = BW_125_00_KHZ, SpreadingFactor sf = SF_9, CodingRate cr = CR_4_7, uint16_t addrEeprom = 0); uint8_t setBandwidth(uint32_t bw);
uint8_t transmit(Packet& pack); uint8_t setSpreadingFactor(uint8_t sf);
uint8_t receive(Packet& pack); uint8_t setCodingRate(uint8_t cr);
uint8_t sleep(); protected:
uint8_t standby(); uint8_t configCommon(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord); // common for SX1272/73
uint8_t setBandwidth(Bandwidth bw);
uint8_t setSpreadingFactor(SpreadingFactor sf);
uint8_t setCodingRate(CodingRate cr);
private: private:
Module* _mod; uint8_t config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord); // specific to SX1272
Bandwidth _bw;
SpreadingFactor _sf;
CodingRate _cr;
uint8_t _address[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint16_t _addrEeprom;
void generateLoRaAdress();
uint8_t config(Bandwidth bw, SpreadingFactor sf, CodingRate cr);
uint8_t setMode(uint8_t mode);
void clearIRQFlags();
int8_t getLastPacketRSSI();
}; };
#endif #endif

76
src/modules/SX1273.cpp Normal file
View file

@ -0,0 +1,76 @@
#include "SX1273.h"
SX1273::SX1273(Module* mod) : SX1272(mod) {
}
uint8_t SX1273::config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
uint8_t status = ERR_NONE;
uint8_t newBandwidth, newSpreadingFactor, newCodingRate;
// check the supplied BW, CR and SF values
switch(bw) {
case 125000:
newBandwidth = SX1272_BW_125_00_KHZ;
break;
case 250000:
newBandwidth = SX1272_BW_250_00_KHZ;
break;
case 500000:
newBandwidth = SX1272_BW_500_00_KHZ;
break;
default:
return(ERR_INVALID_BANDWIDTH);
}
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);
}
switch(cr) {
case 5:
newCodingRate = SX1272_CR_4_5;
break;
case 6:
newCodingRate = SX1272_CR_4_6;
break;
case 7:
newCodingRate = SX1272_CR_4_7;
break;
case 8:
newCodingRate = SX1272_CR_4_8;
break;
default:
return(ERR_INVALID_CODING_RATE);
}
if((freq < 860.0) || (freq > 1020.0)) {
return(ERR_INVALID_FREQUENCY);
}
// execute common part
status = configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord);
if(status != ERR_NONE) {
return(status);
}
// configuration successful, save the new settings
_bw = bw;
_sf = sf;
_cr = cr;
return(ERR_NONE);
}

15
src/modules/SX1273.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _KITELIB_SX1273_H
#define _KITELIB_SX1273_H
#include "TypeDef.h"
#include "SX1272.h"
class SX1273: public SX1272 {
public:
SX1273(Module* mod);
private:
uint8_t config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord);
};
#endif

85
src/modules/SX1276.cpp Normal file
View file

@ -0,0 +1,85 @@
#include "SX1276.h"
SX1276::SX1276(Module* mod) : SX1278(mod) {
}
uint8_t SX1276::config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
uint8_t status = ERR_NONE;
uint8_t newBandwidth, newSpreadingFactor, newCodingRate;
// check the supplied BW, CR and SF values
switch(bw) {
case 125000:
newBandwidth = SX1278_BW_125_00_KHZ;
break;
case 250000:
newBandwidth = SX1278_BW_250_00_KHZ;
break;
case 500000:
newBandwidth = SX1278_BW_500_00_KHZ;
break;
default:
return(ERR_INVALID_BANDWIDTH);
}
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;
case 10:
newSpreadingFactor = SX127X_SF_10;
break;
case 11:
newSpreadingFactor = SX127X_SF_11;
break;
case 12:
newSpreadingFactor = SX127X_SF_12;
break;
default:
return(ERR_INVALID_SPREADING_FACTOR);
}
switch(cr) {
case 5:
newCodingRate = SX1278_CR_4_5;
break;
case 6:
newCodingRate = SX1278_CR_4_6;
break;
case 7:
newCodingRate = SX1278_CR_4_7;
break;
case 8:
newCodingRate = SX1278_CR_4_8;
break;
default:
return(ERR_INVALID_CODING_RATE);
}
if((freq < 137.0) || (freq > 1020.0)) {
return(ERR_INVALID_FREQUENCY);
}
// execute common part
status = configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord);
if(status != ERR_NONE) {
return(status);
}
// configuration successful, save the new settings
_bw = bw;
_sf = sf;
_cr = cr;
return(ERR_NONE);
}

15
src/modules/SX1276.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _KITELIB_SX1276_H
#define _KITELIB_SX1276_H
#include "TypeDef.h"
#include "SX1278.h"
class SX1276: public SX1278 {
public:
SX1276(Module* mod);
private:
uint8_t config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord);
};
#endif

76
src/modules/SX1277.cpp Normal file
View file

@ -0,0 +1,76 @@
#include "SX1277.h"
SX1277::SX1277(Module* mod) : SX1278(mod) {
}
uint8_t SX1277::config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
uint8_t status = ERR_NONE;
uint8_t newBandwidth, newSpreadingFactor, newCodingRate;
// check the supplied BW, CR and SF values
switch(bw) {
case 125000:
newBandwidth = SX1278_BW_125_00_KHZ;
break;
case 250000:
newBandwidth = SX1278_BW_250_00_KHZ;
break;
case 500000:
newBandwidth = SX1278_BW_500_00_KHZ;
break;
default:
return(ERR_INVALID_BANDWIDTH);
}
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);
}
switch(cr) {
case 5:
newCodingRate = SX1278_CR_4_5;
break;
case 6:
newCodingRate = SX1278_CR_4_6;
break;
case 7:
newCodingRate = SX1278_CR_4_7;
break;
case 8:
newCodingRate = SX1278_CR_4_8;
break;
default:
return(ERR_INVALID_CODING_RATE);
}
if((freq < 137.0) || (freq > 1020.0)) {
return(ERR_INVALID_FREQUENCY);
}
// execute common part
status = configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord);
if(status != ERR_NONE) {
return(status);
}
// configuration successful, save the new settings
_bw = bw;
_sf = sf;
_cr = cr;
return(ERR_NONE);
}

15
src/modules/SX1277.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _KITELIB_SX1277_H
#define _KITELIB_SX1277_H
#include "TypeDef.h"
#include "SX1278.h"
class SX1277: public SX1278 {
public:
SX1277(Module* mod);
private:
uint8_t config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord);
};
#endif

View file

@ -1,280 +1,76 @@
#include "SX1278.h" #include "SX1278.h"
SX1278::SX1278(Module* module) { SX1278::SX1278(Module* mod) : SX127x(mod) {
_mod = module;
} }
uint8_t SX1278::begin(Bandwidth bw, SpreadingFactor sf, CodingRate cr, uint16_t addrEeprom) { uint8_t SX1278::begin(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t addrEeprom) {
// copy LoRa modem settings uint8_t state = SX127x::begin(freq, bw, sf, cr, syncWord, addrEeprom);
_bw = bw; if(state != ERR_NONE) {
_sf = sf; return(state);
_cr = cr;
// ESP32-only: initialize EEPROM
#ifdef ESP32
if(!EEPROM.begin(9)) {
DEBUG_PRINTLN_STR("Unable to initialize EEPROM");
return(ERR_EEPROM_NOT_INITIALIZED);
}
#endif
// copy EEPROM start address
_addrEeprom = addrEeprom;
// check if the node has address
bool hasAddress = false;
for(uint16_t i = 0; i < 8; i++) {
if(EEPROM.read(_addrEeprom + i) != 255) {
hasAddress = true;
break;
}
} }
// generate new address return(config(freq, bw, sf, cr, syncWord));
if(!hasAddress) {
randomSeed(analogRead(5));
generateLoRaAdress();
}
DEBUG_PRINTLN_STR("LoRa node address string: ");
for(uint8_t i = 0; i < 8; i++) {
_address[i] = EEPROM.read(i);
#ifdef DEBUG
Serial.print(_address[i], HEX);
if(i < 7) {
Serial.print(":");
} else {
Serial.println();
}
#endif
}
// set module properties
_mod->init(USE_SPI, INT_BOTH);
// try to find the SX1278 chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
uint8_t version = _mod->SPIreadRegister(SX1278_REG_VERSION);
if(version == 0x12) {
flagFound = true;
} else {
#ifdef DEBUG
Serial.print("SX1278 not found! (");
Serial.print(i + 1);
Serial.print(" of 10 tries) SX1278_REG_VERSION == ");
char buffHex[5];
sprintf(buffHex, "0x%02X", version);
Serial.print(buffHex);
Serial.println();
#endif
delay(1000);
i++;
}
}
if(!flagFound) {
DEBUG_PRINTLN_STR("No SX1278 found!");
SPI.end();
return(ERR_CHIP_NOT_FOUND);
} else {
DEBUG_PRINTLN_STR("Found SX1278! (match by SX1278_REG_VERSION == 0x12)");
}
// configure LoRa modem
return(config(_bw, _sf, _cr));
} }
uint8_t SX1278::transmit(Packet& pack) { uint8_t SX1278::setBandwidth(uint32_t bw) {
char buffer[256]; uint8_t state = SX1278::config(bw, _sf, _cr, _freq, _syncWord);
// copy packet source and destination addresses into buffer
for(uint8_t i = 0; i < 8; i++) {
buffer[i] = pack.source[i];
buffer[i+8] = pack.destination[i];
}
// copy packet data into buffer
for(uint8_t i = 0; i < pack.length; i++) {
buffer[i+16] = pack.data[i];
}
// set mode to standby
setMode(SX1278_STANDBY);
// set DIO pin mapping
_mod->SPIsetRegValue(SX1278_REG_DIO_MAPPING_1, SX1278_DIO0_TX_DONE, 7, 6);
// clear interrupt flags
clearIRQFlags();
// check overall packet length
if(pack.length > 256) {
return(ERR_PACKET_TOO_LONG);
}
// write packet to FIFO
_mod->SPIsetRegValue(SX1278_REG_PAYLOAD_LENGTH, pack.length);
_mod->SPIsetRegValue(SX1278_REG_FIFO_TX_BASE_ADDR, SX1278_FIFO_TX_BASE_ADDR_MAX);
_mod->SPIsetRegValue(SX1278_REG_FIFO_ADDR_PTR, SX1278_FIFO_TX_BASE_ADDR_MAX);
_mod->SPIwriteRegisterBurstStr(SX1278_REG_FIFO, buffer, pack.length);
// set mode to transmit
setMode(SX1278_TX);
// wait for transmission end
unsigned long start = millis();
while(!_mod->getInt0State()) {
DEBUG_PRINT('.');
}
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
}
uint8_t SX1278::receive(Packet& pack) {
char buffer[256];
uint32_t startTime = millis();
// set mode to standby
setMode(SX1278_STANDBY);
// set DIO pin mapping
_mod->SPIsetRegValue(SX1278_REG_DIO_MAPPING_1, SX1278_DIO0_RX_DONE | SX1278_DIO1_RX_TIMEOUT, 7, 4);
// clear interrupt flags
clearIRQFlags();
// set FIFO address pointers
_mod->SPIsetRegValue(SX1278_REG_FIFO_RX_BASE_ADDR, SX1278_FIFO_RX_BASE_ADDR_MAX);
_mod->SPIsetRegValue(SX1278_REG_FIFO_ADDR_PTR, SX1278_FIFO_RX_BASE_ADDR_MAX);
// set mode to receive
setMode(SX1278_RXSINGLE);
// wait for packet reception or timeout
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
clearIRQFlags();
return(ERR_RX_TIMEOUT);
}
}
// check received packet CRC
if(_mod->SPIgetRegValue(SX1278_REG_IRQ_FLAGS, 5, 5) == SX1278_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
return(ERR_CRC_MISMATCH);
}
// get header type
uint8_t headerMode = _mod->SPIgetRegValue(SX1278_REG_MODEM_CONFIG_1, 0, 0);
if(headerMode == SX1278_HEADER_EXPL_MODE) {
pack.length = _mod->SPIgetRegValue(SX1278_REG_RX_NB_BYTES);
}
// read packet from FIFO
_mod->SPIreadRegisterBurstStr(SX1278_REG_FIFO, pack.length, buffer);
// clear interrupt flags
clearIRQFlags();
// get packet source and destination addresses from buffer
for(uint8_t i = 0; i < 8; i++) {
pack.source[i] = buffer[i];
pack.destination[i] = buffer[i+8];
}
// get packet source and destination addresses from buffer
for(uint8_t i = 16; i < pack.length; i++) {
pack.data[i-16] = buffer[i];
}
pack.data[pack.length-16] = 0;
// measure overall datarate
uint32_t elapsedTime = millis() - startTime;
dataRate = (pack.length*8.0)/((float)elapsedTime/1000.0);
// get packet RSSI
lastPacketRSSI = getLastPacketRSSI();
return(ERR_NONE);
}
uint8_t SX1278::sleep() {
return(setMode(0b00000000));
}
uint8_t SX1278::standby() {
return(setMode(0b00000001));
}
uint8_t SX1278::setBandwidth(Bandwidth bw) {
uint8_t state = config(bw, _sf, _cr);
if(state == ERR_NONE) { if(state == ERR_NONE) {
_bw = bw; _bw = bw;
} }
return(state); return(state);
} }
uint8_t SX1278::setSpreadingFactor(SpreadingFactor sf) { uint8_t SX1278::setSpreadingFactor(uint8_t sf) {
uint8_t state = config(_bw, sf, _cr); uint8_t state = SX1278::config(_bw, sf, _cr, _freq, _syncWord);
if(state == ERR_NONE) { if(state == ERR_NONE) {
_sf = sf; _sf = sf;
} }
return(state); return(state);
} }
uint8_t SX1278::setCodingRate(CodingRate cr) { uint8_t SX1278::setCodingRate(uint8_t cr) {
uint8_t state = config(_bw, _sf, cr); uint8_t state = SX1278::config(_bw, _sf, cr, _freq, _syncWord);
if(state == ERR_NONE) { if(state == ERR_NONE) {
_cr = cr; _cr = cr;
} }
return(state); return(state);
} }
void SX1278::generateLoRaAdress() { uint8_t SX1278::config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord) {
for(uint8_t i = _addrEeprom; i < (_addrEeprom + 8); i++) {
EEPROM.write(i, (uint8_t)random(0, 256));
}
}
uint8_t SX1278::config(Bandwidth bw, SpreadingFactor sf, CodingRate cr) {
uint8_t status = ERR_NONE; uint8_t status = ERR_NONE;
uint8_t newBandwidth, newSpreadingFactor, newCodingRate; uint8_t newBandwidth, newSpreadingFactor, newCodingRate;
//check the supplied bw, cr and sf values // check the supplied BW, CR and SF values
switch(bw) { switch(bw) {
case BW_7_80_KHZ: case 7800:
newBandwidth = SX1278_BW_7_80_KHZ; newBandwidth = SX1278_BW_7_80_KHZ;
break; break;
case BW_10_40_KHZ: case 10400:
newBandwidth = SX1278_BW_10_40_KHZ; newBandwidth = SX1278_BW_10_40_KHZ;
break; break;
case BW_15_60_KHZ: case 15600:
newBandwidth = SX1278_BW_15_60_KHZ; newBandwidth = SX1278_BW_15_60_KHZ;
break; break;
case BW_20_80_KHZ: case 20800:
newBandwidth = SX1278_BW_20_80_KHZ; newBandwidth = SX1278_BW_20_80_KHZ;
break; break;
case BW_31_25_KHZ: case 31250:
newBandwidth = SX1278_BW_31_25_KHZ; newBandwidth = SX1278_BW_31_25_KHZ;
break; break;
case BW_41_70_KHZ: case 41700:
newBandwidth = SX1278_BW_41_70_KHZ; newBandwidth = SX1278_BW_41_70_KHZ;
break; break;
case BW_62_50_KHZ: case 62500:
newBandwidth = SX1278_BW_62_50_KHZ; newBandwidth = SX1278_BW_62_50_KHZ;
break; break;
case BW_125_00_KHZ: case 125000:
newBandwidth = SX1278_BW_125_00_KHZ; newBandwidth = SX1278_BW_125_00_KHZ;
break; break;
case BW_250_00_KHZ: case 250000:
newBandwidth = SX1278_BW_250_00_KHZ; newBandwidth = SX1278_BW_250_00_KHZ;
break; break;
case BW_500_00_KHZ: case 500000:
newBandwidth = SX1278_BW_500_00_KHZ; newBandwidth = SX1278_BW_500_00_KHZ;
break; break;
default: default:
@ -282,130 +78,107 @@ uint8_t SX1278::config(Bandwidth bw, SpreadingFactor sf, CodingRate cr) {
} }
switch(sf) { switch(sf) {
case SF_6: case 6:
newSpreadingFactor = SX1278_SF_6; newSpreadingFactor = SX127X_SF_6;
break; break;
case SF_7: case 7:
newSpreadingFactor = SX1278_SF_7; newSpreadingFactor = SX127X_SF_7;
break; break;
case SF_8: case 8:
newSpreadingFactor = SX1278_SF_8; newSpreadingFactor = SX127X_SF_8;
break; break;
case SF_9: case 9:
newSpreadingFactor = SX1278_SF_9; newSpreadingFactor = SX127X_SF_9;
break; break;
case SF_10: case 10:
newSpreadingFactor = SX1278_SF_10; newSpreadingFactor = SX127X_SF_10;
break; break;
case SF_11: case 11:
newSpreadingFactor = SX1278_SF_11; newSpreadingFactor = SX127X_SF_11;
break; break;
case SF_12: case 12:
newSpreadingFactor = SX1278_SF_12; newSpreadingFactor = SX127X_SF_12;
break; break;
default: default:
return(ERR_INVALID_SPREADING_FACTOR); return(ERR_INVALID_SPREADING_FACTOR);
} }
switch(cr) { switch(cr) {
case CR_4_5: case 5:
newCodingRate = SX1278_CR_4_5; newCodingRate = SX1278_CR_4_5;
break; break;
case CR_4_6: case 6:
newCodingRate = SX1278_CR_4_6; newCodingRate = SX1278_CR_4_6;
break; break;
case CR_4_7: case 7:
newCodingRate = SX1278_CR_4_7; newCodingRate = SX1278_CR_4_7;
break; break;
case CR_4_8: case 8:
newCodingRate = SX1278_CR_4_8; newCodingRate = SX1278_CR_4_8;
break; break;
default: default:
return(ERR_INVALID_CODING_RATE); return(ERR_INVALID_CODING_RATE);
} }
// set mode to SLEEP if((freq < 137.0) || (freq > 525.0)) {
status = setMode(SX1278_SLEEP); return(ERR_INVALID_FREQUENCY);
}
// execute common part
status = SX1278::configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// set LoRa mode // configuration successful, save the new settings
status = _mod->SPIsetRegValue(SX1278_REG_OP_MODE, SX1278_LORA, 7, 7); _bw = bw;
if(status != ERR_NONE) { _sf = sf;
return(status); _cr = cr;
} _freq = freq;
// set carrier frequency return(ERR_NONE);
status = _mod->SPIsetRegValue(SX1278_REG_FRF_MSB, SX1278_FRF_MSB); }
status = _mod->SPIsetRegValue(SX1278_REG_FRF_MID, SX1278_FRF_MID);
status = _mod->SPIsetRegValue(SX1278_REG_FRF_LSB, SX1278_FRF_LSB); uint8_t SX1278::configCommon(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
// configure common registers
uint8_t status = SX127x::config(bw, sf, cr, freq, syncWord);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// output power configuration // output power configuration
status = _mod->SPIsetRegValue(SX1278_REG_PA_CONFIG, SX1278_PA_SELECT_BOOST | SX1278_MAX_POWER | SX1278_OUTPUT_POWER); status = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_MAX_POWER, 6, 4);
status = _mod->SPIsetRegValue(SX1278_REG_OCP, SX1278_OCP_ON | SX1278_OCP_TRIM, 5, 0); status = _mod->SPIsetRegValue(SX1278_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0);
status = _mod->SPIsetRegValue(SX1278_REG_LNA, SX1278_LNA_GAIN_1 | SX1278_LNA_BOOST_HF_ON);
status = _mod->SPIsetRegValue(SX1278_REG_PA_DAC, SX1278_PA_BOOST_ON, 2, 0);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// turn off frequency hopping // enable LNA gain setting by register
status = _mod->SPIsetRegValue(SX1278_REG_HOP_PERIOD, SX1278_HOP_PERIOD_OFF); status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_OFF, 2, 2);
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// basic setting (bw, cr, sf, header mode and CRC) // calculate symbol length and set low datarate optimization, if needed
if(newSpreadingFactor == SX1278_SF_6) { uint16_t base = 1;
status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_2, SX1278_SF_6 | SX1278_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_OFF, 7, 2); float symbolLength = (float)(base << _sf) / (float)_bw;
status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_1, newBandwidth | newCodingRate | SX1278_HEADER_IMPL_MODE); if(symbolLength >= 0.016) {
status = _mod->SPIsetRegValue(SX1278_REG_DETECT_OPTIMIZE, SX1278_DETECT_OPTIMIZE_SF_6, 2, 0); status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 0, 0);
status = _mod->SPIsetRegValue(SX1278_REG_DETECTION_THRESHOLD, SX1278_DETECTION_THRESHOLD_SF_6);
} else { } else {
status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_2, newSpreadingFactor | SX1278_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_ON, 7, 2); status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_OFF, 0, 0);
status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_1, newBandwidth | newCodingRate | SX1278_HEADER_EXPL_MODE);
status = _mod->SPIsetRegValue(SX1278_REG_DETECT_OPTIMIZE, SX1278_DETECT_OPTIMIZE_SF_7_12, 2, 0);
status = _mod->SPIsetRegValue(SX1278_REG_DETECTION_THRESHOLD, SX1278_DETECTION_THRESHOLD_SF_7_12);
} }
if(status != ERR_NONE) { if(status != ERR_NONE) {
return(status); return(status);
} }
// set default preamble length // set SF6 optimizations
status = _mod->SPIsetRegValue(SX1278_REG_PREAMBLE_MSB, SX1278_PREAMBLE_LENGTH_MSB); if(sf == SX127X_SF_6) {
status = _mod->SPIsetRegValue(SX1278_REG_PREAMBLE_LSB, SX1278_PREAMBLE_LENGTH_LSB); status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_OFF, 2, 2);
if(status != ERR_NONE) { status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1278_HEADER_IMPL_MODE);
return(status); } else {
status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_ON, 2, 2);
status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1278_HEADER_EXPL_MODE);
} }
// set mode to STANDBY return(status);
status = setMode(SX1278_STANDBY);
if(status != ERR_NONE) {
return(status);
}
// save the new settings
_bw = bw;
_sf = sf;
_cr = cr;
return(ERR_NONE);
}
uint8_t SX1278::setMode(uint8_t mode) {
_mod->SPIsetRegValue(SX1278_REG_OP_MODE, mode, 2, 0);
return(ERR_NONE);
}
void SX1278::clearIRQFlags() {
_mod->SPIwriteRegister(SX1278_REG_IRQ_FLAGS, 0b11111111);
}
int8_t SX1278::getLastPacketRSSI() {
return(-164 + _mod->SPIgetRegValue(SX1278_REG_PKT_RSSI_VALUE));
} }

View file

@ -1,59 +1,12 @@
#ifndef _KITELIB_SX1278_H #ifndef _KITELIB_SX1278_H
#define _KITELIB_SX1278_H #define _KITELIB_SX1278_H
#include <EEPROM.h>
#include "TypeDef.h" #include "TypeDef.h"
#include "Module.h" #include "Module.h"
#include "Packet.h" #include "SX127x.h"
//SX1278 register map //SX1278 specific register map
#define SX1278_REG_FIFO 0x00
#define SX1278_REG_OP_MODE 0x01
#define SX1278_REG_FRF_MSB 0x06
#define SX1278_REG_FRF_MID 0x07
#define SX1278_REG_FRF_LSB 0x08
#define SX1278_REG_PA_CONFIG 0x09
#define SX1278_REG_PA_RAMP 0x0A
#define SX1278_REG_OCP 0x0B
#define SX1278_REG_LNA 0x0C
#define SX1278_REG_FIFO_ADDR_PTR 0x0D
#define SX1278_REG_FIFO_TX_BASE_ADDR 0x0E
#define SX1278_REG_FIFO_RX_BASE_ADDR 0x0F
#define SX1278_REG_FIFO_RX_CURRENT_ADDR 0x10
#define SX1278_REG_IRQ_FLAGS_MASK 0x11
#define SX1278_REG_IRQ_FLAGS 0x12
#define SX1278_REG_RX_NB_BYTES 0x13
#define SX1278_REG_RX_HEADER_CNT_VALUE_MSB 0x14
#define SX1278_REG_RX_HEADER_CNT_VALUE_LSB 0x15
#define SX1278_REG_RX_PACKET_CNT_VALUE_MSB 0x16
#define SX1278_REG_RX_PACKET_CNT_VALUE_LSB 0x17
#define SX1278_REG_MODEM_STAT 0x18
#define SX1278_REG_PKT_SNR_VALUE 0x19
#define SX1278_REG_PKT_RSSI_VALUE 0x1A
#define SX1278_REG_RSSI_VALUE 0x1B
#define SX1278_REG_HOP_CHANNEL 0x1C
#define SX1278_REG_MODEM_CONFIG_1 0x1D
#define SX1278_REG_MODEM_CONFIG_2 0x1E
#define SX1278_REG_SYMB_TIMEOUT_LSB 0x1F
#define SX1278_REG_PREAMBLE_MSB 0x20
#define SX1278_REG_PREAMBLE_LSB 0x21
#define SX1278_REG_PAYLOAD_LENGTH 0x22
#define SX1278_REG_MAX_PAYLOAD_LENGTH 0x23
#define SX1278_REG_HOP_PERIOD 0x24
#define SX1278_REG_FIFO_RX_BYTE_ADDR 0x25
#define SX1278_REG_MODEM_CONFIG_3 0x26 #define SX1278_REG_MODEM_CONFIG_3 0x26
#define SX1278_REG_FEI_MSB 0x28
#define SX1278_REG_FEI_MID 0x29
#define SX1278_REG_FEI_LSB 0x2A
#define SX1278_REG_RSSI_WIDEBAND 0x2C
#define SX1278_REG_DETECT_OPTIMIZE 0x31
#define SX1278_REG_INVERT_IQ 0x33
#define SX1278_REG_DETECTION_THRESHOLD 0x37
#define SX1278_REG_SYNC_WORD 0x39
#define SX1278_REG_DIO_MAPPING_1 0x40
#define SX1278_REG_DIO_MAPPING_2 0x41
#define SX1278_REG_VERSION 0x42
#define SX1278_REG_TCXO 0x4B #define SX1278_REG_TCXO 0x4B
#define SX1278_REG_PA_DAC 0x4D #define SX1278_REG_PA_DAC 0x4D
#define SX1278_REG_FORMER_TEMP 0x5D #define SX1278_REG_FORMER_TEMP 0x5D
@ -65,20 +18,8 @@
//SX1278 LoRa modem settings //SX1278 LoRa modem settings
//SX1278_REG_OP_MODE MSB LSB DESCRIPTION //SX1278_REG_OP_MODE MSB LSB DESCRIPTION
#define SX1278_FSK_OOK 0b00000000 // 7 7 FSK/OOK mode
#define SX1278_LORA 0b10000000 // 7 7 LoRa mode
#define SX1278_ACCESS_SHARED_REG_OFF 0b00000000 // 6 6 access LoRa registers (0x0D:0x3F) in LoRa mode
#define SX1278_ACCESS_SHARED_REG_ON 0b01000000 // 6 6 access FSK registers (0x0D:0x3F) in LoRa mode
#define SX1278_HIGH_FREQ 0b00000000 // 3 3 access HF test registers #define SX1278_HIGH_FREQ 0b00000000 // 3 3 access HF test registers
#define SX1278_LOW_FREQ 0b00001000 // 3 3 access LF test registers #define SX1278_LOW_FREQ 0b00001000 // 3 3 access LF test registers
#define SX1278_SLEEP 0b00000000 // 2 0 sleep
#define SX1278_STANDBY 0b00000001 // 2 0 standby
#define SX1278_FSTX 0b00000010 // 2 0 frequency synthesis TX
#define SX1278_TX 0b00000011 // 2 0 transmit
#define SX1278_FSRX 0b00000100 // 2 0 frequency synthesis RX
#define SX1278_RXCONTINUOUS 0b00000101 // 2 0 receive continuous
#define SX1278_RXSINGLE 0b00000110 // 2 0 receive single
#define SX1278_CAD 0b00000111 // 2 0 channel activity detection
//SX1278_REG_FRF_MSB + REG_FRF_MID + REG_FRF_LSB //SX1278_REG_FRF_MSB + REG_FRF_MID + REG_FRF_LSB
#define SX1278_FRF_MSB 0x6C // 7 0 carrier frequency setting: f_RF = (F(XOSC) * FRF)/2^19 #define SX1278_FRF_MSB 0x6C // 7 0 carrier frequency setting: f_RF = (F(XOSC) * FRF)/2^19
@ -86,28 +27,10 @@
#define SX1278_FRF_LSB 0x00 // 7 0 FRF = 3 byte value of FRF registers #define SX1278_FRF_LSB 0x00 // 7 0 FRF = 3 byte value of FRF registers
//SX1278_REG_PA_CONFIG //SX1278_REG_PA_CONFIG
#define SX1278_PA_SELECT_RFO 0b00000000 // 7 7 RFO pin output, power limited to +14 dBm
#define SX1278_PA_SELECT_BOOST 0b10000000 // 7 7 PA_BOOST pin output, power limited to +20 dBm
#define SX1278_MAX_POWER 0b01110000 // 6 4 max power: P_max = 10.8 + 0.6*MAX_POWER [dBm]; P_max(MAX_POWER = 0b111) = 15 dBm #define SX1278_MAX_POWER 0b01110000 // 6 4 max power: P_max = 10.8 + 0.6*MAX_POWER [dBm]; P_max(MAX_POWER = 0b111) = 15 dBm
#define SX1278_OUTPUT_POWER 0b00001111 // 3 0 output power: P_out = 17 - (15 - OUTPUT_POWER) [dBm] for PA_SELECT_BOOST
//SX1278_REG_OCP
#define SX1278_OCP_OFF 0b00000000 // 5 5 PA overload current protection disabled
#define SX1278_OCP_ON 0b00100000 // 5 5 PA overload current protection enabled
#define SX1278_OCP_TRIM 0b00001011 // 4 0 OCP current: I_max(OCP_TRIM = 0b1011) = 100 mA
//SX1278_REG_LNA //SX1278_REG_LNA
#define SX1278_LNA_GAIN_0 0b00000000 // 7 5 LNA gain setting: not used
#define SX1278_LNA_GAIN_1 0b00100000 // 7 5 max gain
#define SX1278_LNA_GAIN_2 0b01000000 // 7 5 .
#define SX1278_LNA_GAIN_3 0b01100000 // 7 5 .
#define SX1278_LNA_GAIN_4 0b10000000 // 7 5 .
#define SX1278_LNA_GAIN_5 0b10100000 // 7 5 .
#define SX1278_LNA_GAIN_6 0b11000000 // 7 5 min gain
#define SX1278_LNA_GAIN_7 0b11100000 // 7 5 not used
#define SX1278_LNA_BOOST_LF_OFF 0b00000000 // 4 3 default LNA current #define SX1278_LNA_BOOST_LF_OFF 0b00000000 // 4 3 default LNA current
#define SX1278_LNA_BOOST_HF_OFF 0b00000000 // 1 0 default LNA current
#define SX1278_LNA_BOOST_HF_ON 0b00000011 // 1 0 150% LNA current
//SX1278_REG_MODEM_CONFIG_1 //SX1278_REG_MODEM_CONFIG_1
#define SX1278_BW_7_80_KHZ 0b00000000 // 7 4 bandwidth: 7.80 kHz #define SX1278_BW_7_80_KHZ 0b00000000 // 7 4 bandwidth: 7.80 kHz
@ -128,25 +51,8 @@
#define SX1278_HEADER_IMPL_MODE 0b00000001 // 0 0 implicit header mode #define SX1278_HEADER_IMPL_MODE 0b00000001 // 0 0 implicit header mode
//SX1278_REG_MODEM_CONFIG_2 //SX1278_REG_MODEM_CONFIG_2
#define SX1278_SF_6 0b01100000 // 7 4 spreading factor: 64 chips/bit
#define SX1278_SF_7 0b01110000 // 7 4 128 chips/bit
#define SX1278_SF_8 0b10000000 // 7 4 256 chips/bit
#define SX1278_SF_9 0b10010000 // 7 4 512 chips/bit
#define SX1278_SF_10 0b10100000 // 7 4 1024 chips/bit
#define SX1278_SF_11 0b10110000 // 7 4 2048 chips/bit
#define SX1278_SF_12 0b11000000 // 7 4 4096 chips/bit
#define SX1278_TX_MODE_SINGLE 0b00000000 // 3 3 single TX
#define SX1278_TX_MODE_CONT 0b00001000 // 3 3 continuous TX
#define SX1278_RX_CRC_MODE_OFF 0b00000000 // 2 2 CRC disabled #define SX1278_RX_CRC_MODE_OFF 0b00000000 // 2 2 CRC disabled
#define SX1278_RX_CRC_MODE_ON 0b00000100 // 2 2 CRC enabled #define SX1278_RX_CRC_MODE_ON 0b00000100 // 2 2 CRC enabled
#define SX1278_RX_TIMEOUT_MSB 0b00000000 // 1 0
//SX1278_REG_SYMB_TIMEOUT_LSB
#define SX1278_RX_TIMEOUT_LSB 0b01100100 // 7 0 10 bit RX operation timeout
//SX1278_REG_PREAMBLE_MSB + REG_PREAMBLE_LSB
#define SX1278_PREAMBLE_LENGTH_MSB 0b00000000 // 7 0 2 byte preamble length setting: l_P = PREAMBLE_LENGTH + 4.25
#define SX1278_PREAMBLE_LENGTH_LSB 0b00001000 // 7 0 where l_p = preamble length
//SX1278_REG_MODEM_CONFIG_3 //SX1278_REG_MODEM_CONFIG_3
#define SX1278_LOW_DATA_RATE_OPT_OFF 0b00000000 // 3 3 low data rate optimization disabled #define SX1278_LOW_DATA_RATE_OPT_OFF 0b00000000 // 3 3 low data rate optimization disabled
@ -154,89 +60,21 @@
#define SX1278_AGC_AUTO_OFF 0b00000000 // 2 2 LNA gain set by REG_LNA #define SX1278_AGC_AUTO_OFF 0b00000000 // 2 2 LNA gain set by REG_LNA
#define SX1278_AGC_AUTO_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop #define SX1278_AGC_AUTO_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop
//SX1278_REG_DETECT_OPTIMIZE class SX1278: public SX127x {
#define SX1278_DETECT_OPTIMIZE_SF_6 0b00000101 // 2 0 SF6 detection optimization
#define SX1278_DETECT_OPTIMIZE_SF_7_12 0b00000011 // 2 0 SF7 to SF12 detection optimization
//SX1278_REG_DETECTION_THRESHOLD
#define SX1278_DETECTION_THRESHOLD_SF_6 0b00001100 // 7 0 SF6 detection threshold
#define SX1278_DETECTION_THRESHOLD_SF_7_12 0b00001010 // 7 0 SF7 to SF12 detection threshold
//SX1278_REG_PA_DAC
#define SX1278_PA_BOOST_OFF 0b00000100 // 2 0 PA_BOOST disabled
#define SX1278_PA_BOOST_ON 0b00000111 // 2 0 +20 dBm on PA_BOOST when OUTPUT_POWER = 0b1111
//SX1278_REG_HOP_PERIOD
#define SX1278_HOP_PERIOD_OFF 0b00000000 // 7 0 number of periods between frequency hops; 0 = disabled
#define SX1278_HOP_PERIOD_MAX 0b11111111 // 7 0
//SX1278_REG_DIO_MAPPING_1
#define SX1278_DIO0_RX_DONE 0b00000000 // 7 6
#define SX1278_DIO0_TX_DONE 0b01000000 // 7 6
#define SX1278_DIO0_CAD_DONE 0b10000000 // 7 6
#define SX1278_DIO1_RX_TIMEOUT 0b00000000 // 5 4
#define SX1278_DIO1_FHSS_CHANGE_CHANNEL 0b00010000 // 5 4
#define SX1278_DIO1_CAD_DETECTED 0b00100000 // 5 4
//SX1278_REG_IRQ_FLAGS
#define SX1278_CLEAR_IRQ_FLAG_RX_TIMEOUT 0b10000000 // 7 7 timeout
#define SX1278_CLEAR_IRQ_FLAG_RX_DONE 0b01000000 // 6 6 packet reception complete
#define SX1278_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR 0b00100000 // 5 5 payload CRC error
#define SX1278_CLEAR_IRQ_FLAG_VALID_HEADER 0b00010000 // 4 4 valid header received
#define SX1278_CLEAR_IRQ_FLAG_TX_DONE 0b00001000 // 3 3 payload transmission complete
#define SX1278_CLEAR_IRQ_FLAG_CAD_DONE 0b00000100 // 2 2 CAD complete
#define SX1278_CLEAR_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b00000010 // 1 1 FHSS change channel
#define SX1278_CLEAR_IRQ_FLAG_CAD_DETECTED 0b00000001 // 0 0 valid LoRa signal detected during CAD operation
//SX1278_REG_IRQ_FLAGS_MASK
#define SX1278_MASK_IRQ_FLAG_RX_TIMEOUT 0b01111111 // 7 7 timeout
#define SX1278_MASK_IRQ_FLAG_RX_DONE 0b10111111 // 6 6 packet reception complete
#define SX1278_MASK_IRQ_FLAG_PAYLOAD_CRC_ERROR 0b11011111 // 5 5 payload CRC error
#define SX1278_MASK_IRQ_FLAG_VALID_HEADER 0b11101111 // 4 4 valid header received
#define SX1278_MASK_IRQ_FLAG_TX_DONE 0b11110111 // 3 3 payload transmission complete
#define SX1278_MASK_IRQ_FLAG_CAD_DONE 0b11111011 // 2 2 CAD complete
#define SX1278_MASK_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b11111101 // 1 1 FHSS change channel
#define SX1278_MASK_IRQ_FLAG_CAD_DETECTED 0b11111110 // 0 0 valid LoRa signal detected during CAD operation
//SX1278_REG_FIFO_TX_BASE_ADDR
#define SX1278_FIFO_TX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for TX only
//SX1278_REG_FIFO_RX_BASE_ADDR
#define SX1278_FIFO_RX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for RX only
class SX1278 {
public: public:
SX1278(Module* module); SX1278(Module* mod);
float dataRate; uint8_t begin(float freq = 434.0, uint32_t bw = 125000, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, uint16_t addrEeprom = 0);
int8_t lastPacketRSSI;
uint8_t begin(Bandwidth bw = BW_125_00_KHZ, SpreadingFactor sf = SF_9, CodingRate cr = CR_4_7, uint16_t addrEeprom = 0); uint8_t setBandwidth(uint32_t bw);
uint8_t transmit(Packet& pack); uint8_t setSpreadingFactor(uint8_t sf);
uint8_t receive(Packet& pack); uint8_t setCodingRate(uint8_t cr);
uint8_t sleep(); protected:
uint8_t standby(); uint8_t configCommon(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord); // common for SX1276/77/78/79
uint8_t setBandwidth(Bandwidth bw);
uint8_t setSpreadingFactor(SpreadingFactor sf);
uint8_t setCodingRate(CodingRate cr);
private: private:
Module* _mod; uint8_t config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord); // specific to SX1278
Bandwidth _bw;
SpreadingFactor _sf;
CodingRate _cr;
uint16_t _addrEeprom;
uint8_t _address[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void generateLoRaAdress();
uint8_t config(Bandwidth bw, SpreadingFactor sf, CodingRate cr);
uint8_t setMode(uint8_t mode);
void clearIRQFlags();
int8_t getLastPacketRSSI();
}; };
#endif #endif

76
src/modules/SX1279.cpp Normal file
View file

@ -0,0 +1,76 @@
#include "SX1279.h"
SX1279::SX1279(Module* mod) : SX1278(mod) {
}
uint8_t SX1279::config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
uint8_t status = ERR_NONE;
uint8_t newBandwidth, newSpreadingFactor, newCodingRate;
// check the supplied BW, CR and SF values
switch(bw) {
case 125000:
newBandwidth = SX1278_BW_125_00_KHZ;
break;
case 250000:
newBandwidth = SX1278_BW_250_00_KHZ;
break;
case 500000:
newBandwidth = SX1278_BW_500_00_KHZ;
break;
default:
return(ERR_INVALID_BANDWIDTH);
}
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);
}
switch(cr) {
case 5:
newCodingRate = SX1278_CR_4_5;
break;
case 6:
newCodingRate = SX1278_CR_4_6;
break;
case 7:
newCodingRate = SX1278_CR_4_7;
break;
case 8:
newCodingRate = SX1278_CR_4_8;
break;
default:
return(ERR_INVALID_CODING_RATE);
}
if((freq < 137.0) || (freq > 960.0)) {
return(ERR_INVALID_FREQUENCY);
}
// execute common part
status = configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord);
if(status != ERR_NONE) {
return(status);
}
// configuration successful, save the new settings
_bw = bw;
_sf = sf;
_cr = cr;
return(ERR_NONE);
}

15
src/modules/SX1279.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _KITELIB_SX1279_H
#define _KITELIB_SX1279_H
#include "TypeDef.h"
#include "SX1278.h"
class SX1279: public SX1278 {
public:
SX1279(Module* mod);
private:
uint8_t config(uint32_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord);
};
#endif

327
src/modules/SX127x.cpp Normal file
View file

@ -0,0 +1,327 @@
#include "SX127x.h"
SX127x::SX127x(Module* mod) {
_mod = mod;
}
uint8_t SX127x::begin(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t addrEeprom) {
// copy LoRa modem settings
_freq = freq;
_bw = bw;
_sf = sf;
_cr = cr;
_syncWord = syncWord;
// ESP32-only: initialize EEPROM
#ifdef ESP32
if(!EEPROM.begin(9)) {
DEBUG_PRINTLN_STR("Unable to initialize EEPROM");
return(ERR_EEPROM_NOT_INITIALIZED);
}
#endif
// copy EEPROM start address
_addrEeprom = addrEeprom;
// check if the node has address
bool hasAddress = false;
for(uint16_t i = 0; i < 8; i++) {
if(EEPROM.read(_addrEeprom + i) != 255) {
hasAddress = true;
break;
}
}
// generate new address
if(!hasAddress) {
randomSeed(analogRead(5));
generateNodeAdress();
}
DEBUG_PRINTLN_STR("LoRa node address string: ");
for(uint8_t i = 0; i < 8; i++) {
_address[i] = EEPROM.read(i);
#ifdef KITELIB_DEBUG
Serial.print(_address[i], HEX);
if(i < 7) {
Serial.print(":");
} else {
Serial.println();
}
#endif
}
// set module properties
_mod->init(USE_SPI, INT_BOTH);
// try to find the SX127x chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
uint8_t version = _mod->SPIreadRegister(SX127X_REG_VERSION);
if(version == 0x12) {
flagFound = true;
} else {
#ifdef KITELIB_DEBUG
Serial.print("SX127x not found! (");
Serial.print(i + 1);
Serial.print(" of 10 tries) SX127X_REG_VERSION == ");
char buffHex[5];
sprintf(buffHex, "0x%02X", version);
Serial.print(buffHex);
Serial.println();
#endif
delay(1000);
i++;
}
}
if(!flagFound) {
DEBUG_PRINTLN_STR("No SX127x found!");
SPI.end();
return(ERR_CHIP_NOT_FOUND);
} else {
DEBUG_PRINTLN_STR("Found SX127x! (match by SX127X_REG_VERSION == 0x12)");
}
return(ERR_NONE);
}
uint8_t SX127x::transmit(Packet& pack) {
// check packet length
if(pack.length >= 256) {
return(ERR_PACKET_TOO_LONG);
}
// calculate timeout
uint16_t base = 1;
float symbolLength = (float)(base << _sf) / (float)_bw;
float de = 0;
if(symbolLength >= 0.016) {
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)pack.length - 4.0 * (float)_sf + 28.0 + 16.0 * crc - 20.0 * ih)/(4.0 * (float)_sf - 8.0 * de)) * (float)_cr, 0);
uint32_t timeout = ceil(symbolLength * (n_pre + n_pay + 4.25) * 1000.0);
// write packet to FIFO
setMode(SX127X_STANDBY);
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_TX_DONE, 7, 6);
clearIRQFlags();
_mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH, pack.length);
_mod->SPIsetRegValue(SX127X_REG_FIFO_TX_BASE_ADDR, SX127X_FIFO_TX_BASE_ADDR_MAX);
_mod->SPIsetRegValue(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDR_MAX);
_mod->SPIwriteRegisterBurstStr(SX127X_REG_FIFO, pack.source, 8);
_mod->SPIwriteRegisterBurstStr(SX127X_REG_FIFO, pack.destination, 8);
_mod->SPIwriteRegisterBurstStr(SX127X_REG_FIFO, pack.data, pack.length - 16);
// start transmission
setMode(SX127X_TX);
// check for timeout
uint32_t start = millis();
while(!_mod->getInt0State()) {
if(millis() - start > timeout) {
clearIRQFlags();
return(ERR_TX_TIMEOUT);
}
}
clearIRQFlags();
return(ERR_NONE);
}
uint8_t SX127x::receive(Packet& pack) {
// prepare for packet reception
setMode(SX127X_STANDBY);
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_RX_DONE | SX127X_DIO1_RX_TIMEOUT, 7, 4);
clearIRQFlags();
_mod->SPIsetRegValue(SX127X_REG_FIFO_RX_BASE_ADDR, SX127X_FIFO_RX_BASE_ADDR_MAX);
_mod->SPIsetRegValue(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_RX_BASE_ADDR_MAX);
// start receiving
setMode(SX127X_RXSINGLE);
uint32_t start = millis();
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
clearIRQFlags();
return(ERR_RX_TIMEOUT);
}
}
uint32_t elapsed = millis() - start;
if(_mod->SPIgetRegValue(SX127X_REG_IRQ_FLAGS, 5, 5) == SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
return(ERR_CRC_MISMATCH);
}
if(_sf != 6) {
pack.length = _mod->SPIgetRegValue(SX127X_REG_RX_NB_BYTES);
}
_mod->SPIreadRegisterBurstStr(SX127X_REG_FIFO, 8, pack.source);
_mod->SPIreadRegisterBurstStr(SX127X_REG_FIFO, 8, pack.destination);
delete[] pack.data;
pack.data = new char[pack.length - 15];
_mod->SPIreadRegisterBurstStr(SX127X_REG_FIFO, pack.length - 16, pack.data);
pack.data[pack.length - 16] = 0;
dataRate = (pack.length*8.0)/((float)elapsed/1000.0);
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;
clearIRQFlags();
return(ERR_NONE);
}
uint8_t SX127x::scanChannel() {
setMode(SX127X_STANDBY);
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
clearIRQFlags();
setMode(SX127X_CAD);
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
clearIRQFlags();
return(PREAMBLE_DETECTED);
}
}
clearIRQFlags();
return(CHANNEL_FREE);
}
uint8_t SX127x::sleep() {
return(setMode(SX127X_SLEEP));
}
uint8_t SX127x::standby() {
return(setMode(SX127X_STANDBY));
}
uint8_t SX127x::setFrequency(float freq) {
uint8_t state = config(_bw, _sf, _cr, freq, _syncWord);
if(state == ERR_NONE) {
_freq = freq;
}
return(state);
}
uint8_t SX127x::setSyncWord(uint8_t syncWord) {
uint8_t state = config(_bw, _sf, _cr, _freq, syncWord);
if(state == ERR_NONE) {
_syncWord = syncWord;
}
return(state);
}
uint8_t SX127x::setOutputPower(int8_t power) {
setMode(SX127X_STANDBY);
if((power < 2) || (power > 17)) {
return(ERR_INVALID_OUTPUT_POWER);
}
return(_mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, power - 2, 3, 0));
}
uint8_t SX127x::config(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord) {
uint8_t status = ERR_NONE;
// set mode to SLEEP
status = setMode(SX127X_SLEEP);
if(status != ERR_NONE) {
return(status);
}
// set LoRa mode
status = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX127X_LORA, 7, 7);
if(status != ERR_NONE) {
return(status);
}
// set carrier frequency
uint32_t base = 1;
uint32_t FRF = (freq * (base << 19)) / 32.0;
status = _mod->SPIsetRegValue(SX127X_REG_FRF_MSB, (FRF & 0xFF0000) >> 16);
status = _mod->SPIsetRegValue(SX127X_REG_FRF_MID, (FRF & 0x00FF00) >> 8);
status = _mod->SPIsetRegValue(SX127X_REG_FRF_LSB, FRF & 0x0000FF);
if(status != ERR_NONE) {
return(status);
}
// output power configuration
status = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST | SX127X_OUTPUT_POWER);
status = _mod->SPIsetRegValue(SX127X_REG_OCP, SX127X_OCP_ON | SX127X_OCP_TRIM, 5, 0);
status = _mod->SPIsetRegValue(SX127X_REG_LNA, SX127X_LNA_GAIN_1 | SX127X_LNA_BOOST_ON);
if(status != ERR_NONE) {
return(status);
}
// turn off frequency hopping
status = _mod->SPIsetRegValue(SX127X_REG_HOP_PERIOD, SX127X_HOP_PERIOD_OFF);
if(status != ERR_NONE) {
return(status);
}
// basic setting (bw, cr, sf, header mode and CRC)
if(sf == SX127X_SF_6) {
status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE, 7, 3);
status = _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
status = _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6);
} else {
status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, sf | SX127X_TX_MODE_SINGLE, 7, 3);
status = _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
status = _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12);
}
if(status != ERR_NONE) {
return(status);
}
// set the sync word
status = _mod->SPIsetRegValue(SX127X_REG_SYNC_WORD, syncWord);
if(status != ERR_NONE) {
return(status);
}
// set default preamble length
status = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB, SX127X_PREAMBLE_LENGTH_MSB);
status = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB, SX127X_PREAMBLE_LENGTH_LSB);
if(status != ERR_NONE) {
return(status);
}
// set mode to STANDBY
status = setMode(SX127X_STANDBY);
return(status);
}
void SX127x::generateNodeAdress() {
for(uint8_t i = _addrEeprom; i < (_addrEeprom + 8); i++) {
EEPROM.write(i, (uint8_t)random(0, 256));
}
}
uint8_t SX127x::setMode(uint8_t mode) {
_mod->SPIsetRegValue(SX127X_REG_OP_MODE, mode, 2, 0);
return(ERR_NONE);
}
void SX127x::clearIRQFlags() {
_mod->SPIwriteRegister(SX127X_REG_IRQ_FLAGS, 0b11111111);
}

211
src/modules/SX127x.h Normal file
View file

@ -0,0 +1,211 @@
#ifndef _KITELIB_SX127X_H
#define _KITELIB_SX127X_H
#include <EEPROM.h>
#include "TypeDef.h"
#include "Module.h"
#include "Packet.h"
// SX127x series common registers
#define SX127X_REG_FIFO 0x00
#define SX127X_REG_OP_MODE 0x01
#define SX127X_REG_FRF_MSB 0x06
#define SX127X_REG_FRF_MID 0x07
#define SX127X_REG_FRF_LSB 0x08
#define SX127X_REG_PA_CONFIG 0x09
#define SX127X_REG_PA_RAMP 0x0A
#define SX127X_REG_OCP 0x0B
#define SX127X_REG_LNA 0x0C
#define SX127X_REG_FIFO_ADDR_PTR 0x0D
#define SX127X_REG_FIFO_TX_BASE_ADDR 0x0E
#define SX127X_REG_FIFO_RX_BASE_ADDR 0x0F
#define SX127X_REG_FIFO_RX_CURRENT_ADDR 0x10
#define SX127X_REG_IRQ_FLAGS_MASK 0x11
#define SX127X_REG_IRQ_FLAGS 0x12
#define SX127X_REG_RX_NB_BYTES 0x13
#define SX127X_REG_RX_HEADER_CNT_VALUE_MSB 0x14
#define SX127X_REG_RX_HEADER_CNT_VALUE_LSB 0x15
#define SX127X_REG_RX_PACKET_CNT_VALUE_MSB 0x16
#define SX127X_REG_RX_PACKET_CNT_VALUE_LSB 0x17
#define SX127X_REG_MODEM_STAT 0x18
#define SX127X_REG_PKT_SNR_VALUE 0x19
#define SX127X_REG_PKT_RSSI_VALUE 0x1A
#define SX127X_REG_RSSI_VALUE 0x1B
#define SX127X_REG_HOP_CHANNEL 0x1C
#define SX127X_REG_MODEM_CONFIG_1 0x1D
#define SX127X_REG_MODEM_CONFIG_2 0x1E
#define SX127X_REG_SYMB_TIMEOUT_LSB 0x1F
#define SX127X_REG_PREAMBLE_MSB 0x20
#define SX127X_REG_PREAMBLE_LSB 0x21
#define SX127X_REG_PAYLOAD_LENGTH 0x22
#define SX127X_REG_MAX_PAYLOAD_LENGTH 0x23
#define SX127X_REG_HOP_PERIOD 0x24
#define SX127X_REG_FIFO_RX_BYTE_ADDR 0x25
#define SX127X_REG_FEI_MSB 0x28
#define SX127X_REG_FEI_MID 0x29
#define SX127X_REG_FEI_LSB 0x2A
#define SX127X_REG_RSSI_WIDEBAND 0x2C
#define SX127X_REG_DETECT_OPTIMIZE 0x31
#define SX127X_REG_INVERT_IQ 0x33
#define SX127X_REG_DETECTION_THRESHOLD 0x37
#define SX127X_REG_SYNC_WORD 0x39
#define SX127X_REG_DIO_MAPPING_1 0x40
#define SX127X_REG_DIO_MAPPING_2 0x41
#define SX127X_REG_VERSION 0x42
// SX127x common modem settings
// SX127X_REG_OP_MODE MSB LSB DESCRIPTION
#define SX127X_FSK_OOK 0b00000000 // 7 7 FSK/OOK mode
#define SX127X_LORA 0b10000000 // 7 7 LoRa mode
#define SX127X_ACCESS_SHARED_REG_OFF 0b00000000 // 6 6 access LoRa registers (0x0D:0x3F) in LoRa mode
#define SX127X_ACCESS_SHARED_REG_ON 0b01000000 // 6 6 access FSK registers (0x0D:0x3F) in LoRa mode
#define SX127X_SLEEP 0b00000000 // 2 0 sleep
#define SX127X_STANDBY 0b00000001 // 2 0 standby
#define SX127X_FSTX 0b00000010 // 2 0 frequency synthesis TX
#define SX127X_TX 0b00000011 // 2 0 transmit
#define SX127X_FSRX 0b00000100 // 2 0 frequency synthesis RX
#define SX127X_RXCONTINUOUS 0b00000101 // 2 0 receive continuous
#define SX127X_RXSINGLE 0b00000110 // 2 0 receive single
#define SX127X_CAD 0b00000111 // 2 0 channel activity detection
// SX127X_REG_PA_CONFIG
#define SX127X_PA_SELECT_RFO 0b00000000 // 7 7 RFO pin output, power limited to +14 dBm
#define SX127X_PA_SELECT_BOOST 0b10000000 // 7 7 PA_BOOST pin output, power limited to +20 dBm
#define SX127X_OUTPUT_POWER 0b00001111 // 3 0 output power: P_out = 2 + OUTPUT_POWER [dBm] for PA_SELECT_BOOST
// P_out = -1 + OUTPUT_POWER [dBm] for PA_SELECT_RFO
// SX127X_REG_OCP
#define SX127X_OCP_OFF 0b00000000 // 5 5 PA overload current protection disabled
#define SX127X_OCP_ON 0b00100000 // 5 5 PA overload current protection enabled
#define SX127X_OCP_TRIM 0b00001011 // 4 0 OCP current: I_max(OCP_TRIM = 0b1011) = 100 mA
// SX127X_REG_LNA
#define SX127X_LNA_GAIN_0 0b00000000 // 7 5 LNA gain setting: not used
#define SX127X_LNA_GAIN_1 0b00100000 // 7 5 max gain
#define SX127X_LNA_GAIN_2 0b01000000 // 7 5 .
#define SX127X_LNA_GAIN_3 0b01100000 // 7 5 .
#define SX127X_LNA_GAIN_4 0b10000000 // 7 5 .
#define SX127X_LNA_GAIN_5 0b10100000 // 7 5 .
#define SX127X_LNA_GAIN_6 0b11000000 // 7 5 min gain
#define SX127X_LNA_GAIN_7 0b11100000 // 7 5 not used
#define SX127X_LNA_BOOST_OFF 0b00000000 // 1 0 default LNA current
#define SX127X_LNA_BOOST_ON 0b00000011 // 1 0 150% LNA current
// SX127X_REG_MODEM_CONFIG_2
#define SX127X_SF_6 0b01100000 // 7 4 spreading factor: 64 chips/bit
#define SX127X_SF_7 0b01110000 // 7 4 128 chips/bit
#define SX127X_SF_8 0b10000000 // 7 4 256 chips/bit
#define SX127X_SF_9 0b10010000 // 7 4 512 chips/bit
#define SX127X_SF_10 0b10100000 // 7 4 1024 chips/bit
#define SX127X_SF_11 0b10110000 // 7 4 2048 chips/bit
#define SX127X_SF_12 0b11000000 // 7 4 4096 chips/bit
#define SX127X_TX_MODE_SINGLE 0b00000000 // 3 3 single TX
#define SX127X_TX_MODE_CONT 0b00001000 // 3 3 continuous TX
#define SX127X_RX_TIMEOUT_MSB 0b00000000 // 1 0
// SX127X_REG_SYMB_TIMEOUT_LSB
#define SX127X_RX_TIMEOUT_LSB 0b01100100 // 7 0 10 bit RX operation timeout
// SX127X_REG_PREAMBLE_MSB + REG_PREAMBLE_LSB
#define SX127X_PREAMBLE_LENGTH_MSB 0b00000000 // 7 0 2 byte preamble length setting: l_P = PREAMBLE_LENGTH + 4.25
#define SX127X_PREAMBLE_LENGTH_LSB 0b00001000 // 7 0 where l_p = preamble length
// SX127X_REG_DETECT_OPTIMIZE
#define SX127X_DETECT_OPTIMIZE_SF_6 0b00000101 // 2 0 SF6 detection optimization
#define SX127X_DETECT_OPTIMIZE_SF_7_12 0b00000011 // 2 0 SF7 to SF12 detection optimization
// SX127X_REG_DETECTION_THRESHOLD
#define SX127X_DETECTION_THRESHOLD_SF_6 0b00001100 // 7 0 SF6 detection threshold
#define SX127X_DETECTION_THRESHOLD_SF_7_12 0b00001010 // 7 0 SF7 to SF12 detection threshold
// SX127X_REG_PA_DAC
#define SX127X_PA_BOOST_OFF 0b00000100 // 2 0 PA_BOOST disabled
#define SX127X_PA_BOOST_ON 0b00000111 // 2 0 +20 dBm on PA_BOOST when OUTPUT_POWER = 0b1111
// SX127X_REG_HOP_PERIOD
#define SX127X_HOP_PERIOD_OFF 0b00000000 // 7 0 number of periods between frequency hops; 0 = disabled
#define SX127X_HOP_PERIOD_MAX 0b11111111 // 7 0
// SX127X_REG_DIO_MAPPING_1
#define SX127X_DIO0_RX_DONE 0b00000000 // 7 6
#define SX127X_DIO0_TX_DONE 0b01000000 // 7 6
#define SX127X_DIO0_CAD_DONE 0b10000000 // 7 6
#define SX127X_DIO1_RX_TIMEOUT 0b00000000 // 5 4
#define SX127X_DIO1_FHSS_CHANGE_CHANNEL 0b00010000 // 5 4
#define SX127X_DIO1_CAD_DETECTED 0b00100000 // 5 4
// SX127X_REG_IRQ_FLAGS
#define SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT 0b10000000 // 7 7 timeout
#define SX127X_CLEAR_IRQ_FLAG_RX_DONE 0b01000000 // 6 6 packet reception complete
#define SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR 0b00100000 // 5 5 payload CRC error
#define SX127X_CLEAR_IRQ_FLAG_VALID_HEADER 0b00010000 // 4 4 valid header received
#define SX127X_CLEAR_IRQ_FLAG_TX_DONE 0b00001000 // 3 3 payload transmission complete
#define SX127X_CLEAR_IRQ_FLAG_CAD_DONE 0b00000100 // 2 2 CAD complete
#define SX127X_CLEAR_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b00000010 // 1 1 FHSS change channel
#define SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED 0b00000001 // 0 0 valid LoRa signal detected during CAD operation
// SX127X_REG_IRQ_FLAGS_MASK
#define SX127X_MASK_IRQ_FLAG_RX_TIMEOUT 0b01111111 // 7 7 timeout
#define SX127X_MASK_IRQ_FLAG_RX_DONE 0b10111111 // 6 6 packet reception complete
#define SX127X_MASK_IRQ_FLAG_PAYLOAD_CRC_ERROR 0b11011111 // 5 5 payload CRC error
#define SX127X_MASK_IRQ_FLAG_VALID_HEADER 0b11101111 // 4 4 valid header received
#define SX127X_MASK_IRQ_FLAG_TX_DONE 0b11110111 // 3 3 payload transmission complete
#define SX127X_MASK_IRQ_FLAG_CAD_DONE 0b11111011 // 2 2 CAD complete
#define SX127X_MASK_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b11111101 // 1 1 FHSS change channel
#define SX127X_MASK_IRQ_FLAG_CAD_DETECTED 0b11111110 // 0 0 valid LoRa signal detected during CAD operation
// SX127X_REG_FIFO_TX_BASE_ADDR
#define SX127X_FIFO_TX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for TX only
// SX127X_REG_FIFO_RX_BASE_ADDR
#define SX127X_FIFO_RX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for RX only
// SX127X_REG_SYNC_WORD
#define SX127X_SYNC_WORD 0x12 // 7 0 default LoRa sync word
#define SX127X_SYNC_WORD_LORAWAN 0x34 // 7 0 sync word reserved for LoRaWAN networks
class SX127x {
public:
SX127x(Module* mod);
float dataRate;
int8_t lastPacketRSSI;
float lastPacketSNR;
uint8_t begin(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t addrEeprom);
uint8_t transmit(Packet& pack);
uint8_t receive(Packet& pack);
uint8_t scanChannel();
uint8_t sleep();
uint8_t standby();
uint8_t setFrequency(float freq);
uint8_t setSyncWord(uint8_t syncWord);
uint8_t setOutputPower(int8_t power);
protected:
Module* _mod;
uint32_t _bw;
uint8_t _sf;
uint8_t _cr;
float _freq;
uint8_t _syncWord;
uint8_t tx(char* data, uint8_t length);
uint8_t rxSingle(char* data, uint8_t* length);
uint8_t config(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord);
private:
uint8_t _address[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint16_t _addrEeprom;
void generateNodeAdress();
uint8_t setMode(uint8_t mode);
void clearIRQFlags();
};
#endif