[MOD] Added stream SPI transfer

pull/684/head
jgromes 2023-02-19 12:32:17 +01:00
rodzic 455ce12eed
commit e07d1d9dc1
2 zmienionych plików z 166 dodań i 0 usunięć

Wyświetl plik

@ -253,6 +253,132 @@ void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* da
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) {
#if defined(RADIOLIB_INTERRUPT_TIMING)
(void)start;

Wyświetl plik

@ -139,6 +139,23 @@ class Module {
*/
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)
/*!
@ -258,6 +275,29 @@ class Module {
\param numBytes Number of bytes to transfer.
*/
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