Skip to content

Commit 5c36a3a

Browse files
committed
moved the chunked transfer management to their own private methods
1 parent f08f376 commit 5c36a3a

File tree

2 files changed

+152
-149
lines changed

2 files changed

+152
-149
lines changed

Adafruit_SPIDevice.cpp

+109-122
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@
77
#if !defined(SPI_INTERFACES_COUNT) || \
88
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
99

10-
//#define DEBUG_SERIAL Serial
10+
// #define DEBUG_SERIAL Serial
1111

1212
#ifdef DEBUG_SERIAL
1313
template <typename T>
14-
static void printChunk(const char *title, const T &buffer, const uint8_t size,
15-
const uint16_t chunkNumber) {
14+
static void printChunk(const char *title, const T &buffer, const uint8_t size) {
1615
DEBUG_SERIAL.print(F("\t"));
1716
DEBUG_SERIAL.print(title);
18-
DEBUG_SERIAL.print(F(" Chunk #"));
19-
DEBUG_SERIAL.print(chunkNumber);
20-
DEBUG_SERIAL.print(F(", size "));
17+
DEBUG_SERIAL.print(F(" Chunk, size "));
2118
DEBUG_SERIAL.println(size);
2219
DEBUG_SERIAL.print(F("\t"));
2320

@@ -45,6 +42,17 @@ static void printBuffer(const char *title, const uint8_t *buffer,
4542
}
4643
#endif
4744

45+
// The Arduino Core of AVR defines min() as a macro. It also has no std::min, so
46+
// undef the macro and create std::min
47+
#if defined(__AVR__)
48+
#undef min
49+
namespace std {
50+
template <typename T> constexpr T min(const T a, const T b) {
51+
return (a < b) ? a : b;
52+
}
53+
}; // namespace std
54+
#endif
55+
4856
/*!
4957
* @brief Create an SPI device with the given CS pin and settings
5058
* @param cspin The arduino pin number to use for chip select
@@ -351,67 +359,118 @@ void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
351359
endTransaction();
352360
}
353361

354-
/*!
355-
* @brief Write a buffer or two to the SPI device, with transaction
356-
* management.
357-
* @param buffer Pointer to buffer of data to write
358-
* @param len Number of bytes from buffer to write
359-
* @param prefix_buffer Pointer to optional array of data to write before
360-
* buffer.
361-
* @param prefix_len Number of bytes from prefix buffer to write
362-
* @return Always returns true because there's no way to test success of SPI
363-
* writes
364-
*/
365-
bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len,
366-
const uint8_t *prefix_buffer,
367-
size_t prefix_len) {
368-
Array<uint8_t, maxBufferSizeForChunkedTransfer> chunkBuffer;
362+
void Adafruit_SPIDevice::transferFilledChunk(
363+
ChunkBuffer &chunkBuffer, ChunkBuffer::Iterator &iteratorToIncrement,
364+
const uint8_t *bufferToSend, const size_t bufferLen) {
365+
auto bytesToTransferLen = bufferLen;
366+
auto bytesToTransferBuffer = bufferToSend;
369367

370-
auto chunkBufferIterator = chunkBuffer.begin();
368+
while (bytesToTransferLen) {
369+
auto bytesToTransferLenThisChunk = std::min(
370+
bytesToTransferLen,
371+
chunkBuffer.size() - (iteratorToIncrement - chunkBuffer.begin()));
371372

372-
#ifdef DEBUG_SERIAL
373-
uint8_t chunkNumber = 1;
374-
#endif
373+
memcpy(iteratorToIncrement, bytesToTransferBuffer,
374+
bytesToTransferLenThisChunk);
375375

376-
beginTransactionWithAssertingCS();
376+
bytesToTransferLen -= bytesToTransferLenThisChunk;
377+
bytesToTransferBuffer += bytesToTransferLenThisChunk;
377378

378-
for (size_t i = 0; i < prefix_len; ++i) {
379-
*chunkBufferIterator++ = prefix_buffer[i];
379+
if (bytesToTransferLen) {
380+
transfer(chunkBuffer.data(), chunkBuffer.size());
380381

381-
if (chunkBufferIterator == chunkBuffer.end()) {
382-
transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer);
383-
chunkBufferIterator = chunkBuffer.begin();
382+
iteratorToIncrement = chunkBuffer.begin();
384383

385384
#ifdef DEBUG_SERIAL
386-
printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer,
387-
chunkNumber++);
385+
printChunk("transferFilledChunk()", chunkBuffer, chunkBuffer.size());
388386
#endif
387+
} else {
388+
iteratorToIncrement = iteratorToIncrement + bytesToTransferLenThisChunk;
389389
}
390390
}
391+
}
391392

392-
for (size_t i = 0; i < len; ++i) {
393-
*chunkBufferIterator++ = buffer[i];
393+
void Adafruit_SPIDevice::transferPartiallyFilledChunk(
394+
ChunkBuffer &chunkBuffer,
395+
const ChunkBuffer::Iterator &chunkBufferIterator) {
396+
if (chunkBufferIterator != chunkBuffer.begin()) {
397+
auto bytesToTransferLenThisChunk =
398+
chunkBufferIterator - chunkBuffer.begin();
394399

395-
if (chunkBufferIterator == chunkBuffer.end()) {
396-
transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer);
397-
chunkBufferIterator = chunkBuffer.begin();
400+
transfer(chunkBuffer.data(), bytesToTransferLenThisChunk);
398401

399402
#ifdef DEBUG_SERIAL
400-
printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer,
401-
chunkNumber++);
403+
printChunk("transferPartiallyFilledChunk()", chunkBuffer,
404+
bytesToTransferLenThisChunk);
402405
#endif
403-
}
404406
}
407+
}
405408

406-
if (chunkBufferIterator != chunkBuffer.begin()) {
407-
auto numberByteToTransfer = chunkBufferIterator - chunkBuffer.begin();
408-
transfer(chunkBuffer.data(), numberByteToTransfer);
409+
void Adafruit_SPIDevice::transferAndReadChunks(
410+
ChunkBuffer &chunkBuffer, ChunkBuffer::Iterator &iteratorToIncrement,
411+
uint8_t *readBuffer, const size_t readLen, const uint8_t sendVal) {
412+
size_t bytesToTransferLen = readLen;
413+
auto readFromIterator = iteratorToIncrement;
414+
415+
while (bytesToTransferLen) {
416+
auto bytesToTransferLenThisChunk = std::min(
417+
bytesToTransferLen,
418+
chunkBuffer.size() - (iteratorToIncrement - chunkBuffer.begin()));
419+
420+
memset(iteratorToIncrement, sendVal, bytesToTransferLenThisChunk);
421+
422+
iteratorToIncrement += bytesToTransferLenThisChunk;
423+
bytesToTransferLen -= bytesToTransferLenThisChunk;
409424

425+
{
426+
auto tranferLen = iteratorToIncrement - chunkBuffer.begin();
427+
#if defined(DEBUG_SERIAL) && defined(DEBUG_VERBOSE)
428+
printChunk("transferAndReadChunks() before transmit", chunkBuffer,
429+
tranferLen);
430+
#endif
431+
transfer(chunkBuffer.data(), tranferLen);
410432
#ifdef DEBUG_SERIAL
411-
printChunk("write() Wrote remaining", chunkBuffer, numberByteToTransfer,
412-
chunkNumber++);
433+
printChunk("transferAndReadChunks() after transmit", chunkBuffer,
434+
tranferLen);
413435
#endif
436+
}
437+
438+
memcpy(readBuffer, readFromIterator, bytesToTransferLenThisChunk);
439+
440+
readBuffer += bytesToTransferLenThisChunk;
441+
442+
readFromIterator = iteratorToIncrement = chunkBuffer.begin();
443+
444+
if (!bytesToTransferLen) {
445+
break;
446+
}
414447
}
448+
}
449+
450+
/*!
451+
* @brief Write a buffer or two to the SPI device, with transaction
452+
* management.
453+
* @param buffer Pointer to buffer of data to write
454+
* @param len Number of bytes from buffer to write
455+
* @param prefix_buffer Pointer to optional array of data to write before
456+
* buffer.
457+
* @param prefix_len Number of bytes from prefix buffer to write
458+
* @return Always returns true because there's no way to test success of SPI
459+
* writes
460+
*/
461+
bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len,
462+
const uint8_t *prefix_buffer,
463+
size_t prefix_len) {
464+
Array<uint8_t, maxBufferSizeForChunkedTransfer> chunkBuffer;
465+
466+
auto chunkBufferIterator = chunkBuffer.begin();
467+
468+
beginTransactionWithAssertingCS();
469+
470+
transferFilledChunk(chunkBuffer, chunkBufferIterator, prefix_buffer,
471+
prefix_len);
472+
transferFilledChunk(chunkBuffer, chunkBufferIterator, buffer, len);
473+
transferPartiallyFilledChunk(chunkBuffer, chunkBufferIterator);
415474

416475
endTransactionWithDeassertingCS();
417476

@@ -462,84 +521,12 @@ bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer,
462521

463522
auto chunkBufferIterator = chunkBuffer.begin();
464523

465-
#ifdef DEBUG_SERIAL
466-
uint8_t chunkNumber = 1;
467-
#endif
468-
469524
beginTransactionWithAssertingCS();
470525

471-
for (size_t i = 0; i < write_len; ++i) {
472-
*chunkBufferIterator++ = write_buffer[i];
473-
474-
if (chunkBufferIterator == chunkBuffer.end()) {
475-
transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer);
476-
chunkBufferIterator = chunkBuffer.begin();
477-
478-
#ifdef DEBUG_SERIAL
479-
printChunk("write_then_read() Wrote", chunkBuffer,
480-
maxBufferSizeForChunkedTransfer, chunkNumber++);
481-
#endif
482-
}
483-
}
484-
485-
auto readBufferIterator = read_buffer;
486-
auto readFromIterator = chunkBufferIterator;
487-
size_t readBufferLen = read_len;
488-
489-
for (size_t i = 0; i < read_len; ++i) {
490-
*chunkBufferIterator++ = sendvalue;
491-
492-
if (chunkBufferIterator == chunkBuffer.end()) {
493-
#ifdef DEBUG_SERIAL
494-
printChunk("write_then_read() before transmit", chunkBuffer,
495-
maxBufferSizeForChunkedTransfer, chunkNumber);
496-
#endif
497-
498-
transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer);
499-
500-
while (readBufferLen) {
501-
if (readFromIterator != chunkBuffer.end()) {
502-
*readBufferIterator++ = *readFromIterator++;
503-
--readBufferLen;
504-
} else {
505-
break;
506-
}
507-
}
508-
509-
#ifdef DEBUG_SERIAL
510-
printChunk("write_then_read() after transmit", chunkBuffer,
511-
maxBufferSizeForChunkedTransfer, chunkNumber++);
512-
#endif
513-
514-
chunkBufferIterator = chunkBuffer.begin();
515-
readFromIterator = chunkBuffer.begin();
516-
}
517-
}
518-
519-
if (chunkBufferIterator != chunkBuffer.begin()) {
520-
auto numberByteToTransfer = chunkBufferIterator - chunkBuffer.begin();
521-
522-
#ifdef DEBUG_SERIAL
523-
printChunk("write_then_read() before transmit remaining", chunkBuffer,
524-
numberByteToTransfer, chunkNumber);
525-
#endif
526-
527-
transfer(chunkBuffer.data(), numberByteToTransfer);
528-
529-
#ifdef DEBUG_SERIAL
530-
printChunk("write_then_read() after transmit remaining", chunkBuffer,
531-
numberByteToTransfer, chunkNumber);
532-
#endif
533-
534-
while (readBufferLen) {
535-
if (readFromIterator != chunkBuffer.end()) {
536-
*readBufferIterator++ = *readFromIterator++;
537-
--readBufferLen;
538-
} else {
539-
break;
540-
}
541-
}
542-
}
526+
transferFilledChunk(chunkBuffer, chunkBufferIterator, write_buffer,
527+
write_len);
528+
transferAndReadChunks(chunkBuffer, chunkBufferIterator, read_buffer, read_len,
529+
sendvalue);
543530

