Skip to content

Commit 699a92d

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

File tree

2 files changed

+157
-149
lines changed

2 files changed

+157
-149
lines changed

Adafruit_SPIDevice.cpp

+114-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,21 @@ 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+
if (a < b) {
52+
return a;
53+
} else {
54+
return b;
55+
}
56+
}
57+
}; // namespace std
58+
#endif
59+
4860
/*!
4961
* @brief Create an SPI device with the given CS pin and settings
5062
* @param cspin The arduino pin number to use for chip select
@@ -351,67 +363,119 @@ void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
351363
endTransaction();
352364
}
353365

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;
366+
void Adafruit_SPIDevice::transferFilledChunk(
367+
ChunkBuffer &chunkBuffer, ChunkBuffer::Iterator &iteratorToIncrement,
368+
const uint8_t *bufferToSend, const size_t bufferLen) {
369+
auto bytesToTransferLen = bufferLen;
370+
auto bytesToTransferBuffer = bufferToSend;
369371

370-
auto chunkBufferIterator = chunkBuffer.begin();
372+
while (bytesToTransferLen) {
373+
auto bytesToTransferLenThisChunk = std::min(
374+
bytesToTransferLen,
375+
chunkBuffer.size() - (iteratorToIncrement - chunkBuffer.begin()));
371376

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

376-
beginTransactionWithAssertingCS();
380+
bytesToTransferLen -= bytesToTransferLenThisChunk;
381+
bytesToTransferBuffer += bytesToTransferLenThisChunk;
377382

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

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

385388
#ifdef DEBUG_SERIAL
386-
printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer,
387-
chunkNumber++);
389+
printChunk("transferFilledChunk()", chunkBuffer, chunkBuffer.size());
388390
#endif
391+
} else {
392+
iteratorToIncrement = iteratorToIncrement + bytesToTransferLenThisChunk;
389393
}
390394
}
395+
}
391396

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

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

399406
#ifdef DEBUG_SERIAL
400-
printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer,
401-
chunkNumber++);
407+
printChunk("transferPartiallyFilledChunk()", chunkBuffer,
408+
bytesToTransferLenThisChunk);
402409
#endif
403-
}
404410
}
411+
}
405412

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

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

416480
endTransactionWithDeassertingCS();
417481

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

463527
auto chunkBufferIterator = chunkBuffer.begin();
464528

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

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-
}
531+
transferFilledChunk(chunkBuffer, chunkBufferIterator, write_buffer,
532+
write_len);
533+
transferAndReadChunks(chunkBuffer, chunkBufferIterator, read_buffer, read_len,
534+
sendvalue);
543535

544536
endTransactionWithDeassertingCS();
545537

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)