Added core source files

This commit is contained in:
Jan Gromeš 2018-03-05 17:08:42 +01:00
parent 274e254e8f
commit 9fe0e36005
20 changed files with 2410 additions and 0 deletions

View file

@ -0,0 +1,56 @@
#include "KiteLib.h"
ESP8266 wifi = Kite.ModuleA;
//SX1278 lora = Kite.ModuleB;
//HC05 bluetooth = Kite.ModuleB;
//Packet pack("01:23:45:67:89:AB:CD:EF", "Hello World! (by LoRa)");
void setup() {
Serial.begin(9600);
Serial.print("[ESP8266] Connecting ... ");
uint8_t state = wifi.begin(9600);
if(state == ERR_NONE) {
Serial.println("success!");
} else {
Serial.print("failed, code ");
Serial.println(state, HEX);
}
Serial.print("[ESP8266] Joining AP ... ");
state = wifi.join("Tenda", "Student20-X13");
if(state == ERR_NONE) {
Serial.println("success!");
} else {
Serial.print("failed, code ");
Serial.println(state, HEX);
}
Serial.print("[ESP8266] Sending GET request ... ");
String response;
uint16_t http_code = wifi.HttpGet("http://www.httpbin.org/ip", response);
if(http_code == 200) {
Serial.println("success!");
Serial.println("[ESP8266] Response:\n");
Serial.println(response);
} else {
Serial.print("failed, code ");
Serial.println(http_code, HEX);
}
//lora.begin();
//bluetooth.begin(9600);
}
void loop() {
//wifi.send("GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n");
//lora.transmit(pack);
//bluetooth.println("Hello World! (by Blueooth)");
delay(1000);
}

View file

@ -0,0 +1,24 @@
#include <SoftwareSerial.h>
const int RX_A = 9;
const int TX_A = 8;
const int RX_B = 7;
const int TX_B = 6;
SoftwareSerial module(RX_A, TX_A); // Rx, Tx, Module A
//SoftwareSerial module(RX_B, TX_B); // Rx, Tx, Module B
void setup() {
Serial.begin(9600);
module.begin(9600);
}
void loop() {
while(Serial.available() > 0) {
module.write(Serial.read());
}
while(module.available() > 0) {
Serial.write(module.read());
}
}

93
keywords.txt Normal file
View file

@ -0,0 +1,93 @@
#######################################
# Syntax Coloring Map For LoRaLib
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
KiteLib KEYWORD1
Kite KEYWORD1
Packet KEYWORD1
ESP8266 KEYWORD1
SX1278 KEYWORD1
SX1272 KEYWORD1
HC05 KEYWORD1
Bandwidth KEYWORD1
SpreadingFactor KEYWORD1
CodingRate KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
# KiteLib
ModuleA KEYWORD2
ModuleB KEYWORD2
# Packet
source KEYWORD2
destination KEYWORD2
data KEYWORD2
length KEYWORD2
getSourceStr KEYWORD2
getDestinationStr KEYWORD2
setSourceStr KEYWORD2
setDestinationStr KEYWORD2
copyInto KEYWORD2
# SX1278/SX1272
dataRate KEYWORD2
lastPacketRSSI KEYWORD2
begin KEYWORD2
transmit KEYWORD2
receive KEYWORD2
sleep KEYWORD2
standby KEYWORD2
setBandwidth KEYWORD2
setSpreadingFactor KEYWORD2
setCodingRate KEYWORD2
# ESP8266
join KEYWORD2
createTCP KEYWORD2
send 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_CHIP_NOT_FOUND LITERAL1
ERR_PACKET_TOO_LONG LITERAL1
ERR_RX_TIMEOUT LITERAL1
ERR_CRC_MISMATCH LITERAL1
ERR_INVALID_BANDWIDTH LITERAL1
ERR_INVALID_SPREADING_FACTOR LITERAL1
ERR_INVALID_CODING_RATE LITERAL1
ERR_INVALID_BIT_RANGE LITERAL1

10
library.properties Normal file
View file

@ -0,0 +1,10 @@
name=KiteLib
version=1.0.0
author=Jan Gromes <gipsonek@gmail.com>
maintainer=Jan Gromes <gipsonek@gmail.com>
sentence=Arduino library for the KITE shield
paragraph=Enables user-friendly control of the KITE shield and various wireless modules.
category=Communication
url=https://github.com/jgromes/KiteLib
architecture=*
includes=KiteLib.h

21
license.txt Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Jan Gromeš
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

172
src/ESP8266.cpp Normal file
View file

@ -0,0 +1,172 @@
#include "ESP8266.h"
ESP8266::ESP8266(Module* module) {
_mod = module;
}
uint8_t ESP8266::begin(long speed) {
_mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE);
_mod->ATemptyBuffer();
if(!_mod->ATsendCommand("AT")) {
return(ERR_UNKNOWN);
}
return(ERR_NONE);
}
uint8_t ESP8266::restart() {
// send the restart command
if(!_mod->ATsendCommand("AT+RST")) {
return(ERR_UNKNOWN);
}
// wait for the module to start
delay(2000);
// test AT setup
uint32_t start = millis();
while (millis() - start < 3000) {
if(!_mod->ATsendCommand("AT")) {
delay(100);
} else {
return(ERR_NONE);
}
}
return(ERR_UNKNOWN);
}
uint8_t ESP8266::join(const char* ssid, const char* password) {
// set mode to station + soft AP
if(!_mod->ATsendCommand("AT+CWMODE_CUR=3")) {
return(ERR_UNKNOWN);
}
// restart module
uint8_t state = restart();
if(state != ERR_NONE) {
return(state);
}
// join AP
String cmd = "AT+CWJAP_CUR=\"";
cmd += ssid;
cmd += "\",\"";
cmd += password;
cmd += "\"";
if(!_mod->ATsendCommand(cmd)) {
return(ERR_UNKNOWN);
}
// disable multiple connection mode
if(!_mod->ATsendCommand("AT+CIPMUX=0")) {
return(ERR_UNKNOWN);
}
return(ERR_NONE);
}
uint16_t ESP8266::HttpGet(const char* url, String& data, uint16_t port) {
String urlString(url);
// get the host address and endpoint
int32_t resourceIndex = urlString.indexOf("/", 7);
if(resourceIndex == -1) {
return(ERR_URL_MALFORMED);
}
String host = urlString.substring(7, resourceIndex);
String endpoint = urlString.substring(resourceIndex);
// create TCP connection
uint8_t state = startTCP(host.c_str(), 80);
if(state != ERR_NONE) {
return(state);
}
// build the GET request
String request = "GET ";
request += endpoint;
request += " HTTP/1.1\r\nHost: ";
request += host;
request += "\r\n\r\n";
// send the GET request
state = send(request);
if(state != ERR_NONE) {
return(state);
}
// read the response
String raw = receive();
// close the TCP connection
state = closeTCP();
if(state != ERR_NONE) {
return(state);
}
// parse the response
int32_t numBytesIndex = raw.indexOf(":");
if(numBytesIndex == -1) {
return(ERR_RESPONSE_MALFORMED_AT);
}
data = raw.substring(numBytesIndex + 1);
// return the HTTP status code
int32_t spaceIndex = data.indexOf(" ");
if(spaceIndex == -1) {
return(ERR_RESPONSE_MALFORMED);
}
String statusString = data.substring(spaceIndex + 1, spaceIndex + 4);
return(statusString.toInt());
}
uint8_t ESP8266::startTCP(const char* host, uint16_t port) {
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += host;
cmd += "\",";
cmd += port;
if(!_mod->ATsendCommand(cmd)) {
return(ERR_UNKNOWN);
}
return(ERR_NONE);
}
uint8_t ESP8266::closeTCP() {
if(!_mod->ATsendCommand("AT+CIPCLOSE")) {
return(ERR_UNKNOWN);
}
return(ERR_NONE);
}
uint8_t ESP8266::send(String data) {
// send data length in bytes
String cmd = "AT+CIPSEND=";
cmd += data.length();
if(!_mod->ATsendCommand(cmd)) {
return(ERR_UNKNOWN);
}
// send data
if(!_mod->ATsendCommand(data)) {
return(ERR_UNKNOWN);
}
return(ERR_NONE);
}
String ESP8266::receive(uint32_t timeout) {
String data;
uint32_t start = millis();
while(millis() - start < timeout) {
while(_mod->ModuleSerial->available() > 0) {
char c = _mod->ModuleSerial->read();
#ifdef DEBUG
Serial.print(c);
#endif
data += c;
}
}
return(data);
}

24
src/ESP8266.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef _KITELIB_ESP8266_H
#define _KITELIB_ESP8266_H
#include "Module.h"
class ESP8266 {
public:
ESP8266(Module* module);
uint8_t begin(long speed);
uint8_t restart();
uint8_t join(const char* ssid, const char* password);
uint16_t HttpGet(const char* url, String& data, uint16_t port = 80);
uint8_t startTCP(const char* host, uint16_t port);
uint8_t closeTCP();
uint8_t send(String data);
String receive(uint32_t timeout = 10000);
private:
Module* _mod;
};
#endif

142
src/HC05.cpp Normal file
View file

@ -0,0 +1,142 @@
#include "HC05.h"
HC05::HC05(Module* module) {
_mod = module;
}
void HC05::begin(long speed) {
_mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE);
}
bool HC05::listen() {
return(_mod->ModuleSerial->listen());
}
void HC05::end() {
_mod->ModuleSerial->end();
}
bool HC05::isListening() {
return(_mod->ModuleSerial->isListening());
}
bool HC05::stopListening() {
return(_mod->ModuleSerial->stopListening());
}
bool HC05::overflow() {
return(_mod->ModuleSerial->overflow());
}
int HC05::peek() {
return(_mod->ModuleSerial->peek());
}
size_t HC05::write(uint8_t b) {
return(_mod->ModuleSerial->write(b));
}
int HC05::read() {
return(_mod->ModuleSerial->read());
}
int HC05::available() {
return(_mod->ModuleSerial->available());
}
void HC05::flush() {
_mod->ModuleSerial->flush();
}
size_t HC05::print(const __FlashStringHelper *ifsh) {
return(_mod->ModuleSerial->print(ifsh));
}
size_t HC05::print(const String &s) {
return(_mod->ModuleSerial->print(s));
}
size_t HC05::print(const char str[]) {
return(_mod->ModuleSerial->print(str));
}
size_t HC05::print(char c) {
return(_mod->ModuleSerial->print(c));
}
size_t HC05::print(unsigned char b, int base) {
return(_mod->ModuleSerial->print(b, base));
}
size_t HC05::print(int n, int base) {
return(_mod->ModuleSerial->print(n, base));
}
size_t HC05::print(unsigned int n, int base) {
return(_mod->ModuleSerial->print(n, base));
}
size_t HC05::print(long n, int base) {
return(_mod->ModuleSerial->print(n, base));
}
size_t HC05::print(unsigned long n, int base) {
return(_mod->ModuleSerial->print(n, base));
}
size_t HC05::print(double n, int digits) {
return(_mod->ModuleSerial->print(n, digits));
}
size_t HC05::print(const Printable& x) {
return(_mod->ModuleSerial->print(x));
}
size_t HC05::println(const __FlashStringHelper *ifsh) {
return(_mod->ModuleSerial->println(ifsh));
}
size_t HC05::println(const String &s) {
return(_mod->ModuleSerial->println(s));
}
size_t HC05::println(const char str[]) {
return(_mod->ModuleSerial->println(str));
}
size_t HC05::println(char c) {
return(_mod->ModuleSerial->println(c));
}
size_t HC05::println(unsigned char b, int base) {
return(_mod->ModuleSerial->println(b, base));
}
size_t HC05::println(int n, int base) {
return(_mod->ModuleSerial->println(n, base));
}
size_t HC05::println(unsigned int n, int base) {
return(_mod->ModuleSerial->println(n, base));
}
size_t HC05::println(long n, int base) {
return(_mod->ModuleSerial->println(n, base));
}
size_t HC05::println(unsigned long n, int base) {
return(_mod->ModuleSerial->println(n, base));
}
size_t HC05::println(double n, int digits) {
return(_mod->ModuleSerial->println(n, digits));
}
size_t HC05::println(const Printable& x) {
return(_mod->ModuleSerial->println(x));
}
size_t HC05::println(void) {
return(_mod->ModuleSerial->println());
}

56
src/HC05.h Normal file
View file

@ -0,0 +1,56 @@
#ifndef _KITELIB_HC05_H
#define _KITELIB_HC05_H
#include "Module.h"
#include <stdio.h>
#include "WString.h"
#include "Printable.h"
class HC05 {
public:
HC05(Module* module);
void begin(long speed);
bool listen();
void end();
bool isListening();
bool stopListening();
bool overflow();
int peek();
size_t write(uint8_t);
int read();
int available();
void flush();
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);
private:
Module* _mod;
};
#endif

19
src/KiteLib.cpp Normal file
View file

@ -0,0 +1,19 @@
#include "KiteLib.h"
/*Kite::Kite(ModuleType moduleA, ModuleType moduleB) {
switch(moduleA) {
case ModuleType::ESP8266:
ESP8266 = new class ESP8266();
break;
case ModuleType::SX1278:
SX1278 = new class SX1278();
break;
};
}*/
KiteShield::KiteShield() {
ModuleA = new Module(KITE_CS_A, KITE_TX_A, KITE_RX_A, KITE_INT_0, KITE_INT_1);
ModuleB = new Module(KITE_CS_B, KITE_TX_B, KITE_RX_B, KITE_INT_0, KITE_INT_1);
}
KiteShield Kite;

35
src/KiteLib.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef _KITELIB_H
#define _KITELIB_H
#include "TypeDef.h"
#include "Module.h"
#include "ESP8266.h"
#include "SX1278.h"
#include "SX1272.h"
#include "HC05.h"
#define KITE_CS_A 10
#define KITE_TX_A 9
#define KITE_RX_A 8
#define KITE_CS_B 5
#define KITE_TX_B 7
#define KITE_RX_B 6
#define KITE_INT_0 2
#define KITE_INT_1 3
class KiteShield {
public:
KiteShield();
Module* ModuleA;
Module* ModuleB;
private:
};
extern KiteShield Kite;
#endif

183
src/Module.cpp Normal file
View file

