From e44e9b4bcef5c733c71ea943c1543b12323ec168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Grome=C5=A1?= Date: Sat, 26 Oct 2024 17:49:35 +0200 Subject: [PATCH] [PHY] Get/Set modem (#1294) * [PHY] Added set modem method * Added new keyword * [SX126x] Added setModem implementation * [LoRaWAN] Use setModem * [PHY] Added getModem * [LoRaWAN] Use getModem instead of caching modulation * [SX126x] Implement getModem * Added new keywords * [LR11x0] Added get/set modem * [LLCC68] Added get/set modem * [SX126x] Added missing default branch * [SX127x] Added get/set modem * [SX128x] Added get/set modem * [CI] Drop Hellschreiber from AVR builds * [CI] Drop Arduino Uno from CI --- .github/workflows/main.yml | 7 +-- keywords.txt | 12 ++++- src/modules/LLCC68/LLCC68.cpp | 16 ++++++ src/modules/LLCC68/LLCC68.h | 8 +++ src/modules/LR11x0/LR1110.cpp | 15 ++++++ src/modules/LR11x0/LR1110.h | 8 +++ src/modules/LR11x0/LR1120.cpp | 15 ++++++ src/modules/LR11x0/LR1120.h | 8 +++ src/modules/LR11x0/LR11x0.cpp | 24 +++++++++ src/modules/LR11x0/LR11x0.h | 7 +++ src/modules/SX126x/SX1262.cpp | 16 ++++++ src/modules/SX126x/SX1262.h | 8 +++ src/modules/SX126x/SX1268.cpp | 16 ++++++ src/modules/SX126x/SX1268.h | 8 +++ src/modules/SX126x/SX126x.cpp | 21 ++++++++ src/modules/SX126x/SX126x.h | 7 +++ src/modules/SX127x/SX1272.cpp | 13 +++++ src/modules/SX127x/SX1272.h | 8 +++ src/modules/SX127x/SX1273.cpp | 13 +++++ src/modules/SX127x/SX1273.h | 8 +++ src/modules/SX127x/SX1276.cpp | 13 +++++ src/modules/SX127x/SX1276.h | 8 +++ src/modules/SX127x/SX1277.cpp | 13 +++++ src/modules/SX127x/SX1277.h | 8 +++ src/modules/SX127x/SX1278.cpp | 13 +++++ src/modules/SX127x/SX1278.h | 8 +++ src/modules/SX127x/SX1279.cpp | 13 +++++ src/modules/SX127x/SX1279.h | 8 +++ src/modules/SX127x/SX127x.cpp | 18 +++++++ src/modules/SX127x/SX127x.h | 7 +++ src/modules/SX128x/SX128x.cpp | 31 +++++++++++ src/modules/SX128x/SX128x.h | 15 ++++++ src/protocols/LoRaWAN/LoRaWAN.cpp | 52 ++++++++++++------- src/protocols/LoRaWAN/LoRaWAN.h | 8 --- src/protocols/PhysicalLayer/PhysicalLayer.cpp | 10 ++++ src/protocols/PhysicalLayer/PhysicalLayer.h | 26 ++++++++++ 36 files changed, 456 insertions(+), 33 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7c518526..ba5e493d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,12 +10,11 @@ on: id: description: The ID of the platform on which the build is run required: true - default: arduino:avr:uno + default: arduino:avr:mega type: choice options: - all - none - - arduino:avr:uno - arduino:avr:mega - arduino:mbed:nano33ble - arduino:mbed:envie_m4 @@ -45,8 +44,6 @@ jobs: matrix: # platform-dependent settings - extra board options, board index URLs, skip patterns etc. include: - - id: arduino:avr:uno - run: echo "skip-pattern=(STM32WL|SSTV|LoRaWAN|LR11x0_Firmware_Update|Pager|APRS|Morse|SX126x)" >> $GITHUB_OUTPUT - id: arduino:avr:mega run: | echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT @@ -131,7 +128,7 @@ jobs: runs-on: ubuntu-latest name: ${{ matrix.id }} env: - run-build: ${{ (inputs.id != 'none' && matrix.id == 'arduino:avr:uno') || contains(github.event.head_commit.message, 'CI_BUILD_ALL') || contains(github.event.head_commit.message, 'Bump version to') || contains(github.event.head_commit.message, format('{0}', matrix.id)) || inputs.id == 'all' || inputs.id == matrix.id }} + run-build: ${{ (inputs.id != 'none' && matrix.id == 'arduino:avr:mega') || contains(github.event.head_commit.message, 'CI_BUILD_ALL') || contains(github.event.head_commit.message, 'Bump version to') || contains(github.event.head_commit.message, format('{0}', matrix.id)) || inputs.id == 'all' || inputs.id == matrix.id }} steps: - name: Free Disk Space (Ubuntu) diff --git a/keywords.txt b/keywords.txt index d903819b..179b4e29 100644 --- a/keywords.txt +++ b/keywords.txt @@ -320,6 +320,15 @@ dropRepeaters KEYWORD2 sendTone KEYWORD2 # PhysicalLayer +RadioLibIrqType_t KEYWORD1 +LoRaRate_t KEYWORD1 +FSKRate_t KEYWORD1 +LrFhssRate_t KEYWORD1 +DataRate_t KEYWORD1 +CADScanConfig_t KEYWORD1 +RSSIScanConfig_t KEYWORD1 +ChannelScanConfig_t KEYWORD1 +ModemType_t KEYWORD1 dropSync KEYWORD2 setTimerFlag KEYWORD2 setInterruptSetup KEYWORD2 @@ -329,9 +338,8 @@ setPacketSentAction KEYWORD2 clearPacketSentAction KEYWORD2 setDataRate KEYWORD2 checkDataRate KEYWORD2 - -# BellModem setModem KEYWORD2 +getModem KEYWORD2 # LoRaWAN getBufferNonces KEYWORD2 diff --git a/src/modules/LLCC68/LLCC68.cpp b/src/modules/LLCC68/LLCC68.cpp index f7d458ad..18ce03dd 100644 --- a/src/modules/LLCC68/LLCC68.cpp +++ b/src/modules/LLCC68/LLCC68.cpp @@ -116,4 +116,20 @@ int16_t LLCC68::checkDataRate(DataRate_t dr) { return(state); } +int16_t LLCC68::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + case(ModemType_t::LRFHSS): { + return(this->beginLRFHSS()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/LLCC68/LLCC68.h b/src/modules/LLCC68/LLCC68.h index 08c52af3..a0b6d19e 100644 --- a/src/modules/LLCC68/LLCC68.h +++ b/src/modules/LLCC68/LLCC68.h @@ -69,6 +69,14 @@ class LLCC68: public SX1262 { \returns \ref status_codes */ int16_t checkDataRate(DataRate_t dr) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK, LoRa or LR-FHSS. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/LR11x0/LR1110.cpp b/src/modules/LR11x0/LR1110.cpp index 7ebf5a7b..0950a3a3 100644 --- a/src/modules/LR11x0/LR1110.cpp +++ b/src/modules/LR11x0/LR1110.cpp @@ -105,4 +105,19 @@ int16_t LR1110::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPo return(RADIOLIB_ERR_NONE); } +int16_t LR1110::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginGFSK()); + } break; + case(ModemType_t::LRFHSS): { + return(this->beginLRFHSS()); + } break; + } + return(RADIOLIB_ERR_WRONG_MODEM); +} + #endif \ No newline at end of file diff --git a/src/modules/LR11x0/LR1110.h b/src/modules/LR11x0/LR1110.h index 3e1bc5fc..bd7818f8 100644 --- a/src/modules/LR11x0/LR1110.h +++ b/src/modules/LR11x0/LR1110.h @@ -123,6 +123,14 @@ class LR1110: public LR11x0 { */ int16_t checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower); + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK, LoRa or LR-FHSS. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; + #if !RADIOLIB_GODMODE private: #endif diff --git a/src/modules/LR11x0/LR1120.cpp b/src/modules/LR11x0/LR1120.cpp index 9afa8dfb..ae4dc4a1 100644 --- a/src/modules/LR11x0/LR1120.cpp +++ b/src/modules/LR11x0/LR1120.cpp @@ -128,4 +128,19 @@ int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPo return(RADIOLIB_ERR_NONE); } +int16_t LR1120::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginGFSK()); + } break; + case(ModemType_t::LRFHSS): { + return(this->beginLRFHSS()); + } break; + } + return(RADIOLIB_ERR_WRONG_MODEM); +} + #endif \ No newline at end of file diff --git a/src/modules/LR11x0/LR1120.h b/src/modules/LR11x0/LR1120.h index 4abae5a9..dde24208 100644 --- a/src/modules/LR11x0/LR1120.h +++ b/src/modules/LR11x0/LR1120.h @@ -132,6 +132,14 @@ class LR1120: public LR11x0 { */ int16_t checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower); + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK, LoRa or LR-FHSS. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; + #if !RADIOLIB_GODMODE private: #endif diff --git a/src/modules/LR11x0/LR11x0.cpp b/src/modules/LR11x0/LR11x0.cpp index 6bb4e227..03d32d04 100644 --- a/src/modules/LR11x0/LR11x0.cpp +++ b/src/modules/LR11x0/LR11x0.cpp @@ -2009,6 +2009,30 @@ int16_t LR11x0::getGnssSatellites(LR11x0GnssSatellite_t* sats, uint8_t numSats) return(state); } +int16_t LR11x0::getModem(ModemType_t* modem) { + if(!modem) { + return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED); + } + + uint8_t packetType = RADIOLIB_LR11X0_PACKET_TYPE_NONE; + int16_t state = getPacketType(&packetType); + RADIOLIB_ASSERT(state); + + switch(packetType) { + case(RADIOLIB_LR11X0_PACKET_TYPE_LORA): + *modem = ModemType_t::LoRa; + return(RADIOLIB_ERR_NONE); + case(RADIOLIB_LR11X0_PACKET_TYPE_GFSK): + *modem = ModemType_t::FSK; + return(RADIOLIB_ERR_NONE); + case(RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS): + *modem = ModemType_t::LRFHSS; + return(RADIOLIB_ERR_NONE); + } + + return(RADIOLIB_ERR_WRONG_MODEM); +} + int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) { this->mod->init(); this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput); diff --git a/src/modules/LR11x0/LR11x0.h b/src/modules/LR11x0/LR11x0.h index 3f1939a5..490c1203 100644 --- a/src/modules/LR11x0/LR11x0.h +++ b/src/modules/LR11x0/LR11x0.h @@ -1602,6 +1602,13 @@ class LR11x0: public PhysicalLayer { \returns \ref status_codes */ int16_t getGnssSatellites(LR11x0GnssSatellite_t* sats, uint8_t numSats); + + /*! + \brief Get modem currently in use by the radio. + \param modem Pointer to a variable to save the retrieved configuration into. + \returns \ref status_codes + */ + int16_t getModem(ModemType_t* modem) override; #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL protected: diff --git a/src/modules/SX126x/SX1262.cpp b/src/modules/SX126x/SX1262.cpp index 43c97063..c4e20eb2 100644 --- a/src/modules/SX126x/SX1262.cpp +++ b/src/modules/SX126x/SX1262.cpp @@ -145,4 +145,20 @@ int16_t SX1262::checkOutputPower(int8_t power, int8_t* clipped) { return(RADIOLIB_ERR_NONE); } +int16_t SX1262::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + case(ModemType_t::LRFHSS): { + return(this->beginLRFHSS()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX126x/SX1262.h b/src/modules/SX126x/SX1262.h index c05ee4b1..0dc27444 100644 --- a/src/modules/SX126x/SX1262.h +++ b/src/modules/SX126x/SX1262.h @@ -109,6 +109,14 @@ class SX1262: public SX126x { \returns \ref status_codes */ int16_t checkOutputPower(int8_t power, int8_t* clipped) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK, LoRa or LR-FHSS. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/SX126x/SX1268.cpp b/src/modules/SX126x/SX1268.cpp index 78cfdae3..a8095b5a 100644 --- a/src/modules/SX126x/SX1268.cpp +++ b/src/modules/SX126x/SX1268.cpp @@ -140,4 +140,20 @@ int16_t SX1268::checkOutputPower(int8_t power, int8_t* clipped) { return(RADIOLIB_ERR_NONE); } +int16_t SX1268::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + case(ModemType_t::LRFHSS): { + return(this->beginLRFHSS()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX126x/SX1268.h b/src/modules/SX126x/SX1268.h index ad411ee7..87cf9b5c 100644 --- a/src/modules/SX126x/SX1268.h +++ b/src/modules/SX126x/SX1268.h @@ -107,6 +107,14 @@ class SX1268: public SX126x { \returns \ref status_codes */ int16_t checkOutputPower(int8_t power, int8_t* clipped) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK, LoRa or LR-FHSS. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 9c17cfed..135ed05c 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -1662,6 +1662,27 @@ int16_t SX126x::invertIQ(bool enable) { return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled)); } +int16_t SX126x::getModem(ModemType_t* modem) { + if(!modem) { + return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED); + } + + uint8_t packetType = getPacketType(); + switch(packetType) { + case(RADIOLIB_SX126X_PACKET_TYPE_LORA): + *modem = ModemType_t::LoRa; + return(RADIOLIB_ERR_NONE); + case(RADIOLIB_SX126X_PACKET_TYPE_GFSK): + *modem = ModemType_t::FSK; + return(RADIOLIB_ERR_NONE); + case(RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS): + *modem = ModemType_t::LRFHSS; + return(RADIOLIB_ERR_NONE); + } + + return(RADIOLIB_ERR_WRONG_MODEM); +} + #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE void SX126x::setDirectAction(void (*func)(void)) { setDio1Action(func); diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index 766e0208..8a0348c3 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -1123,6 +1123,13 @@ class SX126x: public PhysicalLayer { */ int16_t invertIQ(bool enable) override; + /*! + \brief Get modem currently in use by the radio. + \param modem Pointer to a variable to save the retrieved configuration into. + \returns \ref status_codes + */ + int16_t getModem(ModemType_t* modem) override; + #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE /*! \brief Set interrupt service routine function to call when data bit is received in direct mode. diff --git a/src/modules/SX127x/SX1272.cpp b/src/modules/SX127x/SX1272.cpp index 50b088b2..ed615705 100644 --- a/src/modules/SX127x/SX1272.cpp +++ b/src/modules/SX127x/SX1272.cpp @@ -585,4 +585,17 @@ void SX1272::errataFix(bool rx) { mod->SPIsetRegValue(0x31, 0b10000000, 7, 7); } +int16_t SX1272::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX127x/SX1272.h b/src/modules/SX127x/SX1272.h index 292bfd79..26899692 100644 --- a/src/modules/SX127x/SX1272.h +++ b/src/modules/SX127x/SX1272.h @@ -301,6 +301,14 @@ class SX1272: public SX127x { \returns \ref status_codes */ int16_t explicitHeader(); + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK or LoRa. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE protected: diff --git a/src/modules/SX127x/SX1273.cpp b/src/modules/SX127x/SX1273.cpp index 9ef7c175..0efbbe93 100644 --- a/src/modules/SX127x/SX1273.cpp +++ b/src/modules/SX127x/SX1273.cpp @@ -115,4 +115,17 @@ int16_t SX1273::checkDataRate(DataRate_t dr) { return(state); } +int16_t SX1273::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX127x/SX1273.h b/src/modules/SX127x/SX1273.h index 8e7ab1ca..4e9dd1ed 100644 --- a/src/modules/SX127x/SX1273.h +++ b/src/modules/SX127x/SX1273.h @@ -62,6 +62,14 @@ class SX1273: public SX1272 { \returns \ref status_codes */ int16_t checkDataRate(DataRate_t dr) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK or LoRa. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/SX127x/SX1276.cpp b/src/modules/SX127x/SX1276.cpp index d45826fc..8890c6cb 100644 --- a/src/modules/SX127x/SX1276.cpp +++ b/src/modules/SX127x/SX1276.cpp @@ -79,4 +79,17 @@ int16_t SX1276::setFrequency(float freq) { return(state); } +int16_t SX1276::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX127x/SX1276.h b/src/modules/SX127x/SX1276.h index 89ab9f9f..64dbaa3e 100644 --- a/src/modules/SX127x/SX1276.h +++ b/src/modules/SX127x/SX1276.h @@ -62,6 +62,14 @@ class SX1276: public SX1278 { \returns \ref status_codes */ int16_t setFrequency(float freq) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK or LoRa. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/SX127x/SX1277.cpp b/src/modules/SX127x/SX1277.cpp index fea394cd..c85a5fe5 100644 --- a/src/modules/SX127x/SX1277.cpp +++ b/src/modules/SX127x/SX1277.cpp @@ -157,4 +157,17 @@ int16_t SX1277::checkDataRate(DataRate_t dr) { return(state); } +int16_t SX1277::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX127x/SX1277.h b/src/modules/SX127x/SX1277.h index c7efd95b..fe068c0d 100644 --- a/src/modules/SX127x/SX1277.h +++ b/src/modules/SX127x/SX1277.h @@ -83,6 +83,14 @@ class SX1277: public SX1278 { \returns \ref status_codes */ int16_t checkDataRate(DataRate_t dr) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK or LoRa. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/SX127x/SX1278.cpp b/src/modules/SX127x/SX1278.cpp index 3265675f..e53bfe34 100644 --- a/src/modules/SX127x/SX1278.cpp +++ b/src/modules/SX127x/SX1278.cpp @@ -705,4 +705,17 @@ void SX1278::errataFix(bool rx) { mod->SPIsetRegValue(0x30, fixedRegs[2]); } +int16_t SX1278::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX127x/SX1278.h b/src/modules/SX127x/SX1278.h index 3c2b0088..feb1d09c 100644 --- a/src/modules/SX127x/SX1278.h +++ b/src/modules/SX127x/SX1278.h @@ -313,6 +313,14 @@ class SX1278: public SX127x { \returns \ref status_codes */ int16_t explicitHeader(); + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK or LoRa. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE protected: diff --git a/src/modules/SX127x/SX1279.cpp b/src/modules/SX127x/SX1279.cpp index 9f9ac037..4babad05 100644 --- a/src/modules/SX127x/SX1279.cpp +++ b/src/modules/SX127x/SX1279.cpp @@ -79,4 +79,17 @@ int16_t SX1279::setFrequency(float freq) { return(state); } +int16_t SX1279::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + #endif diff --git a/src/modules/SX127x/SX1279.h b/src/modules/SX127x/SX1279.h index 1dceb423..865b1b22 100644 --- a/src/modules/SX127x/SX1279.h +++ b/src/modules/SX127x/SX1279.h @@ -62,6 +62,14 @@ class SX1279: public SX1278 { \returns \ref status_codes */ int16_t setFrequency(float freq) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK or LoRa. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; #if !RADIOLIB_GODMODE private: diff --git a/src/modules/SX127x/SX127x.cpp b/src/modules/SX127x/SX127x.cpp index 55138aa1..425b1cb1 100644 --- a/src/modules/SX127x/SX127x.cpp +++ b/src/modules/SX127x/SX127x.cpp @@ -1754,6 +1754,24 @@ int16_t SX127x::invertIQ(bool enable) { return(state); } +int16_t SX127x::getModem(ModemType_t* modem) { + if(!modem) { + return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED); + } + + int16_t packetType = getActiveModem(); + switch(packetType) { + case(RADIOLIB_SX127X_LORA): + *modem = ModemType_t::LoRa; + return(RADIOLIB_ERR_NONE); + case(RADIOLIB_SX127X_FSK_OOK): + *modem = ModemType_t::FSK; + return(RADIOLIB_ERR_NONE); + } + + return(RADIOLIB_ERR_WRONG_MODEM); +} + #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE void SX127x::setDirectAction(void (*func)(void)) { setDio1Action(func, this->mod->hal->GpioInterruptRising); diff --git a/src/modules/SX127x/SX127x.h b/src/modules/SX127x/SX127x.h index ba492f1d..c54a549f 100644 --- a/src/modules/SX127x/SX127x.h +++ b/src/modules/SX127x/SX127x.h @@ -1149,6 +1149,13 @@ class SX127x: public PhysicalLayer { */ int16_t invertIQ(bool enable) override; + /*! + \brief Get modem currently in use by the radio. + \param modem Pointer to a variable to save the retrieved configuration into. + \returns \ref status_codes + */ + int16_t getModem(ModemType_t* modem) override; + #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE /*! \brief Set interrupt service routine function to call when data bit is received in direct mode. diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index a7fe165b..5847f3d6 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -856,6 +856,37 @@ int16_t SX128x::checkOutputPower(int8_t pwr, int8_t* clipped) { return(RADIOLIB_ERR_NONE); } +int16_t SX128x::setModem(ModemType_t modem) { + switch(modem) { + case(ModemType_t::LoRa): { + return(this->begin()); + } break; + case(ModemType_t::FSK): { + return(this->beginGFSK()); + } break; + default: + return(RADIOLIB_ERR_WRONG_MODEM); + } +} + +int16_t SX128x::getModem(ModemType_t* modem) { + if(!modem) { + return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED); + } + + uint8_t packetType = getPacketType(); + switch(packetType) { + case(RADIOLIB_SX128X_PACKET_TYPE_LORA): + *modem = ModemType_t::LoRa; + return(RADIOLIB_ERR_NONE); + case(RADIOLIB_SX128X_PACKET_TYPE_GFSK): + *modem = ModemType_t::FSK; + return(RADIOLIB_ERR_NONE); + } + + return(RADIOLIB_ERR_WRONG_MODEM); +} + int16_t SX128x::setPreambleLength(uint32_t preambleLength) { uint8_t modem = getPacketType(); if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) { diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index 6f584ead..ae1d4687 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -671,6 +671,21 @@ class SX128x: public PhysicalLayer { \returns \ref status_codes */ int16_t checkOutputPower(int8_t pwr, int8_t* clipped) override; + + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set - FSK, LoRa or LR-FHSS. + \returns \ref status_codes + */ + int16_t setModem(ModemType_t modem) override; + + /*! + \brief Get modem currently in use by the radio. + \param modem Pointer to a variable to save the retrieved configuration into. + \returns \ref status_codes + */ + int16_t getModem(ModemType_t* modem) override; /*! \brief Sets preamble length for currently active modem. Allowed values range from 1 to 65535. diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index 761d3970..7e6e4a8c 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -2768,11 +2768,19 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir, return(state); } - // TODO implement PhysicalLayer::setModem() + // get the currently configured modem from the radio + ModemType_t modem; + state = this->phyLayer->getModem(&modem); + RADIOLIB_ASSERT(state); + // set modem-dependent functions switch(this->band->dataRates[chnl->dr] & RADIOLIB_LORAWAN_DATA_RATE_MODEM) { case(RADIOLIB_LORAWAN_DATA_RATE_LORA): - this->modulation = RADIOLIB_LORAWAN_MODULATION_LORA; + if(modem != ModemType_t::LoRa) { + state = this->phyLayer->setModem(ModemType_t::LoRa); + RADIOLIB_ASSERT(state); + } + modem = ModemType_t::LoRa; // downlink messages are sent with inverted IQ if(dir == RADIOLIB_LORAWAN_DOWNLINK) { state = this->phyLayer->invertIQ(true); @@ -2781,16 +2789,27 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir, } RADIOLIB_ASSERT(state); break; + case(RADIOLIB_LORAWAN_DATA_RATE_FSK): - this->modulation = RADIOLIB_LORAWAN_MODULATION_GFSK; + if(modem != ModemType_t::FSK) { + state = this->phyLayer->setModem(ModemType_t::FSK); + RADIOLIB_ASSERT(state); + } + modem = ModemType_t::FSK; state = this->phyLayer->setDataShaping(RADIOLIB_SHAPING_1_0); RADIOLIB_ASSERT(state); state = this->phyLayer->setEncoding(RADIOLIB_ENCODING_WHITENING); RADIOLIB_ASSERT(state); break; + case(RADIOLIB_LORAWAN_DATA_RATE_LR_FHSS): - this->modulation = RADIOLIB_LORAWAN_MODULATION_LR_FHSS; + if(modem != ModemType_t::LRFHSS) { + state = this->phyLayer->setModem(ModemType_t::LRFHSS); + RADIOLIB_ASSERT(state); + } + modem = ModemType_t::LRFHSS; break; + default: return(RADIOLIB_ERR_UNSUPPORTED); } @@ -2812,40 +2831,37 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir, state = this->phyLayer->setDataRate(dr); RADIOLIB_ASSERT(state); - if(this->modulation == RADIOLIB_LORAWAN_MODULATION_GFSK) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("FSK: BR = %4.1f, FD = %4.1f kHz", - dr.fsk.bitRate, dr.fsk.freqDev); - } - if(this->modulation == RADIOLIB_LORAWAN_MODULATION_LORA) { - RADIOLIB_DEBUG_PROTOCOL_PRINTLN("LoRa: SF = %d, BW = %5.1f kHz, CR = 4/%d, IQ: %c", - dr.lora.spreadingFactor, dr.lora.bandwidth, dr.lora.codingRate, dir ? 'D' : 'U'); - } - // this only needs to be done once-ish uint8_t syncWord[4] = { 0 }; uint8_t syncWordLen = 0; size_t preLen = 0; - switch(this->modulation) { - case(RADIOLIB_LORAWAN_MODULATION_GFSK): { + switch(modem) { + case(ModemType_t::FSK): { preLen = 8*RADIOLIB_LORAWAN_GFSK_PREAMBLE_LEN; syncWord[0] = (uint8_t)(RADIOLIB_LORAWAN_GFSK_SYNC_WORD >> 16); syncWord[1] = (uint8_t)(RADIOLIB_LORAWAN_GFSK_SYNC_WORD >> 8); syncWord[2] = (uint8_t)RADIOLIB_LORAWAN_GFSK_SYNC_WORD; syncWordLen = 3; + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("FSK: BR = %4.1f, FD = %4.1f kHz", + dr.fsk.bitRate, dr.fsk.freqDev); } break; - case(RADIOLIB_LORAWAN_MODULATION_LORA): { + case(ModemType_t::LoRa): { preLen = RADIOLIB_LORAWAN_LORA_PREAMBLE_LEN; syncWord[0] = RADIOLIB_LORAWAN_LORA_SYNC_WORD; syncWordLen = 1; + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("LoRa: SF = %d, BW = %5.1f kHz, CR = 4/%d, IQ: %c", + dr.lora.spreadingFactor, dr.lora.bandwidth, dr.lora.codingRate, dir ? 'D' : 'U'); } break; - case(RADIOLIB_LORAWAN_MODULATION_LR_FHSS): { + case(ModemType_t::LRFHSS): { syncWord[0] = (uint8_t)(RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD >> 24); syncWord[1] = (uint8_t)(RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD >> 16); syncWord[2] = (uint8_t)(RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD >> 8); syncWord[3] = (uint8_t)RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD; syncWordLen = 4; + RADIOLIB_DEBUG_PROTOCOL_PRINTLN("LR-FHSS: BW = 0x%02x, CR = 0x%02x kHz, grid = %c", + dr.lrfhss.bw, dr.lrfhss.cr, dr.lrFhss.narrowGrid ? 'N' : 'W'); } break; default: @@ -2859,7 +2875,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir, if(pre) { preLen = pre; } - if(this->modulation != RADIOLIB_LORAWAN_MODULATION_LR_FHSS) { + if(modem != ModemType_t::LRFHSS) { state = this->phyLayer->setPreambleLength(preLen); } return(state); diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index 3816486f..588882b9 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -15,11 +15,6 @@ #define RADIOLIB_LORAWAN_CLASS_B (0x0B) #define RADIOLIB_LORAWAN_CLASS_C (0x0C) -// modulation type -#define RADIOLIB_LORAWAN_MODULATION_LORA (0) -#define RADIOLIB_LORAWAN_MODULATION_GFSK (1) -#define RADIOLIB_LORAWAN_MODULATION_LR_FHSS (2) - // preamble format #define RADIOLIB_LORAWAN_LORA_SYNC_WORD (0x34) #define RADIOLIB_LORAWAN_LORA_PREAMBLE_LEN (8) @@ -916,9 +911,6 @@ class LoRaWANNode { uint32_t confFCntDown = RADIOLIB_LORAWAN_FCNT_NONE; uint32_t adrFCnt = 0; - // modulation of the currently configured channel - uint8_t modulation = RADIOLIB_LORAWAN_MODULATION_LORA; - // ADR is enabled by default bool adrEnabled = true; diff --git a/src/protocols/PhysicalLayer/PhysicalLayer.cpp b/src/protocols/PhysicalLayer/PhysicalLayer.cpp index 82eb5fba..1ad04e69 100644 --- a/src/protocols/PhysicalLayer/PhysicalLayer.cpp +++ b/src/protocols/PhysicalLayer/PhysicalLayer.cpp @@ -531,6 +531,16 @@ void PhysicalLayer::clearChannelScanAction() { } +int16_t PhysicalLayer::setModem(ModemType_t modem) { + (void)modem; + return(RADIOLIB_ERR_UNSUPPORTED); +} + +int16_t PhysicalLayer::getModem(ModemType_t* modem) { + (void)modem; + return(RADIOLIB_ERR_UNSUPPORTED); +} + #if RADIOLIB_INTERRUPT_TIMING void PhysicalLayer::setInterruptSetup(void (*func)(uint32_t)) { Module* mod = getMod(); diff --git a/src/protocols/PhysicalLayer/PhysicalLayer.h b/src/protocols/PhysicalLayer/PhysicalLayer.h index c463e8b2..c5467990 100644 --- a/src/protocols/PhysicalLayer/PhysicalLayer.h +++ b/src/protocols/PhysicalLayer/PhysicalLayer.h @@ -130,6 +130,16 @@ union ChannelScanConfig_t { RSSIScanConfig_t rssi; }; +/*! + \enum ModemType_t + \brief Type of modem, used by setModem. +*/ +enum ModemType_t { + FSK = 0, + LoRa, + LRFHSS, +}; + /*! \class PhysicalLayer @@ -644,6 +654,21 @@ class PhysicalLayer { */ virtual void clearChannelScanAction(); + /*! + \brief Set modem for the radio to use. Will perform full reset and reconfigure the radio + using its default parameters. + \param modem Modem type to set. Not all modems are implemented by all radio modules! + \returns \ref status_codes + */ + virtual int16_t setModem(ModemType_t modem); + + /*! + \brief Get modem currently in use by the radio. + \param modem Pointer to a variable to save the retrieved configuration into. + \returns \ref status_codes + */ + virtual int16_t getModem(ModemType_t* modem); + #if RADIOLIB_INTERRUPT_TIMING /*! @@ -702,6 +727,7 @@ class PhysicalLayer { friend class BellClient; friend class FT8Client; friend class LoRaWANNode; + friend class M17Client; }; #endif