Sync with LoRaLib v4.1.0

This commit is contained in:
Jan Gromeš 2018-07-26 18:35:11 +02:00
parent 31dd1baadc
commit 619fd8a072
6 changed files with 284 additions and 52 deletions

View file

@ -0,0 +1,143 @@
/*
KiteLib Receive with Inerrupts Example
This example listens for LoRa transmissions and tries to
receive them. Once a packet is received, an interrupt is
triggered. To successfully receive data, the following
settings have to be the same on both transmitter
and receiver:
- carrier frequency
- bandwidth
- spreading factor
- coding rate
- sync word
Other modules from SX127x family can also be used.
SX1272 lora = Kite.ModuleA;
SX1273 lora = Kite.ModuleA;
SX1276 lora = Kite.ModuleA;
SX1277 lora = Kite.ModuleA;
SX1279 lora = Kite.ModuleA;
*/
// include the library
#include <KiteLib.h>
// SX1278 module is in slot A on the shield
SX1278 lora = Kite.ModuleA;
void setup() {
Serial.begin(9600);
// initialize SX1278 with default settings
Serial.print(F("Initializing ... "));
// carrier frequency: 434.0 MHz
// bandwidth: 125.0 kHz
// spreading factor: 9
// coding rate: 7
// sync word: 0x12
// output power: 17 dBm
int state = lora.begin();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// set the function that will be called
// when new packet is received
lora.onReceive(setFlag);
// start listening for LoRa packets
Serial.print(F("Starting to listen ... "));
state = lora.listen();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// if needed, 'listen' mode can be disabled by calling
// any of the following methods:
//
// lora.standby()
// lora.sleep()
// lora.transmit();
// lora.receive();
// lora.scanChannel();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// disable interrupt when it's not needed
volatile bool enableInterrupt = true;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// check if the interrupt is enabled
if(!enableInterrupt) {
return;
}
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {
// disable the interrupt service routine while
// processing the data
enableInterrupt = false;
// reset flag
receivedFlag = false;
// you can read received data as an Arduino String
String str;
int state = lora.readData(str);
// you can also read received data as byte array
/*
byte byteArr[8];
int state = lora.receive(byteArr, 8);
*/
if (state == ERR_NONE) {
// packet was successfully received
Serial.println("Received packet!");
// print data of the packet
Serial.print("Data:\t\t");
Serial.println(str);
// print RSSI (Received Signal Strength Indicator)
Serial.print("RSSI:\t\t");
Serial.print(lora.lastPacketRSSI);
Serial.println(" dBm");
// print SNR (Signal-to-Noise Ratio)
Serial.print("SNR:\t\t");
Serial.print(lora.lastPacketSNR);
Serial.println(" dBm");
} else if (state == ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Serial.println("CRC error!");
}
// we're ready to receive more packets,
// enable interrupt service routine
enableInterrupt = true;
}
}

View file

@ -50,6 +50,9 @@ setCodingRate KEYWORD2
setFrequency KEYWORD2
setSyncWord KEYWORD2
setOutputPower KEYWORD2
listen KEYWORD2
onReceive KEYWORD2
readData KEYWORD2
# RF69-specific
setBitRate KEYWORD2

View file

@ -150,7 +150,7 @@ int16_t SX1272::setCodingRate(uint8_t cr) {
int16_t SX1272::setOutputPower(int8_t power) {
// check allowed power range
if((power < -1) || (power > 20)) {
if(!(((power >= -1) && (power <= 17)) || (power == 20))) {
return(ERR_INVALID_OUTPUT_POWER);
}
@ -158,20 +158,20 @@ int16_t SX1272::setOutputPower(int8_t power) {
SX127x::standby();
int16_t state;
if(power < 15) {
// power is less than 15 dBm, enable PA0 on RFIO
if(power < 2) {
// power is less than 2 dBm, enable PA0 on RFIO
state = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_RFO, 7, 7);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, power + 1, 3, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, (power + 1), 3, 0);
state |= _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_OFF, 2, 0);
} else if((power >= 15) && (power < 18)) {
// power is 15 - 17 dBm, enable PA1 + PA2 on PA_BOOST
} else if((power >= 2) && (power <= 17)) {
// power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST
state = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST, 7, 7);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, power - 2, 3, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, (power - 2), 3, 0);
state |= _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_OFF, 2, 0);
} else if(power >= 18) {
// power is 18 - 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control
} else if(power == 20) {
// power is 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control
state = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST, 7, 7);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, power - 5, 3, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, (power - 5), 3, 0);
state |= _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0);
}