@ -0,0 +1,183 @@
#include "Module.h"
Module::Module() {
}
Module::Module(int cs, int tx, int rx, int int0, int int1) {
_cs = cs;
_tx = tx;
_rx = rx;
_int0 = int0;
_int1 = int1;
ModuleSerial = new SoftwareSerial(_tx, _rx);
}
uint8_t Module::init(uint8_t interface, uint8_t gpio) {
#ifdef DEBUG
Serial.begin(9600);
Serial.println();
#endif
switch(interface) {
case USE_SPI:
pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH);
SPI.begin();
break;
case USE_UART:
ModuleSerial->begin(baudrate);
break;
case USE_I2C:
break;
}
switch(gpio) {
case INT_NONE:
break;
case INT_0:
pinMode(_int0, INPUT);
break;
case INT_1:
pinMode(_int1, INPUT);
break;
case INT_BOTH:
pinMode(_int0, INPUT);
pinMode(_int1, INPUT);
break;
}
}
void Module::ATemptyBuffer() {
while(ModuleSerial->available() > 0) {
ModuleSerial->read();
}
}
bool Module::ATsendCommand(String& cmd) {
return(ATsendCommand(cmd.c_str()));
}
bool Module::ATsendCommand(const char* cmd) {
ATemptyBuffer();
ModuleSerial->print(cmd);
ModuleSerial->print("\r\n");
return(ATgetResponse());
}
bool Module::ATgetResponse() {
String data;
uint32_t start = millis();
while (millis() - start < _ATtimeout) {
while(ModuleSerial->available() > 0) {
char c = ModuleSerial->read();
#ifdef DEBUG
Serial.print(c);
#endif
data += c;
}
if(data.indexOf("OK") != -1) {
#ifdef DEBUG
Serial.println();
#endif
return(true);
} else if (data.indexOf("ERROR") != -1) {
#ifdef DEBUG
Serial.println();
#endif
return(false);
}
}
#ifdef DEBUG
Serial.println();
#endif
return(false);
}
uint8_t Module::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
return(ERR_INVALID_BIT_RANGE);
}
uint8_t rawValue = SPIreadRegister(reg);
uint8_t maskedValue = rawValue & ((0b11111111 << lsb) & (0b11111111 >> (7 - msb)));
return(maskedValue);
}
uint8_t Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {
digitalWrite(_cs, LOW);
SPI.transfer(reg | SPI_READ);
for(uint8_t i = 0; i < numBytes; i++) {
inBytes[i] = SPI.transfer(reg);
}
digitalWrite(_cs, HIGH);
return(ERR_NONE);
}
uint8_t Module::SPIreadRegisterBurstStr(uint8_t reg, uint8_t numBytes, char* inBytes) {
digitalWrite(_cs, LOW);
SPI.transfer(reg | SPI_READ);
for(uint8_t i = 0; i < numBytes; i++) {
inBytes[i] = SPI.transfer(reg);
}
digitalWrite(_cs, HIGH);
return(ERR_NONE);
}
uint8_t Module::SPIreadRegister(uint8_t reg) {
uint8_t inByte;
digitalWrite(_cs, LOW);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
SPI.transfer(reg | SPI_READ);
SPI.endTransaction();
inByte = SPI.transfer(0x00);
digitalWrite(_cs, HIGH);
return(inByte);
}
uint8_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb) {
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
return(ERR_INVALID_BIT_RANGE);
}
uint8_t currentValue = SPIreadRegister(reg);
uint8_t newValue = currentValue & ((0b11111111 << (msb + 1)) & (0b11111111 >> (8 - lsb)));
SPIwriteRegister(reg, newValue | value);
return(ERR_NONE);
}
void Module::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes) {
digitalWrite(_cs, LOW);
SPI.transfer(reg | SPI_WRITE);
for(uint8_t i = 0; i < numBytes; i++) {
SPI.transfer(data[i]);
}
digitalWrite(_cs, HIGH);
}
void Module::SPIwriteRegisterBurstStr(uint8_t reg, const char* data, uint8_t numBytes) {
digitalWrite(_cs, LOW);
SPI.transfer(reg | SPI_WRITE);
for(uint8_t i = 0; i < numBytes; i++) {
SPI.transfer(data[i]);
}
digitalWrite(_cs, HIGH);
}
void Module::SPIwriteRegister(uint8_t reg, uint8_t data) {
digitalWrite(_cs, LOW);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
SPI.transfer(reg | SPI_WRITE);
SPI.transfer(data);
SPI.endTransaction();
digitalWrite(_cs, HIGH);
}
bool Module::getInt0State() {
return(digitalRead(_int0));
}
bool Module::getInt1State() {
return(digitalRead(_int1));
}

52
src/Module.h Normal file
View file

@ -0,0 +1,52 @@
#ifndef _KITELIB_MODULE_H
#define _KITELIB_MODULE_H
#include <SPI.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include "TypeDef.h"
#define SPI_READ 0b00000000
#define SPI_WRITE 0b10000000
class Module {
public:
Module();
Module(int cs, int tx, int rx, int int0, int int1);
SoftwareSerial* ModuleSerial;
uint32_t baudrate = 9600;
uint8_t init(uint8_t interface, uint8_t gpio);
void ATemptyBuffer();
bool ATgetResponse();
bool ATsendCommand(String& cmd);
bool ATsendCommand(const char* cmd);
uint8_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
uint8_t SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
uint8_t SPIreadRegisterBurstStr(uint8_t reg, uint8_t numBytes, char* str);
uint8_t SPIreadRegister(uint8_t reg);
uint8_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0);
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes);
void SPIwriteRegisterBurstStr(uint8_t reg, const char* data, uint8_t numBytes);
void SPIwriteRegister(uint8_t reg, uint8_t data);
bool getInt0State();
bool getInt1State();
private:
int _cs;
int _tx;
int _rx;
int _int0;
int _int1;
uint32_t _ATtimeout = 15000;
};
#endif

178
src/Packet.cpp Normal file
View file

@ -0,0 +1,178 @@
#include "Packet.h"
Packet::Packet(void) {
uint8_t src[8] = {0, 0, 0, 0, 0, 0, 0, 0};
getLoRaAddress(src);
uint8_t dest[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t dat[240];
uint8_t len = 0;
init(src, dest, dat, len);
}
Packet::Packet(const char dest[24], const char dat[240]) {
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]);
}
init(src, destTmp, dat);
}
Packet::Packet(uint8_t dest[8], const char dat[240]) {
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]) {
uint8_t srcTmp[8];
for(uint8_t i = 0; i < 8; i++) {
srcTmp[i] = (parseByte(src[3*i]) << 4) | parseByte(src[3*i + 1]);
}
uint8_t destTmp[8];
for(uint8_t i = 0; i < 8; i++) {
destTmp[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]);
}
init(srcTmp, destTmp, dat);
}
Packet::Packet(uint8_t src[8], uint8_t dest[8], const char dat[240]) {
init(src, dest, dat);
}
Packet::Packet(const char dest[24], 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]);
}
init(src, destTmp, dat, len);
}
Packet::Packet(uint8_t dest[8], 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) {
uint8_t srcTmp[8];
for(uint8_t i = 0; i < 8; i++) {
srcTmp[i] = (parseByte(src[3*i]) << 4) | parseByte(src[3*i + 1]);
}
uint8_t destTmp[8];
for(uint8_t i = 0; i < 8; i++) {
destTmp[i] = (parseByte(dest[3*i]) << 4) | parseByte(dest[3*i + 1]);
}
init(srcTmp, destTmp, dat, len);
}
Packet::Packet(uint8_t src[8], uint8_t dest[8], 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[8], uint8_t dest[8], uint8_t* dat, uint8_t len) {
length = len + 16;
for(uint8_t i = 0; i < 8; i++) {
source[i] = src[i];
destination[i] = dest[i];
}
for(uint8_t i = 0; i < length; i++) {
data[i] = dat[i];
}
}
void Packet::getSourceStr(char src[24]) {
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]);
}
}
void Packet::copyInto(Packet& pack) {
for(uint8_t i = 0; i < 8; i++) {
pack.source[i] = source[i];
pack.destination[i] = destination[i];
}
strcpy(pack.data, data);
}
void Packet::getLoRaAddress(uint8_t addr[8]) {
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);
}

