[SX127x] Sync with LoRaLib 8.1.0

This commit is contained in:
jgromes 2019-06-16 14:33:26 +02:00
parent cca121c85e
commit c72ad019f4
10 changed files with 236 additions and 101 deletions

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);
}
// check allowed range
if(preambleLength < 6) {
return(ERR_INVALID_PREAMBLE_LENGTH);
}
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
if(state != ERR_NONE) {
return(state);
}
// set preamble length
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_MSB, (preambleLength & 0xFF00) >> 8);
state |= _mod->SPIsetRegValue(SX127X_REG_PREAMBLE_LSB, preambleLength & 0x00FF);
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 preamble length
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();

View file

@ -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

View file

@ -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);
}

View file

@ -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