Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LoRaWAN] Improve PHY behaviour, update beginABP, bugfixes #1080

Merged
merged 17 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ jobs:
else
# apply special flags for LoRaWAN
if [[ ${example} =~ "LoRaWAN" ]]; then
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_NWKS_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_FNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
fi

# build sketch
Expand Down
6 changes: 3 additions & 3 deletions examples/LoRaWAN/LoRaWAN_ABP/configABP.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
#define RADIOLIB_LORAWAN_DEV_ADDR 0x------
#endif

#ifndef RADIOLIB_LORAWAN_NWKS_KEY // Replace with your NwkS Key
#define RADIOLIB_LORAWAN_NWKS_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
#ifndef RADIOLIB_LORAWAN_FNWKSINT_KEY // Replace with your FNwkSInt Key
#define RADIOLIB_LORAWAN_FNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
#endif
#ifndef RADIOLIB_LORAWAN_SNWKSINT_KEY // Replace with your SNwkSInt Key
#define RADIOLIB_LORAWAN_SNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
Expand Down Expand Up @@ -118,7 +118,7 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0

// copy over the keys in to the something that will not compile if incorrectly formatted
uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR;
uint8_t NwkSKey[] = { RADIOLIB_LORAWAN_NWKS_KEY };
uint8_t NwkSKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY };
uint8_t SNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY }; // Previously sNwkSIntKey
uint8_t NwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY }; // Previously fNwkSIntKey
uint8_t AppSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
Expand Down
3 changes: 2 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ setCodingRate KEYWORD2
setFrequency KEYWORD2
setSyncWord KEYWORD2
setOutputPower KEYWORD2
checkOutputPower KEYWORD2
setCurrentLimit KEYWORD2
setPreambleLength KEYWORD2
setGain KEYWORD2
Expand Down Expand Up @@ -328,10 +329,10 @@ timeUntilUplink KEYWORD2
setDwellTime KEYWORD2
maxPayloadDwellTime KEYWORD2
setTxPower KEYWORD2
setCSMA KEYWORD2
getMacLinkCheckAns KEYWORD2
getMacDeviceTimeAns KEYWORD2
getDevAddr KEYWORD2
getLastToA KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down
110 changes: 74 additions & 36 deletions src/modules/CC1101/CC1101.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,62 @@ int16_t CC1101::getFrequencyDeviation(float *freqDev) {
}

int16_t CC1101::setOutputPower(int8_t pwr) {
// check if power value is configurable
uint8_t powerRaw = 0;
int16_t state = checkOutputPower(pwr, NULL, &powerRaw);
RADIOLIB_ASSERT(state);

// store the value
this->power = pwr;

if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
// Amplitude modulation:
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)

uint8_t paValues[2] = {0x00, powerRaw};
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
return(RADIOLIB_ERR_NONE);

} else {
// Freq modulation:
// PA_TABLE[0] is the power to be used when transmitting.
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PATABLE, powerRaw));
}
}

int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped) {
return(checkOutputPower(power, clipped, NULL));
}

int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
StevenCellist marked this conversation as resolved.
Show resolved Hide resolved
constexpr int8_t allowedPwrs[8] = { -30, -20, -15, -10, 0, 5, 7, 10 };

if(clipped) {
if(power <= -30) {
*clipped = -30;
} else if(power >= 10) {
*clipped = 10;
} else {
for(int i = 0; i < 8; i++) {
if(allowedPwrs[i] > power) {
break;
}
*clipped = allowedPwrs[i];
}
}
}

// if just a check occurs (and not requesting the raw power value), return now
if(!raw) {
for(int i = 0; i < 8; i++) {
if(allowedPwrs[i] == power) {
return(RADIOLIB_ERR_NONE);
}
}
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
}

// round to the known frequency settings
uint8_t f;
if(this->frequency < 374.0) {
Expand All @@ -586,53 +642,35 @@ int16_t CC1101::setOutputPower(int8_t pwr) {
{0xCB, 0xC8, 0xCB, 0xC7},
{0xC2, 0xC0, 0xC2, 0xC0}};

uint8_t powerRaw;
switch(pwr) {
case -30:
powerRaw = paTable[0][f];
switch(power) {
case allowedPwrs[0]: // -30
*raw = paTable[0][f];
break;
case -20:
powerRaw = paTable[1][f];
case allowedPwrs[1]: // -20
*raw = paTable[1][f];
break;
case -15:
powerRaw = paTable[2][f];
case allowedPwrs[2]: // -15
*raw = paTable[2][f];
break;
case -10:
powerRaw = paTable[3][f];
case allowedPwrs[3]: // -10
*raw = paTable[3][f];
break;
case 0:
powerRaw = paTable[4][f];
case allowedPwrs[4]: // 0
*raw = paTable[4][f];
break;
case 5:
powerRaw = paTable[5][f];
case allowedPwrs[5]: // 5
*raw = paTable[5][f];
break;
case 7:
powerRaw = paTable[6][f];
case allowedPwrs[6]: // 7
*raw = paTable[6][f];
break;
case 10:
powerRaw = paTable[7][f];
case allowedPwrs[7]: // 10
*raw = paTable[7][f];
break;
default:
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
}

// store the value
this->power = pwr;

if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
// Amplitude modulation:
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)

uint8_t paValues[2] = {0x00, powerRaw};
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
return(RADIOLIB_ERR_NONE);

} else {
// Freq modulation:
// PA_TABLE[0] is the power to be used when transmitting.
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PATABLE, powerRaw));
}
return(RADIOLIB_ERR_NONE);
}

int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits, bool requireCarrierSense) {
Expand Down
18 changes: 18 additions & 0 deletions src/modules/CC1101/CC1101.h
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,24 @@ class CC1101: public PhysicalLayer {
*/
int16_t setOutputPower(int8_t pwr);

/*!
\brief Check if output power is configurable.
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
\param power Output power in dBm.
\param clipped Clipped output power value to what is possible within the module's range.
\returns \ref status_codes
*/
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;

/*!
\brief Check if output power is configurable.
\param power Output power in dBm.
\param clipped Clipped output power value to what is possible within the module's range.
\param raw Raw internal value.
\returns \ref status_codes
*/
int16_t checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw);
jgromes marked this conversation as resolved.
Show resolved Hide resolved

StevenCellist marked this conversation as resolved.
Show resolved Hide resolved
/*!
\brief Sets 16-bit sync word as a two byte value.
\param syncH MSB of the sync word.
Expand Down
36 changes: 26 additions & 10 deletions src/modules/LR11x0/LR11x0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,29 +593,45 @@ int16_t LR11x0::setOutputPower(int8_t power) {
}

int16_t LR11x0::setOutputPower(int8_t power, bool forceHighPower) {
// check if power value is configurable
int16_t state = checkOutputPower(power, NULL, forceHighPower);
RADIOLIB_ASSERT(state);

// determine whether to use HP or LP PA and check range accordingly
bool useHp = forceHighPower || (power > 14);
if(useHp) {
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
useHp = true;

} else {
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
useHp = false;

}

// TODO how and when to configure OCP?

// update PA config - always use VBAT for high-power PA
int16_t state = setPaConfig((uint8_t)useHp, (uint8_t)useHp, 0x04, 0x07);
state = setPaConfig((uint8_t)useHp, (uint8_t)useHp, 0x04, 0x07);
RADIOLIB_ASSERT(state);

// set output power
state = setTxParams(power, RADIOLIB_LR11X0_PA_RAMP_48U);
return(state);
}

int16_t LR11x0::checkOutputPower(int8_t power, int8_t* clipped) {
return(checkOutputPower(power, clipped, false));
}

int16_t LR11x0::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower) {
if(forceHighPower || (power > 14)) {
if(clipped) {
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
}
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);

} else {
if(clipped) {
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
}
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);

}
return(RADIOLIB_ERR_NONE);
}

int16_t LR11x0::setBandwidth(float bw) {
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
Expand Down
19 changes: 19 additions & 0 deletions src/modules/LR11x0/LR11x0.h
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,25 @@ class LR11x0: public PhysicalLayer {
*/
int16_t setOutputPower(int8_t power, bool forceHighPower);

/*!
\brief Check if output power is configurable.
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
\param power Output power in dBm, PA will be determined automatically.
\param clipped Clipped output power value to what is possible within the module's range.
\returns \ref status_codes
*/
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;

/*!
\brief Check if output power is configurable.
\param power Output power in dBm.
\param clipped Clipped output power value to what is possible within the module's range.
\param forceHighPower Force using the high-power PA. If set to false, PA will be determined automatically
based on configured output power, preferring the low-power PA. If set to true, only high-power PA will be used.
\returns \ref status_codes
*/
int16_t checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower);

/*!
\brief Sets LoRa bandwidth. Allowed values are 62.5, 125.0, 250.0 and 500.0 kHz.
\param bw LoRa bandwidth to be set in kHz.
Expand Down
14 changes: 12 additions & 2 deletions src/modules/SX126x/SX1261.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ SX1261::SX1261(Module* mod): SX1262(mod) {
}

int16_t SX1261::setOutputPower(int8_t power) {
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
// check if power value is configurable
int16_t state = checkOutputPower(power, NULL);
RADIOLIB_ASSERT(state);

// get current OCP configuration
uint8_t ocp = 0;
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
RADIOLIB_ASSERT(state);

// set PA config
Expand All @@ -25,4 +27,12 @@ int16_t SX1261::setOutputPower(int8_t power) {
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
}

int16_t SX1261::checkOutputPower(int8_t power, int8_t* clipped) {
if(clipped) {
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
}
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
return(RADIOLIB_ERR_NONE);
}

#endif
8 changes: 8 additions & 0 deletions src/modules/SX126x/SX1261.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ class SX1261 : public SX1262 {
*/
int16_t setOutputPower(int8_t power);

/*!
\brief Check if output power is configurable.
\param power Output power in dBm.
\param clipped Clipped output power value to what is possible within the module's range.
\returns \ref status_codes
*/
int16_t checkOutputPower(int8_t power, int8_t* clipped);

#if !RADIOLIB_GODMODE
private:
#endif
Expand Down
14 changes: 12 additions & 2 deletions src/modules/SX126x/SX1262.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@ int16_t SX1262::setFrequency(float freq, bool calibrate) {
}

int16_t SX1262::setOutputPower(int8_t power) {
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
// check if power value is configurable
int16_t state = checkOutputPower(power, NULL);
RADIOLIB_ASSERT(state);

// get current OCP configuration
uint8_t ocp = 0;
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
RADIOLIB_ASSERT(state);

// set PA config
Expand All @@ -117,4 +119,12 @@ int16_t SX1262::setOutputPower(int8_t power) {
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
}

int16_t SX1262::checkOutputPower(int8_t power, int8_t* clipped) {
if(clipped) {
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
}
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
return(RADIOLIB_ERR_NONE);
}

#endif
8 changes: 8 additions & 0 deletions src/modules/SX126x/SX1262.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ class SX1262: public SX126x {
*/
virtual int16_t setOutputPower(int8_t power);

/*!
\brief Check if output power is configurable.
\param power Output power in dBm.
\param clipped Clipped output power value to what is possible within the module's range.
\returns \ref status_codes
*/
int16_t checkOutputPower(int8_t power, int8_t* clipped);

#if !RADIOLIB_GODMODE
private:
#endif
Expand Down
Loading
Loading