diff --git a/keywords.txt b/keywords.txt index 9aabb1c0..5feb6969 100644 --- a/keywords.txt +++ b/keywords.txt @@ -117,6 +117,8 @@ clearGdo2Action KEYWORD2 setTCXO KEYWORD2 setDio2AsRfSwitch KEYWORD2 getTimeOnAir KEYWORD2 +implicitHeader KEYWORD2 +explicitHeader KEYWORD2 setSyncBits KEYWORD2 setWhitening KEYWORD2 startReceiveDutyCycle KEYWORD2 diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 57007104..bc78ee7e 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -21,6 +21,8 @@ int16_t SX126x::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, float _crcType = SX126X_LORA_CRC_ON; _preambleLength = preambleLength; _tcxoDelay = 0; + _headerType = SX126X_LORA_HEADER_EXPLICIT; + _implicitLen = 0xFF; // reset the module and verify startup int16_t state = reset(); @@ -287,7 +289,6 @@ int16_t SX126x::receive(uint8_t* data, size_t len) { // calculate timeout (100 LoRa symbols, the default for SX127x series) float symbolLength = (float)(uint32_t(1) << _sf) / (float)_bwKhz; timeout = (uint32_t)(symbolLength * 100.0 * 1000.0); - } else if(modem == SX126X_PACKET_TYPE_GFSK) { // calculate timeout (500 % of expected time-one-air) size_t maxLen = len; @@ -449,7 +450,7 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) { int16_t state = ERR_NONE; uint8_t modem = getPacketType(); if(modem == SX126X_PACKET_TYPE_LORA) { - state = setPacketParams(_preambleLength, _crcType, len); + state = setPacketParams(_preambleLength, _crcType, len, _headerType); } else if(modem == SX126X_PACKET_TYPE_GFSK) { state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType, len); } else { @@ -598,6 +599,14 @@ int16_t SX126x::startReceiveCommon() { // clear interrupt flags state = clearIrqStatus(); + // set implicit mode and expected len if applicable + if(_headerType == SX126X_LORA_HEADER_IMPLICIT && getPacketType() == SX126X_PACKET_TYPE_LORA) { + state = setPacketParams(_preambleLength, _crcType, _implicitLen, _headerType); + if(state != ERR_NONE) { + return(state); + } + } + return(state); } @@ -741,7 +750,7 @@ int16_t SX126x::setPreambleLength(uint16_t preambleLength) { uint8_t modem = getPacketType(); if(modem == SX126X_PACKET_TYPE_LORA) { _preambleLength = preambleLength; - return(setPacketParams(_preambleLength, _crcType)); + return(setPacketParams(_preambleLength, _crcType, _implicitLen, _headerType)); } else if(modem == SX126X_PACKET_TYPE_GFSK) { _preambleLengthFSK = preambleLength; return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType)); @@ -1046,7 +1055,7 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool _crcType = SX126X_LORA_CRC_OFF; } - return(setPacketParams(_preambleLength, _crcType)); + return(setPacketParams(_preambleLength, _crcType, _implicitLen, _headerType)); } return(ERR_UNKNOWN); @@ -1150,7 +1159,7 @@ uint32_t SX126x::getTimeOnAir(size_t len) { sfDivisor = 4*(_sf - 2); } const int8_t bitsPerCrc = 16; - const int8_t N_symbol_header = 20; + const int8_t N_symbol_header = _headerType == SX126X_LORA_HEADER_EXPLICIT ? 20 : 0; // numerator of equation in section 6.1.4 of SX1268 datasheet v1.1 (might not actually be bitcount, but it has len * 8) int16_t bitCount = (int16_t) 8 * len + _crcType * bitsPerCrc - 4 * _sf + sfCoeff2 + N_symbol_header; @@ -1169,6 +1178,14 @@ uint32_t SX126x::getTimeOnAir(size_t len) { } } +int16_t SX126x::implicitHeader(size_t len) { + return(setHeaderType(SX126X_LORA_HEADER_IMPLICIT, len)); +} + +int16_t SX126x::explicitHeader() { + return(setHeaderType(SX126X_LORA_HEADER_EXPLICIT)); +} + int16_t SX126x::setTCXO(float voltage, uint32_t delay) { // set mode to standby standby(); @@ -1345,6 +1362,25 @@ int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) { return(state); } +int16_t SX126x::setHeaderType(uint8_t headerType, size_t len) { + // check active modem + if(getPacketType() != SX126X_PACKET_TYPE_LORA) { + return(ERR_WRONG_MODEM); + } + + // set requested packet mode + int16_t state = setPacketParams(_preambleLength, _crcType, len, headerType); + if(state != ERR_NONE) { + return(state); + } + + // update cached value + _headerType = headerType; + _implicitLen = len; + + return(state); +} + int16_t SX126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro) { // calculate symbol length and enable low data rate optimization, if needed if(ldro == 0xFF) { diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index d8cc8b70..8267f4cc 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -789,6 +789,22 @@ class SX126x: public PhysicalLayer { \returns Expected time-on-air in microseconds. */ uint32_t getTimeOnAir(size_t len); + + /*! + \brief Set implicit header mode for future reception/transmission. + + \returns \ref status_codes + */ + int16_t implicitHeader(size_t len); + + /*! + \brief Set explicit header mode for future reception/transmission. + + \param len Payload length in bytes. + + \returns \ref status_codes + */ + int16_t explicitHeader(); #ifndef RADIOLIB_GODMODE protected: #endif @@ -810,7 +826,7 @@ class SX126x: public PhysicalLayer { int16_t setTxParams(uint8_t power, uint8_t rampTime = SX126X_PA_RAMP_200U); int16_t setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro = 0xFF); int16_t setModulationParamsFSK(uint32_t br, uint8_t pulseShape, uint8_t rxBw, uint32_t freqDev); - int16_t setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength = 0xFF, uint8_t headerType = SX126X_LORA_HEADER_EXPLICIT, uint8_t invertIQ = SX126X_LORA_IQ_STANDARD); + int16_t setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength, uint8_t headerType, uint8_t invertIQ = SX126X_LORA_IQ_STANDARD); int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t payloadLength = 0xFF, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16); int16_t setBufferBaseAddress(uint8_t txBaseAddress = 0x00, uint8_t rxBaseAddress = 0x00); uint8_t getStatus(); @@ -822,6 +838,7 @@ class SX126x: public PhysicalLayer { int16_t setFrequencyRaw(float freq); int16_t setOptimalHiPowerPaConfig(int8_t* inOutPower); int16_t setPacketMode(uint8_t mode, uint8_t len); + int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF); // fixes to errata int16_t fixSensitivity(); @@ -834,7 +851,7 @@ class SX126x: public PhysicalLayer { #endif Module* _mod; - uint8_t _bw, _sf, _cr, _ldro, _crcType; + uint8_t _bw, _sf, _cr, _ldro, _crcType, _headerType; uint16_t _preambleLength; float _bwKhz; @@ -847,6 +864,8 @@ class SX126x: public PhysicalLayer { uint32_t _tcxoDelay; + size_t _implicitLen; + int16_t config(uint8_t modem); // common low-level SPI interface