[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
|
getStatus KEYWORD2
|
||||||
setAutoAck KEYWORD2
|
setAutoAck KEYWORD2
|
||||||
|
|
||||||
|
# LR11x0
|
||||||
|
beginLRFHSS KEYWORD2
|
||||||
|
setLrFhssConfig KEYWORD2
|
||||||
|
|
||||||
# RTTY
|
# RTTY
|
||||||
idle KEYWORD2
|
idle KEYWORD2
|
||||||
byteArr KEYWORD2
|
byteArr KEYWORD2
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,19 @@ class LR1110: public LR11x0 {
|
||||||
*/
|
*/
|
||||||
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
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -249,6 +194,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,10 +383,18 @@ 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);
|
||||||
|
|
||||||
|
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
|
// write packet to buffer
|
||||||
state = writeBuffer8(data, len);
|
state = writeBuffer8(data, len);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// clear interrupt flags
|
// clear interrupt flags
|
||||||
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
|
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue