From 01fc7fb844cc394c373a14ca427f7c411f8c376d Mon Sep 17 00:00:00 2001 From: Robert <3704942+JasonRJ@users.noreply.github.com> Date: Wed, 23 Feb 2022 11:41:29 -0500 Subject: [PATCH 1/5] Add method to support SX128x Frequency Error of last received LoRa or Ranging packet. Updated SX128x receive examples. --- .../SX128x/SX128x_Receive/SX128x_Receive.ino | 6 ++++ .../SX128x_Receive_Interrupt.ino | 6 ++++ src/modules/SX128x/SX128x.cpp | 33 +++++++++++++++++++ src/modules/SX128x/SX128x.h | 7 ++++ 4 files changed, 52 insertions(+) diff --git a/examples/SX128x/SX128x_Receive/SX128x_Receive.ino b/examples/SX128x/SX128x_Receive/SX128x_Receive.ino index 47c6c63b..28dc8047 100644 --- a/examples/SX128x/SX128x_Receive/SX128x_Receive.ino +++ b/examples/SX128x/SX128x_Receive/SX128x_Receive.ino @@ -85,6 +85,12 @@ void loop() { Serial.print(radio.getSNR()); Serial.println(F(" dB")); + // print the Frequency Error + // of the last received packet + Serial.print(F("[SX1280] Frequency Error:\t")); + Serial.print(radio.getFrequencyError()); + Serial.println(F(" Hz")); + } else if (state == RADIOLIB_ERR_RX_TIMEOUT) { // timeout occurred while waiting for a packet Serial.println(F("timeout!")); diff --git a/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino b/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino index 274121df..77d452c6 100644 --- a/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino +++ b/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino @@ -136,6 +136,12 @@ void loop() { Serial.print(radio.getSNR()); Serial.println(F(" dB")); + // print the Frequency Error + // of the last received packet + Serial.print(F("[SX1280] Frequency Error:\t")); + Serial.print(radio.getFrequencyError()); + Serial.println(F(" Hz")); + } else if (state == RADIOLIB_ERR_CRC_MISMATCH) { // packet was received, but is malformed Serial.println(F("CRC error!")); diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index 972e6ffc..a59572e4 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -1064,6 +1064,39 @@ float SX128x::getSNR() { } } +double SX128x::getFrequencyError() { + // check active modem + uint8_t modem = getPacketType(); + if (!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) { + return (0.0); + } + + uint8_t efeRaw[3] = {0}; + // read the raw frequency error register values + int16_t state = readRegister(RADIOLIB_SX128X_REG_FEI_MSB, &efeRaw[0], 1); + RADIOLIB_ASSERT(state); + state = readRegister(RADIOLIB_SX128X_REG_FEI_MID, &efeRaw[1], 1); + RADIOLIB_ASSERT(state); + state = readRegister(RADIOLIB_SX128X_REG_FEI_LSB, &efeRaw[2], 1); + RADIOLIB_ASSERT(state); + uint32_t efe = ((uint32_t) efeRaw[0] << 16) | ((uint32_t) efeRaw[1] << 8) | efeRaw[2]; + efe &= 0x0FFFFF; + + double error; + + // check the first bit + if (efe & 0x80000) { + // frequency error is negative + efe |= (uint32_t) 0xFFF00000; + efe = ~efe + 1; + error = 1.55 * (double) efe / (1600.0 / (double) _bwKhz) * -1.0; + } else { + error = 1.55 * (double) efe / (1600.0 / (double) _bwKhz); + } + + return (error); +} + size_t SX128x::getPacketLength(bool update) { (void)update; uint8_t rxBufStatus[2] = {0, 0}; diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index 9f258bb1..cf358c74 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -727,6 +727,13 @@ class SX128x: public PhysicalLayer { */ float getSNR(); + /*! + \brief Gets frequency error of the latest received packet. + + \returns Frequency error in Hz. + */ + double getFrequencyError(); + /*! \brief Query modem for the packet length of received payload. From 89de031e187fc37faa3620bea99728b39b8b6392 Mon Sep 17 00:00:00 2001 From: Robert <3704942+JasonRJ@users.noreply.github.com> Date: Wed, 23 Feb 2022 23:51:54 -0500 Subject: [PATCH 2/5] Add method to support SX128x High Sensitivity Mode. --- src/modules/SX128x/SX128x.cpp | 15 +++++++++++++++ src/modules/SX128x/SX128x.h | 9 +++++++++ 2 files changed, 24 insertions(+) diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index a59572e4..9316eae2 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -1020,6 +1020,21 @@ int16_t SX128x::setAccessAddress(uint32_t addr) { return(SX128x::writeRegister(RADIOLIB_SX128X_REG_ACCESS_ADDRESS_BYTE_3, addrBuff, 4)); } +int16_t SX128x::setHighSensitivityMode(bool hsm) { + // update register + uint8_t RxGain = 0; + int16_t state = readRegister(RADIOLIB_SX128X_REG_GAIN_MODE, &RxGain, 1); + RADIOLIB_ASSERT(state); + if (hsm) { + RxGain |= 0xC0; // Set bits 6 and 7 + } else { + RxGain &= ~0xC0; // Unset bits 6 and 7 + } + state = writeRegister(RADIOLIB_SX128X_REG_GAIN_MODE, &RxGain, 1); + RADIOLIB_ASSERT(state); + return(0); +} + float SX128x::getRSSI() { // get packet status uint8_t packetStatus[5]; diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index cf358c74..5c18d6d1 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -713,6 +713,15 @@ class SX128x: public PhysicalLayer { */ int16_t setAccessAddress(uint32_t addr); +/*! + \brief Enables or disables receiver high sensitivity mode. + + \param True to enable and false to disable. + + \returns 0 +*/ + int16_t setHighSensitivityMode(bool hsm = false); + /*! \brief Gets RSSI (Recorded Signal Strength Indicator) of the last received packet. From da0cd455c93f31fe10910c65979190feffb4c822 Mon Sep 17 00:00:00 2001 From: Robert <3704942+JasonRJ@users.noreply.github.com> Date: Wed, 23 Feb 2022 23:58:56 -0500 Subject: [PATCH 3/5] Add method to support SX128x Manual Gain Mode. --- src/modules/SX128x/SX128x.cpp | 33 +++++++++++++++++++++++++++++++++ src/modules/SX128x/SX128x.h | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index 9316eae2..a9241716 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -1035,6 +1035,39 @@ int16_t SX128x::setHighSensitivityMode(bool hsm) { return(0); } +int16_t SX128x::setGainControl(uint8_t gain) { + // update registers + uint8_t ManualGainSetting = 0; + int16_t state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1); + RADIOLIB_ASSERT(state); + uint8_t LNAGainValue = 0; + state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_SETTING, &LNAGainValue, 1); + RADIOLIB_ASSERT(state); + uint8_t LNAGainControl = 0; + state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_1, &LNAGainControl, 1); + RADIOLIB_ASSERT(state); + if (gain > 0 && gain < 14) { + // Set manual gain + ManualGainSetting &= ~0x01; // Set bit 0 to 0 (Enable Manual Gain Control) + LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0 + LNAGainValue |= gain; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13) + LNAGainControl |= 0x80; // Set bit 7 to 1 (Enable Manual Gain Control) + } else { + // Set automatic gain if 0 or out of range + ManualGainSetting |= 0x01; // Set bit 0 to 1 (Enable Automatic Gain Control) + LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0 + LNAGainValue |= 0x0A; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13) + LNAGainControl = 0x4D; // Set bit 7 to 0 (Enable Automatic Gain Control) + } + state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1); + RADIOLIB_ASSERT(state); + state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_SETTING, &LNAGainValue, 1); + RADIOLIB_ASSERT(state); + state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_1, &LNAGainControl, 1); + RADIOLIB_ASSERT(state); + return(0); +} + float SX128x::getRSSI() { // get packet status uint8_t packetStatus[5]; diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index 5c18d6d1..2537fe43 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -722,6 +722,15 @@ class SX128x: public PhysicalLayer { */ int16_t setHighSensitivityMode(bool hsm = false); + /*! + \brief Enables or disables receiver manual gain control. + + \param Gain 0 automatic gain; 1 minimum gain to 13 maximum gain. + + \returns \ref status_codes + */ + int16_t setGainControl(uint8_t gain = 0); + /*! \brief Gets RSSI (Recorded Signal Strength Indicator) of the last received packet. From ff43d95afa4d74176f6b2532989ac5b805325f53 Mon Sep 17 00:00:00 2001 From: Robert <3704942+JasonRJ@users.noreply.github.com> Date: Thu, 24 Feb 2022 00:29:51 -0500 Subject: [PATCH 4/5] Cleaned up formatting in header. Changed assigned value to set only the bit indicated in the documentation. --- src/modules/SX128x/SX128x.cpp | 2 +- src/modules/SX128x/SX128x.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index a9241716..5f5ac79e 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -1057,7 +1057,7 @@ int16_t SX128x::setGainControl(uint8_t gain) { ManualGainSetting |= 0x01; // Set bit 0 to 1 (Enable Automatic Gain Control) LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0 LNAGainValue |= 0x0A; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13) - LNAGainControl = 0x4D; // Set bit 7 to 0 (Enable Automatic Gain Control) + LNAGainControl &= ~0x80; // Set bit 7 to 0 (Enable Automatic Gain Control) } state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1); RADIOLIB_ASSERT(state); diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index 2537fe43..b86c3984 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -713,13 +713,13 @@ class SX128x: public PhysicalLayer { */ int16_t setAccessAddress(uint32_t addr); -/*! - \brief Enables or disables receiver high sensitivity mode. + /*! + \brief Enables or disables receiver high sensitivity mode. - \param True to enable and false to disable. + \param True to enable and false to disable. - \returns 0 -*/ + \returns 0 + */ int16_t setHighSensitivityMode(bool hsm = false); /*! @@ -727,7 +727,7 @@ class SX128x: public PhysicalLayer { \param Gain 0 automatic gain; 1 minimum gain to 13 maximum gain. - \returns \ref status_codes + \returns 0 */ int16_t setGainControl(uint8_t gain = 0); From 89f202ce6a1fcc0ab4906ecd6d68b8b87e94cb9e Mon Sep 17 00:00:00 2001 From: Robert <3704942+JasonRJ@users.noreply.github.com> Date: Sat, 26 Feb 2022 18:44:05 -0500 Subject: [PATCH 5/5] Changed method to return float instead of double. All calculations within the method also use float instead of double. Results of the method do not seem to be effected. --- src/modules/SX128x/SX128x.cpp | 8 ++++---- src/modules/SX128x/SX128x.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index 5f5ac79e..3bc66b89 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -1112,7 +1112,7 @@ float SX128x::getSNR() { } } -double SX128x::getFrequencyError() { +float SX128x::getFrequencyError() { // check active modem uint8_t modem = getPacketType(); if (!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) { @@ -1130,16 +1130,16 @@ double SX128x::getFrequencyError() { uint32_t efe = ((uint32_t) efeRaw[0] << 16) | ((uint32_t) efeRaw[1] << 8) | efeRaw[2]; efe &= 0x0FFFFF; - double error; + float error; // check the first bit if (efe & 0x80000) { // frequency error is negative efe |= (uint32_t) 0xFFF00000; efe = ~efe + 1; - error = 1.55 * (double) efe / (1600.0 / (double) _bwKhz) * -1.0; + error = 1.55 * (float) efe / (1600.0 / (float) _bwKhz) * -1.0; } else { - error = 1.55 * (double) efe / (1600.0 / (double) _bwKhz); + error = 1.55 * (float) efe / (1600.0 / (float) _bwKhz); } return (error); diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index b86c3984..18f12f72 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -750,7 +750,7 @@ class SX128x: public PhysicalLayer { \returns Frequency error in Hz. */ - double getFrequencyError(); + float getFrequencyError(); /*! \brief Query modem for the packet length of received payload.