Adafruit_SPITFT.cpp 97 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621
  1. /*!
  2. * @file Adafruit_SPITFT.cpp
  3. *
  4. * @mainpage Adafruit SPI TFT Displays (and some others)
  5. *
  6. * @section intro_sec Introduction
  7. *
  8. * Part of Adafruit's GFX graphics library. Originally this class was
  9. * written to handle a range of color TFT displays connected via SPI,
  10. * but over time this library and some display-specific subclasses have
  11. * mutated to include some color OLEDs as well as parallel-interfaced
  12. * displays. The name's been kept for the sake of older code.
  13. *
  14. * Adafruit invests time and resources providing this open source code,
  15. * please support Adafruit and open-source hardware by purchasing
  16. * products from Adafruit!
  17. * @section dependencies Dependencies
  18. *
  19. * This library depends on
  20. * <a href="https://github.com/adafruit/Adafruit-GFX-Library">Adafruit_GFX</a>
  21. * being present on your system. Please make sure you have installed the latest
  22. * version before using this library.
  23. *
  24. * @section author Author
  25. *
  26. * Written by Limor "ladyada" Fried for Adafruit Industries,
  27. * with contributions from the open source community.
  28. *
  29. * @section license License
  30. *
  31. * BSD license, all text here must be included in any redistribution.
  32. */
  33. // Not for ATtiny, at all
  34. #if !defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny84__)
  35. #include "Adafruit_SPITFT.h"
  36. #if defined(__AVR__)
  37. #if defined(__AVR_XMEGA__) // only tested with __AVR_ATmega4809__
  38. #define AVR_WRITESPI(x) \
  39. for (SPI0_DATA = (x); (!(SPI0_INTFLAGS & _BV(SPI_IF_bp)));)
  40. #elif defined(__LGT8F__)
  41. #define AVR_WRITESPI(x) \
  42. SPDR = (x); \
  43. asm volatile("nop"); \
  44. while ((SPFR & _BV(RDEMPT))) \
  45. ; \
  46. SPFR = _BV(RDEMPT) | _BV(WREMPT)
  47. #else
  48. #define AVR_WRITESPI(x) for (SPDR = (x); (!(SPSR & _BV(SPIF)));)
  49. #endif
  50. #endif
  51. #if defined(PORT_IOBUS)
  52. // On SAMD21, redefine digitalPinToPort() to use the slightly-faster
  53. // PORT_IOBUS rather than PORT (not needed on SAMD51).
  54. #undef digitalPinToPort
  55. #define digitalPinToPort(P) (&(PORT_IOBUS->Group[g_APinDescription[P].ulPort]))
  56. #endif // end PORT_IOBUS
  57. #if defined(USE_SPI_DMA) && (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
  58. // #pragma message ("GFX DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
  59. #include "wiring_private.h" // pinPeripheral() function
  60. #include <Adafruit_ZeroDMA.h>
  61. #include <malloc.h> // memalign() function
  62. #define tcNum 2 // Timer/Counter for parallel write strobe PWM
  63. #define wrPeripheral PIO_CCL // Use CCL to invert write strobe
  64. // DMA transfer-in-progress indicator and callback
  65. static volatile bool dma_busy = false;
  66. static void dma_callback(Adafruit_ZeroDMA *dma) { dma_busy = false; }
  67. #if defined(__SAMD51__)
  68. // Timer/counter info by index #
  69. static const struct {
  70. Tc *tc; // -> Timer/Counter base address
  71. int gclk; // GCLK ID
  72. int evu; // EVSYS user ID
  73. } tcList[] = {{TC0, TC0_GCLK_ID, EVSYS_ID_USER_TC0_EVU},
  74. {TC1, TC1_GCLK_ID, EVSYS_ID_USER_TC1_EVU},
  75. {TC2, TC2_GCLK_ID, EVSYS_ID_USER_TC2_EVU},
  76. {TC3, TC3_GCLK_ID, EVSYS_ID_USER_TC3_EVU},
  77. #if defined(TC4)
  78. {TC4, TC4_GCLK_ID, EVSYS_ID_USER_TC4_EVU},
  79. #endif
  80. #if defined(TC5)
  81. {TC5, TC5_GCLK_ID, EVSYS_ID_USER_TC5_EVU},
  82. #endif
  83. #if defined(TC6)
  84. {TC6, TC6_GCLK_ID, EVSYS_ID_USER_TC6_EVU},
  85. #endif
  86. #if defined(TC7)
  87. {TC7, TC7_GCLK_ID, EVSYS_ID_USER_TC7_EVU}
  88. #endif
  89. };
  90. #define NUM_TIMERS (sizeof tcList / sizeof tcList[0]) ///< # timer/counters
  91. #endif // end __SAMD51__
  92. #endif // end USE_SPI_DMA
  93. // Possible values for Adafruit_SPITFT.connection:
  94. #define TFT_HARD_SPI 0 ///< Display interface = hardware SPI
  95. #define TFT_SOFT_SPI 1 ///< Display interface = software SPI
  96. #define TFT_PARALLEL 2 ///< Display interface = 8- or 16-bit parallel
  97. // CONSTRUCTORS ------------------------------------------------------------
  98. /*!
  99. @brief Adafruit_SPITFT constructor for software (bitbang) SPI.
  100. @param w Display width in pixels at default rotation setting (0).
  101. @param h Display height in pixels at default rotation setting (0).
  102. @param cs Arduino pin # for chip-select (-1 if unused, tie CS low).
  103. @param dc Arduino pin # for data/command select (required).
  104. @param mosi Arduino pin # for bitbang SPI MOSI signal (required).
  105. @param sck Arduino pin # for bitbang SPI SCK signal (required).
  106. @param rst Arduino pin # for display reset (optional, display reset
  107. can be tied to MCU reset, default of -1 means unused).
  108. @param miso Arduino pin # for bitbang SPI MISO signal (optional,
  109. -1 default, many displays don't support SPI read).
  110. @note Output pins are not initialized; application typically will
  111. need to call subclass' begin() function, which in turn calls
  112. this library's initSPI() function to initialize pins.
  113. */
  114. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t cs, int8_t dc,
  115. int8_t mosi, int8_t sck, int8_t rst,
  116. int8_t miso)
  117. : Adafruit_GFX(w, h), connection(TFT_SOFT_SPI), _rst(rst), _cs(cs),
  118. _dc(dc) {
  119. swspi._sck = sck;
  120. swspi._mosi = mosi;
  121. swspi._miso = miso;
  122. #if defined(USE_FAST_PINIO)
  123. #if defined(HAS_PORT_SET_CLR)
  124. #if defined(CORE_TEENSY)
  125. #if !defined(KINETISK)
  126. dcPinMask = digitalPinToBitMask(dc);
  127. swspi.sckPinMask = digitalPinToBitMask(sck);
  128. swspi.mosiPinMask = digitalPinToBitMask(mosi);
  129. #endif
  130. dcPortSet = portSetRegister(dc);
  131. dcPortClr = portClearRegister(dc);
  132. swspi.sckPortSet = portSetRegister(sck);
  133. swspi.sckPortClr = portClearRegister(sck);
  134. swspi.mosiPortSet = portSetRegister(mosi);
  135. swspi.mosiPortClr = portClearRegister(mosi);
  136. if (cs >= 0) {
  137. #if !defined(KINETISK)
  138. csPinMask = digitalPinToBitMask(cs);
  139. #endif
  140. csPortSet = portSetRegister(cs);
  141. csPortClr = portClearRegister(cs);
  142. } else {
  143. #if !defined(KINETISK)
  144. csPinMask = 0;
  145. #endif
  146. csPortSet = dcPortSet;
  147. csPortClr = dcPortClr;
  148. }
  149. if (miso >= 0) {
  150. swspi.misoPort = portInputRegister(miso);
  151. #if !defined(KINETISK)
  152. swspi.misoPinMask = digitalPinToBitMask(miso);
  153. #endif
  154. } else {
  155. swspi.misoPort = portInputRegister(dc);
  156. }
  157. #else // !CORE_TEENSY
  158. dcPinMask = digitalPinToBitMask(dc);
  159. swspi.sckPinMask = digitalPinToBitMask(sck);
  160. swspi.mosiPinMask = digitalPinToBitMask(mosi);
  161. dcPortSet = &(PORT->Group[g_APinDescription[dc].ulPort].OUTSET.reg);
  162. dcPortClr = &(PORT->Group[g_APinDescription[dc].ulPort].OUTCLR.reg);
  163. swspi.sckPortSet = &(PORT->Group[g_APinDescription[sck].ulPort].OUTSET.reg);
  164. swspi.sckPortClr = &(PORT->Group[g_APinDescription[sck].ulPort].OUTCLR.reg);
  165. swspi.mosiPortSet = &(PORT->Group[g_APinDescription[mosi].ulPort].OUTSET.reg);
  166. swspi.mosiPortClr = &(PORT->Group[g_APinDescription[mosi].ulPort].OUTCLR.reg);
  167. if (cs >= 0) {
  168. csPinMask = digitalPinToBitMask(cs);
  169. csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
  170. csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
  171. } else {
  172. // No chip-select line defined; might be permanently tied to GND.
  173. // Assign a valid GPIO register (though not used for CS), and an
  174. // empty pin bitmask...the nonsense bit-twiddling might be faster
  175. // than checking _cs and possibly branching.
  176. csPortSet = dcPortSet;
  177. csPortClr = dcPortClr;
  178. csPinMask = 0;
  179. }
  180. if (miso >= 0) {
  181. swspi.misoPinMask = digitalPinToBitMask(miso);
  182. swspi.misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(miso));
  183. } else {
  184. swspi.misoPinMask = 0;
  185. swspi.misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(dc));
  186. }
  187. #endif // end !CORE_TEENSY
  188. #else // !HAS_PORT_SET_CLR
  189. dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(dc));
  190. dcPinMaskSet = digitalPinToBitMask(dc);
  191. swspi.sckPort = (PORTreg_t)portOutputRegister(digitalPinToPort(sck));
  192. swspi.sckPinMaskSet = digitalPinToBitMask(sck);
  193. swspi.mosiPort = (PORTreg_t)portOutputRegister(digitalPinToPort(mosi));
  194. swspi.mosiPinMaskSet = digitalPinToBitMask(mosi);
  195. if (cs >= 0) {
  196. csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(cs));
  197. csPinMaskSet = digitalPinToBitMask(cs);
  198. } else {
  199. // No chip-select line defined; might be permanently tied to GND.
  200. // Assign a valid GPIO register (though not used for CS), and an
  201. // empty pin bitmask...the nonsense bit-twiddling might be faster
  202. // than checking _cs and possibly branching.
  203. csPort = dcPort;
  204. csPinMaskSet = 0;
  205. }
  206. if (miso >= 0) {
  207. swspi.misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(miso));
  208. swspi.misoPinMask = digitalPinToBitMask(miso);
  209. } else {
  210. swspi.misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(dc));
  211. swspi.misoPinMask = 0;
  212. }
  213. csPinMaskClr = ~csPinMaskSet;
  214. dcPinMaskClr = ~dcPinMaskSet;
  215. swspi.sckPinMaskClr = ~swspi.sckPinMaskSet;
  216. swspi.mosiPinMaskClr = ~swspi.mosiPinMaskSet;
  217. #endif // !end HAS_PORT_SET_CLR
  218. #endif // end USE_FAST_PINIO
  219. }
  220. /*!
  221. @brief Adafruit_SPITFT constructor for hardware SPI using the board's
  222. default SPI peripheral.
  223. @param w Display width in pixels at default rotation setting (0).
  224. @param h Display height in pixels at default rotation setting (0).
  225. @param cs Arduino pin # for chip-select (-1 if unused, tie CS low).
  226. @param dc Arduino pin # for data/command select (required).
  227. @param rst Arduino pin # for display reset (optional, display reset
  228. can be tied to MCU reset, default of -1 means unused).
  229. @note Output pins are not initialized; application typically will
  230. need to call subclass' begin() function, which in turn calls
  231. this library's initSPI() function to initialize pins.
  232. */
  233. #if defined(ESP8266) // See notes below
  234. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t cs, int8_t dc,
  235. int8_t rst)
  236. : Adafruit_GFX(w, h), connection(TFT_HARD_SPI), _rst(rst), _cs(cs),
  237. _dc(dc) {
  238. hwspi._spi = &SPI;
  239. }
  240. #else // !ESP8266
  241. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t cs, int8_t dc,
  242. int8_t rst)
  243. : Adafruit_SPITFT(w, h, &SPI, cs, dc, rst) {
  244. // This just invokes the hardware SPI constructor below,
  245. // passing the default SPI device (&SPI).
  246. }
  247. #endif // end !ESP8266
  248. #if !defined(ESP8266)
  249. // ESP8266 compiler freaks out at this constructor -- it can't disambiguate
  250. // beteween the SPIClass pointer (argument #3) and a regular integer.
  251. // Solution here it to just not offer this variant on the ESP8266. You can
  252. // use the default hardware SPI peripheral, or you can use software SPI,
  253. // but if there's any library out there that creates a 'virtual' SPIClass
  254. // peripheral and drives it with software bitbanging, that's not supported.
  255. /*!
  256. @brief Adafruit_SPITFT constructor for hardware SPI using a specific
  257. SPI peripheral.
  258. @param w Display width in pixels at default rotation (0).
  259. @param h Display height in pixels at default rotation (0).
  260. @param spiClass Pointer to SPIClass type (e.g. &SPI or &SPI1).
  261. @param cs Arduino pin # for chip-select (-1 if unused, tie CS low).
  262. @param dc Arduino pin # for data/command select (required).
  263. @param rst Arduino pin # for display reset (optional, display reset
  264. can be tied to MCU reset, default of -1 means unused).
  265. @note Output pins are not initialized in constructor; application
  266. typically will need to call subclass' begin() function, which
  267. in turn calls this library's initSPI() function to initialize
  268. pins. EXCEPT...if you have built your own SERCOM SPI peripheral
  269. (calling the SPIClass constructor) rather than one of the
  270. built-in SPI devices (e.g. &SPI, &SPI1 and so forth), you will
  271. need to call the begin() function for your object as well as
  272. pinPeripheral() for the MOSI, MISO and SCK pins to configure
  273. GPIO manually. Do this BEFORE calling the display-specific
  274. begin or init function. Unfortunate but unavoidable.
  275. */
  276. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, SPIClass *spiClass,
  277. int8_t cs, int8_t dc, int8_t rst)
  278. : Adafruit_GFX(w, h), connection(TFT_HARD_SPI), _rst(rst), _cs(cs),
  279. _dc(dc) {
  280. hwspi._spi = spiClass;
  281. #if defined(USE_FAST_PINIO)
  282. #if defined(HAS_PORT_SET_CLR)
  283. #if defined(CORE_TEENSY)
  284. #if !defined(KINETISK)
  285. dcPinMask = digitalPinToBitMask(dc);
  286. #endif
  287. dcPortSet = portSetRegister(dc);
  288. dcPortClr = portClearRegister(dc);
  289. if (cs >= 0) {
  290. #if !defined(KINETISK)
  291. csPinMask = digitalPinToBitMask(cs);
  292. #endif
  293. csPortSet = portSetRegister(cs);
  294. csPortClr = portClearRegister(cs);
  295. } else { // see comments below
  296. #if !defined(KINETISK)
  297. csPinMask = 0;
  298. #endif
  299. csPortSet = dcPortSet;
  300. csPortClr = dcPortClr;
  301. }
  302. #else // !CORE_TEENSY
  303. dcPinMask = digitalPinToBitMask(dc);
  304. dcPortSet = &(PORT->Group[g_APinDescription[dc].ulPort].OUTSET.reg);
  305. dcPortClr = &(PORT->Group[g_APinDescription[dc].ulPort].OUTCLR.reg);
  306. if (cs >= 0) {
  307. csPinMask = digitalPinToBitMask(cs);
  308. csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
  309. csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
  310. } else {
  311. // No chip-select line defined; might be permanently tied to GND.
  312. // Assign a valid GPIO register (though not used for CS), and an
  313. // empty pin bitmask...the nonsense bit-twiddling might be faster
  314. // than checking _cs and possibly branching.
  315. csPortSet = dcPortSet;
  316. csPortClr = dcPortClr;
  317. csPinMask = 0;
  318. }
  319. #endif // end !CORE_TEENSY
  320. #else // !HAS_PORT_SET_CLR
  321. dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(dc));
  322. dcPinMaskSet = digitalPinToBitMask(dc);
  323. if (cs >= 0) {
  324. csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(cs));
  325. csPinMaskSet = digitalPinToBitMask(cs);
  326. } else {
  327. // No chip-select line defined; might be permanently tied to GND.
  328. // Assign a valid GPIO register (though not used for CS), and an
  329. // empty pin bitmask...the nonsense bit-twiddling might be faster
  330. // than checking _cs and possibly branching.
  331. csPort = dcPort;
  332. csPinMaskSet = 0;
  333. }
  334. csPinMaskClr = ~csPinMaskSet;
  335. dcPinMaskClr = ~dcPinMaskSet;
  336. #endif // end !HAS_PORT_SET_CLR
  337. #endif // end USE_FAST_PINIO
  338. }
  339. #endif // end !ESP8266
  340. /*!
  341. @brief Adafruit_SPITFT constructor for parallel display connection.
  342. @param w Display width in pixels at default rotation (0).
  343. @param h Display height in pixels at default rotation (0).
  344. @param busWidth If tft16 (enumeration in header file), is a 16-bit
  345. parallel connection, else 8-bit.
  346. 16-bit isn't fully implemented or tested yet so
  347. applications should pass "tft8bitbus" for now...needed to
  348. stick a required enum argument in there to
  349. disambiguate this constructor from the soft-SPI case.
  350. Argument is ignored on 8-bit architectures (no 'wide'
  351. support there since PORTs are 8 bits anyway).
  352. @param d0 Arduino pin # for data bit 0 (1+ are extrapolated).
  353. The 8 (or 16) data bits MUST be contiguous and byte-
  354. aligned (or word-aligned for wide interface) within
  355. the same PORT register (might not correspond to
  356. Arduino pin sequence).
  357. @param wr Arduino pin # for write strobe (required).
  358. @param dc Arduino pin # for data/command select (required).
  359. @param cs Arduino pin # for chip-select (optional, -1 if unused,
  360. tie CS low).
  361. @param rst Arduino pin # for display reset (optional, display reset
  362. can be tied to MCU reset, default of -1 means unused).
  363. @param rd Arduino pin # for read strobe (optional, -1 if unused).
  364. @note Output pins are not initialized; application typically will need
  365. to call subclass' begin() function, which in turn calls this
  366. library's initSPI() function to initialize pins.
  367. Yes, the name is a misnomer...this library originally handled
  368. only SPI displays, parallel being a recent addition (but not
  369. wanting to break existing code).
  370. */
  371. Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h, tftBusWidth busWidth,
  372. int8_t d0, int8_t wr, int8_t dc, int8_t cs,
  373. int8_t rst, int8_t rd)
  374. : Adafruit_GFX(w, h), connection(TFT_PARALLEL), _rst(rst), _cs(cs),
  375. _dc(dc) {
  376. tft8._d0 = d0;
  377. tft8._wr = wr;
  378. tft8._rd = rd;
  379. tft8.wide = (busWidth == tft16bitbus);
  380. #if defined(USE_FAST_PINIO)
  381. #if defined(HAS_PORT_SET_CLR)
  382. #if defined(CORE_TEENSY)
  383. tft8.wrPortSet = portSetRegister(wr);
  384. tft8.wrPortClr = portClearRegister(wr);
  385. #if !defined(KINETISK)
  386. dcPinMask = digitalPinToBitMask(dc);
  387. #endif
  388. dcPortSet = portSetRegister(dc);
  389. dcPortClr = portClearRegister(dc);
  390. if (cs >= 0) {
  391. #if !defined(KINETISK)
  392. csPinMask = digitalPinToBitMask(cs);
  393. #endif
  394. csPortSet = portSetRegister(cs);
  395. csPortClr = portClearRegister(cs);
  396. } else { // see comments below
  397. #if !defined(KINETISK)
  398. csPinMask = 0;
  399. #endif
  400. csPortSet = dcPortSet;
  401. csPortClr = dcPortClr;
  402. }
  403. if (rd >= 0) { // if read-strobe pin specified...
  404. #if defined(KINETISK)
  405. tft8.rdPinMask = 1;
  406. #else // !KINETISK
  407. tft8.rdPinMask = digitalPinToBitMask(rd);
  408. #endif
  409. tft8.rdPortSet = portSetRegister(rd);
  410. tft8.rdPortClr = portClearRegister(rd);
  411. } else {
  412. tft8.rdPinMask = 0;
  413. tft8.rdPortSet = dcPortSet;
  414. tft8.rdPortClr = dcPortClr;
  415. }
  416. // These are all uint8_t* pointers -- elsewhere they're recast
  417. // as necessary if a 'wide' 16-bit interface is in use.
  418. tft8.writePort = portOutputRegister(d0);
  419. tft8.readPort = portInputRegister(d0);
  420. tft8.dirSet = portModeRegister(d0);
  421. tft8.dirClr = portModeRegister(d0);
  422. #else // !CORE_TEENSY
  423. tft8.wrPinMask = digitalPinToBitMask(wr);
  424. tft8.wrPortSet = &(PORT->Group[g_APinDescription[wr].ulPort].OUTSET.reg);
  425. tft8.wrPortClr = &(PORT->Group[g_APinDescription[wr].ulPort].OUTCLR.reg);
  426. dcPinMask = digitalPinToBitMask(dc);
  427. dcPortSet = &(PORT->Group[g_APinDescription[dc].ulPort].OUTSET.reg);
  428. dcPortClr = &(PORT->Group[g_APinDescription[dc].ulPort].OUTCLR.reg);
  429. if (cs >= 0) {
  430. csPinMask = digitalPinToBitMask(cs);
  431. csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
  432. csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
  433. } else {
  434. // No chip-select line defined; might be permanently tied to GND.
  435. // Assign a valid GPIO register (though not used for CS), and an
  436. // empty pin bitmask...the nonsense bit-twiddling might be faster
  437. // than checking _cs and possibly branching.
  438. csPortSet = dcPortSet;
  439. csPortClr = dcPortClr;
  440. csPinMask = 0;
  441. }
  442. if (rd >= 0) { // if read-strobe pin specified...
  443. tft8.rdPinMask = digitalPinToBitMask(rd);
  444. tft8.rdPortSet = &(PORT->Group[g_APinDescription[rd].ulPort].OUTSET.reg);
  445. tft8.rdPortClr = &(PORT->Group[g_APinDescription[rd].ulPort].OUTCLR.reg);
  446. } else {
  447. tft8.rdPinMask = 0;
  448. tft8.rdPortSet = dcPortSet;
  449. tft8.rdPortClr = dcPortClr;
  450. }
  451. // Get pointers to PORT write/read/dir bytes within 32-bit PORT
  452. uint8_t dBit = g_APinDescription[d0].ulPin; // d0 bit # in PORT
  453. PortGroup *p = (&(PORT->Group[g_APinDescription[d0].ulPort]));
  454. uint8_t offset = dBit / 8; // d[7:0] byte # within PORT
  455. if (tft8.wide)
  456. offset &= ~1; // d[15:8] byte # within PORT
  457. // These are all uint8_t* pointers -- elsewhere they're recast
  458. // as necessary if a 'wide' 16-bit interface is in use.
  459. tft8.writePort = (volatile uint8_t *)&(p->OUT.reg) + offset;
  460. tft8.readPort = (volatile uint8_t *)&(p->IN.reg) + offset;
  461. tft8.dirSet = (volatile uint8_t *)&(p->DIRSET.reg) + offset;
  462. tft8.dirClr = (volatile uint8_t *)&(p->DIRCLR.reg) + offset;
  463. #endif // end !CORE_TEENSY
  464. #else // !HAS_PORT_SET_CLR
  465. tft8.wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(wr));
  466. tft8.wrPinMaskSet = digitalPinToBitMask(wr);
  467. dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(dc));
  468. dcPinMaskSet = digitalPinToBitMask(dc);
  469. if (cs >= 0) {
  470. csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(cs));
  471. csPinMaskSet = digitalPinToBitMask(cs);
  472. } else {
  473. // No chip-select line defined; might be permanently tied to GND.
  474. // Assign a valid GPIO register (though not used for CS), and an
  475. // empty pin bitmask...the nonsense bit-twiddling might be faster
  476. // than checking _cs and possibly branching.
  477. csPort = dcPort;
  478. csPinMaskSet = 0;
  479. }
  480. if (rd >= 0) { // if read-strobe pin specified...
  481. tft8.rdPort = (PORTreg_t)portOutputRegister(digitalPinToPort(rd));
  482. tft8.rdPinMaskSet = digitalPinToBitMask(rd);
  483. } else {
  484. tft8.rdPort = dcPort;
  485. tft8.rdPinMaskSet = 0;
  486. }
  487. csPinMaskClr = ~csPinMaskSet;
  488. dcPinMaskClr = ~dcPinMaskSet;
  489. tft8.wrPinMaskClr = ~tft8.wrPinMaskSet;
  490. tft8.rdPinMaskClr = ~tft8.rdPinMaskSet;
  491. tft8.writePort = (PORTreg_t)portOutputRegister(digitalPinToPort(d0));
  492. tft8.readPort = (PORTreg_t)portInputRegister(digitalPinToPort(d0));
  493. tft8.portDir = (PORTreg_t)portModeRegister(digitalPinToPort(d0));
  494. #endif // end !HAS_PORT_SET_CLR
  495. #endif // end USE_FAST_PINIO
  496. }
  497. // end constructors -------
  498. // CLASS MEMBER FUNCTIONS --------------------------------------------------
  499. // begin() and setAddrWindow() MUST be declared by any subclass.
  500. /*!
  501. @brief Configure microcontroller pins for TFT interfacing. Typically
  502. called by a subclass' begin() function.
  503. @param freq SPI frequency when using hardware SPI. If default (0)
  504. is passed, will fall back on a device-specific value.
  505. Value is ignored when using software SPI or parallel
  506. connection.
  507. @param spiMode SPI mode when using hardware SPI. MUST be one of the
  508. values SPI_MODE0, SPI_MODE1, SPI_MODE2 or SPI_MODE3
  509. defined in SPI.h. Do NOT attempt to pass '0' for
  510. SPI_MODE0 and so forth...the values are NOT the same!
  511. Use ONLY the defines! (Pity it's not an enum.)
  512. @note Another anachronistically-named function; this is called even
  513. when the display connection is parallel (not SPI). Also, this
  514. could probably be made private...quite a few class functions
  515. were generously put in the public section.
  516. */
  517. void Adafruit_SPITFT::initSPI(uint32_t freq, uint8_t spiMode) {
  518. if (!freq)
  519. freq = DEFAULT_SPI_FREQ; // If no freq specified, use default
  520. // Init basic control pins common to all connection types
  521. if (_cs >= 0) {
  522. pinMode(_cs, OUTPUT);
  523. digitalWrite(_cs, HIGH); // Deselect
  524. }
  525. pinMode(_dc, OUTPUT);
  526. digitalWrite(_dc, HIGH); // Data mode
  527. if (connection == TFT_HARD_SPI) {
  528. #if defined(SPI_HAS_TRANSACTION)
  529. hwspi.settings = SPISettings(freq, MSBFIRST, spiMode);
  530. #else
  531. hwspi._freq = freq; // Save freq value for later
  532. #endif
  533. hwspi._mode = spiMode; // Save spiMode value for later
  534. // Call hwspi._spi->begin() ONLY if this is among the 'established'
  535. // SPI interfaces in variant.h. For DIY roll-your-own SERCOM SPIs,
  536. // begin() and pinPeripheral() calls MUST be made in one's calling
  537. // code, BEFORE the screen-specific begin/init function is called.
  538. // Reason for this is that SPI::begin() makes its own calls to
  539. // pinPeripheral() based on g_APinDescription[n].ulPinType, which
  540. // on non-established SPI interface pins will always be PIO_DIGITAL
  541. // or similar, while we need PIO_SERCOM or PIO_SERCOM_ALT...it's
  542. // highly unique between devices and variants for each pin or
  543. // SERCOM so we can't make those calls ourselves here. And the SPI
  544. // device needs to be set up before calling this because it's
  545. // immediately followed with initialization commands. Blargh.
  546. if (
  547. #if !defined(SPI_INTERFACES_COUNT)
  548. 1
  549. #else
  550. #if SPI_INTERFACES_COUNT > 0
  551. (hwspi._spi == &SPI)
  552. #endif
  553. #if SPI_INTERFACES_COUNT > 1
  554. || (hwspi._spi == &SPI1)
  555. #endif
  556. #if SPI_INTERFACES_COUNT > 2
  557. || (hwspi._spi == &SPI2)
  558. #endif
  559. #if SPI_INTERFACES_COUNT > 3
  560. || (hwspi._spi == &SPI3)
  561. #endif
  562. #if SPI_INTERFACES_COUNT > 4
  563. || (hwspi._spi == &SPI4)
  564. #endif
  565. #if SPI_INTERFACES_COUNT > 5
  566. || (hwspi._spi == &SPI5)
  567. #endif
  568. #endif // end SPI_INTERFACES_COUNT
  569. ) {
  570. hwspi._spi->begin();
  571. }
  572. } else if (connection == TFT_SOFT_SPI) {
  573. pinMode(swspi._mosi, OUTPUT);
  574. digitalWrite(swspi._mosi, LOW);
  575. pinMode(swspi._sck, OUTPUT);
  576. digitalWrite(swspi._sck, LOW);
  577. if (swspi._miso >= 0) {
  578. pinMode(swspi._miso, INPUT);
  579. }
  580. } else { // TFT_PARALLEL
  581. // Initialize data pins. We were only passed d0, so scan
  582. // the pin description list looking for the other pins.
  583. // They'll be on the same PORT, and within the next 7 (or 15) bits
  584. // (because we need to write to a contiguous PORT byte or word).
  585. #if defined(__AVR__)
  586. // PORT registers are 8 bits wide, so just need a register match...
  587. for (uint8_t i = 0; i < NUM_DIGITAL_PINS; i++) {
  588. if ((PORTreg_t)portOutputRegister(digitalPinToPort(i)) ==
  589. tft8.writePort) {
  590. pinMode(i, OUTPUT);
  591. digitalWrite(i, LOW);
  592. }
  593. }
  594. #elif defined(USE_FAST_PINIO)
  595. #if defined(CORE_TEENSY)
  596. if (!tft8.wide) {
  597. *tft8.dirSet = 0xFF; // Set port to output
  598. *tft8.writePort = 0x00; // Write all 0s
  599. } else {
  600. *(volatile uint16_t *)tft8.dirSet = 0xFFFF;
  601. *(volatile uint16_t *)tft8.writePort = 0x0000;
  602. }
  603. #else // !CORE_TEENSY
  604. uint8_t portNum = g_APinDescription[tft8._d0].ulPort, // d0 PORT #
  605. dBit = g_APinDescription[tft8._d0].ulPin, // d0 bit in PORT
  606. lastBit = dBit + (tft8.wide ? 15 : 7);
  607. for (uint8_t i = 0; i < PINS_COUNT; i++) {
  608. if ((g_APinDescription[i].ulPort == portNum) &&
  609. (g_APinDescription[i].ulPin >= dBit) &&
  610. (g_APinDescription[i].ulPin <= (uint32_t)lastBit)) {
  611. pinMode(i, OUTPUT);
  612. digitalWrite(i, LOW);
  613. }
  614. }
  615. #endif // end !CORE_TEENSY
  616. #endif
  617. pinMode(tft8._wr, OUTPUT);
  618. digitalWrite(tft8._wr, HIGH);
  619. if (tft8._rd >= 0) {
  620. pinMode(tft8._rd, OUTPUT);
  621. digitalWrite(tft8._rd, HIGH);
  622. }
  623. }
  624. if (_rst >= 0) {
  625. // Toggle _rst low to reset
  626. pinMode(_rst, OUTPUT);
  627. digitalWrite(_rst, HIGH);
  628. delay(100);
  629. digitalWrite(_rst, LOW);
  630. delay(100);
  631. digitalWrite(_rst, HIGH);
  632. delay(200);
  633. }
  634. #if defined(USE_SPI_DMA) && (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
  635. if (((connection == TFT_HARD_SPI) || (connection == TFT_PARALLEL)) &&
  636. (dma.allocate() == DMA_STATUS_OK)) { // Allocate channel
  637. // The DMA library needs to alloc at least one valid descriptor,
  638. // so we do that here. It's not used in the usual sense though,
  639. // just before a transfer we copy descriptor[0] to this address.
  640. if (dptr = dma.addDescriptor(NULL, NULL, 42, DMA_BEAT_SIZE_BYTE, false,
  641. false)) {
  642. // Alloc 2 scanlines worth of pixels on display's major axis,
  643. // whichever that is, rounding each up to 2-pixel boundary.
  644. int major = (WIDTH > HEIGHT) ? WIDTH : HEIGHT;
  645. major += (major & 1); // -> next 2-pixel bound, if needed.
  646. maxFillLen = major * 2; // 2 scanlines
  647. // Note to future self: if you decide to make the pixel buffer
  648. // much larger, remember that DMA transfer descriptors can't
  649. // exceed 65,535 bytes (not 65,536), meaning 32,767 pixels max.
  650. // Not that we have that kind of RAM to throw around right now.
  651. if ((pixelBuf[0] = (uint16_t *)malloc(maxFillLen * sizeof(uint16_t)))) {
  652. // Alloc OK. Get pointer to start of second scanline.
  653. pixelBuf[1] = &pixelBuf[0][major];
  654. // Determine number of DMA descriptors needed to cover
  655. // entire screen when entire 2-line pixelBuf is used
  656. // (round up for fractional last descriptor).
  657. int numDescriptors = (WIDTH * HEIGHT + (maxFillLen - 1)) / maxFillLen;
  658. // DMA descriptors MUST be 128-bit (16 byte) aligned.
  659. // memalign() is considered obsolete but it's replacements
  660. // (aligned_alloc() or posix_memalign()) are not currently
  661. // available in the version of ARM GCC in use, but this
  662. // is, so here we are.
  663. if ((descriptor = (DmacDescriptor *)memalign(
  664. 16, numDescriptors * sizeof(DmacDescriptor)))) {
  665. int dmac_id;
  666. volatile uint32_t *data_reg;
  667. if (connection == TFT_HARD_SPI) {
  668. // THIS IS AN AFFRONT TO NATURE, but I don't know
  669. // any "clean" way to get the sercom number from the
  670. // the SPIClass pointer (e.g. &SPI or &SPI1), which
  671. // is all we have to work with. SPIClass does contain
  672. // a SERCOM pointer but it is a PRIVATE member!
  673. // Doing an UNSPEAKABLY HORRIBLE THING here, directly
  674. // accessing the first 32-bit value in the SPIClass
  675. // structure, knowing that's (currently) where the
  676. // SERCOM pointer lives, but this ENTIRELY DEPENDS on
  677. // that structure not changing nor the compiler
  678. // rearranging things. Oh the humanity!
  679. if (*(SERCOM **)hwspi._spi == &sercom0) {
  680. dmac_id = SERCOM0_DMAC_ID_TX;
  681. data_reg = &SERCOM0->SPI.DATA.reg;
  682. #if defined SERCOM1
  683. } else if (*(SERCOM **)hwspi._spi == &sercom1) {
  684. dmac_id = SERCOM1_DMAC_ID_TX;
  685. data_reg = &SERCOM1->SPI.DATA.reg;
  686. #endif
  687. #if defined SERCOM2
  688. } else if (*(SERCOM **)hwspi._spi == &sercom2) {
  689. dmac_id = SERCOM2_DMAC_ID_TX;
  690. data_reg = &SERCOM2->SPI.DATA.reg;
  691. #endif
  692. #if defined SERCOM3
  693. } else if (*(SERCOM **)hwspi._spi == &sercom3) {
  694. dmac_id = SERCOM3_DMAC_ID_TX;
  695. data_reg = &SERCOM3->SPI.DATA.reg;
  696. #endif
  697. #if defined SERCOM4
  698. } else if (*(SERCOM **)hwspi._spi == &sercom4) {
  699. dmac_id = SERCOM4_DMAC_ID_TX;
  700. data_reg = &SERCOM4->SPI.DATA.reg;
  701. #endif
  702. #if defined SERCOM5
  703. } else if (*(SERCOM **)hwspi._spi == &sercom5) {
  704. dmac_id = SERCOM5_DMAC_ID_TX;
  705. data_reg = &SERCOM5->SPI.DATA.reg;
  706. #endif
  707. #if defined SERCOM6
  708. } else if (*(SERCOM **)hwspi._spi == &sercom6) {
  709. dmac_id = SERCOM6_DMAC_ID_TX;
  710. data_reg = &SERCOM6->SPI.DATA.reg;
  711. #endif
  712. #if defined SERCOM7
  713. } else if (*(SERCOM **)hwspi._spi == &sercom7) {
  714. dmac_id = SERCOM7_DMAC_ID_TX;
  715. data_reg = &SERCOM7->SPI.DATA.reg;
  716. #endif
  717. }
  718. dma.setPriority(DMA_PRIORITY_3);
  719. dma.setTrigger(dmac_id);
  720. dma.setAction(DMA_TRIGGER_ACTON_BEAT);
  721. // Initialize descriptor list.
  722. for (int d = 0; d < numDescriptors; d++) {
  723. // No need to set SRCADDR, DESCADDR or BTCNT --
  724. // those are done in the pixel-writing functions.
  725. descriptor[d].BTCTRL.bit.VALID = true;
  726. descriptor[d].BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_DISABLE;
  727. descriptor[d].BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_NOACT;
  728. descriptor[d].BTCTRL.bit.BEATSIZE = DMA_BEAT_SIZE_BYTE;
  729. descriptor[d].BTCTRL.bit.DSTINC = 0;
  730. descriptor[d].BTCTRL.bit.STEPSEL = DMA_STEPSEL_SRC;
  731. descriptor[d].BTCTRL.bit.STEPSIZE =
  732. DMA_ADDRESS_INCREMENT_STEP_SIZE_1;
  733. descriptor[d].DSTADDR.reg = (uint32_t)data_reg;
  734. }
  735. } else { // Parallel connection
  736. #if defined(__SAMD51__)
  737. int dmaChannel = dma.getChannel();
  738. // Enable event output, use EVOSEL output
  739. DMAC->Channel[dmaChannel].CHEVCTRL.bit.EVOE = 1;
  740. DMAC->Channel[dmaChannel].CHEVCTRL.bit.EVOMODE = 0;
  741. // CONFIGURE TIMER/COUNTER (for write strobe)
  742. Tc *timer = tcList[tcNum].tc; // -> Timer struct
  743. int id = tcList[tcNum].gclk; // Timer GCLK ID
  744. GCLK_PCHCTRL_Type pchctrl;
  745. // Set up timer clock source from GCLK
  746. GCLK->PCHCTRL[id].bit.CHEN = 0; // Stop timer
  747. while (GCLK->PCHCTRL[id].bit.CHEN)
  748. ; // Wait for it
  749. pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK0_Val;
  750. pchctrl.bit.CHEN = 1; // Enable
  751. GCLK->PCHCTRL[id].reg = pchctrl.reg;
  752. while (!GCLK->PCHCTRL[id].bit.CHEN)
  753. ; // Wait for it
  754. // Disable timer/counter before configuring it
  755. timer->COUNT8.CTRLA.bit.ENABLE = 0;
  756. while (timer->COUNT8.SYNCBUSY.bit.STATUS)
  757. ;
  758. timer->COUNT8.WAVE.bit.WAVEGEN = 2; // NPWM
  759. timer->COUNT8.CTRLA.bit.MODE = 1; // 8-bit
  760. timer->COUNT8.CTRLA.bit.PRESCALER = 0; // 1:1
  761. while (timer->COUNT8.SYNCBUSY.bit.STATUS)
  762. ;
  763. timer->COUNT8.CTRLBCLR.bit.DIR = 1; // Count UP
  764. while (timer->COUNT8.SYNCBUSY.bit.CTRLB)
  765. ;
  766. timer->COUNT8.CTRLBSET.bit.ONESHOT = 1; // One-shot
  767. while (timer->COUNT8.SYNCBUSY.bit.CTRLB)
  768. ;
  769. timer->COUNT8.PER.reg = 6; // PWM top
  770. while (timer->COUNT8.SYNCBUSY.bit.PER)
  771. ;
  772. timer->COUNT8.CC[0].reg = 2; // Compare
  773. while (timer->COUNT8.SYNCBUSY.bit.CC0)
  774. ;
  775. // Enable async input events,
  776. // event action = restart.
  777. timer->COUNT8.EVCTRL.bit.TCEI = 1;
  778. timer->COUNT8.EVCTRL.bit.EVACT = 1;
  779. // Enable timer
  780. timer->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
  781. while (timer->COUNT8.SYNCBUSY.bit.STATUS)
  782. ;
  783. #if (wrPeripheral == PIO_CCL)
  784. // CONFIGURE CCL (inverts timer/counter output)
  785. MCLK->APBCMASK.bit.CCL_ = 1; // Enable CCL clock
  786. CCL->CTRL.bit.ENABLE = 0; // Disable to config
  787. CCL->CTRL.bit.SWRST = 1; // Reset CCL registers
  788. CCL->LUTCTRL[tcNum].bit.ENABLE = 0; // Disable LUT
  789. CCL->LUTCTRL[tcNum].bit.FILTSEL = 0; // No filter
  790. CCL->LUTCTRL[tcNum].bit.INSEL0 = 6; // TC input
  791. CCL->LUTCTRL[tcNum].bit.INSEL1 = 0; // MASK
  792. CCL->LUTCTRL[tcNum].bit.INSEL2 = 0; // MASK
  793. CCL->LUTCTRL[tcNum].bit.TRUTH = 1; // Invert in 0
  794. CCL->LUTCTRL[tcNum].bit.ENABLE = 1; // Enable LUT
  795. CCL->CTRL.bit.ENABLE = 1; // Enable CCL
  796. #endif
  797. // CONFIGURE EVENT SYSTEM
  798. // Set up event system clock source from GCLK...
  799. // Disable EVSYS, wait for disable
  800. GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 0;
  801. while (GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN)
  802. ;
  803. pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK0_Val;
  804. pchctrl.bit.CHEN = 1; // Re-enable
  805. GCLK->PCHCTRL[EVSYS_GCLK_ID_0].reg = pchctrl.reg;
  806. // Wait for it, then enable EVSYS clock
  807. while (!GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN)
  808. ;
  809. MCLK->APBBMASK.bit.EVSYS_ = 1;
  810. // Connect Timer EVU to ch 0
  811. EVSYS->USER[tcList[tcNum].evu].reg = 1;
  812. // Datasheet recommends single write operation;
  813. // reg instead of bit. Also datasheet: PATH bits
  814. // must be zero when using async!
  815. EVSYS_CHANNEL_Type ev;
  816. ev.reg = 0;
  817. ev.bit.PATH = 2; // Asynchronous
  818. ev.bit.EVGEN = 0x22 + dmaChannel; // DMA channel 0+
  819. EVSYS->Channel[0].CHANNEL.reg = ev.reg;
  820. // Initialize descriptor list.
  821. for (int d = 0; d < numDescriptors; d++) {
  822. // No need to set SRCADDR, DESCADDR or BTCNT --
  823. // those are done in the pixel-writing functions.
  824. descriptor[d].BTCTRL.bit.VALID = true;
  825. // Event strobe on beat xfer:
  826. descriptor[d].BTCTRL.bit.EVOSEL = 0x3;
  827. descriptor[d].BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_NOACT;
  828. descriptor[d].BTCTRL.bit.BEATSIZE =
  829. tft8.wide ? DMA_BEAT_SIZE_HWORD : DMA_BEAT_SIZE_BYTE;
  830. descriptor[d].BTCTRL.bit.SRCINC = 1;
  831. descriptor[d].BTCTRL.bit.DSTINC = 0;
  832. descriptor[d].BTCTRL.bit.STEPSEL = DMA_STEPSEL_SRC;
  833. descriptor[d].BTCTRL.bit.STEPSIZE =
  834. DMA_ADDRESS_INCREMENT_STEP_SIZE_1;
  835. descriptor[d].DSTADDR.reg = (uint32_t)tft8.writePort;
  836. }
  837. #endif // __SAMD51
  838. } // end parallel-specific DMA setup
  839. lastFillColor = 0x0000;
  840. lastFillLen = 0;
  841. dma.setCallback(dma_callback);
  842. return; // Success!
  843. // else clean up any partial allocation...
  844. } // end descriptor memalign()
  845. free(pixelBuf[0]);
  846. pixelBuf[0] = pixelBuf[1] = NULL;
  847. } // end pixelBuf malloc()
  848. // Don't currently have a descriptor delete function in
  849. // ZeroDMA lib, but if we did, it would be called here.
  850. } // end addDescriptor()
  851. dma.free(); // Deallocate DMA channel
  852. }
  853. #endif // end USE_SPI_DMA
  854. }
  855. /*!
  856. @brief Allow changing the SPI clock speed after initialization
  857. @param freq Desired frequency of SPI clock, may not be the
  858. end frequency you get based on what the chip can do!
  859. */
  860. void Adafruit_SPITFT::setSPISpeed(uint32_t freq) {
  861. #if defined(SPI_HAS_TRANSACTION)
  862. hwspi.settings = SPISettings(freq, MSBFIRST, hwspi._mode);
  863. #else
  864. hwspi._freq = freq; // Save freq value for later
  865. #endif
  866. }
  867. /*!
  868. @brief Call before issuing command(s) or data to display. Performs
  869. chip-select (if required) and starts an SPI transaction (if
  870. using hardware SPI and transactions are supported). Required
  871. for all display types; not an SPI-specific function.
  872. */
  873. void Adafruit_SPITFT::startWrite(void) {
  874. SPI_BEGIN_TRANSACTION();
  875. if (_cs >= 0)
  876. SPI_CS_LOW();
  877. }
  878. /*!
  879. @brief Call after issuing command(s) or data to display. Performs
  880. chip-deselect (if required) and ends an SPI transaction (if
  881. using hardware SPI and transactions are supported). Required
  882. for all display types; not an SPI-specific function.
  883. */
  884. void Adafruit_SPITFT::endWrite(void) {
  885. if (_cs >= 0)
  886. SPI_CS_HIGH();
  887. SPI_END_TRANSACTION();
  888. }
  889. // -------------------------------------------------------------------------
  890. // Lower-level graphics operations. These functions require a chip-select
  891. // and/or SPI transaction around them (via startWrite(), endWrite() above).
  892. // Higher-level graphics primitives might start a single transaction and
  893. // then make multiple calls to these functions (e.g. circle or text
  894. // rendering might make repeated lines or rects) before ending the
  895. // transaction. It's more efficient than starting a transaction every time.
  896. /*!
  897. @brief Draw a single pixel to the display at requested coordinates.
  898. Not self-contained; should follow a startWrite() call.
  899. @param x Horizontal position (0 = left).
  900. @param y Vertical position (0 = top).
  901. @param color 16-bit pixel color in '565' RGB format.
  902. */
  903. void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
  904. if ((x >= 0) && (x < _width) && (y >= 0) && (y < _height)) {
  905. setAddrWindow(x, y, 1, 1);
  906. SPI_WRITE16(color);
  907. }
  908. }
  909. /*!
  910. @brief Swap bytes in an array of pixels; converts little-to-big or
  911. big-to-little endian. Used by writePixels() below in some
  912. situations, but may also be helpful for user code occasionally.
  913. @param src Source address of 16-bit pixels buffer.
  914. @param len Number of pixels to byte-swap.
  915. @param dest Optional destination address if different than src --
  916. otherwise, if NULL (default) or same address is passed,
  917. pixel buffer is overwritten in-place.
  918. */
  919. void Adafruit_SPITFT::swapBytes(uint16_t *src, uint32_t len, uint16_t *dest) {
  920. if (!dest)
  921. dest = src; // NULL -> overwrite src buffer
  922. for (uint32_t i = 0; i < len; i++) {
  923. dest[i] = __builtin_bswap16(src[i]);
  924. }
  925. }
  926. /*!
  927. @brief Issue a series of pixels from memory to the display. Not self-
  928. contained; should follow startWrite() and setAddrWindow() calls.
  929. @param colors Pointer to array of 16-bit pixel values in '565' RGB
  930. format.
  931. @param len Number of elements in 'colors' array.
  932. @param block If true (default case if unspecified), function blocks
  933. until DMA transfer is complete. This is simply IGNORED
  934. if DMA is not enabled. If false, the function returns
  935. immediately after the last DMA transfer is started,
  936. and one should use the dmaWait() function before
  937. doing ANY other display-related activities (or even
  938. any SPI-related activities, if using an SPI display
  939. that shares the bus with other devices).
  940. @param bigEndian If true, bitmap in memory is in big-endian order (most
  941. significant byte first). By default this is false, as
  942. most microcontrollers seem to be little-endian and
  943. 16-bit pixel values must be byte-swapped before
  944. issuing to the display (which tend toward big-endian
  945. when using SPI or 8-bit parallel). If an application
  946. can optimize around this -- for example, a bitmap in a
  947. uint16_t array having the byte values already ordered
  948. big-endian, this can save time here, ESPECIALLY if
  949. using this function's non-blocking DMA mode.
  950. */
  951. void Adafruit_SPITFT::writePixels(uint16_t *colors, uint32_t len, bool block,
  952. bool bigEndian) {
  953. if (!len)
  954. return; // Avoid 0-byte transfers
  955. // avoid paramater-not-used complaints
  956. (void)block;
  957. (void)bigEndian;
  958. #if defined(ESP32)
  959. if (connection == TFT_HARD_SPI) {
  960. if (!bigEndian) {
  961. hwspi._spi->writePixels(colors, len * 2); // Inbuilt endian-swap
  962. } else {
  963. hwspi._spi->writeBytes((uint8_t *)colors, len * 2); // Issue bytes direct
  964. }
  965. return;
  966. }
  967. #elif defined(ARDUINO_NRF52_ADAFRUIT) && \
  968. defined(NRF52840_XXAA) // Adafruit nRF52 use SPIM3 DMA at 32Mhz
  969. if (!bigEndian) {
  970. swapBytes(colors, len); // convert little-to-big endian for display
  971. }
  972. hwspi._spi->transfer(colors, NULL, 2 * len); // NULL RX to avoid overwrite
  973. if (!bigEndian) {
  974. swapBytes(colors, len); // big-to-little endian to restore pixel buffer
  975. }
  976. return;
  977. #elif defined(ARDUINO_ARCH_RP2040)
  978. spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;
  979. if (!bigEndian) {
  980. // switch to 16-bit writes
  981. hw_write_masked(&spi_get_hw(pi_spi)->cr0, 15 << SPI_SSPCR0_DSS_LSB,
  982. SPI_SSPCR0_DSS_BITS);
  983. spi_write16_blocking(pi_spi, colors, len);
  984. // switch back to 8-bit
  985. hw_write_masked(&spi_get_hw(pi_spi)->cr0, 7 << SPI_SSPCR0_DSS_LSB,
  986. SPI_SSPCR0_DSS_BITS);
  987. } else {
  988. spi_write_blocking(pi_spi, (uint8_t *)colors, len * 2);
  989. }
  990. return;
  991. #elif defined(ARDUINO_ARCH_RTTHREAD)
  992. if (!bigEndian) {
  993. swapBytes(colors, len); // convert little-to-big endian for display
  994. }
  995. hwspi._spi->transfer(colors, 2 * len);
  996. if (!bigEndian) {
  997. swapBytes(colors, len); // big-to-little endian to restore pixel buffer
  998. }
  999. return;
  1000. #elif defined(USE_SPI_DMA) && \
  1001. (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
  1002. if ((connection == TFT_HARD_SPI) || (connection == TFT_PARALLEL)) {
  1003. int maxSpan = maxFillLen / 2; // One scanline max
  1004. uint8_t pixelBufIdx = 0; // Active pixel buffer number
  1005. #if defined(__SAMD51__)
  1006. if (connection == TFT_PARALLEL) {
  1007. // Switch WR pin to PWM or CCL
  1008. pinPeripheral(tft8._wr, wrPeripheral);
  1009. }
  1010. #endif // end __SAMD51__
  1011. if (!bigEndian) { // Normal little-endian situation...
  1012. while (len) {
  1013. int count = (len < maxSpan) ? len : maxSpan;
  1014. // Because TFT and SAMD endianisms are different, must swap
  1015. // bytes from the 'colors' array passed into a DMA working
  1016. // buffer. This can take place while the prior DMA transfer
  1017. // is in progress, hence the need for two pixelBufs.
  1018. swapBytes(colors, count, pixelBuf[pixelBufIdx]);
  1019. colors += count;
  1020. // The transfers themselves are relatively small, so we don't
  1021. // need a long descriptor list. We just alternate between the
  1022. // first two, sharing pixelBufIdx for that purpose.
  1023. descriptor[pixelBufIdx].SRCADDR.reg =
  1024. (uint32_t)pixelBuf[pixelBufIdx] + count * 2;
  1025. descriptor[pixelBufIdx].BTCTRL.bit.SRCINC = 1;
  1026. descriptor[pixelBufIdx].BTCNT.reg = count * 2;
  1027. descriptor[pixelBufIdx].DESCADDR.reg = 0;
  1028. while (dma_busy)
  1029. ; // Wait for prior line to finish
  1030. // Move new descriptor into place...
  1031. memcpy(dptr, &descriptor[pixelBufIdx], sizeof(DmacDescriptor));
  1032. dma_busy = true;
  1033. dma.startJob(); // Trigger SPI DMA transfer
  1034. if (connection == TFT_PARALLEL)
  1035. dma.trigger();
  1036. pixelBufIdx = 1 - pixelBufIdx; // Swap DMA pixel buffers
  1037. len -= count;
  1038. }
  1039. } else { // bigEndian == true
  1040. // With big-endian pixel data, this can be handled as a single
  1041. // DMA transfer using chained descriptors. Even full screen, this
  1042. // needs only a relatively short descriptor list, each
  1043. // transferring a max of 32,767 (not 32,768) pixels. The list
  1044. // was allocated large enough to accommodate a full screen's
  1045. // worth of data, so this won't run past the end of the list.
  1046. int d, numDescriptors = (len + 32766) / 32767;
  1047. for (d = 0; d < numDescriptors; d++) {
  1048. int count = (len < 32767) ? len : 32767;
  1049. descriptor[d].SRCADDR.reg = (uint32_t)colors + count * 2;
  1050. descriptor[d].BTCTRL.bit.SRCINC = 1;
  1051. descriptor[d].BTCNT.reg = count * 2;
  1052. descriptor[d].DESCADDR.reg = (uint32_t)&descriptor[d + 1];
  1053. len -= count;
  1054. colors += count;
  1055. }
  1056. descriptor[d - 1].DESCADDR.reg = 0;
  1057. while (dma_busy)
  1058. ; // Wait for prior transfer (if any) to finish
  1059. // Move first descriptor into place and start transfer...
  1060. memcpy(dptr, &descriptor[0], sizeof(DmacDescriptor));
  1061. dma_busy = true;
  1062. dma.startJob(); // Trigger SPI DMA transfer
  1063. if (connection == TFT_PARALLEL)
  1064. dma.trigger();
  1065. } // end bigEndian
  1066. lastFillColor = 0x0000; // pixelBuf has been sullied
  1067. lastFillLen = 0;
  1068. if (block) {
  1069. while (dma_busy)
  1070. ; // Wait for last line to complete
  1071. #if defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO)
  1072. if (connection == TFT_HARD_SPI) {
  1073. // See SAMD51/21 note in writeColor()
  1074. hwspi._spi->setDataMode(hwspi._mode);
  1075. } else {
  1076. pinPeripheral(tft8._wr, PIO_OUTPUT); // Switch WR back to GPIO
  1077. }
  1078. #endif // end __SAMD51__ || ARDUINO_SAMD_ZERO
  1079. }
  1080. return;
  1081. }
  1082. #endif // end USE_SPI_DMA
  1083. // All other cases (bitbang SPI or non-DMA hard SPI or parallel),
  1084. // use a loop with the normal 16-bit data write function:
  1085. if (!bigEndian) {
  1086. while (len--) {
  1087. SPI_WRITE16(*colors++);
  1088. }
  1089. } else {
  1090. // Well this is awkward. SPI_WRITE16() was designed for little-endian
  1091. // hosts and big-endian displays as that's nearly always the typical
  1092. // case. If the bigEndian flag was set, data is already in display's
  1093. // order...so each pixel needs byte-swapping before being issued.
  1094. // Rather than having a separate big-endian SPI_WRITE16 (adding more
  1095. // bloat), it's preferred if calling function is smart and only uses
  1096. // bigEndian where DMA is supported. But we gotta handle this...
  1097. while (len--) {
  1098. SPI_WRITE16(__builtin_bswap16(*colors++));
  1099. }
  1100. }
  1101. }
  1102. /*!
  1103. @brief Wait for the last DMA transfer in a prior non-blocking
  1104. writePixels() call to complete. This does nothing if DMA
  1105. is not enabled, and is not needed if blocking writePixels()
  1106. was used (as is the default case).
  1107. */
  1108. void Adafruit_SPITFT::dmaWait(void) {
  1109. #if defined(USE_SPI_DMA) && (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
  1110. while (dma_busy)
  1111. ;
  1112. #if defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO)
  1113. if (connection == TFT_HARD_SPI) {
  1114. // See SAMD51/21 note in writeColor()
  1115. hwspi._spi->setDataMode(hwspi._mode);
  1116. } else {
  1117. pinPeripheral(tft8._wr, PIO_OUTPUT); // Switch WR back to GPIO
  1118. }
  1119. #endif // end __SAMD51__ || ARDUINO_SAMD_ZERO
  1120. #endif
  1121. }
  1122. /*!
  1123. @brief Check if DMA transfer is active. Always returts false if DMA
  1124. is not enabled.
  1125. @return true if DMA is enabled and transmitting data, false otherwise.
  1126. */
  1127. bool Adafruit_SPITFT::dmaBusy(void) const {
  1128. #if defined(USE_SPI_DMA) && (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
  1129. return dma_busy;
  1130. #else
  1131. return false;
  1132. #endif
  1133. }
  1134. /*!
  1135. @brief Issue a series of pixels, all the same color. Not self-
  1136. contained; should follow startWrite() and setAddrWindow() calls.
  1137. @param color 16-bit pixel color in '565' RGB format.
  1138. @param len Number of pixels to draw.
  1139. */
  1140. void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len) {
  1141. if (!len)
  1142. return; // Avoid 0-byte transfers
  1143. uint8_t hi = color >> 8, lo = color;
  1144. #if defined(ESP32) // ESP32 has a special SPI pixel-writing function...
  1145. if (connection == TFT_HARD_SPI) {
  1146. #define SPI_MAX_PIXELS_AT_ONCE 32
  1147. #define TMPBUF_LONGWORDS (SPI_MAX_PIXELS_AT_ONCE + 1) / 2
  1148. #define TMPBUF_PIXELS (TMPBUF_LONGWORDS * 2)
  1149. static uint32_t temp[TMPBUF_LONGWORDS];
  1150. uint32_t c32 = color * 0x00010001;
  1151. uint16_t bufLen = (len < TMPBUF_PIXELS) ? len : TMPBUF_PIXELS, xferLen,
  1152. fillLen;
  1153. // Fill temp buffer 32 bits at a time
  1154. fillLen = (bufLen + 1) / 2; // Round up to next 32-bit boundary
  1155. for (uint32_t t = 0; t < fillLen; t++) {
  1156. temp[t] = c32;
  1157. }
  1158. // Issue pixels in blocks from temp buffer
  1159. while (len) { // While pixels remain
  1160. xferLen = (bufLen < len) ? bufLen : len; // How many this pass?
  1161. writePixels((uint16_t *)temp, xferLen);
  1162. len -= xferLen;
  1163. }
  1164. return;
  1165. }
  1166. #elif defined(ARDUINO_NRF52_ADAFRUIT) && \
  1167. defined(NRF52840_XXAA) // Adafruit nRF52840 use SPIM3 DMA at 32Mhz
  1168. // at most 2 scan lines
  1169. uint32_t const pixbufcount = min(len, ((uint32_t)2 * width()));
  1170. uint16_t *pixbuf = (uint16_t *)rtos_malloc(2 * pixbufcount);
  1171. // use SPI3 DMA if we could allocate buffer, else fall back to writing each
  1172. // pixel loop below
  1173. if (pixbuf) {
  1174. uint16_t const swap_color = __builtin_bswap16(color);
  1175. // fill buffer with color
  1176. for (uint32_t i = 0; i < pixbufcount; i++) {
  1177. pixbuf[i] = swap_color;
  1178. }
  1179. while (len) {
  1180. uint32_t const count = min(len, pixbufcount);
  1181. writePixels(pixbuf, count, true, true);
  1182. len -= count;
  1183. }
  1184. rtos_free(pixbuf);
  1185. return;
  1186. }
  1187. #elif defined(ARDUINO_ARCH_RTTHREAD)
  1188. uint16_t pixbufcount;
  1189. uint16_t *pixbuf;
  1190. int16_t lines = height() / 4;
  1191. #define QUICKPATH_MAX_LEN 16
  1192. uint16_t quickpath_buffer[QUICKPATH_MAX_LEN];
  1193. do {
  1194. pixbufcount = min(len, (lines * width()));
  1195. if (pixbufcount > QUICKPATH_MAX_LEN) {
  1196. pixbuf = (uint16_t *)rt_malloc(2 * pixbufcount);
  1197. } else {
  1198. pixbuf = quickpath_buffer;
  1199. }
  1200. lines -= 2;
  1201. } while (!pixbuf && lines > 0);
  1202. if (pixbuf) {
  1203. uint16_t const swap_color = __builtin_bswap16(color);
  1204. while (len) {
  1205. uint16_t count = min(len, pixbufcount);
  1206. // fill buffer with color
  1207. for (uint16_t i = 0; i < count; i++) {
  1208. pixbuf[i] = swap_color;
  1209. }
  1210. // Don't need to swap color inside the function
  1211. // It has been done outside this function
  1212. writePixels(pixbuf, count, true, true);
  1213. len -= count;
  1214. }
  1215. if (pixbufcount > QUICKPATH_MAX_LEN) {
  1216. rt_free(pixbuf);
  1217. }
  1218. #undef QUICKPATH_MAX_LEN
  1219. return;
  1220. }
  1221. #else // !ESP32
  1222. #if defined(USE_SPI_DMA) && (defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO))
  1223. if (((connection == TFT_HARD_SPI) || (connection == TFT_PARALLEL)) &&
  1224. (len >= 16)) { // Don't bother with DMA on short pixel runs
  1225. int i, d, numDescriptors;
  1226. if (hi == lo) { // If high & low bytes are same...
  1227. onePixelBuf = color;
  1228. // Can do this with a relatively short descriptor list,
  1229. // each transferring a max of 32,767 (not 32,768) pixels.
  1230. // This won't run off the end of the allocated descriptor list,
  1231. // since we're using much larger chunks per descriptor here.
  1232. numDescriptors = (len + 32766) / 32767;
  1233. for (d = 0; d < numDescriptors; d++) {
  1234. int count = (len < 32767) ? len : 32767;
  1235. descriptor[d].SRCADDR.reg = (uint32_t)&onePixelBuf;
  1236. descriptor[d].BTCTRL.bit.SRCINC = 0;
  1237. descriptor[d].BTCNT.reg = count * 2;
  1238. descriptor[d].DESCADDR.reg = (uint32_t)&descriptor[d + 1];
  1239. len -= count;
  1240. }
  1241. descriptor[d - 1].DESCADDR.reg = 0;
  1242. } else {
  1243. // If high and low bytes are distinct, it's necessary to fill
  1244. // a buffer with pixel data (swapping high and low bytes because
  1245. // TFT and SAMD are different endianisms) and create a longer
  1246. // descriptor list pointing repeatedly to this data. We can do
  1247. // this slightly faster working 2 pixels (32 bits) at a time.
  1248. uint32_t *pixelPtr = (uint32_t *)pixelBuf[0],
  1249. twoPixels = __builtin_bswap16(color) * 0x00010001;
  1250. // We can avoid some or all of the buffer-filling if the color
  1251. // is the same as last time...
  1252. if (color == lastFillColor) {
  1253. // If length is longer than prior instance, fill only the
  1254. // additional pixels in the buffer and update lastFillLen.
  1255. if (len > lastFillLen) {
  1256. int fillStart = lastFillLen / 2,
  1257. fillEnd = (((len < maxFillLen) ? len : maxFillLen) + 1) / 2;
  1258. for (i = fillStart; i < fillEnd; i++)
  1259. pixelPtr[i] = twoPixels;
  1260. lastFillLen = fillEnd * 2;
  1261. } // else do nothing, don't set pixels or change lastFillLen
  1262. } else {
  1263. int fillEnd = (((len < maxFillLen) ? len : maxFillLen) + 1) / 2;
  1264. for (i = 0; i < fillEnd; i++)
  1265. pixelPtr[i] = twoPixels;
  1266. lastFillLen = fillEnd * 2;
  1267. lastFillColor = color;
  1268. }
  1269. numDescriptors = (len + maxFillLen - 1) / maxFillLen;
  1270. for (d = 0; d < numDescriptors; d++) {
  1271. int pixels = (len < maxFillLen) ? len : maxFillLen, bytes = pixels * 2;
  1272. descriptor[d].SRCADDR.reg = (uint32_t)pixelPtr + bytes;
  1273. descriptor[d].BTCTRL.bit.SRCINC = 1;
  1274. descriptor[d].BTCNT.reg = bytes;
  1275. descriptor[d].DESCADDR.reg = (uint32_t)&descriptor[d + 1];
  1276. len -= pixels;
  1277. }
  1278. descriptor[d - 1].DESCADDR.reg = 0;
  1279. }
  1280. memcpy(dptr, &descriptor[0], sizeof(DmacDescriptor));
  1281. #if defined(__SAMD51__)
  1282. if (connection == TFT_PARALLEL) {
  1283. // Switch WR pin to PWM or CCL
  1284. pinPeripheral(tft8._wr, wrPeripheral);
  1285. }
  1286. #endif // end __SAMD51__
  1287. dma_busy = true;
  1288. dma.startJob();
  1289. if (connection == TFT_PARALLEL)
  1290. dma.trigger();
  1291. while (dma_busy)
  1292. ; // Wait for completion
  1293. // Unfortunately blocking is necessary. An earlier version returned
  1294. // immediately and checked dma_busy on startWrite() instead, but it
  1295. // turns out to be MUCH slower on many graphics operations (as when
  1296. // drawing lines, pixel-by-pixel), perhaps because it's a volatile
  1297. // type and doesn't cache. Working on this.
  1298. #if defined(__SAMD51__) || defined(ARDUINO_SAMD_ZERO)
  1299. if (connection == TFT_HARD_SPI) {
  1300. // SAMD51: SPI DMA seems to leave the SPI peripheral in a freaky
  1301. // state on completion. Workaround is to explicitly set it back...
  1302. // (5/17/2019: apparently SAMD21 too, in certain cases, observed
  1303. // with ST7789 display.)
  1304. hwspi._spi->setDataMode(hwspi._mode);
  1305. } else {
  1306. pinPeripheral(tft8._wr, PIO_OUTPUT); // Switch WR back to GPIO
  1307. }
  1308. #endif // end __SAMD51__
  1309. return;
  1310. }
  1311. #endif // end USE_SPI_DMA
  1312. #endif // end !ESP32
  1313. // All other cases (non-DMA hard SPI, bitbang SPI, parallel)...
  1314. if (connection == TFT_HARD_SPI) {
  1315. #if defined(ESP8266)
  1316. do {
  1317. uint32_t pixelsThisPass = len;
  1318. if (pixelsThisPass > 50000)
  1319. pixelsThisPass = 50000;
  1320. len -= pixelsThisPass;
  1321. delay(1); // Periodic delay on long fills
  1322. while (pixelsThisPass--) {
  1323. hwspi._spi->write(hi);
  1324. hwspi._spi->write(lo);
  1325. }
  1326. } while (len);
  1327. #elif defined(ARDUINO_ARCH_RP2040)
  1328. spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;
  1329. color = __builtin_bswap16(color);
  1330. while (len--)
  1331. spi_write_blocking(pi_spi, (uint8_t *)&color, 2);
  1332. #else // !ESP8266 && !ARDUINO_ARCH_RP2040
  1333. while (len--) {
  1334. #if defined(__AVR__)
  1335. AVR_WRITESPI(hi);
  1336. AVR_WRITESPI(lo);
  1337. #elif defined(ESP32)
  1338. hwspi._spi->write(hi);
  1339. hwspi._spi->write(lo);
  1340. #else
  1341. hwspi._spi->transfer(hi);
  1342. hwspi._spi->transfer(lo);
  1343. #endif
  1344. }
  1345. #endif // end !ESP8266
  1346. } else if (connection == TFT_SOFT_SPI) {
  1347. #if defined(ESP8266)
  1348. do {
  1349. uint32_t pixelsThisPass = len;
  1350. if (pixelsThisPass > 20000)
  1351. pixelsThisPass = 20000;
  1352. len -= pixelsThisPass;
  1353. yield(); // Periodic yield() on long fills
  1354. while (pixelsThisPass--) {
  1355. for (uint16_t bit = 0, x = color; bit < 16; bit++) {
  1356. if (x & 0x8000)
  1357. SPI_MOSI_HIGH();
  1358. else
  1359. SPI_MOSI_LOW();
  1360. SPI_SCK_HIGH();
  1361. SPI_SCK_LOW();
  1362. x <<= 1;
  1363. }
  1364. }
  1365. } while (len);
  1366. #else // !ESP8266
  1367. while (len--) {
  1368. #if defined(__AVR__)
  1369. for (uint8_t bit = 0, x = hi; bit < 8; bit++) {
  1370. if (x & 0x80)
  1371. SPI_MOSI_HIGH();
  1372. else
  1373. SPI_MOSI_LOW();
  1374. SPI_SCK_HIGH();
  1375. SPI_SCK_LOW();
  1376. x <<= 1;
  1377. }
  1378. for (uint8_t bit = 0, x = lo; bit < 8; bit++) {
  1379. if (x & 0x80)
  1380. SPI_MOSI_HIGH();
  1381. else
  1382. SPI_MOSI_LOW();
  1383. SPI_SCK_HIGH();
  1384. SPI_SCK_LOW();
  1385. x <<= 1;
  1386. }
  1387. #else // !__AVR__
  1388. for (uint16_t bit = 0, x = color; bit < 16; bit++) {
  1389. if (x & 0x8000)
  1390. SPI_MOSI_HIGH();
  1391. else
  1392. SPI_MOSI_LOW();
  1393. SPI_SCK_HIGH();
  1394. x <<= 1;
  1395. SPI_SCK_LOW();
  1396. }
  1397. #endif // end !__AVR__
  1398. }
  1399. #endif // end !ESP8266
  1400. } else { // PARALLEL
  1401. if (hi == lo) {
  1402. #if defined(__AVR__)
  1403. len *= 2;
  1404. *tft8.writePort = hi;
  1405. while (len--) {
  1406. TFT_WR_STROBE();
  1407. }
  1408. #elif defined(USE_FAST_PINIO)
  1409. if (!tft8.wide) {
  1410. len *= 2;
  1411. *tft8.writePort = hi;
  1412. } else {
  1413. *(volatile uint16_t *)tft8.writePort = color;
  1414. }
  1415. while (len--) {
  1416. TFT_WR_STROBE();
  1417. }
  1418. #endif
  1419. } else {
  1420. while (len--) {
  1421. #if defined(__AVR__)
  1422. *tft8.writePort = hi;
  1423. TFT_WR_STROBE();
  1424. *tft8.writePort = lo;
  1425. #elif defined(USE_FAST_PINIO)
  1426. if (!tft8.wide) {
  1427. *tft8.writePort = hi;
  1428. TFT_WR_STROBE();
  1429. *tft8.writePort = lo;
  1430. } else {
  1431. *(volatile uint16_t *)tft8.writePort = color;
  1432. }
  1433. #endif
  1434. TFT_WR_STROBE();
  1435. }
  1436. }
  1437. }
  1438. }
  1439. /*!
  1440. @brief Draw a filled rectangle to the display. Not self-contained;
  1441. should follow startWrite(). Typically used by higher-level
  1442. graphics primitives; user code shouldn't need to call this and
  1443. is likely to use the self-contained fillRect() instead.
  1444. writeFillRect() performs its own edge clipping and rejection;
  1445. see writeFillRectPreclipped() for a more 'raw' implementation.
  1446. @param x Horizontal position of first corner.
  1447. @param y Vertical position of first corner.
  1448. @param w Rectangle width in pixels (positive = right of first
  1449. corner, negative = left of first corner).
  1450. @param h Rectangle height in pixels (positive = below first
  1451. corner, negative = above first corner).
  1452. @param color 16-bit fill color in '565' RGB format.
  1453. @note Written in this deep-nested way because C by definition will
  1454. optimize for the 'if' case, not the 'else' -- avoids branches
  1455. and rejects clipped rectangles at the least-work possibility.
  1456. */
  1457. void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  1458. uint16_t color) {
  1459. if (w && h) { // Nonzero width and height?
  1460. if (w < 0) { // If negative width...
  1461. x += w + 1; // Move X to left edge
  1462. w = -w; // Use positive width
  1463. }
  1464. if (x < _width) { // Not off right
  1465. if (h < 0) { // If negative height...
  1466. y += h + 1; // Move Y to top edge
  1467. h = -h; // Use positive height
  1468. }
  1469. if (y < _height) { // Not off bottom
  1470. int16_t x2 = x + w - 1;
  1471. if (x2 >= 0) { // Not off left
  1472. int16_t y2 = y + h - 1;
  1473. if (y2 >= 0) { // Not off top
  1474. // Rectangle partly or fully overlaps screen
  1475. if (x < 0) {
  1476. x = 0;
  1477. w = x2 + 1;
  1478. } // Clip left
  1479. if (y < 0) {
  1480. y = 0;
  1481. h = y2 + 1;
  1482. } // Clip top
  1483. if (x2 >= _width) {
  1484. w = _width - x;
  1485. } // Clip right
  1486. if (y2 >= _height) {
  1487. h = _height - y;
  1488. } // Clip bottom
  1489. writeFillRectPreclipped(x, y, w, h, color);
  1490. }
  1491. }
  1492. }
  1493. }
  1494. }
  1495. }
  1496. /*!
  1497. @brief Draw a horizontal line on the display. Performs edge clipping
  1498. and rejection. Not self-contained; should follow startWrite().
  1499. Typically used by higher-level graphics primitives; user code
  1500. shouldn't need to call this and is likely to use the self-
  1501. contained drawFastHLine() instead.
  1502. @param x Horizontal position of first point.
  1503. @param y Vertical position of first point.
  1504. @param w Line width in pixels (positive = right of first point,
  1505. negative = point of first corner).
  1506. @param color 16-bit line color in '565' RGB format.
  1507. */
  1508. void inline Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w,
  1509. uint16_t color) {
  1510. if ((y >= 0) && (y < _height) && w) { // Y on screen, nonzero width
  1511. if (w < 0) { // If negative width...
  1512. x += w + 1; // Move X to left edge
  1513. w = -w; // Use positive width
  1514. }
  1515. if (x < _width) { // Not off right
  1516. int16_t x2 = x + w - 1;
  1517. if (x2 >= 0) { // Not off left
  1518. // Line partly or fully overlaps screen
  1519. if (x < 0) {
  1520. x = 0;
  1521. w = x2 + 1;
  1522. } // Clip left
  1523. if (x2 >= _width) {
  1524. w = _width - x;
  1525. } // Clip right
  1526. writeFillRectPreclipped(x, y, w, 1, color);
  1527. }
  1528. }
  1529. }
  1530. }
  1531. /*!
  1532. @brief Draw a vertical line on the display. Performs edge clipping and
  1533. rejection. Not self-contained; should follow startWrite().
  1534. Typically used by higher-level graphics primitives; user code
  1535. shouldn't need to call this and is likely to use the self-
  1536. contained drawFastVLine() instead.
  1537. @param x Horizontal position of first point.
  1538. @param y Vertical position of first point.
  1539. @param h Line height in pixels (positive = below first point,
  1540. negative = above first point).
  1541. @param color 16-bit line color in '565' RGB format.
  1542. */
  1543. void inline Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h,
  1544. uint16_t color) {
  1545. if ((x >= 0) && (x < _width) && h) { // X on screen, nonzero height
  1546. if (h < 0) { // If negative height...
  1547. y += h + 1; // Move Y to top edge
  1548. h = -h; // Use positive height
  1549. }
  1550. if (y < _height) { // Not off bottom
  1551. int16_t y2 = y + h - 1;
  1552. if (y2 >= 0) { // Not off top
  1553. // Line partly or fully overlaps screen
  1554. if (y < 0) {
  1555. y = 0;
  1556. h = y2 + 1;
  1557. } // Clip top
  1558. if (y2 >= _height) {
  1559. h = _height - y;
  1560. } // Clip bottom
  1561. writeFillRectPreclipped(x, y, 1, h, color);
  1562. }
  1563. }
  1564. }
  1565. }
  1566. /*!
  1567. @brief A lower-level version of writeFillRect(). This version requires
  1568. all inputs are in-bounds, that width and height are positive,
  1569. and no part extends offscreen. NO EDGE CLIPPING OR REJECTION IS
  1570. PERFORMED. If higher-level graphics primitives are written to
  1571. handle their own clipping earlier in the drawing process, this
  1572. can avoid unnecessary function calls and repeated clipping
  1573. operations in the lower-level functions.
  1574. @param x Horizontal position of first corner. MUST BE WITHIN
  1575. SCREEN BOUNDS.
  1576. @param y Vertical position of first corner. MUST BE WITHIN SCREEN
  1577. BOUNDS.
  1578. @param w Rectangle width in pixels. MUST BE POSITIVE AND NOT
  1579. EXTEND OFF SCREEN.
  1580. @param h Rectangle height in pixels. MUST BE POSITIVE AND NOT
  1581. EXTEND OFF SCREEN.
  1582. @param color 16-bit fill color in '565' RGB format.
  1583. @note This is a new function, no graphics primitives besides rects
  1584. and horizontal/vertical lines are written to best use this yet.
  1585. */
  1586. inline void Adafruit_SPITFT::writeFillRectPreclipped(int16_t x, int16_t y,
  1587. int16_t w, int16_t h,
  1588. uint16_t color) {
  1589. setAddrWindow(x, y, w, h);
  1590. writeColor(color, (uint32_t)w * h);
  1591. }
  1592. // -------------------------------------------------------------------------
  1593. // Ever-so-slightly higher-level graphics operations. Similar to the 'write'
  1594. // functions above, but these contain their own chip-select and SPI
  1595. // transactions as needed (via startWrite(), endWrite()). They're typically
  1596. // used solo -- as graphics primitives in themselves, not invoked by higher-
  1597. // level primitives (which should use the functions above for better
  1598. // performance).
  1599. /*!
  1600. @brief Draw a single pixel to the display at requested coordinates.
  1601. Self-contained and provides its own transaction as needed
  1602. (see writePixel(x,y,color) for a lower-level variant).
  1603. Edge clipping is performed here.
  1604. @param x Horizontal position (0 = left).
  1605. @param y Vertical position (0 = top).
  1606. @param color 16-bit pixel color in '565' RGB format.
  1607. */
  1608. void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color) {
  1609. // Clip first...
  1610. if ((x >= 0) && (x < _width) && (y >= 0) && (y < _height)) {
  1611. // THEN set up transaction (if needed) and draw...
  1612. startWrite();
  1613. setAddrWindow(x, y, 1, 1);
  1614. SPI_WRITE16(color);
  1615. endWrite();
  1616. }
  1617. }
  1618. /*!
  1619. @brief Draw a filled rectangle to the display. Self-contained and
  1620. provides its own transaction as needed (see writeFillRect() or
  1621. writeFillRectPreclipped() for lower-level variants). Edge
  1622. clipping and rejection is performed here.
  1623. @param x Horizontal position of first corner.
  1624. @param y Vertical position of first corner.
  1625. @param w Rectangle width in pixels (positive = right of first
  1626. corner, negative = left of first corner).
  1627. @param h Rectangle height in pixels (positive = below first
  1628. corner, negative = above first corner).
  1629. @param color 16-bit fill color in '565' RGB format.
  1630. @note This repeats the writeFillRect() function almost in its entirety,
  1631. with the addition of a transaction start/end. It's done this way
  1632. (rather than starting the transaction and calling writeFillRect()
  1633. to handle clipping and so forth) so that the transaction isn't
  1634. performed at all if the rectangle is rejected. It's really not
  1635. that much code.
  1636. */
  1637. void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  1638. uint16_t color) {
  1639. if (w && h) { // Nonzero width and height?
  1640. if (w < 0) { // If negative width...
  1641. x += w + 1; // Move X to left edge
  1642. w = -w; // Use positive width
  1643. }
  1644. if (x < _width) { // Not off right
  1645. if (h < 0) { // If negative height...
  1646. y += h + 1; // Move Y to top edge
  1647. h = -h; // Use positive height
  1648. }
  1649. if (y < _height) { // Not off bottom
  1650. int16_t x2 = x + w - 1;
  1651. if (x2 >= 0) { // Not off left
  1652. int16_t y2 = y + h - 1;
  1653. if (y2 >= 0) { // Not off top
  1654. // Rectangle partly or fully overlaps screen
  1655. if (x < 0) {
  1656. x = 0;
  1657. w = x2 + 1;
  1658. } // Clip left
  1659. if (y < 0) {
  1660. y = 0;
  1661. h = y2 + 1;
  1662. } // Clip top
  1663. if (x2 >= _width) {
  1664. w = _width - x;
  1665. } // Clip right
  1666. if (y2 >= _height) {
  1667. h = _height - y;
  1668. } // Clip bottom
  1669. startWrite();
  1670. writeFillRectPreclipped(x, y, w, h, color);
  1671. endWrite();
  1672. }
  1673. }
  1674. }
  1675. }
  1676. }
  1677. }
  1678. /*!
  1679. @brief Draw a horizontal line on the display. Self-contained and
  1680. provides its own transaction as needed (see writeFastHLine() for
  1681. a lower-level variant). Edge clipping and rejection is performed
  1682. here.
  1683. @param x Horizontal position of first point.
  1684. @param y Vertical position of first point.
  1685. @param w Line width in pixels (positive = right of first point,
  1686. negative = point of first corner).
  1687. @param color 16-bit line color in '565' RGB format.
  1688. @note This repeats the writeFastHLine() function almost in its
  1689. entirety, with the addition of a transaction start/end. It's
  1690. done this way (rather than starting the transaction and calling
  1691. writeFastHLine() to handle clipping and so forth) so that the
  1692. transaction isn't performed at all if the line is rejected.
  1693. */
  1694. void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y, int16_t w,
  1695. uint16_t color) {
  1696. if ((y >= 0) && (y < _height) && w) { // Y on screen, nonzero width
  1697. if (w < 0) { // If negative width...
  1698. x += w + 1; // Move X to left edge
  1699. w = -w; // Use positive width
  1700. }
  1701. if (x < _width) { // Not off right
  1702. int16_t x2 = x + w - 1;
  1703. if (x2 >= 0) { // Not off left
  1704. // Line partly or fully overlaps screen
  1705. if (x < 0) {
  1706. x = 0;
  1707. w = x2 + 1;
  1708. } // Clip left
  1709. if (x2 >= _width) {
  1710. w = _width - x;
  1711. } // Clip right
  1712. startWrite();
  1713. writeFillRectPreclipped(x, y, w, 1, color);
  1714. endWrite();
  1715. }
  1716. }
  1717. }
  1718. }
  1719. /*!
  1720. @brief Draw a vertical line on the display. Self-contained and provides
  1721. its own transaction as needed (see writeFastHLine() for a lower-
  1722. level variant). Edge clipping and rejection is performed here.
  1723. @param x Horizontal position of first point.
  1724. @param y Vertical position of first point.
  1725. @param h Line height in pixels (positive = below first point,
  1726. negative = above first point).
  1727. @param color 16-bit line color in '565' RGB format.
  1728. @note This repeats the writeFastVLine() function almost in its
  1729. entirety, with the addition of a transaction start/end. It's
  1730. done this way (rather than starting the transaction and calling
  1731. writeFastVLine() to handle clipping and so forth) so that the
  1732. transaction isn't performed at all if the line is rejected.
  1733. */
  1734. void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y, int16_t h,
  1735. uint16_t color) {
  1736. if ((x >= 0) && (x < _width) && h) { // X on screen, nonzero height
  1737. if (h < 0) { // If negative height...
  1738. y += h + 1; // Move Y to top edge
  1739. h = -h; // Use positive height
  1740. }
  1741. if (y < _height) { // Not off bottom
  1742. int16_t y2 = y + h - 1;
  1743. if (y2 >= 0) { // Not off top
  1744. // Line partly or fully overlaps screen
  1745. if (y < 0) {
  1746. y = 0;
  1747. h = y2 + 1;
  1748. } // Clip top
  1749. if (y2 >= _height) {
  1750. h = _height - y;
  1751. } // Clip bottom
  1752. startWrite();
  1753. writeFillRectPreclipped(x, y, 1, h, color);
  1754. endWrite();
  1755. }
  1756. }
  1757. }
  1758. }
  1759. /*!
  1760. @brief Essentially writePixel() with a transaction around it. I don't
  1761. think this is in use by any of our code anymore (believe it was
  1762. for some older BMP-reading examples), but is kept here in case
  1763. any user code relies on it. Consider it DEPRECATED.
  1764. @param color 16-bit pixel color in '565' RGB format.
  1765. */
  1766. void Adafruit_SPITFT::pushColor(uint16_t color) {
  1767. startWrite();
  1768. SPI_WRITE16(color);
  1769. endWrite();
  1770. }
  1771. /*!
  1772. @brief Draw a 16-bit image (565 RGB) at the specified (x,y) position.
  1773. For 16-bit display devices; no color reduction performed.
  1774. Adapted from https://github.com/PaulStoffregen/ILI9341_t3
  1775. by Marc MERLIN. See examples/pictureEmbed to use this.
  1776. 5/6/2017: function name and arguments have changed for
  1777. compatibility with current GFX library and to avoid naming
  1778. problems in prior implementation. Formerly drawBitmap() with
  1779. arguments in different order. Handles its own transaction and
  1780. edge clipping/rejection.
  1781. @param x Top left corner horizontal coordinate.
  1782. @param y Top left corner vertical coordinate.
  1783. @param pcolors Pointer to 16-bit array of pixel values.
  1784. @param w Width of bitmap in pixels.
  1785. @param h Height of bitmap in pixels.
  1786. */
  1787. void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y, uint16_t *pcolors,
  1788. int16_t w, int16_t h) {
  1789. int16_t x2, y2; // Lower-right coord
  1790. if ((x >= _width) || // Off-edge right
  1791. (y >= _height) || // " top
  1792. ((x2 = (x + w - 1)) < 0) || // " left
  1793. ((y2 = (y + h - 1)) < 0))
  1794. return; // " bottom
  1795. int16_t bx1 = 0, by1 = 0, // Clipped top-left within bitmap
  1796. saveW = w; // Save original bitmap width value
  1797. if (x < 0) { // Clip left
  1798. w += x;
  1799. bx1 = -x;
  1800. x = 0;
  1801. }
  1802. if (y < 0) { // Clip top
  1803. h += y;
  1804. by1 = -y;
  1805. y = 0;
  1806. }
  1807. if (x2 >= _width)
  1808. w = _width - x; // Clip right
  1809. if (y2 >= _height)
  1810. h = _height - y; // Clip bottom
  1811. pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
  1812. startWrite();
  1813. setAddrWindow(x, y, w, h); // Clipped area
  1814. while (h--) { // For each (clipped) scanline...
  1815. writePixels(pcolors, w); // Push one (clipped) row
  1816. pcolors += saveW; // Advance pointer by one full (unclipped) line
  1817. }
  1818. endWrite();
  1819. }
  1820. // -------------------------------------------------------------------------
  1821. // Miscellaneous class member functions that don't draw anything.
  1822. /*!
  1823. @brief Invert the colors of the display (if supported by hardware).
  1824. Self-contained, no transaction setup required.
  1825. @param i true = inverted display, false = normal display.
  1826. */
  1827. void Adafruit_SPITFT::invertDisplay(bool i) {
  1828. startWrite();
  1829. writeCommand(i ? invertOnCommand : invertOffCommand);
  1830. endWrite();
  1831. }
  1832. /*!
  1833. @brief Given 8-bit red, green and blue values, return a 'packed'
  1834. 16-bit color value in '565' RGB format (5 bits red, 6 bits
  1835. green, 5 bits blue). This is just a mathematical operation,
  1836. no hardware is touched.
  1837. @param red 8-bit red brightnesss (0 = off, 255 = max).
  1838. @param green 8-bit green brightnesss (0 = off, 255 = max).
  1839. @param blue 8-bit blue brightnesss (0 = off, 255 = max).
  1840. @return 'Packed' 16-bit color value (565 format).
  1841. */
  1842. uint16_t Adafruit_SPITFT::color565(uint8_t red, uint8_t green, uint8_t blue) {
  1843. return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
  1844. }
  1845. /*!
  1846. @brief Adafruit_SPITFT Send Command handles complete sending of commands and
  1847. data
  1848. @param commandByte The Command Byte
  1849. @param dataBytes A pointer to the Data bytes to send
  1850. @param numDataBytes The number of bytes we should send
  1851. */
  1852. void Adafruit_SPITFT::sendCommand(uint8_t commandByte, uint8_t *dataBytes,
  1853. uint8_t numDataBytes) {
  1854. SPI_BEGIN_TRANSACTION();
  1855. if (_cs >= 0)
  1856. SPI_CS_LOW();
  1857. SPI_DC_LOW(); // Command mode
  1858. spiWrite(commandByte); // Send the command byte
  1859. SPI_DC_HIGH();
  1860. for (int i = 0; i < numDataBytes; i++) {
  1861. if ((connection == TFT_PARALLEL) && tft8.wide) {
  1862. SPI_WRITE16(*(uint16_t *)dataBytes);
  1863. dataBytes += 2;
  1864. } else {
  1865. spiWrite(*dataBytes); // Send the data bytes
  1866. dataBytes++;
  1867. }
  1868. }
  1869. if (_cs >= 0)
  1870. SPI_CS_HIGH();
  1871. SPI_END_TRANSACTION();
  1872. }
  1873. /*!
  1874. @brief Adafruit_SPITFT Send Command handles complete sending of commands and
  1875. data
  1876. @param commandByte The Command Byte
  1877. @param dataBytes A pointer to the Data bytes to send
  1878. @param numDataBytes The number of bytes we should send
  1879. */
  1880. void Adafruit_SPITFT::sendCommand(uint8_t commandByte, const uint8_t *dataBytes,
  1881. uint8_t numDataBytes) {
  1882. SPI_BEGIN_TRANSACTION();
  1883. if (_cs >= 0)
  1884. SPI_CS_LOW();
  1885. SPI_DC_LOW(); // Command mode
  1886. spiWrite(commandByte); // Send the command byte
  1887. SPI_DC_HIGH();
  1888. for (int i = 0; i < numDataBytes; i++) {
  1889. if ((connection == TFT_PARALLEL) && tft8.wide) {
  1890. SPI_WRITE16(*(uint16_t *)dataBytes);
  1891. dataBytes += 2;
  1892. } else {
  1893. spiWrite(pgm_read_byte(dataBytes++));
  1894. }
  1895. }
  1896. if (_cs >= 0)
  1897. SPI_CS_HIGH();
  1898. SPI_END_TRANSACTION();
  1899. }
  1900. /*!
  1901. @brief Adafruit_SPITFT sendCommand16 handles complete sending of
  1902. commands and data for 16-bit parallel displays. Currently somewhat
  1903. rigged for the NT35510, which has the odd behavior of wanting
  1904. commands 16-bit, but subsequent data as 8-bit values, despite
  1905. the 16-bit bus (high byte is always 0). Also seems to require
  1906. issuing and incrementing address with each transfer.
  1907. @param commandWord The command word (16 bits)
  1908. @param dataBytes A pointer to the data bytes to send
  1909. @param numDataBytes The number of bytes we should send
  1910. */
  1911. void Adafruit_SPITFT::sendCommand16(uint16_t commandWord,
  1912. const uint8_t *dataBytes,
  1913. uint8_t numDataBytes) {
  1914. SPI_BEGIN_TRANSACTION();
  1915. if (_cs >= 0)
  1916. SPI_CS_LOW();
  1917. if (numDataBytes == 0) {
  1918. SPI_DC_LOW(); // Command mode
  1919. SPI_WRITE16(commandWord); // Send the command word
  1920. SPI_DC_HIGH(); // Data mode
  1921. }
  1922. for (int i = 0; i < numDataBytes; i++) {
  1923. SPI_DC_LOW(); // Command mode
  1924. SPI_WRITE16(commandWord); // Send the command word
  1925. SPI_DC_HIGH(); // Data mode
  1926. commandWord++;
  1927. SPI_WRITE16((uint16_t)pgm_read_byte(dataBytes++));
  1928. }
  1929. if (_cs >= 0)
  1930. SPI_CS_HIGH();
  1931. SPI_END_TRANSACTION();
  1932. }
  1933. /*!
  1934. @brief Read 8 bits of data from display configuration memory (not RAM).
  1935. This is highly undocumented/supported and should be avoided,
  1936. function is only included because some of the examples use it.
  1937. @param commandByte
  1938. The command register to read data from.
  1939. @param index
  1940. The byte index into the command to read from.
  1941. @return Unsigned 8-bit data read from display register.
  1942. */
  1943. /**************************************************************************/
  1944. uint8_t Adafruit_SPITFT::readcommand8(uint8_t commandByte, uint8_t index) {
  1945. uint8_t result;
  1946. startWrite();
  1947. SPI_DC_LOW(); // Command mode
  1948. spiWrite(commandByte);
  1949. SPI_DC_HIGH(); // Data mode
  1950. do {
  1951. result = spiRead();
  1952. } while (index--); // Discard bytes up to index'th
  1953. endWrite();
  1954. return result;
  1955. }
  1956. /*!
  1957. @brief Read 16 bits of data from display register.
  1958. For 16-bit parallel displays only.
  1959. @param addr Command/register to access.
  1960. @return Unsigned 16-bit data.
  1961. */
  1962. uint16_t Adafruit_SPITFT::readcommand16(uint16_t addr) {
  1963. #if defined(USE_FAST_PINIO) // NOT SUPPORTED without USE_FAST_PINIO
  1964. uint16_t result = 0;
  1965. if ((connection == TFT_PARALLEL) && tft8.wide) {
  1966. startWrite();
  1967. SPI_DC_LOW(); // Command mode
  1968. SPI_WRITE16(addr);
  1969. SPI_DC_HIGH(); // Data mode
  1970. TFT_RD_LOW(); // Read line LOW
  1971. #if defined(HAS_PORT_SET_CLR)
  1972. *(volatile uint16_t *)tft8.dirClr = 0xFFFF; // Input state
  1973. result = *(volatile uint16_t *)tft8.readPort; // 16-bit read
  1974. *(volatile uint16_t *)tft8.dirSet = 0xFFFF; // Output state
  1975. #else // !HAS_PORT_SET_CLR
  1976. *(volatile uint16_t *)tft8.portDir = 0x0000; // Input state
  1977. result = *(volatile uint16_t *)tft8.readPort; // 16-bit read
  1978. *(volatile uint16_t *)tft8.portDir = 0xFFFF; // Output state
  1979. #endif // end !HAS_PORT_SET_CLR
  1980. TFT_RD_HIGH(); // Read line HIGH
  1981. endWrite();
  1982. }
  1983. return result;
  1984. #else
  1985. (void)addr; // disable -Wunused-parameter warning
  1986. return 0;
  1987. #endif // end !USE_FAST_PINIO
  1988. }
  1989. // -------------------------------------------------------------------------
  1990. // Lowest-level hardware-interfacing functions. Many of these are inline and
  1991. // compile to different things based on #defines -- typically just a few
  1992. // instructions. Others, not so much, those are not inlined.
  1993. /*!
  1994. @brief Start an SPI transaction if using the hardware SPI interface to
  1995. the display. If using an earlier version of the Arduino platform
  1996. (before the addition of SPI transactions), this instead attempts
  1997. to set up the SPI clock and mode. No action is taken if the
  1998. connection is not hardware SPI-based. This does NOT include a
  1999. chip-select operation -- see startWrite() for a function that
  2000. encapsulated both actions.
  2001. */
  2002. inline void Adafruit_SPITFT::SPI_BEGIN_TRANSACTION(void) {
  2003. if (connection == TFT_HARD_SPI) {
  2004. #if defined(SPI_HAS_TRANSACTION)
  2005. hwspi._spi->beginTransaction(hwspi.settings);
  2006. #else // No transactions, configure SPI manually...
  2007. #if defined(__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_STM32F1)
  2008. hwspi._spi->setClockDivider(SPI_CLOCK_DIV2);
  2009. #elif defined(__arm__)
  2010. hwspi._spi->setClockDivider(11);
  2011. #elif defined(ESP8266) || defined(ESP32)
  2012. hwspi._spi->setFrequency(hwspi._freq);
  2013. #elif defined(RASPI) || defined(ARDUINO_ARCH_STM32F1)
  2014. hwspi._spi->setClock(hwspi._freq);
  2015. #endif
  2016. hwspi._spi->setBitOrder(MSBFIRST);
  2017. hwspi._spi->setDataMode(hwspi._mode);
  2018. #endif // end !SPI_HAS_TRANSACTION
  2019. }
  2020. }
  2021. /*!
  2022. @brief End an SPI transaction if using the hardware SPI interface to
  2023. the display. No action is taken if the connection is not
  2024. hardware SPI-based or if using an earlier version of the Arduino
  2025. platform (before the addition of SPI transactions). This does
  2026. NOT include a chip-deselect operation -- see endWrite() for a
  2027. function that encapsulated both actions.
  2028. */
  2029. inline void Adafruit_SPITFT::SPI_END_TRANSACTION(void) {
  2030. #if defined(SPI_HAS_TRANSACTION)
  2031. if (connection == TFT_HARD_SPI) {
  2032. hwspi._spi->endTransaction();
  2033. }
  2034. #endif
  2035. }
  2036. /*!
  2037. @brief Issue a single 8-bit value to the display. Chip-select,
  2038. transaction and data/command selection must have been
  2039. previously set -- this ONLY issues the byte. This is another of
  2040. those functions in the library with a now-not-accurate name
  2041. that's being maintained for compatibility with outside code.
  2042. This function is used even if display connection is parallel.
  2043. @param b 8-bit value to write.
  2044. */
  2045. void Adafruit_SPITFT::spiWrite(uint8_t b) {
  2046. if (connection == TFT_HARD_SPI) {
  2047. #if defined(__AVR__)
  2048. AVR_WRITESPI(b);
  2049. #elif defined(ESP8266) || defined(ESP32)
  2050. hwspi._spi->write(b);
  2051. #elif defined(ARDUINO_ARCH_RP2040)
  2052. spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;
  2053. spi_write_blocking(pi_spi, &b, 1);
  2054. #else
  2055. hwspi._spi->transfer(b);
  2056. #endif
  2057. } else if (connection == TFT_SOFT_SPI) {
  2058. for (uint8_t bit = 0; bit < 8; bit++) {
  2059. if (b & 0x80)
  2060. SPI_MOSI_HIGH();
  2061. else
  2062. SPI_MOSI_LOW();
  2063. SPI_SCK_HIGH();
  2064. b <<= 1;
  2065. SPI_SCK_LOW();
  2066. }
  2067. } else { // TFT_PARALLEL
  2068. #if defined(__AVR__)
  2069. *tft8.writePort = b;
  2070. #elif defined(USE_FAST_PINIO)
  2071. if (!tft8.wide)
  2072. *tft8.writePort = b;
  2073. else
  2074. *(volatile uint16_t *)tft8.writePort = b;
  2075. #endif
  2076. TFT_WR_STROBE();
  2077. }
  2078. }
  2079. /*!
  2080. @brief Write a single command byte to the display. Chip-select and
  2081. transaction must have been previously set -- this ONLY sets
  2082. the device to COMMAND mode, issues the byte and then restores
  2083. DATA mode. There is no corresponding explicit writeData()
  2084. function -- just use spiWrite().
  2085. @param cmd 8-bit command to write.
  2086. */
  2087. void Adafruit_SPITFT::writeCommand(uint8_t cmd) {
  2088. SPI_DC_LOW();
  2089. spiWrite(cmd);
  2090. SPI_DC_HIGH();
  2091. }
  2092. /*!
  2093. @brief Read a single 8-bit value from the display. Chip-select and
  2094. transaction must have been previously set -- this ONLY reads
  2095. the byte. This is another of those functions in the library
  2096. with a now-not-accurate name that's being maintained for
  2097. compatibility with outside code. This function is used even if
  2098. display connection is parallel.
  2099. @return Unsigned 8-bit value read (always zero if USE_FAST_PINIO is
  2100. not supported by the MCU architecture).
  2101. */
  2102. uint8_t Adafruit_SPITFT::spiRead(void) {
  2103. uint8_t b = 0;
  2104. uint16_t w = 0;
  2105. if (connection == TFT_HARD_SPI) {
  2106. return hwspi._spi->transfer((uint8_t)0);
  2107. } else if (connection == TFT_SOFT_SPI) {
  2108. if (swspi._miso >= 0) {
  2109. for (uint8_t i = 0; i < 8; i++) {
  2110. SPI_SCK_HIGH();
  2111. b <<= 1;
  2112. if (SPI_MISO_READ())
  2113. b++;
  2114. SPI_SCK_LOW();
  2115. }
  2116. }
  2117. return b;
  2118. } else { // TFT_PARALLEL
  2119. if (tft8._rd >= 0) {
  2120. #if defined(USE_FAST_PINIO)
  2121. TFT_RD_LOW(); // Read line LOW
  2122. #if defined(__AVR__)
  2123. *tft8.portDir = 0x00; // Set port to input state
  2124. w = *tft8.readPort; // Read value from port
  2125. *tft8.portDir = 0xFF; // Restore port to output
  2126. #else // !__AVR__
  2127. if (!tft8.wide) { // 8-bit TFT connection
  2128. #if defined(HAS_PORT_SET_CLR)
  2129. *tft8.dirClr = 0xFF; // Set port to input state
  2130. w = *tft8.readPort; // Read value from port
  2131. *tft8.dirSet = 0xFF; // Restore port to output
  2132. #else // !HAS_PORT_SET_CLR
  2133. *tft8.portDir = 0x00; // Set port to input state
  2134. w = *tft8.readPort; // Read value from port
  2135. *tft8.portDir = 0xFF; // Restore port to output
  2136. #endif // end HAS_PORT_SET_CLR
  2137. } else { // 16-bit TFT connection
  2138. #if defined(HAS_PORT_SET_CLR)
  2139. *(volatile uint16_t *)tft8.dirClr = 0xFFFF; // Input state
  2140. w = *(volatile uint16_t *)tft8.readPort; // 16-bit read
  2141. *(volatile uint16_t *)tft8.dirSet = 0xFFFF; // Output state
  2142. #else // !HAS_PORT_SET_CLR
  2143. *(volatile uint16_t *)tft8.portDir = 0x0000; // Input state
  2144. w = *(volatile uint16_t *)tft8.readPort; // 16-bit read
  2145. *(volatile uint16_t *)tft8.portDir = 0xFFFF; // Output state
  2146. #endif // end !HAS_PORT_SET_CLR
  2147. }
  2148. TFT_RD_HIGH(); // Read line HIGH
  2149. #endif // end !__AVR__
  2150. #else // !USE_FAST_PINIO
  2151. w = 0; // Parallel TFT is NOT SUPPORTED without USE_FAST_PINIO
  2152. #endif // end !USE_FAST_PINIO
  2153. }
  2154. return w;
  2155. }
  2156. }
  2157. /*!
  2158. @brief Issue a single 16-bit value to the display. Chip-select,
  2159. transaction and data/command selection must have been
  2160. previously set -- this ONLY issues the word.
  2161. Thus operates ONLY on 'wide' (16-bit) parallel displays!
  2162. @param w 16-bit value to write.
  2163. */
  2164. void Adafruit_SPITFT::write16(uint16_t w) {
  2165. if (connection == TFT_PARALLEL) {
  2166. #if defined(USE_FAST_PINIO)
  2167. if (tft8.wide)
  2168. *(volatile uint16_t *)tft8.writePort = w;
  2169. #else
  2170. (void)w; // disable -Wunused-parameter warning
  2171. #endif
  2172. TFT_WR_STROBE();
  2173. }
  2174. }
  2175. /*!
  2176. @brief Write a single command word to the display. Chip-select and
  2177. transaction must have been previously set -- this ONLY sets
  2178. the device to COMMAND mode, issues the byte and then restores
  2179. DATA mode. This operates ONLY on 'wide' (16-bit) parallel
  2180. displays!
  2181. @param cmd 16-bit command to write.
  2182. */
  2183. void Adafruit_SPITFT::writeCommand16(uint16_t cmd) {
  2184. SPI_DC_LOW();
  2185. write16(cmd);
  2186. SPI_DC_HIGH();
  2187. }
  2188. /*!
  2189. @brief Read a single 16-bit value from the display. Chip-select and
  2190. transaction must have been previously set -- this ONLY reads
  2191. the byte. This operates ONLY on 'wide' (16-bit) parallel
  2192. displays!
  2193. @return Unsigned 16-bit value read (always zero if USE_FAST_PINIO is
  2194. not supported by the MCU architecture).
  2195. */
  2196. uint16_t Adafruit_SPITFT::read16(void) {
  2197. uint16_t w = 0;
  2198. if (connection == TFT_PARALLEL) {
  2199. if (tft8._rd >= 0) {
  2200. #if defined(USE_FAST_PINIO)
  2201. TFT_RD_LOW(); // Read line LOW
  2202. if (tft8.wide) { // 16-bit TFT connection
  2203. #if defined(HAS_PORT_SET_CLR)
  2204. *(volatile uint16_t *)tft8.dirClr = 0xFFFF; // Input state
  2205. w = *(volatile uint16_t *)tft8.readPort; // 16-bit read
  2206. *(volatile uint16_t *)tft8.dirSet = 0xFFFF; // Output state
  2207. #else // !HAS_PORT_SET_CLR
  2208. *(volatile uint16_t *)tft8.portDir = 0x0000; // Input state
  2209. w = *(volatile uint16_t *)tft8.readPort; // 16-bit read
  2210. *(volatile uint16_t *)tft8.portDir = 0xFFFF; // Output state
  2211. #endif // end !HAS_PORT_SET_CLR
  2212. }
  2213. TFT_RD_HIGH(); // Read line HIGH
  2214. #else // !USE_FAST_PINIO
  2215. w = 0; // Parallel TFT is NOT SUPPORTED without USE_FAST_PINIO
  2216. #endif // end !USE_FAST_PINIO
  2217. }
  2218. }
  2219. return w;
  2220. }
  2221. /*!
  2222. @brief Set the software (bitbang) SPI MOSI line HIGH.
  2223. */
  2224. inline void Adafruit_SPITFT::SPI_MOSI_HIGH(void) {
  2225. #if defined(USE_FAST_PINIO)
  2226. #if defined(HAS_PORT_SET_CLR)
  2227. #if defined(KINETISK)
  2228. *swspi.mosiPortSet = 1;
  2229. #else // !KINETISK
  2230. *swspi.mosiPortSet = swspi.mosiPinMask;
  2231. #endif
  2232. #else // !HAS_PORT_SET_CLR
  2233. *swspi.mosiPort |= swspi.mosiPinMaskSet;
  2234. #endif // end !HAS_PORT_SET_CLR
  2235. #else // !USE_FAST_PINIO
  2236. digitalWrite(swspi._mosi, HIGH);
  2237. #endif // end !USE_FAST_PINIO
  2238. }
  2239. /*!
  2240. @brief Set the software (bitbang) SPI MOSI line LOW.
  2241. */
  2242. inline void Adafruit_SPITFT::SPI_MOSI_LOW(void) {
  2243. #if defined(USE_FAST_PINIO)
  2244. #if defined(HAS_PORT_SET_CLR)
  2245. #if defined(KINETISK)
  2246. *swspi.mosiPortClr = 1;
  2247. #else // !KINETISK
  2248. *swspi.mosiPortClr = swspi.mosiPinMask;
  2249. #endif
  2250. #else // !HAS_PORT_SET_CLR
  2251. *swspi.mosiPort &= swspi.mosiPinMaskClr;
  2252. #endif // end !HAS_PORT_SET_CLR
  2253. #else // !USE_FAST_PINIO
  2254. digitalWrite(swspi._mosi, LOW);
  2255. #endif // end !USE_FAST_PINIO
  2256. }
  2257. /*!
  2258. @brief Set the software (bitbang) SPI SCK line HIGH.
  2259. */
  2260. inline void Adafruit_SPITFT::SPI_SCK_HIGH(void) {
  2261. #if defined(USE_FAST_PINIO)
  2262. #if defined(HAS_PORT_SET_CLR)
  2263. #if defined(KINETISK)
  2264. *swspi.sckPortSet = 1;
  2265. #else // !KINETISK
  2266. *swspi.sckPortSet = swspi.sckPinMask;
  2267. #endif
  2268. #else // !HAS_PORT_SET_CLR
  2269. *swspi.sckPort |= swspi.sckPinMaskSet;
  2270. #endif // end !HAS_PORT_SET_CLR
  2271. #else // !USE_FAST_PINIO
  2272. digitalWrite(swspi._sck, HIGH);
  2273. #endif // end !USE_FAST_PINIO
  2274. }
  2275. /*!
  2276. @brief Set the software (bitbang) SPI SCK line LOW.
  2277. */
  2278. inline void Adafruit_SPITFT::SPI_SCK_LOW(void) {
  2279. #if defined(USE_FAST_PINIO)
  2280. #if defined(HAS_PORT_SET_CLR)
  2281. #if defined(KINETISK)
  2282. *swspi.sckPortClr = 1;
  2283. #else // !KINETISK
  2284. *swspi.sckPortClr = swspi.sckPinMask;
  2285. #endif
  2286. #else // !HAS_PORT_SET_CLR
  2287. *swspi.sckPort &= swspi.sckPinMaskClr;
  2288. #endif // end !HAS_PORT_SET_CLR
  2289. #else // !USE_FAST_PINIO
  2290. digitalWrite(swspi._sck, LOW);
  2291. #endif // end !USE_FAST_PINIO
  2292. }
  2293. /*!
  2294. @brief Read the state of the software (bitbang) SPI MISO line.
  2295. @return true if HIGH, false if LOW.
  2296. */
  2297. inline bool Adafruit_SPITFT::SPI_MISO_READ(void) {
  2298. #if defined(USE_FAST_PINIO)
  2299. #if defined(KINETISK)
  2300. return *swspi.misoPort;
  2301. #else // !KINETISK
  2302. return *swspi.misoPort & swspi.misoPinMask;
  2303. #endif // end !KINETISK
  2304. #else // !USE_FAST_PINIO
  2305. return digitalRead(swspi._miso);
  2306. #endif // end !USE_FAST_PINIO
  2307. }
  2308. /*!
  2309. @brief Issue a single 16-bit value to the display. Chip-select,
  2310. transaction and data/command selection must have been
  2311. previously set -- this ONLY issues the word. Despite the name,
  2312. this function is used even if display connection is parallel;
  2313. name was maintaned for backward compatibility. Naming is also
  2314. not consistent with the 8-bit version, spiWrite(). Sorry about
  2315. that. Again, staying compatible with outside code.
  2316. @param w 16-bit value to write.
  2317. */
  2318. void Adafruit_SPITFT::SPI_WRITE16(uint16_t w) {
  2319. if (connection == TFT_HARD_SPI) {
  2320. #if defined(__AVR__)
  2321. AVR_WRITESPI(w >> 8);
  2322. AVR_WRITESPI(w);
  2323. #elif defined(ESP8266) || defined(ESP32)
  2324. hwspi._spi->write16(w);
  2325. #elif defined(ARDUINO_ARCH_RP2040)
  2326. spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;
  2327. w = __builtin_bswap16(w);
  2328. spi_write_blocking(pi_spi, (uint8_t *)&w, 2);
  2329. #elif defined(ARDUINO_ARCH_RTTHREAD)
  2330. hwspi._spi->transfer16(w);
  2331. #else
  2332. // MSB, LSB because TFTs are generally big-endian
  2333. hwspi._spi->transfer(w >> 8);
  2334. hwspi._spi->transfer(w);
  2335. #endif
  2336. } else if (connection == TFT_SOFT_SPI) {
  2337. for (uint8_t bit = 0; bit < 16; bit++) {
  2338. if (w & 0x8000)
  2339. SPI_MOSI_HIGH();
  2340. else
  2341. SPI_MOSI_LOW();
  2342. SPI_SCK_HIGH();
  2343. SPI_SCK_LOW();
  2344. w <<= 1;
  2345. }
  2346. } else { // TFT_PARALLEL
  2347. #if defined(__AVR__)
  2348. *tft8.writePort = w >> 8;
  2349. TFT_WR_STROBE();
  2350. *tft8.writePort = w;
  2351. #elif defined(USE_FAST_PINIO)
  2352. if (!tft8.wide) {
  2353. *tft8.writePort = w >> 8;
  2354. TFT_WR_STROBE();
  2355. *tft8.writePort = w;
  2356. } else {
  2357. *(volatile uint16_t *)tft8.writePort = w;
  2358. }
  2359. #endif
  2360. TFT_WR_STROBE();
  2361. }
  2362. }
  2363. /*!
  2364. @brief Issue a single 32-bit value to the display. Chip-select,
  2365. transaction and data/command selection must have been
  2366. previously set -- this ONLY issues the longword. Despite the
  2367. name, this function is used even if display connection is
  2368. parallel; name was maintaned for backward compatibility. Naming
  2369. is also not consistent with the 8-bit version, spiWrite().
  2370. Sorry about that. Again, staying compatible with outside code.
  2371. @param l 32-bit value to write.
  2372. */
  2373. void Adafruit_SPITFT::SPI_WRITE32(uint32_t l) {
  2374. if (connection == TFT_HARD_SPI) {
  2375. #if defined(__AVR__)
  2376. AVR_WRITESPI(l >> 24);
  2377. AVR_WRITESPI(l >> 16);
  2378. AVR_WRITESPI(l >> 8);
  2379. AVR_WRITESPI(l);
  2380. #elif defined(ESP8266) || defined(ESP32)
  2381. hwspi._spi->write32(l);
  2382. #elif defined(ARDUINO_ARCH_RP2040)
  2383. spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;
  2384. l = __builtin_bswap32(l);
  2385. spi_write_blocking(pi_spi, (uint8_t *)&l, 4);
  2386. #elif defined(ARDUINO_ARCH_RTTHREAD)
  2387. hwspi._spi->transfer16(l >> 16);
  2388. hwspi._spi->transfer16(l);
  2389. #else
  2390. hwspi._spi->transfer(l >> 24);
  2391. hwspi._spi->transfer(l >> 16);
  2392. hwspi._spi->transfer(l >> 8);
  2393. hwspi._spi->transfer(l);
  2394. #endif
  2395. } else if (connection == TFT_SOFT_SPI) {
  2396. for (uint8_t bit = 0; bit < 32; bit++) {
  2397. if (l & 0x80000000)
  2398. SPI_MOSI_HIGH();
  2399. else
  2400. SPI_MOSI_LOW();
  2401. SPI_SCK_HIGH();
  2402. SPI_SCK_LOW();
  2403. l <<= 1;
  2404. }
  2405. } else { // TFT_PARALLEL
  2406. #if defined(__AVR__)
  2407. *tft8.writePort = l >> 24;
  2408. TFT_WR_STROBE();
  2409. *tft8.writePort = l >> 16;
  2410. TFT_WR_STROBE();
  2411. *tft8.writePort = l >> 8;
  2412. TFT_WR_STROBE();
  2413. *tft8.writePort = l;
  2414. #elif defined(USE_FAST_PINIO)
  2415. if (!tft8.wide) {
  2416. *tft8.writePort = l >> 24;
  2417. TFT_WR_STROBE();
  2418. *tft8.writePort = l >> 16;
  2419. TFT_WR_STROBE();
  2420. *tft8.writePort = l >> 8;
  2421. TFT_WR_STROBE();
  2422. *tft8.writePort = l;
  2423. } else {
  2424. *(volatile uint16_t *)tft8.writePort = l >> 16;
  2425. TFT_WR_STROBE();
  2426. *(volatile uint16_t *)tft8.writePort = l;
  2427. }
  2428. #endif
  2429. TFT_WR_STROBE();
  2430. }
  2431. }
  2432. /*!
  2433. @brief Set the WR line LOW, then HIGH. Used for parallel-connected
  2434. interfaces when writing data.
  2435. */
  2436. inline void Adafruit_SPITFT::TFT_WR_STROBE(void) {
  2437. #if defined(USE_FAST_PINIO)
  2438. #if defined(HAS_PORT_SET_CLR)
  2439. #if defined(KINETISK)
  2440. *tft8.wrPortClr = 1;
  2441. *tft8.wrPortSet = 1;
  2442. #else // !KINETISK
  2443. *tft8.wrPortClr = tft8.wrPinMask;
  2444. *tft8.wrPortSet = tft8.wrPinMask;
  2445. #endif // end !KINETISK
  2446. #else // !HAS_PORT_SET_CLR
  2447. *tft8.wrPort &= tft8.wrPinMaskClr;
  2448. *tft8.wrPort |= tft8.wrPinMaskSet;
  2449. #endif // end !HAS_PORT_SET_CLR
  2450. #else // !USE_FAST_PINIO
  2451. digitalWrite(tft8._wr, LOW);
  2452. digitalWrite(tft8._wr, HIGH);
  2453. #endif // end !USE_FAST_PINIO
  2454. }
  2455. /*!
  2456. @brief Set the RD line HIGH. Used for parallel-connected interfaces
  2457. when reading data.
  2458. */
  2459. inline void Adafruit_SPITFT::TFT_RD_HIGH(void) {
  2460. #if defined(USE_FAST_PINIO)
  2461. #if defined(HAS_PORT_SET_CLR)
  2462. *tft8.rdPortSet = tft8.rdPinMask;
  2463. #else // !HAS_PORT_SET_CLR
  2464. *tft8.rdPort |= tft8.rdPinMaskSet;
  2465. #endif // end !HAS_PORT_SET_CLR
  2466. #else // !USE_FAST_PINIO
  2467. digitalWrite(tft8._rd, HIGH);
  2468. #endif // end !USE_FAST_PINIO
  2469. }
  2470. /*!
  2471. @brief Set the RD line LOW. Used for parallel-connected interfaces
  2472. when reading data.
  2473. */
  2474. inline void Adafruit_SPITFT::TFT_RD_LOW(void) {
  2475. #if defined(USE_FAST_PINIO)
  2476. #if defined(HAS_PORT_SET_CLR)
  2477. *tft8.rdPortClr = tft8.rdPinMask;
  2478. #else // !HAS_PORT_SET_CLR
  2479. *tft8.rdPort &= tft8.rdPinMaskClr;
  2480. #endif // end !HAS_PORT_SET_CLR
  2481. #else // !USE_FAST_PINIO
  2482. digitalWrite(tft8._rd, LOW);
  2483. #endif // end !USE_FAST_PINIO
  2484. }
  2485. #endif // end __AVR_ATtiny85__ __AVR_ATtiny84__