47
src/Packet.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef _LORALIB_PACKET_H
#define _LORALIB_PACKET_H
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <EEPROM.h>
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[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);
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];
uint8_t length = 0;
void getSourceStr(char src[24]);
void getDestinationStr(char dest[24]);
void setSourceStr(const char src[24]);
void setDestinationStr(const char dest[24]);
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]);
uint8_t parseByte(char c);
char reparseChar(uint8_t b);
};
#endif

371
src/SX1272.cpp Normal file
View file

@ -0,0 +1,371 @@
#include "SX1272.h"
SX1272::SX1272(Module* module) {
_mod = module;
}
uint8_t SX1272::begin(Bandwidth bw, SpreadingFactor sf, CodingRate cr, uint16_t addrEeprom) {
switch(bw) {
case BW_125_00_KHZ:
_bw = SX1272_BW_125_00_KHZ;
break;
case BW_250_00_KHZ:
_bw = SX1272_BW_250_00_KHZ;
break;
case BW_500_00_KHZ:
_bw = SX1272_BW_500_00_KHZ;
break;
default:
_bw = SX1272_BW_250_00_KHZ;
break;
}
switch(sf) {
case SF_6:
_sf = SX1272_SF_6;
break;
case SF_7:
_sf = SX1272_SF_7;
break;
case SF_8:
_sf = SX1272_SF_8;
break;
case SF_9:
_sf = SX1272_SF_9;
break;
case SF_10:
_sf = SX1272_SF_10;
break;
case SF_11:
_sf = SX1272_SF_11;
break;
case SF_12:
_sf = SX1272_SF_12;
break;
default:
_sf = SX1272_SF_12;
break;
}
switch(cr) {
case CR_4_5:
_cr = SX1272_CR_4_5;
break;
case CR_4_6:
_cr = SX1272_CR_4_6;
break;
case CR_4_7:
_cr = SX1272_CR_4_7;
break;
case CR_4_8:
_cr = SX1272_CR_4_8;
break;
default:
_cr = SX1272_CR_4_5;
break;
}
#ifdef ESP32
if(!EEPROM.begin(9)) {
#ifdef DEBUG
Serial.println("Unable to initialize EEPROM");
#endif
return(ERR_EEPROM_NOT_INITIALIZED);
}
#endif
_addrEeprom = addrEeprom;
bool hasAddress = false;
for(uint16_t i = 0; i < 8; i++) {
if(EEPROM.read(_addrEeprom + i) != 255) {
hasAddress = true;
break;
}
}
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
}
_mod->init(USE_SPI, INT_BOTH);
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
uint8_t version = _mod->SPIreadRegister(SX1272_REG_VERSION);
if(version == 0x12) {
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) {
#ifdef DEBUG
Serial.println("No SX1272 found!");
#endif
SPI.end();
return(ERR_CHIP_NOT_FOUND);
}
#ifdef DEBUG
else {
Serial.println("Found SX1272! (match by SX1272_REG_VERSION == 0x12)");
}
#endif
return(config(_bw, _sf, _cr));
}
uint8_t SX1272::transmit(Packet& pack) {
char buffer[256];
for(uint8_t i = 0; i < 8; i++) {
buffer[i] = pack.source[i];
buffer[i+8] = pack.destination[i];
}
for(uint8_t i = 0; i < pack.length; i++) {
buffer[i+16] = pack.data[i];
}
setMode(SX1272_STANDBY);
_mod->SPIsetRegValue(SX1272_REG_DIO_MAPPING_1, SX1272_DIO0_TX_DONE, 7, 6);
clearIRQFlags();
if(pack.length > 256) {
return(ERR_PACKET_TOO_LONG);
}
_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);
setMode(SX1272_TX);
unsigned long start = millis();
while(!_mod->getInt0State()) {
#ifdef DEBUG
Serial.print('.');
#endif
}
clearIRQFlags();
return(ERR_NONE);
}
uint8_t SX1272::receive(Packet& pack) {
char buffer[256];
uint32_t startTime = millis();
setMode(SX1272_STANDBY);
_mod->SPIsetRegValue(SX1272_REG_DIO_MAPPING_1, SX1272_DIO0_RX_DONE | SX1272_DIO1_RX_TIMEOUT, 7, 4);
clearIRQFlags();
_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);
setMode(SX1272_RXSINGLE);
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
clearIRQFlags();
return(ERR_RX_TIMEOUT);
}
}
if(_mod->SPIgetRegValue(SX1272_REG_IRQ_FLAGS, 5, 5) == SX1272_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
return(ERR_CRC_MISMATCH);
}
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);
}
_mod->SPIreadRegisterBurstStr(SX1272_REG_FIFO, pack.length, buffer);
clearIRQFlags();
for(uint8_t i = 0; i < 8; i++) {
pack.source[i] = buffer[i];
pack.destination[i] = buffer[i+8];
}
for(uint8_t i = 16; i < pack.length; i++) {
pack.data[i-16] = buffer[i];
}
pack.data[pack.length-16] = 0;
uint32_t elapsedTime = millis() - startTime;
dataRate = (pack.length*8.0)/((float)elapsedTime/1000.0);
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) {
return(config(bw, _sf, _cr));
}
uint8_t SX1272::setSpreadingFactor(SpreadingFactor sf) {
return(config(_bw, sf, _cr));
}
uint8_t SX1272::setCodingRate(CodingRate cr) {
return(config(_bw, _sf, cr));
}
void SX1272::generateLoRaAdress() {
for(uint8_t i = _addrEeprom; i < (_addrEeprom + 8); i++) {
EEPROM.write(i, (uint8_t)random(0, 256));
}
}
uint8_t SX1272::config(uint8_t bw, uint8_t sf, uint8_t cr) {
uint8_t status = ERR_NONE;
//check the supplied bw, cr and sf values
if((bw != SX1272_BW_125_00_KHZ) &&
(bw != SX1272_BW_250_00_KHZ) &&
(bw != SX1272_BW_500_00_KHZ)) {
return(ERR_INVALID_BANDWIDTH);
}
if((sf != SX1272_SF_6) &&
(sf != SX1272_SF_7) &&
(sf != SX1272_SF_8) &&
(sf != SX1272_SF_9) &&
(sf != SX1272_SF_10) &&
(sf != SX1272_SF_11) &&
(sf != SX1272_SF_12)) {
return(ERR_INVALID_SPREADING_FACTOR);
}
if((cr != SX1272_CR_4_5) &&
(cr != SX1272_CR_4_6) &&
(cr != SX1272_CR_4_7) &&
(cr != SX1272_CR_4_8)) {
return(ERR_INVALID_CODING_RATE);
}
// set mode to SLEEP
status = setMode(SX1272_SLEEP);
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);
}
// 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);
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);
if(status != ERR_NONE) {
return(status);
}
// turn off frequency hopping
status = _mod->SPIsetRegValue(SX1272_REG_HOP_PERIOD, SX1272_HOP_PERIOD_OFF);
if(status != ERR_NONE) {
return(status);
}
// basic setting (bw, cr, sf, header mode and CRC)
if(sf == 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, bw | cr | 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 {
status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_2, sf | SX1272_TX_MODE_SINGLE | SX1272_RX_CRC_MODE_ON, 7, 2);
status = _mod->SPIsetRegValue(SX1272_REG_MODEM_CONFIG_1, bw | cr | 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) {
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);
if(status != ERR_NONE) {
return(status);
}
// set mode to STANDBY
status = setMode(SX1272_STANDBY);
if(status != ERR_NONE) {
return(status);
}
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));
}

