@@ -949,6 +949,24 @@ void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
949
949
}
950
950
}
951
951
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
+
952
970
/* !
953
971
@brief Issue a series of pixels from memory to the display. Not self-
954
972
contained; should follow startWrite() and setAddrWindow() calls.
@@ -963,19 +981,16 @@ void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
963
981
doing ANY other display-related activities (or even
964
982
any SPI-related activities, if using an SPI display
965
983
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.
979
994
*/
980
995
void Adafruit_SPITFT::writePixels (uint16_t *colors, uint32_t len, bool block,
981
996
bool bigEndian) {
@@ -987,28 +1002,23 @@ void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
987
1002
(void )block;
988
1003
(void )bigEndian;
989
1004
990
- #if defined(ESP32) // ESP32 has a special SPI pixel-writing function...
1005
+ #if defined(ESP32)
991
1006
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
+ }
993
1012
return ;
994
1013
}
995
1014
#elif defined(ARDUINO_NRF52_ADAFRUIT) && \
996
1015
defined (NRF52840_XXAA) // Adafruit nRF52 use SPIM3 DMA at 32Mhz
997
- // TFT and SPI DMA endian is different we need to swap bytes
998
1016
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
1002
1018
}
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
1008
1020
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
1012
1022
}
1013
1023
1014
1024
return ;
@@ -1031,9 +1041,9 @@ void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
1031
1041
// bytes from the 'colors' array passed into a DMA working
1032
1042
// buffer. This can take place while the prior DMA transfer
1033
1043
// 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
+
1037
1047
// The transfers themselves are relatively small, so we don't
1038
1048
// need a long descriptor list. We just alternate between the
1039
1049
// first two, sharing pixelBufIdx for that purpose.
@@ -1106,8 +1116,22 @@ void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
1106
1116
1107
1117
// All other cases (bitbang SPI or non-DMA hard SPI or parallel),
1108
1118
// 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
+ }
1111
1135
}
1112
1136
}
1113
1137
@@ -2362,6 +2386,7 @@ void Adafruit_SPITFT::SPI_WRITE16(uint16_t w) {
2362
2386
#elif defined(ESP8266) || defined(ESP32)
2363
2387
hwspi._spi ->write16 (w);
2364
2388
#else
2389
+ // MSB, LSB because TFTs are generally big-endian
2365
2390
hwspi._spi ->transfer (w >> 8 );
2366
2391
hwspi._spi ->transfer (w);
2367
2392
#endif
0 commit comments