[SX128x] Added FLRC modem support
This commit is contained in:
parent
5c0c7f32c3
commit
ff3225cd19
5 changed files with 304 additions and 46 deletions
114
examples/SX128x/SX128x_FLRC_Modem/SX128x_FLRC_Modem.ino
Normal file
114
examples/SX128x/SX128x_FLRC_Modem/SX128x_FLRC_Modem.ino
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
RadioLib SX128x FLRC Modem Example
|
||||
|
||||
This example shows how to use FLRC modem in SX128x chips.
|
||||
|
||||
NOTE: The sketch below is just a guide on how to use
|
||||
FLRC modem, so this code should not be run directly!
|
||||
Instead, modify the other examples to use FLRC
|
||||
modem and use the appropriate configuration
|
||||
methods.
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1280 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1280 flrc = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//SX1280 flrc = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1280 with default settings
|
||||
Serial.print(F("[SX1280] Initializing ... "));
|
||||
// carrier frequency: 2400.0 MHz
|
||||
// bit rate: 650 kbps
|
||||
// coding rate: 3
|
||||
// output power: 10 dBm
|
||||
// preamble length: 16 bits
|
||||
// data shaping: Gaussian, BT = 0.5
|
||||
// sync word: 0x2D 0x01 0x4B 0x1D
|
||||
// CRC: enabled
|
||||
int state = flrc.beginFLRC();
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, you can switch between LoRa and FLRC modes
|
||||
//
|
||||
// flrc.begin() start LoRa mode (and disable FLRC)
|
||||
// lora.beginFLRC() start FLRC mode (and disable LoRa)
|
||||
|
||||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = flrc.setFrequency(2410.5);
|
||||
state = flrc.setBitRate(200);
|
||||
state = flrc.setCodingRate(2);
|
||||
state = flrc.setOutputPower(5);
|
||||
state = flrc.setDataShaping(1.0);
|
||||
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67};
|
||||
state = flrc.setSyncWord(syncWord, 4);
|
||||
if (state != 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() {
|
||||
// FLRC modem can use the same transmit/receive methods
|
||||
// as the LoRa modem, even their interrupt-driven versions
|
||||
|
||||
// transmit FLRC packet
|
||||
int state = flrc.transmit("Hello World!");
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = flrc.transmit(byteArr, 8);
|
||||
*/
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("[SX1280] Packet transmitted successfully!"));
|
||||
} else if (state == ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[SX1280] Packet too long!"));
|
||||
} else if (state == ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[SX1280] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[SX1280] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// receive GFSK packet
|
||||
String str;
|
||||
state = flrc.receive(str);
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = flrc.receive(byteArr, 8);
|
||||
*/
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("[SX1280] Received packet!"));
|
||||
Serial.print(F("[SX1280] Data:\t"));
|
||||
Serial.println(str);
|
||||
} else if (state == ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("[SX1280] Timed out while waiting for packet!"));
|
||||
} else {
|
||||
Serial.print(F("[SX1280] Failed to receive packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
|
@ -37,7 +37,6 @@ void setup() {
|
|||
// frequency deviation: 400.0 kHz
|
||||
// output power: 10 dBm
|
||||
// preamble length: 16 bits
|
||||
// coding rate: 7
|
||||
// data shaping: Gaussian, BT = 0.5
|
||||
// sync word: 0x2D 0x01
|
||||
// CRC: enabled, CRC16 (CCIT)
|
||||
|
|
|
@ -214,6 +214,11 @@ getPictureHeight KEYWORD2
|
|||
|
||||
# SX128x
|
||||
beginGFSK KEYWORD2
|
||||
beginFLRC KEYWORD2
|
||||
beginBLE KEYWORD2
|
||||
range KEYWORD2
|
||||
startRanging KEYWORD2
|
||||
getRangingResult KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
|
|
@ -114,6 +114,64 @@ int16_t SX128x::beginGFSK(float freq, uint16_t br, float freqDev, int8_t power,
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX128x::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t power, uint16_t preambleLength, float dataShaping) {
|
||||
// set module properties
|
||||
_mod->init(RADIOLIB_USE_SPI);
|
||||
Module::pinMode(_mod->getIrq(), INPUT);
|
||||
Module::pinMode(_mod->getGpio(), INPUT);
|
||||
|
||||
// initialize FLRC modulation variables
|
||||
_brKbps = br;
|
||||
_br = SX128X_FLRC_BR_0_650_BW_0_6;
|
||||
_crFLRC = SX128X_FLRC_CR_3_4;
|
||||
_shaping = SX128X_FLRC_BT_0_5;
|
||||
|
||||
// initialize FLRC packet variables
|
||||
_preambleLengthGFSK = preambleLength;
|
||||
_syncWordLen = 2;
|
||||
_syncWordMatch = SX128X_GFSK_FLRC_SYNC_WORD_1;
|
||||
_crcGFSK = SX128X_GFSK_FLRC_CRC_2_BYTE;
|
||||
_whitening = SX128X_GFSK_BLE_WHITENING_OFF;
|
||||
|
||||
// reset the module and verify startup
|
||||
int16_t state = reset();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set mode to standby
|
||||
state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure settings not accessible by API
|
||||
state = config(SX128X_PACKET_TYPE_FLRC);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setBitRate(br);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setCodingRate(cr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setPreambleLength(preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setDataShaping(dataShaping);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set publicly accessible settings that are not a part of begin method
|
||||
uint8_t sync[] = { 0x2D, 0x01, 0x4B, 0x1D};
|
||||
state = setSyncWord(sync, 4);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX128x::reset(bool verify) {
|
||||
// run the reset sequence - same as SX126x, as SX128x docs don't seem to mention this
|
||||
Module::pinMode(_mod->getRst(), OUTPUT);
|
||||
|
@ -336,7 +394,7 @@ int16_t SX128x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
uint8_t modem = getPacketType();
|
||||
if(modem == SX128X_PACKET_TYPE_LORA) {
|
||||
state = setPacketParamsLoRa(_preambleLengthLoRa, _headerType, len, _crcLoRa);
|
||||
} else if(modem == SX128X_PACKET_TYPE_GFSK) {
|
||||
} else if((modem == SX128X_PACKET_TYPE_GFSK) || (modem == SX128X_PACKET_TYPE_FLRC)) {
|
||||
state = setPacketParamsGFSK(_preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening, len);
|
||||
} else {
|
||||
return(ERR_WRONG_MODEM);
|
||||
|
@ -406,6 +464,11 @@ int16_t SX128x::startReceive(uint16_t timeout) {
|
|||
}
|
||||
|
||||
int16_t SX128x::readData(uint8_t* data, size_t len) {
|
||||
// check active modem
|
||||
if(getPacketType() == SX128X_PACKET_TYPE_RANGING) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -511,19 +574,29 @@ int16_t SX128x::setSpreadingFactor(uint8_t sf) {
|
|||
int16_t SX128x::setCodingRate(uint8_t cr, bool longInterleaving) {
|
||||
// check active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(!((modem == SX128X_PACKET_TYPE_LORA) || (modem == SX128X_PACKET_TYPE_RANGING))) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
|
||||
// LoRa/ranging
|
||||
if((modem == SX128X_PACKET_TYPE_LORA) || (modem == SX128X_PACKET_TYPE_RANGING)) {
|
||||
RADIOLIB_CHECK_RANGE(cr, 5, 8, ERR_INVALID_CODING_RATE);
|
||||
|
||||
// update modulation parameters
|
||||
if(longInterleaving && (modem == SX128X_PACKET_TYPE_LORA)) {
|
||||
_cr = cr;
|
||||
} else {
|
||||
_cr = cr - 4;
|
||||
}
|
||||
return(setModulationParams(_sf, _bw, _cr));
|
||||
|
||||
// FLRC
|
||||
} else if(modem == SX128X_PACKET_TYPE_FLRC) {
|
||||
RADIOLIB_CHECK_RANGE(cr, 2, 4, ERR_INVALID_CODING_RATE);
|
||||
|
||||
// update modulation parameters
|
||||
_crFLRC = (cr - 2) * 2;
|
||||
return(setModulationParams(_br, _crFLRC, _shaping));
|
||||
}
|
||||
|
||||
RADIOLIB_CHECK_RANGE(cr, 5, 8, ERR_INVALID_CODING_RATE);
|
||||
|
||||
// update modulation parameters
|
||||
if(longInterleaving && (modem == SX128X_PACKET_TYPE_LORA)) {
|
||||
_cr = cr;
|
||||
} else {
|
||||
_cr = cr - 4;
|
||||
}
|
||||
return(setModulationParams(_sf, _bw, _cr));
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
int16_t SX128x::setOutputPower(int8_t power) {
|
||||
|
@ -583,33 +656,58 @@ int16_t SX128x::setPreambleLength(uint32_t preambleLength) {
|
|||
int16_t SX128x::setBitRate(uint16_t br) {
|
||||
// check active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(!((modem == SX128X_PACKET_TYPE_GFSK) || (modem == SX128X_PACKET_TYPE_BLE))) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
|
||||
// GFSK/BLE
|
||||
if((modem == SX128X_PACKET_TYPE_GFSK) || (modem == SX128X_PACKET_TYPE_BLE)) {
|
||||
if(br == 125) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_125_BW_0_3;
|
||||
} else if(br == 250) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_250_BW_0_6;
|
||||
} else if(br == 400) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_400_BW_1_2;
|
||||
} else if(br == 500) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_500_BW_1_2;
|
||||
} else if(br == 800) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_800_BW_2_4;
|
||||
} else if(br == 1000) {
|
||||
_br = SX128X_BLE_GFSK_BR_1_000_BW_2_4;
|
||||
} else if(br == 1600) {
|
||||
_br = SX128X_BLE_GFSK_BR_1_600_BW_2_4;
|
||||
} else if(br == 2000) {
|
||||
_br = SX128X_BLE_GFSK_BR_2_000_BW_2_4;
|
||||
} else {
|
||||
return(ERR_INVALID_BIT_RATE);
|
||||
}
|
||||
|
||||
// update modulation parameters
|
||||
_brKbps = br;
|
||||
return(setModulationParams(_br, _modIndex, _shaping));
|
||||
|
||||
// FLRC
|
||||
} else if(modem == SX128X_PACKET_TYPE_FLRC) {
|
||||
if(br == 260) {
|
||||
_br = SX128X_FLRC_BR_0_260_BW_0_3;
|
||||
} else if(br == 325) {
|
||||
_br = SX128X_FLRC_BR_0_325_BW_0_3;
|
||||
} else if(br == 520) {
|
||||
_br = SX128X_FLRC_BR_0_520_BW_0_6;
|
||||
} else if(br == 650) {
|
||||
_br = SX128X_FLRC_BR_0_650_BW_0_6;
|
||||
} else if(br == 1000) {
|
||||
_br = SX128X_FLRC_BR_1_000_BW_1_2;
|
||||
} else if(br == 1300) {
|
||||
_br = SX128X_FLRC_BR_1_300_BW_1_2;
|
||||
} else {
|
||||
return(ERR_INVALID_BIT_RATE);
|
||||
}
|
||||
|
||||
// update modulation parameters
|
||||
_brKbps = br;
|
||||
return(setModulationParams(_br, _crFLRC, _shaping));
|
||||
|
||||
}
|
||||
|
||||
if(br == 125) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_125_BW_0_3;
|
||||
} else if(br == 250) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_250_BW_0_6;
|
||||
} else if(br == 400) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_400_BW_1_2;
|
||||
} else if(br == 500) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_500_BW_1_2;
|
||||
} else if(br == 800) {
|
||||
_br = SX128X_BLE_GFSK_BR_0_800_BW_2_4;
|
||||
} else if(br == 1000) {
|
||||
_br = SX128X_BLE_GFSK_BR_1_000_BW_2_4;
|
||||
} else if(br == 1600) {
|
||||
_br = SX128X_BLE_GFSK_BR_1_600_BW_2_4;
|
||||
} else if(br == 2000) {
|
||||
_br = SX128X_BLE_GFSK_BR_2_000_BW_2_4;
|
||||
} else {
|
||||
return(ERR_INVALID_BIT_RATE);
|
||||
}
|
||||
|
||||
// update modulation parameters
|
||||
_brKbps = br;
|
||||
return(setModulationParams(_br, _modIndex, _shaping));
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
int16_t SX128x::setFrequencyDeviation(float freqDev) {
|
||||
|
@ -642,7 +740,7 @@ int16_t SX128x::setFrequencyDeviation(float freqDev) {
|
|||
int16_t SX128x::setDataShaping(float dataShaping) {
|
||||
// check active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(!((modem == SX128X_PACKET_TYPE_GFSK) || (modem == SX128X_PACKET_TYPE_BLE))) {
|
||||
if(!((modem == SX128X_PACKET_TYPE_GFSK) || (modem == SX128X_PACKET_TYPE_BLE) || (modem == SX128X_PACKET_TYPE_FLRC))) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
|
@ -659,7 +757,11 @@ int16_t SX128x::setDataShaping(float dataShaping) {
|
|||
}
|
||||
|
||||
// update modulation parameters
|
||||
return(setModulationParams(_br, _modIndex, _shaping));
|
||||
if((modem == SX128X_PACKET_TYPE_GFSK) || (modem == SX128X_PACKET_TYPE_BLE)) {
|
||||
return(setModulationParams(_br, _modIndex, _shaping));
|
||||
} else {
|
||||
return(setModulationParams(_br, _crFLRC, _shaping));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t SX128x::setSyncWord(uint8_t* syncWord, uint8_t len) {
|
||||
|
@ -669,8 +771,25 @@ int16_t SX128x::setSyncWord(uint8_t* syncWord, uint8_t len) {
|
|||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
if(len > 5) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
if(modem == SX128X_PACKET_TYPE_GFSK) {
|
||||
// GFSK can use up to 5 bytes as sync word
|
||||
if(len > 5) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
// calculate sync word length parameter value
|
||||
if(len > 0) {
|
||||
_syncWordLen = (len - 1)*2;
|
||||
}
|
||||
|
||||
} else {
|
||||
// FLRC requires 32-bit sync word
|
||||
if(!((len == 0) || (len == 4))) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
// save sync word length parameter value
|
||||
_syncWordLen = len;
|
||||
}
|
||||
|
||||
// reverse sync word byte order
|
||||
|
@ -684,7 +803,6 @@ int16_t SX128x::setSyncWord(uint8_t* syncWord, uint8_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update packet parameters
|
||||
_syncWordLen = len;
|
||||
if(_syncWordLen == 0) {
|
||||
_syncWordMatch = SX128X_GFSK_FLRC_SYNC_WORD_OFF;
|
||||
} else {
|
||||
|
|
|
@ -384,6 +384,25 @@ class SX128x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t beginGFSK(float freq = 2400.0, uint16_t br = 800, float freqDev = 400.0, int8_t power = 10, uint16_t preambleLength = 16, float dataShaping = 0.5);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FLRC modem.
|
||||
|
||||
\param freq Carrier frequency in MHz. Defaults to 2400.0 MHz.
|
||||
|
||||
\param br FLRC bit rate in kbps. Defaults to 650 kbps.
|
||||
|
||||
\param cr FLRC coding rate. Defaults to 3 (coding rate 3/4).
|
||||
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
|
||||
\parma preambleLength FLRC preamble length in bits. Defaults to 16 bits.
|
||||
|
||||
\param dataShaping Time-bandwidth product of the Gaussian filter to be used for shaping. Defaults to 0.5.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginFLRC(float freq = 2400.0, uint16_t br = 650, uint8_t cr = 3, int8_t power = 10, uint16_t preambleLength = 16, float dataShaping = 0.5);
|
||||
|
||||
/*!
|
||||
\brief Reset method. Will reset the chip to the default state using RST pin.
|
||||
|
||||
|
@ -576,9 +595,9 @@ class SX128x: public PhysicalLayer {
|
|||
int16_t setPreambleLength(uint32_t preambleLength);
|
||||
|
||||
/*!
|
||||
\brief Sets FSK bit rate. Allowed values are 125, 250, 400, 500, 800, 1000, 1600 and 2000 kbps.
|
||||
\brief Sets FSK or FLRC bit rate. Allowed values are 125, 250, 400, 500, 800, 1000, 1600 and 2000 kbps (for FSK modem) or 260, 325, 520, 650, 1000 and 1300 (for FLRC modem).
|
||||
|
||||
\param br FSK bit rate to be set in kbps.
|
||||
\param br FSK/FLRC bit rate to be set in kbps.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
|
@ -603,7 +622,7 @@ class SX128x: public PhysicalLayer {
|
|||
int16_t setDataShaping(float dataShaping);
|
||||
|
||||
/*!
|
||||
\brief Sets sync word in the form of array of up to 8 bytes.
|
||||
\brief Sets FSK/FLRC sync word in the form of array of up to 5 bytes (FSK). For FLRC modem, the sync word must be exactly 4 bytes long
|
||||
|
||||
\param syncWord Sync word to be set.
|
||||
|
||||
|
@ -737,6 +756,9 @@ class SX128x: public PhysicalLayer {
|
|||
uint8_t _br, _modIndex, _shaping;
|
||||
uint8_t _preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening;
|
||||
|
||||
// cached FLRC parameters
|
||||
uint8_t _crFLRC;
|
||||
|
||||
// cached BLE parameters
|
||||
uint8_t _connectionState, _crcBLE, _bleTestPayload;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue