Initial work on full-length FSK messages based on ISR callbacks.

Untested, but it does compile.
This commit is contained in:
Justin Stephens 2021-12-08 11:02:33 -05:00
parent e2d7f41347
commit 7dedc57b4c
4 changed files with 224 additions and 4 deletions

View file

@ -0,0 +1,83 @@
/*
RadioLib SX127x FSK FIFO on-the-fly Refilling Example
This example shows how to use refill the FIFO buffer in SX127x chips, to allow for transmitting
FSK/OOK packets longer than 256 bytes.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx127xrfm9x---fsk-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1276 has the following connections:
// NSS pin: 8
// DIO0 pin: 51
// RESET pin: 22
// DIO1 pin: 52
SX1276 radio = new Module(8, 51, 22, 52);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 fsk = RadioShield.ModuleA;
uint8_t syncWord[] = { 0x91, 0xD3, 0x91, 0xD3 };
char* msg = "This is just some message that extends well beyond the 64 bytes limit of the FIFO";
size_t msg_length;
size_t msg_counter;
// this interrupt is called whenever the FIFO buffer falls below a certain threshold
void fifoRefill() {
msg_counter += radio.fifoAppend(
(uint8_t*)msg + msg_counter, // start of message, offset by # of bytes already sent
msg_length - msg_counter // # of bytes left to send
);
}
void setup() {
Serial.begin(9600);
// RF switch for my board
pinMode(47, OUTPUT);
// initialize SX1278 FSK modem with default settings
Serial.print(F("[SX1276] Initializing ... "));
int state = radio.beginFSK();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// Set config options
radio.setDataShaping(RADIOLIB_SHAPING_NONE);
radio.setSyncWord(syncWord, sizeof(syncWord));
radio.setEncoding(RADIOLIB_ENCODING_WHITENING);
radio.setCRC(true);
// Set up FIFO operations
radio.setFifoThreshold(16);
radio.setFifoThresholdAction(fifoRefill);
}
void loop() {
radio.variablePacketLengthMode();
// set RF switch to TX mode
digitalWrite(47, LOW);
// start transmission of message
msg_length = strlen(msg);
radio.startTransmit((uint8_t*)msg, msg_length, msg_counter);
while (msg_counter != msg_length);
Serial.println("[SX1276] Done transmitting");
}

View file

@ -446,6 +446,19 @@ void SX127x::clearDio1Action() {
}
int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
// if in FSK/OOK mode and trying to send a packet larger than can fit in the
// FIFO, error out. For packets larger than FIFO, the startTransmit overload
// with a counter outparam must be used.
if (getActiveModem() == SX127X_FSK_OOK && len >= SX127X_FIFO_CAPACITY) {
return ERR_PACKET_TOO_LONG;
}
// call the "full" startTransmit overload
return startTransmit(data, len, 0, addr);
}
int16_t SX127x::startTransmit(uint8_t* data, size_t len, size_t&& counter, uint8_t addr) {
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
@ -472,12 +485,28 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_TX_BASE_ADDR, SX127X_FIFO_TX_BASE_ADDR_MAX);
state |= _mod->SPIsetRegValue(SX127X_REG_FIFO_ADDR_PTR, SX127X_FIFO_TX_BASE_ADDR_MAX);
// set the counter to the length written to FIFO
counter = len;
// write packet to FIFO
_mod->SPIwriteRegisterBurst(SX127X_REG_FIFO, data, len);
} else if(modem == SX127X_FSK_OOK) {
// check packet length
if(len >= SX127X_MAX_PACKET_LENGTH_FSK) {
return(ERR_PACKET_TOO_LONG);
}
// if packet is too large to fit in the FIFO at once, attach the fifo-refill ISR to DIO1. If no
// ISR has been defined by the user, error out.
else if (len >= SX127X_FIFO_CAPACITY) {
if (_fifoThresholdISR == NULL) {
return ERR_PACKET_TOO_LONG;
} else {
Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getGpio()), _fifoThresholdISR, RISING);
}
}
// set DIO mapping
_mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_PACK_PACKET_SENT, 7, 6);
@ -494,10 +523,13 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
if((filter == SX127X_ADDRESS_FILTERING_NODE) || (filter == SX127X_ADDRESS_FILTERING_NODE_BROADCAST)) {
_mod->SPIwriteRegister(SX127X_REG_FIFO, addr);
}
}
// write packet to FIFO
_mod->SPIwriteRegisterBurst(SX127X_REG_FIFO, data, len);
// set the byte counter to the length to be written to FIFO
counter = min(len, SX127X_FIFO_CAPACITY - 1);
// write packet to FIFO
_mod->SPIwriteRegisterBurst(SX127X_REG_FIFO, data, counter);
}
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
@ -509,6 +541,41 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
return(ERR_NONE);
}
void SX127x::setFifoThresholdAction(void (*func)(void)) {
_fifoThresholdISR = func;
}
int SX127x::fifoAppend(uint8_t* buff, size_t remaining) {
// check modem
if (getActiveModem() != SX127X_FSK_OOK) {
return ERR_WRONG_MODEM;
}
// figure out how much to write
uint8_t fifoThresh = _mod->SPIreadRegister(SX127X_FIFO_THRESH) & 0x3F;
uint8_t toWrite = min(remaining, SX127X_FIFO_CAPACITY - fifoThresh);
// write to the register
_mod->SPIwriteRegisterBurst(SX127X_REG_FIFO, buff, toWrite);
return toWrite;
}
int SX127x::fifoGet(uint8_t* buff, size_t available) {
// check modem
if (getActiveModem() != SX127X_FSK_OOK) {
return ERR_WRONG_MODEM;
}
// figure out how many bytes to read in
uint8_t fifoThresh = _mod->SPIreadRegister(SX127X_FIFO_THRESH) & 0x3F;
uint8_t toRead = min(available, fifoThresh);
// write to the register
_mod->SPIreadRegisterBurst(SX127X_REG_FIFO, toRead, buff);
return toRead;
}
int16_t SX127x::readData(uint8_t* data, size_t len) {
int16_t modem = getActiveModem();
size_t length = len;
@ -1003,6 +1070,18 @@ int16_t SX127x::variablePacketLengthMode(uint8_t maxLen) {
return(SX127x::setPacketMode(SX127X_PACKET_VARIABLE, maxLen));
}
int16_t SX127x::setFifoThreshold(uint8_t cap) {
// check active modem
if (getActiveModem() != SX127X_FSK_OOK) {
return ERR_WRONG_MODEM;
} else if (cap > 63) {
return ERR_PACKET_TOO_LONG;
}
// write the 6 LSbits to the register
return _mod->SPIsetRegValue(SX127X_REG_FIFO_THRESH, cap & 0x3F);
}
int16_t SX127x::setRSSIConfig(uint8_t smoothingSamples, int8_t offset) {
// check active modem
if(getActiveModem() != SX127X_FSK_OOK) {

View file

@ -12,7 +12,8 @@
// SX127x physical layer properties
#define SX127X_FREQUENCY_STEP_SIZE 61.03515625
#define SX127X_MAX_PACKET_LENGTH 255
#define SX127X_MAX_PACKET_LENGTH_FSK 64
#define SX127X_MAX_PACKET_LENGTH_FSK 255
#define SX127X_FIFO_CAPACITY 64
#define SX127X_CRYSTAL_FREQ 32.0
#define SX127X_DIV_EXPONENT 19
@ -712,6 +713,16 @@ class SX127x: public PhysicalLayer {
*/
int16_t startTransmit(uint8_t* data, size_t len, uint8_t addr = 0) override;
/*!
\brief Interrupt-driven binary transmit method. Will start transmitting arbitrary binary data up to 255 bytes long using %LoRa or up to 255 bytes using FSK modem.
\param data Binary data that will be transmitted.
\param len Length of binary data to transmit (in bytes).
\param[out] counter Reference to a variable to track the number of sent bytes in
\param addr Node address to transmit the packet to. Only used in FSK mode.
\returns \ref status_codes
*/
int16_t startTransmit(uint8_t* data, size_t len, size_t&& counter, uint8_t addr = 0) override;
/*!
\brief Interrupt-driven receive method. DIO0 will be activated when full valid packet is received.
@ -947,6 +958,15 @@ class SX127x: public PhysicalLayer {
*/
int16_t variablePacketLengthMode(uint8_t maxLen = SX127X_MAX_PACKET_LENGTH_FSK);
/*!
\brief Set the level at which the FIFO Threshold interrupt triggers
\param cap A capacity 0-63 for the FIFO buffer.
*/
int16_t setFifoThreshold(uint8_t cap = 16);
void setFifoThresholdAction(void (*func)(void)) override;
int fifoAppend(uint8_t* buff, size_t remaining) override;
int fifoGet(uint8_t* buff, size_t remaining) override;
/*!
\brief Sets RSSI measurement configuration in FSK mode.
@ -1071,6 +1091,7 @@ class SX127x: public PhysicalLayer {
float _dataRate = 0;
bool _packetLengthQueried = false; // FSK packet length is the first byte in FIFO, length can only be queried once
uint8_t _packetLengthConfig = SX127X_PACKET_VARIABLE;
void (*_fifoThresholdISR)(void) = NULL;
bool findChip(uint8_t ver);
int16_t setMode(uint8_t mode);

View file

@ -139,6 +139,43 @@ class PhysicalLayer {
*/
virtual int16_t startTransmit(uint8_t* data, size_t len, uint8_t addr = 0) = 0;
/*!
\brief Interrupt-driven binary transmit method.
\param data Binary data that will be transmitted.
\param len Length of binary data to transmit (in bytes).
\param[out] counter Reference to a variable to track the number of bytes sent in.
\param addr Node address to transmit the packet to. Only used in FSK mode.
*/
virtual int16_t startTransmit(uint8_t* data, size_t len, size_t&& counter, uint8_t add = 0) = 0;
/*!
\brief Set the ISR routine to execute when the FIFO falls below the threshold.
This interrupt will only be called when transmitting a message larger than the FIFO capacity.
\param func Pointer to an Interrupt Service Routine. `NULL` will clear action.
*/
virtual void setFifoThresholdAction(void (*func)(void)) = 0;
/*!
\brief Append more data into the FIFO Buffer
This is used for stream-based transmissions.
\param buff A pointer to the start of the data to append
\param remaining A pointer to a counter variable
\return Number of bytes consumed from `buff`, or error code.
*/
virtual int16_t fifoAppend(uint8_t* buff, size_t remaining) = 0;
/*!
\brief Read data from the FIFO buffer.
\param buff the buffer to read data into
\param available the maximum number of bytes available in `buff`
\return Number of bytes read in from FIFO, or error code.
*/
virtual int16_t fifoGet(uint8_t* buff, size_t available) = 0;
/*!
\brief Reads data that was received after calling startReceive method.