|
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,17 @@ 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 | + return (a < b) ? a : b; |
| 52 | +} |
| 53 | +}; // namespace std |
| 54 | +#endif |
| 55 | + |
48 | 56 | /*! |
49 | 57 | * @brief Create an SPI device with the given CS pin and settings |
50 | 58 | * @param cspin The arduino pin number to use for chip select |
@@ -351,67 +359,119 @@ void Adafruit_SPIDevice::endTransactionWithDeassertingCS() { |
351 | 359 | endTransaction(); |
352 | 360 | } |
353 | 361 |
|
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; |
369 | 367 |
|
370 | | - auto chunkBufferIterator = chunkBuffer.begin(); |
| 368 | + while (bytesToTransferLen) { |
| 369 | + auto bytesToTransferLenThisChunk = std::min( |
| 370 | + bytesToTransferLen, |
| 371 | + chunkBuffer.size() - (iteratorToIncrement - chunkBuffer.begin())); |
371 | 372 |
|
372 | | -#ifdef DEBUG_SERIAL |
373 | | - uint8_t chunkNumber = 1; |
374 | | -#endif |
| 373 | + memcpy(iteratorToIncrement, bytesToTransferBuffer, |
| 374 | + bytesToTransferLenThisChunk); |
375 | 375 |
|
376 | | - beginTransactionWithAssertingCS(); |
| 376 | + bytesToTransferLen -= bytesToTransferLenThisChunk; |
| 377 | + bytesToTransferBuffer += bytesToTransferLenThisChunk; |
377 | 378 |
|
378 | | - for (size_t i = 0; i < prefix_len; ++i) { |
379 | | - *chunkBufferIterator++ = prefix_buffer[i]; |
| 379 | + if (bytesToTransferLen) { |
| 380 | + transfer(chunkBuffer.data(), chunkBuffer.size()); |
380 | 381 |
|
381 | | - if (chunkBufferIterator == chunkBuffer.end()) { |
382 | | - transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer); |
383 | | - chunkBufferIterator = chunkBuffer.begin(); |
| 382 | + iteratorToIncrement = chunkBuffer.begin(); |
384 | 383 |
|
385 | 384 | #ifdef DEBUG_SERIAL |
386 | | - printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer, |
387 | | - chunkNumber++); |
| 385 | + printChunk("transferFilledChunk()", chunkBuffer, chunkBuffer.size()); |
388 | 386 | #endif |
| 387 | + } else { |
| 388 | + iteratorToIncrement = iteratorToIncrement + bytesToTransferLenThisChunk; |
389 | 389 | } |
390 | 390 | } |
| 391 | +} |
391 | 392 |
|
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(); |
394 | 399 |
|
395 | | - if (chunkBufferIterator == chunkBuffer.end()) { |
396 | | - transfer(chunkBuffer.data(), maxBufferSizeForChunkedTransfer); |
397 | | - chunkBufferIterator = chunkBuffer.begin(); |
| 400 | + transfer(chunkBuffer.data(), bytesToTransferLenThisChunk); |
398 | 401 |
|
399 | 402 | #ifdef DEBUG_SERIAL |
400 | | - printChunk("write() Wrote", chunkBuffer, maxBufferSizeForChunkedTransfer, |
401 | | - chunkNumber++); |
| 403 | + printChunk("transferPartiallyFilledChunk()", chunkBuffer, |
| 404 | + bytesToTransferLenThisChunk); |
402 | 405 | #endif |
403 | | - } |
404 | 406 | } |
| 407 | +} |
405 | 408 |
|
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 | + bytesToTransferLen -= bytesToTransferLenThisChunk; |
409 | 423 |
|
| 424 | + { |
| 425 | + auto tranferLen = readFromIterator == chunkBuffer.begin() |
| 426 | + ? bytesToTransferLenThisChunk |
| 427 | + : chunkBuffer.size(); |
| 428 | +#if defined(DEBUG_SERIAL) && defined(DEBUG_VERBOSE) |
| 429 | + printChunk("transferAndReadChunks() before transmit", chunkBuffer, |
| 430 | + tranferLen); |
| 431 | +#endif |
| 432 | + transfer(chunkBuffer.data(), tranferLen); |
410 | 433 | #ifdef DEBUG_SERIAL |
411 | | - printChunk("write() Wrote remaining", chunkBuffer, numberByteToTransfer, |
412 | | - chunkNumber++); |
| 434 | + printChunk("transferAndReadChunks() after transmit", chunkBuffer, |
| 435 | + tranferLen); |
413 | 436 | #endif |
| 437 | + } |
| 438 | + |
| 439 | + memcpy(readBuffer, readFromIterator, bytesToTransferLenThisChunk); |
| 440 | + |
| 441 | + readBuffer += bytesToTransferLenThisChunk; |
| 442 | + |
| 443 | + readFromIterator = iteratorToIncrement = chunkBuffer.begin(); |
| 444 | + |
| 445 | + if (!bytesToTransferLen) { |
| 446 | + break; |
| 447 | + } |
414 | 448 | } |
| 449 | +} |
| 450 | + |
| 451 | +/*! |
| 452 | + * @brief Write a buffer or two to the SPI device, with transaction |
| 453 | + * management. |
| 454 | + * @param buffer Pointer to buffer of data to write |
| 455 | + * @param len Number of bytes from buffer to write |
| 456 | + * @param prefix_buffer Pointer to optional array of data to write before |
| 457 | + * buffer. |
| 458 | + * @param prefix_len Number of bytes from prefix buffer to write |
| 459 | + * @return Always returns true because there's no way to test success of SPI |
| 460 | + * writes |
| 461 | + */ |
| 462 | +bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len, |
| 463 | + const uint8_t *prefix_buffer, |
| 464 | + size_t prefix_len) { |
| 465 | + Array<uint8_t, maxBufferSizeForChunkedTransfer> chunkBuffer; |
| 466 | + |
| 467 | + auto chunkBufferIterator = chunkBuffer.begin(); |
| 468 | + |
| 469 | + beginTransactionWithAssertingCS(); |
| 470 | + |
| 471 | + transferFilledChunk(chunkBuffer, chunkBufferIterator, prefix_buffer, |
| 472 | + prefix_len); |
| 473 | + transferFilledChunk(chunkBuffer, chunkBufferIterator, buffer, len); |
| 474 | + transferPartiallyFilledChunk(chunkBuffer, chunkBufferIterator); |
415 | 475 |
|
416 | 476 | endTransactionWithDeassertingCS(); |
417 | 477 |
|
@@ -462,84 +522,12 @@ bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer, |
462 | 522 |
|
463 | 523 | auto chunkBufferIterator = chunkBuffer.begin(); |
464 | 524 |
|
465 | | -#ifdef DEBUG_SERIAL |
466 | | - uint8_t chunkNumber = 1; |
467 | | -#endif |
468 | | - |
469 | 525 | beginTransactionWithAssertingCS(); |
470 | 526 |
|
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 | | - } |
| 527 | + transferFilledChunk(chunkBuffer, chunkBufferIterator, write_buffer, |
| 528 | + write_len); |
| 529 | + transferAndReadChunks(chunkBuffer, chunkBufferIterator, read_buffer, read_len, |
| 530 | + sendvalue); |
543 | 531 |
|
544 | 532 | endTransactionWithDeassertingCS(); |
545 | 533 |
|
|
0 commit comments