229
src/SX1272.h Normal file
View file

@ -0,0 +1,229 @@
#ifndef _KITELIB_SX1272_H
#define _KITELIB_SX1272_H
#include <EEPROM.h>
#include "TypeDef.h"
#include "Module.h"
#include "Packet.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
#define SX1272_REG_AGC_REF 0x43
#define SX1272_REG_AGC_THRESH_1 0x44
#define SX1272_REG_AGC_THRESH_2 0x45
#define SX1272_REG_AGC_THRESH_3 0x46
#define SX1272_REG_PLL_HOP 0x4B
#define SX1272_REG_TCXO 0x58
#define SX1272_REG_PA_DAC 0x5A
#define SX1272_REG_PLL 0x5C
#define SX1272_REG_PLL_LOW_PN 0x5E
#define SX1272_REG_FORMER_TEMP 0x6C
#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
#define SX1272_BW_500_00_KHZ 0b10000000 // 7 6 500 kHz
#define SX1272_CR_4_5 0b00001000 // 5 3 error coding rate: 4/5
#define SX1272_CR_4_6 0b00010000 // 5 3 4/6
#define SX1272_CR_4_7 0b00011000 // 5 3 4/7
#define SX1272_CR_4_8 0b00100000 // 5 3 4/8
#define SX1272_HEADER_EXPL_MODE 0b00000000 // 2 2 explicit header mode
#define SX1272_HEADER_IMPL_MODE 0b00000100 // 2 2 implicit header mode
#define SX1272_RX_CRC_MODE_OFF 0b00000000 // 1 1 CRC disabled
#define SX1272_RX_CRC_MODE_ON 0b00000010 // 1 1 CRC enabled
#define SX1272_LOW_DATA_RATE_OPT_OFF 0b00000000 // 0 0 low data rate optimization disabled
#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 {
public:
SX1272(Module* module);
float dataRate;
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 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);
private:
Module* _mod;
uint8_t _bw, _sf, _cr;
uint8_t _address[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint16_t _addrEeprom;
void generateLoRaAdress();
uint8_t config(uint8_t bw, uint8_t sf, uint8_t cr);
uint8_t setMode(uint8_t mode);
void clearIRQFlags();
int8_t getLastPacketRSSI();
};
#endif

399
src/SX1278.cpp Normal file
View file

