Added core source files
This commit is contained in:
parent
274e254e8f
commit
9fe0e36005
20 changed files with 2410 additions and 0 deletions
56
examples/api_test/api_test.ino
Normal file
56
examples/api_test/api_test.ino
Normal 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);
|
||||
}
|
||||
|
24
examples/uart_test/uart_test.ino
Normal file
24
examples/uart_test/uart_test.ino
Normal 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
93
keywords.txt
Normal 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
10
library.properties
Normal 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
21
license.txt
Normal 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
172
src/ESP8266.cpp
Normal 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
24
src/ESP8266.h
Normal 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
142
src/HC05.cpp
Normal 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
56
src/HC05.h
Normal 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
19
src/KiteLib.cpp
Normal 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
35
src/KiteLib.h
Normal 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
183
src/Module.cpp
Normal 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
52
src/Module.h
Normal 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
178
src/Packet.cpp
Normal 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
47
src/Packet.h
Normal 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
371
src/SX1272.cpp
Normal 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
229
src/SX1272.h
Normal 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
399
src/SX1278.cpp
Normal 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
239
src/SX1278.h
Normal 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
60
src/TypeDef.h
Normal 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
|
Loading…
Add table
Reference in a new issue