diff --git a/keywords.txt b/keywords.txt index 98cc0a36..32dddce8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -14,7 +14,11 @@ ESP8266 KEYWORD1 HC05 KEYWORD1 RF69 KEYWORD1 SX1272 KEYWORD1 +SX1273 KEYWORD1 +SX1276 KEYWORD1 +SX1277 KEYWORD1 SX1278 KEYWORD1 +SX1279 KEYWORD1 XBee KEYWORD1 Bandwidth KEYWORD1 @@ -39,8 +43,9 @@ getDestinationStr KEYWORD2 setSourceStr KEYWORD2 setDestinationStr KEYWORD2 copyInto KEYWORD2 +setPacketData KEYWORD2 -# SX1278/SX1272 + RF69 +# SX1272/73/76/77/78/79 + RF69 dataRate KEYWORD2 lastPacketRSSI KEYWORD2 begin KEYWORD2 @@ -51,6 +56,9 @@ standby KEYWORD2 setBandwidth KEYWORD2 setSpreadingFactor KEYWORD2 setCodingRate KEYWORD2 +setFrequency KEYWORD2 +setSyncWord KEYWORD2 +setOutputPower KEYWORD2 # ESP8266 join KEYWORD2 @@ -74,31 +82,9 @@ setPanId KEYWORD2 # 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_UNKNOWN LITERAL1 + ERR_CHIP_NOT_FOUND LITERAL1 ERR_EEPROM_NOT_INITIALIZED LITERAL1 ERR_PACKET_TOO_LONG LITERAL1 @@ -109,10 +95,19 @@ ERR_INVALID_BANDWIDTH LITERAL1 ERR_INVALID_SPREADING_FACTOR LITERAL1 ERR_INVALID_CODING_RATE 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_URL_MALFORMED LITERAL1 ERR_RESPONSE_MALFORMED_AT 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 diff --git a/src/KiteLib.h b/src/KiteLib.h index b4b22e35..63fe30d7 100644 --- a/src/KiteLib.h +++ b/src/KiteLib.h @@ -8,7 +8,11 @@ #include "modules/HC05.h" #include "modules/RF69.h" #include "modules/SX1272.h" +#include "modules/SX1273.h" +#include "modules/SX1276.h" +#include "modules/SX1277.h" #include "modules/SX1278.h" +#include "modules/SX1279.h" #include "modules/XBee.h" #define KITE_CS_A 10 diff --git a/src/Module.cpp b/src/Module.cpp index 00560460..8be34656 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -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 newValue = currentValue & ((0b11111111 << (msb + 1)) & (0b11111111 >> (8 - lsb))); - SPIwriteRegister(reg, newValue | value); + uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb))); + uint8_t newValue = (currentValue & ~mask) | (value & mask); + SPIwriteRegister(reg, newValue); return(ERR_NONE); } diff --git a/src/Packet.cpp b/src/Packet.cpp index 3c461ec2..77b61e27 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -5,174 +5,177 @@ Packet::Packet(void) { getLoRaAddress(src); uint8_t dest[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t dat[240]; + uint8_t* dat; uint8_t len = 0; 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}; getLoRaAddress(src); uint8_t destTmp[8]; 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); } -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}; getLoRaAddress(src); 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]; 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]; 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); } -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); } -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}; getLoRaAddress(src); uint8_t destTmp[8]; 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); } -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}; getLoRaAddress(src); 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]; 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]; 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); } -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); } -void Packet::init(uint8_t src[8], uint8_t dest[8], const char dat[240]) { - for(uint8_t i = 0; i < 8; i++) { - 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, uint8_t* dest, const char* dat) { + init(src, dest, (uint8_t*)dat, strlen(dat)); } -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; - for(uint8_t i = 0; i < 8; i++) { - source[i] = src[i]; - destination[i] = dest[i]; - } + data = new char[len + 1]; + memcpy(data, dat, len + 1); +} - for(uint8_t i = 0; i < length; i++) { - data[i] = dat[i]; +String Packet::getSourceStr() { + 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++) { - src[3*i] = reparseChar(source[i] >> 4); - src[3*i+1] = reparseChar(source[i] & 0x0F); - 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]); + char str[] = {dest[3*i], dest[3*i + 1]}; + destination[i] = strtoul(str, NULL, 16); } } void Packet::copyInto(Packet& pack) { - for(uint8_t i = 0; i < 8; i++) { - pack.source[i] = source[i]; - pack.destination[i] = destination[i]; - } + memcpy(pack.source, source, 8); + memcpy(pack.destination, destination, 8); 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++) { 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); -} diff --git a/src/Packet.h b/src/Packet.h index f4cb1f7c..3df76c4c 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -1,5 +1,5 @@ -#ifndef _LORALIB_PACKET_H -#define _LORALIB_PACKET_H +#ifndef _KITELIB_PACKET_H +#define _KITELIB_PACKET_H #if ARDUINO >= 100 #include "Arduino.h" @@ -12,36 +12,37 @@ class Packet { public: Packet(void); - Packet(const char dest[24], const char dat[240]); - Packet(uint8_t dest[8], const char dat[240]); - Packet(const char src[24], const char dest[24], const char dat[240]); - Packet(uint8_t src[8], uint8_t dest[8], const char dat[240]); + Packet(const char* dest, const char* dat); + Packet(uint8_t* dest, const char* dat); + Packet(const char* src, const char* dest, const char* dat); + Packet(uint8_t* src, uint8_t* dest, const char* dat); - Packet(const char dest[24], uint8_t* dat, uint8_t len); - Packet(uint8_t dest[8], uint8_t* dat, uint8_t len); - Packet(const char src[24], const char dest[24], uint8_t* dat, uint8_t len); - Packet(uint8_t src[8], uint8_t dest[8], uint8_t* dat, uint8_t len); + Packet(const char* dest, uint8_t* dat, uint8_t len); + Packet(uint8_t* dest, uint8_t* dat, uint8_t len); + Packet(const char* src, const char* dest, 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 destination[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - char data[240]; + char* data; uint8_t length = 0; - void getSourceStr(char src[24]); - void getDestinationStr(char dest[24]); + String getSourceStr(); + String getDestinationStr(); - void setSourceStr(const char src[24]); - void setDestinationStr(const char dest[24]); + void setSourceStr(const char* src); + void setDestinationStr(const char* dest); void copyInto(Packet& pack); - private: - void init(uint8_t src[8], uint8_t dest[8], const char dat[240]); - void init(uint8_t src[8], uint8_t dest[8], uint8_t* dat, uint8_t len); - void getLoRaAddress(uint8_t addr[8]); + void setPacketData(char* charArray); + void setPacketData(String str); + void setPacketData(float f, uint8_t decimals = 3); - uint8_t parseByte(char c); - char reparseChar(uint8_t b); + private: + 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 diff --git a/src/TypeDef.h b/src/TypeDef.h index 42059540..b75ca46b 100644 --- a/src/TypeDef.h +++ b/src/TypeDef.h @@ -7,9 +7,9 @@ #include "WProgram.h" #endif -//#define DEBUG +//#define KITELIB_DEBUG -/*#ifdef DEBUG +#ifdef KITELIB_DEBUG #define DEBUG_BEGIN(x) Serial.begin (x) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINT_DEC(x) Serial.print (x, DEC) @@ -17,7 +17,7 @@ #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINT_STR(x) Serial.print (F(x)) #define DEBUG_PRINTLN_STR(x) Serial.println (F(x)) -#else*/ +#else #define DEBUG_BEGIN(x) #define DEBUG_PRINT(x) #define DEBUG_PRINT_DEC(x) @@ -25,58 +25,62 @@ #define DEBUG_PRINTLN(x) #define DEBUG_PRINT_STR(x) #define DEBUG_PRINTLN_STR(x) -//#endif +#endif // Shield configuration -#define USE_SPI 0x00 -#define USE_UART 0x01 -#define USE_I2C 0x02 -#define INT_NONE 0x00 -#define INT_0 0x01 -#define INT_1 0x02 -#define INT_BOTH 0x03 +#define USE_SPI 0x00 +#define USE_UART 0x01 +#define USE_I2C 0x02 +#define INT_NONE 0x00 +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_BOTH 0x03 // UART configuration -#define UART_STOPBIT_1 0x01 -#define UART_STOPBIT_1_5 0x02 -#define UART_STOPBIT_2 0x03 -#define UART_PARITY_NONE 0x00 -#define UART_PARITY_ODD 0x01 -#define UART_PARITY_EVEN 0x02 -#define UART_FLOW_NONE 0x00 -#define UART_FLOW_RTS 0x01 -#define UART_FLOW_CTS 0x02 -#define UART_FLOW_BOTH 0x03 +#define UART_STOPBIT_1 0x01 +#define UART_STOPBIT_1_5 0x02 +#define UART_STOPBIT_2 0x03 +#define UART_PARITY_NONE 0x00 +#define UART_PARITY_ODD 0x01 +#define UART_PARITY_EVEN 0x02 +#define UART_FLOW_NONE 0x00 +#define UART_FLOW_RTS 0x01 +#define UART_FLOW_CTS 0x02 +#define UART_FLOW_BOTH 0x03 -// Common error codes -#define ERR_NONE 0x00 -#define ERR_UNKNOWN 0x63 // maximum error code value is 99, so that it does not interfere with HTTP status codes +// Common status codes +#define ERR_NONE 0x00 +#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 -#define ERR_CHIP_NOT_FOUND 0x01 -#define ERR_EEPROM_NOT_INITIALIZED 0x02 -#define ERR_PACKET_TOO_LONG 0x03 -#define ERR_TX_TIMEOUT 0x04 -#define ERR_RX_TIMEOUT 0x05 -#define ERR_CRC_MISMATCH 0x06 -#define ERR_INVALID_BANDWIDTH 0x07 -#define ERR_INVALID_SPREADING_FACTOR 0x08 -#define ERR_INVALID_CODING_RATE 0x09 -#define ERR_INVALID_BIT_RANGE 0x10 +// SX1278/SX1272/RF69 status codes +#define ERR_CHIP_NOT_FOUND 0x01 +#define ERR_EEPROM_NOT_INITIALIZED 0x02 +#define ERR_PACKET_TOO_LONG 0x03 +#define ERR_TX_TIMEOUT 0x04 +#define ERR_RX_TIMEOUT 0x05 +#define ERR_CRC_MISMATCH 0x06 +#define ERR_INVALID_BANDWIDTH 0x07 +#define ERR_INVALID_SPREADING_FACTOR 0x08 +#define ERR_INVALID_CODING_RATE 0x09 +#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 -#define ERR_AT_FAILED 0x01 -#define ERR_URL_MALFORMED 0x02 -#define ERR_RESPONSE_MALFORMED_AT 0x03 -#define ERR_RESPONSE_MALFORMED 0x04 -#define ERR_MQTT_CONN_VERSION_REJECTED 0x05 -#define ERR_MQTT_CONN_ID_REJECTED 0x06 -#define ERR_MQTT_CONN_SERVER_UNAVAILABLE 0x07 -#define MQTT_CONN_BAD_USERNAME_PASSWORD 0x08 -#define ERR_MQTT_CONN_NOT_AUTHORIZED 0x09 +// ESP8266 status codes +#define ERR_AT_FAILED 0x01 +#define ERR_URL_MALFORMED 0x02 +#define ERR_RESPONSE_MALFORMED_AT 0x03 +#define ERR_RESPONSE_MALFORMED 0x04 +#define ERR_MQTT_CONN_VERSION_REJECTED 0x05 +#define ERR_MQTT_CONN_ID_REJECTED 0x06 +#define ERR_MQTT_CONN_SERVER_UNAVAILABLE 0x07 +#define ERR_MQTT_CONN_BAD_USERNAME_PASSWORD 0x08 +#define ERR_MQTT_CONN_NOT_AUTHORIZED 0x09 -// XBee error codes -#define ERR_CMD_MODE_FAILED 0x02 +// XBee status codes +#define ERR_CMD_MODE_FAILED 0x02 enum Slot {SlotA, SlotB}; diff --git a/src/modules/SX1272.cpp b/src/modules/SX1272.cpp index 0dabeb96..2971951d 100644 --- a/src/modules/SX1272.cpp +++ b/src/modules/SX1272.cpp @@ -1,262 +1,55 @@ #include "SX1272.h" -SX1272::SX1272(Module* module) { - _mod = module; +SX1272::SX1272(Module* mod) : SX127x(mod) { + } -uint8_t SX1272::begin(Bandwidth bw, SpreadingFactor sf, CodingRate cr, uint16_t addrEeprom) { - // copy LoRa modem settings - _bw = bw; - _sf = sf; - _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; - } +uint8_t SX1272::begin(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t addrEeprom) { + uint8_t state = SX127x::begin(freq, bw, sf, cr, syncWord, addrEeprom); + if(state != ERR_NONE) { + return(state); } - // generate new address - 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)); + return(config(freq, bw, sf, cr, syncWord)); } -uint8_t SX1272::transmit(Packet& pack) { - char buffer[256]; - - // 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); +uint8_t SX1272::setBandwidth(uint32_t bw) { + uint8_t state = SX1272::config(bw, _sf, _cr, _freq, _syncWord); if(state == ERR_NONE) { _bw = bw; } return(state); } -uint8_t SX1272::setSpreadingFactor(SpreadingFactor sf) { - uint8_t state = config(_bw, sf, _cr); +uint8_t SX1272::setSpreadingFactor(uint8_t sf) { + uint8_t state = SX1272::config(_bw, sf, _cr, _freq, _syncWord); if(state == ERR_NONE) { _sf = sf; } return(state); } -uint8_t SX1272::setCodingRate(CodingRate cr) { - uint8_t state = config(_bw, _sf, cr); +uint8_t SX1272::setCodingRate(uint8_t cr) { + uint8_t state = SX1272::config(_bw, _sf, cr, _freq, _syncWord); if(state == ERR_NONE) { _cr = cr; } return(state); } -void SX1272::generateLoRaAdress() { - 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 SX1272::config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord) { uint8_t status = ERR_NONE; uint8_t newBandwidth, newSpreadingFactor, newCodingRate; - //check the supplied bw, cr and sf values + // check the supplied BW, CR and SF values switch(bw) { - case BW_125_00_KHZ: + case 125000: newBandwidth = SX1272_BW_125_00_KHZ; break; - case BW_250_00_KHZ: + case 250000: newBandwidth = SX1272_BW_250_00_KHZ; break; - case BW_500_00_KHZ: + case 500000: newBandwidth = SX1272_BW_500_00_KHZ; break; default: @@ -264,130 +57,107 @@ uint8_t SX1272::config(Bandwidth bw, SpreadingFactor sf, CodingRate cr) { } switch(sf) { - case SF_6: - newSpreadingFactor = SX1272_SF_6; + case 6: + newSpreadingFactor = SX127X_SF_6; break; - case SF_7: - newSpreadingFactor = SX1272_SF_7; + case 7: + newSpreadingFactor = SX127X_SF_7; break; - case SF_8: - newSpreadingFactor = SX1272_SF_8; + case 8: + newSpreadingFactor = SX127X_SF_8; break; - case SF_9: - newSpreadingFactor = SX1272_SF_9; + case 9: + newSpreadingFactor = SX127X_SF_9; break; - case SF_10: - newSpreadingFactor = SX1272_SF_10; + case 10: + newSpreadingFactor = SX127X_SF_10; break; - case SF_11: - newSpreadingFactor = SX1272_SF_11; + case 11: + newSpreadingFactor = SX127X_SF_11; break; - case SF_12: - newSpreadingFactor = SX1272_SF_12; + case 12: + newSpreadingFactor = SX127X_SF_12; break; default: return(ERR_INVALID_SPREADING_FACTOR); } switch(cr) { - case CR_4_5: + case 5: newCodingRate = SX1272_CR_4_5; break; - case CR_4_6: + case 6: newCodingRate = SX1272_CR_4_6; break; - case CR_4_7: + case 7: newCodingRate = SX1272_CR_4_7; break; - case CR_4_8: + case 8: newCodingRate = SX1272_CR_4_8; break; default: return(ERR_INVALID_CODING_RATE); } - // set mode to SLEEP - status = setMode(SX1272_SLEEP); + if((freq < 137.0) || (freq > 525.0)) { + return(ERR_INVALID_FREQUENCY); + } + + // execute common part + status = SX1272::configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord); if(status != ERR_NONE) { return(status); } - // set LoRa mode - status = _mod->SPIsetRegValue(SX1272_REG_OP_MODE, SX1272_LORA, 7, 7); - if(status != ERR_NONE) { - return(status); - } + // configuration successful, save the new settings + _bw = bw; + _sf = sf; + _cr = cr; + _freq = freq; - // set carrier frequency - 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); + return(ERR_NONE); +} + +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) { return(status); } // output power configuration - status = _mod->SPIsetRegValue(SX1272_REG_PA_CONFIG, SX1272_PA_SELECT_BOOST | SX1272_OUTPUT_POWER); - 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); + status = _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0); if(status != ERR_NONE) { return(status); } - // turn off frequency hopping - status = _mod->SPIsetRegValue(SX1272_REG_HOP_PERIOD, SX1272_HOP_PERIOD_OFF); + // enable LNA gain setting by register + status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_OFF, 2, 2); if(status != ERR_NONE) { return(status); } - // basic setting (bw, cr, sf, header mode and CRC) - if(newSpreadingFactor == SX1272_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(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); + // set SF6 optimizations + if(sf == SX127X_SF_6) { + status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1272_HEADER_IMPL_MODE | SX1272_RX_CRC_MODE_OFF, 7, 1); } else { - status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_2, newSpreadingFactor | SX1272_TX_MODE_SINGLE | SX1272_RX_CRC_MODE_ON, 7, 2); - 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); + status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1272_HEADER_EXPL_MODE | SX1272_RX_CRC_MODE_ON, 7, 1); } - if(status != ERR_NONE) { return(status); } - // set default preamble length - status = _mod->SPIsetRegValue(SX1272_REG_PREAMBLE_MSB, SX1272_PREAMBLE_LENGTH_MSB); - status = _mod->SPIsetRegValue(SX1272_REG_PREAMBLE_LSB, SX1272_PREAMBLE_LENGTH_LSB); + // calculate symbol length and set low datarate optimization, if needed + uint16_t base = 1; + float symbolLength = (float)(base << _sf) / (float)_bw; + if(symbolLength >= 0.016) { + 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) { return(status); } - // set mode to STANDBY - 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)); + return(status); } diff --git a/src/modules/SX1272.h b/src/modules/SX1272.h index 10cfe6d9..11d6ec6b 100644 --- a/src/modules/SX1272.h +++ b/src/modules/SX1272.h @@ -1,58 +1,11 @@ #ifndef _KITELIB_SX1272_H #define _KITELIB_SX1272_H -#include - #include "TypeDef.h" #include "Module.h" -#include "Packet.h" +#include "SX127x.h" -//SX1272 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 +//SX1272 specific register map #define SX1272_REG_AGC_REF 0x43 #define SX1272_REG_AGC_THRESH_1 0x44 #define SX1272_REG_AGC_THRESH_2 0x45 @@ -66,47 +19,11 @@ #define SX1272_REG_BIT_RATE_FRAC 0x70 //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 #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_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 #define SX1272_BW_125_00_KHZ 0b00000000 // 7 6 bandwidth: 125 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 //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_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop -#define SX1272_RX_TIMEOUT_MSB 0b00000000 // 1 0 -//SX1272_REG_SYMB_TIMEOUT_LSB -#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 { +class SX1272: public SX127x { public: - SX1272(Module* module); + SX1272(Module* mod); - float dataRate; - int8_t lastPacketRSSI; + 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); - uint8_t begin(Bandwidth bw = BW_125_00_KHZ, SpreadingFactor sf = SF_9, CodingRate cr = CR_4_7, uint16_t addrEeprom = 0); - uint8_t transmit(Packet& pack); - uint8_t receive(Packet& pack); - - uint8_t sleep(); - uint8_t standby(); - - uint8_t setBandwidth(Bandwidth bw); - uint8_t setSpreadingFactor(SpreadingFactor sf); - uint8_t setCodingRate(CodingRate cr); + uint8_t setBandwidth(uint32_t bw); + uint8_t setSpreadingFactor(uint8_t sf); + uint8_t setCodingRate(uint8_t cr); + protected: + uint8_t configCommon(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord); // common for SX1272/73 + 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 diff --git a/src/modules/SX1273.cpp b/src/modules/SX1273.cpp new file mode 100644 index 00000000..57f71cce --- /dev/null +++ b/src/modules/SX1273.cpp @@ -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); +} diff --git a/src/modules/SX1273.h b/src/modules/SX1273.h new file mode 100644 index 00000000..d03b246d --- /dev/null +++ b/src/modules/SX1273.h @@ -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 diff --git a/src/modules/SX1276.cpp b/src/modules/SX1276.cpp new file mode 100644 index 00000000..4e76645f --- /dev/null +++ b/src/modules/SX1276.cpp @@ -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); +} diff --git a/src/modules/SX1276.h b/src/modules/SX1276.h new file mode 100644 index 00000000..d8d6a197 --- /dev/null +++ b/src/modules/SX1276.h @@ -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 diff --git a/src/modules/SX1277.cpp b/src/modules/SX1277.cpp new file mode 100644 index 00000000..86ff3e51 --- /dev/null +++ b/src/modules/SX1277.cpp @@ -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); +} diff --git a/src/modules/SX1277.h b/src/modules/SX1277.h new file mode 100644 index 00000000..a97ad783 --- /dev/null +++ b/src/modules/SX1277.h @@ -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 diff --git a/src/modules/SX1278.cpp b/src/modules/SX1278.cpp index ea92e459..204078b7 100644 --- a/src/modules/SX1278.cpp +++ b/src/modules/SX1278.cpp @@ -1,280 +1,76 @@ #include "SX1278.h" -SX1278::SX1278(Module* module) { - _mod = module; +SX1278::SX1278(Module* mod) : SX127x(mod) { + } -uint8_t SX1278::begin(Bandwidth bw, SpreadingFactor sf, CodingRate cr, uint16_t addrEeprom) { - // copy LoRa modem settings - _bw = bw; - _sf = sf; - _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; - } +uint8_t SX1278::begin(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t addrEeprom) { + uint8_t state = SX127x::begin(freq, bw, sf, cr, syncWord, addrEeprom); + if(state != ERR_NONE) { + return(state); } - // generate new address - 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)); + return(config(freq, bw, sf, cr, syncWord)); } -uint8_t SX1278::transmit(Packet& pack) { - char buffer[256]; - - // 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); +uint8_t SX1278::setBandwidth(uint32_t bw) { + uint8_t state = SX1278::config(bw, _sf, _cr, _freq, _syncWord); if(state == ERR_NONE) { _bw = bw; } return(state); } -uint8_t SX1278::setSpreadingFactor(SpreadingFactor sf) { - uint8_t state = config(_bw, sf, _cr); +uint8_t SX1278::setSpreadingFactor(uint8_t sf) { + uint8_t state = SX1278::config(_bw, sf, _cr, _freq, _syncWord); if(state == ERR_NONE) { _sf = sf; } return(state); } -uint8_t SX1278::setCodingRate(CodingRate cr) { - uint8_t state = config(_bw, _sf, cr); +uint8_t SX1278::setCodingRate(uint8_t cr) { + uint8_t state = SX1278::config(_bw, _sf, cr, _freq, _syncWord); if(state == ERR_NONE) { _cr = cr; } return(state); } -void SX1278::generateLoRaAdress() { - 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 SX1278::config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord) { uint8_t status = ERR_NONE; uint8_t newBandwidth, newSpreadingFactor, newCodingRate; - //check the supplied bw, cr and sf values + // check the supplied BW, CR and SF values switch(bw) { - case BW_7_80_KHZ: + case 7800: newBandwidth = SX1278_BW_7_80_KHZ; break; - case BW_10_40_KHZ: + case 10400: newBandwidth = SX1278_BW_10_40_KHZ; break; - case BW_15_60_KHZ: + case 15600: newBandwidth = SX1278_BW_15_60_KHZ; break; - case BW_20_80_KHZ: + case 20800: newBandwidth = SX1278_BW_20_80_KHZ; break; - case BW_31_25_KHZ: + case 31250: newBandwidth = SX1278_BW_31_25_KHZ; break; - case BW_41_70_KHZ: + case 41700: newBandwidth = SX1278_BW_41_70_KHZ; break; - case BW_62_50_KHZ: + case 62500: newBandwidth = SX1278_BW_62_50_KHZ; break; - case BW_125_00_KHZ: + case 125000: newBandwidth = SX1278_BW_125_00_KHZ; break; - case BW_250_00_KHZ: + case 250000: newBandwidth = SX1278_BW_250_00_KHZ; break; - case BW_500_00_KHZ: + case 500000: newBandwidth = SX1278_BW_500_00_KHZ; break; default: @@ -282,130 +78,107 @@ uint8_t SX1278::config(Bandwidth bw, SpreadingFactor sf, CodingRate cr) { } switch(sf) { - case SF_6: - newSpreadingFactor = SX1278_SF_6; + case 6: + newSpreadingFactor = SX127X_SF_6; break; - case SF_7: - newSpreadingFactor = SX1278_SF_7; + case 7: + newSpreadingFactor = SX127X_SF_7; break; - case SF_8: - newSpreadingFactor = SX1278_SF_8; + case 8: + newSpreadingFactor = SX127X_SF_8; break; - case SF_9: - newSpreadingFactor = SX1278_SF_9; + case 9: + newSpreadingFactor = SX127X_SF_9; break; - case SF_10: - newSpreadingFactor = SX1278_SF_10; + case 10: + newSpreadingFactor = SX127X_SF_10; break; - case SF_11: - newSpreadingFactor = SX1278_SF_11; + case 11: + newSpreadingFactor = SX127X_SF_11; break; - case SF_12: - newSpreadingFactor = SX1278_SF_12; + case 12: + newSpreadingFactor = SX127X_SF_12; break; default: return(ERR_INVALID_SPREADING_FACTOR); } switch(cr) { - case CR_4_5: + case 5: newCodingRate = SX1278_CR_4_5; break; - case CR_4_6: + case 6: newCodingRate = SX1278_CR_4_6; break; - case CR_4_7: + case 7: newCodingRate = SX1278_CR_4_7; break; - case CR_4_8: + case 8: newCodingRate = SX1278_CR_4_8; break; default: return(ERR_INVALID_CODING_RATE); } - // set mode to SLEEP - status = setMode(SX1278_SLEEP); + if((freq < 137.0) || (freq > 525.0)) { + return(ERR_INVALID_FREQUENCY); + } + + // execute common part + status = SX1278::configCommon(newBandwidth, newSpreadingFactor, newCodingRate, freq, syncWord); if(status != ERR_NONE) { return(status); } - // set LoRa mode - status = _mod->SPIsetRegValue(SX1278_REG_OP_MODE, SX1278_LORA, 7, 7); - if(status != ERR_NONE) { - return(status); - } + // configuration successful, save the new settings + _bw = bw; + _sf = sf; + _cr = cr; + _freq = freq; - // set carrier frequency - 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); + return(ERR_NONE); +} + +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) { return(status); } // output power configuration - status = _mod->SPIsetRegValue(SX1278_REG_PA_CONFIG, SX1278_PA_SELECT_BOOST | SX1278_MAX_POWER | SX1278_OUTPUT_POWER); - status = _mod->SPIsetRegValue(SX1278_REG_OCP, SX1278_OCP_ON | SX1278_OCP_TRIM, 5, 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); + status = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_MAX_POWER, 6, 4); + status = _mod->SPIsetRegValue(SX1278_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0); if(status != ERR_NONE) { return(status); } - // turn off frequency hopping - status = _mod->SPIsetRegValue(SX1278_REG_HOP_PERIOD, SX1278_HOP_PERIOD_OFF); + // enable LNA gain setting by register + status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_AGC_AUTO_OFF, 2, 2); if(status != ERR_NONE) { return(status); } - // basic setting (bw, cr, sf, header mode and CRC) - if(newSpreadingFactor == SX1278_SF_6) { - status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_2, SX1278_SF_6 | SX1278_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_OFF, 7, 2); - status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_1, newBandwidth | newCodingRate | SX1278_HEADER_IMPL_MODE); - status = _mod->SPIsetRegValue(SX1278_REG_DETECT_OPTIMIZE, SX1278_DETECT_OPTIMIZE_SF_6, 2, 0); - status = _mod->SPIsetRegValue(SX1278_REG_DETECTION_THRESHOLD, SX1278_DETECTION_THRESHOLD_SF_6); + // calculate symbol length and set low datarate optimization, if needed + uint16_t base = 1; + float symbolLength = (float)(base << _sf) / (float)_bw; + if(symbolLength >= 0.016) { + status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 0, 0); } 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_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); + status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_OFF, 0, 0); } - if(status != ERR_NONE) { return(status); } - // set default preamble length - status = _mod->SPIsetRegValue(SX1278_REG_PREAMBLE_MSB, SX1278_PREAMBLE_LENGTH_MSB); - status = _mod->SPIsetRegValue(SX1278_REG_PREAMBLE_LSB, SX1278_PREAMBLE_LENGTH_LSB); - if(status != ERR_NONE) { - return(status); + // set SF6 optimizations + if(sf == SX127X_SF_6) { + status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_OFF, 2, 2); + status = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, bw | cr | SX1278_HEADER_IMPL_MODE); + } 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 - 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)); + return(status); } diff --git a/src/modules/SX1278.h b/src/modules/SX1278.h index 44d343c8..ca9a0608 100644 --- a/src/modules/SX1278.h +++ b/src/modules/SX1278.h @@ -1,59 +1,12 @@ #ifndef _KITELIB_SX1278_H #define _KITELIB_SX1278_H -#include - #include "TypeDef.h" #include "Module.h" -#include "Packet.h" +#include "SX127x.h" -//SX1278 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 +//SX1278 specific register map #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_PA_DAC 0x4D #define SX1278_REG_FORMER_TEMP 0x5D @@ -65,20 +18,8 @@ //SX1278 LoRa modem settings //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_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 #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 //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_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 -#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_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 #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 //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_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 #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_ON 0b00000100 // 2 2 LNA gain set by internal AGC loop -//SX1278_REG_DETECT_OPTIMIZE -#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 { +class SX1278: public SX127x { public: - SX1278(Module* module); + SX1278(Module* mod); - float dataRate; - int8_t lastPacketRSSI; + 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); - uint8_t begin(Bandwidth bw = BW_125_00_KHZ, SpreadingFactor sf = SF_9, CodingRate cr = CR_4_7, uint16_t addrEeprom = 0); - uint8_t transmit(Packet& pack); - uint8_t receive(Packet& pack); - - uint8_t sleep(); - uint8_t standby(); - - uint8_t setBandwidth(Bandwidth bw); - uint8_t setSpreadingFactor(SpreadingFactor sf); - uint8_t setCodingRate(CodingRate cr); + uint8_t setBandwidth(uint32_t bw); + uint8_t setSpreadingFactor(uint8_t sf); + uint8_t setCodingRate(uint8_t cr); + + protected: + uint8_t configCommon(uint8_t bw, uint8_t sf, uint8_t cr, float freq, uint8_t syncWord); // common for SX1276/77/78/79 private: - Module* _mod; - - 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(); + uint8_t config(float freq, uint32_t bw, uint8_t sf, uint8_t cr, uint8_t syncWord); // specific to SX1278 }; #endif diff --git a/src/modules/SX1279.cpp b/src/modules/SX1279.cpp new file mode 100644 index 00000000..745be1dc --- /dev/null +++ b/src/modules/SX1279.cpp @@ -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); +} diff --git a/src/modules/SX1279.h b/src/modules/SX1279.h new file mode 100644 index 00000000..5ccbc73b --- /dev/null +++ b/src/modules/SX1279.h @@ -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 diff --git a/src/modules/SX127x.cpp b/src/modules/SX127x.cpp new file mode 100644 index 00000000..7631cf2a --- /dev/null +++ b/src/modules/SX127x.cpp @@ -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); +} diff --git a/src/modules/SX127x.h b/src/modules/SX127x.h new file mode 100644 index 00000000..67ae1859 --- /dev/null +++ b/src/modules/SX127x.h @@ -0,0 +1,211 @@ +#ifndef _KITELIB_SX127X_H +#define _KITELIB_SX127X_H + +#include + +#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