@ -0,0 +1,399 @@
#include "SX1278.h"
SX1278::SX1278(Module* module) {
_mod = module;
}
uint8_t SX1278::begin(Bandwidth bw, SpreadingFactor sf, CodingRate cr, uint16_t addrEeprom) {
switch(bw) {
case BW_7_80_KHZ:
_bw = SX1278_BW_7_80_KHZ;
break;
case BW_10_40_KHZ:
_bw = SX1278_BW_10_40_KHZ;
break;
case BW_15_60_KHZ:
_bw = SX1278_BW_15_60_KHZ;
break;
case BW_20_80_KHZ:
_bw = SX1278_BW_20_80_KHZ;
break;
case BW_31_25_KHZ:
_bw = SX1278_BW_31_25_KHZ;
break;
case BW_41_70_KHZ:
_bw = SX1278_BW_41_70_KHZ;
break;
case BW_62_50_KHZ:
_bw = SX1278_BW_62_50_KHZ;
break;
case BW_125_00_KHZ:
_bw = SX1278_BW_125_00_KHZ;
break;
case BW_250_00_KHZ:
_bw = SX1278_BW_250_00_KHZ;
break;
case BW_500_00_KHZ:
_bw = SX1278_BW_500_00_KHZ;
break;
default:
_bw = SX1278_BW_250_00_KHZ;
break;
}
switch(sf) {
case SF_6:
_sf = SX1278_SF_6;
break;
case SF_7:
_sf = SX1278_SF_7;
break;
case SF_8:
_sf = SX1278_SF_8;
break;
case SF_9:
_sf = SX1278_SF_9;
break;
case SF_10:
_sf = SX1278_SF_10;
break;
case SF_11:
_sf = SX1278_SF_11;
break;
case SF_12:
_sf = SX1278_SF_12;
break;
default:
_sf = SX1278_SF_12;
break;
}
switch(cr) {
case CR_4_5:
_cr = SX1278_CR_4_5;
break;
case CR_4_6:
_cr = SX1278_CR_4_6;
break;
case CR_4_7:
_cr = SX1278_CR_4_7;
break;
case CR_4_8:
_cr = SX1278_CR_4_8;
break;
default:
_cr = SX1278_CR_4_5;
break;
}
#ifdef ESP32
if(!EEPROM.begin(9)) {
#ifdef DEBUG
Serial.println("Unable to initialize EEPROM");
#endif
return(ERR_EEPROM_NOT_INITIALIZED);
}
#endif
_addrEeprom = addrEeprom;
bool hasAddress = false;
for(uint16_t i = 0; i < 8; i++) {
if(EEPROM.read(_addrEeprom + i) != 255) {
hasAddress = true;
break;
}
}
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
}
_mod->init(USE_SPI, INT_BOTH);
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) {
#ifdef DEBUG
Serial.println("No SX1278 found!");
#endif
SPI.end();
return(ERR_CHIP_NOT_FOUND);
}
#ifdef DEBUG
else {
Serial.println("Found SX1278! (match by SX1278_REG_VERSION == 0x12)");
}
#endif
return(config(_bw, _sf, _cr));
}
uint8_t SX1278::transmit(Packet& pack) {
char buffer[256];
for(uint8_t i = 0; i < 8; i++) {
buffer[i] = pack.source[i];
buffer[i+8] = pack.destination[i];
}
for(uint8_t i = 0; i < pack.length; i++) {
buffer[i+16] = pack.data[i];
}
setMode(SX1278_STANDBY);
_mod->SPIsetRegValue(SX1278_REG_DIO_MAPPING_1, SX1278_DIO0_TX_DONE, 7, 6);
clearIRQFlags();
if(pack.length > 256) {
return(ERR_PACKET_TOO_LONG);
}
_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);
setMode(SX1278_TX);
unsigned long start = millis();
while(!_mod->getInt0State()) {
#ifdef DEBUG
Serial.print('.');
#endif
}
clearIRQFlags();
return(ERR_NONE);
}
uint8_t SX1278::receive(Packet& pack) {
char buffer[256];
uint32_t startTime = millis();
setMode(SX1278_STANDBY);
_mod->SPIsetRegValue(SX1278_REG_DIO_MAPPING_1, SX1278_DIO0_RX_DONE | SX1278_DIO1_RX_TIMEOUT, 7, 4);
clearIRQFlags();
_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);
setMode(SX1278_RXSINGLE);
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
clearIRQFlags();
return(ERR_RX_TIMEOUT);
}
}
if(_mod->SPIgetRegValue(SX1278_REG_IRQ_FLAGS, 5, 5) == SX1278_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
return(ERR_CRC_MISMATCH);
}
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);
}
_mod->SPIreadRegisterBurstStr(SX1278_REG_FIFO, pack.length, buffer);
clearIRQFlags();
for(uint8_t i = 0; i < 8; i++) {
pack.source[i] = buffer[i];
pack.destination[i] = buffer[i+8];
}
for(uint8_t i = 16; i < pack.length; i++) {
pack.data[i-16] = buffer[i];
}
pack.data[pack.length-16] = 0;
uint32_t elapsedTime = millis() - startTime;
dataRate = (pack.length*8.0)/((float)elapsedTime/1000.0);
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) {
return(config(bw, _sf, _cr));
}
uint8_t SX1278::setSpreadingFactor(SpreadingFactor sf) {
return(config(_bw, sf, _cr));
}
uint8_t SX1278::setCodingRate(CodingRate cr) {
return(config(_bw, _sf, cr));
}
void SX1278::generateLoRaAdress() {
for(uint8_t i = _addrEeprom; i < (_addrEeprom + 8); i++) {
EEPROM.write(i, (uint8_t)random(0, 256));
}
}
uint8_t SX1278::config(uint8_t bw, uint8_t sf, uint8_t cr) {
uint8_t status = ERR_NONE;
//check the supplied bw, cr and sf values
if((bw != SX1278_BW_7_80_KHZ) &&
(bw != SX1278_BW_10_40_KHZ) &&
(bw != SX1278_BW_15_60_KHZ) &&
(bw != SX1278_BW_20_80_KHZ) &&
(bw != SX1278_BW_31_25_KHZ) &&
(bw != SX1278_BW_41_70_KHZ) &&
(bw != SX1278_BW_62_50_KHZ) &&
(bw != SX1278_BW_125_00_KHZ) &&
(bw != SX1278_BW_250_00_KHZ) &&
(bw != SX1278_BW_500_00_KHZ)) {
return(ERR_INVALID_BANDWIDTH);
}
if((sf != SX1278_SF_6) &&
(sf != SX1278_SF_7) &&
(sf != SX1278_SF_8) &&
(sf != SX1278_SF_9) &&
(sf != SX1278_SF_10) &&
(sf != SX1278_SF_11) &&
(sf != SX1278_SF_12)) {
return(ERR_INVALID_SPREADING_FACTOR);
}
if((cr != SX1278_CR_4_5) &&
(cr != SX1278_CR_4_6) &&
(cr != SX1278_CR_4_7) &&
(cr != SX1278_CR_4_8)) {
return(ERR_INVALID_CODING_RATE);
}
// set mode to SLEEP
status = setMode(SX1278_SLEEP);
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);
}
// 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);
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);
if(status != ERR_NONE) {
return(status);
}
// turn off frequency hopping
status = _mod->SPIsetRegValue(SX1278_REG_HOP_PERIOD, SX1278_HOP_PERIOD_OFF);
if(status != ERR_NONE) {
return(status);
}
// basic setting (bw, cr, sf, header mode and CRC)
if(sf == 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, bw | cr | 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);
} else {
status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_2, sf | SX1278_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_ON, 7, 2);
status = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_1, bw | cr | 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) {
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 mode to STANDBY
status = setMode(SX1278_STANDBY);
if(status != ERR_NONE) {
return(status);
}
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));
}

