TFT_eSPI.cpp 151 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985
  1. /***************************************************
  2. Arduino TFT graphics library targeted at 32 bit
  3. processors such as ESP32, ESP8266 and STM32.
  4. This is a stand-alone library that contains the
  5. hardware driver, the graphics functions and the
  6. proportional fonts.
  7. The larger fonts are Run Length Encoded to reduce their
  8. size.
  9. Created by Bodmer 2/12/16
  10. Last update by Bodmer 20/03/20
  11. ****************************************************/
  12. #include "TFT_eSPI.h"
  13. #if defined (ESP32)
  14. #include "Processors/TFT_eSPI_ESP32.c"
  15. #elif defined (ESP8266)
  16. #include "Processors/TFT_eSPI_ESP8266.c"
  17. #elif defined (STM32) // (_VARIANT_ARDUINO_STM32_) stm32_def.h
  18. #include "Processors/TFT_eSPI_STM32.c"
  19. #elif defined (ARDUINO_ARCH_RP2040) // Raspberry Pi Pico
  20. #include "Processors/TFT_eSPI_RP2040.c"
  21. #else
  22. #include "Processors/TFT_eSPI_Generic.c"
  23. #endif
  24. #ifndef SPI_BUSY_CHECK
  25. #define SPI_BUSY_CHECK
  26. #endif
  27. // Clipping macro for pushImage
  28. #define PI_CLIP \
  29. if (_vpOoB) return; \
  30. x+= _xDatum; \
  31. y+= _yDatum; \
  32. \
  33. if ((x >= _vpW) || (y >= _vpH)) return; \
  34. \
  35. int32_t dx = 0; \
  36. int32_t dy = 0; \
  37. int32_t dw = w; \
  38. int32_t dh = h; \
  39. \
  40. if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } \
  41. if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } \
  42. \
  43. if ((x + dw) > _vpW ) dw = _vpW - x; \
  44. if ((y + dh) > _vpH ) dh = _vpH - y; \
  45. \
  46. if (dw < 1 || dh < 1) return;
  47. /***************************************************************************************
  48. ** Function name: begin_tft_write (was called spi_begin)
  49. ** Description: Start SPI transaction for writes and select TFT
  50. ***************************************************************************************/
  51. inline void TFT_eSPI::begin_tft_write(void){
  52. #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
  53. if (locked) {
  54. locked = false; // Flag to show SPI access now unlocked
  55. spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); // RP2040 SDK -> 68us delay!
  56. CS_L;
  57. SET_BUS_WRITE_MODE; // Some processors (e.g. ESP32) allow recycling the tx buffer when rx is not used
  58. }
  59. #else
  60. CS_L;
  61. SET_BUS_WRITE_MODE;
  62. #endif
  63. }
  64. /***************************************************************************************
  65. ** Function name: end_tft_write (was called spi_end)
  66. ** Description: End transaction for write and deselect TFT
  67. ***************************************************************************************/
  68. inline void TFT_eSPI::end_tft_write(void){
  69. #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
  70. if(!inTransaction) { // Flag to stop ending tranaction during multiple graphics calls
  71. if (!locked) { // Locked when beginTransaction has been called
  72. locked = true; // Flag to show SPI access now locked
  73. SPI_BUSY_CHECK; // Check send complete and clean out unused rx data
  74. CS_H;
  75. spi.endTransaction(); // RP2040 SDK -> 0.7us delay
  76. }
  77. SET_BUS_READ_MODE; // In case SPI has been configured for tx only
  78. }
  79. #else
  80. if(!inTransaction) {SPI_BUSY_CHECK; CS_H; SET_BUS_READ_MODE;}
  81. #endif
  82. }
  83. /***************************************************************************************
  84. ** Function name: begin_tft_read (was called spi_begin_read)
  85. ** Description: Start transaction for reads and select TFT
  86. ***************************************************************************************/
  87. // Reads require a lower SPI clock rate than writes
  88. inline void TFT_eSPI::begin_tft_read(void){
  89. DMA_BUSY_CHECK; // Wait for any DMA transfer to complete before changing SPI settings
  90. #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
  91. if (locked) {
  92. locked = false;
  93. spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
  94. CS_L;
  95. }
  96. #else
  97. #if !defined(TFT_PARALLEL_8_BIT)
  98. spi.setFrequency(SPI_READ_FREQUENCY);
  99. #endif
  100. CS_L;
  101. #endif
  102. SET_BUS_READ_MODE;
  103. }
  104. /***************************************************************************************
  105. ** Function name: setViewport
  106. ** Description: Set the clipping region for the TFT screen
  107. ***************************************************************************************/
  108. void TFT_eSPI::setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum)
  109. {
  110. // Viewport metrics (not clipped)
  111. _xDatum = x; // Datum x position in screen coordinates
  112. _yDatum = y; // Datum y position in screen coordinates
  113. _xWidth = w; // Viewport width
  114. _yHeight = h; // Viewport height
  115. // Full size default viewport
  116. _vpDatum = false; // Datum is at top left corner of screen (true = top left of viewport)
  117. _vpOoB = false; // Out of Bounds flag (true is all of viewport is off screen)
  118. _vpX = 0; // Viewport top left corner x coordinate
  119. _vpY = 0; // Viewport top left corner y coordinate
  120. _vpW = width(); // Equivalent of TFT width (Nb: viewport right edge coord + 1)
  121. _vpH = height(); // Equivalent of TFT height (Nb: viewport bottom edge coord + 1)
  122. // Clip viewport to screen area
  123. if (x<0) { w += x; x = 0; }
  124. if (y<0) { h += y; y = 0; }
  125. if ((x + w) > width() ) { w = width() - x; }
  126. if ((y + h) > height() ) { h = height() - y; }
  127. //Serial.print(" x=");Serial.print( x);Serial.print(", y=");Serial.print( y);
  128. //Serial.print(", w=");Serial.print(w);Serial.print(", h=");Serial.println(h);
  129. // Check if viewport is entirely out of bounds
  130. if (w < 1 || h < 1)
  131. {
  132. // Set default values and Out of Bounds flag in case of error
  133. _xDatum = 0;
  134. _yDatum = 0;
  135. _xWidth = width();
  136. _yHeight = height();
  137. _vpOoB = true; // Set Out of Bounds flag to inhibit all drawing
  138. return;
  139. }
  140. if (!vpDatum)
  141. {
  142. _xDatum = 0; // Reset to top left of screen if not using a viewport datum
  143. _yDatum = 0;
  144. _xWidth = width();
  145. _yHeight = height();
  146. }
  147. // Store the clipped screen viewport metrics and datum position
  148. _vpX = x;
  149. _vpY = y;
  150. _vpW = x + w;
  151. _vpH = y + h;
  152. _vpDatum = vpDatum;
  153. //Serial.print(" _xDatum=");Serial.print( _xDatum);Serial.print(", _yDatum=");Serial.print( _yDatum);
  154. //Serial.print(", _xWidth=");Serial.print(_xWidth);Serial.print(", _yHeight=");Serial.println(_yHeight);
  155. //Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
  156. //Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
  157. }
  158. /***************************************************************************************
  159. ** Function name: checkViewport
  160. ** Description: Check if any part of specified area is visible in viewport
  161. ***************************************************************************************/
  162. // Note: Setting w and h to 1 will check if coordinate x,y is in area
  163. bool TFT_eSPI::checkViewport(int32_t x, int32_t y, int32_t w, int32_t h)
  164. {
  165. if (_vpOoB) return false;
  166. x+= _xDatum;
  167. y+= _yDatum;
  168. if ((x >= _vpW) || (y >= _vpH)) return false;
  169. int32_t dx = 0;
  170. int32_t dy = 0;
  171. int32_t dw = w;
  172. int32_t dh = h;
  173. if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
  174. if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
  175. if ((x + dw) > _vpW ) dw = _vpW - x;
  176. if ((y + dh) > _vpH ) dh = _vpH - y;
  177. if (dw < 1 || dh < 1) return false;
  178. return true;
  179. }
  180. /***************************************************************************************
  181. ** Function name: resetViewport
  182. ** Description: Reset viewport to whle TFT screen, datum at 0,0
  183. ***************************************************************************************/
  184. void TFT_eSPI::resetViewport(void)
  185. {
  186. // Reset viewport to the whole screen (or sprite) area
  187. _vpDatum = false;
  188. _vpOoB = false;
  189. _xDatum = 0;
  190. _yDatum = 0;
  191. _vpX = 0;
  192. _vpY = 0;
  193. _vpW = width();
  194. _vpH = height();
  195. _xWidth = width();
  196. _yHeight = height();
  197. }
  198. /***************************************************************************************
  199. ** Function name: getViewportX
  200. ** Description: Get x position of the viewport datum
  201. ***************************************************************************************/
  202. int32_t TFT_eSPI::getViewportX(void)
  203. {
  204. return _xDatum;
  205. }
  206. /***************************************************************************************
  207. ** Function name: getViewportY
  208. ** Description: Get y position of the viewport datum
  209. ***************************************************************************************/
  210. int32_t TFT_eSPI::getViewportY(void)
  211. {
  212. return _yDatum;
  213. }
  214. /***************************************************************************************
  215. ** Function name: getViewportWidth
  216. ** Description: Get width of the viewport
  217. ***************************************************************************************/
  218. int32_t TFT_eSPI::getViewportWidth(void)
  219. {
  220. return _xWidth;
  221. }
  222. /***************************************************************************************
  223. ** Function name: getViewportHeight
  224. ** Description: Get height of the viewport
  225. ***************************************************************************************/
  226. int32_t TFT_eSPI::getViewportHeight(void)
  227. {
  228. return _yHeight;
  229. }
  230. /***************************************************************************************
  231. ** Function name: getViewportDatum
  232. ** Description: Get datum flag of the viewport (true = viewport corner)
  233. ***************************************************************************************/
  234. bool TFT_eSPI::getViewportDatum(void)
  235. {
  236. return _vpDatum;
  237. }
  238. /***************************************************************************************
  239. ** Function name: frameViewport
  240. ** Description: Draw a frame inside or outside the viewport of width w
  241. ***************************************************************************************/
  242. void TFT_eSPI::frameViewport(uint16_t color, int32_t w)
  243. {
  244. // Save datum position
  245. bool _dT = _vpDatum;
  246. // If w is positive the frame is drawn inside the viewport
  247. // a large positive width will clear the screen inside the viewport
  248. if (w>0)
  249. {
  250. // Set vpDatum true to simplify coordinate derivation
  251. _vpDatum = true;
  252. fillRect(0, 0, _vpW - _vpX, w, color); // Top
  253. fillRect(0, w, w, _vpH - _vpY - w - w, color); // Left
  254. fillRect(_xWidth - w, w, w, _yHeight - w - w, color); // Right
  255. fillRect(0, _yHeight - w, _xWidth, w, color); // Bottom
  256. }
  257. else
  258. // If w is negative the frame is drawn outside the viewport
  259. // a large negative width will clear the screen outside the viewport
  260. {
  261. w = -w;
  262. // Save old values
  263. int32_t _xT = _vpX; _vpX = 0;
  264. int32_t _yT = _vpY; _vpY = 0;
  265. int32_t _wT = _vpW;
  266. int32_t _hT = _vpH;
  267. // Set vpDatum false so frame can be drawn outside window
  268. _vpDatum = false; // When false the full width and height is accessed
  269. _vpH = height();
  270. _vpW = width();
  271. // Draw frame
  272. fillRect(_xT - w - _xDatum, _yT - w - _yDatum, _wT - _xT + w + w, w, color); // Top
  273. fillRect(_xT - w - _xDatum, _yT - _yDatum, w, _hT - _yT, color); // Left
  274. fillRect(_wT - _xDatum, _yT - _yDatum, w, _hT - _yT, color); // Right
  275. fillRect(_xT - w - _xDatum, _hT - _yDatum, _wT - _xT + w + w, w, color); // Bottom
  276. // Restore old values
  277. _vpX = _xT;
  278. _vpY = _yT;
  279. _vpW = _wT;
  280. _vpH = _hT;
  281. }
  282. // Restore vpDatum
  283. _vpDatum = _dT;
  284. }
  285. /***************************************************************************************
  286. ** Function name: end_tft_read (was called spi_end_read)
  287. ** Description: End transaction for reads and deselect TFT
  288. ***************************************************************************************/
  289. inline void TFT_eSPI::end_tft_read(void){
  290. #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
  291. if(!inTransaction) {
  292. if (!locked) {
  293. locked = true;
  294. CS_H;
  295. spi.endTransaction();
  296. }
  297. }
  298. #else
  299. #if !defined(TFT_PARALLEL_8_BIT)
  300. spi.setFrequency(SPI_FREQUENCY);
  301. #endif
  302. if(!inTransaction) {CS_H;}
  303. #endif
  304. SET_BUS_WRITE_MODE;
  305. // The ST7796 appears to need a 4ms delay after a CGRAM read, otherwise subsequent writes will fail!
  306. #ifdef ST7796_DRIVER
  307. delay(4);
  308. #endif
  309. }
  310. /***************************************************************************************
  311. ** Function name: Legacy - deprecated
  312. ** Description: Start/end transaction
  313. ***************************************************************************************/
  314. void TFT_eSPI::spi_begin() {begin_tft_write();}
  315. void TFT_eSPI::spi_end() { end_tft_write();}
  316. void TFT_eSPI::spi_begin_read() {begin_tft_read(); }
  317. void TFT_eSPI::spi_end_read() { end_tft_read(); }
  318. /***************************************************************************************
  319. ** Function name: TFT_eSPI
  320. ** Description: Constructor , we must use hardware SPI pins
  321. ***************************************************************************************/
  322. TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
  323. {
  324. // The control pins are deliberately set to the inactive state (CS high) as setup()
  325. // might call and initialise other SPI peripherals which would could cause conflicts
  326. // if CS is floating or undefined.
  327. #ifdef TFT_CS
  328. pinMode(TFT_CS, OUTPUT);
  329. digitalWrite(TFT_CS, HIGH); // Chip select high (inactive)
  330. #endif
  331. // Configure chip select for touchscreen controller if present
  332. #ifdef TOUCH_CS
  333. pinMode(TOUCH_CS, OUTPUT);
  334. digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
  335. #endif
  336. #ifdef TFT_WR
  337. pinMode(TFT_WR, OUTPUT);
  338. digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive)
  339. #endif
  340. #ifdef TFT_DC
  341. pinMode(TFT_DC, OUTPUT);
  342. digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode
  343. #endif
  344. #ifdef TFT_RST
  345. if (TFT_RST >= 0) {
  346. pinMode(TFT_RST, OUTPUT);
  347. digitalWrite(TFT_RST, HIGH); // Set high, do not share pin with another SPI device
  348. }
  349. #endif
  350. #if defined (TFT_PARALLEL_8_BIT)
  351. // Make sure read is high before we set the bus to output
  352. pinMode(TFT_RD, OUTPUT);
  353. digitalWrite(TFT_RD, HIGH);
  354. // Set TFT data bus lines to output
  355. pinMode(TFT_D0, OUTPUT); digitalWrite(TFT_D0, HIGH);
  356. pinMode(TFT_D1, OUTPUT); digitalWrite(TFT_D1, HIGH);
  357. pinMode(TFT_D2, OUTPUT); digitalWrite(TFT_D2, HIGH);
  358. pinMode(TFT_D3, OUTPUT); digitalWrite(TFT_D3, HIGH);
  359. pinMode(TFT_D4, OUTPUT); digitalWrite(TFT_D4, HIGH);
  360. pinMode(TFT_D5, OUTPUT); digitalWrite(TFT_D5, HIGH);
  361. pinMode(TFT_D6, OUTPUT); digitalWrite(TFT_D6, HIGH);
  362. pinMode(TFT_D7, OUTPUT); digitalWrite(TFT_D7, HIGH);
  363. CONSTRUCTOR_INIT_TFT_DATA_BUS;
  364. #endif
  365. _init_width = _width = w; // Set by specific xxxxx_Defines.h file or by users sketch
  366. _init_height = _height = h; // Set by specific xxxxx_Defines.h file or by users sketch
  367. // Reset the viewport to the whole screen
  368. resetViewport();
  369. rotation = 0;
  370. cursor_y = cursor_x = 0;
  371. textfont = 1;
  372. textsize = 1;
  373. textcolor = bitmap_fg = 0xFFFF; // White
  374. textbgcolor = bitmap_bg = 0x0000; // Black
  375. padX = 0; // No padding
  376. isDigits = false; // No bounding box adjustment
  377. textwrapX = true; // Wrap text at end of line when using print stream
  378. textwrapY = false; // Wrap text at bottom of screen when using print stream
  379. textdatum = TL_DATUM; // Top Left text alignment is default
  380. fontsloaded = 0;
  381. _swapBytes = false; // Do not swap colour bytes by default
  382. locked = true; // Transaction mutex lock flag to ensure begin/endTranaction pairing
  383. inTransaction = false; // Flag to prevent multiple sequential functions to keep bus access open
  384. lockTransaction = false; // start/endWrite lock flag to allow sketch to keep SPI bus access open
  385. _booted = true; // Default attributes
  386. _cp437 = true; // Legacy GLCD font bug fix
  387. _utf8 = true; // UTF8 decoding enabled
  388. #ifdef FONT_FS_AVAILABLE
  389. fs_font = true; // Smooth font filing system or array (fs_font = false) flag
  390. #endif
  391. #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT)
  392. if (psramFound()) _psram_enable = true; // Enable the use of PSRAM (if available)
  393. else
  394. #endif
  395. _psram_enable = false;
  396. addr_row = 0xFFFF; // drawPixel command length optimiser
  397. addr_col = 0xFFFF; // drawPixel command length optimiser
  398. _xPivot = 0;
  399. _yPivot = 0;
  400. // Legacy support for bit GPIO masks
  401. cspinmask = 0;
  402. dcpinmask = 0;
  403. wrpinmask = 0;
  404. sclkpinmask = 0;
  405. // Flags for which fonts are loaded
  406. #ifdef LOAD_GLCD
  407. fontsloaded = 0x0002; // Bit 1 set
  408. #endif
  409. #ifdef LOAD_FONT2
  410. fontsloaded |= 0x0004; // Bit 2 set
  411. #endif
  412. #ifdef LOAD_FONT4
  413. fontsloaded |= 0x0010; // Bit 4 set
  414. #endif
  415. #ifdef LOAD_FONT6
  416. fontsloaded |= 0x0040; // Bit 6 set
  417. #endif
  418. #ifdef LOAD_FONT7
  419. fontsloaded |= 0x0080; // Bit 7 set
  420. #endif
  421. #ifdef LOAD_FONT8
  422. fontsloaded |= 0x0100; // Bit 8 set
  423. #endif
  424. #ifdef LOAD_FONT8N
  425. fontsloaded |= 0x0200; // Bit 9 set
  426. #endif
  427. #ifdef SMOOTH_FONT
  428. fontsloaded |= 0x8000; // Bit 15 set
  429. #endif
  430. }
  431. /***************************************************************************************
  432. ** Function name: begin
  433. ** Description: Included for backwards compatibility
  434. ***************************************************************************************/
  435. void TFT_eSPI::begin(uint8_t tc)
  436. {
  437. init(tc);
  438. }
  439. /***************************************************************************************
  440. ** Function name: init (tc is tab colour for ST7735 displays only)
  441. ** Description: Reset, then initialise the TFT display registers
  442. ***************************************************************************************/
  443. void TFT_eSPI::init(uint8_t tc)
  444. {
  445. if (_booted)
  446. {
  447. #if !defined (ESP32) && !defined(TFT_PARALLEL_8_BIT) && !defined(ARDUINO_ARCH_RP2040)
  448. // Legacy bitmasks for GPIO
  449. #if defined (TFT_CS) && (TFT_CS >= 0)
  450. cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS);
  451. #endif
  452. #if defined (TFT_DC) && (TFT_DC >= 0)
  453. dcpinmask = (uint32_t) digitalPinToBitMask(TFT_DC);
  454. #endif
  455. #if defined (TFT_WR) && (TFT_WR >= 0)
  456. wrpinmask = (uint32_t) digitalPinToBitMask(TFT_WR);
  457. #endif
  458. #if defined (TFT_SCLK) && (TFT_SCLK >= 0)
  459. sclkpinmask = (uint32_t) digitalPinToBitMask(TFT_SCLK);
  460. #endif
  461. #if defined (TFT_SPI_OVERLAP) && defined (ESP8266)
  462. // #pragma GCC diagnostic ignored "TFT_SPI_OVERLAP defined"
  463. // #pragma GCC diagnostic warning "TFT_SPI_OVERLAP defined"
  464. // Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS
  465. // pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss);
  466. spi.pins( 6, 7, 8, 0);
  467. //spi.pins(10, 13, 14, 9);
  468. #endif
  469. spi.begin(); // This will set HMISO to input
  470. #else
  471. #if !defined(TFT_PARALLEL_8_BIT)
  472. #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040)
  473. spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
  474. #else
  475. spi.begin();
  476. #endif
  477. #endif
  478. #endif
  479. lockTransaction = false;
  480. inTransaction = false;
  481. locked = true;
  482. INIT_TFT_DATA_BUS;
  483. #ifdef TFT_CS
  484. // Set to output once again in case ESP8266 D6 (MISO) is used for CS
  485. pinMode(TFT_CS, OUTPUT);
  486. digitalWrite(TFT_CS, HIGH); // Chip select high (inactive)
  487. #elif defined (ESP8266) && !defined (TFT_PARALLEL_8_BIT)
  488. spi.setHwCs(1); // Use hardware SS toggling
  489. #endif
  490. // Set to output once again in case ESP8266 D6 (MISO) is used for DC
  491. #ifdef TFT_DC
  492. pinMode(TFT_DC, OUTPUT);
  493. digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode
  494. #endif
  495. _booted = false;
  496. end_tft_write();
  497. } // end of: if just _booted
  498. // Toggle RST low to reset
  499. #ifdef TFT_RST
  500. if (TFT_RST >= 0) {
  501. digitalWrite(TFT_RST, HIGH);
  502. delay(5);
  503. digitalWrite(TFT_RST, LOW);
  504. delay(20);
  505. digitalWrite(TFT_RST, HIGH);
  506. }
  507. else writecommand(TFT_SWRST); // Software reset
  508. #else
  509. writecommand(TFT_SWRST); // Software reset
  510. #endif
  511. delay(150); // Wait for reset to complete
  512. begin_tft_write();
  513. tc = tc; // Supress warning
  514. // This loads the driver specific initialisation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<<
  515. #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER)
  516. #include "TFT_Drivers/ILI9341_Init.h"
  517. #elif defined (ST7735_DRIVER)
  518. tabcolor = tc;
  519. #include "TFT_Drivers/ST7735_Init.h"
  520. #elif defined (ILI9163_DRIVER)
  521. #include "TFT_Drivers/ILI9163_Init.h"
  522. #elif defined (S6D02A1_DRIVER)
  523. #include "TFT_Drivers/S6D02A1_Init.h"
  524. #elif defined (ST7796_DRIVER)
  525. #include "TFT_Drivers/ST7796_Init.h"
  526. #elif defined (ILI9486_DRIVER)
  527. #include "TFT_Drivers/ILI9486_Init.h"
  528. #elif defined (ILI9481_DRIVER)
  529. #include "TFT_Drivers/ILI9481_Init.h"
  530. #elif defined (ILI9488_DRIVER)
  531. #include "TFT_Drivers/ILI9488_Init.h"
  532. #elif defined (HX8357D_DRIVER)
  533. #include "TFT_Drivers/HX8357D_Init.h"
  534. #elif defined (ST7789_DRIVER)
  535. #include "TFT_Drivers/ST7789_Init.h"
  536. #elif defined (R61581_DRIVER)
  537. #include "TFT_Drivers/R61581_Init.h"
  538. #elif defined (RM68140_DRIVER)
  539. #include "TFT_Drivers/RM68140_Init.h"
  540. #elif defined (ST7789_2_DRIVER)
  541. #include "TFT_Drivers/ST7789_2_Init.h"
  542. #elif defined (SSD1351_DRIVER)
  543. #include "TFT_Drivers/SSD1351_Init.h"
  544. #elif defined (SSD1963_DRIVER)
  545. #include "TFT_Drivers/SSD1963_Init.h"
  546. #elif defined (GC9A01_DRIVER)
  547. #include "TFT_Drivers/GC9A01_Init.h"
  548. #elif defined (ILI9225_DRIVER)
  549. #include "TFT_Drivers/ILI9225_Init.h"
  550. #endif
  551. #ifdef TFT_INVERSION_ON
  552. writecommand(TFT_INVON);
  553. #endif
  554. #ifdef TFT_INVERSION_OFF
  555. writecommand(TFT_INVOFF);
  556. #endif
  557. end_tft_write();
  558. setRotation(rotation);
  559. #if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON)
  560. pinMode(TFT_BL, OUTPUT);
  561. digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
  562. #else
  563. #if defined (TFT_BL) && defined (M5STACK)
  564. // Turn on the back-light LED
  565. pinMode(TFT_BL, OUTPUT);
  566. digitalWrite(TFT_BL, HIGH);
  567. #endif
  568. #endif
  569. }
  570. /***************************************************************************************
  571. ** Function name: setRotation
  572. ** Description: rotate the screen orientation m = 0-3 or 4-7 for BMP drawing
  573. ***************************************************************************************/
  574. void TFT_eSPI::setRotation(uint8_t m)
  575. {
  576. begin_tft_write();
  577. // This loads the driver specific rotation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<<
  578. #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER)
  579. #include "TFT_Drivers/ILI9341_Rotation.h"
  580. #elif defined (ST7735_DRIVER)
  581. #include "TFT_Drivers/ST7735_Rotation.h"
  582. #elif defined (ILI9163_DRIVER)
  583. #include "TFT_Drivers/ILI9163_Rotation.h"
  584. #elif defined (S6D02A1_DRIVER)
  585. #include "TFT_Drivers/S6D02A1_Rotation.h"
  586. #elif defined (ST7796_DRIVER)
  587. #include "TFT_Drivers/ST7796_Rotation.h"
  588. #elif defined (ILI9486_DRIVER)
  589. #include "TFT_Drivers/ILI9486_Rotation.h"
  590. #elif defined (ILI9481_DRIVER)
  591. #include "TFT_Drivers/ILI9481_Rotation.h"
  592. #elif defined (ILI9488_DRIVER)
  593. #include "TFT_Drivers/ILI9488_Rotation.h"
  594. #elif defined (HX8357D_DRIVER)
  595. #include "TFT_Drivers/HX8357D_Rotation.h"
  596. #elif defined (ST7789_DRIVER)
  597. #include "TFT_Drivers/ST7789_Rotation.h"
  598. #elif defined (R61581_DRIVER)
  599. #include "TFT_Drivers/R61581_Rotation.h"
  600. #elif defined (RM68140_DRIVER)
  601. #include "TFT_Drivers/RM68140_Rotation.h"
  602. #elif defined (ST7789_2_DRIVER)
  603. #include "TFT_Drivers/ST7789_2_Rotation.h"
  604. #elif defined (SSD1351_DRIVER)
  605. #include "TFT_Drivers/SSD1351_Rotation.h"
  606. #elif defined (SSD1963_DRIVER)
  607. #include "TFT_Drivers/SSD1963_Rotation.h"
  608. #elif defined (GC9A01_DRIVER)
  609. #include "TFT_Drivers/GC9A01_Rotation.h"
  610. #elif defined (ILI9225_DRIVER)
  611. #include "TFT_Drivers/ILI9225_Rotation.h"
  612. #endif
  613. delayMicroseconds(10);
  614. end_tft_write();
  615. addr_row = 0xFFFF;
  616. addr_col = 0xFFFF;
  617. // Reset the viewport to the whole screen
  618. resetViewport();
  619. }
  620. /***************************************************************************************
  621. ** Function name: commandList, used for FLASH based lists only (e.g. ST7735)
  622. ** Description: Get initialisation commands from FLASH and send to TFT
  623. ***************************************************************************************/
  624. void TFT_eSPI::commandList (const uint8_t *addr)
  625. {
  626. uint8_t numCommands;
  627. uint8_t numArgs;
  628. uint8_t ms;
  629. numCommands = pgm_read_byte(addr++); // Number of commands to follow
  630. while (numCommands--) // For each command...
  631. {
  632. writecommand(pgm_read_byte(addr++)); // Read, issue command
  633. numArgs = pgm_read_byte(addr++); // Number of args to follow
  634. ms = numArgs & TFT_INIT_DELAY; // If hibit set, delay follows args
  635. numArgs &= ~TFT_INIT_DELAY; // Mask out delay bit
  636. while (numArgs--) // For each argument...
  637. {
  638. writedata(pgm_read_byte(addr++)); // Read, issue argument
  639. }
  640. if (ms)
  641. {
  642. ms = pgm_read_byte(addr++); // Read post-command delay time (ms)
  643. delay( (ms==255 ? 500 : ms) );
  644. }
  645. }
  646. }
  647. /***************************************************************************************
  648. ** Function name: spiwrite
  649. ** Description: Write 8 bits to SPI port (legacy support only)
  650. ***************************************************************************************/
  651. void TFT_eSPI::spiwrite(uint8_t c)
  652. {
  653. begin_tft_write();
  654. tft_Write_8(c);
  655. end_tft_write();
  656. }
  657. /***************************************************************************************
  658. ** Function name: writecommand
  659. ** Description: Send an 8 bit command to the TFT
  660. ***************************************************************************************/
  661. void TFT_eSPI::writecommand(uint8_t c)
  662. {
  663. begin_tft_write();
  664. DC_C;
  665. tft_Write_8(c);
  666. DC_D;
  667. end_tft_write();
  668. }
  669. /***************************************************************************************
  670. ** Function name: writedata
  671. ** Description: Send a 8 bit data value to the TFT
  672. ***************************************************************************************/
  673. void TFT_eSPI::writedata(uint8_t d)
  674. {
  675. begin_tft_write();
  676. DC_D; // Play safe, but should already be in data mode
  677. tft_Write_8(d);
  678. CS_L; // Allow more hold time for low VDI rail
  679. end_tft_write();
  680. }
  681. /***************************************************************************************
  682. ** Function name: readcommand8
  683. ** Description: Read a 8 bit data value from an indexed command register
  684. ***************************************************************************************/
  685. uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index)
  686. {
  687. uint8_t reg = 0;
  688. #ifdef TFT_PARALLEL_8_BIT
  689. writecommand(cmd_function); // Sets DC and CS high
  690. busDir(dir_mask, INPUT);
  691. CS_L;
  692. // Read nth parameter (assumes caller discards 1st parameter or points index to 2nd)
  693. while(index--) reg = readByte();
  694. busDir(dir_mask, OUTPUT);
  695. CS_H;
  696. #else // SPI interface
  697. // Tested with ILI9341 set to Interface II i.e. IM [3:0] = "1101"
  698. begin_tft_read();
  699. index = 0x10 + (index & 0x0F);
  700. DC_C; tft_Write_8(0xD9);
  701. DC_D; tft_Write_8(index);
  702. CS_H; // Some displays seem to need CS to be pulsed here, or is just a delay needed?
  703. CS_L;
  704. DC_C; tft_Write_8(cmd_function);
  705. DC_D;
  706. reg = tft_Read_8();
  707. end_tft_read();
  708. #endif
  709. return reg;
  710. }
  711. /***************************************************************************************
  712. ** Function name: readcommand16
  713. ** Description: Read a 16 bit data value from an indexed command register
  714. ***************************************************************************************/
  715. uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index)
  716. {
  717. uint32_t reg;
  718. reg = (readcommand8(cmd_function, index + 0) << 8);
  719. reg |= (readcommand8(cmd_function, index + 1) << 0);
  720. return reg;
  721. }
  722. /***************************************************************************************
  723. ** Function name: readcommand32
  724. ** Description: Read a 32 bit data value from an indexed command register
  725. ***************************************************************************************/
  726. uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index)
  727. {
  728. uint32_t reg;
  729. reg = ((uint32_t)readcommand8(cmd_function, index + 0) << 24);
  730. reg |= ((uint32_t)readcommand8(cmd_function, index + 1) << 16);
  731. reg |= ((uint32_t)readcommand8(cmd_function, index + 2) << 8);
  732. reg |= ((uint32_t)readcommand8(cmd_function, index + 3) << 0);
  733. return reg;
  734. }
  735. /***************************************************************************************
  736. ** Function name: read pixel (for SPI Interface II i.e. IM [3:0] = "1101")
  737. ** Description: Read 565 pixel colours from a pixel
  738. ***************************************************************************************/
  739. uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
  740. {
  741. if (_vpOoB) return 0;
  742. x0+= _xDatum;
  743. y0+= _yDatum;
  744. // Range checking
  745. if ((x0 < _vpX) || (y0 < _vpY) ||(x0 >= _vpW) || (y0 >= _vpH)) return 0;
  746. #if defined(TFT_PARALLEL_8_BIT)
  747. CS_L;
  748. readAddrWindow(x0, y0, 1, 1);
  749. // Set masked pins D0- D7 to input
  750. busDir(dir_mask, INPUT);
  751. #if !defined (SSD1963_DRIVER)
  752. // Dummy read to throw away don't care value
  753. readByte();
  754. #endif
  755. // Fetch the 16 bit BRG pixel
  756. //uint16_t rgb = (readByte() << 8) | readByte();
  757. #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9488_DRIVER) || defined (SSD1963_DRIVER)// Read 3 bytes
  758. // Read window pixel 24 bit RGB values and fill in LS bits
  759. uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3);
  760. CS_H;
  761. // Set masked pins D0- D7 to output
  762. busDir(dir_mask, OUTPUT);
  763. return rgb;
  764. #else // ILI9481 or ILI9486 16 bit read
  765. // Fetch the 16 bit BRG pixel
  766. uint16_t bgr = (readByte() << 8) | readByte();
  767. CS_H;
  768. // Set masked pins D0- D7 to output
  769. busDir(dir_mask, OUTPUT);
  770. #ifdef ILI9486_DRIVER
  771. return bgr;
  772. #else
  773. // Swap Red and Blue (could check MADCTL setting to see if this is needed)
  774. return (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
  775. #endif
  776. #endif
  777. #else // Not TFT_PARALLEL_8_BIT
  778. // This function can get called during antialiased font rendering
  779. // so a transaction may be in progress
  780. bool wasInTransaction = inTransaction;
  781. if (inTransaction) { inTransaction= false; end_tft_write();}
  782. uint16_t color = 0;
  783. begin_tft_read();
  784. readAddrWindow(x0, y0, 1, 1); // Sets CS low
  785. #ifdef TFT_SDA_READ
  786. begin_SDA_Read();
  787. #endif
  788. // Dummy read to throw away don't care value
  789. tft_Read_8();
  790. //#if !defined (ILI9488_DRIVER)
  791. #if defined (ST7796_DRIVER)
  792. // Read the 2 bytes
  793. color = ((tft_Read_8()) << 8) | (tft_Read_8());
  794. #else
  795. // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
  796. // as the TFT stores colours as 18 bits
  797. uint8_t r = tft_Read_8();
  798. uint8_t g = tft_Read_8();
  799. uint8_t b = tft_Read_8();
  800. color = color565(r, g, b);
  801. #endif
  802. /*
  803. #else
  804. // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse
  805. // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left
  806. uint8_t r = (tft_Read_8()&0x7E)<<1;
  807. uint8_t g = (tft_Read_8()&0x7E)<<1;
  808. uint8_t b = (tft_Read_8()&0x7E)<<1;
  809. color = color565(r, g, b);
  810. #endif
  811. */
  812. CS_H;
  813. #ifdef TFT_SDA_READ
  814. end_SDA_Read();
  815. #endif
  816. end_tft_read();
  817. // Reinstate the transaction if one was in progress
  818. if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
  819. return color;
  820. #endif
  821. }
  822. void TFT_eSPI::setCallback(getColorCallback getCol)
  823. {
  824. getColor = getCol;
  825. }
  826. /***************************************************************************************
  827. ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
  828. ** Description: Read 565 pixel colours from a defined area
  829. ***************************************************************************************/
  830. void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
  831. {
  832. PI_CLIP ;
  833. #if defined(TFT_PARALLEL_8_BIT)
  834. CS_L;
  835. readAddrWindow(x, y, dw, dh);
  836. data += dx + dy * w;
  837. // Set masked pins D0- D7 to input
  838. busDir(dir_mask, INPUT);
  839. #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9488_DRIVER) // Read 3 bytes
  840. // Dummy read to throw away don't care value
  841. readByte();
  842. // Fetch the 24 bit RGB value
  843. while (dh--) {
  844. int32_t lw = dw;
  845. uint16_t* line = data;
  846. while (lw--) {
  847. // Assemble the RGB 16 bit colour
  848. uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3);
  849. // Swapped byte order for compatibility with pushRect()
  850. *line++ = (rgb<<8) | (rgb>>8);
  851. }
  852. data += w;
  853. }
  854. #elif defined (SSD1963_DRIVER)
  855. // Fetch the 18 bit BRG pixels
  856. while (dh--) {
  857. int32_t lw = dw;
  858. uint16_t* line = data;
  859. while (lw--) {
  860. uint16_t bgr = ((readByte() & 0xF8) >> 3);; // CS_L adds a small delay
  861. bgr |= ((readByte() & 0xFC) << 3);
  862. bgr |= (readByte() << 8);
  863. // Swap Red and Blue (could check MADCTL setting to see if this is needed)
  864. uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
  865. // Swapped byte order for compatibility with pushRect()
  866. *line++ = (rgb<<8) | (rgb>>8);
  867. }
  868. data += w;
  869. }
  870. #else // ILI9481 reads as 16 bits
  871. // Dummy read to throw away don't care value
  872. readByte();
  873. // Fetch the 16 bit BRG pixels
  874. while (dh--) {
  875. int32_t lw = dw;
  876. uint16_t* line = data;
  877. while (lw--) {
  878. #ifdef ILI9486_DRIVER
  879. // Read the RGB 16 bit colour
  880. *line++ = readByte() | (readByte() << 8);
  881. #else
  882. // Read the BRG 16 bit colour
  883. uint16_t bgr = (readByte() << 8) | readByte();
  884. // Swap Red and Blue (could check MADCTL setting to see if this is needed)
  885. uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
  886. // Swapped byte order for compatibility with pushRect()
  887. *line++ = (rgb<<8) | (rgb>>8);
  888. #endif
  889. }
  890. data += w;
  891. }
  892. #endif
  893. CS_H;
  894. // Set masked pins D0- D7 to output
  895. busDir(dir_mask, OUTPUT);
  896. #else // SPI interface
  897. // This function can get called after a begin_tft_write
  898. // so a transaction may be in progress
  899. bool wasInTransaction = inTransaction;
  900. if (inTransaction) { inTransaction= false; end_tft_write();}
  901. uint16_t color = 0;
  902. begin_tft_read();
  903. readAddrWindow(x, y, dw, dh);
  904. data += dx + dy * w;
  905. #ifdef TFT_SDA_READ
  906. begin_SDA_Read();
  907. #endif
  908. // Dummy read to throw away don't care value
  909. tft_Read_8();
  910. // Read window pixel 24 bit RGB values
  911. while (dh--) {
  912. int32_t lw = dw;
  913. uint16_t* line = data;
  914. while (lw--) {
  915. #if !defined (ILI9488_DRIVER)
  916. #if defined (ST7796_DRIVER)
  917. // Read the 2 bytes
  918. color = ((tft_Read_8()) << 8) | (tft_Read_8());
  919. #else
  920. // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
  921. // as the TFT stores colours as 18 bits
  922. uint8_t r = tft_Read_8();
  923. uint8_t g = tft_Read_8();
  924. uint8_t b = tft_Read_8();
  925. color = color565(r, g, b);
  926. #endif
  927. #else
  928. // The 6 colour bits are in MS 6 bits of each byte but we do not include the extra clock pulse
  929. // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left
  930. uint8_t r = (tft_Read_8()&0x7E)<<1;
  931. uint8_t g = (tft_Read_8()&0x7E)<<1;
  932. uint8_t b = (tft_Read_8()&0x7E)<<1;
  933. color = color565(r, g, b);
  934. #endif
  935. // Swapped colour byte order for compatibility with pushRect()
  936. *line++ = color << 8 | color >> 8;
  937. }
  938. data += w;
  939. }
  940. //CS_H;
  941. #ifdef TFT_SDA_READ
  942. end_SDA_Read();
  943. #endif
  944. end_tft_read();
  945. // Reinstate the transaction if one was in progress
  946. if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
  947. #endif
  948. }
  949. /***************************************************************************************
  950. ** Function name: push rectangle
  951. ** Description: push 565 pixel colours into a defined area
  952. ***************************************************************************************/
  953. void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
  954. {
  955. bool swap = _swapBytes; _swapBytes = false;
  956. pushImage(x, y, w, h, data);
  957. _swapBytes = swap;
  958. }
  959. /***************************************************************************************
  960. ** Function name: pushImage
  961. ** Description: plot 16 bit colour sprite or image onto TFT
  962. ***************************************************************************************/
  963. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
  964. {
  965. PI_CLIP;
  966. begin_tft_write();
  967. inTransaction = true;
  968. setWindow(x, y, x + dw - 1, y + dh - 1);
  969. data += dx + dy * w;
  970. // Check if whole image can be pushed
  971. if (dw == w) pushPixels(data, dw * dh);
  972. else {
  973. // Push line segments to crop image
  974. while (dh--)
  975. {
  976. pushPixels(data, dw);
  977. data += w;
  978. }
  979. }
  980. inTransaction = lockTransaction;
  981. end_tft_write();
  982. }
  983. /***************************************************************************************
  984. ** Function name: pushImage
  985. ** Description: plot 16 bit sprite or image with 1 colour being transparent
  986. ***************************************************************************************/
  987. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp)
  988. {
  989. PI_CLIP;
  990. begin_tft_write();
  991. inTransaction = true;
  992. data += dx + dy * w;
  993. int32_t xe = x + dw - 1, ye = y + dh - 1;
  994. uint16_t lineBuf[dw]; // Use buffer to minimise setWindow call count
  995. // The little endian transp color must be byte swapped if the image is big endian
  996. if (!_swapBytes) transp = transp >> 8 | transp << 8;
  997. while (dh--)
  998. {
  999. int32_t len = dw;
  1000. uint16_t* ptr = data;
  1001. int32_t px = x;
  1002. bool move = true;
  1003. uint16_t np = 0;
  1004. while (len--)
  1005. {
  1006. if (transp != *ptr)
  1007. {
  1008. if (move) { move = false; setWindow(px, y, xe, ye); }
  1009. lineBuf[np] = *ptr;
  1010. np++;
  1011. }
  1012. else
  1013. {
  1014. move = true;
  1015. if (np)
  1016. {
  1017. pushPixels((uint16_t*)lineBuf, np);
  1018. np = 0;
  1019. }
  1020. }
  1021. px++;
  1022. ptr++;
  1023. }
  1024. if (np) pushPixels((uint16_t*)lineBuf, np);
  1025. y++;
  1026. data += w;
  1027. }
  1028. inTransaction = lockTransaction;
  1029. end_tft_write();
  1030. }
  1031. /***************************************************************************************
  1032. ** Function name: pushImage - for FLASH (PROGMEM) stored images
  1033. ** Description: plot 16 bit image
  1034. ***************************************************************************************/
  1035. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data)
  1036. {
  1037. // Requires 32 bit aligned access, so use PROGMEM 16 bit word functions
  1038. PI_CLIP;
  1039. begin_tft_write();
  1040. inTransaction = true;
  1041. data += dx + dy * w;
  1042. uint16_t buffer[dw];
  1043. setWindow(x, y, x + dw - 1, y + dh - 1);
  1044. // Fill and send line buffers to TFT
  1045. for (int32_t i = 0; i < dh; i++) {
  1046. for (int32_t j = 0; j < dw; j++) {
  1047. buffer[j] = pgm_read_word(&data[i * w + j]);
  1048. }
  1049. pushPixels(buffer, dw);
  1050. }
  1051. inTransaction = lockTransaction;
  1052. end_tft_write();
  1053. }
  1054. /***************************************************************************************
  1055. ** Function name: pushImage - for FLASH (PROGMEM) stored images
  1056. ** Description: plot 16 bit image with 1 colour being transparent
  1057. ***************************************************************************************/
  1058. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp)
  1059. {
  1060. // Requires 32 bit aligned access, so use PROGMEM 16 bit word functions
  1061. PI_CLIP;
  1062. begin_tft_write();
  1063. inTransaction = true;
  1064. data += dx + dy * w;
  1065. int32_t xe = x + dw - 1, ye = y + dh - 1;
  1066. uint16_t lineBuf[dw];
  1067. // The little endian transp color must be byte swapped if the image is big endian
  1068. if (!_swapBytes) transp = transp >> 8 | transp << 8;
  1069. while (dh--) {
  1070. int32_t len = dw;
  1071. uint16_t* ptr = (uint16_t*)data;
  1072. int32_t px = x;
  1073. bool move = true;
  1074. uint16_t np = 0;
  1075. while (len--) {
  1076. uint16_t color = pgm_read_word(ptr);
  1077. if (transp != color) {
  1078. if (move) { move = false; setWindow(px, y, xe, ye); }
  1079. lineBuf[np] = color;
  1080. np++;
  1081. }
  1082. else {
  1083. move = true;
  1084. if (np) {
  1085. pushPixels(lineBuf, np);
  1086. np = 0;
  1087. }
  1088. }
  1089. px++;
  1090. ptr++;
  1091. }
  1092. if (np) pushPixels(lineBuf, np);
  1093. y++;
  1094. data += w;
  1095. }
  1096. inTransaction = lockTransaction;
  1097. end_tft_write();
  1098. }
  1099. /***************************************************************************************
  1100. ** Function name: pushImage
  1101. ** Description: plot 8 bit or 4 bit or 1 bit image or sprite using a line buffer
  1102. ***************************************************************************************/
  1103. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap)
  1104. {
  1105. PI_CLIP;
  1106. begin_tft_write();
  1107. inTransaction = true;
  1108. bool swap = _swapBytes;
  1109. setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
  1110. // Line buffer makes plotting faster
  1111. uint16_t lineBuf[dw];
  1112. if (bpp8)
  1113. {
  1114. _swapBytes = false;
  1115. uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
  1116. _lastColor = -1; // Set to illegal value
  1117. // Used to store last shifted colour
  1118. uint8_t msbColor = 0;
  1119. uint8_t lsbColor = 0;
  1120. data += dx + dy * w;
  1121. while (dh--) {
  1122. uint32_t len = dw;
  1123. uint8_t* ptr = (uint8_t*)data;
  1124. uint8_t* linePtr = (uint8_t*)lineBuf;
  1125. while(len--) {
  1126. uint32_t color = pgm_read_byte(ptr++);
  1127. // Shifts are slow so check if colour has changed first
  1128. if (color != _lastColor) {
  1129. // =====Green===== ===============Red==============
  1130. msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0);
  1131. // =====Green===== =======Blue======
  1132. lsbColor = (color & 0x1C)<<3 | blue[color & 0x03];
  1133. _lastColor = color;
  1134. }
  1135. *linePtr++ = msbColor;
  1136. *linePtr++ = lsbColor;
  1137. }
  1138. pushPixels(lineBuf, dw);
  1139. data += w;
  1140. }
  1141. _swapBytes = swap; // Restore old value
  1142. }
  1143. else if (cmap != nullptr) // Must be 4bpp
  1144. {
  1145. _swapBytes = true;
  1146. w = (w+1) & 0xFFFE; // if this is a sprite, w will already be even; this does no harm.
  1147. bool splitFirst = (dx & 0x01) != 0; // split first means we have to push a single px from the left of the sprite / image
  1148. if (splitFirst) {
  1149. data += ((dx - 1 + dy * w) >> 1);
  1150. }
  1151. else {
  1152. data += ((dx + dy * w) >> 1);
  1153. }
  1154. while (dh--) {
  1155. uint32_t len = dw;
  1156. uint8_t * ptr = (uint8_t*)data;
  1157. uint16_t *linePtr = lineBuf;
  1158. uint8_t colors; // two colors in one byte
  1159. uint16_t index;
  1160. if (splitFirst) {
  1161. colors = pgm_read_byte(ptr);
  1162. index = (colors & 0x0F);
  1163. *linePtr++ = cmap[index];
  1164. len--;
  1165. ptr++;
  1166. }
  1167. while (len--)
  1168. {
  1169. colors = pgm_read_byte(ptr);
  1170. index = ((colors & 0xF0) >> 4) & 0x0F;
  1171. *linePtr++ = cmap[index];
  1172. if (len--)
  1173. {
  1174. index = colors & 0x0F;
  1175. *linePtr++ = cmap[index];
  1176. } else {
  1177. break; // nothing to do here
  1178. }
  1179. ptr++;
  1180. }
  1181. pushPixels(lineBuf, dw);
  1182. data += (w >> 1);
  1183. }
  1184. _swapBytes = swap; // Restore old value
  1185. }
  1186. else // Must be 1bpp
  1187. {
  1188. _swapBytes = false;
  1189. uint8_t * ptr = (uint8_t*)data;
  1190. uint32_t ww = (w+7)>>3; // Width of source image line in bytes
  1191. for (int32_t yp = dy; yp < dy + dh; yp++)
  1192. {
  1193. uint8_t* linePtr = (uint8_t*)lineBuf;
  1194. for (int32_t xp = dx; xp < dx + dw; xp++)
  1195. {
  1196. uint16_t col = (pgm_read_byte(ptr + (xp>>3)) & (0x80 >> (xp & 0x7)) );
  1197. if (col) {*linePtr++ = bitmap_fg>>8; *linePtr++ = (uint8_t) bitmap_fg;}
  1198. else {*linePtr++ = bitmap_bg>>8; *linePtr++ = (uint8_t) bitmap_bg;}
  1199. }
  1200. ptr += ww;
  1201. pushPixels(lineBuf, dw);
  1202. }
  1203. }
  1204. _swapBytes = swap; // Restore old value
  1205. inTransaction = lockTransaction;
  1206. end_tft_write();
  1207. }
  1208. /***************************************************************************************
  1209. ** Function name: pushImage
  1210. ** Description: plot 8 bit or 4 bit or 1 bit image or sprite using a line buffer
  1211. ***************************************************************************************/
  1212. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8, uint16_t *cmap)
  1213. {
  1214. PI_CLIP;
  1215. begin_tft_write();
  1216. inTransaction = true;
  1217. bool swap = _swapBytes;
  1218. setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
  1219. // Line buffer makes plotting faster
  1220. uint16_t lineBuf[dw];
  1221. if (bpp8)
  1222. {
  1223. _swapBytes = false;
  1224. uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
  1225. _lastColor = -1; // Set to illegal value
  1226. // Used to store last shifted colour
  1227. uint8_t msbColor = 0;
  1228. uint8_t lsbColor = 0;
  1229. data += dx + dy * w;
  1230. while (dh--) {
  1231. uint32_t len = dw;
  1232. uint8_t* ptr = data;
  1233. uint8_t* linePtr = (uint8_t*)lineBuf;
  1234. while(len--) {
  1235. uint32_t color = *ptr++;
  1236. // Shifts are slow so check if colour has changed first
  1237. if (color != _lastColor) {
  1238. // =====Green===== ===============Red==============
  1239. msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0);
  1240. // =====Green===== =======Blue======
  1241. lsbColor = (color & 0x1C)<<3 | blue[color & 0x03];
  1242. _lastColor = color;
  1243. }
  1244. *linePtr++ = msbColor;
  1245. *linePtr++ = lsbColor;
  1246. }
  1247. pushPixels(lineBuf, dw);
  1248. data += w;
  1249. }
  1250. _swapBytes = swap; // Restore old value
  1251. }
  1252. else if (cmap != nullptr) // Must be 4bpp
  1253. {
  1254. _swapBytes = true;
  1255. w = (w+1) & 0xFFFE; // if this is a sprite, w will already be even; this does no harm.
  1256. bool splitFirst = (dx & 0x01) != 0; // split first means we have to push a single px from the left of the sprite / image
  1257. if (splitFirst) {
  1258. data += ((dx - 1 + dy * w) >> 1);
  1259. }
  1260. else {
  1261. data += ((dx + dy * w) >> 1);
  1262. }
  1263. while (dh--) {
  1264. uint32_t len = dw;
  1265. uint8_t * ptr = data;
  1266. uint16_t *linePtr = lineBuf;
  1267. uint8_t colors; // two colors in one byte
  1268. uint16_t index;
  1269. if (splitFirst) {
  1270. colors = *ptr;
  1271. index = (colors & 0x0F);
  1272. *linePtr++ = cmap[index];
  1273. len--;
  1274. ptr++;
  1275. }
  1276. while (len--)
  1277. {
  1278. colors = *ptr;
  1279. index = ((colors & 0xF0) >> 4) & 0x0F;
  1280. *linePtr++ = cmap[index];
  1281. if (len--)
  1282. {
  1283. index = colors & 0x0F;
  1284. *linePtr++ = cmap[index];
  1285. } else {
  1286. break; // nothing to do here
  1287. }
  1288. ptr++;
  1289. }
  1290. pushPixels(lineBuf, dw);
  1291. data += (w >> 1);
  1292. }
  1293. _swapBytes = swap; // Restore old value
  1294. }
  1295. else // Must be 1bpp
  1296. {
  1297. _swapBytes = false;
  1298. uint32_t ww = (w+7)>>3; // Width of source image line in bytes
  1299. for (int32_t yp = dy; yp < dy + dh; yp++)
  1300. {
  1301. uint8_t* linePtr = (uint8_t*)lineBuf;
  1302. for (int32_t xp = dx; xp < dx + dw; xp++)
  1303. {
  1304. uint16_t col = (data[(xp>>3)] & (0x80 >> (xp & 0x7)) );
  1305. if (col) {*linePtr++ = bitmap_fg>>8; *linePtr++ = (uint8_t) bitmap_fg;}
  1306. else {*linePtr++ = bitmap_bg>>8; *linePtr++ = (uint8_t) bitmap_bg;}
  1307. }
  1308. data += ww;
  1309. pushPixels(lineBuf, dw);
  1310. }
  1311. }
  1312. _swapBytes = swap; // Restore old value
  1313. inTransaction = lockTransaction;
  1314. end_tft_write();
  1315. }
  1316. /***************************************************************************************
  1317. ** Function name: pushImage
  1318. ** Description: plot 8 or 4 or 1 bit image or sprite with a transparent colour
  1319. ***************************************************************************************/
  1320. void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transp, bool bpp8, uint16_t *cmap)
  1321. {
  1322. PI_CLIP;
  1323. begin_tft_write();
  1324. inTransaction = true;
  1325. bool swap = _swapBytes;
  1326. int32_t xe = x + dw - 1, ye = y + dh - 1;
  1327. // Line buffer makes plotting faster
  1328. uint16_t lineBuf[dw];
  1329. if (bpp8) { // 8 bits per pixel
  1330. _swapBytes = false;
  1331. data += dx + dy * w;
  1332. uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
  1333. _lastColor = -1; // Set to illegal value
  1334. // Used to store last shifted colour
  1335. uint8_t msbColor = 0;
  1336. uint8_t lsbColor = 0;
  1337. while (dh--) {
  1338. int32_t len = dw;
  1339. uint8_t* ptr = data;
  1340. uint8_t* linePtr = (uint8_t*)lineBuf;
  1341. int32_t px = x;
  1342. bool move = true;
  1343. uint16_t np = 0;
  1344. while (len--) {
  1345. if (transp != *ptr) {
  1346. if (move) { move = false; setWindow(px, y, xe, ye);}
  1347. uint8_t color = *ptr;
  1348. // Shifts are slow so check if colour has changed first
  1349. if (color != _lastColor) {
  1350. // =====Green===== ===============Red==============
  1351. msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0);
  1352. // =====Green===== =======Blue======
  1353. lsbColor = (color & 0x1C)<<3 | blue[color & 0x03];
  1354. _lastColor = color;
  1355. }
  1356. *linePtr++ = msbColor;
  1357. *linePtr++ = lsbColor;
  1358. np++;
  1359. }
  1360. else {
  1361. move = true;
  1362. if (np) {
  1363. pushPixels(lineBuf, np);
  1364. linePtr = (uint8_t*)lineBuf;
  1365. np = 0;
  1366. }
  1367. }
  1368. px++;
  1369. ptr++;
  1370. }
  1371. if (np) pushPixels(lineBuf, np);
  1372. y++;
  1373. data += w;
  1374. }
  1375. }
  1376. else if (cmap != nullptr) // 4bpp with color map
  1377. {
  1378. _swapBytes = true;
  1379. w = (w+1) & 0xFFFE; // here we try to recreate iwidth from dwidth.
  1380. bool splitFirst = ((dx & 0x01) != 0);
  1381. if (splitFirst) {
  1382. data += ((dx - 1 + dy * w) >> 1);
  1383. }
  1384. else {
  1385. data += ((dx + dy * w) >> 1);
  1386. }
  1387. while (dh--) {
  1388. uint32_t len = dw;
  1389. uint8_t * ptr = data;
  1390. int32_t px = x;
  1391. bool move = true;
  1392. uint16_t np = 0;
  1393. uint8_t index; // index into cmap.
  1394. if (splitFirst) {
  1395. index = (*ptr & 0x0F); // odd = bits 3 .. 0
  1396. if (index != transp) {
  1397. move = false; setWindow(px, y, xe, ye);
  1398. lineBuf[np] = cmap[index];
  1399. np++;
  1400. }
  1401. px++; ptr++;
  1402. len--;
  1403. }
  1404. while (len--)
  1405. {
  1406. uint8_t color = *ptr;
  1407. // find the actual color you care about. There will be two pixels here!
  1408. // but we may only want one at the end of the row
  1409. uint16_t index = ((color & 0xF0) >> 4) & 0x0F; // high bits are the even numbers
  1410. if (index != transp) {
  1411. if (move) {
  1412. move = false; setWindow(px, y, xe, ye);
  1413. }
  1414. lineBuf[np] = cmap[index];
  1415. np++; // added a pixel
  1416. }
  1417. else {
  1418. move = true;
  1419. if (np) {
  1420. pushPixels(lineBuf, np);
  1421. np = 0;
  1422. }
  1423. }
  1424. px++;
  1425. if (len--)
  1426. {
  1427. index = color & 0x0F; // the odd number is 3 .. 0
  1428. if (index != transp) {
  1429. if (move) {
  1430. move = false; setWindow(px, y, xe, ye);
  1431. }
  1432. lineBuf[np] = cmap[index];
  1433. np++;
  1434. }
  1435. else {
  1436. move = true;
  1437. if (np) {
  1438. pushPixels(lineBuf, np);
  1439. np = 0;
  1440. }
  1441. }
  1442. px++;
  1443. }
  1444. else {
  1445. break; // we are done with this row.
  1446. }
  1447. ptr++; // we only increment ptr once in the loop (deliberate)
  1448. }
  1449. if (np) {
  1450. pushPixels(lineBuf, np);
  1451. np = 0;
  1452. }
  1453. data += (w>>1);
  1454. y++;
  1455. }
  1456. }
  1457. else { // 1 bit per pixel
  1458. _swapBytes = false;
  1459. uint32_t ww = (w+7)>>3; // Width of source image line in bytes
  1460. uint16_t np = 0;
  1461. for (int32_t yp = dy; yp < dy + dh; yp++)
  1462. {
  1463. int32_t px = x;
  1464. bool move = true;
  1465. for (int32_t xp = dx; xp < dx + dw; xp++)
  1466. {
  1467. if (data[(xp>>3)] & (0x80 >> (xp & 0x7))) {
  1468. if (move) {
  1469. move = false;
  1470. setWindow(px, y, xe, ye);
  1471. }
  1472. np++;
  1473. }
  1474. else {
  1475. if (np) {
  1476. pushBlock(bitmap_fg, np);
  1477. np = 0;
  1478. move = true;
  1479. }
  1480. }
  1481. px++;
  1482. }
  1483. y++;
  1484. data += ww;
  1485. if (np) { pushBlock(bitmap_fg, np); np = 0; }
  1486. }
  1487. }
  1488. _swapBytes = swap; // Restore old value
  1489. inTransaction = lockTransaction;
  1490. end_tft_write();
  1491. }
  1492. /***************************************************************************************
  1493. ** Function name: setSwapBytes
  1494. ** Description: Used by 16 bit pushImage() to swap byte order in colours
  1495. ***************************************************************************************/
  1496. void TFT_eSPI::setSwapBytes(bool swap)
  1497. {
  1498. _swapBytes = swap;
  1499. }
  1500. /***************************************************************************************
  1501. ** Function name: getSwapBytes
  1502. ** Description: Return the swap byte order for colours
  1503. ***************************************************************************************/
  1504. bool TFT_eSPI::getSwapBytes(void)
  1505. {
  1506. return _swapBytes;
  1507. }
  1508. /***************************************************************************************
  1509. ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
  1510. ** Description: Read RGB pixel colours from a defined area
  1511. ***************************************************************************************/
  1512. // If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel
  1513. void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data)
  1514. {
  1515. #if defined(TFT_PARALLEL_8_BIT)
  1516. uint32_t len = w * h;
  1517. uint8_t* buf565 = data + len;
  1518. readRect(x0, y0, w, h, (uint16_t*)buf565);
  1519. while (len--) {
  1520. uint16_t pixel565 = (*buf565++)<<8;
  1521. pixel565 |= *buf565++;
  1522. uint8_t red = (pixel565 & 0xF800) >> 8; red |= red >> 5;
  1523. uint8_t green = (pixel565 & 0x07E0) >> 3; green |= green >> 6;
  1524. uint8_t blue = (pixel565 & 0x001F) << 3; blue |= blue >> 5;
  1525. *data++ = red;
  1526. *data++ = green;
  1527. *data++ = blue;
  1528. }
  1529. #else // Not TFT_PARALLEL_8_BIT
  1530. begin_tft_read();
  1531. readAddrWindow(x0, y0, w, h); // Sets CS low
  1532. #ifdef TFT_SDA_READ
  1533. begin_SDA_Read();
  1534. #endif
  1535. // Dummy read to throw away don't care value
  1536. tft_Read_8();
  1537. // Read window pixel 24 bit RGB values, buffer must be set in sketch to 3 * w * h
  1538. uint32_t len = w * h;
  1539. while (len--) {
  1540. #if !defined (ILI9488_DRIVER)
  1541. // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
  1542. // as the TFT stores colours as 18 bits
  1543. *data++ = tft_Read_8();
  1544. *data++ = tft_Read_8();
  1545. *data++ = tft_Read_8();
  1546. #else
  1547. // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse
  1548. // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left
  1549. *data++ = (tft_Read_8()&0x7E)<<1;
  1550. *data++ = (tft_Read_8()&0x7E)<<1;
  1551. *data++ = (tft_Read_8()&0x7E)<<1;
  1552. #endif
  1553. }
  1554. CS_H;
  1555. #ifdef TFT_SDA_READ
  1556. end_SDA_Read();
  1557. #endif
  1558. end_tft_read();
  1559. #endif
  1560. }
  1561. /***************************************************************************************
  1562. ** Function name: drawCircle
  1563. ** Description: Draw a circle outline
  1564. ***************************************************************************************/
  1565. // Optimised midpoint circle algorithm
  1566. void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
  1567. {
  1568. if ( r <= 0 ) return;
  1569. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1570. inTransaction = true;
  1571. int32_t f = 1 - r;
  1572. int32_t ddF_y = -2 * r;
  1573. int32_t ddF_x = 1;
  1574. int32_t xs = -1;
  1575. int32_t xe = 0;
  1576. int32_t len = 0;
  1577. bool first = true;
  1578. do {
  1579. while (f < 0) {
  1580. ++xe;
  1581. f += (ddF_x += 2);
  1582. }
  1583. f += (ddF_y += 2);
  1584. if (xe-xs>1) {
  1585. if (first) {
  1586. len = 2*(xe - xs)-1;
  1587. drawFastHLine(x0 - xe, y0 + r, len, color);
  1588. drawFastHLine(x0 - xe, y0 - r, len, color);
  1589. drawFastVLine(x0 + r, y0 - xe, len, color);
  1590. drawFastVLine(x0 - r, y0 - xe, len, color);
  1591. first = false;
  1592. }
  1593. else {
  1594. len = xe - xs++;
  1595. drawFastHLine(x0 - xe, y0 + r, len, color);
  1596. drawFastHLine(x0 - xe, y0 - r, len, color);
  1597. drawFastHLine(x0 + xs, y0 - r, len, color);
  1598. drawFastHLine(x0 + xs, y0 + r, len, color);
  1599. drawFastVLine(x0 + r, y0 + xs, len, color);
  1600. drawFastVLine(x0 + r, y0 - xe, len, color);
  1601. drawFastVLine(x0 - r, y0 - xe, len, color);
  1602. drawFastVLine(x0 - r, y0 + xs, len, color);
  1603. }
  1604. }
  1605. else {
  1606. ++xs;
  1607. drawPixel(x0 - xe, y0 + r, color);
  1608. drawPixel(x0 - xe, y0 - r, color);
  1609. drawPixel(x0 + xs, y0 - r, color);
  1610. drawPixel(x0 + xs, y0 + r, color);
  1611. drawPixel(x0 + r, y0 + xs, color);
  1612. drawPixel(x0 + r, y0 - xe, color);
  1613. drawPixel(x0 - r, y0 - xe, color);
  1614. drawPixel(x0 - r, y0 + xs, color);
  1615. }
  1616. xs = xe;
  1617. } while (xe < --r);
  1618. inTransaction = lockTransaction;
  1619. end_tft_write(); // Does nothing if Sprite class uses this function
  1620. }
  1621. /***************************************************************************************
  1622. ** Function name: drawCircleHelper
  1623. ** Description: Support function for drawRoundRect()
  1624. ***************************************************************************************/
  1625. void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t rr, uint8_t cornername, uint32_t color)
  1626. {
  1627. if (rr <= 0) return;
  1628. int32_t f = 1 - rr;
  1629. int32_t ddF_x = 1;
  1630. int32_t ddF_y = -2 * rr;
  1631. int32_t xe = 0;
  1632. int32_t xs = 0;
  1633. int32_t len = 0;
  1634. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1635. inTransaction = true;
  1636. while (xe < rr--)
  1637. {
  1638. while (f < 0) {
  1639. ++xe;
  1640. f += (ddF_x += 2);
  1641. }
  1642. f += (ddF_y += 2);
  1643. if (xe-xs==1) {
  1644. if (cornername & 0x1) { // left top
  1645. drawPixel(x0 - xe, y0 - rr, color);
  1646. drawPixel(x0 - rr, y0 - xe, color);
  1647. }
  1648. if (cornername & 0x2) { // right top
  1649. drawPixel(x0 + rr , y0 - xe, color);
  1650. drawPixel(x0 + xs + 1, y0 - rr, color);
  1651. }
  1652. if (cornername & 0x4) { // right bottom
  1653. drawPixel(x0 + xs + 1, y0 + rr , color);
  1654. drawPixel(x0 + rr, y0 + xs + 1, color);
  1655. }
  1656. if (cornername & 0x8) { // left bottom
  1657. drawPixel(x0 - rr, y0 + xs + 1, color);
  1658. drawPixel(x0 - xe, y0 + rr , color);
  1659. }
  1660. }
  1661. else {
  1662. len = xe - xs++;
  1663. if (cornername & 0x1) { // left top
  1664. drawFastHLine(x0 - xe, y0 - rr, len, color);
  1665. drawFastVLine(x0 - rr, y0 - xe, len, color);
  1666. }
  1667. if (cornername & 0x2) { // right top
  1668. drawFastVLine(x0 + rr, y0 - xe, len, color);
  1669. drawFastHLine(x0 + xs, y0 - rr, len, color);
  1670. }
  1671. if (cornername & 0x4) { // right bottom
  1672. drawFastHLine(x0 + xs, y0 + rr, len, color);
  1673. drawFastVLine(x0 + rr, y0 + xs, len, color);
  1674. }
  1675. if (cornername & 0x8) { // left bottom
  1676. drawFastVLine(x0 - rr, y0 + xs, len, color);
  1677. drawFastHLine(x0 - xe, y0 + rr, len, color);
  1678. }
  1679. }
  1680. xs = xe;
  1681. }
  1682. inTransaction = lockTransaction;
  1683. end_tft_write(); // Does nothing if Sprite class uses this function
  1684. }
  1685. /***************************************************************************************
  1686. ** Function name: fillCircle
  1687. ** Description: draw a filled circle
  1688. ***************************************************************************************/
  1689. // Optimised midpoint circle algorithm, changed to horizontal lines (faster in sprites)
  1690. // Improved algorithm avoids repetition of lines
  1691. void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
  1692. {
  1693. int32_t x = 0;
  1694. int32_t dx = 1;
  1695. int32_t dy = r+r;
  1696. int32_t p = -(r>>1);
  1697. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1698. inTransaction = true;
  1699. drawFastHLine(x0 - r, y0, dy+1, color);
  1700. while(x<r){
  1701. if(p>=0) {
  1702. drawFastHLine(x0 - x, y0 + r, dx, color);
  1703. drawFastHLine(x0 - x, y0 - r, dx, color);
  1704. dy-=2;
  1705. p-=dy;
  1706. r--;
  1707. }
  1708. dx+=2;
  1709. p+=dx;
  1710. x++;
  1711. drawFastHLine(x0 - r, y0 + x, dy+1, color);
  1712. drawFastHLine(x0 - r, y0 - x, dy+1, color);
  1713. }
  1714. inTransaction = lockTransaction;
  1715. end_tft_write(); // Does nothing if Sprite class uses this function
  1716. }
  1717. /***************************************************************************************
  1718. ** Function name: fillCircleHelper
  1719. ** Description: Support function for fillRoundRect()
  1720. ***************************************************************************************/
  1721. // Support drawing roundrects, changed to horizontal lines (faster in sprites)
  1722. void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color)
  1723. {
  1724. int32_t f = 1 - r;
  1725. int32_t ddF_x = 1;
  1726. int32_t ddF_y = -r - r;
  1727. int32_t y = 0;
  1728. delta++;
  1729. while (y < r) {
  1730. if (f >= 0) {
  1731. if (cornername & 0x1) drawFastHLine(x0 - y, y0 + r, y + y + delta, color);
  1732. if (cornername & 0x2) drawFastHLine(x0 - y, y0 - r, y + y + delta, color);
  1733. r--;
  1734. ddF_y += 2;
  1735. f += ddF_y;
  1736. }
  1737. y++;
  1738. ddF_x += 2;
  1739. f += ddF_x;
  1740. if (cornername & 0x1) drawFastHLine(x0 - r, y0 + y, r + r + delta, color);
  1741. if (cornername & 0x2) drawFastHLine(x0 - r, y0 - y, r + r + delta, color);
  1742. }
  1743. }
  1744. /***************************************************************************************
  1745. ** Function name: drawEllipse
  1746. ** Description: Draw a ellipse outline
  1747. ***************************************************************************************/
  1748. void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
  1749. {
  1750. if (rx<2) return;
  1751. if (ry<2) return;
  1752. int32_t x, y;
  1753. int32_t rx2 = rx * rx;
  1754. int32_t ry2 = ry * ry;
  1755. int32_t fx2 = 4 * rx2;
  1756. int32_t fy2 = 4 * ry2;
  1757. int32_t s;
  1758. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1759. inTransaction = true;
  1760. for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) {
  1761. // These are ordered to minimise coordinate changes in x or y
  1762. // drawPixel can then send fewer bounding box commands
  1763. drawPixel(x0 + x, y0 + y, color);
  1764. drawPixel(x0 - x, y0 + y, color);
  1765. drawPixel(x0 - x, y0 - y, color);
  1766. drawPixel(x0 + x, y0 - y, color);
  1767. if (s >= 0) {
  1768. s += fx2 * (1 - y);
  1769. y--;
  1770. }
  1771. s += ry2 * ((4 * x) + 6);
  1772. }
  1773. for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) {
  1774. // These are ordered to minimise coordinate changes in x or y
  1775. // drawPixel can then send fewer bounding box commands
  1776. drawPixel(x0 + x, y0 + y, color);
  1777. drawPixel(x0 - x, y0 + y, color);
  1778. drawPixel(x0 - x, y0 - y, color);
  1779. drawPixel(x0 + x, y0 - y, color);
  1780. if (s >= 0)
  1781. {
  1782. s += fy2 * (1 - x);
  1783. x--;
  1784. }
  1785. s += rx2 * ((4 * y) + 6);
  1786. }
  1787. inTransaction = lockTransaction;
  1788. end_tft_write(); // Does nothing if Sprite class uses this function
  1789. }
  1790. /***************************************************************************************
  1791. ** Function name: fillEllipse
  1792. ** Description: draw a filled ellipse
  1793. ***************************************************************************************/
  1794. void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
  1795. {
  1796. if (rx<2) return;
  1797. if (ry<2) return;
  1798. int32_t x, y;
  1799. int32_t rx2 = rx * rx;
  1800. int32_t ry2 = ry * ry;
  1801. int32_t fx2 = 4 * rx2;
  1802. int32_t fy2 = 4 * ry2;
  1803. int32_t s;
  1804. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1805. inTransaction = true;
  1806. for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) {
  1807. drawFastHLine(x0 - x, y0 - y, x + x + 1, color);
  1808. drawFastHLine(x0 - x, y0 + y, x + x + 1, color);
  1809. if (s >= 0) {
  1810. s += fx2 * (1 - y);
  1811. y--;
  1812. }
  1813. s += ry2 * ((4 * x) + 6);
  1814. }
  1815. for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) {
  1816. drawFastHLine(x0 - x, y0 - y, x + x + 1, color);
  1817. drawFastHLine(x0 - x, y0 + y, x + x + 1, color);
  1818. if (s >= 0) {
  1819. s += fy2 * (1 - x);
  1820. x--;
  1821. }
  1822. s += rx2 * ((4 * y) + 6);
  1823. }
  1824. inTransaction = lockTransaction;
  1825. end_tft_write(); // Does nothing if Sprite class uses this function
  1826. }
  1827. /***************************************************************************************
  1828. ** Function name: fillScreen
  1829. ** Description: Clear the screen to defined colour
  1830. ***************************************************************************************/
  1831. void TFT_eSPI::fillScreen(uint32_t color)
  1832. {
  1833. fillRect(0, 0, _width, _height, color);
  1834. }
  1835. /***************************************************************************************
  1836. ** Function name: drawRect
  1837. ** Description: Draw a rectangle outline
  1838. ***************************************************************************************/
  1839. // Draw a rectangle
  1840. void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
  1841. {
  1842. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1843. inTransaction = true;
  1844. drawFastHLine(x, y, w, color);
  1845. drawFastHLine(x, y + h - 1, w, color);
  1846. // Avoid drawing corner pixels twice
  1847. drawFastVLine(x, y+1, h-2, color);
  1848. drawFastVLine(x + w - 1, y+1, h-2, color);
  1849. inTransaction = lockTransaction;
  1850. end_tft_write(); // Does nothing if Sprite class uses this function
  1851. }
  1852. /***************************************************************************************
  1853. ** Function name: drawRoundRect
  1854. ** Description: Draw a rounded corner rectangle outline
  1855. ***************************************************************************************/
  1856. // Draw a rounded rectangle
  1857. void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color)
  1858. {
  1859. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1860. inTransaction = true;
  1861. // smarter version
  1862. drawFastHLine(x + r , y , w - r - r, color); // Top
  1863. drawFastHLine(x + r , y + h - 1, w - r - r, color); // Bottom
  1864. drawFastVLine(x , y + r , h - r - r, color); // Left
  1865. drawFastVLine(x + w - 1, y + r , h - r - r, color); // Right
  1866. // draw four corners
  1867. drawCircleHelper(x + r , y + r , r, 1, color);
  1868. drawCircleHelper(x + w - r - 1, y + r , r, 2, color);
  1869. drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
  1870. drawCircleHelper(x + r , y + h - r - 1, r, 8, color);
  1871. inTransaction = lockTransaction;
  1872. end_tft_write(); // Does nothing if Sprite class uses this function
  1873. }
  1874. /***************************************************************************************
  1875. ** Function name: fillRoundRect
  1876. ** Description: Draw a rounded corner filled rectangle
  1877. ***************************************************************************************/
  1878. // Fill a rounded rectangle, changed to horizontal lines (faster in sprites)
  1879. void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color)
  1880. {
  1881. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1882. inTransaction = true;
  1883. // smarter version
  1884. fillRect(x, y + r, w, h - r - r, color);
  1885. // draw four corners
  1886. fillCircleHelper(x + r, y + h - r - 1, r, 1, w - r - r - 1, color);
  1887. fillCircleHelper(x + r , y + r, r, 2, w - r - r - 1, color);
  1888. inTransaction = lockTransaction;
  1889. end_tft_write(); // Does nothing if Sprite class uses this function
  1890. }
  1891. /***************************************************************************************
  1892. ** Function name: drawTriangle
  1893. ** Description: Draw a triangle outline using 3 arbitrary points
  1894. ***************************************************************************************/
  1895. // Draw a triangle
  1896. void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color)
  1897. {
  1898. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1899. inTransaction = true;
  1900. drawLine(x0, y0, x1, y1, color);
  1901. drawLine(x1, y1, x2, y2, color);
  1902. drawLine(x2, y2, x0, y0, color);
  1903. inTransaction = lockTransaction;
  1904. end_tft_write(); // Does nothing if Sprite class uses this function
  1905. }
  1906. /***************************************************************************************
  1907. ** Function name: fillTriangle
  1908. ** Description: Draw a filled triangle using 3 arbitrary points
  1909. ***************************************************************************************/
  1910. // Fill a triangle - original Adafruit function works well and code footprint is small
  1911. void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color)
  1912. {
  1913. int32_t a, b, y, last;
  1914. // Sort coordinates by Y order (y2 >= y1 >= y0)
  1915. if (y0 > y1) {
  1916. swap_coord(y0, y1); swap_coord(x0, x1);
  1917. }
  1918. if (y1 > y2) {
  1919. swap_coord(y2, y1); swap_coord(x2, x1);
  1920. }
  1921. if (y0 > y1) {
  1922. swap_coord(y0, y1); swap_coord(x0, x1);
  1923. }
  1924. if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
  1925. a = b = x0;
  1926. if (x1 < a) a = x1;
  1927. else if (x1 > b) b = x1;
  1928. if (x2 < a) a = x2;
  1929. else if (x2 > b) b = x2;
  1930. drawFastHLine(a, y0, b - a + 1, color);
  1931. return;
  1932. }
  1933. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1934. inTransaction = true;
  1935. int32_t
  1936. dx01 = x1 - x0,
  1937. dy01 = y1 - y0,
  1938. dx02 = x2 - x0,
  1939. dy02 = y2 - y0,
  1940. dx12 = x2 - x1,
  1941. dy12 = y2 - y1,
  1942. sa = 0,
  1943. sb = 0;
  1944. // For upper part of triangle, find scanline crossings for segments
  1945. // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
  1946. // is included here (and second loop will be skipped, avoiding a /0
  1947. // error there), otherwise scanline y1 is skipped here and handled
  1948. // in the second loop...which also avoids a /0 error here if y0=y1
  1949. // (flat-topped triangle).
  1950. if (y1 == y2) last = y1; // Include y1 scanline
  1951. else last = y1 - 1; // Skip it
  1952. for (y = y0; y <= last; y++) {
  1953. a = x0 + sa / dy01;
  1954. b = x0 + sb / dy02;
  1955. sa += dx01;
  1956. sb += dx02;
  1957. if (a > b) swap_coord(a, b);
  1958. drawFastHLine(a, y, b - a + 1, color);
  1959. }
  1960. // For lower part of triangle, find scanline crossings for segments
  1961. // 0-2 and 1-2. This loop is skipped if y1=y2.
  1962. sa = dx12 * (y - y1);
  1963. sb = dx02 * (y - y0);
  1964. for (; y <= y2; y++) {
  1965. a = x1 + sa / dy12;
  1966. b = x0 + sb / dy02;
  1967. sa += dx12;
  1968. sb += dx02;
  1969. if (a > b) swap_coord(a, b);
  1970. drawFastHLine(a, y, b - a + 1, color);
  1971. }
  1972. inTransaction = lockTransaction;
  1973. end_tft_write(); // Does nothing if Sprite class uses this function
  1974. }
  1975. /***************************************************************************************
  1976. ** Function name: drawBitmap
  1977. ** Description: Draw an image stored in an array on the TFT
  1978. ***************************************************************************************/
  1979. void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
  1980. {
  1981. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  1982. inTransaction = true;
  1983. int32_t i, j, byteWidth = (w + 7) / 8;
  1984. for (j = 0; j < h; j++) {
  1985. for (i = 0; i < w; i++ ) {
  1986. if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
  1987. drawPixel(x + i, y + j, color);
  1988. }
  1989. }
  1990. }
  1991. inTransaction = lockTransaction;
  1992. end_tft_write(); // Does nothing if Sprite class uses this function
  1993. }
  1994. /***************************************************************************************
  1995. ** Function name: drawBitmap
  1996. ** Description: Draw an image stored in an array on the TFT
  1997. ***************************************************************************************/
  1998. void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor)
  1999. {
  2000. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  2001. inTransaction = true;
  2002. int32_t i, j, byteWidth = (w + 7) / 8;
  2003. for (j = 0; j < h; j++) {
  2004. for (i = 0; i < w; i++ ) {
  2005. if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7)))
  2006. drawPixel(x + i, y + j, fgcolor);
  2007. else drawPixel(x + i, y + j, bgcolor);
  2008. }
  2009. }
  2010. inTransaction = lockTransaction;
  2011. end_tft_write(); // Does nothing if Sprite class uses this function
  2012. }
  2013. /***************************************************************************************
  2014. ** Function name: drawXBitmap
  2015. ** Description: Draw an image stored in an XBM array onto the TFT
  2016. ***************************************************************************************/
  2017. void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
  2018. {
  2019. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  2020. inTransaction = true;
  2021. int32_t i, j, byteWidth = (w + 7) / 8;
  2022. for (j = 0; j < h; j++) {
  2023. for (i = 0; i < w; i++ ) {
  2024. if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i & 7))) {
  2025. drawPixel(x + i, y + j, color);
  2026. }
  2027. }
  2028. }
  2029. inTransaction = lockTransaction;
  2030. end_tft_write(); // Does nothing if Sprite class uses this function
  2031. }
  2032. /***************************************************************************************
  2033. ** Function name: drawXBitmap
  2034. ** Description: Draw an XBM image with foreground and background colors
  2035. ***************************************************************************************/
  2036. void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor)
  2037. {
  2038. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  2039. inTransaction = true;
  2040. int32_t i, j, byteWidth = (w + 7) / 8;
  2041. for (j = 0; j < h; j++) {
  2042. for (i = 0; i < w; i++ ) {
  2043. if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i & 7)))
  2044. drawPixel(x + i, y + j, color);
  2045. else drawPixel(x + i, y + j, bgcolor);
  2046. }
  2047. }
  2048. inTransaction = lockTransaction;
  2049. end_tft_write(); // Does nothing if Sprite class uses this function
  2050. }
  2051. /***************************************************************************************
  2052. ** Function name: setCursor
  2053. ** Description: Set the text cursor x,y position
  2054. ***************************************************************************************/
  2055. void TFT_eSPI::setCursor(int16_t x, int16_t y)
  2056. {
  2057. cursor_x = x;
  2058. cursor_y = y;
  2059. }
  2060. /***************************************************************************************
  2061. ** Function name: setCursor
  2062. ** Description: Set the text cursor x,y position and font
  2063. ***************************************************************************************/
  2064. void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font)
  2065. {
  2066. textfont = font;
  2067. cursor_x = x;
  2068. cursor_y = y;
  2069. }
  2070. /***************************************************************************************
  2071. ** Function name: getCursorX
  2072. ** Description: Get the text cursor x position
  2073. ***************************************************************************************/
  2074. int16_t TFT_eSPI::getCursorX(void)
  2075. {
  2076. return cursor_x;
  2077. }
  2078. /***************************************************************************************
  2079. ** Function name: getCursorY
  2080. ** Description: Get the text cursor y position
  2081. ***************************************************************************************/
  2082. int16_t TFT_eSPI::getCursorY(void)
  2083. {
  2084. return cursor_y;
  2085. }
  2086. /***************************************************************************************
  2087. ** Function name: setTextSize
  2088. ** Description: Set the text size multiplier
  2089. ***************************************************************************************/
  2090. void TFT_eSPI::setTextSize(uint8_t s)
  2091. {
  2092. if (s>7) s = 7; // Limit the maximum size multiplier so byte variables can be used for rendering
  2093. textsize = (s > 0) ? s : 1; // Don't allow font size 0
  2094. }
  2095. /***************************************************************************************
  2096. ** Function name: setTextColor
  2097. ** Description: Set the font foreground colour (background is transparent)
  2098. ***************************************************************************************/
  2099. void TFT_eSPI::setTextColor(uint16_t c)
  2100. {
  2101. // For 'transparent' background, we'll set the bg
  2102. // to the same as fg instead of using a flag
  2103. textcolor = textbgcolor = c;
  2104. }
  2105. /***************************************************************************************
  2106. ** Function name: setTextColor
  2107. ** Description: Set the font foreground and background colour
  2108. ***************************************************************************************/
  2109. void TFT_eSPI::setTextColor(uint16_t c, uint16_t b)
  2110. {
  2111. textcolor = c;
  2112. textbgcolor = b;
  2113. }
  2114. /***************************************************************************************
  2115. ** Function name: setPivot
  2116. ** Description: Set the pivot point on the TFT
  2117. *************************************************************************************x*/
  2118. void TFT_eSPI::setPivot(int16_t x, int16_t y)
  2119. {
  2120. _xPivot = x;
  2121. _yPivot = y;
  2122. }
  2123. /***************************************************************************************
  2124. ** Function name: getPivotX
  2125. ** Description: Get the x pivot position
  2126. ***************************************************************************************/
  2127. int16_t TFT_eSPI::getPivotX(void)
  2128. {
  2129. return _xPivot;
  2130. }
  2131. /***************************************************************************************
  2132. ** Function name: getPivotY
  2133. ** Description: Get the y pivot position
  2134. ***************************************************************************************/
  2135. int16_t TFT_eSPI::getPivotY(void)
  2136. {
  2137. return _yPivot;
  2138. }
  2139. /***************************************************************************************
  2140. ** Function name: setBitmapColor
  2141. ** Description: Set the foreground foreground and background colour
  2142. ***************************************************************************************/
  2143. void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b)
  2144. {
  2145. if (c == b) b = ~c;
  2146. bitmap_fg = c;
  2147. bitmap_bg = b;
  2148. }
  2149. /***************************************************************************************
  2150. ** Function name: setTextWrap
  2151. ** Description: Define if text should wrap at end of line
  2152. ***************************************************************************************/
  2153. void TFT_eSPI::setTextWrap(bool wrapX, bool wrapY)
  2154. {
  2155. textwrapX = wrapX;
  2156. textwrapY = wrapY;
  2157. }
  2158. /***************************************************************************************
  2159. ** Function name: setTextDatum
  2160. ** Description: Set the text position reference datum
  2161. ***************************************************************************************/
  2162. void TFT_eSPI::setTextDatum(uint8_t d)
  2163. {
  2164. textdatum = d;
  2165. }
  2166. /***************************************************************************************
  2167. ** Function name: setTextPadding
  2168. ** Description: Define padding width (aids erasing old text and numbers)
  2169. ***************************************************************************************/
  2170. void TFT_eSPI::setTextPadding(uint16_t x_width)
  2171. {
  2172. padX = x_width;
  2173. }
  2174. /***************************************************************************************
  2175. ** Function name: setTextPadding
  2176. ** Description: Define padding width (aids erasing old text and numbers)
  2177. ***************************************************************************************/
  2178. uint16_t TFT_eSPI::getTextPadding(void)
  2179. {
  2180. return padX;
  2181. }
  2182. /***************************************************************************************
  2183. ** Function name: getRotation
  2184. ** Description: Return the rotation value (as used by setRotation())
  2185. ***************************************************************************************/
  2186. uint8_t TFT_eSPI::getRotation(void)
  2187. {
  2188. return rotation;
  2189. }
  2190. /***************************************************************************************
  2191. ** Function name: getTextDatum
  2192. ** Description: Return the text datum value (as used by setTextDatum())
  2193. ***************************************************************************************/
  2194. uint8_t TFT_eSPI::getTextDatum(void)
  2195. {
  2196. return textdatum;
  2197. }
  2198. /***************************************************************************************
  2199. ** Function name: width
  2200. ** Description: Return the pixel width of display (per current rotation)
  2201. ***************************************************************************************/
  2202. // Return the size of the display (per current rotation)
  2203. int16_t TFT_eSPI::width(void)
  2204. {
  2205. if (_vpDatum) return _xWidth;
  2206. return _width;
  2207. }
  2208. /***************************************************************************************
  2209. ** Function name: height
  2210. ** Description: Return the pixel height of display (per current rotation)
  2211. ***************************************************************************************/
  2212. int16_t TFT_eSPI::height(void)
  2213. {
  2214. if (_vpDatum) return _yHeight;
  2215. return _height;
  2216. }
  2217. /***************************************************************************************
  2218. ** Function name: textWidth
  2219. ** Description: Return the width in pixels of a string in a given font
  2220. ***************************************************************************************/
  2221. int16_t TFT_eSPI::textWidth(const String& string)
  2222. {
  2223. int16_t len = string.length() + 2;
  2224. char buffer[len];
  2225. string.toCharArray(buffer, len);
  2226. return textWidth(buffer, textfont);
  2227. }
  2228. int16_t TFT_eSPI::textWidth(const String& string, uint8_t font)
  2229. {
  2230. int16_t len = string.length() + 2;
  2231. char buffer[len];
  2232. string.toCharArray(buffer, len);
  2233. return textWidth(buffer, font);
  2234. }
  2235. int16_t TFT_eSPI::textWidth(const char *string)
  2236. {
  2237. return textWidth(string, textfont);
  2238. }
  2239. int16_t TFT_eSPI::textWidth(const char *string, uint8_t font)
  2240. {
  2241. int32_t str_width = 0;
  2242. uint16_t uniCode = 0;
  2243. #ifdef SMOOTH_FONT
  2244. if(fontLoaded) {
  2245. while (*string) {
  2246. uniCode = decodeUTF8(*string++);
  2247. if (uniCode) {
  2248. if (uniCode == 0x20) str_width += gFont.spaceWidth;
  2249. else {
  2250. uint16_t gNum = 0;
  2251. bool found = getUnicodeIndex(uniCode, &gNum);
  2252. if (found) {
  2253. if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum];
  2254. if (*string || isDigits) str_width += gxAdvance[gNum];
  2255. else str_width += (gdX[gNum] + gWidth[gNum]);
  2256. }
  2257. else str_width += gFont.spaceWidth + 1;
  2258. }
  2259. }
  2260. }
  2261. isDigits = false;
  2262. return str_width;
  2263. }
  2264. #endif
  2265. if (font>1 && font<9) {
  2266. char *widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop
  2267. while (*string) {
  2268. uniCode = *(string++);
  2269. if (uniCode > 31 && uniCode < 128)
  2270. str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subtract 32 from uniCode
  2271. else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width
  2272. }
  2273. }
  2274. else {
  2275. #ifdef LOAD_GFXFF
  2276. if(gfxFont) { // New font
  2277. while (*string) {
  2278. uniCode = decodeUTF8(*string++);
  2279. if ((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last ))) {
  2280. uniCode -= pgm_read_word(&gfxFont->first);
  2281. GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]);
  2282. // If this is not the last character or is a digit then use xAdvance
  2283. if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance);
  2284. // Else use the offset plus width since this can be bigger than xAdvance
  2285. else str_width += ((int8_t)pgm_read_byte(&glyph->xOffset) + pgm_read_byte(&glyph->width));
  2286. }
  2287. }
  2288. }
  2289. else
  2290. #endif
  2291. {
  2292. #ifdef LOAD_GLCD
  2293. while (*string++) str_width += 6;
  2294. #endif
  2295. }
  2296. }
  2297. isDigits = false;
  2298. return str_width * textsize;
  2299. }
  2300. /***************************************************************************************
  2301. ** Function name: fontsLoaded
  2302. ** Description: return an encoded 16 bit value showing the fonts loaded
  2303. ***************************************************************************************/
  2304. // Returns a value showing which fonts are loaded (bit N set = Font N loaded)
  2305. uint16_t TFT_eSPI::fontsLoaded(void)
  2306. {
  2307. return fontsloaded;
  2308. }
  2309. /***************************************************************************************
  2310. ** Function name: fontHeight
  2311. ** Description: return the height of a font (yAdvance for free fonts)
  2312. ***************************************************************************************/
  2313. int16_t TFT_eSPI::fontHeight(int16_t font)
  2314. {
  2315. #ifdef SMOOTH_FONT
  2316. if(fontLoaded) return gFont.yAdvance;
  2317. #endif
  2318. #ifdef LOAD_GFXFF
  2319. if (font==1) {
  2320. if(gfxFont) { // New font
  2321. return pgm_read_byte(&gfxFont->yAdvance) * textsize;
  2322. }
  2323. }
  2324. #endif
  2325. return pgm_read_byte( &fontdata[font].height ) * textsize;
  2326. }
  2327. int16_t TFT_eSPI::fontHeight(void)
  2328. {
  2329. return fontHeight(textfont);
  2330. }
  2331. /***************************************************************************************
  2332. ** Function name: drawChar
  2333. ** Description: draw a single character in the GLCD or GFXFF font
  2334. ***************************************************************************************/
  2335. void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size)
  2336. {
  2337. if (_vpOoB) return;
  2338. int32_t xd = x + _xDatum;
  2339. int32_t yd = y + _yDatum;
  2340. if (c < 32) return;
  2341. #ifdef LOAD_GLCD
  2342. //>>>>>>>>>>>>>>>>>>
  2343. #ifdef LOAD_GFXFF
  2344. if(!gfxFont) { // 'Classic' built-in font
  2345. #endif
  2346. //>>>>>>>>>>>>>>>>>>
  2347. if ((xd >= _vpW) || // Clip right
  2348. ( yd >= _vpH) || // Clip bottom
  2349. ((xd + 6 * size - 1) < _vpX) || // Clip left
  2350. ((yd + 8 * size - 1) < _vpY)) // Clip top
  2351. return;
  2352. bool fillbg = (bg != color);
  2353. bool clip = xd < _vpX || xd + 6 * textsize >= _vpW || yd < _vpY || yd + 8 * textsize >= _vpH;
  2354. if ((size==1) && fillbg && !clip) {
  2355. uint8_t column[6];
  2356. uint8_t mask = 0x1;
  2357. begin_tft_write();
  2358. setWindow(xd, yd, xd+5, yd+8);
  2359. for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i);
  2360. column[5] = 0;
  2361. for (int8_t j = 0; j < 8; j++) {
  2362. for (int8_t k = 0; k < 5; k++ ) {
  2363. if (column[k] & mask) {tft_Write_16(color);}
  2364. else {tft_Write_16(bg);}
  2365. }
  2366. mask <<= 1;
  2367. tft_Write_16(bg);
  2368. }
  2369. end_tft_write();
  2370. }
  2371. else {
  2372. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  2373. inTransaction = true;
  2374. for (int8_t i = 0; i < 6; i++ ) {
  2375. uint8_t line;
  2376. if (i == 5)
  2377. line = 0x0;
  2378. else
  2379. line = pgm_read_byte(font + (c * 5) + i);
  2380. if (size == 1 && !fillbg) { // default size
  2381. for (int8_t j = 0; j < 8; j++) {
  2382. if (line & 0x1) drawPixel(x + i, y + j, color);
  2383. line >>= 1;
  2384. }
  2385. }
  2386. else { // big size or clipped
  2387. for (int8_t j = 0; j < 8; j++) {
  2388. if (line & 0x1) fillRect(x + (i * size), y + (j * size), size, size, color);
  2389. else if (fillbg) fillRect(x + i * size, y + j * size, size, size, bg);
  2390. line >>= 1;
  2391. }
  2392. }
  2393. }
  2394. inTransaction = lockTransaction;
  2395. end_tft_write(); // Does nothing if Sprite class uses this function
  2396. }
  2397. //>>>>>>>>>>>>>>>>>>>>>>>>>>>
  2398. #ifdef LOAD_GFXFF
  2399. } else { // Custom font
  2400. #endif
  2401. //>>>>>>>>>>>>>>>>>>>>>>>>>>>
  2402. #endif // LOAD_GLCD
  2403. #ifdef LOAD_GFXFF
  2404. // Filter out bad characters not present in font
  2405. if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) {
  2406. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  2407. inTransaction = true;
  2408. //>>>>>>>>>>>>>>>>>>>>>>>>>>>
  2409. c -= pgm_read_word(&gfxFont->first);
  2410. GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]);
  2411. uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap);
  2412. uint32_t bo = pgm_read_word(&glyph->bitmapOffset);
  2413. uint8_t w = pgm_read_byte(&glyph->width),
  2414. h = pgm_read_byte(&glyph->height);
  2415. //xa = pgm_read_byte(&glyph->xAdvance);
  2416. int8_t xo = pgm_read_byte(&glyph->xOffset),
  2417. yo = pgm_read_byte(&glyph->yOffset);
  2418. uint8_t xx, yy, bits=0, bit=0;
  2419. int16_t xo16 = 0, yo16 = 0;
  2420. if(size > 1) {
  2421. xo16 = xo;
  2422. yo16 = yo;
  2423. }
  2424. // GFXFF rendering speed up
  2425. uint16_t hpc = 0; // Horizontal foreground pixel count
  2426. for(yy=0; yy<h; yy++) {
  2427. for(xx=0; xx<w; xx++) {
  2428. if(bit == 0) {
  2429. bits = pgm_read_byte(&bitmap[bo++]);
  2430. bit = 0x80;
  2431. }
  2432. if(bits & bit) hpc++;
  2433. else {
  2434. if (hpc) {
  2435. if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color);
  2436. else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color);
  2437. hpc=0;
  2438. }
  2439. }
  2440. bit >>= 1;
  2441. }
  2442. // Draw pixels for this line as we are about to increment yy
  2443. if (hpc) {
  2444. if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color);
  2445. else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color);
  2446. hpc=0;
  2447. }
  2448. }
  2449. inTransaction = lockTransaction;
  2450. end_tft_write(); // Does nothing if Sprite class uses this function
  2451. }
  2452. #endif
  2453. #ifdef LOAD_GLCD
  2454. #ifdef LOAD_GFXFF
  2455. } // End classic vs custom font
  2456. #endif
  2457. #endif
  2458. }
  2459. /***************************************************************************************
  2460. ** Function name: setAddrWindow
  2461. ** Description: define an area to receive a stream of pixels
  2462. ***************************************************************************************/
  2463. // Chip select is high at the end of this function
  2464. void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h)
  2465. {
  2466. begin_tft_write();
  2467. setWindow(x0, y0, x0 + w - 1, y0 + h - 1);
  2468. end_tft_write();
  2469. }
  2470. /***************************************************************************************
  2471. ** Function name: setWindow
  2472. ** Description: define an area to receive a stream of pixels
  2473. ***************************************************************************************/
  2474. // Chip select stays low, call begin_tft_write first. Use setAddrWindow() from sketches
  2475. void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
  2476. {
  2477. //begin_tft_write(); // Must be called before setWindow
  2478. addr_row = 0xFFFF;
  2479. addr_col = 0xFFFF;
  2480. #if defined (ILI9225_DRIVER)
  2481. if (rotation & 0x01) { swap_coord(x0, y0); swap_coord(x1, y1); }
  2482. SPI_BUSY_CHECK;
  2483. DC_C; tft_Write_8(TFT_CASET1);
  2484. DC_D; tft_Write_16(x0);
  2485. DC_C; tft_Write_8(TFT_CASET2);
  2486. DC_D; tft_Write_16(x1);
  2487. DC_C; tft_Write_8(TFT_PASET1);
  2488. DC_D; tft_Write_16(y0);
  2489. DC_C; tft_Write_8(TFT_PASET2);
  2490. DC_D; tft_Write_16(y1);
  2491. DC_C; tft_Write_8(TFT_RAM_ADDR1);
  2492. DC_D; tft_Write_16(x0);
  2493. DC_C; tft_Write_8(TFT_RAM_ADDR2);
  2494. DC_D; tft_Write_16(y0);
  2495. // write to RAM
  2496. DC_C; tft_Write_8(TFT_RAMWR);
  2497. DC_D;
  2498. #elif defined (SSD1351_DRIVER)
  2499. if (rotation & 1) {
  2500. swap_coord(x0, y0);
  2501. swap_coord(x1, y1);
  2502. }
  2503. SPI_BUSY_CHECK;
  2504. DC_C; tft_Write_8(TFT_CASET);
  2505. DC_D; tft_Write_16(x1 | (x0 << 8));
  2506. DC_C; tft_Write_8(TFT_PASET);
  2507. DC_D; tft_Write_16(y1 | (y0 << 8));
  2508. DC_C; tft_Write_8(TFT_RAMWR);
  2509. DC_D;
  2510. #else
  2511. #if defined (SSD1963_DRIVER)
  2512. if ((rotation & 0x1) == 0) { swap_coord(x0, y0); swap_coord(x1, y1); }
  2513. #endif
  2514. #ifdef CGRAM_OFFSET
  2515. x0+=colstart;
  2516. x1+=colstart;
  2517. y0+=rowstart;
  2518. y1+=rowstart;
  2519. #endif
  2520. // Temporary solution is to include the RP2040 optimised code here
  2521. #if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
  2522. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2523. DC_C;
  2524. #if !defined (SPI_18BIT_DRIVER)
  2525. spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
  2526. #endif
  2527. spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
  2528. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2529. DC_D;
  2530. spi_get_hw(spi0)->dr = (uint32_t)x0>>8;
  2531. spi_get_hw(spi0)->dr = (uint32_t)x0;
  2532. spi_get_hw(spi0)->dr = (uint32_t)x1>>8;
  2533. spi_get_hw(spi0)->dr = (uint32_t)x1;
  2534. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2535. DC_C;
  2536. spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
  2537. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2538. DC_D;
  2539. spi_get_hw(spi0)->dr = (uint32_t)y0>>8;
  2540. spi_get_hw(spi0)->dr = (uint32_t)y0;
  2541. spi_get_hw(spi0)->dr = (uint32_t)y1>>8;
  2542. spi_get_hw(spi0)->dr = (uint32_t)y1;
  2543. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2544. DC_C;
  2545. spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMWR;
  2546. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2547. #if !defined (SPI_18BIT_DRIVER)
  2548. spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
  2549. #endif
  2550. DC_D;
  2551. #else
  2552. SPI_BUSY_CHECK;
  2553. DC_C; tft_Write_8(TFT_CASET);
  2554. DC_D; tft_Write_32C(x0, x1);
  2555. DC_C; tft_Write_8(TFT_PASET);
  2556. DC_D; tft_Write_32C(y0, y1);
  2557. DC_C; tft_Write_8(TFT_RAMWR);
  2558. DC_D;
  2559. #endif // RP2040 SPI
  2560. #endif
  2561. //end_tft_write(); // Must be called after setWindow
  2562. }
  2563. /***************************************************************************************
  2564. ** Function name: readAddrWindow
  2565. ** Description: define an area to read a stream of pixels
  2566. ***************************************************************************************/
  2567. void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
  2568. {
  2569. //begin_tft_write(); // Must be called before readAddrWindow or CS set low
  2570. int32_t xe = xs + w - 1;
  2571. int32_t ye = ys + h - 1;
  2572. addr_col = 0xFFFF;
  2573. addr_row = 0xFFFF;
  2574. #ifdef CGRAM_OFFSET
  2575. xs += colstart;
  2576. xe += colstart;
  2577. ys += rowstart;
  2578. ye += rowstart;
  2579. #endif
  2580. #if defined (SSD1963_DRIVER)
  2581. if ((rotation & 0x1) == 0) { swap_coord(xs, ys); swap_coord(xe, ye); }
  2582. #endif
  2583. // Temporary solution is to include the RP2040 optimised code here
  2584. #if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
  2585. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2586. DC_C;
  2587. spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
  2588. spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
  2589. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2590. DC_D;
  2591. spi_get_hw(spi0)->dr = (uint32_t)xs>>8;
  2592. spi_get_hw(spi0)->dr = (uint32_t)xs;
  2593. spi_get_hw(spi0)->dr = (uint32_t)xe>>8;
  2594. spi_get_hw(spi0)->dr = (uint32_t)xe;
  2595. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2596. DC_C;
  2597. spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
  2598. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2599. DC_D;
  2600. spi_get_hw(spi0)->dr = (uint32_t)ys>>8;
  2601. spi_get_hw(spi0)->dr = (uint32_t)ys;
  2602. spi_get_hw(spi0)->dr = (uint32_t)ye>>8;
  2603. spi_get_hw(spi0)->dr = (uint32_t)ye;
  2604. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2605. DC_C;
  2606. spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMRD;
  2607. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2608. //spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
  2609. DC_D;
  2610. // Flush the rx buffer and reset overflow flag
  2611. while (spi_is_readable(spi0)) (void)spi_get_hw(spi0)->dr;
  2612. spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS;
  2613. #else
  2614. // Column addr set
  2615. DC_C; tft_Write_8(TFT_CASET);
  2616. DC_D; tft_Write_32C(xs, xe);
  2617. // Row addr set
  2618. DC_C; tft_Write_8(TFT_PASET);
  2619. DC_D; tft_Write_32C(ys, ye);
  2620. // Read CGRAM command
  2621. DC_C; tft_Write_8(TFT_RAMRD);
  2622. DC_D;
  2623. #endif // RP2040 SPI
  2624. //end_tft_write(); // Must be called after readAddrWindow or CS set high
  2625. }
  2626. /***************************************************************************************
  2627. ** Function name: drawPixel
  2628. ** Description: push a single pixel at an arbitrary position
  2629. ***************************************************************************************/
  2630. void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
  2631. {
  2632. if (_vpOoB) return;
  2633. x+= _xDatum;
  2634. y+= _yDatum;
  2635. // Range checking
  2636. if ((x < _vpX) || (y < _vpY) ||(x >= _vpW) || (y >= _vpH)) return;
  2637. #ifdef CGRAM_OFFSET
  2638. x+=colstart;
  2639. y+=rowstart;
  2640. #endif
  2641. begin_tft_write();
  2642. #if defined (ILI9225_DRIVER)
  2643. if (rotation & 0x01) { swap_coord(x, y); }
  2644. SPI_BUSY_CHECK;
  2645. // Set window to full screen to optimise sequential pixel rendering
  2646. if (addr_row != 0x9225) {
  2647. addr_row = 0x9225; // addr_row used for flag
  2648. DC_C; tft_Write_8(TFT_CASET1);
  2649. DC_D; tft_Write_16(0);
  2650. DC_C; tft_Write_8(TFT_CASET2);
  2651. DC_D; tft_Write_16(175);
  2652. DC_C; tft_Write_8(TFT_PASET1);
  2653. DC_D; tft_Write_16(0);
  2654. DC_C; tft_Write_8(TFT_PASET2);
  2655. DC_D; tft_Write_16(219);
  2656. }
  2657. // Define pixel coordinate
  2658. DC_C; tft_Write_8(TFT_RAM_ADDR1);
  2659. DC_D; tft_Write_16(x);
  2660. DC_C; tft_Write_8(TFT_RAM_ADDR2);
  2661. DC_D; tft_Write_16(y);
  2662. // write to RAM
  2663. DC_C; tft_Write_8(TFT_RAMWR);
  2664. #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32)
  2665. DC_D; tft_Write_16(color);
  2666. #else
  2667. DC_D; tft_Write_16N(color);
  2668. #endif
  2669. // Temporary solution is to include the RP2040 optimised code here
  2670. #elif defined (ARDUINO_ARCH_RP2040)
  2671. // Since the SPI functions do not terminate until transmission is complete
  2672. // a busy check is not needed.
  2673. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2674. DC_C;
  2675. spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
  2676. spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
  2677. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS){};
  2678. DC_D;
  2679. spi_get_hw(spi0)->dr = (uint32_t)x>>8;
  2680. spi_get_hw(spi0)->dr = (uint32_t)x;
  2681. spi_get_hw(spi0)->dr = (uint32_t)x>>8;
  2682. spi_get_hw(spi0)->dr = (uint32_t)x;
  2683. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2684. DC_C;
  2685. spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
  2686. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2687. DC_D;
  2688. spi_get_hw(spi0)->dr = (uint32_t)y>>8;
  2689. spi_get_hw(spi0)->dr = (uint32_t)y;
  2690. spi_get_hw(spi0)->dr = (uint32_t)y>>8;
  2691. spi_get_hw(spi0)->dr = (uint32_t)y;
  2692. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2693. DC_C;
  2694. spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMWR;
  2695. #if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
  2696. uint8_t r = (color & 0xF800)>>8;
  2697. uint8_t g = (color & 0x07E0)>>3;
  2698. uint8_t b = (color & 0x001F)<<3;
  2699. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2700. DC_D;
  2701. tft_Write_8N(r); tft_Write_8N(g); tft_Write_8N(b);
  2702. #else
  2703. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2704. DC_D;
  2705. spi_get_hw(spi0)->dr = (uint32_t)color>>8;
  2706. spi_get_hw(spi0)->dr = (uint32_t)color;
  2707. #endif
  2708. /*
  2709. // Subsequent pixel reads work OK without draining the FIFO...
  2710. // Drain RX FIFO, then wait for shifting to finish (which may be *after*
  2711. // TX FIFO drains), then drain RX FIFO again
  2712. while (spi_is_readable(spi0))
  2713. (void)spi_get_hw(spi0)->dr;
  2714. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS)
  2715. tight_loop_contents();
  2716. while (spi_is_readable(spi0))
  2717. (void)spi_get_hw(spi0)->dr;
  2718. //*/
  2719. // Subsequent pixel reads work without this
  2720. // spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS;
  2721. while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
  2722. // Next call will start with 8 bit command so changing to 16 bit not needed here
  2723. //spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
  2724. #else
  2725. #if defined (SSD1351_DRIVER) || defined (SSD1963_DRIVER)
  2726. if ((rotation & 0x1) == 0) { swap_coord(x, y); }
  2727. #endif
  2728. SPI_BUSY_CHECK;
  2729. #if defined (MULTI_TFT_SUPPORT) || defined (GC9A01_DRIVER)
  2730. // No optimisation
  2731. DC_C; tft_Write_8(TFT_CASET);
  2732. DC_D; tft_Write_32D(x);
  2733. DC_C; tft_Write_8(TFT_PASET);
  2734. DC_D; tft_Write_32D(y);
  2735. #elif defined (SSD1351_DRIVER)
  2736. // No need to send x if it has not changed (speeds things up)
  2737. if (addr_col != x) {
  2738. DC_C; tft_Write_8(TFT_CASET);
  2739. DC_D; tft_Write_16(x | (x << 8));
  2740. addr_col = x;
  2741. }
  2742. // No need to send y if it has not changed (speeds things up)
  2743. if (addr_row != y) {
  2744. DC_C; tft_Write_8(TFT_PASET);
  2745. DC_D; tft_Write_16(y | (y << 8));
  2746. addr_row = y;
  2747. }
  2748. #else
  2749. // No need to send x if it has not changed (speeds things up)
  2750. if (addr_col != x) {
  2751. DC_C; tft_Write_8(TFT_CASET);
  2752. DC_D; tft_Write_32D(x);
  2753. addr_col = x;
  2754. }
  2755. // No need to send y if it has not changed (speeds things up)
  2756. if (addr_row != y) {
  2757. DC_C; tft_Write_8(TFT_PASET);
  2758. DC_D; tft_Write_32D(y);
  2759. addr_row = y;
  2760. }
  2761. #endif
  2762. DC_C; tft_Write_8(TFT_RAMWR);
  2763. #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32)
  2764. DC_D; tft_Write_16(color);
  2765. #else
  2766. DC_D; tft_Write_16N(color);
  2767. #endif
  2768. #endif
  2769. end_tft_write();
  2770. }
  2771. /***************************************************************************************
  2772. ** Function name: pushColor
  2773. ** Description: push a single pixel
  2774. ***************************************************************************************/
  2775. void TFT_eSPI::pushColor(uint16_t color)
  2776. {
  2777. begin_tft_write();
  2778. tft_Write_16(color);
  2779. end_tft_write();
  2780. }
  2781. /***************************************************************************************
  2782. ** Function name: pushColor
  2783. ** Description: push a single colour to "len" pixels
  2784. ***************************************************************************************/
  2785. void TFT_eSPI::pushColor(uint16_t color, uint32_t len)
  2786. {
  2787. begin_tft_write();
  2788. pushBlock(color, len);
  2789. end_tft_write();
  2790. }
  2791. /***************************************************************************************
  2792. ** Function name: startWrite
  2793. ** Description: begin transaction with CS low, MUST later call endWrite
  2794. ***************************************************************************************/
  2795. void TFT_eSPI::startWrite(void)
  2796. {
  2797. begin_tft_write();
  2798. lockTransaction = true; // Lock transaction for all sequentially run sketch functions
  2799. inTransaction = true;
  2800. }
  2801. /***************************************************************************************
  2802. ** Function name: endWrite
  2803. ** Description: end transaction with CS high
  2804. ***************************************************************************************/
  2805. void TFT_eSPI::endWrite(void)
  2806. {
  2807. lockTransaction = false; // Release sketch induced transaction lock
  2808. inTransaction = false;
  2809. DMA_BUSY_CHECK; // Safety check - user code should have checked this!
  2810. end_tft_write(); // Release SPI bus
  2811. }
  2812. /***************************************************************************************
  2813. ** Function name: writeColor (use startWrite() and endWrite() before & after)
  2814. ** Description: raw write of "len" pixels avoiding transaction check
  2815. ***************************************************************************************/
  2816. void TFT_eSPI::writeColor(uint16_t color, uint32_t len)
  2817. {
  2818. pushBlock(color, len);
  2819. }
  2820. /***************************************************************************************
  2821. ** Function name: pushColors
  2822. ** Description: push an array of pixels for 16 bit raw image drawing
  2823. ***************************************************************************************/
  2824. // Assumed that setAddrWindow() has previously been called
  2825. // len is number of bytes, not pixels
  2826. void TFT_eSPI::pushColors(uint8_t *data, uint32_t len)
  2827. {
  2828. begin_tft_write();
  2829. pushPixels(data, len>>1);
  2830. end_tft_write();
  2831. }
  2832. /***************************************************************************************
  2833. ** Function name: pushColors
  2834. ** Description: push an array of pixels, for image drawing
  2835. ***************************************************************************************/
  2836. void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap)
  2837. {
  2838. begin_tft_write();
  2839. if (swap) {swap = _swapBytes; _swapBytes = true; }
  2840. pushPixels(data, len);
  2841. _swapBytes = swap; // Restore old value
  2842. end_tft_write();
  2843. }
  2844. /***************************************************************************************
  2845. ** Function name: drawLine
  2846. ** Description: draw a line between 2 arbitrary points
  2847. ***************************************************************************************/
  2848. // Bresenham's algorithm - thx wikipedia - speed enhanced by Bodmer to use
  2849. // an efficient FastH/V Line draw routine for line segments of 2 pixels or more
  2850. void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color)
  2851. {
  2852. if (_vpOoB) return;
  2853. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  2854. inTransaction = true;
  2855. //x+= _xDatum; // Not added here, added by drawPixel & drawFastXLine
  2856. //y+= _yDatum;
  2857. bool steep = abs(y1 - y0) > abs(x1 - x0);
  2858. if (steep) {
  2859. swap_coord(x0, y0);
  2860. swap_coord(x1, y1);
  2861. }
  2862. if (x0 > x1) {
  2863. swap_coord(x0, x1);
  2864. swap_coord(y0, y1);
  2865. }
  2866. int32_t dx = x1 - x0, dy = abs(y1 - y0);;
  2867. int32_t err = dx >> 1, ystep = -1, xs = x0, dlen = 0;
  2868. if (y0 < y1) ystep = 1;
  2869. // Split into steep and not steep for FastH/V separation
  2870. if (steep) {
  2871. for (; x0 <= x1; x0++) {
  2872. dlen++;
  2873. err -= dy;
  2874. if (err < 0) {
  2875. if (dlen == 1) drawPixel(y0, xs, color);
  2876. else drawFastVLine(y0, xs, dlen, color);
  2877. dlen = 0;
  2878. y0 += ystep; xs = x0 + 1;
  2879. err += dx;
  2880. }
  2881. }
  2882. if (dlen) drawFastVLine(y0, xs, dlen, color);
  2883. }
  2884. else
  2885. {
  2886. for (; x0 <= x1; x0++) {
  2887. dlen++;
  2888. err -= dy;
  2889. if (err < 0) {
  2890. if (dlen == 1) drawPixel(xs, y0, color);
  2891. else drawFastHLine(xs, y0, dlen, color);
  2892. dlen = 0;
  2893. y0 += ystep; xs = x0 + 1;
  2894. err += dx;
  2895. }
  2896. }
  2897. if (dlen) drawFastHLine(xs, y0, dlen, color);
  2898. }
  2899. inTransaction = lockTransaction;
  2900. end_tft_write();
  2901. }
  2902. /***************************************************************************************
  2903. ** Function name: drawFastVLine
  2904. ** Description: draw a vertical line
  2905. ***************************************************************************************/
  2906. void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
  2907. {
  2908. if (_vpOoB) return;
  2909. x+= _xDatum;
  2910. y+= _yDatum;
  2911. // Clipping
  2912. if ((x < _vpX) || (x >= _vpW) || (y >= _vpH)) return;
  2913. if (y < _vpY) { h += y - _vpY; y = _vpY; }
  2914. if ((y + h) > _vpH) h = _vpH - y;
  2915. if (h < 1) return;
  2916. begin_tft_write();
  2917. setWindow(x, y, x, y + h - 1);
  2918. pushBlock(color, h);
  2919. end_tft_write();
  2920. }
  2921. /***************************************************************************************
  2922. ** Function name: drawFastHLine
  2923. ** Description: draw a horizontal line
  2924. ***************************************************************************************/
  2925. void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
  2926. {
  2927. if (_vpOoB) return;
  2928. x+= _xDatum;
  2929. y+= _yDatum;
  2930. // Clipping
  2931. if ((y < _vpY) || (x >= _vpW) || (y >= _vpH)) return;
  2932. if (x < _vpX) { w += x - _vpX; x = _vpX; }
  2933. if ((x + w) > _vpW) w = _vpW - x;
  2934. if (w < 1) return;
  2935. begin_tft_write();
  2936. setWindow(x, y, x + w - 1, y);
  2937. pushBlock(color, w);
  2938. end_tft_write();
  2939. }
  2940. /***************************************************************************************
  2941. ** Function name: fillRect
  2942. ** Description: draw a filled rectangle
  2943. ***************************************************************************************/
  2944. void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
  2945. {
  2946. if (_vpOoB) return;
  2947. x+= _xDatum;
  2948. y+= _yDatum;
  2949. // Clipping
  2950. if ((x >= _vpW) || (y >= _vpH)) return;
  2951. if (x < _vpX) { w += x - _vpX; x = _vpX; }
  2952. if (y < _vpY) { h += y - _vpY; y = _vpY; }
  2953. if ((x + w) > _vpW) w = _vpW - x;
  2954. if ((y + h) > _vpH) h = _vpH - y;
  2955. if ((w < 1) || (h < 1)) return;
  2956. //Serial.print(" _xDatum=");Serial.print( _xDatum);Serial.print(", _yDatum=");Serial.print( _yDatum);
  2957. //Serial.print(", _xWidth=");Serial.print(_xWidth);Serial.print(", _yHeight=");Serial.println(_yHeight);
  2958. //Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
  2959. //Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
  2960. //Serial.print(" x=");Serial.print( y);Serial.print(", y=");Serial.print( y);
  2961. //Serial.print(", w=");Serial.print(w);Serial.print(", h=");Serial.println(h);
  2962. begin_tft_write();
  2963. setWindow(x, y, x + w - 1, y + h - 1);
  2964. pushBlock(color, w * h);
  2965. end_tft_write();
  2966. }
  2967. /***************************************************************************************
  2968. ** Function name: color565
  2969. ** Description: convert three 8 bit RGB levels to a 16 bit colour value
  2970. ***************************************************************************************/
  2971. uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b)
  2972. {
  2973. return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
  2974. }
  2975. /***************************************************************************************
  2976. ** Function name: color16to8
  2977. ** Description: convert 16 bit colour to an 8 bit 332 RGB colour value
  2978. ***************************************************************************************/
  2979. uint8_t TFT_eSPI::color16to8(uint16_t c)
  2980. {
  2981. return ((c & 0xE000)>>8) | ((c & 0x0700)>>6) | ((c & 0x0018)>>3);
  2982. }
  2983. /***************************************************************************************
  2984. ** Function name: color8to16
  2985. ** Description: convert 8 bit colour to a 16 bit 565 colour value
  2986. ***************************************************************************************/
  2987. uint16_t TFT_eSPI::color8to16(uint8_t color)
  2988. {
  2989. uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
  2990. uint16_t color16 = 0;
  2991. // =====Green===== ===============Red==============
  2992. color16 = (color & 0x1C)<<6 | (color & 0xC0)<<5 | (color & 0xE0)<<8;
  2993. // =====Green===== =======Blue======
  2994. color16 |= (color & 0x1C)<<3 | blue[color & 0x03];
  2995. return color16;
  2996. }
  2997. /***************************************************************************************
  2998. ** Function name: color16to24
  2999. ** Description: convert 16 bit colour to a 24 bit 888 colour value
  3000. ***************************************************************************************/
  3001. uint32_t TFT_eSPI::color16to24(uint16_t color565)
  3002. {
  3003. uint8_t r = (color565 >> 8) & 0xF8; r |= (r >> 5);
  3004. uint8_t g = (color565 >> 3) & 0xFC; g |= (g >> 6);
  3005. uint8_t b = (color565 << 3) & 0xF8; b |= (b >> 5);
  3006. return ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b << 0);
  3007. }
  3008. /***************************************************************************************
  3009. ** Function name: color24to16
  3010. ** Description: convert 24 bit colour to a 16 bit 565 colour value
  3011. ***************************************************************************************/
  3012. uint32_t TFT_eSPI::color24to16(uint32_t color888)
  3013. {
  3014. uint16_t r = (color888 >> 8) & 0xF800;
  3015. uint16_t g = (color888 >> 5) & 0x07E0;
  3016. uint16_t b = (color888 >> 3) & 0x001F;
  3017. return (r | g | b);
  3018. }
  3019. /***************************************************************************************
  3020. ** Function name: invertDisplay
  3021. ** Description: invert the display colours i = 1 invert, i = 0 normal
  3022. ***************************************************************************************/
  3023. void TFT_eSPI::invertDisplay(bool i)
  3024. {
  3025. begin_tft_write();
  3026. // Send the command twice as otherwise it does not always work!
  3027. writecommand(i ? TFT_INVON : TFT_INVOFF);
  3028. writecommand(i ? TFT_INVON : TFT_INVOFF);
  3029. end_tft_write();
  3030. }
  3031. /**************************************************************************
  3032. ** Function name: setAttribute
  3033. ** Description: Sets a control parameter of an attribute
  3034. **************************************************************************/
  3035. void TFT_eSPI::setAttribute(uint8_t attr_id, uint8_t param) {
  3036. switch (attr_id) {
  3037. break;
  3038. case CP437_SWITCH:
  3039. _cp437 = param;
  3040. break;
  3041. case UTF8_SWITCH:
  3042. _utf8 = param;
  3043. decoderState = 0;
  3044. break;
  3045. case PSRAM_ENABLE:
  3046. #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT)
  3047. if (psramFound()) _psram_enable = param; // Enable the use of PSRAM (if available)
  3048. else
  3049. #endif
  3050. _psram_enable = false;
  3051. break;
  3052. //case 4: // TBD future feature control
  3053. // _tbd = param;
  3054. // break;
  3055. }
  3056. }
  3057. /**************************************************************************
  3058. ** Function name: getAttribute
  3059. ** Description: Get value of an attribute (control parameter)
  3060. **************************************************************************/
  3061. uint8_t TFT_eSPI::getAttribute(uint8_t attr_id) {
  3062. switch (attr_id) {
  3063. case CP437_SWITCH: // ON/OFF control of full CP437 character set
  3064. return _cp437;
  3065. case UTF8_SWITCH: // ON/OFF control of UTF-8 decoding
  3066. return _utf8;
  3067. case PSRAM_ENABLE:
  3068. return _psram_enable;
  3069. //case 3: // TBD future feature control
  3070. // return _tbd;
  3071. // break;
  3072. }
  3073. return false;
  3074. }
  3075. /***************************************************************************************
  3076. ** Function name: decodeUTF8
  3077. ** Description: Serial UTF-8 decoder with fall-back to extended ASCII
  3078. *************************************************************************************x*/
  3079. uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
  3080. {
  3081. if (!_utf8) return c;
  3082. // 7 bit Unicode Code Point
  3083. if ((c & 0x80) == 0x00) {
  3084. decoderState = 0;
  3085. return c;
  3086. }
  3087. if (decoderState == 0) {
  3088. // 11 bit Unicode Code Point
  3089. if ((c & 0xE0) == 0xC0) {
  3090. decoderBuffer = ((c & 0x1F)<<6);
  3091. decoderState = 1;
  3092. return 0;
  3093. }
  3094. // 16 bit Unicode Code Point
  3095. if ((c & 0xF0) == 0xE0) {
  3096. decoderBuffer = ((c & 0x0F)<<12);
  3097. decoderState = 2;
  3098. return 0;
  3099. }
  3100. // 21 bit Unicode Code Point not supported so fall-back to extended ASCII
  3101. // if ((c & 0xF8) == 0xF0) return c;
  3102. }
  3103. else {
  3104. if (decoderState == 2) {
  3105. decoderBuffer |= ((c & 0x3F)<<6);
  3106. decoderState--;
  3107. return 0;
  3108. }
  3109. else {
  3110. decoderBuffer |= (c & 0x3F);
  3111. decoderState = 0;
  3112. return decoderBuffer;
  3113. }
  3114. }
  3115. decoderState = 0;
  3116. return c; // fall-back to extended ASCII
  3117. }
  3118. /***************************************************************************************
  3119. ** Function name: decodeUTF8
  3120. ** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
  3121. *************************************************************************************x*/
  3122. uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
  3123. {
  3124. uint16_t c = buf[(*index)++];
  3125. //Serial.print("Byte from string = 0x"); Serial.println(c, HEX);
  3126. if (!_utf8) return c;
  3127. // 7 bit Unicode
  3128. if ((c & 0x80) == 0x00) return c;
  3129. // 11 bit Unicode
  3130. if (((c & 0xE0) == 0xC0) && (remaining > 1))
  3131. return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F);
  3132. // 16 bit Unicode
  3133. if (((c & 0xF0) == 0xE0) && (remaining > 2)) {
  3134. c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6);
  3135. return c | ((buf[(*index)++]&0x3F));
  3136. }
  3137. // 21 bit Unicode not supported so fall-back to extended ASCII
  3138. // if ((c & 0xF8) == 0xF0) return c;
  3139. return c; // fall-back to extended ASCII
  3140. }
  3141. /***************************************************************************************
  3142. ** Function name: alphaBlend
  3143. ** Description: Blend 16bit foreground and background
  3144. *************************************************************************************x*/
  3145. uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc)
  3146. {
  3147. // For speed use fixed point maths and rounding to permit a power of 2 division
  3148. uint16_t fgR = ((fgc >> 10) & 0x3E) + 1;
  3149. uint16_t fgG = ((fgc >> 4) & 0x7E) + 1;
  3150. uint16_t fgB = ((fgc << 1) & 0x3E) + 1;
  3151. uint16_t bgR = ((bgc >> 10) & 0x3E) + 1;
  3152. uint16_t bgG = ((bgc >> 4) & 0x7E) + 1;
  3153. uint16_t bgB = ((bgc << 1) & 0x3E) + 1;
  3154. // Shift right 1 to drop rounding bit and shift right 8 to divide by 256
  3155. uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
  3156. uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
  3157. uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
  3158. // Combine RGB565 colours into 16 bits
  3159. //return ((r&0x18) << 11) | ((g&0x30) << 5) | ((b&0x18) << 0); // 2 bit greyscale
  3160. //return ((r&0x1E) << 11) | ((g&0x3C) << 5) | ((b&0x1E) << 0); // 4 bit greyscale
  3161. return (r << 11) | (g << 5) | (b << 0);
  3162. }
  3163. /***************************************************************************************
  3164. ** Function name: alphaBlend
  3165. ** Description: Blend 16bit foreground and background with dither
  3166. *************************************************************************************x*/
  3167. uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither)
  3168. {
  3169. if (dither) {
  3170. int16_t alphaDither = (int16_t)alpha - dither + random(2*dither+1); // +/-4 randomised
  3171. alpha = (uint8_t)alphaDither;
  3172. if (alphaDither < 0) alpha = 0;
  3173. if (alphaDither >255) alpha = 255;
  3174. }
  3175. return alphaBlend(alpha, fgc, bgc);
  3176. }
  3177. /***************************************************************************************
  3178. ** Function name: alphaBlend
  3179. ** Description: Blend 24bit foreground and background with optional dither
  3180. *************************************************************************************x*/
  3181. uint32_t TFT_eSPI::alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither)
  3182. {
  3183. if (dither) {
  3184. int16_t alphaDither = (int16_t)alpha - dither + random(2*dither+1); // +/-dither randomised
  3185. alpha = (uint8_t)alphaDither;
  3186. if (alphaDither < 0) alpha = 0;
  3187. if (alphaDither >255) alpha = 255;
  3188. }
  3189. // For speed use fixed point maths and rounding to permit a power of 2 division
  3190. uint16_t fgR = ((fgc >> 15) & 0x1FE) + 1;
  3191. uint16_t fgG = ((fgc >> 7) & 0x1FE) + 1;
  3192. uint16_t fgB = ((fgc << 1) & 0x1FE) + 1;
  3193. uint16_t bgR = ((bgc >> 15) & 0x1FE) + 1;
  3194. uint16_t bgG = ((bgc >> 7) & 0x1FE) + 1;
  3195. uint16_t bgB = ((bgc << 1) & 0x1FE) + 1;
  3196. // Shift right 1 to drop rounding bit and shift right 8 to divide by 256
  3197. uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
  3198. uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
  3199. uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
  3200. // Combine RGB colours into 24 bits
  3201. return (r << 16) | (g << 8) | (b << 0);
  3202. }
  3203. /***************************************************************************************
  3204. ** Function name: write
  3205. ** Description: draw characters piped through serial stream
  3206. ***************************************************************************************/
  3207. size_t TFT_eSPI::write(uint8_t utf8)
  3208. {
  3209. if (_vpOoB) return 1;
  3210. uint16_t uniCode = decodeUTF8(utf8);
  3211. if (!uniCode) return 1;
  3212. if (utf8 == '\r') return 1;
  3213. #ifdef SMOOTH_FONT
  3214. if(fontLoaded) {
  3215. if (uniCode < 32 && utf8 != '\n') return 1;
  3216. drawGlyph(uniCode);
  3217. return 1;
  3218. }
  3219. #endif
  3220. if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors
  3221. else if (uniCode < 32) return 1;
  3222. uint16_t cwidth = 0;
  3223. uint16_t cheight = 0;
  3224. //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  3225. //Serial.print((uint8_t) uniCode); // Debug line sends all printed TFT text to serial port
  3226. //Serial.println(uniCode, HEX); // Debug line sends all printed TFT text to serial port
  3227. //delay(5); // Debug optional wait for serial port to flush through
  3228. //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  3229. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3230. #ifdef LOAD_GFXFF
  3231. if(!gfxFont) {
  3232. #endif
  3233. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3234. #ifdef LOAD_FONT2
  3235. if (textfont == 2) {
  3236. if (uniCode > 127) return 1;
  3237. cwidth = pgm_read_byte(widtbl_f16 + uniCode-32);
  3238. cheight = chr_hgt_f16;
  3239. // Font 2 is rendered in whole byte widths so we must allow for this
  3240. cwidth = (cwidth + 6) / 8; // Width in whole bytes for font 2, should be + 7 but must allow for font width change
  3241. cwidth = cwidth * 8; // Width converted back to pixels
  3242. }
  3243. #ifdef LOAD_RLE
  3244. else
  3245. #endif
  3246. #endif
  3247. #ifdef LOAD_RLE
  3248. {
  3249. if ((textfont>2) && (textfont<9)) {
  3250. if (uniCode > 127) return 1;
  3251. // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements
  3252. cwidth = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 );
  3253. cheight= pgm_read_byte( &fontdata[textfont].height );
  3254. }
  3255. }
  3256. #endif
  3257. #ifdef LOAD_GLCD
  3258. if (textfont==1) {
  3259. cwidth = 6;
  3260. cheight = 8;
  3261. }
  3262. #else
  3263. if (textfont==1) return 1;
  3264. #endif
  3265. cheight = cheight * textsize;
  3266. if (utf8 == '\n') {
  3267. cursor_y += cheight;
  3268. cursor_x = 0;
  3269. }
  3270. else {
  3271. if (textwrapX && (cursor_x + cwidth * textsize > width())) {
  3272. cursor_y += cheight;
  3273. cursor_x = 0;
  3274. }
  3275. if (textwrapY && (cursor_y >= (int32_t) height())) cursor_y = 0;
  3276. cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
  3277. }
  3278. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3279. #ifdef LOAD_GFXFF
  3280. } // Custom GFX font
  3281. else {
  3282. if(utf8 == '\n') {
  3283. cursor_x = 0;
  3284. cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
  3285. } else {
  3286. if (uniCode > pgm_read_word(&gfxFont->last )) return 1;
  3287. if (uniCode < pgm_read_word(&gfxFont->first)) return 1;
  3288. uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
  3289. GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
  3290. uint8_t w = pgm_read_byte(&glyph->width),
  3291. h = pgm_read_byte(&glyph->height);
  3292. if((w > 0) && (h > 0)) { // Is there an associated bitmap?
  3293. int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset);
  3294. if(textwrapX && ((cursor_x + textsize * (xo + w)) > width())) {
  3295. // Drawing character would go off right edge; wrap to new line
  3296. cursor_x = 0;
  3297. cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
  3298. }
  3299. if (textwrapY && (cursor_y >= (int32_t) height())) cursor_y = 0;
  3300. drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize);
  3301. }
  3302. cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
  3303. }
  3304. }
  3305. #endif // LOAD_GFXFF
  3306. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3307. return 1;
  3308. }
  3309. /***************************************************************************************
  3310. ** Function name: drawChar
  3311. ** Description: draw a Unicode glyph onto the screen
  3312. ***************************************************************************************/
  3313. // TODO: Rationalise with TFT_eSprite
  3314. // Any UTF-8 decoding must be done before calling drawChar()
  3315. int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y)
  3316. {
  3317. return drawChar(uniCode, x, y, textfont);
  3318. }
  3319. // Any UTF-8 decoding must be done before calling drawChar()
  3320. int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
  3321. {
  3322. if (_vpOoB || !uniCode) return 0;
  3323. if (font==1) {
  3324. #ifdef LOAD_GLCD
  3325. #ifndef LOAD_GFXFF
  3326. drawChar(x, y, uniCode, textcolor, textbgcolor, textsize);
  3327. return 6 * textsize;
  3328. #endif
  3329. #else
  3330. #ifndef LOAD_GFXFF
  3331. return 0;
  3332. #endif
  3333. #endif
  3334. #ifdef LOAD_GFXFF
  3335. drawChar(x, y, uniCode, textcolor, textbgcolor, textsize);
  3336. if(!gfxFont) { // 'Classic' built-in font
  3337. #ifdef LOAD_GLCD
  3338. return 6 * textsize;
  3339. #else
  3340. return 0;
  3341. #endif
  3342. }
  3343. else {
  3344. if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) )) {
  3345. uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
  3346. GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
  3347. return pgm_read_byte(&glyph->xAdvance) * textsize;
  3348. }
  3349. else {
  3350. return 0;
  3351. }
  3352. }
  3353. #endif
  3354. }
  3355. if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0;
  3356. int32_t width = 0;
  3357. int32_t height = 0;
  3358. uint32_t flash_address = 0;
  3359. uniCode -= 32;
  3360. #ifdef LOAD_FONT2
  3361. if (font == 2) {
  3362. flash_address = pgm_read_dword(&chrtbl_f16[uniCode]);
  3363. width = pgm_read_byte(widtbl_f16 + uniCode);
  3364. height = chr_hgt_f16;
  3365. }
  3366. #ifdef LOAD_RLE
  3367. else
  3368. #endif
  3369. #endif
  3370. #ifdef LOAD_RLE
  3371. {
  3372. if ((font>2) && (font<9)) {
  3373. flash_address = pgm_read_dword( (const void*)(pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *)) );
  3374. width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode );
  3375. height= pgm_read_byte( &fontdata[font].height );
  3376. }
  3377. }
  3378. #endif
  3379. int32_t xd = x + _xDatum;
  3380. int32_t yd = y + _yDatum;
  3381. if ((xd + width * textsize < _vpX || xd >= _vpW) && (yd + height * textsize < _vpY || yd >= _vpH)) return width * textsize ;
  3382. int32_t w = width;
  3383. int32_t pX = 0;
  3384. int32_t pY = y;
  3385. uint8_t line = 0;
  3386. bool clip = xd < _vpX || xd + width * textsize >= _vpW || yd < _vpY || yd + height * textsize >= _vpH;
  3387. #ifdef LOAD_FONT2 // chop out code if we do not need it
  3388. if (font == 2) {
  3389. w = w + 6; // Should be + 7 but we need to compensate for width increment
  3390. w = w / 8;
  3391. if (textcolor == textbgcolor || textsize != 1 || clip) {
  3392. //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
  3393. inTransaction = true;
  3394. for (int32_t i = 0; i < height; i++) {
  3395. if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor);
  3396. for (int32_t k = 0; k < w; k++) {
  3397. line = pgm_read_byte((uint8_t *)flash_address + w * i + k);
  3398. if (line) {
  3399. if (textsize == 1) {
  3400. pX = x + k * 8;
  3401. if (line & 0x80) drawPixel(pX, pY, textcolor);
  3402. if (line & 0x40) drawPixel(pX + 1, pY, textcolor);
  3403. if (line & 0x20) drawPixel(pX + 2, pY, textcolor);
  3404. if (line & 0x10) drawPixel(pX + 3, pY, textcolor);
  3405. if (line & 0x08) drawPixel(pX + 4, pY, textcolor);
  3406. if (line & 0x04) drawPixel(pX + 5, pY, textcolor);
  3407. if (line & 0x02) drawPixel(pX + 6, pY, textcolor);
  3408. if (line & 0x01) drawPixel(pX + 7, pY, textcolor);
  3409. }
  3410. else {
  3411. pX = x + k * 8 * textsize;
  3412. if (line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor);
  3413. if (line & 0x40) fillRect(pX + textsize, pY, textsize, textsize, textcolor);
  3414. if (line & 0x20) fillRect(pX + 2 * textsize, pY, textsize, textsize, textcolor);
  3415. if (line & 0x10) fillRect(pX + 3 * textsize, pY, textsize, textsize, textcolor);
  3416. if (line & 0x08) fillRect(pX + 4 * textsize, pY, textsize, textsize, textcolor);
  3417. if (line & 0x04) fillRect(pX + 5 * textsize, pY, textsize, textsize, textcolor);
  3418. if (line & 0x02) fillRect(pX + 6 * textsize, pY, textsize, textsize, textcolor);
  3419. if (line & 0x01) fillRect(pX + 7 * textsize, pY, textsize, textsize, textcolor);
  3420. }
  3421. }
  3422. }
  3423. pY += textsize;
  3424. }
  3425. inTransaction = lockTransaction;
  3426. end_tft_write();
  3427. }
  3428. else { // Faster drawing of characters and background using block write
  3429. begin_tft_write();
  3430. setWindow(xd, yd, xd + width - 1, yd + height - 1);
  3431. uint8_t mask;
  3432. for (int32_t i = 0; i < height; i++) {
  3433. pX = width;
  3434. for (int32_t k = 0; k < w; k++) {
  3435. line = pgm_read_byte((uint8_t *) (flash_address + w * i + k) );
  3436. mask = 0x80;
  3437. while (mask && pX) {
  3438. if (line & mask) {tft_Write_16(textcolor);}
  3439. else {tft_Write_16(textbgcolor);}
  3440. pX--;
  3441. mask = mask >> 1;
  3442. }
  3443. }
  3444. if (pX) {tft_Write_16(textbgcolor);}
  3445. }
  3446. end_tft_write();
  3447. }
  3448. }
  3449. #ifdef LOAD_RLE
  3450. else
  3451. #endif
  3452. #endif //FONT2
  3453. #ifdef LOAD_RLE //674 bytes of code
  3454. // Font is not 2 and hence is RLE encoded
  3455. {
  3456. begin_tft_write();
  3457. inTransaction = true;
  3458. w *= height; // Now w is total number of pixels in the character
  3459. if (textcolor == textbgcolor && !clip) {
  3460. int32_t px = 0, py = pY; // To hold character block start and end column and row values
  3461. int32_t pc = 0; // Pixel count
  3462. uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel
  3463. uint8_t tnp = 0; // Temporary copy of np for while loop
  3464. uint8_t ts = textsize - 1; // Temporary copy of textsize
  3465. // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area
  3466. // w is total number of pixels to plot to fill character block
  3467. while (pc < w) {
  3468. line = pgm_read_byte((uint8_t *)flash_address);
  3469. flash_address++;
  3470. if (line & 0x80) {
  3471. line &= 0x7F;
  3472. line++;
  3473. if (ts) {
  3474. px = xd + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow
  3475. py = yd + textsize * (pc / width);
  3476. }
  3477. else {
  3478. px = xd + pc % width; // Keep these px and py calculations outside the loop as they are slow
  3479. py = yd + pc / width;
  3480. }
  3481. while (line--) { // In this case the while(line--) is faster
  3482. pc++; // This is faster than putting pc+=line before while()?
  3483. setWindow(px, py, px + ts, py + ts);
  3484. if (ts) {
  3485. tnp = np;
  3486. while (tnp--) {tft_Write_16(textcolor);}
  3487. }
  3488. else {tft_Write_16(textcolor);}
  3489. px += textsize;
  3490. if (px >= (xd + width * textsize)) {
  3491. px = xd;
  3492. py += textsize;
  3493. }
  3494. }
  3495. }
  3496. else {
  3497. line++;
  3498. pc += line;
  3499. }
  3500. }
  3501. }
  3502. else {
  3503. // Text colour != background and textsize = 1 and character is within viewport area
  3504. // so use faster drawing of characters and background using block write
  3505. if (textcolor != textbgcolor && textsize == 1 && !clip)
  3506. {
  3507. setWindow(xd, yd, xd + width - 1, yd + height - 1);
  3508. // Maximum font size is equivalent to 180x180 pixels in area
  3509. while (w > 0) {
  3510. line = pgm_read_byte((uint8_t *)flash_address++); // 8 bytes smaller when incrementing here
  3511. if (line & 0x80) {
  3512. line &= 0x7F;
  3513. line++; w -= line;
  3514. pushBlock(textcolor,line);
  3515. }
  3516. else {
  3517. line++; w -= line;
  3518. pushBlock(textbgcolor,line);
  3519. }
  3520. }
  3521. }
  3522. else
  3523. {
  3524. int32_t px = 0, py = 0; // To hold character pixel coords
  3525. int32_t tx = 0, ty = 0; // To hold character TFT pixel coords
  3526. int32_t pc = 0; // Pixel count
  3527. int32_t pl = 0; // Pixel line length
  3528. uint16_t pcol = 0; // Pixel color
  3529. bool pf = true; // Flag for plotting
  3530. while (pc < w) {
  3531. line = pgm_read_byte((uint8_t *)flash_address);
  3532. flash_address++;
  3533. if (line & 0x80) { pcol = textcolor; line &= 0x7F; pf = true;}
  3534. else { pcol = textbgcolor; if (textcolor == textbgcolor) pf = false;}
  3535. line++;
  3536. px = pc % width;
  3537. tx = x + textsize * px;
  3538. py = pc / width;
  3539. ty = y + textsize * py;
  3540. pl = 0;
  3541. pc += line;
  3542. while (line--) {
  3543. pl++;
  3544. if ((px+pl) >= width) {
  3545. if (pf) fillRect(tx, ty, pl * textsize, textsize, pcol);
  3546. pl = 0;
  3547. px = 0;
  3548. tx = x;
  3549. py ++;
  3550. ty += textsize;
  3551. }
  3552. }
  3553. if (pl && pf) fillRect(tx, ty, pl * textsize, textsize, pcol);
  3554. }
  3555. }
  3556. }
  3557. inTransaction = lockTransaction;
  3558. end_tft_write();
  3559. }
  3560. // End of RLE font rendering
  3561. #endif
  3562. return width * textsize; // x +
  3563. }
  3564. /***************************************************************************************
  3565. ** Function name: drawString (with or without user defined font)
  3566. ** Description : draw string with padding if it is defined
  3567. ***************************************************************************************/
  3568. // Without font number, uses font set by setTextFont()
  3569. int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY)
  3570. {
  3571. int16_t len = string.length() + 2;
  3572. char buffer[len];
  3573. string.toCharArray(buffer, len);
  3574. return drawString(buffer, poX, poY, textfont);
  3575. }
  3576. // With font number
  3577. int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uint8_t font)
  3578. {
  3579. int16_t len = string.length() + 2;
  3580. char buffer[len];
  3581. string.toCharArray(buffer, len);
  3582. return drawString(buffer, poX, poY, font);
  3583. }
  3584. // Without font number, uses font set by setTextFont()
  3585. int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY)
  3586. {
  3587. return drawString(string, poX, poY, textfont);
  3588. }
  3589. // With font number. Note: font number is over-ridden if a smooth font is loaded
  3590. int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font)
  3591. {
  3592. int16_t sumX = 0;
  3593. uint8_t padding = 1, baseline = 0;
  3594. uint16_t cwidth = textWidth(string, font); // Find the pixel width of the string in the font
  3595. uint16_t cheight = 8 * textsize;
  3596. #ifdef LOAD_GFXFF
  3597. #ifdef SMOOTH_FONT
  3598. bool freeFont = (font == 1 && gfxFont && !fontLoaded);
  3599. #else
  3600. bool freeFont = (font == 1 && gfxFont);
  3601. #endif
  3602. if (freeFont) {
  3603. cheight = glyph_ab * textsize;
  3604. poY += cheight; // Adjust for baseline datum of free fonts
  3605. baseline = cheight;
  3606. padding =101; // Different padding method used for Free Fonts
  3607. // We need to make an adjustment for the bottom of the string (eg 'y' character)
  3608. if ((textdatum == BL_DATUM) || (textdatum == BC_DATUM) || (textdatum == BR_DATUM)) {
  3609. cheight += glyph_bb * textsize;
  3610. }
  3611. }
  3612. #endif
  3613. // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font
  3614. #ifdef SMOOTH_FONT
  3615. if(fontLoaded) {
  3616. baseline = gFont.maxAscent;
  3617. cheight = fontHeight();
  3618. }
  3619. else
  3620. #endif
  3621. if (font!=1) {
  3622. baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize;
  3623. cheight = fontHeight(font);
  3624. }
  3625. if (textdatum || padX) {
  3626. switch(textdatum) {
  3627. case TC_DATUM:
  3628. poX -= cwidth/2;
  3629. padding += 1;
  3630. break;
  3631. case TR_DATUM:
  3632. poX -= cwidth;
  3633. padding += 2;
  3634. break;
  3635. case ML_DATUM:
  3636. poY -= cheight/2;
  3637. //padding += 0;
  3638. break;
  3639. case MC_DATUM:
  3640. poX -= cwidth/2;
  3641. poY -= cheight/2;
  3642. padding += 1;
  3643. break;
  3644. case MR_DATUM:
  3645. poX -= cwidth;
  3646. poY -= cheight/2;
  3647. padding += 2;
  3648. break;
  3649. case BL_DATUM:
  3650. poY -= cheight;
  3651. //padding += 0;
  3652. break;
  3653. case BC_DATUM:
  3654. poX -= cwidth/2;
  3655. poY -= cheight;
  3656. padding += 1;
  3657. break;
  3658. case BR_DATUM:
  3659. poX -= cwidth;
  3660. poY -= cheight;
  3661. padding += 2;
  3662. break;
  3663. case L_BASELINE:
  3664. poY -= baseline;
  3665. //padding += 0;
  3666. break;
  3667. case C_BASELINE:
  3668. poX -= cwidth/2;
  3669. poY -= baseline;
  3670. padding += 1;
  3671. break;
  3672. case R_BASELINE:
  3673. poX -= cwidth;
  3674. poY -= baseline;
  3675. padding += 2;
  3676. break;
  3677. }
  3678. }
  3679. int8_t xo = 0;
  3680. #ifdef LOAD_GFXFF
  3681. if (freeFont && (textcolor!=textbgcolor)) {
  3682. cheight = (glyph_ab + glyph_bb) * textsize;
  3683. // Get the offset for the first character only to allow for negative offsets
  3684. uint16_t c2 = 0;
  3685. uint16_t len = strlen(string);
  3686. uint16_t n = 0;
  3687. while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n);
  3688. if((c2 >= pgm_read_word(&gfxFont->first)) && (c2 <= pgm_read_word(&gfxFont->last) )) {
  3689. c2 -= pgm_read_word(&gfxFont->first);
  3690. GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
  3691. xo = pgm_read_byte(&glyph->xOffset) * textsize;
  3692. // Adjust for negative xOffset
  3693. if (xo > 0) xo = 0;
  3694. else cwidth -= xo;
  3695. // Add 1 pixel of padding all round
  3696. //cheight +=2;
  3697. //fillRect(poX+xo-1, poY - 1 - glyph_ab * textsize, cwidth+2, cheight, textbgcolor);
  3698. fillRect(poX+xo, poY - glyph_ab * textsize, cwidth, cheight, textbgcolor);
  3699. }
  3700. padding -=100;
  3701. }
  3702. #endif
  3703. uint16_t len = strlen(string);
  3704. uint16_t n = 0;
  3705. #ifdef SMOOTH_FONT
  3706. if(fontLoaded) {
  3707. if (textcolor!=textbgcolor) fillRect(poX, poY, cwidth, cheight, textbgcolor);
  3708. /*
  3709. // The above only works for a single text line, not if the text is going to wrap...
  3710. // So need to use code like this in a while loop to fix it:
  3711. if (textwrapX && (cursor_x + width * textsize > width())) {
  3712. cursor_y += height;
  3713. cursor_x = 0;
  3714. }
  3715. if (textwrapY && (cursor_y >= (int32_t)height())) cursor_y = 0;
  3716. cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
  3717. */
  3718. setCursor(poX, poY);
  3719. while (n < len) {
  3720. uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
  3721. drawGlyph(uniCode);
  3722. }
  3723. sumX += cwidth;
  3724. //fontFile.close();
  3725. }
  3726. else
  3727. #endif
  3728. {
  3729. while (n < len) {
  3730. uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
  3731. sumX += drawChar(uniCode, poX+sumX, poY, font);
  3732. }
  3733. }
  3734. //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  3735. // Switch on debugging for the padding areas
  3736. //#define PADDING_DEBUG
  3737. #ifndef PADDING_DEBUG
  3738. //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  3739. if((padX>cwidth) && (textcolor!=textbgcolor)) {
  3740. int16_t padXc = poX+cwidth+xo;
  3741. #ifdef LOAD_GFXFF
  3742. if (freeFont) {
  3743. poX +=xo; // Adjust for negative offset start character
  3744. poY -= glyph_ab * textsize;
  3745. sumX += poX;
  3746. }
  3747. #endif
  3748. switch(padding) {
  3749. case 1:
  3750. fillRect(padXc,poY,padX-cwidth,cheight, textbgcolor);
  3751. break;
  3752. case 2:
  3753. fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
  3754. padXc = poX - ((padX-cwidth)>>1);
  3755. fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
  3756. break;
  3757. case 3:
  3758. if (padXc>padX) padXc = padX;
  3759. fillRect(poX + cwidth - padXc,poY,padXc-cwidth,cheight, textbgcolor);
  3760. break;
  3761. }
  3762. }
  3763. #else
  3764. //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  3765. // This is debug code to show text (green box) and blanked (white box) areas
  3766. // It shows that the padding areas are being correctly sized and positioned
  3767. if((padX>sumX) && (textcolor!=textbgcolor)) {
  3768. int16_t padXc = poX+sumX; // Maximum left side padding
  3769. #ifdef LOAD_GFXFF
  3770. if ((font == 1) && (gfxFont)) poY -= glyph_ab;
  3771. #endif
  3772. drawRect(poX,poY,sumX,cheight, TFT_GREEN);
  3773. switch(padding) {
  3774. case 1:
  3775. drawRect(padXc,poY,padX-sumX,cheight, TFT_WHITE);
  3776. break;
  3777. case 2:
  3778. drawRect(padXc,poY,(padX-sumX)>>1, cheight, TFT_WHITE);
  3779. padXc = (padX-sumX)>>1;
  3780. drawRect(poX - padXc,poY,(padX-sumX)>>1,cheight, TFT_WHITE);
  3781. break;
  3782. case 3:
  3783. if (padXc>padX) padXc = padX;
  3784. drawRect(poX + sumX - padXc,poY,padXc-sumX,cheight, TFT_WHITE);
  3785. break;
  3786. }
  3787. }
  3788. #endif
  3789. //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  3790. return sumX;
  3791. }
  3792. /***************************************************************************************
  3793. ** Function name: drawCentreString (deprecated, use setTextDatum())
  3794. ** Descriptions: draw string centred on dX
  3795. ***************************************************************************************/
  3796. int16_t TFT_eSPI::drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font)
  3797. {
  3798. int16_t len = string.length() + 2;
  3799. char buffer[len];
  3800. string.toCharArray(buffer, len);
  3801. return drawCentreString(buffer, dX, poY, font);
  3802. }
  3803. int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font)
  3804. {
  3805. uint8_t tempdatum = textdatum;
  3806. int32_t sumX = 0;
  3807. textdatum = TC_DATUM;
  3808. sumX = drawString(string, dX, poY, font);
  3809. textdatum = tempdatum;
  3810. return sumX;
  3811. }
  3812. /***************************************************************************************
  3813. ** Function name: drawRightString (deprecated, use setTextDatum())
  3814. ** Descriptions: draw string right justified to dX
  3815. ***************************************************************************************/
  3816. int16_t TFT_eSPI::drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font)
  3817. {
  3818. int16_t len = string.length() + 2;
  3819. char buffer[len];
  3820. string.toCharArray(buffer, len);
  3821. return drawRightString(buffer, dX, poY, font);
  3822. }
  3823. int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font)
  3824. {
  3825. uint8_t tempdatum = textdatum;
  3826. int16_t sumX = 0;
  3827. textdatum = TR_DATUM;
  3828. sumX = drawString(string, dX, poY, font);
  3829. textdatum = tempdatum;
  3830. return sumX;
  3831. }
  3832. /***************************************************************************************
  3833. ** Function name: drawNumber
  3834. ** Description: draw a long integer
  3835. ***************************************************************************************/
  3836. int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY)
  3837. {
  3838. isDigits = true; // Eliminate jiggle in monospaced fonts
  3839. char str[12];
  3840. ltoa(long_num, str, 10);
  3841. return drawString(str, poX, poY, textfont);
  3842. }
  3843. int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font)
  3844. {
  3845. isDigits = true; // Eliminate jiggle in monospaced fonts
  3846. char str[12];
  3847. ltoa(long_num, str, 10);
  3848. return drawString(str, poX, poY, font);
  3849. }
  3850. /***************************************************************************************
  3851. ** Function name: drawFloat
  3852. ** Descriptions: drawFloat, prints 7 non zero digits maximum
  3853. ***************************************************************************************/
  3854. // Assemble and print a string, this permits alignment relative to a datum
  3855. // looks complicated but much more compact and actually faster than using print class
  3856. int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY)
  3857. {
  3858. return drawFloat(floatNumber, dp, poX, poY, textfont);
  3859. }
  3860. int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY, uint8_t font)
  3861. {
  3862. isDigits = true;
  3863. char str[14]; // Array to contain decimal string
  3864. uint8_t ptr = 0; // Initialise pointer for array
  3865. int8_t digits = 1; // Count the digits to avoid array overflow
  3866. float rounding = 0.5; // Round up down delta
  3867. if (dp > 7) dp = 7; // Limit the size of decimal portion
  3868. // Adjust the rounding value
  3869. for (uint8_t i = 0; i < dp; ++i) rounding /= 10.0;
  3870. if (floatNumber < -rounding) { // add sign, avoid adding - sign to 0.0!
  3871. str[ptr++] = '-'; // Negative number
  3872. str[ptr] = 0; // Put a null in the array as a precaution
  3873. digits = 0; // Set digits to 0 to compensate so pointer value can be used later
  3874. floatNumber = -floatNumber; // Make positive
  3875. }
  3876. floatNumber += rounding; // Round up or down
  3877. // For error put ... in string and return (all TFT_eSPI library fonts contain . character)
  3878. if (floatNumber >= 2147483647) {
  3879. strcpy(str, "...");
  3880. return drawString(str, poX, poY, font);
  3881. }
  3882. // No chance of overflow from here on
  3883. // Get integer part
  3884. uint32_t temp = (uint32_t)floatNumber;
  3885. // Put integer part into array
  3886. ltoa(temp, str + ptr, 10);
  3887. // Find out where the null is to get the digit count loaded
  3888. while ((uint8_t)str[ptr] != 0) ptr++; // Move the pointer along
  3889. digits += ptr; // Count the digits
  3890. str[ptr++] = '.'; // Add decimal point
  3891. str[ptr] = '0'; // Add a dummy zero
  3892. str[ptr + 1] = 0; // Add a null but don't increment pointer so it can be overwritten
  3893. // Get the decimal portion
  3894. floatNumber = floatNumber - temp;
  3895. // Get decimal digits one by one and put in array
  3896. // Limit digit count so we don't get a false sense of resolution
  3897. uint8_t i = 0;
  3898. while ((i < dp) && (digits < 9)) { // while (i < dp) for no limit but array size must be increased
  3899. i++;
  3900. floatNumber *= 10; // for the next decimal
  3901. temp = floatNumber; // get the decimal
  3902. ltoa(temp, str + ptr, 10);
  3903. ptr++; digits++; // Increment pointer and digits count
  3904. floatNumber -= temp; // Remove that digit
  3905. }
  3906. // Finally we can plot the string and return pixel length
  3907. return drawString(str, poX, poY, font);
  3908. }
  3909. /***************************************************************************************
  3910. ** Function name: setFreeFont
  3911. ** Descriptions: Sets the GFX free font to use
  3912. ***************************************************************************************/
  3913. #ifdef LOAD_GFXFF
  3914. void TFT_eSPI::setFreeFont(const GFXfont *f)
  3915. {
  3916. if (f == nullptr) { // Fix issue #400 (ESP32 crash)
  3917. setTextFont(1); // Use GLCD font
  3918. return;
  3919. }
  3920. textfont = 1;
  3921. gfxFont = (GFXfont *)f;
  3922. glyph_ab = 0;
  3923. glyph_bb = 0;
  3924. uint16_t numChars = pgm_read_word(&gfxFont->last) - pgm_read_word(&gfxFont->first);
  3925. // Find the biggest above and below baseline offsets
  3926. for (uint8_t c = 0; c < numChars; c++) {
  3927. GFXglyph *glyph1 = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]);
  3928. int8_t ab = -pgm_read_byte(&glyph1->yOffset);
  3929. if (ab > glyph_ab) glyph_ab = ab;
  3930. int8_t bb = pgm_read_byte(&glyph1->height) - ab;
  3931. if (bb > glyph_bb) glyph_bb = bb;
  3932. }
  3933. }
  3934. /***************************************************************************************
  3935. ** Function name: setTextFont
  3936. ** Description: Set the font for the print stream
  3937. ***************************************************************************************/
  3938. void TFT_eSPI::setTextFont(uint8_t f)
  3939. {
  3940. textfont = (f > 0) ? f : 1; // Don't allow font 0
  3941. gfxFont = NULL;
  3942. }
  3943. #else
  3944. /***************************************************************************************
  3945. ** Function name: setFreeFont
  3946. ** Descriptions: Sets the GFX free font to use
  3947. ***************************************************************************************/
  3948. // Alternative to setTextFont() so we don't need two different named functions
  3949. void TFT_eSPI::setFreeFont(uint8_t font)
  3950. {
  3951. setTextFont(font);
  3952. }
  3953. /***************************************************************************************
  3954. ** Function name: setTextFont
  3955. ** Description: Set the font for the print stream
  3956. ***************************************************************************************/
  3957. void TFT_eSPI::setTextFont(uint8_t f)
  3958. {
  3959. textfont = (f > 0) ? f : 1; // Don't allow font 0
  3960. }
  3961. #endif
  3962. /***************************************************************************************
  3963. ** Function name: getSPIinstance
  3964. ** Description: Get the instance of the SPI class
  3965. ***************************************************************************************/
  3966. #if !defined (TFT_PARALLEL_8_BIT)
  3967. SPIClass& TFT_eSPI::getSPIinstance(void)
  3968. {
  3969. return spi;
  3970. }
  3971. #endif
  3972. /***************************************************************************************
  3973. ** Function name: getSetup
  3974. ** Description: Get the setup details for diagnostic and sketch access
  3975. ***************************************************************************************/
  3976. void TFT_eSPI::getSetup(setup_t &tft_settings)
  3977. {
  3978. // tft_settings.version is set in header file
  3979. #if defined (PROCESSOR_ID)
  3980. tft_settings.esp = PROCESSOR_ID;
  3981. #else
  3982. tft_settings.esp = -1;
  3983. #endif
  3984. #if defined (SUPPORT_TRANSACTIONS)
  3985. tft_settings.trans = true;
  3986. #else
  3987. tft_settings.trans = false;
  3988. #endif
  3989. #if defined (TFT_PARALLEL_8_BIT)
  3990. tft_settings.serial = false;
  3991. tft_settings.tft_spi_freq = 0;
  3992. #else
  3993. tft_settings.serial = true;
  3994. tft_settings.tft_spi_freq = SPI_FREQUENCY/100000;
  3995. #ifdef SPI_READ_FREQUENCY
  3996. tft_settings.tft_rd_freq = SPI_READ_FREQUENCY/100000;
  3997. #endif
  3998. #endif
  3999. #if defined(TFT_SPI_OVERLAP)
  4000. tft_settings.overlap = true;
  4001. #else
  4002. tft_settings.overlap = false;
  4003. #endif
  4004. tft_settings.tft_driver = TFT_DRIVER;
  4005. tft_settings.tft_width = _init_width;
  4006. tft_settings.tft_height = _init_height;
  4007. #ifdef CGRAM_OFFSET
  4008. tft_settings.r0_x_offset = colstart;
  4009. tft_settings.r0_y_offset = rowstart;
  4010. tft_settings.r1_x_offset = 0;
  4011. tft_settings.r1_y_offset = 0;
  4012. tft_settings.r2_x_offset = 0;
  4013. tft_settings.r2_y_offset = 0;
  4014. tft_settings.r3_x_offset = 0;
  4015. tft_settings.r3_y_offset = 0;
  4016. #else
  4017. tft_settings.r0_x_offset = 0;
  4018. tft_settings.r0_y_offset = 0;
  4019. tft_settings.r1_x_offset = 0;
  4020. tft_settings.r1_y_offset = 0;
  4021. tft_settings.r2_x_offset = 0;
  4022. tft_settings.r2_y_offset = 0;
  4023. tft_settings.r3_x_offset = 0;
  4024. tft_settings.r3_y_offset = 0;
  4025. #endif
  4026. #if defined (TFT_MOSI)
  4027. tft_settings.pin_tft_mosi = TFT_MOSI;
  4028. #else
  4029. tft_settings.pin_tft_mosi = -1;
  4030. #endif
  4031. #if defined (TFT_MISO)
  4032. tft_settings.pin_tft_miso = TFT_MISO;
  4033. #else
  4034. tft_settings.pin_tft_miso = -1;
  4035. #endif
  4036. #if defined (TFT_SCLK)
  4037. tft_settings.pin_tft_clk = TFT_SCLK;
  4038. #else
  4039. tft_settings.pin_tft_clk = -1;
  4040. #endif
  4041. #if defined (TFT_CS)
  4042. tft_settings.pin_tft_cs = TFT_CS;
  4043. #else
  4044. tft_settings.pin_tft_cs = -1;
  4045. #endif
  4046. #if defined (TFT_DC)
  4047. tft_settings.pin_tft_dc = TFT_DC;
  4048. #else
  4049. tft_settings.pin_tft_dc = -1;
  4050. #endif
  4051. #if defined (TFT_RD)
  4052. tft_settings.pin_tft_rd = TFT_RD;
  4053. #else
  4054. tft_settings.pin_tft_rd = -1;
  4055. #endif
  4056. #if defined (TFT_WR)
  4057. tft_settings.pin_tft_wr = TFT_WR;
  4058. #else
  4059. tft_settings.pin_tft_wr = -1;
  4060. #endif
  4061. #if defined (TFT_RST)
  4062. tft_settings.pin_tft_rst = TFT_RST;
  4063. #else
  4064. tft_settings.pin_tft_rst = -1;
  4065. #endif
  4066. #if defined (TFT_PARALLEL_8_BIT)
  4067. tft_settings.pin_tft_d0 = TFT_D0;
  4068. tft_settings.pin_tft_d1 = TFT_D1;
  4069. tft_settings.pin_tft_d2 = TFT_D2;
  4070. tft_settings.pin_tft_d3 = TFT_D3;
  4071. tft_settings.pin_tft_d4 = TFT_D4;
  4072. tft_settings.pin_tft_d5 = TFT_D5;
  4073. tft_settings.pin_tft_d6 = TFT_D6;
  4074. tft_settings.pin_tft_d7 = TFT_D7;
  4075. #else
  4076. tft_settings.pin_tft_d0 = -1;
  4077. tft_settings.pin_tft_d1 = -1;
  4078. tft_settings.pin_tft_d2 = -1;
  4079. tft_settings.pin_tft_d3 = -1;
  4080. tft_settings.pin_tft_d4 = -1;
  4081. tft_settings.pin_tft_d5 = -1;
  4082. tft_settings.pin_tft_d6 = -1;
  4083. tft_settings.pin_tft_d7 = -1;
  4084. #endif
  4085. #if defined (TFT_BL)
  4086. tft_settings.pin_tft_led = TFT_BL;
  4087. #endif
  4088. #if defined (TFT_BACKLIGHT_ON)
  4089. tft_settings.pin_tft_led_on = TFT_BACKLIGHT_ON;
  4090. #endif
  4091. #if defined (TOUCH_CS)
  4092. tft_settings.pin_tch_cs = TOUCH_CS;
  4093. tft_settings.tch_spi_freq = SPI_TOUCH_FREQUENCY/100000;
  4094. #else
  4095. tft_settings.pin_tch_cs = -1;
  4096. tft_settings.tch_spi_freq = 0;
  4097. #endif
  4098. }
  4099. ////////////////////////////////////////////////////////////////////////////////////////
  4100. #ifdef TOUCH_CS
  4101. #include "Extensions/Touch.cpp"
  4102. #include "Extensions/Button.cpp"
  4103. #endif
  4104. #include "Extensions/Sprite.cpp"
  4105. #ifdef SMOOTH_FONT
  4106. #include "Extensions/Smooth_font.cpp"
  4107. #endif
  4108. ////////////////////////////////////////////////////////////////////////////////////////