kopia lustrzana https://github.com/jgromes/RadioLib
Merge pull request #84 from BarryPSmith/receiveDutyCycle
Added sx126x receive duty cycle interfacepull/88/head
commit
104c656860
|
@ -115,6 +115,8 @@ setDio2AsRfSwitch KEYWORD2
|
|||
getTimeOnAir KEYWORD2
|
||||
setSyncBits KEYWORD2
|
||||
setWhitening KEYWORD2
|
||||
startReceiveDutyCycle KEYWORD2
|
||||
startReceiveDutyCycleAuto KEYWORD2
|
||||
|
||||
# ESP8266
|
||||
join KEYWORD2
|
||||
|
@ -246,3 +248,5 @@ ERR_INVALID_MODULATION_PARAMETERS LITERAL1
|
|||
ERR_SPI_CMD_TIMEOUT LITERAL1
|
||||
ERR_SPI_CMD_INVALID LITERAL1
|
||||
ERR_SPI_CMD_FAILED LITERAL1
|
||||
ERR_INVALID_SLEEP_PERIOD LITERAL1
|
||||
ERR_INVALID_RX_PERIOD LITERAL1
|
||||
|
|
|
@ -524,6 +524,21 @@
|
|||
*/
|
||||
#define ERR_SPI_CMD_FAILED -707
|
||||
|
||||
/*!
|
||||
\brief The supplied sleep period is invalid.
|
||||
|
||||
The specified sleep period is shorter than the time necessary to sleep and wake the hardware
|
||||
including TCXO delay, or longer than the maximum possible
|
||||
*/
|
||||
#define ERR_INVALID_SLEEP_PERIOD -708
|
||||
|
||||
/*!
|
||||
\brief The supplied Rx period is invalid.
|
||||
|
||||
The specified Rx period is shorter or longer than the hardware can handle.
|
||||
*/
|
||||
#define ERR_INVALID_RX_PERIOD -709
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@ int16_t SX126x::begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, float
|
|||
_ldro = 0x00;
|
||||
_crcType = SX126X_LORA_CRC_ON;
|
||||
_preambleLength = preambleLength;
|
||||
_tcxoDelay = 0;
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
|
@ -443,6 +444,87 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
int16_t SX126x::startReceive(uint32_t timeout) {
|
||||
int16_t state = startReceiveCommon();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set mode to receive
|
||||
state = setRx(timeout);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod) {
|
||||
// datasheet claims time to go to sleep is ~500us, same to wake up, compensate for that with 1 ms + TCXO delay
|
||||
uint32_t transitionTime = _tcxoDelay + 1000;
|
||||
sleepPeriod -= transitionTime;
|
||||
|
||||
// divide by 15.625
|
||||
uint32_t rxPeriodRaw = (rxPeriod * 8) / 125;
|
||||
uint32_t sleepPeriodRaw = (sleepPeriod * 8) / 125;
|
||||
|
||||
// check 24 bit limit and zero value (likely not intended)
|
||||
if((rxPeriodRaw & 0xFF000000) || (rxPeriodRaw == 0)) {
|
||||
return(ERR_INVALID_RX_PERIOD);
|
||||
}
|
||||
|
||||
// this check of the high byte also catches underflow when we subtracted transitionTime
|
||||
if((sleepPeriodRaw & 0xFF000000) || (sleepPeriodRaw == 0)) {
|
||||
return(ERR_INVALID_SLEEP_PERIOD);
|
||||
}
|
||||
|
||||
int16_t state = startReceiveCommon();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
uint8_t data[6] = {(rxPeriodRaw >> 16) & 0xFF, (rxPeriodRaw >> 8) & 0xFF, rxPeriodRaw & 0xFF,
|
||||
(sleepPeriodRaw >> 16) & 0xFF, (sleepPeriodRaw >> 8) & 0xFF, sleepPeriodRaw & 0xFF};
|
||||
return(SPIwriteCommand(SX126X_CMD_SET_RX_DUTY_CYCLE, data, 6));
|
||||
}
|
||||
|
||||
int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_t minSymbols) {
|
||||
if(senderPreambleLength == 0) {
|
||||
senderPreambleLength = _preambleLength;
|
||||
}
|
||||
|
||||
// worst case is that the sender starts transmiting when we're just less than minSymbols from going back to sleep.
|
||||
// in this case, we don't catch minSymbols before going to sleep,
|
||||
// so we must be awake for at least that long before the sender stops transmitting.
|
||||
uint16_t sleepSymbols = senderPreambleLength - 2 * minSymbols;
|
||||
|
||||
// if we're not to sleep at all, just use the standard startReceive.
|
||||
if(2 * minSymbols > senderPreambleLength) {
|
||||
return(startReceive());
|
||||
}
|
||||
|
||||
uint32_t symbolLength = ((uint32_t)(10 * 1000) << _sf) / (10 * _bwKhz);
|
||||
uint32_t sleepPeriod = symbolLength * sleepSymbols;
|
||||
RADIOLIB_DEBUG_PRINT(F("Auto sleep period: "));
|
||||
RADIOLIB_DEBUG_PRINTLN(sleepPeriod);
|
||||
|
||||
// when the unit detects a preamble, it starts a timer that will timeout if it doesn't receive a header in time.
|
||||
// the duration is sleepPeriod + 2 * wakePeriod.
|
||||
// The sleepPeriod doesn't take into account shutdown and startup time for the unit (~1ms)
|
||||
// We need to ensure that the timout is longer than senderPreambleLength.
|
||||
// So we must satisfy: wakePeriod > (preamblePeriod - (sleepPeriod - 1000)) / 2. (A)
|
||||
// we also need to ensure the unit is awake to see at least minSymbols. (B)
|
||||
uint32_t wakePeriod = max(
|
||||
(symbolLength * (senderPreambleLength + 1) - (sleepPeriod - 1000)) / 2, // (A)
|
||||
symbolLength * (minSymbols + 1)); //(B)
|
||||
RADIOLIB_DEBUG_PRINT(F("Auto wake period: "));
|
||||
RADIOLIB_DEBUG_PRINTLN(wakePeriod);
|
||||
|
||||
//If our sleep period is shorter than our transition time, just use the standard startReceive
|
||||
if(sleepPeriod < _tcxoDelay + 1016) {
|
||||
return(startReceive());
|
||||
}
|
||||
|
||||
return(startReceiveDutyCycle(wakePeriod, sleepPeriod));
|
||||
}
|
||||
|
||||
int16_t SX126x::startReceiveCommon() {
|
||||
// set DIO mapping
|
||||
int16_t state = setDioIrqParams(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR | SX126X_IRQ_HEADER_ERR, SX126X_IRQ_RX_DONE);
|
||||
if(state != ERR_NONE) {
|
||||
|
@ -457,12 +539,6 @@ int16_t SX126x::startReceive(uint32_t timeout) {
|
|||
|
||||
// clear interrupt flags
|
||||
state = clearIrqStatus();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set mode to receive
|
||||
state = setRx(timeout);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -1072,6 +1148,8 @@ int16_t SX126x::setTCXO(float voltage, uint32_t delay) {
|
|||
data[2] = (uint8_t)((delayValue >> 8) & 0xFF);
|
||||
data[3] = (uint8_t)(delayValue & 0xFF);
|
||||
|
||||
_tcxoDelay = delay;
|
||||
|
||||
// enable TCXO control on DIO3
|
||||
return(SPIwriteCommand(SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, data, 4));
|
||||
}
|
||||
|
|
|
@ -499,6 +499,31 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t startReceive(uint32_t timeout = SX126X_RX_TIMEOUT_INF);
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method where the device mostly sleeps and periodically wakes to listen.
|
||||
Note that this function assumes the unit will take 500us + TCXO_delay to change state. See datasheet section 13.1.7, version 1.2.
|
||||
|
||||
\param rxPeriod The duration the receiver will be in Rx mode, in microseconds.
|
||||
|
||||
\param sleepPeriod The duration the receiver will not be in Rx mode, in microseconds.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod);
|
||||
|
||||
/*!
|
||||
\brief Calls \ref startReceiveDutyCycle with rxPeriod and sleepPeriod set so the unit shouldn't miss any messages.
|
||||
|
||||
\param senderPreambleLength Expected preamble length of the messages to receive.
|
||||
If set to zero, the currently configured preamble length will be used. Defaults to zero.
|
||||
|
||||
\param minSymbols Parameters will be chosen to ensure that the unit will catch at least this many symbols of any preamble of the specified length. Defaults to 8.
|
||||
According to Semtech, receiver requires 8 symbols to reliably latch a preamble. This makes this method redundant when transmitter preamble length is less than 17 (2*minSymbols + 1).
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceiveDutyCycleAuto(uint16_t senderPreambleLength = 0, uint16_t minSymbols = 8);
|
||||
|
||||
/*!
|
||||
\brief Reads data received after calling startReceive method.
|
||||
|
||||
|
@ -747,7 +772,6 @@ class SX126x: public PhysicalLayer {
|
|||
\returns Expected time-on-air in microseconds.
|
||||
*/
|
||||
uint32_t getTimeOnAir(size_t len);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
|
@ -777,6 +801,7 @@ class SX126x: public PhysicalLayer {
|
|||
uint16_t getDeviceErrors();
|
||||
int16_t clearDeviceErrors();
|
||||
|
||||
int16_t startReceiveCommon();
|
||||
int16_t setFrequencyRaw(float freq);
|
||||
int16_t setOptimalHiPowerPaConfig(int8_t* inOutPower);
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
@ -803,6 +828,8 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
float _dataRate;
|
||||
|
||||
uint32_t _tcxoDelay;
|
||||
|
||||
int16_t config(uint8_t modem);
|
||||
|
||||
// common low-level SPI interface
|
||||
|
|
Ładowanie…
Reference in New Issue