kopia lustrzana https://github.com/jgromes/RadioLib
Merge branch 'master' of https://github.com/jgromes/RadioLib
* 'master' of https://github.com/jgromes/RadioLib: Comment and error checking cleanup. Fixed power adjustment for SX1261 Removed memory allocation and copying from SX126X read* and write* functions Implemented optimal PA settings for SX1268. Ensured OCP is always restored when changing power. Slight refactor to avoid duplicated SX1262 / SX1268 code. Fixed link to ESP32 package index Implemented power scaling in setOutputPower, in accordance with datasheet. Missed SX1261 PA Config flag in previous commit Adjusted setPaConfig in SX126x setOutputPower.pull/63/head
commit
f9a746cf82
|
@ -29,7 +29,7 @@ before_install:
|
|||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# install 3rd party boards
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://dl.espressif.com/dl/package_esp32_index.json,https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json" --save-prefs 2>&1
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json" --save-prefs 2>&1
|
||||
- if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
|
||||
arduino --install-boards esp8266:esp8266;
|
||||
export SKIP_PAT='(HTTP|MQTT).*ino';
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#include "SX1261.h"
|
||||
|
||||
SX1261::SX1261(Module* mod)
|
||||
: SX1262(mod) {
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1261::setOutputPower(int8_t power) {
|
||||
// check allowed power range
|
||||
if (!((power >= -17) && (power <= 14))) {
|
||||
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);
|
||||
}
|
||||
|
||||
state = setOptimalLowPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// restore OCP configuration
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
||||
|
||||
int16_t SX1261::setOptimalLowPowerPaConfig(int8_t* inOutPower)
|
||||
{
|
||||
int16_t state;
|
||||
if (*inOutPower > 10) {
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
}
|
||||
else {
|
||||
state = SX126x::setPaConfig(0x01, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
// changing the PaConfig means output power is now scaled so we get 3 dB less than requested.
|
||||
// see datasheet table 13-21 and comments in setOptimalHiPowerPaConfig.
|
||||
*inOutPower -= 3;
|
||||
}
|
||||
return state;
|
||||
}
|
|
@ -8,9 +8,29 @@
|
|||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
|
||||
// TODO: implement SX1261 class
|
||||
using SX1261 = SX1262;
|
||||
class SX1261 : public SX1262 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1261(Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -17 to 14 dBm.
|
||||
|
||||
\param power Output power to be set in dBm.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
private:
|
||||
int16_t setOptimalLowPowerPaConfig(int8_t* inOutPower);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,28 +85,32 @@ int16_t SX1262::setFrequency(float freq, bool calibrate) {
|
|||
|
||||
int16_t SX1262::setOutputPower(int8_t power) {
|
||||
// check allowed power range
|
||||
if(!((power >= -17) && (power <= 22))) {
|
||||
if (!((power >= -17) && (power <= 22))) {
|
||||
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) {
|
||||
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);
|
||||
} else {
|
||||
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261);
|
||||
// this function sets the optimal PA settings
|
||||
// and adjusts power based on the PA settings chosen
|
||||
// so that output power matches requested power.
|
||||
state = SX126x::setOptimalHiPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
SX126x::setTxParams(power);
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include "SX126x.h"
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
|
||||
/*!
|
||||
\class SX1262
|
||||
|
|
|
@ -89,13 +89,19 @@ int16_t SX1268::setOutputPower(int8_t power) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
// enable high power PA
|
||||
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1268);
|
||||
// enable optimal PA - this changes the value of power.
|
||||
state = SX126x::setOptimalHiPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
SX126x::setTxParams(power);
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
||||
|
|
|
@ -1036,18 +1036,8 @@ int16_t SX126x::setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMa
|
|||
}
|
||||
|
||||
int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
|
||||
#ifdef STATIC_ONLY
|
||||
uint8_t dat[STATIC_ARRAY_SIZE + 2];
|
||||
#else
|
||||
uint8_t* dat = new uint8_t[2 + numBytes];
|
||||
#endif
|
||||
dat[0] = (uint8_t)((addr >> 8) & 0xFF);
|
||||
dat[1] = (uint8_t)(addr & 0xFF);
|
||||
memcpy(dat + 2, data, numBytes);
|
||||
int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_REGISTER, dat, 2 + numBytes);
|
||||
#ifndef STATIC_ONLY
|
||||
delete[] dat;
|
||||
#endif
|
||||
uint8_t cmd[] = { SX126X_CMD_WRITE_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
|
||||
int16_t state = SPIwriteCommand(cmd, 3, data, numBytes);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -1057,34 +1047,15 @@ int16_t SX126x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
|
|||
}
|
||||
|
||||
int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
|
||||
#ifdef STATIC_ONLY
|
||||
uint8_t dat[STATIC_ARRAY_SIZE + 1];
|
||||
#else
|
||||
uint8_t* dat = new uint8_t[1 + numBytes];
|
||||
#endif
|
||||
dat[0] = offset;
|
||||
memcpy(dat + 1, data, numBytes);
|
||||
int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_BUFFER, dat, 1 + numBytes);
|
||||
#ifndef STATIC_ONLY
|
||||
delete[] dat;
|
||||
#endif
|
||||
uint8_t cmd[] = { SX126X_CMD_WRITE_BUFFER, offset };
|
||||
int16_t state = SPIwriteCommand(cmd, 2, data, numBytes);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes) {
|
||||
// offset will be always set to 0 (one extra NOP is sent)
|
||||
#ifdef STATIC_ONLY
|
||||
uint8_t dat[STATIC_ARRAY_SIZE + 1];
|
||||
#else
|
||||
uint8_t* dat = new uint8_t[1 + numBytes];
|
||||
#endif
|
||||
dat[0] = SX126X_CMD_NOP;
|
||||
memcpy(dat + 1, data, numBytes);
|
||||
int16_t state = SPIreadCommand(SX126X_CMD_READ_BUFFER, dat, 1 + numBytes);
|
||||
memcpy(data, dat + 1, numBytes);
|
||||
#ifndef STATIC_ONLY
|
||||
delete[] dat;
|
||||
#endif
|
||||
uint8_t cmd[] = { SX126X_CMD_READ_BUFFER, SX126X_CMD_NOP };
|
||||
int16_t state = SPIreadCommand(cmd, 2, data, numBytes);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -1127,6 +1098,32 @@ int16_t SX126x::setTxParams(uint8_t power, uint8_t rampTime) {
|
|||
return(SPIwriteCommand(SX126X_CMD_SET_TX_PARAMS, data, 2));
|
||||
}
|
||||
|
||||
// set PA config for optimal consumption as described in section 13-21 of the datasheet.
|
||||
int16_t SX126x::setOptimalHiPowerPaConfig(int8_t * inOutPower)
|
||||
{
|
||||
// the final column of Table 13-21 suggests that the value passed in SetTxParams
|
||||
// is actually scaled depending on the parameters of setPaConfig.
|
||||
// Testing confirms this is approximately right
|
||||
int16_t state;
|
||||
if (*inOutPower >= 21) {
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262_8, SX126X_PA_CONFIG_HP_MAX/*0x07*/);
|
||||
}
|
||||
else if (*inOutPower >= 18) {
|
||||
state = SX126x::setPaConfig(0x03, SX126X_PA_CONFIG_SX1262_8, 0x05);
|
||||
// datasheet instructs request 22 dBm for 20 dBm actual output power
|
||||
*inOutPower += 2;
|
||||
} else if (*inOutPower >= 15) {
|
||||
state = SX126x::setPaConfig(0x02, SX126X_PA_CONFIG_SX1262_8, 0x03);
|
||||
// datasheet instructs request 22 dBm for 17 dBm actual output power
|
||||
*inOutPower += 5;
|
||||
} else {
|
||||
state = SX126x::setPaConfig(0x02, SX126X_PA_CONFIG_SX1262_8, 0x02);
|
||||
// datasheet instructs request 22 dBm for 14 dBm actual output power.
|
||||
*inOutPower += 8;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
int16_t SX126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro) {
|
||||
// calculate symbol length and enable low data rate optimization, if needed
|
||||
if(ldro == 0xFF) {
|
||||
|
@ -1265,14 +1262,20 @@ int16_t SX126x::config(uint8_t modem) {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
return(SX126x::SPItransfer(cmd, cmdLen, true, data, NULL, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
uint8_t cmdBuffer[] = {cmd};
|
||||
return(SX126x::SPItransfer(cmdBuffer, 1, true, data, NULL, numBytes, waitForBusy));
|
||||
return(SX126x::SPItransfer(&cmd, 1, true, data, NULL, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
return(SX126x::SPItransfer(cmd, cmdLen, false, NULL, data, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
uint8_t cmdBuffer[] = {cmd};
|
||||
return(SX126x::SPItransfer(cmdBuffer, 1, false, NULL, data, numBytes, waitForBusy));
|
||||
return(SX126x::SPItransfer(&cmd, 1, false, NULL, data, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout) {
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_HP_MAX 0x07
|
||||
#define SX126X_PA_CONFIG_PA_LUT 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262_8 0x00
|
||||
|
||||
//SX126X_CMD_SET_RX_TX_FALLBACK_MODE
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode
|
||||
|
@ -739,6 +740,7 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t calibrateImage(uint8_t* data);
|
||||
uint8_t getPacketType();
|
||||
int16_t setTxParams(uint8_t power, uint8_t rampTime = SX126X_PA_RAMP_200U);
|
||||
int16_t setOptimalHiPowerPaConfig(int8_t* inOutPower);
|
||||
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);
|
||||
|
@ -769,7 +771,9 @@ 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 SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, 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 SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout = 5000);
|
||||
};
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue