[MOD] Added stream SPI transfer
This commit is contained in:
parent
455ce12eed
commit
e07d1d9dc1
2 changed files with 166 additions and 0 deletions
126
src/Module.cpp
126
src/Module.cpp
|
@ -253,6 +253,132 @@ void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* da
|
||||||
this->SPIendTransaction();
|
this->SPIendTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForGpio, uint32_t timeout) {
|
||||||
|
#if defined(RADIOLIB_VERBOSE)
|
||||||
|
uint8_t debugBuff[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// pull NSS low
|
||||||
|
this->digitalWrite(this->getCs(), LOW);
|
||||||
|
|
||||||
|
// ensure GPIO is low
|
||||||
|
uint32_t start = this->millis();
|
||||||
|
while(this->digitalRead(this->getGpio())) {
|
||||||
|
this->yield();
|
||||||
|
if(this->millis() - start >= timeout) {
|
||||||
|
this->digitalWrite(this->getCs(), HIGH);
|
||||||
|
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start transfer
|
||||||
|
this->SPIbeginTransaction();
|
||||||
|
|
||||||
|
// send command byte(s)
|
||||||
|
for(uint8_t n = 0; n < cmdLen; n++) {
|
||||||
|
this->SPItransfer(cmd[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// variable to save error during SPI transfer
|
||||||
|
int16_t state = RADIOLIB_ERR_NONE;
|
||||||
|
|
||||||
|
// send/receive all bytes
|
||||||
|
if(write) {
|
||||||
|
for(uint8_t n = 0; n < numBytes; n++) {
|
||||||
|
// send byte
|
||||||
|
uint8_t in = this->SPItransfer(dataOut[n]);
|
||||||
|
#if defined(RADIOLIB_VERBOSE)
|
||||||
|
debugBuff[n] = in;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check status
|
||||||
|
if(this->SPIparseStatusCb != nullptr) {
|
||||||
|
state = this->SPIparseStatusCb(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// skip the first byte for read-type commands (status-only)
|
||||||
|
uint8_t in = this->SPItransfer(this->SPIreadCommand);
|
||||||
|
#if defined(RADIOLIB_VERBOSE)
|
||||||
|
debugBuff[0] = in;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check status
|
||||||
|
if(this->SPIparseStatusCb != nullptr) {
|
||||||
|
state = this->SPIparseStatusCb(in);
|
||||||
|
} else {
|
||||||
|
state = RADIOLIB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the data
|
||||||
|
if(state == RADIOLIB_ERR_NONE) {
|
||||||
|
for(uint8_t n = 0; n < numBytes; n++) {
|
||||||
|
dataIn[n] = this->SPItransfer(this->SPIreadCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop transfer
|
||||||
|
this->SPIendTransaction();
|
||||||
|
this->digitalWrite(this->getCs(), HIGH);
|
||||||
|
|
||||||
|
// wait for GPIO to go high and then low
|
||||||
|
if(waitForGpio) {
|
||||||
|
this->delayMicroseconds(1);
|
||||||
|
uint32_t start = this->millis();
|
||||||
|
while(this->digitalRead(this->getGpio())) {
|
||||||
|
this->yield();
|
||||||
|
if(this->millis() - start >= timeout) {
|
||||||
|
state = RADIOLIB_ERR_SPI_CMD_TIMEOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print debug output
|
||||||
|
#if defined(RADIOLIB_VERBOSE)
|
||||||
|
// print command byte(s)
|
||||||
|
RADIOLIB_VERBOSE_PRINT("CMD\t");
|
||||||
|
for(uint8_t n = 0; n < cmdLen; n++) {
|
||||||
|
RADIOLIB_VERBOSE_PRINT(cmd[n], HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t');
|
||||||
|
}
|
||||||
|
RADIOLIB_VERBOSE_PRINTLN();
|
||||||
|
|
||||||
|
// print data bytes
|
||||||
|
RADIOLIB_VERBOSE_PRINT("DAT");
|
||||||
|
if(write) {
|
||||||
|
RADIOLIB_VERBOSE_PRINT("W\t");
|
||||||
|
for(uint8_t n = 0; n < numBytes; n++) {
|
||||||
|
RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t');
|
||||||
|
RADIOLIB_VERBOSE_PRINT(debugBuff[n], HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t');
|
||||||
|
}
|
||||||
|
RADIOLIB_VERBOSE_PRINTLN();
|
||||||
|
} else {
|
||||||
|
RADIOLIB_VERBOSE_PRINT("R\t");
|
||||||
|
// skip the first byte for read-type commands (status-only)
|
||||||
|
RADIOLIB_VERBOSE_PRINT(this->SPIreadCommand, HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t');
|
||||||
|
RADIOLIB_VERBOSE_PRINT(debugBuff[0], HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t')
|
||||||
|
|
||||||
|
for(uint8_t n = 0; n < numBytes; n++) {
|
||||||
|
RADIOLIB_VERBOSE_PRINT(this->SPIreadCommand, HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t');
|
||||||
|
RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
|
||||||
|
RADIOLIB_VERBOSE_PRINT('\t');
|
||||||
|
}
|
||||||
|
RADIOLIB_VERBOSE_PRINTLN();
|
||||||
|
}
|
||||||
|
RADIOLIB_VERBOSE_PRINTLN();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return(state);
|
||||||
|
}
|
||||||
|
|
||||||
void Module::waitForMicroseconds(uint32_t start, uint32_t len) {
|
void Module::waitForMicroseconds(uint32_t start, uint32_t len) {
|
||||||
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
||||||
(void)start;
|
(void)start;
|
||||||
|
|
40
src/Module.h
40
src/Module.h
|
@ -139,6 +139,23 @@ class Module {
|
||||||
*/
|
*/
|
||||||
uint8_t SPIwriteCommand = 0b10000000;
|
uint8_t SPIwriteCommand = 0b10000000;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Whether the SPI interface is stream-type (e.g. SX126x) or register-type (e.g. SX127x).
|
||||||
|
Defaults to register-type SPI interfaces.
|
||||||
|
*/
|
||||||
|
bool SPIstreamType = false;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief SPI status parsing callback typedef.
|
||||||
|
*/
|
||||||
|
typedef int16_t (*SPIparseStatusCb_t)(uint8_t in);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Callback to function that will parse the module-specific status codes to RadioLib status codes.
|
||||||
|
Typically used for modules with SPI stream-type interface (e.g. SX126x/SX128x).
|
||||||
|
*/
|
||||||
|
SPIparseStatusCb_t SPIparseStatusCb = nullptr;
|
||||||
|
|
||||||
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -259,6 +276,29 @@ class Module {
|
||||||
*/
|
*/
|
||||||
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes);
|
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief SPI single transfer method for modules with stream-type SPI interface (SX126x, SX128x etc.).
|
||||||
|
|
||||||
|
\param cmd SPI operation command.
|
||||||
|
|
||||||
|
\param cmd SPI command length in bytes.
|
||||||
|
|
||||||
|
\param write Set to true for write commands, false for read commands.
|
||||||
|
|
||||||
|
\param dataOut Data that will be transfered from master to slave.
|
||||||
|
|
||||||
|
\param dataIn Data that was transfered from slave to master.
|
||||||
|
|
||||||
|
\param numBytes Number of bytes to transfer.
|
||||||
|
|
||||||
|
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||||
|
|
||||||
|
\param timeout GPIO wait period timeout in milliseconds.
|
||||||
|
|
||||||
|
\returns \ref status_codes
|
||||||
|
*/
|
||||||
|
int16_t SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForGpio, uint32_t timeout);
|
||||||
|
|
||||||
// pin number access methods
|
// pin number access methods
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
Loading…
Add table
Reference in a new issue