[SX127x] Sync with LoRaLib 8.1.0
This commit is contained in:
parent
cca121c85e
commit
c72ad019f4
10 changed files with 236 additions and 101 deletions
|
@ -162,7 +162,7 @@ ERR_NONE LITERAL1
|
|||
ERR_UNKNOWN LITERAL1
|
||||
|
||||
ERR_CHIP_NOT_FOUND LITERAL1
|
||||
ERR_EEPROM_NOT_INITIALIZED LITERAL1
|
||||
ERR_MEMORY_ALLOCATION_FAILED LITERAL1
|
||||
ERR_PACKET_TOO_LONG LITERAL1
|
||||
ERR_TX_TIMEOUT LITERAL1
|
||||
ERR_RX_TIMEOUT LITERAL1
|
||||
|
|
|
@ -150,9 +150,9 @@
|
|||
#define ERR_CHIP_NOT_FOUND -2
|
||||
|
||||
/*!
|
||||
\brief Deprecated.
|
||||
\brief Failed to allocate memory for temporary buffer. This can be cause by not enough RAM or by passing invalid pointer.
|
||||
*/
|
||||
#define ERR_EEPROM_NOT_INITIALIZED -3
|
||||
#define ERR_MEMORY_ALLOCATION_FAILED -3
|
||||
|
||||
/*!
|
||||
\brief Packet supplied to transmission method was longer than limit.
|
||||
|
|
|
@ -58,9 +58,9 @@ int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t currentLimit, bool enableOOK) {
|
||||
int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::beginFSK(SX1272_CHIP_VERSION, br, rxBw, freqDev, currentLimit, enableOOK);
|
||||
int16_t state = SX127x::beginFSK(SX1272_CHIP_VERSION, br, rxBw, freqDev, currentLimit, preambleLength, enableOOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -294,13 +294,14 @@ int16_t SX1272::setDataShaping(float sh) {
|
|||
int16_t state = SX127x::standby();
|
||||
|
||||
// set data shaping
|
||||
sh *= 10.0;
|
||||
if(abs(sh - 0.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_NO_SHAPING, 4, 3);
|
||||
} else if(abs(sh - 0.3) <= 0.001) {
|
||||
} else if(abs(sh - 3.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_0_3, 4, 3);
|
||||
} else if(abs(sh - 0.5) <= 0.001) {
|
||||
} else if(abs(sh - 5.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_0_5, 4, 3);
|
||||
} else if(abs(sh - 1.0) <= 0.001) {
|
||||
} else if(abs(sh - 10.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_1_0, 4, 3);
|
||||
} else {
|
||||
return(ERR_INVALID_DATA_SHAPING);
|
||||
|
|
|
@ -148,11 +148,13 @@ class SX1272: public SX127x {
|
|||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of FSK preamble in bits.
|
||||
|
||||
\param enableOOK Use OOK modulation instead of FSK.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float freq = 915.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 13, uint8_t currentLimit = 100, bool enableOOK = false);
|
||||
int16_t beginFSK(float freq = 915.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 13, uint8_t currentLimit = 100, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
|
|
@ -51,9 +51,9 @@ int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t currentLimit, bool enableOOK) {
|
||||
int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// execute common part
|
||||
int16_t state = SX127x::beginFSK(SX1278_CHIP_VERSION, br, freqDev, rxBw, currentLimit, enableOOK);
|
||||
int16_t state = SX127x::beginFSK(SX1278_CHIP_VERSION, br, freqDev, rxBw, currentLimit, preambleLength, enableOOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -364,13 +364,14 @@ int16_t SX1278::setDataShaping(float sh) {
|
|||
int16_t state = SX127x::standby();
|
||||
|
||||
// set data shaping
|
||||
sh *= 10.0;
|
||||
if(abs(sh - 0.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_NO_SHAPING, 6, 5);
|
||||
} else if(abs(sh - 0.3) <= 0.001) {
|
||||
} else if(abs(sh - 3.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_0_3, 6, 5);
|
||||
} else if(abs(sh - 0.5) <= 0.001) {
|
||||
} else if(abs(sh - 5.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_0_5, 6, 5);
|
||||
} else if(abs(sh - 1.0) <= 0.001) {
|
||||
} else if(abs(sh - 10.0) <= 0.001) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_FSK_GAUSSIAN_1_0, 6, 5);
|
||||
} else {
|
||||
return(ERR_INVALID_DATA_SHAPING);
|
||||
|
|
|
@ -157,11 +157,13 @@ class SX1278: public SX127x {
|
|||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of FSK preamble in bits.
|
||||
|
||||
\param enableOOK Use OOK modulation instead of FSK.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 13, uint8_t currentLimit = 100, bool enableOOK = false);
|
||||
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 13, uint8_t currentLimit = 100, uint16_t preambleLength = 16, bool enableOOK = false);
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include "SX127x.h"
|
||||
|
||||
SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_CRYSTAL_FREQ, SX127X_DIV_EXPONENT) {
|
||||
SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_CRYSTAL_FREQ, SX127X_DIV_EXPONENT, SX127X_MAX_PACKET_LENGTH) {
|
||||
_mod = mod;
|
||||
_packetLengthQueried = false;
|
||||
}
|
||||
|
||||
int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength) {
|
||||
|
@ -48,7 +49,7 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, bool enableOOK) {
|
||||
int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
|
||||
|
@ -95,6 +96,12 @@ int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxB
|
|||
return(state);
|
||||
}
|
||||
|
||||
// set preamble length
|
||||
state = SX127x::setPreambleLength(preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// default sync word value 0x2D01 is the same as the default in LowPowerLab RFM69 library
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, 2);
|
||||
|
@ -130,7 +137,7 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
float crc = (float)(_mod->SPIgetRegValue(SX127X_REG_MODEM_CONFIG_2, 2, 2) >> 2);
|
||||
float n_pre = (float)((_mod->SPIgetRegValue(SX127X_REG_PREAMBLE_MSB) << 8) | _mod->SPIgetRegValue(SX127X_REG_PREAMBLE_LSB));
|
||||
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);
|
||||
uint32_t timeout = ceil(symbolLength * (n_pre + n_pay + 4.25) * 1500.0);
|
||||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
|
@ -139,17 +146,17 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
uint32_t start = millis();
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
if(millis() - start > timeout) {
|
||||
if(micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
uint32_t elapsed = millis() - start;
|
||||
uint32_t elapsed = micros() - start;
|
||||
|
||||
// update data rate
|
||||
_dataRate = (len*8.0)/((float)elapsed/1000.0);
|
||||
_dataRate = (len*8.0)/((float)elapsed/1000000.0);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
@ -157,8 +164,8 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(ERR_NONE);
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// calculate timeout (150 % of expected time-on-air)
|
||||
uint32_t timeout = (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 1500.0);
|
||||
// calculate timeout (5ms + 150 % of expected time-on-air)
|
||||
uint32_t timeout = 5000 + (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 1500000.0);
|
||||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
|
@ -167,9 +174,9 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
// wait for transmission end or timeout
|
||||
uint32_t start = millis();
|
||||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
if(millis() - start > timeout) {
|
||||
if(micros() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
standby();
|
||||
return(ERR_TX_TIMEOUT);
|
||||
|
@ -195,7 +202,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
int16_t modem = getActiveModem();
|
||||
if(modem == SX127X_LORA) {
|
||||
// set mode to receive
|
||||
state = startReceive(SX127X_RXSINGLE);
|
||||
state = startReceive(len, SX127X_RXSINGLE);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -208,19 +215,12 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
// read the received data
|
||||
return(readData(data, len));
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// 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)) * 5000.0);
|
||||
uint32_t timeout = (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 5000.0);
|
||||
|
||||
// set mode to receive
|
||||
state = startReceive(SX127X_RX);
|
||||
state = startReceive(len, SX127X_RX);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -233,12 +233,12 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// read the received data
|
||||
return(readData(data, len));
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
// read the received data
|
||||
state = readData(data, len);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX127x::scanChannel() {
|
||||
|
@ -351,7 +351,7 @@ int16_t SX127x::packetMode() {
|
|||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_2, SX127X_DATA_MODE_PACKET, 6, 6));
|
||||
}
|
||||
|
||||
int16_t SX127x::startReceive(uint8_t mode) {
|
||||
int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
|
||||
|
@ -360,6 +360,11 @@ int16_t SX127x::startReceive(uint8_t mode) {
|
|||
// set DIO pin mapping
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_RX_DONE | SX127X_DIO1_RX_TIMEOUT, 7, 4);
|
||||
|
||||
// set expected packet length for SF6
|
||||
if(_sf == 6) {
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH, len);
|
||||
}
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
||||
|
@ -469,7 +474,13 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t SX127x::readData(uint8_t* data, size_t len) {
|
||||
int16_t modem = getActiveModem();
|
||||
size_t length = len;
|
||||
|
||||
if(modem == SX127X_LORA) {
|
||||
// len set to maximum indicates unknown packet length, read the number of actually received bytes
|
||||
if(len == SX127X_MAX_PACKET_LENGTH) {
|
||||
length = getPacketLength();
|
||||
}
|
||||
|
||||
// check integrity CRC
|
||||
if(_mod->SPIgetRegValue(SX127X_REG_IRQ_FLAGS, 5, 5) == SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR) {
|
||||
// clear interrupt flags
|
||||
|
@ -478,14 +489,9 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
|
|||
return(ERR_CRC_MISMATCH);
|
||||
}
|
||||
|
||||
// get packet length
|
||||
if(_sf != 6) {
|
||||
length = _mod->SPIgetRegValue(SX127X_REG_RX_NB_BYTES);
|
||||
}
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// get packet length
|
||||
length = _mod->SPIreadRegister(SX127X_REG_FIFO);
|
||||
// read packet length (always required in FSK)
|
||||
length = getPacketLength();
|
||||
|
||||
// check address filtering
|
||||
uint8_t filter = _mod->SPIgetRegValue(SX127X_REG_PACKET_CONFIG_1, 2, 1);
|
||||
|
@ -495,16 +501,16 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
// 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;
|
||||
// dump bytes that weren't requested
|
||||
size_t packetLength = getPacketLength();
|
||||
if(packetLength > length) {
|
||||
clearFIFO(packetLength - length);
|
||||
}
|
||||
|
||||
// clear internal flag so getPacketLength can return the new packet length
|
||||
_packetLengthQueried = false;
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
|
@ -550,23 +556,33 @@ int16_t SX127x::setCurrentLimit(uint8_t currentLimit) {
|
|||
}
|
||||
|
||||
int16_t SX127x::setPreambleLength(uint16_t preambleLength) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// check active modem
|
||||
uint8_t modem = getActiveModem();
|
||||
if(modem == SX127X_LORA) {
|
||||
// check allowed range
|
||||
if(preambleLength < 6) {
|
||||
return(ERR_INVALID_PREAMBLE_LENGTH);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = setMode(SX127X_STANDBY);
|
||||
|
||||
// set preamble length
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB, (preambleLength & 0xFF00) >> 8);
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB, (preambleLength & 0xFF00) >> 8);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB, preambleLength & 0x00FF);
|
||||
return(state);
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// set preamble length
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB_FSK, (preambleLength & 0xFF00) >> 8);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB_FSK, preambleLength & 0x00FF);
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
float SX127x::getFrequencyError(bool autoCorrect) {
|
||||
|
@ -740,7 +756,6 @@ int16_t SX127x::setRxBandwidth(float rxBw) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
|
@ -862,6 +877,30 @@ int16_t SX127x::setFrequencyRaw(float newFreq) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
size_t SX127x::getPacketLength(bool update) {
|
||||
int16_t modem = getActiveModem();
|
||||
|
||||
if(modem == SX127X_LORA) {
|
||||
if(_sf != 6) {
|
||||
// get packet length for SF7 - SF12
|
||||
return(_mod->SPIreadRegister(SX127X_REG_RX_NB_BYTES));
|
||||
|
||||
} else {
|
||||
// return the maximum value for SF6
|
||||
return(SX127X_MAX_PACKET_LENGTH);
|
||||
}
|
||||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// get packet length
|
||||
if(!_packetLengthQueried && update) {
|
||||
_packetLength = _mod->SPIreadRegister(SX127X_REG_FIFO);
|
||||
_packetLengthQueried = true;
|
||||
}
|
||||
}
|
||||
|
||||
return(_packetLength);
|
||||
}
|
||||
|
||||
int16_t SX127x::config() {
|
||||
// turn off frequency hopping
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_HOP_PERIOD, SX127X_HOP_PERIOD_OFF);
|
||||
|
@ -879,12 +918,18 @@ int16_t SX127x::configFSK() {
|
|||
_mod->SPIwriteRegister(SX127X_REG_IRQ_FLAGS_2, SX127X_FLAG_FIFO_OVERRUN);
|
||||
|
||||
// set packet configuration
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_PACKET_VARIABLE | SX127X_DC_FREE_NONE | SX127X_CRC_ON | SX127X_CRC_AUTOCLEAR_ON, 7, 3);
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_PACKET_VARIABLE | SX127X_DC_FREE_WHITENING | SX127X_CRC_ON | SX127X_CRC_AUTOCLEAR_ON | SX127X_ADDRESS_FILTERING_OFF | SX127X_CRC_WHITENING_TYPE_CCITT, 7, 0);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_2, SX127X_DATA_MODE_PACKET | SX127X_IO_HOME_OFF, 6, 5);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set preamble polarity
|
||||
state =_mod->SPIsetRegValue(SX127X_REG_SYNC_CONFIG, SX127X_PREAMBLE_POLARITY_55, 5, 5);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set FIFO threshold
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_FIFO_THRESH, SX127X_TX_START_FIFO_NOT_EMPTY, 7, 7);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_THRESH, SX127X_FIFO_THRESH, 5, 0);
|
||||
|
@ -901,7 +946,7 @@ int16_t SX127x::configFSK() {
|
|||
}
|
||||
|
||||
// enable preamble detector and set preamble length
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_DETECT, SX127X_PREAMBLE_DETECTOR_ON | SX127X_PREAMBLE_DETECTOR_1_BYTE | SX127X_PREAMBLE_DETECTOR_TOL);
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_DETECT, SX127X_PREAMBLE_DETECTOR_ON | SX127X_PREAMBLE_DETECTOR_2_BYTE | SX127X_PREAMBLE_DETECTOR_TOL);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB_FSK, SX127X_PREAMBLE_SIZE_MSB);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB_FSK, SX127X_PREAMBLE_SIZE_LSB);
|
||||
if(state != ERR_NONE) {
|
||||
|
@ -969,6 +1014,13 @@ void SX127x::clearIRQFlags() {
|
|||
}
|
||||
}
|
||||
|
||||
void SX127x::clearFIFO(size_t count) {
|
||||
while(count) {
|
||||
_mod->SPIreadRegister(SX127X_REG_FIFO);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
void SX127x::regDump() {
|
||||
Serial.println();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// SX127x physical layer properties
|
||||
#define SX127X_CRYSTAL_FREQ 32.0
|
||||
#define SX127X_DIV_EXPONENT 19
|
||||
#define SX127X_MAX_PACKET_LENGTH 256
|
||||
|
||||
// SX127x series common LoRa registers
|
||||
#define SX127X_REG_FIFO 0x00
|
||||
|
@ -574,11 +575,13 @@ class SX127x: public PhysicalLayer {
|
|||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA.
|
||||
|
||||
\param preambleLength Length of FSK preamble in bits.
|
||||
|
||||
\param enableOOK Flag to specify OOK mode. This modulation is similar to FSK.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, bool enableOOK);
|
||||
int16_t beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK);
|
||||
|
||||
/*!
|
||||
\brief Binary transmit method. Will transmit arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
|
||||
|
@ -686,14 +689,16 @@ class SX127x: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Interrupt-driven receive method. DIO0 will be activated when full valid packet is received.
|
||||
|
||||
\param len Expected length of packet to be received. Required for LoRa spreading factor 6.
|
||||
|
||||
\param mode Receive mode to be used. Defaults to RxContinuous.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint8_t mode = SX127X_RXCONTINUOUS);
|
||||
int16_t startReceive(uint8_t len = 0, uint8_t mode = SX127X_RXCONTINUOUS);
|
||||
|
||||
/*!
|
||||
\brief Reads data that was received after calling startReceive method.
|
||||
\brief Reads data that was received after calling startReceive method. This method reads len characters.
|
||||
|
||||
\param data Pointer to array to save the received binary data.
|
||||
|
||||
|
@ -828,6 +833,15 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setOOK(bool enableOOK);
|
||||
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
|
||||
\param update Update received packet length. Will return cached value when set to false.
|
||||
|
||||
\returns Length of last received packet in bytes.
|
||||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
void regDump();
|
||||
#endif
|
||||
|
@ -849,13 +863,17 @@ class SX127x: public PhysicalLayer {
|
|||
int16_t getActiveModem();
|
||||
int16_t directMode();
|
||||
|
||||
|
||||
private:
|
||||
float _dataRate;
|
||||
size_t _packetLength;
|
||||
bool _packetLengthQueried; // FSK packet length is the first byte in FIFO, length can only be queried once
|
||||
|
||||
bool findChip(uint8_t ver);
|
||||
int16_t setMode(uint8_t mode);
|
||||
int16_t setActiveModem(uint8_t modem);
|
||||
void clearIRQFlags();
|
||||
void clearFIFO(size_t count); // used mostly to clear remaining bytes in FIFO after a packet read
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include "PhysicalLayer.h"
|
||||
|
||||
PhysicalLayer::PhysicalLayer(float crysFreq, uint8_t divExp) {
|
||||
PhysicalLayer::PhysicalLayer(float crysFreq, uint8_t divExp, size_t maxPacketLength) {
|
||||
_crystalFreq = crysFreq;
|
||||
_divExponent = divExp;
|
||||
_maxPacketLength = maxPacketLength;
|
||||
}
|
||||
|
||||
int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
|
||||
|
@ -49,30 +50,76 @@ int16_t PhysicalLayer::startTransmit(const char* str, uint8_t 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);
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
// if packet was received successfully, copy data into String
|
||||
if(state == ERR_NONE) {
|
||||
str = String(data);
|
||||
// read the number of actually received bytes
|
||||
size_t length = getPacketLength();
|
||||
|
||||
if((len < length) && (len != 0)) {
|
||||
// user requested less bytes than were received, this is allowed (but frowned upon)
|
||||
// requests for more data than were received will only return the number of actually received bytes (unlike PhysicalLayer::receive())
|
||||
length = len;
|
||||
}
|
||||
|
||||
// build a temporary buffer
|
||||
uint8_t* data = new uint8_t[length + 1];
|
||||
if(!data) {
|
||||
return(ERR_MEMORY_ALLOCATION_FAILED);
|
||||
}
|
||||
|
||||
// read the received data
|
||||
state = readData(data, length);
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
// add null terminator
|
||||
data[length] = 0;
|
||||
|
||||
// initialize Arduino String class
|
||||
str = String((char*)data);
|
||||
}
|
||||
|
||||
// deallocate temporary buffer
|
||||
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];
|
||||
int16_t state = receive((uint8_t*)data, len);
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
// if packet was received successfully, copy data into String
|
||||
if(state == ERR_NONE) {
|
||||
str = String(data);
|
||||
// user can override the length of data to read
|
||||
size_t length = len;
|
||||
|
||||
if(len == 0) {
|
||||
// unknown packet length, set to maximum
|
||||
length = _maxPacketLength;
|
||||
}
|
||||
|
||||
// build a temporary buffer
|
||||
uint8_t* data = new uint8_t[length + 1];
|
||||
if(!data) {
|
||||
return(ERR_MEMORY_ALLOCATION_FAILED);
|
||||
}
|
||||
|
||||
// attempt packet reception
|
||||
state = receive(data, length);
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
// read the number of actually received bytes (for unknown packets)
|
||||
if(len == 0) {
|
||||
length = getPacketLength(false);
|
||||
}
|
||||
|
||||
// add null terminator
|
||||
data[length] = 0;
|
||||
|
||||
// initialize Arduino String class
|
||||
str = String((char*)data);
|
||||
}
|
||||
|
||||
// deallocate temporary buffer
|
||||
delete[] data;
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,10 @@ class PhysicalLayer {
|
|||
\param crysFreq Frequency of crystal oscillator inside the module in MHz.
|
||||
|
||||
\param divExp Exponent of module frequency divider.
|
||||
|
||||
\param maxPacketLength Maximum length of packet that can be received by the module-
|
||||
*/
|
||||
PhysicalLayer(float crysFreq, uint8_t divExp);
|
||||
PhysicalLayer(float crysFreq, uint8_t divExp, size_t maxPacketLength);
|
||||
|
||||
// basic methods
|
||||
|
||||
|
@ -77,12 +79,19 @@ class PhysicalLayer {
|
|||
|
||||
\param str Address of Arduino String to save the received data.
|
||||
|
||||
\param len Expected number of characters in the message.
|
||||
\param len Expected number of characters in the message. Leave as 0 if expecting a unknown size packet
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t receive(String& str, size_t len = 0);
|
||||
|
||||
/*!
|
||||
\brief Sets module to standby.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
virtual int16_t standby() = 0;
|
||||
|
||||
/*!
|
||||
\brief Binary receive method. Must be implemented in module class.
|
||||
|
||||
|
@ -94,13 +103,6 @@ class PhysicalLayer {
|
|||
*/
|
||||
virtual int16_t receive(uint8_t* data, size_t len) = 0;
|
||||
|
||||
/*!
|
||||
\brief Sets module to standby.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
virtual int16_t standby() = 0;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven Arduino String transmit method. Unlike the standard transmit method, this one is non-blocking.
|
||||
Interrupt pin will be activated when transmission finishes.
|
||||
|
@ -168,7 +170,7 @@ class PhysicalLayer {
|
|||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
virtual int16_t transmitDirect(uint32_t frf = 0) = 0;
|
||||
virtual int16_t transmitDirect(uint32_t FRF = 0) = 0;
|
||||
|
||||
/*!
|
||||
\brief Enables direct reception mode on pins DIO1 (clock) and DIO2 (data). Must be implemented in module class.
|
||||
|
@ -204,9 +206,19 @@ class PhysicalLayer {
|
|||
*/
|
||||
uint8_t getDivExponent();
|
||||
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
|
||||
\param update Update received packet length. Will return cached value when set to false.
|
||||
|
||||
\returns Length of last received packet in bytes.
|
||||
*/
|
||||
virtual size_t getPacketLength(bool update = true) = 0;
|
||||
|
||||
private:
|
||||
float _crystalFreq;
|
||||
uint8_t _divExponent;
|
||||
size_t _maxPacketLength;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue