diff --git a/src/modules/LR2021/LR2021.cpp b/src/modules/LR2021/LR2021.cpp index e8b1c530..b72443a2 100644 --- a/src/modules/LR2021/LR2021.cpp +++ b/src/modules/LR2021/LR2021.cpp @@ -21,6 +21,27 @@ LR2021::LR2021(Module* mod) : PhysicalLayer() { this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_LR2021_IRQ_TIMEOUT; } +int16_t LR2021::sleep() { + return(this->sleep(RADIOLIB_LR2021_SLEEP_RETENTION_ENABLED, 0)); +} + +int16_t LR2021::sleep(uint8_t cfg, uint32_t time) { + // set RF switch (if present) + this->mod->setRfSwitchState(Module::MODE_IDLE); + + uint8_t buff[] = { cfg, + (uint8_t)((time >> 24) & 0xFF), (uint8_t)((time >> 16) & 0xFF), + (uint8_t)((time >> 8) & 0xFF), (uint8_t)(time & 0xFF), + }; + + int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_SET_SLEEP, true, buff, sizeof(buff)); + + // wait for the module to safely enter sleep mode + this->mod->hal->delay(1); + + return(state); +} + Module* LR2021::getMod() { return(this->mod); } diff --git a/src/modules/LR2021/LR2021.h b/src/modules/LR2021/LR2021.h index 8cd2dede..20e9d776 100644 --- a/src/modules/LR2021/LR2021.h +++ b/src/modules/LR2021/LR2021.h @@ -187,6 +187,16 @@ #define RADIOLIB_LR2021_IRQ_RNG_EXCH_VALID (0x01UL << 30) // 31 0 master receive valid ranging response #define RADIOLIB_LR2021_IRQ_RNG_TIMEOUT (0x01UL << 31) // 31 0 ranging timeout +// RADIOLIB_LR2021_CMD_WRITE_REG_MEM +#define RADIOLIB_LR2021_SPI_MAX_READ_WRITE_LEN (256) // 7 0 maximum length of read/write SPI payload in bytes + +// RADIOLIB_LR2021_CMD_SET_SLEEP +#define RADIOLIB_LR2021_SLEEP_32K_CLK_DISABLED (0x00UL << 0) // 0 0 32 kHz clock: disabled +#define RADIOLIB_LR2021_SLEEP_32K_CLK_ENABLED (0x01UL << 0) // 0 0 enabled +#define RADIOLIB_LR2021_SLEEP_RETENTION_DISABLED (0x00UL << 1) // 1 1 configuration retention in sleep mode: disabled +#define RADIOLIB_LR2021_SLEEP_RETENTION_ENABLED (0x01UL << 1) // 1 1 enabled + + /*! \class LR2021 \brief @@ -206,6 +216,9 @@ class LR2021: public PhysicalLayer { */ explicit LR2021(Module* mod); + int16_t sleep(); + int16_t sleep(uint8_t cfg, uint32_t time); + #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL protected: #endif @@ -223,6 +236,13 @@ class LR2021: public PhysicalLayer { static int16_t SPIparseStatus(uint8_t in); static int16_t SPIcheckStatus(Module* mod); + + int16_t readRadioRxFifo(uint8_t* data, size_t len); + int16_t writeRadioTxFifo(uint8_t* data, size_t len); + int16_t writeRegMem32(uint32_t addr, const uint32_t* data, size_t len); + int16_t writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data); + int16_t readRegMem32(uint32_t addr, uint32_t* data, size_t len); + }; #endif diff --git a/src/modules/LR2021/LR2021_commands.cpp b/src/modules/LR2021/LR2021_commands.cpp index e11aa494..599d2da6 100644 --- a/src/modules/LR2021/LR2021_commands.cpp +++ b/src/modules/LR2021/LR2021_commands.cpp @@ -1,10 +1,74 @@ #include "LR2021.h" +#include "../LR11x0/LR_common.h" + #include #include #if !RADIOLIB_EXCLUDE_LR2021 +int16_t LR2021::readRadioRxFifo(uint8_t* data, size_t len) { + return(this->SPIcommand(RADIOLIB_LR2021_CMD_READ_RX_FIFO, false, data, len, NULL, 0)); +} +int16_t LR2021::writeRadioTxFifo(uint8_t* data, size_t len) { + return(this->SPIcommand(RADIOLIB_LR2021_CMD_WRITE_TX_FIFO, true, data, len, NULL, 0)); +} +// TODO reuse LR11x0 method +int16_t LR2021::writeRegMem32(uint32_t addr, const uint32_t* data, size_t len) { + // check maximum size + if(len > (RADIOLIB_LR2021_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) { + return(RADIOLIB_ERR_SPI_CMD_INVALID); + } + return(LR_writeCommon(this->mod, RADIOLIB_LR2021_CMD_WRITE_REG_MEM_32, addr, data, len, false)); +} + +// TODO reuse LR11x0 method +int16_t LR2021::writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data) { + uint8_t buff[12] = { + (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF), + (uint8_t)((mask >> 24) & 0xFF), (uint8_t)((mask >> 16) & 0xFF), (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF), + (uint8_t)((data >> 24) & 0xFF), (uint8_t)((data >> 16) & 0xFF), (uint8_t)((data >> 8) & 0xFF), (uint8_t)(data & 0xFF), + }; + return(this->SPIcommand(RADIOLIB_LR2021_CMD_WRITE_REG_MEM_MASK_32, true, buff, sizeof(buff))); +} + +// TODO reuse LR11x0 method +int16_t LR2021::readRegMem32(uint32_t addr, uint32_t* data, size_t len) { + // check maximum size + if(len >= (RADIOLIB_LR2021_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) { + return(RADIOLIB_ERR_SPI_CMD_INVALID); + } + + // the request contains the address and length + uint8_t reqBuff[5] = { + (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), + (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF), + (uint8_t)len, + }; + + // build buffers - later we need to ensure endians are correct, + // so there is probably no way to do this without copying buffers and iterating + #if RADIOLIB_STATIC_ONLY + uint8_t rplBuff[RADIOLIB_LR2021_SPI_MAX_READ_WRITE_LEN]; + #else + uint8_t* rplBuff = new uint8_t[len*sizeof(uint32_t)]; + #endif + + int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_READ_REG_MEM_32, false, rplBuff, len*sizeof(uint32_t), reqBuff, sizeof(reqBuff)); + + // convert endians + if(data && (state == RADIOLIB_ERR_NONE)) { + for(size_t i = 0; i < len; i++) { + data[i] = ((uint32_t)rplBuff[2 + i*sizeof(uint32_t)] << 24) | ((uint32_t)rplBuff[3 + i*sizeof(uint32_t)] << 16) | ((uint32_t)rplBuff[4 + i*sizeof(uint32_t)] << 8) | (uint32_t)rplBuff[5 + i*sizeof(uint32_t)]; + } + } + + #if !RADIOLIB_STATIC_ONLY + delete[] rplBuff; + #endif + + return(state); +} #endif