[SX127x] Sync with LoRaLib 8.0.4

This commit is contained in:
jgromes 2019-05-18 12:17:25 +02:00
parent 606e841aca
commit 608dad60c8
4 changed files with 436 additions and 530 deletions

View file

@ -120,12 +120,7 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
int16_t modem = getActiveModem();
if(modem == SX127X_LORA) {
// check packet length
if(len >= 256) {
return(ERR_PACKET_TOO_LONG);
}
// calculate timeout
// calculate timeout (150 % of expected time-one-air)
uint16_t base = 1;
float symbolLength = (float)(base << _sf) / (float)_bw;
float de = 0;
@ -138,24 +133,8 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
float n_pay = 8.0 + max(ceil((8.0 * (float)len - 4.0 * (float)_sf + 28.0 + 16.0 * crc - 20.0 * ih)/(4.0 * (float)_sf - 8.0 * de)) * (float)_cr, 0.0);
uint32_t timeout = ceil(symbolLength * (n_pre + n_pay + 4.25) * 1.5);
// set DIO mapping
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_TX_DONE, 7, 6);
// clear interrupt flags
clearIRQFlags();
// set packet length
state |= _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH, len);
// set FIFO pointers
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_TX_BASE_ADDR, SX127X_FIFO_TX_BASE_ADDR_MAX);
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDR_MAX);
// write packet to FIFO
_mod->SPIwriteRegisterBurst(SX127X_REG_FIFO, data, len);
// start transmission
state |= setMode(SX127X_TX);
state = startTransmit(data, len, addr);
if(state != ERR_NONE) {
return(state);
}
@ -179,37 +158,16 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
return(ERR_NONE);
} else if(modem == SX127X_FSK_OOK) {
// check packet length
if(len >= 64) {
return(ERR_PACKET_TOO_LONG);
}
// set DIO mapping
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_PACK_PACKET_SENT, 7, 6);
// clear interrupt flags
clearIRQFlags();
// set packet length
_mod->SPIwriteRegister(SX127X_REG_FIFO, len);
// check address filtering
uint8_t filter = _mod->SPIgetRegValue(SX127X_REG_PACKET_CONFIG_1, 2, 1);
if((filter == SX127X_ADDRESS_FILTERING_NODE) || (filter == SX127X_ADDRESS_FILTERING_NODE_BROADCAST)) {
_mod->SPIwriteRegister(SX127X_REG_FIFO, addr);
}
// write packet to FIFO
_mod->SPIwriteRegisterBurst(SX127X_REG_FIFO, data, len);
// calculate timeout (150 % of expected time-on-air)
uint32_t timeout = (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 1500.0);
// start transmission
state |= setMode(SX127X_TX);
state = startTransmit(data, len, addr);
if(state != ERR_NONE) {
return(state);
}
// wait for transmission end or timeout (150 % of expected time-on-air)
uint32_t timeout = (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 1500.0);
// wait for transmission end or timeout
uint32_t start = millis();
while(!digitalRead(_mod->getInt0())) {
if(millis() - start > timeout) {
@ -237,23 +195,13 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
int16_t modem = getActiveModem();
if(modem == SX127X_LORA) {
// set DIO pin mapping
state |= _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_RX_DONE | SX127X_DIO1_RX_TIMEOUT, 7, 4);
// 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);
// set mode to receive
state |= setMode(SX127X_RXSINGLE);
state = startReceive(SX127X_RXSINGLE);
if(state != ERR_NONE) {
return(state);
}
// wait for packet reception or timeout
// wait for packet reception or timeout (100 LoRa symbols)
while(!digitalRead(_mod->getInt0())) {
if(digitalRead(_mod->getInt1())) {
clearIRQFlags();
@ -261,56 +209,24 @@ int16_t SX127x::receive(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) {
// clear interrupt flags
clearIRQFlags();
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 + 1];
}
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, length, data);
// add terminating null
data[length] = 0;
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
// read the received data
return(readData(data, len));
} else if(modem == SX127X_FSK_OOK) {
// set DIO pin mapping
state |= _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_PACK_PAYLOAD_READY, 7, 6);
// clear interrupt flags
clearIRQFlags();
// set mode to receive
state |= setMode(SX127X_RX);
if(state != ERR_NONE) {
return(state);
}
// wait for packet reception or timeout (150 % of expected time-one-air)
// calculate timeout (500 % of expected time-one-air)
size_t maxLen = len;
if(len == 0) {
maxLen = 0xFF;
}
uint32_t timeout = (uint32_t)((((float)(maxLen * 8)) / (_br * 1000.0)) * 1500.0);
uint32_t timeout = (uint32_t)((((float)(maxLen * 8)) / (_br * 1000.0)) * 5000.0);
// set mode to receive
state = startReceive(SX127X_RX);
if(state != ERR_NONE) {
return(state);
}
// wait for packet reception or timeout
uint32_t start = millis();
while(!digitalRead(_mod->getInt0())) {
if(millis() - start > timeout) {
@ -319,31 +235,8 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
}
}
// get packet length
size_t length = _mod->SPIreadRegister(SX127X_REG_FIFO);
// check address filtering
uint8_t filter = _mod->SPIgetRegValue(SX127X_REG_PACKET_CONFIG_1, 2, 1);
if((filter == SX127X_ADDRESS_FILTERING_NODE) || (filter == SX127X_ADDRESS_FILTERING_NODE_BROADCAST)) {
_mod->SPIreadRegister(SX127X_REG_FIFO);
}
// 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 + 1];
}
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, length, data);
// add terminating null
data[length] = 0;
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
// read the received data
return(readData(data, len));
}
return(ERR_UNKNOWN);
@ -459,7 +352,7 @@ int16_t SX127x::packetMode() {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_2, SX127X_DATA_MODE_PACKET, 6, 6));
}
int16_t SX127x::startReceive() {
int16_t SX127x::startReceive(uint8_t mode) {
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
@ -478,9 +371,6 @@ int16_t SX127x::startReceive() {
return(state);
}
// set mode to continuous reception
return(setMode(SX127X_RXCONTINUOUS));
} else if(modem == SX127X_FSK_OOK) {
// set DIO pin mapping
state |= _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_PACK_PAYLOAD_READY, 7, 6);
@ -488,11 +378,14 @@ int16_t SX127x::startReceive() {
// clear interrupt flags
clearIRQFlags();
// set mode to receive
return(setMode(SX127X_RX));
// FSK modem does not distinguish between Rx single and continuous
if(mode == SX127X_RXCONTINUOUS) {
return(setMode(SX127X_RX));
}
}
return(ERR_UNKNOWN);
// set mode to receive
return(setMode(mode));
}
void SX127x::setDio0Action(void (*func)(void)) {
@ -503,25 +396,17 @@ void SX127x::setDio1Action(void (*func)(void)) {
attachInterrupt(digitalPinToInterrupt(_mod->getInt1()), func, RISING);
}
int16_t SX127x::startTransmit(String& str, uint8_t addr) {
return(SX127x::startTransmit(str.c_str(), addr));
}
int16_t SX127x::startTransmit(const char* str, uint8_t addr) {
return(SX127x::startTransmit((uint8_t*)str, strlen(str), addr));
}
int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
// check packet length
if(len >= 256) {
return(ERR_PACKET_TOO_LONG);
}
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
int16_t modem = getActiveModem();
if(modem == SX127X_LORA) {
// check packet length
if(len >= 256) {
return(ERR_PACKET_TOO_LONG);
}
// set DIO mapping
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_TX_DONE, 7, 6);
@ -547,6 +432,11 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
return(ERR_NONE);
} else if(modem == SX127X_FSK_OOK) {
// check packet length
if(len >= 64) {
return(ERR_PACKET_TOO_LONG);
}
// set DIO mapping
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_PACK_PACKET_SENT, 7, 6);
@ -577,22 +467,9 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
return(ERR_UNKNOWN);
}
int16_t SX127x::readData(String& str, size_t len) {
// create temporary array to store received data
char* data = new char[len + 1];
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) {
int16_t modem = getActiveModem();
size_t length;
if(modem == SX127X_LORA) {
// check integrity CRC
if(_mod->SPIgetRegValue(SX127X_REG_IRQ_FLAGS, 5, 5) == SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
@ -603,61 +480,40 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
}
// get packet length
size_t length = len;
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 + 1];
}
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, length, data);
// add terminating null
if(len == 0) {
data[length] = 0;
}
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
} else if(modem == SX127X_FSK_OOK) {
// get packet length
size_t length = _mod->SPIreadRegister(SX127X_REG_FIFO);
length = _mod->SPIreadRegister(SX127X_REG_FIFO);
// check address filtering
uint8_t filter = _mod->SPIgetRegValue(SX127X_REG_PACKET_CONFIG_1, 2, 1);
if((filter == SX127X_ADDRESS_FILTERING_NODE) || (filter == SX127X_ADDRESS_FILTERING_NODE_BROADCAST)) {
_mod->SPIreadRegister(SX127X_REG_FIFO);
}
// 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 + 1];
}
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, length, data);
// add terminating null
if(len == 0) {
data[length] = 0;
}
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
}
return(ERR_UNKNOWN);
// 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 + 1];
}
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, length, data);
// add terminating null
if(len == 0) {
data[length] = 0;
}
// clear interrupt flags
clearIRQFlags();
return(ERR_NONE);
}
int16_t SX127x::setSyncWord(uint8_t syncWord) {

View file

@ -532,6 +532,8 @@ class SX127x: public PhysicalLayer {
// introduce PhysicalLayer overloads
using PhysicalLayer::transmit;
using PhysicalLayer::receive;
using PhysicalLayer::startTransmit;
using PhysicalLayer::readData;
// constructor
@ -668,30 +670,6 @@ class SX127x: public PhysicalLayer {
*/
void setDio1Action(void (*func)(void));
/*!
\brief Interrupt-driven Arduino String transmit method. Will start transmitting Arduino String up to 255 characters long using %LoRa or up to 63 bytes using FSK modem.
Unlike the standard transmit method, this one is non-blocking. DIO0 will be activated when transmission finishes.
\param str Address of Arduino String that will be transmitted.
\param addr Node address to transmit the packet to. Only used in FSK mode.
\returns \ref status_codes
*/
int16_t startTransmit(String& str, uint8_t addr = 0);
/*!
\brief Interrupt-driven Arduino String transmit method. Will start transmitting Arduino String up to 255 characters long using %LoRa or up to 63 bytes using FSK modem.
Unlike the standard transmit method, this one is non-blocking. DIO0 will be activated when transmission finishes.
\param str C-string that will be transmitted.
\param addr Node address to transmit the packet to. Only used in FSK mode.
\returns \ref status_codes
*/
int16_t startTransmit(const char* str, uint8_t addr = 0);
/*!
\brief Interrupt-driven binary transmit method. Will start transmitting arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
@ -708,20 +686,11 @@ class SX127x: public PhysicalLayer {
/*!
\brief Interrupt-driven receive method. DIO0 will be activated when full valid packet is received.
\returns \ref status_codes
*/
int16_t startReceive();
/*!
\brief Reads data that was received after calling startReceive method.
\param str Address of Arduino String to save the received data.
\param len Expected number of characters in the message. Must be known in advance for %LoRa spreading factor 6.
\param mode Receive mode to be used. Defaults to RxContinuous.
\returns \ref status_codes
*/
int16_t readData(String& str, size_t len = 0);
int16_t startReceive(uint8_t mode = SX127X_RXCONTINUOUS);
/*!
\brief Reads data that was received after calling startReceive method.

View file

@ -13,6 +13,28 @@ int16_t PhysicalLayer::transmit(const char* str, uint8_t addr) {
return(transmit((uint8_t*)str, strlen(str), addr));
}
int16_t PhysicalLayer::startTransmit(String& str, uint8_t addr) {
return(startTransmit(str.c_str(), addr));
}
int16_t PhysicalLayer::startTransmit(const char* str, uint8_t addr) {
return(startTransmit((uint8_t*)str, strlen(str), addr));
}
int16_t PhysicalLayer::readData(String& str, size_t len) {
// create temporary array to store received data
char* data = new char[len + 1];
int16_t state = 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 PhysicalLayer::receive(String& str, size_t len) {
// create temporary array to store received data
char* data = new char[len + 1];

View file

@ -85,6 +85,65 @@ class PhysicalLayer {
*/
virtual int16_t receive(uint8_t* data, size_t len) = 0;
/*!
\brief Interrupt-driven Arduino String transmit method. Will start transmitting Arduino String up to 255 characters long using %LoRa or up to 63 bytes using FSK modem.
Unlike the standard transmit method, this one is non-blocking. DIO0 will be activated when transmission finishes.
\param str Address of Arduino String that will be transmitted.
\param addr Node address to transmit the packet to. Only used in FSK mode.
\returns \ref status_codes
*/
int16_t startTransmit(String& str, uint8_t addr = 0);
/*!
\brief Interrupt-driven Arduino String transmit method. Will start transmitting Arduino String up to 255 characters long using %LoRa or up to 63 bytes using FSK modem.
Unlike the standard transmit method, this one is non-blocking. DIO0 will be activated when transmission finishes.
\param str C-string that will be transmitted.
\param addr Node address to transmit the packet to. Only used in FSK mode.
\returns \ref status_codes
*/
int16_t startTransmit(const char* str, uint8_t addr = 0);
/*!
\brief Interrupt-driven binary transmit method. Will start transmitting arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
\param data Binary data that will be transmitted.
\param len Length of binary data to transmit (in bytes).
\param addr Node address to transmit the packet to. Only used in FSK mode.
\returns \ref status_codes
*/
virtual int16_t startTransmit(uint8_t* data, size_t len, uint8_t addr = 0) = 0;
/*!
\brief Reads data that was received after calling startReceive method.
\param str Address of Arduino String to save the received data.
\param len Expected number of characters in the message. Must be known in advance for %LoRa spreading factor 6.
\returns \ref status_codes
*/
int16_t readData(String& str, size_t len = 0);
/*!
\brief Reads data that was received after calling startReceive method.
\param data Pointer to array to save the received binary data.
\param len Number of bytes that will be received. Must be known in advance for binary transmissions.
\returns \ref status_codes
*/
virtual int16_t readData(uint8_t* data, size_t len) = 0;
/*!
\brief Enables direct transmission mode on pins DIO1 (clock) and DIO2 (data). Must be implemented in module class.
While in direct mode, the module will not be able to transmit or receive packets. Can only be activated in FSK mode.