From ad8c234343db014c47303b7cb4e3a5c87da3fc68 Mon Sep 17 00:00:00 2001 From: mmrein <55082189+mmrein@users.noreply.github.com> Date: Thu, 19 Sep 2019 23:09:02 +0200 Subject: [PATCH 1/2] SX126x FSK: Implement setWhitening method Add setWhitening method for FSK modem for possibility to disable whitening (default enabled) or change whitening initial value. --- keywords.txt | 1 + src/modules/SX126x.cpp | 55 +++++++++++++++++++++++++++++++++++------- src/modules/SX126x.h | 16 ++++++++++-- 3 files changed, 61 insertions(+), 11 deletions(-) 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..4d6b444f 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,38 @@ 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 { + // TODO: possibly take care of this note (pg. 65 of datasheet v1.2): "The user should not change the value of the 7 MSB's of this register." + // enable whitening + _whitening = SX126X_GFSK_WHITENING_ON; + // write initial whitening value + uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (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 +1123,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..324f97b3 100644 --- a/src/modules/SX126x.h +++ b/src/modules/SX126x.h @@ -655,6 +655,18 @@ 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. + The user should not change the value of the 7 MSB's of this register (pg. 65 of datasheet v1.2) + + \returns \ref status_codes + */ + int16_t setWhitening(bool enabled, uint16_t initial = 0x0100); + /*! \brief Sets TCXO (Temperature Compensated Crystal Oscillator) configuration. @@ -730,7 +742,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 +759,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; From 4388cfa06f4a59f5bfb4c35873bd1e40d27e3a4f Mon Sep 17 00:00:00 2001 From: mmrein <55082189+mmrein@users.noreply.github.com> Date: Fri, 20 Sep 2019 11:40:50 +0200 Subject: [PATCH 2/2] SX126x whitening: solved 7 MSBs Proper handling of the datasheet note for Whitening MSB register: "The user should not change the value of the 7 MSB's of this register" --- src/modules/SX126x.cpp | 18 +++++++++++++++--- src/modules/SX126x.h | 1 - 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/modules/SX126x.cpp b/src/modules/SX126x.cpp index 4d6b444f..982acaf8 100644 --- a/src/modules/SX126x.cpp +++ b/src/modules/SX126x.cpp @@ -877,20 +877,32 @@ int16_t SX126x::setWhitening(bool enabled, uint16_t initial) { if(enabled != true) { // disable whitening _whitening = SX126X_GFSK_WHITENING_OFF; + state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening); if(state != ERR_NONE) { return(state); } } else { - // TODO: possibly take care of this note (pg. 65 of datasheet v1.2): "The user should not change the value of the 7 MSB's of this register." // enable whitening _whitening = SX126X_GFSK_WHITENING_ON; + // write initial whitening value - uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF)}; - state = writeRegister(SX126X_REG_WHITENING_INITIAL_MSB, data, 2); + // 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); diff --git a/src/modules/SX126x.h b/src/modules/SX126x.h index 324f97b3..80a3841e 100644 --- a/src/modules/SX126x.h +++ b/src/modules/SX126x.h @@ -661,7 +661,6 @@ class SX126x: public PhysicalLayer { \param enabled True = Whitening enabled \param initial Initial value used for the whitening LFSR in FSK mode. - The user should not change the value of the 7 MSB's of this register (pg. 65 of datasheet v1.2) \returns \ref status_codes */