View file

@ -223,7 +223,7 @@ int16_t SX1278::setCodingRate(uint8_t cr) {
}
int16_t SX1278::setOutputPower(int8_t power) {
if((power < -3) || (power > 20)) {
if(!(((power >= -3) && (power <= 17)) || (power == 20))) {
return(ERR_INVALID_OUTPUT_POWER);
}
@ -231,20 +231,20 @@ int16_t SX1278::setOutputPower(int8_t power) {
SX127x::standby();
int16_t state;
if(power < 13) {
// power is less than 12 dBm, enable PA on RFO
if(power < 2) {
// power is less than 2 dBm, enable PA on RFO
state = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_RFO, 7, 7);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_LOW_POWER | (power + 3), 6, 0);
state |= _mod->SPIsetRegValue(SX1278_REG_PA_DAC, SX127X_PA_BOOST_OFF, 2, 0);
} else if((power >= 13) && (power < 18)) {
// power is 13 - 17 dBm, enable PA1 + PA2 on PA_BOOST
} else if((power >= 2) && (power <= 17)) {
// power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST
state = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST, 7, 7);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_MAX_POWER | (power + 2), 6, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_MAX_POWER | (power - 2), 6, 0);
state |= _mod->SPIsetRegValue(SX1278_REG_PA_DAC, SX127X_PA_BOOST_OFF, 2, 0);
} else if(power >= 18) {
// power is 18 - 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power mode
} else if(power == 20) {
// power is 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power mode
state = _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST, 7, 7);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_MAX_POWER | (power + 2), 6, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX1278_MAX_POWER | (power - 5), 6, 0);
state |= _mod->SPIsetRegValue(SX1278_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0);
}

View file

@ -49,6 +49,14 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord) {
return(ERR_NONE);
}
int16_t SX127x::transmit(String& str) {
return(SX127x::transmit(str.c_str()));
}
int16_t SX127x::transmit(const char* str) {
return(SX127x::transmit((uint8_t*)str, strlen(str)));
}
int16_t SX127x::transmit(uint8_t* data, size_t len) {
// check packet length
if(len >= 256) {
@ -92,12 +100,16 @@ int16_t SX127x::transmit(uint8_t* data, size_t len) {
// wait for packet transmission or timeout
uint32_t start = millis();
while(!_mod->getInt0State()) {
while(!digitalRead(_mod->int0())) {
if(millis() - start > timeout) {
clearIRQFlags();
return(ERR_TX_TIMEOUT);
}
}
uint32_t elapsed = millis() - start;
// update data rate
dataRate = (len*8.0)/((float)elapsed/1000.0);
// clear interrupt flags
clearIRQFlags();
@ -105,12 +117,18 @@ int16_t SX127x::transmit(uint8_t* data, size_t len) {
return(ERR_NONE);
}
int16_t SX127x::transmit(const char* str) {
return(SX127x::transmit((uint8_t*)str, strlen(str)));
}
int16_t SX127x::transmit(String& str) {
return(SX127x::transmit(str.c_str()));
int16_t SX127x::receive(String& str, size_t len) {
// create temporary array to store received data
char* data = new char[len];
int16_t state = SX127x::receive((uint8_t*)data, len);
// if packet was received successfully, copy data into String
if(state == ERR_NONE) {
str = String(data);
}
delete[] data;
return(state);
}
int16_t SX127x::receive(uint8_t* data, size_t len) {
@ -132,13 +150,12 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
// wait for packet reception or timeout
uint32_t start = millis();
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
while(!digitalRead(_mod->int0())) {
if(digitalRead(_mod->int1())) {
clearIRQFlags();
return(ERR_RX_TIMEOUT);
}
}
uint32_t elapsed = millis() - start;
// check integrity CRC
if(_mod->SPIgetRegValue(SX127X_REG_IRQ_FLAGS, 5, 5) == SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
@ -165,8 +182,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
data[length] = 0;
}
// update data rate, RSSI and SNR
dataRate = (length*8.0)/((float)elapsed/1000.0);
// update RSSI and SNR
lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
int8_t rawSNR = (int8_t)_mod->SPIgetRegValue(SX127X_REG_PKT_SNR_VALUE);
lastPacketSNR = rawSNR / 4.0;
@ -177,20 +193,6 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
return(ERR_NONE);
}
int16_t SX127x::receive(String& str, size_t len) {
// create temporary array to store received data
char* data = new char[len];
int16_t state = SX127x::receive((uint8_t*)data, len);
// if packet was received successfully, copy data into String
if(state == ERR_NONE) {
str = String(data);
}
delete[] data;
return(state);
}
int16_t SX127x::scanChannel() {
// set mode to standby
setMode(SX127X_STANDBY);
@ -203,8 +205,8 @@ int16_t SX127x::scanChannel() {
setMode(SX127X_CAD);
// wait for channel activity detected or timeout
while(!_mod->getInt0State()) {
if(_mod->getInt1State()) {
while(!digitalRead(_mod->int0())) {
if(digitalRead(_mod->int1())) {
clearIRQFlags();
return(PREAMBLE_DETECTED);
}
@ -226,6 +228,30 @@ int16_t SX127x::standby() {
return(setMode(SX127X_STANDBY));
}
int16_t SX127x::listen() {
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
// set DIO pin mapping
state |= _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_RX_DONE | SX127X_DIO1_RX_TIMEOUT, 7, 4);
if(state != ERR_NONE) {
return(state);
}
// clear interrupt flags
clearIRQFlags();
// set FIFO pointers
state = _mod->SPIsetRegValue(SX127X_REG_FIFO_RX_BASE_ADDR, SX127X_FIFO_RX_BASE_ADDR_MAX);
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_RX_BASE_ADDR_MAX);
if(state != ERR_NONE) {
return(state);
}
// set mode to continuous reception
return(setMode(SX127X_RXCONTINUOUS));
}
int16_t SX127x::setSyncWord(uint8_t syncWord) {
// set mode to standby
setMode(SX127X_STANDBY);
@ -250,6 +276,61 @@ int16_t SX127x::setFrequencyRaw(float newFreq) {
return(state);
}
void SX127x::onReceive(void (*func)(void)) {
attachInterrupt(digitalPinToInterrupt(_mod->int0()), func, RISING);
}
int16_t SX127x::readData(String& str, size_t len) {
// create temporary array to store received data
char* data = new char[len];
int16_t state = SX127x::readData((uint8_t*)data, len);
// if packet was received successfully, copy data into String
if(state == ERR_NONE) {
str = String(data);
}
delete[] data;
return(state);
}
int16_t SX127x::readData(uint8_t* data, size_t len) {
// check integrity CRC
if(_mod->SPIgetRegValue(SX127X_REG_IRQ_FLAGS, 5, 5) == SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
return(ERR_CRC_MISMATCH);
}
// get packet length
size_t length = len;
if(_sf != 6) {
length = _mod->SPIgetRegValue(SX127X_REG_RX_NB_BYTES);
}
// read packet data
if(len == 0) {
// argument len equal to zero indicates String call, which means dynamically allocated data array
// dispose of the original and create a new one
delete[] data;
data = new uint8_t[length];
}
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, length, data);
// add terminating null
if(len == 0) {
data[length] = 0;
}
// update RSSI and SNR
lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
int8_t rawSNR = (int8_t)_mod->SPIgetRegValue(SX127X_REG_PKT_SNR_VALUE);
lastPacketSNR = rawSNR / 4.0;
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
}
int16_t SX127x::config() {
// set mode to SLEEP
int16_t state = setMode(SX127X_SLEEP);
@ -295,8 +376,7 @@ int16_t SX127x::config() {
}
int16_t SX127x::setMode(uint8_t mode) {
_mod->SPIsetRegValue(SX127X_REG_OP_MODE, mode, 2, 0);
return(ERR_NONE);
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, mode, 2, 0));
}
void SX127x::clearIRQFlags() {

View file

@ -174,14 +174,20 @@ class SX127x {
// basic methods
int16_t begin(uint8_t chipVersion, uint8_t syncWord);
int16_t transmit(uint8_t* data, size_t len);
int16_t transmit(const char* str);
int16_t transmit(String& str);
int16_t receive(uint8_t* data, size_t len);
int16_t transmit(const char* str);
int16_t transmit(uint8_t* data, size_t len);
int16_t receive(String& str, size_t len = 0);
int16_t receive(uint8_t* data, size_t len);
int16_t scanChannel();
int16_t sleep();
int16_t standby();
int16_t listen();
// interrupt methods
int16_t readData(String& str, size_t len = 0);
int16_t readData(uint8_t* data, size_t len);
void onReceive(void (*func)(void));
// configuration methods
int16_t setSyncWord(uint8_t syncWord);