11#include " Adafruit_SPIDevice.h"
22
3+ #if !defined(__AVR__)
4+ #include < array>
5+ #endif
6+
37#if !defined(SPI_INTERFACES_COUNT) || \
48 (defined (SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0 ))
59
10+ // ! constant for the buffer size for the chunked transfer
11+ constexpr size_t maxBufferSizeForChunkedTransfer = 64 ;
12+
613// #define DEBUG_SERIAL Serial
714
15+ #ifdef DEBUG_SERIAL
16+ #if !defined(__AVR__)
17+ template <typename T>
18+ static void printChunk (const char *title, const T &buffer, const uint8_t size,
19+ const uint16_t chunkNumber) {
20+ DEBUG_SERIAL.print (F (" \t " ));
21+ DEBUG_SERIAL.print (title);
22+ DEBUG_SERIAL.print (F (" Chunk #" ));
23+ DEBUG_SERIAL.print (chunkNumber);
24+ DEBUG_SERIAL.print (F (" , size " ));
25+ DEBUG_SERIAL.println (size);
26+ DEBUG_SERIAL.print (F (" \t " ));
27+
28+ for (uint8_t i = 0 ; i < size; ++i) {
29+ DEBUG_SERIAL.print (F (" 0x" ));
30+ DEBUG_SERIAL.print (buffer[i], HEX);
31+ DEBUG_SERIAL.print (F (" , " ));
32+ }
33+ DEBUG_SERIAL.println ();
34+ }
35+ #endif
36+
37+ static void printBuffer (const char *title, const uint8_t *buffer,
38+ const size_t len) {
39+ DEBUG_SERIAL.print (F (" \t " ));
40+ DEBUG_SERIAL.println (title);
41+ for (size_t i = 0 ; i < len; i++) {
42+ DEBUG_SERIAL.print (F (" 0x" ));
43+ DEBUG_SERIAL.print (buffer[i], HEX);
44+ DEBUG_SERIAL.print (F (" , " ));
45+ if (i % 32 == 31 ) {
46+ DEBUG_SERIAL.println ();
47+ }
48+ }
49+ DEBUG_SERIAL.println ();
50+ }
51+ #endif
52+
853/* !
954 * @brief Create an SPI device with the given CS pin and settings
1055 * @param cspin The arduino pin number to use for chip select
@@ -160,7 +205,6 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
160205 // Serial.print(send, HEX);
161206 for (uint8_t b = startbit; b != 0 ;
162207 b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1 ) {
163-
164208 if (bitdelay_us) {
165209 delayMicroseconds (bitdelay_us);
166210 }
@@ -326,49 +370,77 @@ void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
326370bool Adafruit_SPIDevice::write (const uint8_t *buffer, size_t len,
327371 const uint8_t *prefix_buffer,
328372 size_t prefix_len) {
373+ #if !defined(__AVR__)
374+ std::array<uint8_t , maxBufferSizeForChunkedTransfer> chunkBuffer;
375+
376+ auto chunkBufferIterator = chunkBuffer.begin ();
377+
378+ #ifdef DEBUG_SERIAL
379+ uint8_t chunkNumber = 1 ;
380+ #endif
381+
329382 beginTransactionWithAssertingCS ();
330383
331- // do the writing
332- # if defined(ARDUINO_ARCH_ESP32)
333- if (_spi) {
334- if (prefix_len > 0 ) {
335- _spi-> transferBytes (prefix_buffer, nullptr , prefix_len );
336- }
337- if (len > 0 ) {
338- _spi-> transferBytes (buffer, nullptr , len);
339- }
340- } else
384+ for ( size_t i = 0 ; i < prefix_len; ++i) {
385+ *chunkBufferIterator++ = prefix_buffer[i];
386+
387+ if (chunkBufferIterator == chunkBuffer. end () ) {
388+ transfer (chunkBuffer. data (), maxBufferSizeForChunkedTransfer );
389+ chunkBufferIterator = chunkBuffer. begin ();
390+
391+ # ifdef DEBUG_SERIAL
392+ printChunk ( " write() Wrote " , chunkBuffer, maxBufferSizeForChunkedTransfer,
393+ chunkNumber++);
341394#endif
342- {
343- for (size_t i = 0 ; i < prefix_len; i++) {
344- transfer (prefix_buffer[i]);
345- }
346- for (size_t i = 0 ; i < len; i++) {
347- transfer (buffer[i]);
348395 }
349396 }
350- endTransactionWithDeassertingCS ();
397+
398+ for (size_t i = 0 ; i < len; ++i) {
399+ *chunkBufferIterator++ = buffer[i];
400+
401+ if (chunkBufferIterator == chunkBuffer.end ()) {
402+ transfer (chunkBuffer.data (), maxBufferSizeForChunkedTransfer);
403+ chunkBufferIterator = chunkBuffer.begin ();
351404
352405#ifdef DEBUG_SERIAL
353- DEBUG_SERIAL.print (F (" \t SPIDevice Wrote: " ));
354- if ((prefix_len != 0 ) && (prefix_buffer != nullptr )) {
355- for (uint16_t i = 0 ; i < prefix_len; i++) {
356- DEBUG_SERIAL.print (F (" 0x" ));
357- DEBUG_SERIAL.print (prefix_buffer[i], HEX);
358- DEBUG_SERIAL.print (F (" , " ));
406+ printChunk (" write() Wrote" , chunkBuffer, maxBufferSizeForChunkedTransfer,
407+ chunkNumber++);
408+ #endif
359409 }
360410 }
361- for (uint16_t i = 0 ; i < len; i++) {
362- DEBUG_SERIAL.print (F (" 0x" ));
363- DEBUG_SERIAL.print (buffer[i], HEX);
364- DEBUG_SERIAL.print (F (" , " ));
365- if (i % 32 == 31 ) {
366- DEBUG_SERIAL.println ();
367- }
411+
412+ if (chunkBufferIterator != chunkBuffer.begin ()) {
413+ auto numberByteToTransfer = chunkBufferIterator - chunkBuffer.begin ();
414+ transfer (chunkBuffer.data (), numberByteToTransfer);
415+
416+ #ifdef DEBUG_SERIAL
417+ printChunk (" write() Wrote remaining" , chunkBuffer, numberByteToTransfer,
418+ chunkNumber++);
419+ #endif
368420 }
369- DEBUG_SERIAL.println ();
421+
422+ endTransactionWithDeassertingCS ();
423+
424+ #else // !defined(__AVR__)
425+
426+ beginTransactionWithAssertingCS ();
427+
428+ for (size_t i = 0 ; i < prefix_len; i++) {
429+ transfer (prefix_buffer[i]);
430+ }
431+ for (size_t i = 0 ; i < len; i++) {
432+ transfer (buffer[i]);
433+ }
434+
435+ endTransactionWithDeassertingCS ();
436+
437+ #ifdef DEBUG_SERIAL
438+ printBuffer (" write() prefix_buffer" , prefix_buffer, prefix_len);
439+ printBuffer (" write() buffer" , buffer, len);
370440#endif
371441
442+ #endif // !defined(__AVR__)
443+
372444 return true ;
373445}
374446
@@ -390,16 +462,7 @@ bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
390462 endTransactionWithDeassertingCS ();
391463
392464#ifdef DEBUG_SERIAL
393- DEBUG_SERIAL.print (F (" \t SPIDevice Read: " ));
394- for (uint16_t i = 0 ; i < len; i++) {
395- DEBUG_SERIAL.print (F (" 0x" ));
396- DEBUG_SERIAL.print (buffer[i], HEX);
397- DEBUG_SERIAL.print (F (" , " ));
398- if (len % 32 == 31 ) {
399- DEBUG_SERIAL.println ();
400- }
401- }
402- DEBUG_SERIAL.println ();
465+ printBuffer (" read() buffer" , buffer, len);
403466#endif
404467
405468 return true ;
@@ -421,53 +484,112 @@ bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
421484bool Adafruit_SPIDevice::write_then_read (const uint8_t *write_buffer,
422485 size_t write_len, uint8_t *read_buffer,
423486 size_t read_len, uint8_t sendvalue) {
487+ #if !defined(__AVR__)
488+ std::array<uint8_t , maxBufferSizeForChunkedTransfer> chunkBuffer;
489+
490+ auto chunkBufferIterator = chunkBuffer.begin ();
491+
492+ #ifdef DEBUG_SERIAL
493+ uint8_t chunkNumber = 1 ;
494+ #endif
495+
424496 beginTransactionWithAssertingCS ();
425- // do the writing
426- #if defined(ARDUINO_ARCH_ESP32)
427- if (_spi) {
428- if (write_len > 0 ) {
429- _spi->transferBytes (write_buffer, nullptr , write_len);
430- }
431- } else
497+
498+ for (size_t i = 0 ; i < write_len; ++i) {
499+ *chunkBufferIterator++ = write_buffer[i];
500+
501+ if (chunkBufferIterator == chunkBuffer.end ()) {
502+ transfer (chunkBuffer.data (), maxBufferSizeForChunkedTransfer);
503+ chunkBufferIterator = chunkBuffer.begin ();
504+
505+ #ifdef DEBUG_SERIAL
506+ printChunk (" write_then_read() Wrote" , chunkBuffer,
507+ maxBufferSizeForChunkedTransfer, chunkNumber++);
432508#endif
433- {
434- for (size_t i = 0 ; i < write_len; i++) {
435- transfer (write_buffer[i]);
436509 }
437510 }
438511
512+ auto readBufferIterator = read_buffer;
513+ auto readFromIterator = chunkBufferIterator;
514+ size_t readBufferLen = read_len;
515+
516+ for (size_t i = 0 ; i < read_len; ++i) {
517+ *chunkBufferIterator++ = sendvalue;
518+
519+ if (chunkBufferIterator == chunkBuffer.end ()) {
439520#ifdef DEBUG_SERIAL
440- DEBUG_SERIAL.print (F (" \t SPIDevice Wrote: " ));
441- for (uint16_t i = 0 ; i < write_len; i++) {
442- DEBUG_SERIAL.print (F (" 0x" ));
443- DEBUG_SERIAL.print (write_buffer[i], HEX);
444- DEBUG_SERIAL.print (F (" , " ));
445- if (write_len % 32 == 31 ) {
446- DEBUG_SERIAL.println ();
521+ printChunk (" write_then_read() before transmit" , chunkBuffer,
522+ maxBufferSizeForChunkedTransfer, chunkNumber);
523+ #endif
524+
525+ transfer (chunkBuffer.data (), maxBufferSizeForChunkedTransfer);
526+
527+ while (readBufferLen) {
528+ if (readFromIterator != chunkBuffer.end ()) {
529+ *readBufferIterator++ = *readFromIterator++;
530+ --readBufferLen;
531+ } else {
532+ break ;
533+ }
534+ }
535+
536+ #ifdef DEBUG_SERIAL
537+ printChunk (" write_then_read() after transmit" , chunkBuffer,
538+ maxBufferSizeForChunkedTransfer, chunkNumber++);
539+ #endif
540+
541+ chunkBufferIterator = chunkBuffer.begin ();
542+ readFromIterator = chunkBuffer.begin ();
447543 }
448544 }
449- DEBUG_SERIAL.println ();
545+
546+ if (chunkBufferIterator != chunkBuffer.begin ()) {
547+ auto numberByteToTransfer = chunkBufferIterator - chunkBuffer.begin ();
548+
549+ #ifdef DEBUG_SERIAL
550+ printChunk (" write_then_read() before transmit remaining" , chunkBuffer,
551+ numberByteToTransfer, chunkNumber);
552+ #endif
553+
554+ transfer (chunkBuffer.data (), numberByteToTransfer);
555+
556+ #ifdef DEBUG_SERIAL
557+ printChunk (" write_then_read() after transmit remaining" , chunkBuffer,
558+ numberByteToTransfer, chunkNumber);
450559#endif
451560
452- // do the reading
561+ while (readBufferLen) {
562+ if (readFromIterator != chunkBuffer.end ()) {
563+ *readBufferIterator++ = *readFromIterator++;
564+ --readBufferLen;
565+ } else {
566+ break ;
567+ }
568+ }
569+ }
570+
571+ endTransactionWithDeassertingCS ();
572+
573+ #else // !defined(__AVR__)
574+
575+ beginTransactionWithAssertingCS ();
576+
577+ for (size_t i = 0 ; i < write_len; i++) {
578+ transfer (write_buffer[i]);
579+ }
580+
453581 for (size_t i = 0 ; i < read_len; i++) {
454582 read_buffer[i] = transfer (sendvalue);
455583 }
456584
585+ endTransactionWithDeassertingCS ();
586+
457587#ifdef DEBUG_SERIAL
458- DEBUG_SERIAL.print (F (" \t SPIDevice Read: " ));
459- for (uint16_t i = 0 ; i < read_len; i++) {
460- DEBUG_SERIAL.print (F (" 0x" ));
461- DEBUG_SERIAL.print (read_buffer[i], HEX);
462- DEBUG_SERIAL.print (F (" , " ));
463- if (read_len % 32 == 31 ) {
464- DEBUG_SERIAL.println ();
465- }
466- }
467- DEBUG_SERIAL.println ();
588+ printBuffer (" write_then_read() write_buffer" , write_buffer, write_len);
589+ printBuffer (" write_then_read() read_buffer" , read_buffer, read_len);
468590#endif
469591
470- endTransactionWithDeassertingCS ();
592+ # endif // !defined(__AVR__)
471593
472594 return true ;
473595}
0 commit comments