[LR11x0] Added support for LR-FHSS
This commit is contained in:
parent
ce4d9aa150
commit
e8a6297c60
6 changed files with 298 additions and 92 deletions
110
examples/LR11x0/LR11x0_LR_FHSS_Modem/LR11x0_LR_FHSS_Modem.ino
Normal file
110
examples/LR11x0/LR11x0_LR_FHSS_Modem/LR11x0_LR_FHSS_Modem.ino
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -239,6 +239,10 @@ disablePipe KEYWORD2
|
|||
getStatus KEYWORD2
|
||||
setAutoAck KEYWORD2
|
||||
|
||||
# LR11x0
|
||||
beginLRFHSS KEYWORD2
|
||||
setLrFhssConfig KEYWORD2
|
||||
|
||||
# RTTY
|
||||
idle KEYWORD2
|
||||
byteArr KEYWORD2
|
||||
|
|
|
@ -31,6 +31,19 @@ int16_t LR1110::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_
|
|||
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) {
|
||||
return(this->setFrequency(freq, true));
|
||||
}
|
||||
|
|
|
@ -52,6 +52,19 @@ class LR1110: public LR11x0 {
|
|||
\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);
|
||||
|
||||
/*!
|
||||
\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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
// set module properties
|
||||
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->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);
|
||||
// set module properties and perform initial setup
|
||||
int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_LORA);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// 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) {
|
||||
// set module properties
|
||||
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
|
||||
state = config(RADIOLIB_LR11X0_PACKET_TYPE_GFSK);
|
||||
// set module properties and perform initial setup
|
||||
int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_GFSK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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() {
|
||||
// run the reset sequence
|
||||
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);
|
||||
}
|
||||
|
||||
uint32_t timeout = 0;
|
||||
|
||||
// get currently active modem
|
||||
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
|
||||
state = getPacketType(&modem);
|
||||
uint32_t timeout = getTimeOnAir(len);
|
||||
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
|
||||
// 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)
|
||||
timeout = getTimeOnAir(len) * 5;
|
||||
timeout = timeout * 5;
|
||||
|
||||
} else {
|
||||
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;
|
||||
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 {
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
|
@ -417,10 +369,13 @@ int16_t LR11x0::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
|
||||
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcTypeLoRa, this->invertIQEnabled);
|
||||
|
||||
} 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);
|
||||
} else {
|
||||
|
||||
} else if(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
|
||||
}
|
||||
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);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// write packet to buffer
|
||||
state = writeBuffer8(data, len);
|
||||
RADIOLIB_ASSERT(state);
|
||||
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
|
||||
// in LR-FHSS mode, the packet is built by the device
|
||||
// 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
|
||||
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;
|
||||
state = getPacketType(&modem);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -519,7 +484,9 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) {
|
|||
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
|
||||
state = getPacketType(&modem);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -659,7 +626,7 @@ int16_t LR11x0::setSpreadingFactor(uint8_t sf, bool legacy) {
|
|||
|
||||
RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
|
||||
|
||||
// enable SF6 legacy mode
|
||||
// TODO enable SF6 legacy mode
|
||||
if(legacy && (sf == 6)) {
|
||||
//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));
|
||||
}
|
||||
|
||||
int16_t LR11x0::setSyncWord(uint8_t syncWord) {
|
||||
return(setLoRaSyncWord(syncWord));
|
||||
int16_t LR11x0::setSyncWord(uint32_t 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) {
|
||||
|
@ -1271,6 +1250,9 @@ uint32_t LR11x0::getTimeOnAir(size_t len) {
|
|||
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
|
||||
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);
|
||||
|
@ -1280,6 +1262,65 @@ float LR11x0::getDataRate() const {
|
|||
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) {
|
||||
if((in & 0b00001110) == RADIOLIB_LR11X0_STAT_1_CMD_PERR) {
|
||||
return(RADIOLIB_ERR_SPI_CMD_INVALID);
|
||||
|
|
|
@ -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_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_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_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);
|
||||
|
||||
/*!
|
||||
\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.
|
||||
\returns \ref status_codes
|
||||
|
@ -798,11 +808,11 @@ class LR11x0: public PhysicalLayer {
|
|||
int16_t setCodingRate(uint8_t cr, bool longInterleave = false);
|
||||
|
||||
/*!
|
||||
\brief Sets LoRa sync word.
|
||||
\param syncWord LoRa sync word to be set.
|
||||
\brief Sets LoRa or LR-FHSS sync word.
|
||||
\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
|
||||
*/
|
||||
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.
|
||||
|
@ -996,6 +1006,16 @@ class LR11x0: public PhysicalLayer {
|
|||
*/
|
||||
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
|
||||
protected:
|
||||
#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;
|
||||
uint16_t preambleLengthGFSK = 0;
|
||||
|
||||
// cached LR-FHSS parameters
|
||||
uint8_t lrFhssCr = 0, lrFhssBw = 0, lrFhssHdrCount = 0;
|
||||
uint16_t lrFhssHopSeq = 0;
|
||||
|
||||
float dataRateMeasured = 0;
|
||||
|
||||
int16_t modSetup(float tcxoVoltage, uint8_t modem);
|
||||
static int16_t SPIparseStatus(uint8_t in);
|
||||
static int16_t SPIcheckStatus(Module* mod);
|
||||
bool findChip(uint8_t ver);
|
||||
|
|
Loading…
Add table
Reference in a new issue