Skip to content

Commit 28ff05d

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

File tree

2 files changed

+155
-153
lines changed

2 files changed

+155
-153
lines changed

Adafruit_SPIDevice.cpp

+112-126
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
#include "Adafruit_SPIDevice.h"
22

3-
#if !defined(__AVR__)
4-
#include <array>
5-
#endif
6-
73
#if !defined(SPI_INTERFACES_COUNT) || \
84
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
95

10-
//#define DEBUG_SERIAL Serial
6+
// #define DEBUG_SERIAL Serial
117

128
#ifdef DEBUG_SERIAL
139
template <typename T>
14-
static void printChunk(const char *title, const T &buffer, const uint8_t size,
15-
const uint16_t chunkNumber) {
10+
static void printChunk(const char *title, const T &buffer, const uint8_t size) {
1611
DEBUG_SERIAL.print(F("\t"));
1712
DEBUG_SERIAL.print(title);
18-
DEBUG_SERIAL.print(F(" Chunk #"));
19-
DEBUG_SERIAL.print(chunkNumber);
20-
DEBUG_SERIAL.print(F(", size "));
13+
DEBUG_SERIAL.print(F(" Chunk, size "));
2114
DEBUG_SERIAL.println(size);
2215
DEBUG_SERIAL.print(F("\t"));
2316

@@ -45,6 +38,20 @@ static void printBuffer(const char *title, const uint8_t *buffer,
4538
}
4639
#endif
4740

41+
// The Arduino Core of AVR defines min() as a macro. It also has no std::min, so
42+
// undef the macro and create std::min
43+
#if defined(__AVR__)
44+
#undef min
45+
namespace std {
46+
template <typename T> constexpr T min(const T a, const T b) {
47+
return (a < b) ? a : b;
48+
}
49+
}; // namespace std
50+
#else
51+
// all other platforms have stdlib's <algorithm>, so include the real deal
52+
#include <algorithm>
53+
#endif
54+
4855
/*!
4956
* @brief Create an SPI device with the given CS pin and settings
5057
* @param cspin The arduino pin number to use for chip select
@@ -351,67 +358,118 @@ void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
351358
endTransaction();
352359
}
353360

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;
361+
void Adafruit_SPIDevice::transferFilledChunk(
362+
ChunkBuffer &chunkBuffer, ChunkBuffer::Iterator &iteratorToIncrement,
363+
const uint8_t *bufferToSend, const size_t bufferLen) {
364+
auto bytesToTransferLen = bufferLen;
365+
auto bytesToTransferBuffer = bufferToSend;
369366

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

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

376-
beginTransactionWithAssertingCS();
375+
bytesToTransferLen -= bytesToTransferLenThisChunk;
376+
bytesToTransferBuffer += bytesToTransferLenThisChunk;
377377

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

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

385383
#ifdef DEBUG_SERIAL
386-
printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer,
387-
chunkNumber++);
384+
printChunk("transferFilledChunk()", chunkBuffer, chunkBuffer.size());
388385
#endif
386+
} else {
387+
iteratorToIncrement = iteratorToIncrement + bytesToTransferLenThisChunk;
389388
}
390389
}
390+
}
391391

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

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

399401
#ifdef DEBUG_SERIAL
400-
printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer,
401-
chunkNumber++);
402+
printChunk("transferPartiallyFilledChunk()", chunkBuffer,
403+
bytesToTransferLenThisChunk);
402404
#endif
403-
}
404405
}
406+
}
405407

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

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

416474
endTransactionWithDeassertingCS();
417475

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

463521
auto chunkBufferIterator = chunkBuffer.begin();
464522

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

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-
}
525+
transferFilledChunk(chunkBuffer, chunkBufferIterator, write_buffer,
526+
write_len);
527+
transferAndReadChunks(chunkBuffer, chunkBufferIterator, read_buffer, read_len,
528+
sendvalue);
543529

544530
endTransactionWithDeassertingCS();
545531

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)