544531
endTransactionWithDeassertingCS();
545532

Adafruit_SPIDevice.h

+43-27
Original file line numberDiff line numberDiff line change
@@ -103,30 +103,6 @@ class Adafruit_SPIDevice {
103103
void beginTransactionWithAssertingCS();
104104
void endTransactionWithDeassertingCS();
105105

106-
private:
107-
SPIClass *_spi;
108-
SPISettings *_spiSetting;
109-
uint32_t _freq;
110-
BusIOBitOrder _dataOrder;
111-
uint8_t _dataMode;
112-
113-
void setChipSelect(int value);
114-
115-
int8_t _cs, _sck, _mosi, _miso;
116-
#ifdef BUSIO_USE_FAST_PINIO
117-
BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort;
118-
BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask;
119-
#endif
120-
121-
//! constant for the buffer size for the chunked transfer
122-
static constexpr size_t maxBufferSizeForChunkedTransfer =
123-
#ifdef __AVR__
124-
32;
125-
#else
126-
64;
127-
#endif
128-
bool _begun;
129-
130106
protected:
131107
/*!
132108
* @brief Template to encypsulate a C-array, provides STL-style accessors
@@ -136,15 +112,18 @@ class Adafruit_SPIDevice {
136112
*/
137113
template <typename Type, size_t Size> class Array {
138114
public:
115+
//! Iterator type
116+
using Iterator = Type *;
117+
139118
/*! @brief returns a pointer the start of the buffer
140119
* @returns a pointer the start of the buffer
141120
*/
142-
Type *begin() { return buffer; }
121+
Iterator begin() { return buffer; }
143122

144123
/*! @brief returns a pointer the one increment beyond the end of the buffer
145124
* @returns a pointer the one increment beyond the end of the buffer
146125
*/
147-
Type *end() { return endPointer; }
126+
Iterator end() { return endPointer; }
148127

149128
/*! @brief returns the size of the buffer
150129
* @returns the size of the buffer
@@ -172,8 +151,45 @@ class Adafruit_SPIDevice {
172151
//! the buffer
173152
Type buffer[Size];
174153
//! address buffer one increment after the end
175-
Type *endPointer = buffer + Size;
154+
Iterator endPointer = buffer + Size;
176155
};
156+
157+
private:
158+
//! constant for the buffer size for the chunked transfer
159+
static constexpr size_t maxBufferSizeForChunkedTransfer =
160+
#ifdef __AVR__
161+
32;
162+
#else
163+
64;
164+
#endif
165+
166+
using ChunkBuffer = Array<uint8_t, maxBufferSizeForChunkedTransfer>;
167+
168+
SPIClass *_spi;
169+
SPISettings *_spiSetting;
170+
uint32_t _freq;
171+
BusIOBitOrder _dataOrder;
172+
uint8_t _dataMode;
173+
174+
void setChipSelect(int value);
175+
void transferFilledChunk(ChunkBuffer &chunkBuffer,
176+
ChunkBuffer::Iterator &iteratorToIncrement,
177+
const uint8_t *bufferToSend, const size_t bufferLen);
178+
void transferPartiallyFilledChunk(
179+
ChunkBuffer &chunkBuffer,
180+
const ChunkBuffer::Iterator &chunkBufferIterator);
181+
182+
void transferAndReadChunks(ChunkBuffer &chunkBuffer,
183+
ChunkBuffer::Iterator &iteratorToIncrement,
184+
uint8_t *readBuffer, const size_t readLen,
185+
const uint8_t sendVal);
186+
187+
int8_t _cs, _sck, _mosi, _miso;
188+
#ifdef BUSIO_USE_FAST_PINIO
189+
BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort;
190+
BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask;
191+
#endif
192+
bool _begun;
177193
};
178194

179195
#endif // has SPI defined

0 commit comments

Comments
 (0)