RadioLib/src/modules/SX127x/SX1272.cpp

474 wiersze
13 KiB
C++
Czysty Zwykły widok Historia

2018-03-05 16:08:42 +00:00
#include "SX1272.h"
2020-06-30 08:43:56 +00:00
#if !defined(RADIOLIB_EXCLUDE_SX127X)
2018-03-05 16:08:42 +00:00
SX1272::SX1272(Module* mod) : SX127x(mod) {
2019-05-19 14:15:50 +00:00
2018-03-05 16:08:42 +00:00
}
int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
// execute common part
int16_t state = SX127x::begin(SX1272_CHIP_VERSION, syncWord, preambleLength);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-08-02 13:11:38 +00:00
// mitigation of receiver spurious response
// see SX1272/73 Errata, section 2.2 for details
state = _mod->SPIsetRegValue(0x31, 0b10000000, 7, 7);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
// configure publicly accessible settings
state = setBandwidth(bw);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
state = setFrequency(freq);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
state = setSpreadingFactor(sf);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
state = setCodingRate(cr);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-07-09 14:37:22 +00:00
state = setOutputPower(power);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-08-02 13:11:38 +00:00
state = setGain(gain);
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-08-02 13:11:38 +00:00
return(state);
2018-03-05 16:08:42 +00:00
}
int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t power, uint16_t preambleLength, bool enableOOK) {
2018-08-18 14:17:10 +00:00
// execute common part
int16_t state = SX127x::beginFSK(SX1272_CHIP_VERSION, br, rxBw, freqDev, preambleLength, enableOOK);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
// configure settings not accessible by API
state = configFSK();
RADIOLIB_ASSERT(state);
2018-08-18 14:17:10 +00:00
// configure publicly accessible settings
state = setFrequency(freq);
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
state = setDataShaping(RADIOLIB_SHAPING_NONE);
RADIOLIB_ASSERT(state);
2018-08-18 14:17:10 +00:00
state = setOutputPower(power);
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-08-18 14:17:10 +00:00
return(state);
}
void SX1272::reset() {
Module::pinMode(_mod->getRst(), OUTPUT);
Module::digitalWrite(_mod->getRst(), HIGH);
Module::delay(1);
Module::digitalWrite(_mod->getRst(), LOW);
Module::delay(5);
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setFrequency(float freq) {
2020-03-30 17:29:29 +00:00
RADIOLIB_CHECK_RANGE(freq, 860.0, 1020.0, ERR_INVALID_FREQUENCY);
2019-05-19 14:15:50 +00:00
2018-10-31 16:44:47 +00:00
// set frequency and if successful, save the new setting
int16_t state = SX127x::setFrequencyRaw(freq);
if(state == ERR_NONE) {
SX127x::_freq = freq;
}
return(state);
2018-03-05 16:08:42 +00:00
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setBandwidth(float bw) {
2018-08-18 14:17:10 +00:00
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
uint8_t newBandwidth;
2019-05-19 14:15:50 +00:00
// check allowed bandwidth values
2018-08-02 13:11:38 +00:00
if(abs(bw - 125.0) <= 0.001) {
newBandwidth = SX1272_BW_125_00_KHZ;
2018-08-02 13:11:38 +00:00
} else if(abs(bw - 250.0) <= 0.001) {
newBandwidth = SX1272_BW_250_00_KHZ;
2018-08-02 13:11:38 +00:00
} else if(abs(bw - 500.0) <= 0.001) {
newBandwidth = SX1272_BW_500_00_KHZ;
} else {
return(ERR_INVALID_BANDWIDTH);
}
2019-05-19 14:15:50 +00:00
2018-07-11 15:56:26 +00:00
// set bandwidth and if successful, save the new setting
2018-07-23 10:47:47 +00:00
int16_t state = SX1272::setBandwidthRaw(newBandwidth);
2018-07-04 12:26:58 +00:00
if(state == ERR_NONE) {
SX127x::_bw = bw;
2019-06-02 14:22:57 +00:00
// calculate symbol length and set low data rate optimization, if auto-configuration is enabled
if(_ldroAuto) {
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
RADIOLIB_DEBUG_PRINT("Symbol length: ");
RADIOLIB_DEBUG_PRINT(symbolLength);
RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0);
}
2019-06-02 14:22:57 +00:00
}
2018-07-04 12:26:58 +00:00
}
return(state);
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setSpreadingFactor(uint8_t sf) {
2018-08-18 14:17:10 +00:00
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
uint8_t newSpreadingFactor;
2019-05-19 14:15:50 +00:00
// check allowed spreading factor values
switch(sf) {
case 6:
newSpreadingFactor = SX127X_SF_6;
break;
case 7:
newSpreadingFactor = SX127X_SF_7;
break;
case 8:
newSpreadingFactor = SX127X_SF_8;
break;
case 9:
newSpreadingFactor = SX127X_SF_9;
break;
case 10:
newSpreadingFactor = SX127X_SF_10;
break;
case 11:
newSpreadingFactor = SX127X_SF_11;
break;
case 12:
newSpreadingFactor = SX127X_SF_12;
break;
default:
return(ERR_INVALID_SPREADING_FACTOR);
2018-03-05 16:08:42 +00:00
}
2019-05-19 14:15:50 +00:00
2018-07-11 15:56:26 +00:00
// set spreading factor and if successful, save the new setting
2018-07-23 10:47:47 +00:00
int16_t state = SX1272::setSpreadingFactorRaw(newSpreadingFactor);
if(state == ERR_NONE) {
SX127x::_sf = sf;
2019-06-02 14:22:57 +00:00
// calculate symbol length and set low data rate optimization, if auto-configuration is enabled
if(_ldroAuto) {
2019-06-02 14:22:57 +00:00
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
RADIOLIB_DEBUG_PRINT("Symbol length: ");
RADIOLIB_DEBUG_PRINT(symbolLength);
RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0);
}
2019-06-02 14:22:57 +00:00
}
}
return(state);
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setCodingRate(uint8_t cr) {
2018-08-18 14:17:10 +00:00
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
uint8_t newCodingRate;
2019-05-19 14:15:50 +00:00
// check allowed coding rate values
switch(cr) {
case 5:
newCodingRate = SX1272_CR_4_5;
break;
case 6:
newCodingRate = SX1272_CR_4_6;
break;
case 7:
newCodingRate = SX1272_CR_4_7;
break;
case 8:
newCodingRate = SX1272_CR_4_8;
break;
default:
return(ERR_INVALID_CODING_RATE);
2018-03-05 16:08:42 +00:00
}
2019-05-19 14:15:50 +00:00
2018-07-11 15:56:26 +00:00
// set coding rate and if successful, save the new setting
2018-07-23 10:47:47 +00:00
int16_t state = SX1272::setCodingRateRaw(newCodingRate);
if(state == ERR_NONE) {
SX127x::_cr = cr;
2018-03-05 16:08:42 +00:00
}
return(state);
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setOutputPower(int8_t power) {
2018-07-11 15:56:26 +00:00
// check allowed power range
2018-07-26 16:35:11 +00:00
if(!(((power >= -1) && (power <= 17)) || (power == 20))) {
2018-07-09 14:37:22 +00:00
return(ERR_INVALID_OUTPUT_POWER);
}
2019-05-19 14:15:50 +00:00
2018-07-11 15:56:26 +00:00
// set mode to standby
2018-08-02 13:11:38 +00:00
int16_t state = SX127x::standby();
2019-05-19 14:15:50 +00:00
2018-08-02 13:11:38 +00:00
// set output power
2018-07-26 16:35:11 +00:00
if(power < 2) {
// power is less than 2 dBm, enable PA0 on RFIO
2018-08-02 13:11:38 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_RFO, 7, 7);
2018-07-26 16:35:11 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, (power + 1), 3, 0);
2018-07-09 14:37:22 +00:00
state |= _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_OFF, 2, 0);
2020-07-04 12:49:05 +00:00
} else if(power <= 17) {
2018-07-26 16:35:11 +00:00
// power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST
2018-08-02 13:11:38 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST, 7, 7);
2018-07-26 16:35:11 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, (power - 2), 3, 0);
2018-07-09 14:37:22 +00:00
state |= _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_OFF, 2, 0);
2018-07-26 16:35:11 +00:00
} else if(power == 20) {
// power is 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control
2018-08-02 13:11:38 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, SX127X_PA_SELECT_BOOST, 7, 7);
2018-07-26 16:35:11 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_PA_CONFIG, (power - 5), 3, 0);
2018-07-09 14:37:22 +00:00
state |= _mod->SPIsetRegValue(SX1272_REG_PA_DAC, SX127X_PA_BOOST_ON, 2, 0);
}
2018-08-02 13:11:38 +00:00
return(state);
}
int16_t SX1272::setGain(uint8_t gain) {
2018-08-18 14:17:10 +00:00
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
2018-08-02 13:11:38 +00:00
// check allowed range
if(gain > 6) {
return(ERR_INVALID_GAIN);
}
2019-05-19 14:15:50 +00:00
2018-08-02 13:11:38 +00:00
// set mode to standby
int16_t state = SX127x::standby();
2019-05-19 14:15:50 +00:00
2018-08-02 13:11:38 +00:00
// set gain
if(gain == 0) {
// gain set to 0, enable AGC loop
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_ON, 2, 2);
} else {
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_AGC_AUTO_OFF, 2, 2);
state |= _mod->SPIsetRegValue(SX127X_REG_LNA, (gain << 5) | SX127X_LNA_BOOST_ON);
}
2018-07-09 14:37:22 +00:00
return(state);
}
int16_t SX1272::setDataShaping(uint8_t sh) {
2018-12-26 10:36:30 +00:00
// check active modem
if(getActiveModem() != SX127X_FSK_OOK) {
return(ERR_WRONG_MODEM);
}
2019-05-19 14:15:50 +00:00
2019-03-22 18:01:56 +00:00
// check modulation
if(SX127x::_ook) {
2019-03-22 18:01:56 +00:00
return(ERR_INVALID_MODULATION);
}
2019-05-19 14:15:50 +00:00
2018-12-26 10:36:30 +00:00
// set mode to standby
int16_t state = SX127x::standby();
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-12-26 10:36:30 +00:00
// set data shaping
switch(sh) {
case RADIOLIB_SHAPING_NONE:
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_NO_SHAPING, 4, 3));
case RADIOLIB_SHAPING_0_3:
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_0_3, 4, 3));
case RADIOLIB_SHAPING_0_5:
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_0_5, 4, 3));
case RADIOLIB_SHAPING_1_0:
return(_mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_FSK_GAUSSIAN_1_0, 4, 3));
default:
return(ERR_INVALID_DATA_SHAPING);
2018-12-26 10:36:30 +00:00
}
}
2019-03-22 18:01:56 +00:00
int16_t SX1272::setDataShapingOOK(uint8_t sh) {
// check active modem
if(getActiveModem() != SX127X_FSK_OOK) {
return(ERR_WRONG_MODEM);
}
2019-05-19 14:15:50 +00:00
2019-03-22 18:01:56 +00:00
// check modulation
if(!SX127x::_ook) {
return(ERR_INVALID_MODULATION);
}
2019-05-19 14:15:50 +00:00
2019-03-22 18:01:56 +00:00
// set mode to standby
int16_t state = SX127x::standby();
2019-05-19 14:15:50 +00:00
2019-03-22 18:01:56 +00:00
// set data shaping
switch(sh) {
case 0:
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_NO_SHAPING, 4, 3);
2019-03-22 18:01:56 +00:00
break;
case 1:
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_OOK_FILTER_BR, 4, 3);
2019-03-22 18:01:56 +00:00
break;
case 2:
state |= _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX1272_OOK_FILTER_2BR, 4, 3);
2019-03-22 18:01:56 +00:00
break;
default:
state = ERR_INVALID_DATA_SHAPING;
break;
}
2019-05-19 14:15:50 +00:00
2019-03-22 18:01:56 +00:00
return(state);
}
2019-11-19 16:08:59 +00:00
float SX1272::getRSSI() {
if(getActiveModem() == SX127X_LORA) {
// RSSI calculation uses different constant for low-frequency and high-frequency ports
float lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
// spread-spectrum modulation signal can be received below noise floor
// check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
float lastPacketSNR = SX127x::getSNR();
if(lastPacketSNR < 0.0) {
lastPacketRSSI += lastPacketSNR;
}
2019-05-19 14:15:50 +00:00
2019-11-19 16:08:59 +00:00
return(lastPacketRSSI);
2019-05-19 14:15:50 +00:00
2019-11-19 16:08:59 +00:00
} else {
// enable listen mode
startReceive();
// read the value for FSK
float rssi = (float)_mod->SPIgetRegValue(SX127X_REG_RSSI_VALUE_FSK) / -2.0;
2019-05-19 14:15:50 +00:00
2019-11-19 16:08:59 +00:00
// set mode back to standby
standby();
// return the value
return(rssi);
}
2018-10-31 16:44:47 +00:00
}
2019-03-22 18:01:56 +00:00
int16_t SX1272::setCRC(bool enableCRC) {
if(getActiveModem() == SX127X_LORA) {
// set LoRa CRC
SX127x::_crcEnabled = enableCRC;
2019-03-22 18:01:56 +00:00
if(enableCRC) {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_RX_CRC_MODE_ON, 2, 2));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_RX_CRC_MODE_OFF, 2, 2));
}
} else {
// set FSK CRC
if(enableCRC) {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4));
}
}
}
int16_t SX1272::forceLDRO(bool enable) {
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
_ldroAuto = false;
if(enable) {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0));
}
}
int16_t SX1272::autoLDRO() {
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
_ldroAuto = true;
return(ERR_NONE);
}
int16_t SX1272::implicitHeader(size_t len) {
return(setHeaderType(SX1272_HEADER_IMPL_MODE, len));
}
int16_t SX1272::explicitHeader() {
return(setHeaderType(SX1272_HEADER_EXPL_MODE));
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) {
// set mode to standby
2018-08-02 13:11:38 +00:00
int16_t state = SX127x::standby();
2019-05-19 14:15:50 +00:00
// write register
2018-08-02 13:11:38 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, newBandwidth, 7, 6);
return(state);
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
// set mode to standby
2018-08-02 13:11:38 +00:00
int16_t state = SX127x::standby();
2019-05-19 14:15:50 +00:00
// write registers
if(newSpreadingFactor == SX127X_SF_6) {
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_IMPL_MODE | (SX127x::_crcEnabled ? SX1272_RX_CRC_MODE_ON : SX1272_RX_CRC_MODE_OFF), 2, 1);
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE, 7, 3);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6);
} else {
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_EXPL_MODE | (SX127x::_crcEnabled ? SX1272_RX_CRC_MODE_ON : SX1272_RX_CRC_MODE_OFF), 2, 1);
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | SX127X_TX_MODE_SINGLE, 7, 3);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12);
2018-03-05 16:08:42 +00:00
}
return(state);
}
2018-07-23 10:47:47 +00:00
int16_t SX1272::setCodingRateRaw(uint8_t newCodingRate) {
// set mode to standby
2018-08-02 13:11:38 +00:00
int16_t state = SX127x::standby();
2019-05-19 14:15:50 +00:00
// write register
2018-08-02 13:11:38 +00:00
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, newCodingRate, 5, 3);
return(state);
}
int16_t SX1272::setHeaderType(uint8_t headerType, size_t len) {
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
// set requested packet mode
int16_t state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, headerType, 2, 2);
RADIOLIB_ASSERT(state);
// set length to register
state = _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH, len);
RADIOLIB_ASSERT(state);
// update cached value
_packetLength = len;
return(state);
}
2018-08-18 14:17:10 +00:00
int16_t SX1272::configFSK() {
// configure common registers
int16_t state = SX127x::configFSK();
2020-01-13 15:37:31 +00:00
RADIOLIB_ASSERT(state);
2019-05-19 14:15:50 +00:00
2018-08-20 10:02:25 +00:00
// set fast PLL hop
state = _mod->SPIsetRegValue(SX1272_REG_PLL_HOP, SX127X_FAST_HOP_ON, 7, 7);
2018-08-18 14:17:10 +00:00
return(state);
}
2020-06-30 08:43:56 +00:00
#endif