Adafruit_SPITFT.cpp 91 KB

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