@@ -949,6 +949,24 @@ void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
949949 }
950950}
951951
952+ /* !
953+ @brief Swap bytes in an array of pixels; converts little-to-big or
954+ big-to-little endian. Used by writePixels() below in some
955+ situations, but may also be helpful for user code occasionally.
956+ @param src Source address of 16-bit pixels buffer.
957+ @param len Number of pixels to byte-swap.
958+ @param dest Optional destination address if different than src --
959+ otherwise, if NULL (default) or same address is passed,
960+ pixel buffer is overwritten in-place.
961+ */
962+ void swapBytes (uint16_t *src, uint32_t len, uint16_t *dest) {
963+ if (!dest)
964+ dest = src; // NULL -> overwrite src buffer
965+ for (uint32_t i = 0 ; i < len; i++) {
966+ dest[i] = __builtin_bswap16 (src[i]);
967+ }
968+ }
969+
952970/* !
953971 @brief Issue a series of pixels from memory to the display. Not self-
954972 contained; should follow startWrite() and setAddrWindow() calls.
@@ -963,19 +981,16 @@ void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
963981 doing ANY other display-related activities (or even
964982 any SPI-related activities, if using an SPI display
965983 that shares the bus with other devices).
966- @param bigEndian If using DMA, and if set true, bitmap in memory is in
967- big-endian order (most significant byte first). By
968- default this is false, as most microcontrollers seem
969- to be little-endian and 16-bit pixel values must be
970- byte-swapped before issuing to the display (which tend
971- to be big-endian when using SPI or 8-bit parallel).
972- If an application can optimize around this -- for
973- example, a bitmap in a uint16_t array having the byte
974- values already reordered big-endian, this can save
975- some processing time here, ESPECIALLY if using this
976- function's non-blocking DMA mode. Not all cases are
977- covered...this is really here only for SAMD DMA and
978- much forethought on the application side.
984+ @param bigEndian If true, bitmap in memory is in big-endian order (most
985+ significant byte first). By default this is false, as
986+ most microcontrollers seem to be little-endian and
987+ 16-bit pixel values must be byte-swapped before
988+ issuing to the display (which tend toward big-endian
989+ when using SPI or 8-bit parallel). If an application
990+ can optimize around this -- for example, a bitmap in a
991+ uint16_t array having the byte values already ordered
992+ big-endian, this can save time here, ESPECIALLY if
993+ using this function's non-blocking DMA mode.
979994*/
980995void Adafruit_SPITFT::writePixels (uint16_t *colors, uint32_t len, bool block,
981996 bool bigEndian) {
@@ -987,28 +1002,23 @@ void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
9871002 (void )block;
9881003 (void )bigEndian;
9891004
990- #if defined(ESP32) // ESP32 has a special SPI pixel-writing function...
1005+ #if defined(ESP32)
9911006 if (connection == TFT_HARD_SPI) {
992- hwspi._spi ->writePixels (colors, len * 2 );
1007+ if (!bigEndian) {
1008+ hwspi._spi ->writePixels (colors, len * 2 ); // Inbuilt endian-swap
1009+ } else {
1010+ hwspi._spi ->writeBytes (colors, len * 2 ); // Issue bytes direct
1011+ }
9931012 return ;
9941013 }
9951014#elif defined(ARDUINO_NRF52_ADAFRUIT) && \
9961015 defined (NRF52840_XXAA) // Adafruit nRF52 use SPIM3 DMA at 32Mhz
997- // TFT and SPI DMA endian is different we need to swap bytes
9981016 if (!bigEndian) {
999- for (uint32_t i = 0 ; i < len; i++) {
1000- colors[i] = __builtin_bswap16 (colors[i]);
1001- }
1017+ byteSwap (colors, len); // convert little-to-big endian for display
10021018 }
1003-
1004- // use the separate tx, rx buf variant to prevent overwrite the buffer
1005- hwspi._spi ->transfer (colors, NULL , 2 * len);
1006-
1007- // swap back color buffer
1019+ hwspi._spi ->transfer (colors, NULL , 2 * len); // NULL RX to avoid overwrite
10081020 if (!bigEndian) {
1009- for (uint32_t i = 0 ; i < len; i++) {
1010- colors[i] = __builtin_bswap16 (colors[i]);
1011- }
1021+ byteSwap (colors, len); // big-to-little endian to restore pixel buffer
10121022 }
10131023
10141024 return ;
@@ -1031,9 +1041,9 @@ void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
10311041 // bytes from the 'colors' array passed into a DMA working
10321042 // buffer. This can take place while the prior DMA transfer
10331043 // is in progress, hence the need for two pixelBufs.
1034- for ( int i = 0 ; i < count; i++) {
1035- pixelBuf[pixelBufIdx][i] = __builtin_bswap16 (*colors++) ;
1036- }
1044+ swapBytes (colors, count, pixelBuf[pixelBufIdx]);
1045+ colors += count ;
1046+
10371047 // The transfers themselves are relatively small, so we don't
10381048 // need a long descriptor list. We just alternate between the
10391049 // first two, sharing pixelBufIdx for that purpose.
@@ -1106,8 +1116,22 @@ void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
11061116
11071117 // All other cases (bitbang SPI or non-DMA hard SPI or parallel),
11081118 // use a loop with the normal 16-bit data write function:
1109- while (len--) {
1110- SPI_WRITE16 (*colors++);
1119+
1120+ if (!bigEndian) {
1121+ while (len--) {
1122+ SPI_WRITE16 (*colors++);
1123+ }
1124+ } else {
1125+ // Well this is awkward. SPI_WRITE16() was designed for little-endian
1126+ // hosts and big-endian displays as that's nearly always the typical
1127+ // case. If the bigEndian flag was set, data is already in display's
1128+ // order...so each pixel needs byte-swapping before being issued.
1129+ // Rather than having a separate big-endian SPI_WRITE16 (adding more
1130+ // bloat), it's preferred if calling function is smart and only uses
1131+ // bigEndian where DMA is supported. But we gotta handle this...
1132+ while (len--) {
1133+ SPI_WRITE16 (__builtin_bswap16 (*colors++));
1134+ }
11111135 }
11121136}
11131137
@@ -2362,6 +2386,7 @@ void Adafruit_SPITFT::SPI_WRITE16(uint16_t w) {
23622386#elif defined(ESP8266) || defined(ESP32)
23632387 hwspi._spi ->write16 (w);
23642388#else
2389+ // MSB, LSB because TFTs are generally big-endian
23652390 hwspi._spi ->transfer (w >> 8 );
23662391 hwspi._spi ->transfer (w);
23672392#endif
0 commit comments