|
7 | 7 | #if !defined(SPI_INTERFACES_COUNT) || \
|
8 | 8 | (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
|
9 | 9 |
|
10 |
| -//#define DEBUG_SERIAL Serial |
| 10 | +// #define DEBUG_SERIAL Serial |
11 | 11 |
|
12 | 12 | #ifdef DEBUG_SERIAL
|
13 | 13 | 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) { |
16 | 15 | DEBUG_SERIAL.print(F("\t"));
|
17 | 16 | 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 ")); |
21 | 18 | DEBUG_SERIAL.println(size);
|
22 | 19 | DEBUG_SERIAL.print(F("\t"));
|
23 | 20 |
|
@@ -45,6 +42,21 @@ static void printBuffer(const char *title, const uint8_t *buffer,
|
45 | 42 | }
|
46 | 43 | #endif
|
47 | 44 |
|
| 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 | + |
48 | 60 | /*!
|
49 | 61 | * @brief Create an SPI device with the given CS pin and settings
|
50 | 62 | * @param cspin The arduino pin number to use for chip select
|
@@ -351,67 +363,119 @@ void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
|
351 | 363 | endTransaction();
|
352 | 364 | }
|
353 | 365 |
|
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; |
369 | 371 |
|
370 |
| - auto chunkBufferIterator = chunkBuffer.begin(); |
| 372 | + while (bytesToTransferLen) { |
| 373 | + auto bytesToTransferLenThisChunk = std::min( |
| 374 | + bytesToTransferLen, |
| 375 | + chunkBuffer.size() - (iteratorToIncrement - chunkBuffer.begin())); |
371 | 376 |
|
372 |
| -#ifdef DEBUG_SERIAL |
373 |
| - uint8_t chunkNumber = 1; |
374 |
| -#endif |
| 377 | + memcpy(iteratorToIncrement, bytesToTransferBuffer, |
| 378 | + bytesToTransferLenThisChunk); |
375 | 379 |
|
376 |
| - beginTransactionWithAssertingCS(); |
| 380 | + bytesToTransferLen -= bytesToTransferLenThisChunk; |
| 381 | + bytesToTransferBuffer += bytesToTransferLenThisChunk; |
377 | 382 |
|
378 |
| - for (size_t i = 0; i < prefix_len; ++i) { |
379 |
| - *chunkBufferIterator++ = prefix_buffer[i]; |
| 383 | + if (bytesToTransferLen) { |
| 384 | + transfer(chunkBuffer.data(), chunkBuffer.size()); |
380 | 385 |
|
381 |
| - if (chunkBufferIterator == chunkBuffer.end()) { |
382 |
| - transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer); |
383 |
| - chunkBufferIterator = chunkBuffer.begin(); |
| 386 | + iteratorToIncrement = chunkBuffer.begin(); |
384 | 387 |
|
385 | 388 | #ifdef DEBUG_SERIAL
|
386 |
| - printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer, |
387 |
| - chunkNumber++); |
| 389 | + printChunk("transferFilledChunk()", chunkBuffer, chunkBuffer.size()); |
388 | 390 | #endif
|
| 391 | + } else { |
| 392 | + iteratorToIncrement = iteratorToIncrement + bytesToTransferLenThisChunk; |
389 | 393 | }
|
390 | 394 | }
|
| 395 | +} |
391 | 396 |
|
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(); |
394 | 403 |
|
395 |
| - if (chunkBufferIterator == chunkBuffer.end()) { |
396 |
| - transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer); |
397 |
| - chunkBufferIterator = chunkBuffer.begin(); |
| 404 | + transfer(chunkBuffer.data(), bytesToTransferLenThisChunk); |
398 | 405 |
|
399 | 406 | #ifdef DEBUG_SERIAL
|
400 |
| - printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer, |
401 |
| - chunkNumber++); |
| 407 | + printChunk("transferPartiallyFilledChunk()", chunkBuffer, |
| 408 | + bytesToTransferLenThisChunk); |
402 | 409 | #endif
|
403 |
| - } |
404 | 410 | }
|
| 411 | +} |
405 | 412 |
|
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); |
409 | 425 |
|
| 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); |
410 | 437 | #ifdef DEBUG_SERIAL
|
411 |
| - printChunk("write() Wrote remaining", chunkBuffer, numberByteToTransfer, |
412 |
| - chunkNumber++); |
| 438 | + printChunk("transferAndReadChunks() after transmit", chunkBuffer, |
| 439 | + tranferLen); |
413 | 440 | #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 | + } |
414 | 452 | }
|
| 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); |
415 | 479 |
|
416 | 480 | endTransactionWithDeassertingCS();
|
417 | 481 |
|
@@ -462,84 +526,12 @@ bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer,
|
462 | 526 |
|
463 | 527 | auto chunkBufferIterator = chunkBuffer.begin();
|
464 | 528 |
|
465 |
| -#ifdef DEBUG_SERIAL |
466 |
| - uint8_t chunkNumber = 1; |
467 |
| -#endif |
468 |
| - |
469 | 529 | beginTransactionWithAssertingCS();
|
470 | 530 |
|
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); |
543 | 535 |
|
544 | 536 | endTransactionWithDeassertingCS();
|
545 | 537 |
|
|
0 commit comments