From e1c79af18b756179c12f1eb53a4476261e788cd8 Mon Sep 17 00:00:00 2001 From: jgromes Date: Sat, 22 Jun 2019 16:37:57 +0200 Subject: [PATCH] [SX126x] Added OCP config reset --- src/modules/SX1262.cpp | 27 ++++---- src/modules/SX1268.cpp | 27 ++++---- src/modules/SX126x.cpp | 138 ++++++++++++++++++++++------------------- src/modules/SX126x.h | 30 ++++----- 4 files changed, 112 insertions(+), 110 deletions(-) diff --git a/src/modules/SX1262.cpp b/src/modules/SX1262.cpp index 218751ab..0bcce47d 100644 --- a/src/modules/SX1262.cpp +++ b/src/modules/SX1262.cpp @@ -6,7 +6,7 @@ SX1262::SX1262(Module* mod) : SX126x(mod) { int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, int8_t power, float currentLimit, uint16_t preambleLength) { // execute common part - int16_t state = SX126x::begin(bw, sf, cr, syncWord, preambleLength); + int16_t state = SX126x::begin(bw, sf, cr, syncWord, currentLimit, preambleLength); if(state != ERR_NONE) { return(state); } @@ -22,18 +22,12 @@ int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syn return(state); } - // OCP must be configured after PA - state = SX126x::setCurrentLimit(currentLimit); - if(state != ERR_NONE) { - return(state); - } - return(state); } int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping) { // execute common part - int16_t state = SX126x::beginFSK(br, freqDev, rxBw, preambleLength, dataShaping); + int16_t state = SX126x::beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping); if(state != ERR_NONE) { return(state); } @@ -49,12 +43,6 @@ int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t return(state); } - // OCP must be configured after PA - state = SX126x::setCurrentLimit(currentLimit); - if(state != ERR_NONE) { - return(state); - } - return(state); } @@ -101,6 +89,13 @@ int16_t SX1262::setOutputPower(int8_t power) { return(ERR_INVALID_OUTPUT_POWER); } + // get current OCP configuration + uint8_t ocp = 0; + int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1); + if(state != ERR_NONE) { + return(state); + } + // enable high power PA for output power higher than 14 dBm if(power > 13) { SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262); @@ -111,5 +106,7 @@ int16_t SX1262::setOutputPower(int8_t power) { // set output power // TODO power ramp time configuration SX126x::setTxParams(power); - return(ERR_NONE); + + // restore OCP configuration + return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1)); } diff --git a/src/modules/SX1268.cpp b/src/modules/SX1268.cpp index 95718f0c..c0b01a80 100644 --- a/src/modules/SX1268.cpp +++ b/src/modules/SX1268.cpp @@ -6,7 +6,7 @@ SX1268::SX1268(Module* mod) : SX126x(mod) { int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, int8_t power, float currentLimit, uint16_t preambleLength) { // execute common part - int16_t state = SX126x::begin(bw, sf, cr, syncWord, preambleLength); + int16_t state = SX126x::begin(bw, sf, cr, syncWord, currentLimit, preambleLength); if(state != ERR_NONE) { return(state); } @@ -22,17 +22,11 @@ int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syn return(state); } - // OCP must be configured after PA - state = SX126x::setCurrentLimit(currentLimit); - if(state != ERR_NONE) { - return(state); - } - return(state); } int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping) { // execute common part - int16_t state = SX126x::beginFSK(br, freqDev, rxBw, preambleLength, dataShaping); + int16_t state = SX126x::beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping); if(state != ERR_NONE) { return(state); } @@ -48,12 +42,6 @@ int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t return(state); } - // OCP must be configured after PA - state = SX126x::setCurrentLimit(currentLimit); - if(state != ERR_NONE) { - return(state); - } - return(state); } @@ -94,11 +82,20 @@ int16_t SX1268::setOutputPower(int8_t power) { return(ERR_INVALID_OUTPUT_POWER); } + // get current OCP configuration + uint8_t ocp = 0; + int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1); + if(state != ERR_NONE) { + return(state); + } + // enable high power PA SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1268); // set output power // TODO power ramp time configuration SX126x::setTxParams(power); - return(ERR_NONE); + + // restore OCP configuration + return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1)); } diff --git a/src/modules/SX126x.cpp b/src/modules/SX126x.cpp index b6efdc00..5a90af65 100644 --- a/src/modules/SX126x.cpp +++ b/src/modules/SX126x.cpp @@ -447,7 +447,10 @@ int16_t SX126x::readData(uint8_t* data, size_t len) { } // get packet length - size_t length = getPacketLength(); + size_t length = len; + if(len == SX126X_MAX_PACKET_LENGTH) { + length = getPacketLength(); + } // read packet data int16_t state = readBuffer(data, length); @@ -774,67 +777,67 @@ int16_t SX126x::disableAddressFiltering() { return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp)); } -int16_t SX126x::setCRC(bool enableCRC) { - // check active modem - if(getPacketType() != SX126X_PACKET_TYPE_LORA) { - return(ERR_WRONG_MODEM); - } - - // update packet parameters - if(enableCRC) { - _crcType = SX126X_LORA_CRC_ON; - } else { - _crcType = SX126X_LORA_CRC_OFF; - } - return(setPacketParams(_preambleLength, _crcType)); -} - int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) { // check active modem - if(getPacketType() != SX126X_PACKET_TYPE_GFSK) { - return(ERR_WRONG_MODEM); - } + uint8_t modem = getPacketType(); + + if(modem == SX126X_PACKET_TYPE_GFSK) { + // update packet parameters + switch(len) { + case 0: + _crcTypeFSK = SX126X_GFSK_CRC_OFF; + break; + case 1: + if(inverted) { + _crcTypeFSK = SX126X_GFSK_CRC_1_BYTE_INV; + } else { + _crcTypeFSK = SX126X_GFSK_CRC_1_BYTE; + } + break; + case 2: + if(inverted) { + _crcTypeFSK = SX126X_GFSK_CRC_2_BYTE_INV; + } else { + _crcTypeFSK = SX126X_GFSK_CRC_2_BYTE; + } + break; + default: + return(ERR_INVALID_CRC_CONFIGURATION); + } + + int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); + if(state != ERR_NONE) { + return(state); + } + + // write initial CRC value + uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF)}; + state = writeRegister(SX126X_REG_CRC_INITIAL_MSB, data, 2); + if(state != ERR_NONE) { + return(state); + } + + // write CRC polynomial value + data[0] = (uint8_t)((polynomial >> 8) & 0xFF); + data[1] = (uint8_t)(polynomial & 0xFF); + state = writeRegister(SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2); - // update packet parameters - switch(len) { - case 0: - _crcTypeFSK = SX126X_GFSK_CRC_OFF; - break; - case 1: - if(inverted) { - _crcTypeFSK = SX126X_GFSK_CRC_1_BYTE_INV; - } else { - _crcTypeFSK = SX126X_GFSK_CRC_1_BYTE; - } - break; - case 2: - if(inverted) { - _crcTypeFSK = SX126X_GFSK_CRC_2_BYTE_INV; - } else { - _crcTypeFSK = SX126X_GFSK_CRC_2_BYTE; - } - break; - default: - return(ERR_INVALID_CRC_CONFIGURATION); - } - int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); - if(state != ERR_NONE) { return(state); + + } else if(modem == SX126X_PACKET_TYPE_LORA) { + // LoRa CRC doesn't allow to set CRC polynomial, inital value, or inversion + + // update packet parameters + if(len) { + _crcType = SX126X_LORA_CRC_ON; + } else { + _crcType = SX126X_LORA_CRC_OFF; + } + + return(setPacketParams(_preambleLength, _crcType)); } - // write initial CRC value - uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF)}; - state = writeRegister(SX126X_REG_CRC_INITIAL_MSB, data, 2); - if(state != ERR_NONE) { - return(state); - } - - // write CRC polynomial value - data[0] = (uint8_t)((polynomial >> 8) & 0xFF); - data[1] = (uint8_t)(polynomial & 0xFF); - state = writeRegister(SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2); - - return(state); + return(ERR_UNKNOWN); } float SX126x::getDataRate() { @@ -944,6 +947,11 @@ int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { return(state); } +int16_t SX126x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { + uint8_t cmd[] = {SX126X_CMD_READ_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF)}; + return(SX126x::SPItransfer(cmd, 3, false, NULL, data, numBytes, true)); +} + int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) { uint8_t* dat = new uint8_t[1 + numBytes]; dat[0] = offset; @@ -1148,14 +1156,16 @@ int16_t SX126x::config(uint8_t modem) { } int16_t SX126x::SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) { - return(SX126x::SPItransfer(cmd, true, data, NULL, numBytes, waitForBusy)); + uint8_t cmdBuffer[] = {cmd}; + return(SX126x::SPItransfer(cmdBuffer, 1, true, data, NULL, numBytes, waitForBusy)); } int16_t SX126x::SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) { - return(SX126x::SPItransfer(cmd, false, NULL, data, numBytes, waitForBusy)); + uint8_t cmdBuffer[] = {cmd}; + return(SX126x::SPItransfer(cmdBuffer, 1, false, NULL, data, numBytes, waitForBusy)); } -int16_t SX126x::SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy) { +int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy) { // get pointer to used SPI interface and the settings SPIClass* spi = _mod->getSpi(); SPISettings spiSettings = _mod->getSpiSettings(); @@ -1168,10 +1178,12 @@ int16_t SX126x::SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* digitalWrite(_mod->getCs(), LOW); spi->beginTransaction(spiSettings); - // send command byte - spi->transfer(cmd); - DEBUG_PRINT(cmd, HEX); - DEBUG_PRINT('\t'); + // send command byte(s) + for(uint8_t n = 0; n < cmdLen; n++) { + spi->transfer(cmd[n]); + DEBUG_PRINT(cmd[n], HEX); + DEBUG_PRINT('\t'); + } // variable to save error during SPI transfer uint8_t status = 0; diff --git a/src/modules/SX126x.h b/src/modules/SX126x.h index 696c728e..0662e508 100644 --- a/src/modules/SX126x.h +++ b/src/modules/SX126x.h @@ -351,11 +351,13 @@ class SX126x: public PhysicalLayer { \param syncWord 2-byte LoRa sync word. + \param currentLimit Current protection limit in mA. + \param preambleLength LoRa preamble length in symbols. Allowed values range from 1 to 65535. \returns \ref status_codes */ - int16_t begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, uint16_t preambleLength); + int16_t begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, float currentLimit, uint16_t preambleLength); /*! \brief Initialization method for FSK modem. @@ -366,13 +368,15 @@ class SX126x: public PhysicalLayer { \param rxBw Receiver bandwidth in kHz. Allowed values are 4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2, 93.8, 117.3, 156.2, 187.2, 234.3, 312.0, 373.6 and 467.0 kHz. + \param currentLimit Current protection limit in mA. + \param preambleLength FSK preamble length in bits. Allowed values range from 0 to 65535. \param dataShaping Time-bandwidth product of the Gaussian filter to be used for shaping. Allowed values are 0.3, 0.5, 0.7 and 1.0. Set to 0 to disable shaping. \returns \ref status_codes */ - int16_t beginFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float dataShaping); + int16_t beginFSK(float br, float freqDev, float rxBw, float currentLimit, uint16_t preambleLength, float dataShaping); /*! \brief Blocking binary transmit method. @@ -626,24 +630,15 @@ class SX126x: public PhysicalLayer { int16_t disableAddressFiltering(); /*! - \brief Sets LoRa CRC. + \brief Sets CRC configuration. - \param enableCRC Enable or disable LoRa CRC. + \param len CRC length in bytes, Allowed values are 1 or 2, set to 0 to disable CRC. - \returns \ref status_codes - */ - int16_t setCRC(bool enableCRC); + \param initial Initial CRC value. FSK only. Defaults to 0x1D0F (CCIT CRC). - /*! - \brief Sets FSK CRC configuration. + \param polynomial Polynomial for CRC calculation. FSK only. Defaults to 0x1021 (CCIT CRC). - \param len CRC length in bytes, Allowed values are 1 or 2, set to 0 to disable FSK CRC. - - \param initial Initial CRC value. Defaults to 0x1D0F (CCIT CRC). - - \param polynomial Polynomial for CRC calculation. Defaults to 0x1021 (CCIT CRC). - - \param inverted Invert CRC bytes. Defaults to true (CCIT CRC) + \param inverted Invert CRC bytes. FSK only. Defaults to true (CCIT CRC). \returns \ref status_codes */ @@ -702,6 +697,7 @@ class SX126x: public PhysicalLayer { int16_t setCad(); int16_t setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMax = SX126X_PA_CONFIG_HP_MAX, uint8_t paLut = SX126X_PA_CONFIG_PA_LUT); int16_t writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes); + int16_t readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes); int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00); int16_t readBuffer(uint8_t* data, uint8_t numBytes); int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = SX126X_IRQ_NONE, uint16_t dio3Mask = SX126X_IRQ_NONE); @@ -742,7 +738,7 @@ class SX126x: public PhysicalLayer { // common low-level SPI interface int16_t SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); int16_t SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); - int16_t SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy); + int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy); }; #endif