[LR11x0] Added support for LR-FHSS

pull/1075/head
jgromes 2024-04-21 15:01:57 +02:00
rodzic ce4d9aa150
commit e8a6297c60
6 zmienionych plików z 298 dodań i 92 usunięć

Wyświetl plik

@ -0,0 +1,110 @@
/*
RadioLib LR11x0 LR-FHSS Modem Example
This example shows how to use LR-FHSS modem in LR11x0 chips.
NOTE: The sketch below is just a guide on how to use
LR-FHSS modem, so this code should not be run directly!
Instead, modify the other examples to use LR-FHSS
modem and use the appropriate configuration
methods.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lr-fhss-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// LR1110 has the following connections:
// NSS pin: 10
// IRQ pin: 2
// NRST pin: 3
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
void setup() {
Serial.begin(9600);
// initialize LR1110 with default settings
Serial.print(F("[LR1110] Initializing ... "));
int state = radio.beginLRFHSS();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// if needed, you can switch between any of the modems
//
// radio.begin() start LoRa modem (and disable LR-FHSS)
// radio.beginLRFHSS() start LR-FHSS modem (and disable LoRa)
// the following settings can also
// be modified at run-time
state = radio.setFrequency(433.5);
state = radio.setLrFhssConfig(RADIOLIB_LR11X0_LR_FHSS_BW_1523_4, // bandwidth
RADIOLIB_LR11X0_LR_FHSS_CR_1_2, // coding rate
3, // header count
0x13A); // hopping sequence seed
state = radio.setOutputPower(10.0);
state = radio.setSyncWord(0x12345678);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Unable to set configuration, code "));
Serial.println(state);
while (true);
}
#warning "This sketch is just an API guide! Read the note at line 6."
}
void loop() {
// LR-FHSS modem can use the same transmit/receive methods
// as the LoRa modem, even their interrupt-driven versions
// transmit LR-FHSS packet
int state = radio.transmit("Hello World!");
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);
*/
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("[LR1110] Packet transmitted successfully!"));
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
Serial.println(F("[LR1110] Packet too long!"));
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
Serial.println(F("[LR1110] Timed out while transmitting!"));
} else {
Serial.println(F("[LR1110] Failed to transmit packet, code "));
Serial.println(state);
}
// receive LR-FHSS packet
String str;
state = radio.receive(str);
/*
byte byteArr[8];
int state = radio.receive(byteArr, 8);
*/
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("[LR1110] Received packet!"));
Serial.print(F("[LR1110] Data:\t"));
Serial.println(str);
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
Serial.println(F("[LR1110] Timed out while waiting for packet!"));
} else {
Serial.print(F("[LR1110] Failed to receive packet, code "));
Serial.println(state);
}
}

Wyświetl plik

@ -239,6 +239,10 @@ disablePipe KEYWORD2
getStatus KEYWORD2 getStatus KEYWORD2
setAutoAck KEYWORD2 setAutoAck KEYWORD2
# LR11x0
beginLRFHSS KEYWORD2
setLrFhssConfig KEYWORD2
# RTTY # RTTY
idle KEYWORD2 idle KEYWORD2
byteArr KEYWORD2 byteArr KEYWORD2

Wyświetl plik

@ -31,6 +31,19 @@ int16_t LR1110::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_
return(state); return(state);
} }
int16_t LR1110::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
// execute common part
int16_t state = LR11x0::beginLRFHSS(bw, cr, tcxoVoltage);
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
state = setOutputPower(power);
return(state);
}
int16_t LR1110::setFrequency(float freq) { int16_t LR1110::setFrequency(float freq) {
return(this->setFrequency(freq, true)); return(this->setFrequency(freq, true));
} }

Wyświetl plik

@ -52,6 +52,19 @@ class LR1110: public LR11x0 {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t beginGFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6); int16_t beginGFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6);
/*!
\brief Initialization method for LR-FHSS modem.
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values. Defaults to 722.66 kHz.
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values. Defaults to 2/3 coding rate.
\param power Output power in dBm. Defaults to 10 dBm.
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
\returns \ref status_codes
*/
int16_t beginLRFHSS(float freq = 434.0, uint8_t bw = RADIOLIB_LR11X0_LR_FHSS_BW_722_66, uint8_t cr = RADIOLIB_LR11X0_LR_FHSS_CR_2_3, int8_t power = 10, float tcxoVoltage = 1.6);
// configuration methods // configuration methods

