Sync with LoRaLib v4.1.0
This commit is contained in:
parent
31dd1baadc
commit
619fd8a072
6 changed files with 284 additions and 52 deletions
143
examples/SX127x_ReceiveInterrupt/SX127x_ReceiveInterrupt.ino
Normal file
143
examples/SX127x_ReceiveInterrupt/SX127x_ReceiveInterrupt.ino
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -50,6 +50,9 @@ setCodingRate KEYWORD2
|
|||
setFrequency KEYWORD2
|
||||
setSyncWord KEYWORD2
|
||||
setOutputPower KEYWORD2
|
||||
listen KEYWORD2
|
||||
onReceive KEYWORD2
|
||||
readData KEYWORD2
|
||||
|
||||
# RF69-specific
|
||||
setBitRate KEYWORD2
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue