diff --git a/keywords.txt b/keywords.txt index 9f0d6d10..76cf9f20 100644 --- a/keywords.txt +++ b/keywords.txt @@ -107,6 +107,7 @@ setTCXO KEYWORD2 setDio2AsRfSwitch KEYWORD2 getTimeOnAir KEYWORD2 setSyncBits KEYWORD2 +setWhitening KEYWORD2 # ESP8266 join KEYWORD2 diff --git a/src/modules/SX126x.cpp b/src/modules/SX126x.cpp index 99996ea8..982acaf8 100644 --- a/src/modules/SX126x.cpp +++ b/src/modules/SX126x.cpp @@ -134,6 +134,11 @@ int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, float currentLimit return(state); } + state = setWhitening(true, 0x0100); + if(state != ERR_NONE) { + return(state); + } + state = setDio2AsRfSwitch(false); return(state); @@ -365,7 +370,7 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) { if(modem == SX126X_PACKET_TYPE_LORA) { state = setPacketParams(_preambleLength, _crcType, len); } else if(modem == SX126X_PACKET_TYPE_GFSK) { - state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, len); + state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, len); } else { return(ERR_UNKNOWN); } @@ -554,7 +559,7 @@ int16_t SX126x::setPreambleLength(uint16_t preambleLength) { return(setPacketParams(_preambleLength, _crcType)); } else if(modem == SX126X_PACKET_TYPE_GFSK) { _preambleLengthFSK = preambleLength; - return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp)); + return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening)); } return(ERR_UNKNOWN); @@ -716,7 +721,7 @@ int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len) { // update packet parameters _syncWordLength = len * 8; - state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); + state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); return(state); } @@ -745,7 +750,7 @@ int16_t SX126x::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) { // update packet parameters _syncWordLength = bitsLen; - state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); + state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); return(state); } @@ -758,7 +763,7 @@ int16_t SX126x::setNodeAddress(uint8_t nodeAddr) { // enable address filtering (node only) _addrComp = SX126X_GFSK_ADDRESS_FILT_NODE; - int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); + int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); if(state != ERR_NONE) { return(state); } @@ -777,7 +782,7 @@ int16_t SX126x::setBroadcastAddress(uint8_t broadAddr) { // enable address filtering (node and broadcast) _addrComp = SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST; - int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); + int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); if(state != ERR_NONE) { return(state); } @@ -796,7 +801,7 @@ int16_t SX126x::disableAddressFiltering() { // disable address filtering _addrComp = SX126X_GFSK_ADDRESS_FILT_OFF; - return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp)); + return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening)); } int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) { @@ -827,7 +832,7 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool return(ERR_INVALID_CRC_CONFIGURATION); } - int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); + int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); if(state != ERR_NONE) { return(state); } @@ -862,6 +867,50 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool return(ERR_UNKNOWN); } +int16_t SX126x::setWhitening(bool enabled, uint16_t initial) { + // check active modem + if(getPacketType() != SX126X_PACKET_TYPE_GFSK) { + return(ERR_WRONG_MODEM); + } + + int16_t state = ERR_NONE; + if(enabled != true) { + // disable whitening + _whitening = SX126X_GFSK_WHITENING_OFF; + + state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); + if(state != ERR_NONE) { + return(state); + } + } else { + // enable whitening + _whitening = SX126X_GFSK_WHITENING_ON; + + // write initial whitening value + // as per note on pg. 65 of datasheet v1.2: "The user should not change the value of the 7 MSB's of this register" + uint8_t data[2]; + // first read the actual value and mask 7 MSB which we can not change + // if different value is written in 7 MSB, the Rx won't even work (tested on HW) + state = readRegister(SX126X_REG_WHITENING_INITIAL_MSB, data, 1); + if(state != ERR_NONE) { + return(state); + } + data[0] = (data[0] & 0xFE) | (uint8_t)((initial >> 8) & 0x01); + data[1] = (uint8_t)(initial & 0xFF); + state = writeRegister(SX126X_REG_WHITENING_INITIAL_MSB, data, 2); + + if(state != ERR_NONE) { + return(state); + } + + state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); + if(state != ERR_NONE) { + return(state); + } + } + return(state); +} + float SX126x::getDataRate() { return(_dataRate); } @@ -1086,7 +1135,7 @@ int16_t SX126x::setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_ return(SPIwriteCommand(SX126X_CMD_SET_PACKET_PARAMS, data, 6)); } -int16_t SX126x::setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t payloadLength, uint8_t packetType, uint8_t preambleDetectorLength, uint8_t whitening) { +int16_t SX126x::setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t payloadLength, uint8_t packetType, uint8_t preambleDetectorLength) { uint8_t data[9] = {(uint8_t)((preambleLength >> 8) & 0xFF), (uint8_t)(preambleLength & 0xFF), preambleDetectorLength, syncWordLength, addrComp, packetType, payloadLength, crcType, whitening}; diff --git a/src/modules/SX126x.h b/src/modules/SX126x.h index 072cf7ac..80a3841e 100644 --- a/src/modules/SX126x.h +++ b/src/modules/SX126x.h @@ -655,6 +655,17 @@ class SX126x: public PhysicalLayer { */ int16_t setCRC(uint8_t len, uint16_t initial = 0x1D0F, uint16_t polynomial = 0x1021, bool inverted = true); + /*! + \brief Sets FSK whitening parameters. + + \param enabled True = Whitening enabled + + \param initial Initial value used for the whitening LFSR in FSK mode. + + \returns \ref status_codes + */ + int16_t setWhitening(bool enabled, uint16_t initial = 0x0100); + /*! \brief Sets TCXO (Temperature Compensated Crystal Oscillator) configuration. @@ -730,7 +741,7 @@ class SX126x: public PhysicalLayer { 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 setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t payloadLength = 0xFF, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16, uint8_t whitening = SX126X_GFSK_WHITENING_ON); + int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t payloadLength = 0xFF, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16); int16_t setBufferBaseAddress(uint8_t txBaseAddress = 0x00, uint8_t rxBaseAddress = 0x00); uint8_t getStatus(); uint32_t getPacketStatus(); @@ -747,7 +758,7 @@ class SX126x: public PhysicalLayer { float _bwKhz; uint32_t _br, _freqDev; - uint8_t _rxBw, _pulseShape, _crcTypeFSK, _syncWordLength, _addrComp; + uint8_t _rxBw, _pulseShape, _crcTypeFSK, _syncWordLength, _addrComp, _whitening; uint16_t _preambleLengthFSK; float _rxBwKhz;