Wyświetl plik

@ -14,44 +14,8 @@ LR11x0::LR11x0(Module* mod) : PhysicalLayer(RADIOLIB_LR11X0_FREQUENCY_STEP_SIZE,
} }
int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage) { int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage) {
// set module properties // set module properties and perform initial setup
this->mod->init(); int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_LORA);
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_32;
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_8;
this->mod->spiConfig.statusPos = 0;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_LR11X0_CMD_READ_REG_MEM;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_LR11X0_CMD_WRITE_REG_MEM;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_LR11X0_CMD_NOP;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_LR11X0_CMD_GET_STATUS;
this->mod->spiConfig.stream = true;
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
this->mod->spiConfig.checkStatusCb = SPIcheckStatus;
// try to find the LR11x0 chip - this will also reset the module at least once
if(!LR11x0::findChip(this->chipType)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No LR11x0 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
}
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tLR11x0");
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
// set TCXO control, if requested
if(!this->XTAL && tcxoVoltage > 0.0) {
state = setTCXO(tcxoVoltage);
RADIOLIB_ASSERT(state);
}
// configure settings not accessible by API
state = config(RADIOLIB_LR11X0_PACKET_TYPE_LORA);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// configure publicly accessible settings // configure publicly accessible settings
@ -81,42 +45,8 @@ int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16
} }
int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage) { int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage) {
// set module properties // set module properties and perform initial setup
this->mod->init(); int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_GFSK);
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_32;
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_8;
this->mod->spiConfig.statusPos = 0;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_LR11X0_CMD_READ_REG_MEM;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_LR11X0_CMD_WRITE_REG_MEM;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_LR11X0_CMD_NOP;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_LR11X0_CMD_GET_STATUS;
this->mod->spiConfig.stream = true;
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
this->mod->spiConfig.checkStatusCb = SPIcheckStatus;
// try to find the LR11x0 chip - this will also reset the module at least once
if(!LR11x0::findChip(this->chipType)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No LR11x0 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
}
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tLR11x0");
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
// set TCXO control, if requested
if(!this->XTAL && tcxoVoltage > 0.0) {
state = setTCXO(tcxoVoltage);
RADIOLIB_ASSERT(state);
}
// configure settings not accessible by API
state = config(RADIOLIB_LR11X0_PACKET_TYPE_GFSK);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// configure publicly accessible settings // configure publicly accessible settings
@ -152,6 +82,22 @@ int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, uint16_t preamble
return(RADIOLIB_ERR_NONE); return(RADIOLIB_ERR_NONE);
} }
int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, float tcxoVoltage) {
// set module properties and perform initial setup
int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS);
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setLrFhssConfig(bw, cr);
RADIOLIB_ASSERT(state);
state = setSyncWord(0x12AD101B);
RADIOLIB_ASSERT(state);
// set fixed configuration
return(setModulationParamsLrFhss(RADIOLIB_LR11X0_LR_FHSS_BIT_RATE_RAW, RADIOLIB_LR11X0_LR_FHSS_SHAPING_GAUSSIAN_BT_1_0));
}
int16_t LR11x0::reset() { int16_t LR11x0::reset() {
// run the reset sequence // run the reset sequence
this->mod->hal->pinMode(this->mod->getRst(), this->mod->hal->GpioModeOutput); this->mod->hal->pinMode(this->mod->getRst(), this->mod->hal->GpioModeOutput);
@ -185,18 +131,17 @@ int16_t LR11x0::transmit(uint8_t* data, size_t len, uint8_t addr) {
return(RADIOLIB_ERR_PACKET_TOO_LONG); return(RADIOLIB_ERR_PACKET_TOO_LONG);
} }
uint32_t timeout = 0;
// get currently active modem // get currently active modem
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE; uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem); state = getPacketType(&modem);
uint32_t timeout = getTimeOnAir(len);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) { if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
// calculate timeout (150% of expected time-on-air) // calculate timeout (150% of expected time-on-air)
timeout = (getTimeOnAir(len) * 3) / 2; timeout = (timeout * 3) / 2;
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) { } else if((modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) || (modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS)) {
// calculate timeout (500% of expected time-on-air) // calculate timeout (500% of expected time-on-air)
timeout = getTimeOnAir(len) * 5; timeout = timeout * 5;
} else { } else {
return(RADIOLIB_ERR_UNKNOWN); return(RADIOLIB_ERR_UNKNOWN);
@ -248,6 +193,13 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
} }
float brBps = ((float)(RADIOLIB_LR11X0_CRYSTAL_FREQ) * 1000000.0 * 32.0) / (float)this->bitRate; float brBps = ((float)(RADIOLIB_LR11X0_CRYSTAL_FREQ) * 1000000.0 * 32.0) / (float)this->bitRate;
timeout = (uint32_t)(((maxLen * 8.0) / brBps) * 1000.0 * 5.0); timeout = (uint32_t)(((maxLen * 8.0) / brBps) * 1000.0 * 5.0);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
size_t maxLen = len;
if(len == 0) {
maxLen = 0xFF;
}
timeout = (uint32_t)(((maxLen * 8.0) / (RADIOLIB_LR11X0_LR_FHSS_BIT_RATE)) * 1000.0 * 5.0);
} else { } else {
return(RADIOLIB_ERR_UNKNOWN); return(RADIOLIB_ERR_UNKNOWN);
@ -417,10 +369,13 @@ int16_t LR11x0::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) { if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcTypeLoRa, this->invertIQEnabled); state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcTypeLoRa, this->invertIQEnabled);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) { } else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, len, this->crcTypeGFSK, this->whitening); state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, len, this->crcTypeGFSK, this->whitening);
} else {
} else if(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN); return(RADIOLIB_ERR_UNKNOWN);
} }
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
@ -428,9 +383,17 @@ int16_t LR11x0::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_TX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT, 0); state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_TX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT, 0);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// write packet to buffer if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
state = writeBuffer8(data, len); // in LR-FHSS mode, the packet is built by the device
RADIOLIB_ASSERT(state); // TODO add configurable grid step and device offset
state = lrFhssBuildFrame(this->lrFhssHdrCount, this->lrFhssCr, RADIOLIB_LR11X0_LR_FHSS_GRID_STEP_FCC, true, this->lrFhssBw, this->lrFhssHopSeq, 0, data, len);
} else {
// write packet to buffer
state = writeBuffer8(data, len);
RADIOLIB_ASSERT(state);
}
// clear interrupt flags // clear interrupt flags
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL); state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
@ -471,7 +434,9 @@ int16_t LR11x0::startReceive(uint32_t timeout, uint32_t irqFlags, size_t len) {
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE; uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem); state = getPacketType(&modem);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) && (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) { if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS)) {
return(RADIOLIB_ERR_WRONG_MODEM); return(RADIOLIB_ERR_WRONG_MODEM);
} }
@ -519,7 +484,9 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) {
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE; uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem); state = getPacketType(&modem);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) && (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) { if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS)) {
return(RADIOLIB_ERR_WRONG_MODEM); return(RADIOLIB_ERR_WRONG_MODEM);
} }
@ -659,7 +626,7 @@ int16_t LR11x0::setSpreadingFactor(uint8_t sf, bool legacy) {
RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR); RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
// enable SF6 legacy mode // TODO enable SF6 legacy mode
if(legacy && (sf == 6)) { if(legacy && (sf == 6)) {
//this->mod->SPIsetRegValue(RADIOLIB_LR11X0_REG_SF6_SX127X_COMPAT, RADIOLIB_LR11X0_SF6_SX127X, 18, 18); //this->mod->SPIsetRegValue(RADIOLIB_LR11X0_REG_SF6_SX127X_COMPAT, RADIOLIB_LR11X0_SF6_SX127X, 18, 18);
} }
@ -702,8 +669,20 @@ int16_t LR11x0::setCodingRate(uint8_t cr, bool longInterleave) {
return(setModulationParamsLoRa(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize)); return(setModulationParamsLoRa(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
} }
int16_t LR11x0::setSyncWord(uint8_t syncWord) { int16_t LR11x0::setSyncWord(uint32_t syncWord) {
return(setLoRaSyncWord(syncWord)); // check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
return(setLoRaSyncWord(syncWord & 0xFF));
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(lrFhssSetSyncWord(syncWord));
}
return(RADIOLIB_ERR_WRONG_MODEM);
} }
int16_t LR11x0::setBitRate(float br) { int16_t LR11x0::setBitRate(float br) {
@ -1271,6 +1250,9 @@ uint32_t LR11x0::getTimeOnAir(size_t len) {
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) { } else if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
return(((uint32_t)len * 8 * 1000000UL) / this->bitRate); return(((uint32_t)len * 8 * 1000000UL) / this->bitRate);
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(((uint32_t)len * 8 * 1000000UL) / RADIOLIB_LR11X0_LR_FHSS_BIT_RATE);
} }
return(0); return(0);
@ -1280,6 +1262,65 @@ float LR11x0::getDataRate() const {
return(this->dataRateMeasured); return(this->dataRateMeasured);
} }
int16_t LR11x0::setLrFhssConfig(uint8_t bw, uint8_t cr, uint8_t hdrCount, uint16_t hopSeed) {
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
if(type != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// check and cache all parameters
RADIOLIB_CHECK_RANGE((int8_t)cr, (int8_t)RADIOLIB_LR11X0_LR_FHSS_CR_5_6, (int8_t)RADIOLIB_LR11X0_LR_FHSS_CR_1_3, RADIOLIB_ERR_INVALID_CODING_RATE);
this->lrFhssCr = cr;
RADIOLIB_CHECK_RANGE((int8_t)bw, (int8_t)RADIOLIB_LR11X0_LR_FHSS_BW_39_06, (int8_t)RADIOLIB_LR11X0_LR_FHSS_BW_1574_2, RADIOLIB_ERR_INVALID_BANDWIDTH);
this->lrFhssBw = bw;
RADIOLIB_CHECK_RANGE(hdrCount, 1, 4, RADIOLIB_ERR_INVALID_BIT_RANGE);
this->lrFhssHdrCount = hdrCount;
RADIOLIB_CHECK_RANGE((int16_t)hopSeed, (int16_t)0x000, (int16_t)0x1FF, RADIOLIB_ERR_INVALID_DATA_SHAPING);
this->lrFhssHopSeq = hopSeed;
return(RADIOLIB_ERR_NONE);
}
int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_32;
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_8;
this->mod->spiConfig.statusPos = 0;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_LR11X0_CMD_READ_REG_MEM;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_LR11X0_CMD_WRITE_REG_MEM;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_LR11X0_CMD_NOP;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_LR11X0_CMD_GET_STATUS;
this->mod->spiConfig.stream = true;
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
this->mod->spiConfig.checkStatusCb = SPIcheckStatus;
// try to find the LR11x0 chip - this will also reset the module at least once
if(!LR11x0::findChip(this->chipType)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No LR11x0 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
}
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tLR11x0");
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
// set TCXO control, if requested
if(!this->XTAL && tcxoVoltage > 0.0) {
state = setTCXO(tcxoVoltage);
RADIOLIB_ASSERT(state);
}
// configure settings not accessible by API
return(config(modem));
}
int16_t LR11x0::SPIparseStatus(uint8_t in) { int16_t LR11x0::SPIparseStatus(uint8_t in) {
if((in & 0b00001110) == RADIOLIB_LR11X0_STAT_1_CMD_PERR) { if((in & 0b00001110) == RADIOLIB_LR11X0_STAT_1_CMD_PERR) {
return(RADIOLIB_ERR_SPI_CMD_INVALID); return(RADIOLIB_ERR_SPI_CMD_INVALID);

Wyświetl plik

@ -366,7 +366,8 @@
#define RADIOLIB_LR11X0_GFSK_RX_BW_312_0 (0x19UL << 0) // 7 0 312.0 kHz #define RADIOLIB_LR11X0_GFSK_RX_BW_312_0 (0x19UL << 0) // 7 0 312.0 kHz
#define RADIOLIB_LR11X0_GFSK_RX_BW_373_6 (0x11UL << 0) // 7 0 373.6 kHz #define RADIOLIB_LR11X0_GFSK_RX_BW_373_6 (0x11UL << 0) // 7 0 373.6 kHz
#define RADIOLIB_LR11X0_GFSK_RX_BW_467_0 (0x09UL << 0) // 7 0 467.0 kHz #define RADIOLIB_LR11X0_GFSK_RX_BW_467_0 (0x09UL << 0) // 7 0 467.0 kHz
#define RADIOLIB_LR11X0_LR_FHSS_BIT_RATE (0x8001E848UL) // 31 0 LR FHSS bit rate: 488.28215 bps #define RADIOLIB_LR11X0_LR_FHSS_BIT_RATE (488.28215) // 31 0 LR FHSS bit rate: 488.28215 bps
#define RADIOLIB_LR11X0_LR_FHSS_BIT_RATE_RAW (0x8001E848UL) // 31 0 488.28215 bps in raw
#define RADIOLIB_LR11X0_LR_FHSS_SHAPING_GAUSSIAN_BT_1_0 (0x0BUL << 0) // 7 0 shaping filter: Gaussian, BT = 1.0 #define RADIOLIB_LR11X0_LR_FHSS_SHAPING_GAUSSIAN_BT_1_0 (0x0BUL << 0) // 7 0 shaping filter: Gaussian, BT = 1.0
#define RADIOLIB_LR11X0_SIGFOX_SHAPING_GAUSSIAN_BT_0_7 (0x16UL << 0) // 7 0 shaping filter: Gaussian, BT = 0.7 #define RADIOLIB_LR11X0_SIGFOX_SHAPING_GAUSSIAN_BT_0_7 (0x16UL << 0) // 7 0 shaping filter: Gaussian, BT = 0.7
@ -582,6 +583,15 @@ class LR11x0: public PhysicalLayer {
*/ */
int16_t beginGFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage); int16_t beginGFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage);
/*!
\brief Initialization method for LR-FHSS modem.
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values.
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values.
\param tcxoVoltage TCXO reference voltage to be set.
\returns \ref status_codes
*/
int16_t beginLRFHSS(uint8_t bw, uint8_t cr, float tcxoVoltage);
/*! /*!
\brief Reset method. Will reset the chip to the default state using RST pin. \brief Reset method. Will reset the chip to the default state using RST pin.
\returns \ref status_codes \returns \ref status_codes
@ -798,11 +808,11 @@ class LR11x0: public PhysicalLayer {
int16_t setCodingRate(uint8_t cr, bool longInterleave = false); int16_t setCodingRate(uint8_t cr, bool longInterleave = false);
/*! /*!
\brief Sets LoRa sync word. \brief Sets LoRa or LR-FHSS sync word.
\param syncWord LoRa sync word to be set. \param syncWord LoRa or LR-FHSS sync word to be set. For LoRa, only 8 least significant bits will be used
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setSyncWord(uint8_t syncWord); int16_t setSyncWord(uint32_t syncWord);
/*! /*!
\brief Sets GFSK bit rate. Allowed values range from 0.6 to 300.0 kbps. \brief Sets GFSK bit rate. Allowed values range from 0.6 to 300.0 kbps.
@ -996,6 +1006,16 @@ class LR11x0: public PhysicalLayer {
*/ */
float getDataRate() const; float getDataRate() const;
/*!
\brief Sets LR-FHSS configuration.
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values.
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values.
\param hdrCount Header packet count, 1 - 4. Defaults to 3.
\param hopSeed 9-bit seed number for PRNG generation of the hopping sequence. Defaults to 0x13A.
\returns \ref status_codes
*/
int16_t setLrFhssConfig(uint8_t bw, uint8_t cr, uint8_t hdrCount = 3, uint16_t hopSeed = 0x13A);
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
protected: protected:
#endif #endif
@ -1165,8 +1185,13 @@ class LR11x0: public PhysicalLayer {
uint8_t preambleDetLength = 0, rxBandwidth = 0, pulseShape = 0, crcTypeGFSK = 0, syncWordLength = 0, addrComp = 0, whitening = 0, packetType = 0, node = 0; uint8_t preambleDetLength = 0, rxBandwidth = 0, pulseShape = 0, crcTypeGFSK = 0, syncWordLength = 0, addrComp = 0, whitening = 0, packetType = 0, node = 0;
uint16_t preambleLengthGFSK = 0; uint16_t preambleLengthGFSK = 0;
// cached LR-FHSS parameters
uint8_t lrFhssCr = 0, lrFhssBw = 0, lrFhssHdrCount = 0;
uint16_t lrFhssHopSeq = 0;
float dataRateMeasured = 0; float dataRateMeasured = 0;
int16_t modSetup(float tcxoVoltage, uint8_t modem);
static int16_t SPIparseStatus(uint8_t in); static int16_t SPIparseStatus(uint8_t in);
static int16_t SPIcheckStatus(Module* mod); static int16_t SPIcheckStatus(Module* mod);
bool findChip(uint8_t ver); bool findChip(uint8_t ver);