239
src/SX1278.h Normal file
View file

@ -0,0 +1,239 @@
#ifndef _KITELIB_SX1278_H
#define _KITELIB_SX1278_H
#include <EEPROM.h>
#include "TypeDef.h"
#include "Module.h"
#include "Packet.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
#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
#define SX1278_REG_AGC_REF 0x61
#define SX1278_REG_AGC_THRESH_1 0x62
#define SX1278_REG_AGC_THRESH_2 0x63
#define SX1278_REG_AGC_THRESH_3 0x64
#define SX1278_REG_PLL 0x70
//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
#define SX1278_FRF_MID 0x80 // 7 0 where F(XOSC) = 32 MHz
#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
#define SX1278_BW_10_40_KHZ 0b00010000 // 7 4 10.40 kHz
#define SX1278_BW_15_60_KHZ 0b00100000 // 7 4 15.60 kHz
#define SX1278_BW_20_80_KHZ 0b00110000 // 7 4 20.80 kHz
#define SX1278_BW_31_25_KHZ 0b01000000 // 7 4 31.25 kHz
#define SX1278_BW_41_70_KHZ 0b01010000 // 7 4 41.70 kHz
#define SX1278_BW_62_50_KHZ 0b01100000 // 7 4 62.50 kHz
#define SX1278_BW_125_00_KHZ 0b01110000 // 7 4 125.00 kHz
#define SX1278_BW_250_00_KHZ 0b10000000 // 7 4 250.00 kHz
#define SX1278_BW_500_00_KHZ 0b10010000 // 7 4 500.00 kHz
#define SX1278_CR_4_5 0b00000010 // 3 1 error coding rate: 4/5
#define SX1278_CR_4_6 0b00000100 // 3 1 4/6
#define SX1278_CR_4_7 0b00000110 // 3 1 4/7
#define SX1278_CR_4_8 0b00001000 // 3 1 4/8
#define SX1278_HEADER_EXPL_MODE 0b00000000 // 0 0 explicit header mode
#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
#define SX1278_LOW_DATA_RATE_OPT_ON 0b00001000 // 3 3 low data rate optimization enabled
#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 {
public:
SX1278(Module* module);
float dataRate;
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 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);
private:
Module* _mod;
uint8_t _bw, _sf, _cr;
uint16_t _addrEeprom;
uint8_t _address[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void generateLoRaAdress();
uint8_t config(uint8_t bw, uint8_t sf, uint8_t cr);
uint8_t setMode(uint8_t mode);
void clearIRQFlags();
int8_t getLastPacketRSSI();
};
#endif

60
src/TypeDef.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef _KITELIB_TYPES_H
#define _KITELIB_TYPES_H
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
//#define DEBUG
// 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
// 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
// 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
// SX1278/SX1272 error codes
#define ERR_CHIP_NOT_FOUND 0x01
#define ERR_EEPROM_NOT_INITIALIZED 0x02
#define ERR_PACKET_TOO_LONG 0x10
#define ERR_RX_TIMEOUT 0x20
#define ERR_CRC_MISMATCH 0x21
#define ERR_INVALID_BANDWIDTH 0x30
#define ERR_INVALID_SPREADING_FACTOR 0x31
#define ERR_INVALID_CODING_RATE 0x32
#define ERR_INVALID_BIT_RANGE 0x40
// ESP8266 error codes
#define ERR_URL_MALFORMED 0x01
#define ERR_RESPONSE_MALFORMED_AT 0x02
#define ERR_RESPONSE_MALFORMED 0x03
enum Slot {SlotA, SlotB};
enum Bandwidth {BW_7_80_KHZ, BW_10_40_KHZ, BW_15_60_KHZ, BW_20_80_KHZ, BW_31_25_KHZ, BW_41_70_KHZ, BW_62_50_KHZ, BW_125_00_KHZ, BW_250_00_KHZ, BW_500_00_KHZ, };
enum SpreadingFactor {SF_6, SF_7, SF_8, SF_9, SF_10, SF_11, SF_12};
enum CodingRate {CR_4_5, CR_4_6, CR_4_7, CR_4_8};
#endif