| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985 |
- /***************************************************
- Arduino TFT graphics library targeted at 32 bit
- processors such as ESP32, ESP8266 and STM32.
- This is a stand-alone library that contains the
- hardware driver, the graphics functions and the
- proportional fonts.
- The larger fonts are Run Length Encoded to reduce their
- size.
- Created by Bodmer 2/12/16
- Last update by Bodmer 20/03/20
- ****************************************************/
- #include "TFT_eSPI.h"
- #if defined (ESP32)
- #include "Processors/TFT_eSPI_ESP32.c"
- #elif defined (ESP8266)
- #include "Processors/TFT_eSPI_ESP8266.c"
- #elif defined (STM32) // (_VARIANT_ARDUINO_STM32_) stm32_def.h
- #include "Processors/TFT_eSPI_STM32.c"
- #elif defined (ARDUINO_ARCH_RP2040) // Raspberry Pi Pico
- #include "Processors/TFT_eSPI_RP2040.c"
- #else
- #include "Processors/TFT_eSPI_Generic.c"
- #endif
- #ifndef SPI_BUSY_CHECK
- #define SPI_BUSY_CHECK
- #endif
- // Clipping macro for pushImage
- #define PI_CLIP \
- if (_vpOoB) return; \
- x+= _xDatum; \
- y+= _yDatum; \
- \
- if ((x >= _vpW) || (y >= _vpH)) return; \
- \
- int32_t dx = 0; \
- int32_t dy = 0; \
- int32_t dw = w; \
- int32_t dh = h; \
- \
- if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } \
- if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } \
- \
- if ((x + dw) > _vpW ) dw = _vpW - x; \
- if ((y + dh) > _vpH ) dh = _vpH - y; \
- \
- if (dw < 1 || dh < 1) return;
- /***************************************************************************************
- ** Function name: begin_tft_write (was called spi_begin)
- ** Description: Start SPI transaction for writes and select TFT
- ***************************************************************************************/
- inline void TFT_eSPI::begin_tft_write(void){
- #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
- if (locked) {
- locked = false; // Flag to show SPI access now unlocked
- spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); // RP2040 SDK -> 68us delay!
- CS_L;
- SET_BUS_WRITE_MODE; // Some processors (e.g. ESP32) allow recycling the tx buffer when rx is not used
- }
- #else
- CS_L;
- SET_BUS_WRITE_MODE;
- #endif
- }
- /***************************************************************************************
- ** Function name: end_tft_write (was called spi_end)
- ** Description: End transaction for write and deselect TFT
- ***************************************************************************************/
- inline void TFT_eSPI::end_tft_write(void){
- #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
- if(!inTransaction) { // Flag to stop ending tranaction during multiple graphics calls
- if (!locked) { // Locked when beginTransaction has been called
- locked = true; // Flag to show SPI access now locked
- SPI_BUSY_CHECK; // Check send complete and clean out unused rx data
- CS_H;
- spi.endTransaction(); // RP2040 SDK -> 0.7us delay
- }
- SET_BUS_READ_MODE; // In case SPI has been configured for tx only
- }
- #else
- if(!inTransaction) {SPI_BUSY_CHECK; CS_H; SET_BUS_READ_MODE;}
- #endif
- }
- /***************************************************************************************
- ** Function name: begin_tft_read (was called spi_begin_read)
- ** Description: Start transaction for reads and select TFT
- ***************************************************************************************/
- // Reads require a lower SPI clock rate than writes
- inline void TFT_eSPI::begin_tft_read(void){
- DMA_BUSY_CHECK; // Wait for any DMA transfer to complete before changing SPI settings
- #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
- if (locked) {
- locked = false;
- spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
- CS_L;
- }
- #else
- #if !defined(TFT_PARALLEL_8_BIT)
- spi.setFrequency(SPI_READ_FREQUENCY);
- #endif
- CS_L;
- #endif
- SET_BUS_READ_MODE;
- }
- /***************************************************************************************
- ** Function name: setViewport
- ** Description: Set the clipping region for the TFT screen
- ***************************************************************************************/
- void TFT_eSPI::setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum)
- {
- // Viewport metrics (not clipped)
- _xDatum = x; // Datum x position in screen coordinates
- _yDatum = y; // Datum y position in screen coordinates
- _xWidth = w; // Viewport width
- _yHeight = h; // Viewport height
- // Full size default viewport
- _vpDatum = false; // Datum is at top left corner of screen (true = top left of viewport)
- _vpOoB = false; // Out of Bounds flag (true is all of viewport is off screen)
- _vpX = 0; // Viewport top left corner x coordinate
- _vpY = 0; // Viewport top left corner y coordinate
- _vpW = width(); // Equivalent of TFT width (Nb: viewport right edge coord + 1)
- _vpH = height(); // Equivalent of TFT height (Nb: viewport bottom edge coord + 1)
- // Clip viewport to screen area
- if (x<0) { w += x; x = 0; }
- if (y<0) { h += y; y = 0; }
- if ((x + w) > width() ) { w = width() - x; }
- if ((y + h) > height() ) { h = height() - y; }
- //Serial.print(" x=");Serial.print( x);Serial.print(", y=");Serial.print( y);
- //Serial.print(", w=");Serial.print(w);Serial.print(", h=");Serial.println(h);
- // Check if viewport is entirely out of bounds
- if (w < 1 || h < 1)
- {
- // Set default values and Out of Bounds flag in case of error
- _xDatum = 0;
- _yDatum = 0;
- _xWidth = width();
- _yHeight = height();
- _vpOoB = true; // Set Out of Bounds flag to inhibit all drawing
- return;
- }
- if (!vpDatum)
- {
- _xDatum = 0; // Reset to top left of screen if not using a viewport datum
- _yDatum = 0;
- _xWidth = width();
- _yHeight = height();
- }
- // Store the clipped screen viewport metrics and datum position
- _vpX = x;
- _vpY = y;
- _vpW = x + w;
- _vpH = y + h;
- _vpDatum = vpDatum;
- //Serial.print(" _xDatum=");Serial.print( _xDatum);Serial.print(", _yDatum=");Serial.print( _yDatum);
- //Serial.print(", _xWidth=");Serial.print(_xWidth);Serial.print(", _yHeight=");Serial.println(_yHeight);
- //Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
- //Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
- }
- /***************************************************************************************
- ** Function name: checkViewport
- ** Description: Check if any part of specified area is visible in viewport
- ***************************************************************************************/
- // Note: Setting w and h to 1 will check if coordinate x,y is in area
- bool TFT_eSPI::checkViewport(int32_t x, int32_t y, int32_t w, int32_t h)
- {
- if (_vpOoB) return false;
- x+= _xDatum;
- y+= _yDatum;
- if ((x >= _vpW) || (y >= _vpH)) return false;
- int32_t dx = 0;
- int32_t dy = 0;
- int32_t dw = w;
- int32_t dh = h;
- if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
- if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
- if ((x + dw) > _vpW ) dw = _vpW - x;
- if ((y + dh) > _vpH ) dh = _vpH - y;
- if (dw < 1 || dh < 1) return false;
- return true;
- }
- /***************************************************************************************
- ** Function name: resetViewport
- ** Description: Reset viewport to whle TFT screen, datum at 0,0
- ***************************************************************************************/
- void TFT_eSPI::resetViewport(void)
- {
- // Reset viewport to the whole screen (or sprite) area
- _vpDatum = false;
- _vpOoB = false;
- _xDatum = 0;
- _yDatum = 0;
- _vpX = 0;
- _vpY = 0;
- _vpW = width();
- _vpH = height();
- _xWidth = width();
- _yHeight = height();
- }
- /***************************************************************************************
- ** Function name: getViewportX
- ** Description: Get x position of the viewport datum
- ***************************************************************************************/
- int32_t TFT_eSPI::getViewportX(void)
- {
- return _xDatum;
- }
- /***************************************************************************************
- ** Function name: getViewportY
- ** Description: Get y position of the viewport datum
- ***************************************************************************************/
- int32_t TFT_eSPI::getViewportY(void)
- {
- return _yDatum;
- }
- /***************************************************************************************
- ** Function name: getViewportWidth
- ** Description: Get width of the viewport
- ***************************************************************************************/
- int32_t TFT_eSPI::getViewportWidth(void)
- {
- return _xWidth;
- }
- /***************************************************************************************
- ** Function name: getViewportHeight
- ** Description: Get height of the viewport
- ***************************************************************************************/
- int32_t TFT_eSPI::getViewportHeight(void)
- {
- return _yHeight;
- }
- /***************************************************************************************
- ** Function name: getViewportDatum
- ** Description: Get datum flag of the viewport (true = viewport corner)
- ***************************************************************************************/
- bool TFT_eSPI::getViewportDatum(void)
- {
- return _vpDatum;
- }
- /***************************************************************************************
- ** Function name: frameViewport
- ** Description: Draw a frame inside or outside the viewport of width w
- ***************************************************************************************/
- void TFT_eSPI::frameViewport(uint16_t color, int32_t w)
- {
- // Save datum position
- bool _dT = _vpDatum;
- // If w is positive the frame is drawn inside the viewport
- // a large positive width will clear the screen inside the viewport
- if (w>0)
- {
- // Set vpDatum true to simplify coordinate derivation
- _vpDatum = true;
- fillRect(0, 0, _vpW - _vpX, w, color); // Top
- fillRect(0, w, w, _vpH - _vpY - w - w, color); // Left
- fillRect(_xWidth - w, w, w, _yHeight - w - w, color); // Right
- fillRect(0, _yHeight - w, _xWidth, w, color); // Bottom
- }
- else
- // If w is negative the frame is drawn outside the viewport
- // a large negative width will clear the screen outside the viewport
- {
- w = -w;
-
- // Save old values
- int32_t _xT = _vpX; _vpX = 0;
- int32_t _yT = _vpY; _vpY = 0;
- int32_t _wT = _vpW;
- int32_t _hT = _vpH;
- // Set vpDatum false so frame can be drawn outside window
- _vpDatum = false; // When false the full width and height is accessed
- _vpH = height();
- _vpW = width();
- // Draw frame
- fillRect(_xT - w - _xDatum, _yT - w - _yDatum, _wT - _xT + w + w, w, color); // Top
- fillRect(_xT - w - _xDatum, _yT - _yDatum, w, _hT - _yT, color); // Left
- fillRect(_wT - _xDatum, _yT - _yDatum, w, _hT - _yT, color); // Right
- fillRect(_xT - w - _xDatum, _hT - _yDatum, _wT - _xT + w + w, w, color); // Bottom
- // Restore old values
- _vpX = _xT;
- _vpY = _yT;
- _vpW = _wT;
- _vpH = _hT;
- }
- // Restore vpDatum
- _vpDatum = _dT;
- }
- /***************************************************************************************
- ** Function name: end_tft_read (was called spi_end_read)
- ** Description: End transaction for reads and deselect TFT
- ***************************************************************************************/
- inline void TFT_eSPI::end_tft_read(void){
- #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
- if(!inTransaction) {
- if (!locked) {
- locked = true;
- CS_H;
- spi.endTransaction();
- }
- }
- #else
- #if !defined(TFT_PARALLEL_8_BIT)
- spi.setFrequency(SPI_FREQUENCY);
- #endif
- if(!inTransaction) {CS_H;}
- #endif
- SET_BUS_WRITE_MODE;
- // The ST7796 appears to need a 4ms delay after a CGRAM read, otherwise subsequent writes will fail!
- #ifdef ST7796_DRIVER
- delay(4);
- #endif
- }
- /***************************************************************************************
- ** Function name: Legacy - deprecated
- ** Description: Start/end transaction
- ***************************************************************************************/
- void TFT_eSPI::spi_begin() {begin_tft_write();}
- void TFT_eSPI::spi_end() { end_tft_write();}
- void TFT_eSPI::spi_begin_read() {begin_tft_read(); }
- void TFT_eSPI::spi_end_read() { end_tft_read(); }
- /***************************************************************************************
- ** Function name: TFT_eSPI
- ** Description: Constructor , we must use hardware SPI pins
- ***************************************************************************************/
- TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
- {
- // The control pins are deliberately set to the inactive state (CS high) as setup()
- // might call and initialise other SPI peripherals which would could cause conflicts
- // if CS is floating or undefined.
- #ifdef TFT_CS
- pinMode(TFT_CS, OUTPUT);
- digitalWrite(TFT_CS, HIGH); // Chip select high (inactive)
- #endif
- // Configure chip select for touchscreen controller if present
- #ifdef TOUCH_CS
- pinMode(TOUCH_CS, OUTPUT);
- digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
- #endif
- #ifdef TFT_WR
- pinMode(TFT_WR, OUTPUT);
- digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive)
- #endif
- #ifdef TFT_DC
- pinMode(TFT_DC, OUTPUT);
- digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode
- #endif
- #ifdef TFT_RST
- if (TFT_RST >= 0) {
- pinMode(TFT_RST, OUTPUT);
- digitalWrite(TFT_RST, HIGH); // Set high, do not share pin with another SPI device
- }
- #endif
- #if defined (TFT_PARALLEL_8_BIT)
- // Make sure read is high before we set the bus to output
- pinMode(TFT_RD, OUTPUT);
- digitalWrite(TFT_RD, HIGH);
- // Set TFT data bus lines to output
- pinMode(TFT_D0, OUTPUT); digitalWrite(TFT_D0, HIGH);
- pinMode(TFT_D1, OUTPUT); digitalWrite(TFT_D1, HIGH);
- pinMode(TFT_D2, OUTPUT); digitalWrite(TFT_D2, HIGH);
- pinMode(TFT_D3, OUTPUT); digitalWrite(TFT_D3, HIGH);
- pinMode(TFT_D4, OUTPUT); digitalWrite(TFT_D4, HIGH);
- pinMode(TFT_D5, OUTPUT); digitalWrite(TFT_D5, HIGH);
- pinMode(TFT_D6, OUTPUT); digitalWrite(TFT_D6, HIGH);
- pinMode(TFT_D7, OUTPUT); digitalWrite(TFT_D7, HIGH);
- CONSTRUCTOR_INIT_TFT_DATA_BUS;
- #endif
- _init_width = _width = w; // Set by specific xxxxx_Defines.h file or by users sketch
- _init_height = _height = h; // Set by specific xxxxx_Defines.h file or by users sketch
- // Reset the viewport to the whole screen
- resetViewport();
- rotation = 0;
- cursor_y = cursor_x = 0;
- textfont = 1;
- textsize = 1;
- textcolor = bitmap_fg = 0xFFFF; // White
- textbgcolor = bitmap_bg = 0x0000; // Black
- padX = 0; // No padding
- isDigits = false; // No bounding box adjustment
- textwrapX = true; // Wrap text at end of line when using print stream
- textwrapY = false; // Wrap text at bottom of screen when using print stream
- textdatum = TL_DATUM; // Top Left text alignment is default
- fontsloaded = 0;
- _swapBytes = false; // Do not swap colour bytes by default
- locked = true; // Transaction mutex lock flag to ensure begin/endTranaction pairing
- inTransaction = false; // Flag to prevent multiple sequential functions to keep bus access open
- lockTransaction = false; // start/endWrite lock flag to allow sketch to keep SPI bus access open
- _booted = true; // Default attributes
- _cp437 = true; // Legacy GLCD font bug fix
- _utf8 = true; // UTF8 decoding enabled
- #ifdef FONT_FS_AVAILABLE
- fs_font = true; // Smooth font filing system or array (fs_font = false) flag
- #endif
- #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT)
- if (psramFound()) _psram_enable = true; // Enable the use of PSRAM (if available)
- else
- #endif
- _psram_enable = false;
- addr_row = 0xFFFF; // drawPixel command length optimiser
- addr_col = 0xFFFF; // drawPixel command length optimiser
- _xPivot = 0;
- _yPivot = 0;
- // Legacy support for bit GPIO masks
- cspinmask = 0;
- dcpinmask = 0;
- wrpinmask = 0;
- sclkpinmask = 0;
- // Flags for which fonts are loaded
- #ifdef LOAD_GLCD
- fontsloaded = 0x0002; // Bit 1 set
- #endif
- #ifdef LOAD_FONT2
- fontsloaded |= 0x0004; // Bit 2 set
- #endif
- #ifdef LOAD_FONT4
- fontsloaded |= 0x0010; // Bit 4 set
- #endif
- #ifdef LOAD_FONT6
- fontsloaded |= 0x0040; // Bit 6 set
- #endif
- #ifdef LOAD_FONT7
- fontsloaded |= 0x0080; // Bit 7 set
- #endif
- #ifdef LOAD_FONT8
- fontsloaded |= 0x0100; // Bit 8 set
- #endif
- #ifdef LOAD_FONT8N
- fontsloaded |= 0x0200; // Bit 9 set
- #endif
- #ifdef SMOOTH_FONT
- fontsloaded |= 0x8000; // Bit 15 set
- #endif
- }
- /***************************************************************************************
- ** Function name: begin
- ** Description: Included for backwards compatibility
- ***************************************************************************************/
- void TFT_eSPI::begin(uint8_t tc)
- {
- init(tc);
- }
- /***************************************************************************************
- ** Function name: init (tc is tab colour for ST7735 displays only)
- ** Description: Reset, then initialise the TFT display registers
- ***************************************************************************************/
- void TFT_eSPI::init(uint8_t tc)
- {
- if (_booted)
- {
- #if !defined (ESP32) && !defined(TFT_PARALLEL_8_BIT) && !defined(ARDUINO_ARCH_RP2040)
- // Legacy bitmasks for GPIO
- #if defined (TFT_CS) && (TFT_CS >= 0)
- cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS);
- #endif
- #if defined (TFT_DC) && (TFT_DC >= 0)
- dcpinmask = (uint32_t) digitalPinToBitMask(TFT_DC);
- #endif
- #if defined (TFT_WR) && (TFT_WR >= 0)
- wrpinmask = (uint32_t) digitalPinToBitMask(TFT_WR);
- #endif
- #if defined (TFT_SCLK) && (TFT_SCLK >= 0)
- sclkpinmask = (uint32_t) digitalPinToBitMask(TFT_SCLK);
- #endif
- #if defined (TFT_SPI_OVERLAP) && defined (ESP8266)
- // #pragma GCC diagnostic ignored "TFT_SPI_OVERLAP defined"
- // #pragma GCC diagnostic warning "TFT_SPI_OVERLAP defined"
- // Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS
- // pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss);
- spi.pins( 6, 7, 8, 0);
- //spi.pins(10, 13, 14, 9);
- #endif
- spi.begin(); // This will set HMISO to input
- #else
- #if !defined(TFT_PARALLEL_8_BIT)
- #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040)
- spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
- #else
- spi.begin();
- #endif
- #endif
- #endif
- lockTransaction = false;
- inTransaction = false;
- locked = true;
- INIT_TFT_DATA_BUS;
- #ifdef TFT_CS
- // Set to output once again in case ESP8266 D6 (MISO) is used for CS
- pinMode(TFT_CS, OUTPUT);
- digitalWrite(TFT_CS, HIGH); // Chip select high (inactive)
- #elif defined (ESP8266) && !defined (TFT_PARALLEL_8_BIT)
- spi.setHwCs(1); // Use hardware SS toggling
- #endif
- // Set to output once again in case ESP8266 D6 (MISO) is used for DC
- #ifdef TFT_DC
- pinMode(TFT_DC, OUTPUT);
- digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode
- #endif
- _booted = false;
- end_tft_write();
- } // end of: if just _booted
- // Toggle RST low to reset
- #ifdef TFT_RST
- if (TFT_RST >= 0) {
- digitalWrite(TFT_RST, HIGH);
- delay(5);
- digitalWrite(TFT_RST, LOW);
- delay(20);
- digitalWrite(TFT_RST, HIGH);
- }
- else writecommand(TFT_SWRST); // Software reset
- #else
- writecommand(TFT_SWRST); // Software reset
- #endif
- delay(150); // Wait for reset to complete
- begin_tft_write();
- tc = tc; // Supress warning
- // This loads the driver specific initialisation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<<
- #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER)
- #include "TFT_Drivers/ILI9341_Init.h"
- #elif defined (ST7735_DRIVER)
- tabcolor = tc;
- #include "TFT_Drivers/ST7735_Init.h"
- #elif defined (ILI9163_DRIVER)
- #include "TFT_Drivers/ILI9163_Init.h"
- #elif defined (S6D02A1_DRIVER)
- #include "TFT_Drivers/S6D02A1_Init.h"
- #elif defined (ST7796_DRIVER)
- #include "TFT_Drivers/ST7796_Init.h"
- #elif defined (ILI9486_DRIVER)
- #include "TFT_Drivers/ILI9486_Init.h"
- #elif defined (ILI9481_DRIVER)
- #include "TFT_Drivers/ILI9481_Init.h"
- #elif defined (ILI9488_DRIVER)
- #include "TFT_Drivers/ILI9488_Init.h"
- #elif defined (HX8357D_DRIVER)
- #include "TFT_Drivers/HX8357D_Init.h"
- #elif defined (ST7789_DRIVER)
- #include "TFT_Drivers/ST7789_Init.h"
- #elif defined (R61581_DRIVER)
- #include "TFT_Drivers/R61581_Init.h"
- #elif defined (RM68140_DRIVER)
- #include "TFT_Drivers/RM68140_Init.h"
- #elif defined (ST7789_2_DRIVER)
- #include "TFT_Drivers/ST7789_2_Init.h"
- #elif defined (SSD1351_DRIVER)
- #include "TFT_Drivers/SSD1351_Init.h"
- #elif defined (SSD1963_DRIVER)
- #include "TFT_Drivers/SSD1963_Init.h"
- #elif defined (GC9A01_DRIVER)
- #include "TFT_Drivers/GC9A01_Init.h"
- #elif defined (ILI9225_DRIVER)
- #include "TFT_Drivers/ILI9225_Init.h"
- #endif
- #ifdef TFT_INVERSION_ON
- writecommand(TFT_INVON);
- #endif
- #ifdef TFT_INVERSION_OFF
- writecommand(TFT_INVOFF);
- #endif
- end_tft_write();
- setRotation(rotation);
- #if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON)
- pinMode(TFT_BL, OUTPUT);
- digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
- #else
- #if defined (TFT_BL) && defined (M5STACK)
- // Turn on the back-light LED
- pinMode(TFT_BL, OUTPUT);
- digitalWrite(TFT_BL, HIGH);
- #endif
- #endif
- }
- /***************************************************************************************
- ** Function name: setRotation
- ** Description: rotate the screen orientation m = 0-3 or 4-7 for BMP drawing
- ***************************************************************************************/
- void TFT_eSPI::setRotation(uint8_t m)
- {
- begin_tft_write();
- // This loads the driver specific rotation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<<
- #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER)
- #include "TFT_Drivers/ILI9341_Rotation.h"
- #elif defined (ST7735_DRIVER)
- #include "TFT_Drivers/ST7735_Rotation.h"
- #elif defined (ILI9163_DRIVER)
- #include "TFT_Drivers/ILI9163_Rotation.h"
- #elif defined (S6D02A1_DRIVER)
- #include "TFT_Drivers/S6D02A1_Rotation.h"
- #elif defined (ST7796_DRIVER)
- #include "TFT_Drivers/ST7796_Rotation.h"
- #elif defined (ILI9486_DRIVER)
- #include "TFT_Drivers/ILI9486_Rotation.h"
- #elif defined (ILI9481_DRIVER)
- #include "TFT_Drivers/ILI9481_Rotation.h"
- #elif defined (ILI9488_DRIVER)
- #include "TFT_Drivers/ILI9488_Rotation.h"
- #elif defined (HX8357D_DRIVER)
- #include "TFT_Drivers/HX8357D_Rotation.h"
- #elif defined (ST7789_DRIVER)
- #include "TFT_Drivers/ST7789_Rotation.h"
- #elif defined (R61581_DRIVER)
- #include "TFT_Drivers/R61581_Rotation.h"
- #elif defined (RM68140_DRIVER)
- #include "TFT_Drivers/RM68140_Rotation.h"
- #elif defined (ST7789_2_DRIVER)
- #include "TFT_Drivers/ST7789_2_Rotation.h"
- #elif defined (SSD1351_DRIVER)
- #include "TFT_Drivers/SSD1351_Rotation.h"
- #elif defined (SSD1963_DRIVER)
- #include "TFT_Drivers/SSD1963_Rotation.h"
- #elif defined (GC9A01_DRIVER)
- #include "TFT_Drivers/GC9A01_Rotation.h"
- #elif defined (ILI9225_DRIVER)
- #include "TFT_Drivers/ILI9225_Rotation.h"
- #endif
- delayMicroseconds(10);
- end_tft_write();
- addr_row = 0xFFFF;
- addr_col = 0xFFFF;
- // Reset the viewport to the whole screen
- resetViewport();
- }
- /***************************************************************************************
- ** Function name: commandList, used for FLASH based lists only (e.g. ST7735)
- ** Description: Get initialisation commands from FLASH and send to TFT
- ***************************************************************************************/
- void TFT_eSPI::commandList (const uint8_t *addr)
- {
- uint8_t numCommands;
- uint8_t numArgs;
- uint8_t ms;
- numCommands = pgm_read_byte(addr++); // Number of commands to follow
- while (numCommands--) // For each command...
- {
- writecommand(pgm_read_byte(addr++)); // Read, issue command
- numArgs = pgm_read_byte(addr++); // Number of args to follow
- ms = numArgs & TFT_INIT_DELAY; // If hibit set, delay follows args
- numArgs &= ~TFT_INIT_DELAY; // Mask out delay bit
- while (numArgs--) // For each argument...
- {
- writedata(pgm_read_byte(addr++)); // Read, issue argument
- }
- if (ms)
- {
- ms = pgm_read_byte(addr++); // Read post-command delay time (ms)
- delay( (ms==255 ? 500 : ms) );
- }
- }
- }
- /***************************************************************************************
- ** Function name: spiwrite
- ** Description: Write 8 bits to SPI port (legacy support only)
- ***************************************************************************************/
- void TFT_eSPI::spiwrite(uint8_t c)
- {
- begin_tft_write();
- tft_Write_8(c);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: writecommand
- ** Description: Send an 8 bit command to the TFT
- ***************************************************************************************/
- void TFT_eSPI::writecommand(uint8_t c)
- {
- begin_tft_write();
- DC_C;
- tft_Write_8(c);
- DC_D;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: writedata
- ** Description: Send a 8 bit data value to the TFT
- ***************************************************************************************/
- void TFT_eSPI::writedata(uint8_t d)
- {
- begin_tft_write();
- DC_D; // Play safe, but should already be in data mode
- tft_Write_8(d);
- CS_L; // Allow more hold time for low VDI rail
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: readcommand8
- ** Description: Read a 8 bit data value from an indexed command register
- ***************************************************************************************/
- uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index)
- {
- uint8_t reg = 0;
- #ifdef TFT_PARALLEL_8_BIT
- writecommand(cmd_function); // Sets DC and CS high
- busDir(dir_mask, INPUT);
- CS_L;
- // Read nth parameter (assumes caller discards 1st parameter or points index to 2nd)
- while(index--) reg = readByte();
- busDir(dir_mask, OUTPUT);
- CS_H;
- #else // SPI interface
- // Tested with ILI9341 set to Interface II i.e. IM [3:0] = "1101"
- begin_tft_read();
- index = 0x10 + (index & 0x0F);
- DC_C; tft_Write_8(0xD9);
- DC_D; tft_Write_8(index);
- CS_H; // Some displays seem to need CS to be pulsed here, or is just a delay needed?
- CS_L;
- DC_C; tft_Write_8(cmd_function);
- DC_D;
- reg = tft_Read_8();
- end_tft_read();
- #endif
- return reg;
- }
- /***************************************************************************************
- ** Function name: readcommand16
- ** Description: Read a 16 bit data value from an indexed command register
- ***************************************************************************************/
- uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index)
- {
- uint32_t reg;
- reg = (readcommand8(cmd_function, index + 0) << 8);
- reg |= (readcommand8(cmd_function, index + 1) << 0);
- return reg;
- }
- /***************************************************************************************
- ** Function name: readcommand32
- ** Description: Read a 32 bit data value from an indexed command register
- ***************************************************************************************/
- uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index)
- {
- uint32_t reg;
- reg = ((uint32_t)readcommand8(cmd_function, index + 0) << 24);
- reg |= ((uint32_t)readcommand8(cmd_function, index + 1) << 16);
- reg |= ((uint32_t)readcommand8(cmd_function, index + 2) << 8);
- reg |= ((uint32_t)readcommand8(cmd_function, index + 3) << 0);
- return reg;
- }
- /***************************************************************************************
- ** Function name: read pixel (for SPI Interface II i.e. IM [3:0] = "1101")
- ** Description: Read 565 pixel colours from a pixel
- ***************************************************************************************/
- uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
- {
- if (_vpOoB) return 0;
- x0+= _xDatum;
- y0+= _yDatum;
- // Range checking
- if ((x0 < _vpX) || (y0 < _vpY) ||(x0 >= _vpW) || (y0 >= _vpH)) return 0;
- #if defined(TFT_PARALLEL_8_BIT)
- CS_L;
- readAddrWindow(x0, y0, 1, 1);
- // Set masked pins D0- D7 to input
- busDir(dir_mask, INPUT);
- #if !defined (SSD1963_DRIVER)
- // Dummy read to throw away don't care value
- readByte();
- #endif
- // Fetch the 16 bit BRG pixel
- //uint16_t rgb = (readByte() << 8) | readByte();
- #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9488_DRIVER) || defined (SSD1963_DRIVER)// Read 3 bytes
- // Read window pixel 24 bit RGB values and fill in LS bits
- uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3);
- CS_H;
- // Set masked pins D0- D7 to output
- busDir(dir_mask, OUTPUT);
- return rgb;
- #else // ILI9481 or ILI9486 16 bit read
- // Fetch the 16 bit BRG pixel
- uint16_t bgr = (readByte() << 8) | readByte();
- CS_H;
- // Set masked pins D0- D7 to output
- busDir(dir_mask, OUTPUT);
- #ifdef ILI9486_DRIVER
- return bgr;
- #else
- // Swap Red and Blue (could check MADCTL setting to see if this is needed)
- return (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
- #endif
- #endif
- #else // Not TFT_PARALLEL_8_BIT
- // This function can get called during antialiased font rendering
- // so a transaction may be in progress
- bool wasInTransaction = inTransaction;
- if (inTransaction) { inTransaction= false; end_tft_write();}
- uint16_t color = 0;
- begin_tft_read();
- readAddrWindow(x0, y0, 1, 1); // Sets CS low
- #ifdef TFT_SDA_READ
- begin_SDA_Read();
- #endif
- // Dummy read to throw away don't care value
- tft_Read_8();
- //#if !defined (ILI9488_DRIVER)
- #if defined (ST7796_DRIVER)
- // Read the 2 bytes
- color = ((tft_Read_8()) << 8) | (tft_Read_8());
- #else
- // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
- // as the TFT stores colours as 18 bits
- uint8_t r = tft_Read_8();
- uint8_t g = tft_Read_8();
- uint8_t b = tft_Read_8();
- color = color565(r, g, b);
- #endif
- /*
- #else
- // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse
- // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left
- uint8_t r = (tft_Read_8()&0x7E)<<1;
- uint8_t g = (tft_Read_8()&0x7E)<<1;
- uint8_t b = (tft_Read_8()&0x7E)<<1;
- color = color565(r, g, b);
- #endif
- */
- CS_H;
- #ifdef TFT_SDA_READ
- end_SDA_Read();
- #endif
- end_tft_read();
- // Reinstate the transaction if one was in progress
- if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
- return color;
- #endif
- }
- void TFT_eSPI::setCallback(getColorCallback getCol)
- {
- getColor = getCol;
- }
- /***************************************************************************************
- ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
- ** Description: Read 565 pixel colours from a defined area
- ***************************************************************************************/
- void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
- {
- PI_CLIP ;
- #if defined(TFT_PARALLEL_8_BIT)
- CS_L;
- readAddrWindow(x, y, dw, dh);
- data += dx + dy * w;
- // Set masked pins D0- D7 to input
- busDir(dir_mask, INPUT);
- #if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9488_DRIVER) // Read 3 bytes
- // Dummy read to throw away don't care value
- readByte();
- // Fetch the 24 bit RGB value
- while (dh--) {
- int32_t lw = dw;
- uint16_t* line = data;
- while (lw--) {
- // Assemble the RGB 16 bit colour
- uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3);
- // Swapped byte order for compatibility with pushRect()
- *line++ = (rgb<<8) | (rgb>>8);
- }
- data += w;
- }
- #elif defined (SSD1963_DRIVER)
- // Fetch the 18 bit BRG pixels
- while (dh--) {
- int32_t lw = dw;
- uint16_t* line = data;
- while (lw--) {
- uint16_t bgr = ((readByte() & 0xF8) >> 3);; // CS_L adds a small delay
- bgr |= ((readByte() & 0xFC) << 3);
- bgr |= (readByte() << 8);
- // Swap Red and Blue (could check MADCTL setting to see if this is needed)
- uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
- // Swapped byte order for compatibility with pushRect()
- *line++ = (rgb<<8) | (rgb>>8);
- }
- data += w;
- }
- #else // ILI9481 reads as 16 bits
- // Dummy read to throw away don't care value
- readByte();
- // Fetch the 16 bit BRG pixels
- while (dh--) {
- int32_t lw = dw;
- uint16_t* line = data;
- while (lw--) {
- #ifdef ILI9486_DRIVER
- // Read the RGB 16 bit colour
- *line++ = readByte() | (readByte() << 8);
- #else
- // Read the BRG 16 bit colour
- uint16_t bgr = (readByte() << 8) | readByte();
- // Swap Red and Blue (could check MADCTL setting to see if this is needed)
- uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
- // Swapped byte order for compatibility with pushRect()
- *line++ = (rgb<<8) | (rgb>>8);
- #endif
- }
- data += w;
- }
- #endif
- CS_H;
- // Set masked pins D0- D7 to output
- busDir(dir_mask, OUTPUT);
- #else // SPI interface
- // This function can get called after a begin_tft_write
- // so a transaction may be in progress
- bool wasInTransaction = inTransaction;
- if (inTransaction) { inTransaction= false; end_tft_write();}
- uint16_t color = 0;
- begin_tft_read();
- readAddrWindow(x, y, dw, dh);
- data += dx + dy * w;
- #ifdef TFT_SDA_READ
- begin_SDA_Read();
- #endif
- // Dummy read to throw away don't care value
- tft_Read_8();
- // Read window pixel 24 bit RGB values
- while (dh--) {
- int32_t lw = dw;
- uint16_t* line = data;
- while (lw--) {
- #if !defined (ILI9488_DRIVER)
- #if defined (ST7796_DRIVER)
- // Read the 2 bytes
- color = ((tft_Read_8()) << 8) | (tft_Read_8());
- #else
- // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
- // as the TFT stores colours as 18 bits
- uint8_t r = tft_Read_8();
- uint8_t g = tft_Read_8();
- uint8_t b = tft_Read_8();
- color = color565(r, g, b);
- #endif
- #else
- // The 6 colour bits are in MS 6 bits of each byte but we do not include the extra clock pulse
- // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left
- uint8_t r = (tft_Read_8()&0x7E)<<1;
- uint8_t g = (tft_Read_8()&0x7E)<<1;
- uint8_t b = (tft_Read_8()&0x7E)<<1;
- color = color565(r, g, b);
- #endif
- // Swapped colour byte order for compatibility with pushRect()
- *line++ = color << 8 | color >> 8;
- }
- data += w;
- }
- //CS_H;
- #ifdef TFT_SDA_READ
- end_SDA_Read();
- #endif
- end_tft_read();
- // Reinstate the transaction if one was in progress
- if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
- #endif
- }
- /***************************************************************************************
- ** Function name: push rectangle
- ** Description: push 565 pixel colours into a defined area
- ***************************************************************************************/
- void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
- {
- bool swap = _swapBytes; _swapBytes = false;
- pushImage(x, y, w, h, data);
- _swapBytes = swap;
- }
- /***************************************************************************************
- ** Function name: pushImage
- ** Description: plot 16 bit colour sprite or image onto TFT
- ***************************************************************************************/
- void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
- {
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- setWindow(x, y, x + dw - 1, y + dh - 1);
- data += dx + dy * w;
- // Check if whole image can be pushed
- if (dw == w) pushPixels(data, dw * dh);
- else {
- // Push line segments to crop image
- while (dh--)
- {
- pushPixels(data, dw);
- data += w;
- }
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushImage
- ** Description: plot 16 bit sprite or image with 1 colour being transparent
- ***************************************************************************************/
- void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp)
- {
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- data += dx + dy * w;
- int32_t xe = x + dw - 1, ye = y + dh - 1;
- uint16_t lineBuf[dw]; // Use buffer to minimise setWindow call count
- // The little endian transp color must be byte swapped if the image is big endian
- if (!_swapBytes) transp = transp >> 8 | transp << 8;
- while (dh--)
- {
- int32_t len = dw;
- uint16_t* ptr = data;
- int32_t px = x;
- bool move = true;
- uint16_t np = 0;
- while (len--)
- {
- if (transp != *ptr)
- {
- if (move) { move = false; setWindow(px, y, xe, ye); }
- lineBuf[np] = *ptr;
- np++;
- }
- else
- {
- move = true;
- if (np)
- {
- pushPixels((uint16_t*)lineBuf, np);
- np = 0;
- }
- }
- px++;
- ptr++;
- }
- if (np) pushPixels((uint16_t*)lineBuf, np);
- y++;
- data += w;
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushImage - for FLASH (PROGMEM) stored images
- ** Description: plot 16 bit image
- ***************************************************************************************/
- void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data)
- {
- // Requires 32 bit aligned access, so use PROGMEM 16 bit word functions
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- data += dx + dy * w;
- uint16_t buffer[dw];
- setWindow(x, y, x + dw - 1, y + dh - 1);
- // Fill and send line buffers to TFT
- for (int32_t i = 0; i < dh; i++) {
- for (int32_t j = 0; j < dw; j++) {
- buffer[j] = pgm_read_word(&data[i * w + j]);
- }
- pushPixels(buffer, dw);
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushImage - for FLASH (PROGMEM) stored images
- ** Description: plot 16 bit image with 1 colour being transparent
- ***************************************************************************************/
- void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp)
- {
- // Requires 32 bit aligned access, so use PROGMEM 16 bit word functions
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- data += dx + dy * w;
- int32_t xe = x + dw - 1, ye = y + dh - 1;
- uint16_t lineBuf[dw];
- // The little endian transp color must be byte swapped if the image is big endian
- if (!_swapBytes) transp = transp >> 8 | transp << 8;
- while (dh--) {
- int32_t len = dw;
- uint16_t* ptr = (uint16_t*)data;
- int32_t px = x;
- bool move = true;
- uint16_t np = 0;
- while (len--) {
- uint16_t color = pgm_read_word(ptr);
- if (transp != color) {
- if (move) { move = false; setWindow(px, y, xe, ye); }
- lineBuf[np] = color;
- np++;
- }
- else {
- move = true;
- if (np) {
- pushPixels(lineBuf, np);
- np = 0;
- }
- }
- px++;
- ptr++;
- }
- if (np) pushPixels(lineBuf, np);
- y++;
- data += w;
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushImage
- ** Description: plot 8 bit or 4 bit or 1 bit image or sprite using a line buffer
- ***************************************************************************************/
- 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)
- {
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- bool swap = _swapBytes;
- setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
- // Line buffer makes plotting faster
- uint16_t lineBuf[dw];
- if (bpp8)
- {
- _swapBytes = false;
- uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
- _lastColor = -1; // Set to illegal value
- // Used to store last shifted colour
- uint8_t msbColor = 0;
- uint8_t lsbColor = 0;
- data += dx + dy * w;
- while (dh--) {
- uint32_t len = dw;
- uint8_t* ptr = (uint8_t*)data;
- uint8_t* linePtr = (uint8_t*)lineBuf;
- while(len--) {
- uint32_t color = pgm_read_byte(ptr++);
- // Shifts are slow so check if colour has changed first
- if (color != _lastColor) {
- // =====Green===== ===============Red==============
- msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0);
- // =====Green===== =======Blue======
- lsbColor = (color & 0x1C)<<3 | blue[color & 0x03];
- _lastColor = color;
- }
- *linePtr++ = msbColor;
- *linePtr++ = lsbColor;
- }
- pushPixels(lineBuf, dw);
- data += w;
- }
- _swapBytes = swap; // Restore old value
- }
- else if (cmap != nullptr) // Must be 4bpp
- {
- _swapBytes = true;
- w = (w+1) & 0xFFFE; // if this is a sprite, w will already be even; this does no harm.
- bool splitFirst = (dx & 0x01) != 0; // split first means we have to push a single px from the left of the sprite / image
- if (splitFirst) {
- data += ((dx - 1 + dy * w) >> 1);
- }
- else {
- data += ((dx + dy * w) >> 1);
- }
- while (dh--) {
- uint32_t len = dw;
- uint8_t * ptr = (uint8_t*)data;
- uint16_t *linePtr = lineBuf;
- uint8_t colors; // two colors in one byte
- uint16_t index;
- if (splitFirst) {
- colors = pgm_read_byte(ptr);
- index = (colors & 0x0F);
- *linePtr++ = cmap[index];
- len--;
- ptr++;
- }
- while (len--)
- {
- colors = pgm_read_byte(ptr);
- index = ((colors & 0xF0) >> 4) & 0x0F;
- *linePtr++ = cmap[index];
- if (len--)
- {
- index = colors & 0x0F;
- *linePtr++ = cmap[index];
- } else {
- break; // nothing to do here
- }
- ptr++;
- }
- pushPixels(lineBuf, dw);
- data += (w >> 1);
- }
- _swapBytes = swap; // Restore old value
- }
- else // Must be 1bpp
- {
- _swapBytes = false;
- uint8_t * ptr = (uint8_t*)data;
- uint32_t ww = (w+7)>>3; // Width of source image line in bytes
- for (int32_t yp = dy; yp < dy + dh; yp++)
- {
- uint8_t* linePtr = (uint8_t*)lineBuf;
- for (int32_t xp = dx; xp < dx + dw; xp++)
- {
- uint16_t col = (pgm_read_byte(ptr + (xp>>3)) & (0x80 >> (xp & 0x7)) );
- if (col) {*linePtr++ = bitmap_fg>>8; *linePtr++ = (uint8_t) bitmap_fg;}
- else {*linePtr++ = bitmap_bg>>8; *linePtr++ = (uint8_t) bitmap_bg;}
- }
- ptr += ww;
- pushPixels(lineBuf, dw);
- }
- }
- _swapBytes = swap; // Restore old value
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushImage
- ** Description: plot 8 bit or 4 bit or 1 bit image or sprite using a line buffer
- ***************************************************************************************/
- void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8, uint16_t *cmap)
- {
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- bool swap = _swapBytes;
- setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
- // Line buffer makes plotting faster
- uint16_t lineBuf[dw];
- if (bpp8)
- {
- _swapBytes = false;
- uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
- _lastColor = -1; // Set to illegal value
- // Used to store last shifted colour
- uint8_t msbColor = 0;
- uint8_t lsbColor = 0;
- data += dx + dy * w;
- while (dh--) {
- uint32_t len = dw;
- uint8_t* ptr = data;
- uint8_t* linePtr = (uint8_t*)lineBuf;
- while(len--) {
- uint32_t color = *ptr++;
- // Shifts are slow so check if colour has changed first
- if (color != _lastColor) {
- // =====Green===== ===============Red==============
- msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0);
- // =====Green===== =======Blue======
- lsbColor = (color & 0x1C)<<3 | blue[color & 0x03];
- _lastColor = color;
- }
- *linePtr++ = msbColor;
- *linePtr++ = lsbColor;
- }
- pushPixels(lineBuf, dw);
- data += w;
- }
- _swapBytes = swap; // Restore old value
- }
- else if (cmap != nullptr) // Must be 4bpp
- {
- _swapBytes = true;
- w = (w+1) & 0xFFFE; // if this is a sprite, w will already be even; this does no harm.
- bool splitFirst = (dx & 0x01) != 0; // split first means we have to push a single px from the left of the sprite / image
- if (splitFirst) {
- data += ((dx - 1 + dy * w) >> 1);
- }
- else {
- data += ((dx + dy * w) >> 1);
- }
- while (dh--) {
- uint32_t len = dw;
- uint8_t * ptr = data;
- uint16_t *linePtr = lineBuf;
- uint8_t colors; // two colors in one byte
- uint16_t index;
- if (splitFirst) {
- colors = *ptr;
- index = (colors & 0x0F);
- *linePtr++ = cmap[index];
- len--;
- ptr++;
- }
- while (len--)
- {
- colors = *ptr;
- index = ((colors & 0xF0) >> 4) & 0x0F;
- *linePtr++ = cmap[index];
- if (len--)
- {
- index = colors & 0x0F;
- *linePtr++ = cmap[index];
- } else {
- break; // nothing to do here
- }
- ptr++;
- }
- pushPixels(lineBuf, dw);
- data += (w >> 1);
- }
- _swapBytes = swap; // Restore old value
- }
- else // Must be 1bpp
- {
- _swapBytes = false;
- uint32_t ww = (w+7)>>3; // Width of source image line in bytes
- for (int32_t yp = dy; yp < dy + dh; yp++)
- {
- uint8_t* linePtr = (uint8_t*)lineBuf;
- for (int32_t xp = dx; xp < dx + dw; xp++)
- {
- uint16_t col = (data[(xp>>3)] & (0x80 >> (xp & 0x7)) );
- if (col) {*linePtr++ = bitmap_fg>>8; *linePtr++ = (uint8_t) bitmap_fg;}
- else {*linePtr++ = bitmap_bg>>8; *linePtr++ = (uint8_t) bitmap_bg;}
- }
- data += ww;
- pushPixels(lineBuf, dw);
- }
- }
- _swapBytes = swap; // Restore old value
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushImage
- ** Description: plot 8 or 4 or 1 bit image or sprite with a transparent colour
- ***************************************************************************************/
- 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)
- {
- PI_CLIP;
- begin_tft_write();
- inTransaction = true;
- bool swap = _swapBytes;
- int32_t xe = x + dw - 1, ye = y + dh - 1;
- // Line buffer makes plotting faster
- uint16_t lineBuf[dw];
- if (bpp8) { // 8 bits per pixel
- _swapBytes = false;
- data += dx + dy * w;
- uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
- _lastColor = -1; // Set to illegal value
- // Used to store last shifted colour
- uint8_t msbColor = 0;
- uint8_t lsbColor = 0;
- while (dh--) {
- int32_t len = dw;
- uint8_t* ptr = data;
- uint8_t* linePtr = (uint8_t*)lineBuf;
- int32_t px = x;
- bool move = true;
- uint16_t np = 0;
- while (len--) {
- if (transp != *ptr) {
- if (move) { move = false; setWindow(px, y, xe, ye);}
- uint8_t color = *ptr;
- // Shifts are slow so check if colour has changed first
- if (color != _lastColor) {
- // =====Green===== ===============Red==============
- msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0);
- // =====Green===== =======Blue======
- lsbColor = (color & 0x1C)<<3 | blue[color & 0x03];
- _lastColor = color;
- }
- *linePtr++ = msbColor;
- *linePtr++ = lsbColor;
- np++;
- }
- else {
- move = true;
- if (np) {
- pushPixels(lineBuf, np);
- linePtr = (uint8_t*)lineBuf;
- np = 0;
- }
- }
- px++;
- ptr++;
- }
- if (np) pushPixels(lineBuf, np);
- y++;
- data += w;
- }
- }
- else if (cmap != nullptr) // 4bpp with color map
- {
- _swapBytes = true;
- w = (w+1) & 0xFFFE; // here we try to recreate iwidth from dwidth.
- bool splitFirst = ((dx & 0x01) != 0);
- if (splitFirst) {
- data += ((dx - 1 + dy * w) >> 1);
- }
- else {
- data += ((dx + dy * w) >> 1);
- }
- while (dh--) {
- uint32_t len = dw;
- uint8_t * ptr = data;
- int32_t px = x;
- bool move = true;
- uint16_t np = 0;
- uint8_t index; // index into cmap.
- if (splitFirst) {
- index = (*ptr & 0x0F); // odd = bits 3 .. 0
- if (index != transp) {
- move = false; setWindow(px, y, xe, ye);
- lineBuf[np] = cmap[index];
- np++;
- }
- px++; ptr++;
- len--;
- }
- while (len--)
- {
- uint8_t color = *ptr;
- // find the actual color you care about. There will be two pixels here!
- // but we may only want one at the end of the row
- uint16_t index = ((color & 0xF0) >> 4) & 0x0F; // high bits are the even numbers
- if (index != transp) {
- if (move) {
- move = false; setWindow(px, y, xe, ye);
- }
- lineBuf[np] = cmap[index];
- np++; // added a pixel
- }
- else {
- move = true;
- if (np) {
- pushPixels(lineBuf, np);
- np = 0;
- }
- }
- px++;
- if (len--)
- {
- index = color & 0x0F; // the odd number is 3 .. 0
- if (index != transp) {
- if (move) {
- move = false; setWindow(px, y, xe, ye);
- }
- lineBuf[np] = cmap[index];
- np++;
- }
- else {
- move = true;
- if (np) {
- pushPixels(lineBuf, np);
- np = 0;
- }
- }
- px++;
- }
- else {
- break; // we are done with this row.
- }
- ptr++; // we only increment ptr once in the loop (deliberate)
- }
- if (np) {
- pushPixels(lineBuf, np);
- np = 0;
- }
- data += (w>>1);
- y++;
- }
- }
- else { // 1 bit per pixel
- _swapBytes = false;
- uint32_t ww = (w+7)>>3; // Width of source image line in bytes
- uint16_t np = 0;
- for (int32_t yp = dy; yp < dy + dh; yp++)
- {
- int32_t px = x;
- bool move = true;
- for (int32_t xp = dx; xp < dx + dw; xp++)
- {
- if (data[(xp>>3)] & (0x80 >> (xp & 0x7))) {
- if (move) {
- move = false;
- setWindow(px, y, xe, ye);
- }
- np++;
- }
- else {
- if (np) {
- pushBlock(bitmap_fg, np);
- np = 0;
- move = true;
- }
- }
- px++;
- }
- y++;
- data += ww;
- if (np) { pushBlock(bitmap_fg, np); np = 0; }
- }
- }
- _swapBytes = swap; // Restore old value
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: setSwapBytes
- ** Description: Used by 16 bit pushImage() to swap byte order in colours
- ***************************************************************************************/
- void TFT_eSPI::setSwapBytes(bool swap)
- {
- _swapBytes = swap;
- }
- /***************************************************************************************
- ** Function name: getSwapBytes
- ** Description: Return the swap byte order for colours
- ***************************************************************************************/
- bool TFT_eSPI::getSwapBytes(void)
- {
- return _swapBytes;
- }
- /***************************************************************************************
- ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
- ** Description: Read RGB pixel colours from a defined area
- ***************************************************************************************/
- // If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel
- void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data)
- {
- #if defined(TFT_PARALLEL_8_BIT)
- uint32_t len = w * h;
- uint8_t* buf565 = data + len;
- readRect(x0, y0, w, h, (uint16_t*)buf565);
-
- while (len--) {
- uint16_t pixel565 = (*buf565++)<<8;
- pixel565 |= *buf565++;
- uint8_t red = (pixel565 & 0xF800) >> 8; red |= red >> 5;
- uint8_t green = (pixel565 & 0x07E0) >> 3; green |= green >> 6;
- uint8_t blue = (pixel565 & 0x001F) << 3; blue |= blue >> 5;
- *data++ = red;
- *data++ = green;
- *data++ = blue;
- }
- #else // Not TFT_PARALLEL_8_BIT
- begin_tft_read();
- readAddrWindow(x0, y0, w, h); // Sets CS low
- #ifdef TFT_SDA_READ
- begin_SDA_Read();
- #endif
- // Dummy read to throw away don't care value
- tft_Read_8();
- // Read window pixel 24 bit RGB values, buffer must be set in sketch to 3 * w * h
- uint32_t len = w * h;
- while (len--) {
- #if !defined (ILI9488_DRIVER)
- // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
- // as the TFT stores colours as 18 bits
- *data++ = tft_Read_8();
- *data++ = tft_Read_8();
- *data++ = tft_Read_8();
- #else
- // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse
- // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left
- *data++ = (tft_Read_8()&0x7E)<<1;
- *data++ = (tft_Read_8()&0x7E)<<1;
- *data++ = (tft_Read_8()&0x7E)<<1;
- #endif
- }
- CS_H;
- #ifdef TFT_SDA_READ
- end_SDA_Read();
- #endif
- end_tft_read();
- #endif
- }
- /***************************************************************************************
- ** Function name: drawCircle
- ** Description: Draw a circle outline
- ***************************************************************************************/
- // Optimised midpoint circle algorithm
- void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
- {
- if ( r <= 0 ) return;
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- int32_t f = 1 - r;
- int32_t ddF_y = -2 * r;
- int32_t ddF_x = 1;
- int32_t xs = -1;
- int32_t xe = 0;
- int32_t len = 0;
-
- bool first = true;
- do {
- while (f < 0) {
- ++xe;
- f += (ddF_x += 2);
- }
- f += (ddF_y += 2);
- if (xe-xs>1) {
- if (first) {
- len = 2*(xe - xs)-1;
- drawFastHLine(x0 - xe, y0 + r, len, color);
- drawFastHLine(x0 - xe, y0 - r, len, color);
- drawFastVLine(x0 + r, y0 - xe, len, color);
- drawFastVLine(x0 - r, y0 - xe, len, color);
- first = false;
- }
- else {
- len = xe - xs++;
- drawFastHLine(x0 - xe, y0 + r, len, color);
- drawFastHLine(x0 - xe, y0 - r, len, color);
- drawFastHLine(x0 + xs, y0 - r, len, color);
- drawFastHLine(x0 + xs, y0 + r, len, color);
- drawFastVLine(x0 + r, y0 + xs, len, color);
- drawFastVLine(x0 + r, y0 - xe, len, color);
- drawFastVLine(x0 - r, y0 - xe, len, color);
- drawFastVLine(x0 - r, y0 + xs, len, color);
- }
- }
- else {
- ++xs;
- drawPixel(x0 - xe, y0 + r, color);
- drawPixel(x0 - xe, y0 - r, color);
- drawPixel(x0 + xs, y0 - r, color);
- drawPixel(x0 + xs, y0 + r, color);
- drawPixel(x0 + r, y0 + xs, color);
- drawPixel(x0 + r, y0 - xe, color);
- drawPixel(x0 - r, y0 - xe, color);
- drawPixel(x0 - r, y0 + xs, color);
- }
- xs = xe;
- } while (xe < --r);
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawCircleHelper
- ** Description: Support function for drawRoundRect()
- ***************************************************************************************/
- void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t rr, uint8_t cornername, uint32_t color)
- {
- if (rr <= 0) return;
- int32_t f = 1 - rr;
- int32_t ddF_x = 1;
- int32_t ddF_y = -2 * rr;
- int32_t xe = 0;
- int32_t xs = 0;
- int32_t len = 0;
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- while (xe < rr--)
- {
- while (f < 0) {
- ++xe;
- f += (ddF_x += 2);
- }
- f += (ddF_y += 2);
- if (xe-xs==1) {
- if (cornername & 0x1) { // left top
- drawPixel(x0 - xe, y0 - rr, color);
- drawPixel(x0 - rr, y0 - xe, color);
- }
- if (cornername & 0x2) { // right top
- drawPixel(x0 + rr , y0 - xe, color);
- drawPixel(x0 + xs + 1, y0 - rr, color);
- }
- if (cornername & 0x4) { // right bottom
- drawPixel(x0 + xs + 1, y0 + rr , color);
- drawPixel(x0 + rr, y0 + xs + 1, color);
- }
- if (cornername & 0x8) { // left bottom
- drawPixel(x0 - rr, y0 + xs + 1, color);
- drawPixel(x0 - xe, y0 + rr , color);
- }
- }
- else {
- len = xe - xs++;
- if (cornername & 0x1) { // left top
- drawFastHLine(x0 - xe, y0 - rr, len, color);
- drawFastVLine(x0 - rr, y0 - xe, len, color);
- }
- if (cornername & 0x2) { // right top
- drawFastVLine(x0 + rr, y0 - xe, len, color);
- drawFastHLine(x0 + xs, y0 - rr, len, color);
- }
- if (cornername & 0x4) { // right bottom
- drawFastHLine(x0 + xs, y0 + rr, len, color);
- drawFastVLine(x0 + rr, y0 + xs, len, color);
- }
- if (cornername & 0x8) { // left bottom
- drawFastVLine(x0 - rr, y0 + xs, len, color);
- drawFastHLine(x0 - xe, y0 + rr, len, color);
- }
- }
- xs = xe;
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: fillCircle
- ** Description: draw a filled circle
- ***************************************************************************************/
- // Optimised midpoint circle algorithm, changed to horizontal lines (faster in sprites)
- // Improved algorithm avoids repetition of lines
- void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
- {
- int32_t x = 0;
- int32_t dx = 1;
- int32_t dy = r+r;
- int32_t p = -(r>>1);
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- drawFastHLine(x0 - r, y0, dy+1, color);
- while(x<r){
- if(p>=0) {
- drawFastHLine(x0 - x, y0 + r, dx, color);
- drawFastHLine(x0 - x, y0 - r, dx, color);
- dy-=2;
- p-=dy;
- r--;
- }
- dx+=2;
- p+=dx;
- x++;
- drawFastHLine(x0 - r, y0 + x, dy+1, color);
- drawFastHLine(x0 - r, y0 - x, dy+1, color);
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: fillCircleHelper
- ** Description: Support function for fillRoundRect()
- ***************************************************************************************/
- // Support drawing roundrects, changed to horizontal lines (faster in sprites)
- void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color)
- {
- int32_t f = 1 - r;
- int32_t ddF_x = 1;
- int32_t ddF_y = -r - r;
- int32_t y = 0;
- delta++;
- while (y < r) {
- if (f >= 0) {
- if (cornername & 0x1) drawFastHLine(x0 - y, y0 + r, y + y + delta, color);
- if (cornername & 0x2) drawFastHLine(x0 - y, y0 - r, y + y + delta, color);
- r--;
- ddF_y += 2;
- f += ddF_y;
- }
- y++;
- ddF_x += 2;
- f += ddF_x;
- if (cornername & 0x1) drawFastHLine(x0 - r, y0 + y, r + r + delta, color);
- if (cornername & 0x2) drawFastHLine(x0 - r, y0 - y, r + r + delta, color);
- }
- }
- /***************************************************************************************
- ** Function name: drawEllipse
- ** Description: Draw a ellipse outline
- ***************************************************************************************/
- void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
- {
- if (rx<2) return;
- if (ry<2) return;
- int32_t x, y;
- int32_t rx2 = rx * rx;
- int32_t ry2 = ry * ry;
- int32_t fx2 = 4 * rx2;
- int32_t fy2 = 4 * ry2;
- int32_t s;
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) {
- // These are ordered to minimise coordinate changes in x or y
- // drawPixel can then send fewer bounding box commands
- drawPixel(x0 + x, y0 + y, color);
- drawPixel(x0 - x, y0 + y, color);
- drawPixel(x0 - x, y0 - y, color);
- drawPixel(x0 + x, y0 - y, color);
- if (s >= 0) {
- s += fx2 * (1 - y);
- y--;
- }
- s += ry2 * ((4 * x) + 6);
- }
- for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) {
- // These are ordered to minimise coordinate changes in x or y
- // drawPixel can then send fewer bounding box commands
- drawPixel(x0 + x, y0 + y, color);
- drawPixel(x0 - x, y0 + y, color);
- drawPixel(x0 - x, y0 - y, color);
- drawPixel(x0 + x, y0 - y, color);
- if (s >= 0)
- {
- s += fy2 * (1 - x);
- x--;
- }
- s += rx2 * ((4 * y) + 6);
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: fillEllipse
- ** Description: draw a filled ellipse
- ***************************************************************************************/
- void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
- {
- if (rx<2) return;
- if (ry<2) return;
- int32_t x, y;
- int32_t rx2 = rx * rx;
- int32_t ry2 = ry * ry;
- int32_t fx2 = 4 * rx2;
- int32_t fy2 = 4 * ry2;
- int32_t s;
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) {
- drawFastHLine(x0 - x, y0 - y, x + x + 1, color);
- drawFastHLine(x0 - x, y0 + y, x + x + 1, color);
- if (s >= 0) {
- s += fx2 * (1 - y);
- y--;
- }
- s += ry2 * ((4 * x) + 6);
- }
- for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) {
- drawFastHLine(x0 - x, y0 - y, x + x + 1, color);
- drawFastHLine(x0 - x, y0 + y, x + x + 1, color);
- if (s >= 0) {
- s += fy2 * (1 - x);
- x--;
- }
- s += rx2 * ((4 * y) + 6);
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: fillScreen
- ** Description: Clear the screen to defined colour
- ***************************************************************************************/
- void TFT_eSPI::fillScreen(uint32_t color)
- {
- fillRect(0, 0, _width, _height, color);
- }
- /***************************************************************************************
- ** Function name: drawRect
- ** Description: Draw a rectangle outline
- ***************************************************************************************/
- // Draw a rectangle
- void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- drawFastHLine(x, y, w, color);
- drawFastHLine(x, y + h - 1, w, color);
- // Avoid drawing corner pixels twice
- drawFastVLine(x, y+1, h-2, color);
- drawFastVLine(x + w - 1, y+1, h-2, color);
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawRoundRect
- ** Description: Draw a rounded corner rectangle outline
- ***************************************************************************************/
- // Draw a rounded rectangle
- void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- // smarter version
- drawFastHLine(x + r , y , w - r - r, color); // Top
- drawFastHLine(x + r , y + h - 1, w - r - r, color); // Bottom
- drawFastVLine(x , y + r , h - r - r, color); // Left
- drawFastVLine(x + w - 1, y + r , h - r - r, color); // Right
- // draw four corners
- drawCircleHelper(x + r , y + r , r, 1, color);
- drawCircleHelper(x + w - r - 1, y + r , r, 2, color);
- drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
- drawCircleHelper(x + r , y + h - r - 1, r, 8, color);
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: fillRoundRect
- ** Description: Draw a rounded corner filled rectangle
- ***************************************************************************************/
- // Fill a rounded rectangle, changed to horizontal lines (faster in sprites)
- void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- // smarter version
- fillRect(x, y + r, w, h - r - r, color);
- // draw four corners
- fillCircleHelper(x + r, y + h - r - 1, r, 1, w - r - r - 1, color);
- fillCircleHelper(x + r , y + r, r, 2, w - r - r - 1, color);
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawTriangle
- ** Description: Draw a triangle outline using 3 arbitrary points
- ***************************************************************************************/
- // Draw a triangle
- 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)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- drawLine(x0, y0, x1, y1, color);
- drawLine(x1, y1, x2, y2, color);
- drawLine(x2, y2, x0, y0, color);
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: fillTriangle
- ** Description: Draw a filled triangle using 3 arbitrary points
- ***************************************************************************************/
- // Fill a triangle - original Adafruit function works well and code footprint is small
- 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)
- {
- int32_t a, b, y, last;
- // Sort coordinates by Y order (y2 >= y1 >= y0)
- if (y0 > y1) {
- swap_coord(y0, y1); swap_coord(x0, x1);
- }
- if (y1 > y2) {
- swap_coord(y2, y1); swap_coord(x2, x1);
- }
- if (y0 > y1) {
- swap_coord(y0, y1); swap_coord(x0, x1);
- }
- if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
- a = b = x0;
- if (x1 < a) a = x1;
- else if (x1 > b) b = x1;
- if (x2 < a) a = x2;
- else if (x2 > b) b = x2;
- drawFastHLine(a, y0, b - a + 1, color);
- return;
- }
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- int32_t
- dx01 = x1 - x0,
- dy01 = y1 - y0,
- dx02 = x2 - x0,
- dy02 = y2 - y0,
- dx12 = x2 - x1,
- dy12 = y2 - y1,
- sa = 0,
- sb = 0;
- // For upper part of triangle, find scanline crossings for segments
- // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
- // is included here (and second loop will be skipped, avoiding a /0
- // error there), otherwise scanline y1 is skipped here and handled
- // in the second loop...which also avoids a /0 error here if y0=y1
- // (flat-topped triangle).
- if (y1 == y2) last = y1; // Include y1 scanline
- else last = y1 - 1; // Skip it
- for (y = y0; y <= last; y++) {
- a = x0 + sa / dy01;
- b = x0 + sb / dy02;
- sa += dx01;
- sb += dx02;
- if (a > b) swap_coord(a, b);
- drawFastHLine(a, y, b - a + 1, color);
- }
- // For lower part of triangle, find scanline crossings for segments
- // 0-2 and 1-2. This loop is skipped if y1=y2.
- sa = dx12 * (y - y1);
- sb = dx02 * (y - y0);
- for (; y <= y2; y++) {
- a = x1 + sa / dy12;
- b = x0 + sb / dy02;
- sa += dx12;
- sb += dx02;
- if (a > b) swap_coord(a, b);
- drawFastHLine(a, y, b - a + 1, color);
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawBitmap
- ** Description: Draw an image stored in an array on the TFT
- ***************************************************************************************/
- void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- int32_t i, j, byteWidth = (w + 7) / 8;
- for (j = 0; j < h; j++) {
- for (i = 0; i < w; i++ ) {
- if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
- drawPixel(x + i, y + j, color);
- }
- }
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawBitmap
- ** Description: Draw an image stored in an array on the TFT
- ***************************************************************************************/
- 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)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- int32_t i, j, byteWidth = (w + 7) / 8;
- for (j = 0; j < h; j++) {
- for (i = 0; i < w; i++ ) {
- if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7)))
- drawPixel(x + i, y + j, fgcolor);
- else drawPixel(x + i, y + j, bgcolor);
- }
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawXBitmap
- ** Description: Draw an image stored in an XBM array onto the TFT
- ***************************************************************************************/
- void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- int32_t i, j, byteWidth = (w + 7) / 8;
- for (j = 0; j < h; j++) {
- for (i = 0; i < w; i++ ) {
- if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i & 7))) {
- drawPixel(x + i, y + j, color);
- }
- }
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: drawXBitmap
- ** Description: Draw an XBM image with foreground and background colors
- ***************************************************************************************/
- 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)
- {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- int32_t i, j, byteWidth = (w + 7) / 8;
- for (j = 0; j < h; j++) {
- for (i = 0; i < w; i++ ) {
- if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i & 7)))
- drawPixel(x + i, y + j, color);
- else drawPixel(x + i, y + j, bgcolor);
- }
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- /***************************************************************************************
- ** Function name: setCursor
- ** Description: Set the text cursor x,y position
- ***************************************************************************************/
- void TFT_eSPI::setCursor(int16_t x, int16_t y)
- {
- cursor_x = x;
- cursor_y = y;
- }
- /***************************************************************************************
- ** Function name: setCursor
- ** Description: Set the text cursor x,y position and font
- ***************************************************************************************/
- void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font)
- {
- textfont = font;
- cursor_x = x;
- cursor_y = y;
- }
- /***************************************************************************************
- ** Function name: getCursorX
- ** Description: Get the text cursor x position
- ***************************************************************************************/
- int16_t TFT_eSPI::getCursorX(void)
- {
- return cursor_x;
- }
- /***************************************************************************************
- ** Function name: getCursorY
- ** Description: Get the text cursor y position
- ***************************************************************************************/
- int16_t TFT_eSPI::getCursorY(void)
- {
- return cursor_y;
- }
- /***************************************************************************************
- ** Function name: setTextSize
- ** Description: Set the text size multiplier
- ***************************************************************************************/
- void TFT_eSPI::setTextSize(uint8_t s)
- {
- if (s>7) s = 7; // Limit the maximum size multiplier so byte variables can be used for rendering
- textsize = (s > 0) ? s : 1; // Don't allow font size 0
- }
- /***************************************************************************************
- ** Function name: setTextColor
- ** Description: Set the font foreground colour (background is transparent)
- ***************************************************************************************/
- void TFT_eSPI::setTextColor(uint16_t c)
- {
- // For 'transparent' background, we'll set the bg
- // to the same as fg instead of using a flag
- textcolor = textbgcolor = c;
- }
- /***************************************************************************************
- ** Function name: setTextColor
- ** Description: Set the font foreground and background colour
- ***************************************************************************************/
- void TFT_eSPI::setTextColor(uint16_t c, uint16_t b)
- {
- textcolor = c;
- textbgcolor = b;
- }
- /***************************************************************************************
- ** Function name: setPivot
- ** Description: Set the pivot point on the TFT
- *************************************************************************************x*/
- void TFT_eSPI::setPivot(int16_t x, int16_t y)
- {
- _xPivot = x;
- _yPivot = y;
- }
- /***************************************************************************************
- ** Function name: getPivotX
- ** Description: Get the x pivot position
- ***************************************************************************************/
- int16_t TFT_eSPI::getPivotX(void)
- {
- return _xPivot;
- }
- /***************************************************************************************
- ** Function name: getPivotY
- ** Description: Get the y pivot position
- ***************************************************************************************/
- int16_t TFT_eSPI::getPivotY(void)
- {
- return _yPivot;
- }
- /***************************************************************************************
- ** Function name: setBitmapColor
- ** Description: Set the foreground foreground and background colour
- ***************************************************************************************/
- void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b)
- {
- if (c == b) b = ~c;
- bitmap_fg = c;
- bitmap_bg = b;
- }
- /***************************************************************************************
- ** Function name: setTextWrap
- ** Description: Define if text should wrap at end of line
- ***************************************************************************************/
- void TFT_eSPI::setTextWrap(bool wrapX, bool wrapY)
- {
- textwrapX = wrapX;
- textwrapY = wrapY;
- }
- /***************************************************************************************
- ** Function name: setTextDatum
- ** Description: Set the text position reference datum
- ***************************************************************************************/
- void TFT_eSPI::setTextDatum(uint8_t d)
- {
- textdatum = d;
- }
- /***************************************************************************************
- ** Function name: setTextPadding
- ** Description: Define padding width (aids erasing old text and numbers)
- ***************************************************************************************/
- void TFT_eSPI::setTextPadding(uint16_t x_width)
- {
- padX = x_width;
- }
- /***************************************************************************************
- ** Function name: setTextPadding
- ** Description: Define padding width (aids erasing old text and numbers)
- ***************************************************************************************/
- uint16_t TFT_eSPI::getTextPadding(void)
- {
- return padX;
- }
- /***************************************************************************************
- ** Function name: getRotation
- ** Description: Return the rotation value (as used by setRotation())
- ***************************************************************************************/
- uint8_t TFT_eSPI::getRotation(void)
- {
- return rotation;
- }
- /***************************************************************************************
- ** Function name: getTextDatum
- ** Description: Return the text datum value (as used by setTextDatum())
- ***************************************************************************************/
- uint8_t TFT_eSPI::getTextDatum(void)
- {
- return textdatum;
- }
- /***************************************************************************************
- ** Function name: width
- ** Description: Return the pixel width of display (per current rotation)
- ***************************************************************************************/
- // Return the size of the display (per current rotation)
- int16_t TFT_eSPI::width(void)
- {
- if (_vpDatum) return _xWidth;
- return _width;
- }
- /***************************************************************************************
- ** Function name: height
- ** Description: Return the pixel height of display (per current rotation)
- ***************************************************************************************/
- int16_t TFT_eSPI::height(void)
- {
- if (_vpDatum) return _yHeight;
- return _height;
- }
- /***************************************************************************************
- ** Function name: textWidth
- ** Description: Return the width in pixels of a string in a given font
- ***************************************************************************************/
- int16_t TFT_eSPI::textWidth(const String& string)
- {
- int16_t len = string.length() + 2;
- char buffer[len];
- string.toCharArray(buffer, len);
- return textWidth(buffer, textfont);
- }
- int16_t TFT_eSPI::textWidth(const String& string, uint8_t font)
- {
- int16_t len = string.length() + 2;
- char buffer[len];
- string.toCharArray(buffer, len);
- return textWidth(buffer, font);
- }
- int16_t TFT_eSPI::textWidth(const char *string)
- {
- return textWidth(string, textfont);
- }
- int16_t TFT_eSPI::textWidth(const char *string, uint8_t font)
- {
- int32_t str_width = 0;
- uint16_t uniCode = 0;
- #ifdef SMOOTH_FONT
- if(fontLoaded) {
- while (*string) {
- uniCode = decodeUTF8(*string++);
- if (uniCode) {
- if (uniCode == 0x20) str_width += gFont.spaceWidth;
- else {
- uint16_t gNum = 0;
- bool found = getUnicodeIndex(uniCode, &gNum);
- if (found) {
- if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum];
- if (*string || isDigits) str_width += gxAdvance[gNum];
- else str_width += (gdX[gNum] + gWidth[gNum]);
- }
- else str_width += gFont.spaceWidth + 1;
- }
- }
- }
- isDigits = false;
- return str_width;
- }
- #endif
- if (font>1 && font<9) {
- char *widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop
- while (*string) {
- uniCode = *(string++);
- if (uniCode > 31 && uniCode < 128)
- str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subtract 32 from uniCode
- else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width
- }
- }
- else {
- #ifdef LOAD_GFXFF
- if(gfxFont) { // New font
- while (*string) {
- uniCode = decodeUTF8(*string++);
- if ((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last ))) {
- uniCode -= pgm_read_word(&gfxFont->first);
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]);
- // If this is not the last character or is a digit then use xAdvance
- if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance);
- // Else use the offset plus width since this can be bigger than xAdvance
- else str_width += ((int8_t)pgm_read_byte(&glyph->xOffset) + pgm_read_byte(&glyph->width));
- }
- }
- }
- else
- #endif
- {
- #ifdef LOAD_GLCD
- while (*string++) str_width += 6;
- #endif
- }
- }
- isDigits = false;
- return str_width * textsize;
- }
- /***************************************************************************************
- ** Function name: fontsLoaded
- ** Description: return an encoded 16 bit value showing the fonts loaded
- ***************************************************************************************/
- // Returns a value showing which fonts are loaded (bit N set = Font N loaded)
- uint16_t TFT_eSPI::fontsLoaded(void)
- {
- return fontsloaded;
- }
- /***************************************************************************************
- ** Function name: fontHeight
- ** Description: return the height of a font (yAdvance for free fonts)
- ***************************************************************************************/
- int16_t TFT_eSPI::fontHeight(int16_t font)
- {
- #ifdef SMOOTH_FONT
- if(fontLoaded) return gFont.yAdvance;
- #endif
- #ifdef LOAD_GFXFF
- if (font==1) {
- if(gfxFont) { // New font
- return pgm_read_byte(&gfxFont->yAdvance) * textsize;
- }
- }
- #endif
- return pgm_read_byte( &fontdata[font].height ) * textsize;
- }
- int16_t TFT_eSPI::fontHeight(void)
- {
- return fontHeight(textfont);
- }
- /***************************************************************************************
- ** Function name: drawChar
- ** Description: draw a single character in the GLCD or GFXFF font
- ***************************************************************************************/
- void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size)
- {
- if (_vpOoB) return;
- int32_t xd = x + _xDatum;
- int32_t yd = y + _yDatum;
- if (c < 32) return;
- #ifdef LOAD_GLCD
- //>>>>>>>>>>>>>>>>>>
- #ifdef LOAD_GFXFF
- if(!gfxFont) { // 'Classic' built-in font
- #endif
- //>>>>>>>>>>>>>>>>>>
- if ((xd >= _vpW) || // Clip right
- ( yd >= _vpH) || // Clip bottom
- ((xd + 6 * size - 1) < _vpX) || // Clip left
- ((yd + 8 * size - 1) < _vpY)) // Clip top
- return;
- bool fillbg = (bg != color);
- bool clip = xd < _vpX || xd + 6 * textsize >= _vpW || yd < _vpY || yd + 8 * textsize >= _vpH;
- if ((size==1) && fillbg && !clip) {
- uint8_t column[6];
- uint8_t mask = 0x1;
- begin_tft_write();
- setWindow(xd, yd, xd+5, yd+8);
- for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i);
- column[5] = 0;
- for (int8_t j = 0; j < 8; j++) {
- for (int8_t k = 0; k < 5; k++ ) {
- if (column[k] & mask) {tft_Write_16(color);}
- else {tft_Write_16(bg);}
- }
- mask <<= 1;
- tft_Write_16(bg);
- }
- end_tft_write();
- }
- else {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- for (int8_t i = 0; i < 6; i++ ) {
- uint8_t line;
- if (i == 5)
- line = 0x0;
- else
- line = pgm_read_byte(font + (c * 5) + i);
- if (size == 1 && !fillbg) { // default size
- for (int8_t j = 0; j < 8; j++) {
- if (line & 0x1) drawPixel(x + i, y + j, color);
- line >>= 1;
- }
- }
- else { // big size or clipped
- for (int8_t j = 0; j < 8; j++) {
- if (line & 0x1) fillRect(x + (i * size), y + (j * size), size, size, color);
- else if (fillbg) fillRect(x + i * size, y + j * size, size, size, bg);
- line >>= 1;
- }
- }
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>
- #ifdef LOAD_GFXFF
- } else { // Custom font
- #endif
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>
- #endif // LOAD_GLCD
- #ifdef LOAD_GFXFF
- // Filter out bad characters not present in font
- if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>
- c -= pgm_read_word(&gfxFont->first);
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]);
- uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap);
- uint32_t bo = pgm_read_word(&glyph->bitmapOffset);
- uint8_t w = pgm_read_byte(&glyph->width),
- h = pgm_read_byte(&glyph->height);
- //xa = pgm_read_byte(&glyph->xAdvance);
- int8_t xo = pgm_read_byte(&glyph->xOffset),
- yo = pgm_read_byte(&glyph->yOffset);
- uint8_t xx, yy, bits=0, bit=0;
- int16_t xo16 = 0, yo16 = 0;
- if(size > 1) {
- xo16 = xo;
- yo16 = yo;
- }
- // GFXFF rendering speed up
- uint16_t hpc = 0; // Horizontal foreground pixel count
- for(yy=0; yy<h; yy++) {
- for(xx=0; xx<w; xx++) {
- if(bit == 0) {
- bits = pgm_read_byte(&bitmap[bo++]);
- bit = 0x80;
- }
- if(bits & bit) hpc++;
- else {
- if (hpc) {
- if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color);
- else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color);
- hpc=0;
- }
- }
- bit >>= 1;
- }
- // Draw pixels for this line as we are about to increment yy
- if (hpc) {
- if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color);
- else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color);
- hpc=0;
- }
- }
- inTransaction = lockTransaction;
- end_tft_write(); // Does nothing if Sprite class uses this function
- }
- #endif
- #ifdef LOAD_GLCD
- #ifdef LOAD_GFXFF
- } // End classic vs custom font
- #endif
- #endif
- }
- /***************************************************************************************
- ** Function name: setAddrWindow
- ** Description: define an area to receive a stream of pixels
- ***************************************************************************************/
- // Chip select is high at the end of this function
- void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h)
- {
- begin_tft_write();
- setWindow(x0, y0, x0 + w - 1, y0 + h - 1);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: setWindow
- ** Description: define an area to receive a stream of pixels
- ***************************************************************************************/
- // Chip select stays low, call begin_tft_write first. Use setAddrWindow() from sketches
- void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
- {
- //begin_tft_write(); // Must be called before setWindow
- addr_row = 0xFFFF;
- addr_col = 0xFFFF;
- #if defined (ILI9225_DRIVER)
- if (rotation & 0x01) { swap_coord(x0, y0); swap_coord(x1, y1); }
- SPI_BUSY_CHECK;
- DC_C; tft_Write_8(TFT_CASET1);
- DC_D; tft_Write_16(x0);
- DC_C; tft_Write_8(TFT_CASET2);
- DC_D; tft_Write_16(x1);
- DC_C; tft_Write_8(TFT_PASET1);
- DC_D; tft_Write_16(y0);
- DC_C; tft_Write_8(TFT_PASET2);
- DC_D; tft_Write_16(y1);
- DC_C; tft_Write_8(TFT_RAM_ADDR1);
- DC_D; tft_Write_16(x0);
- DC_C; tft_Write_8(TFT_RAM_ADDR2);
- DC_D; tft_Write_16(y0);
- // write to RAM
- DC_C; tft_Write_8(TFT_RAMWR);
- DC_D;
- #elif defined (SSD1351_DRIVER)
- if (rotation & 1) {
- swap_coord(x0, y0);
- swap_coord(x1, y1);
- }
- SPI_BUSY_CHECK;
- DC_C; tft_Write_8(TFT_CASET);
- DC_D; tft_Write_16(x1 | (x0 << 8));
- DC_C; tft_Write_8(TFT_PASET);
- DC_D; tft_Write_16(y1 | (y0 << 8));
- DC_C; tft_Write_8(TFT_RAMWR);
- DC_D;
- #else
- #if defined (SSD1963_DRIVER)
- if ((rotation & 0x1) == 0) { swap_coord(x0, y0); swap_coord(x1, y1); }
- #endif
- #ifdef CGRAM_OFFSET
- x0+=colstart;
- x1+=colstart;
- y0+=rowstart;
- y1+=rowstart;
- #endif
- // Temporary solution is to include the RP2040 optimised code here
- #if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- #if !defined (SPI_18BIT_DRIVER)
- spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
- #endif
- spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)x0>>8;
- spi_get_hw(spi0)->dr = (uint32_t)x0;
- spi_get_hw(spi0)->dr = (uint32_t)x1>>8;
- spi_get_hw(spi0)->dr = (uint32_t)x1;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)y0>>8;
- spi_get_hw(spi0)->dr = (uint32_t)y0;
- spi_get_hw(spi0)->dr = (uint32_t)y1>>8;
- spi_get_hw(spi0)->dr = (uint32_t)y1;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMWR;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- #if !defined (SPI_18BIT_DRIVER)
- spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
- #endif
- DC_D;
- #else
- SPI_BUSY_CHECK;
- DC_C; tft_Write_8(TFT_CASET);
- DC_D; tft_Write_32C(x0, x1);
- DC_C; tft_Write_8(TFT_PASET);
- DC_D; tft_Write_32C(y0, y1);
- DC_C; tft_Write_8(TFT_RAMWR);
- DC_D;
- #endif // RP2040 SPI
- #endif
- //end_tft_write(); // Must be called after setWindow
- }
- /***************************************************************************************
- ** Function name: readAddrWindow
- ** Description: define an area to read a stream of pixels
- ***************************************************************************************/
- void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
- {
- //begin_tft_write(); // Must be called before readAddrWindow or CS set low
- int32_t xe = xs + w - 1;
- int32_t ye = ys + h - 1;
- addr_col = 0xFFFF;
- addr_row = 0xFFFF;
- #ifdef CGRAM_OFFSET
- xs += colstart;
- xe += colstart;
- ys += rowstart;
- ye += rowstart;
- #endif
- #if defined (SSD1963_DRIVER)
- if ((rotation & 0x1) == 0) { swap_coord(xs, ys); swap_coord(xe, ye); }
- #endif
- // Temporary solution is to include the RP2040 optimised code here
- #if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
- spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)xs>>8;
- spi_get_hw(spi0)->dr = (uint32_t)xs;
- spi_get_hw(spi0)->dr = (uint32_t)xe>>8;
- spi_get_hw(spi0)->dr = (uint32_t)xe;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)ys>>8;
- spi_get_hw(spi0)->dr = (uint32_t)ys;
- spi_get_hw(spi0)->dr = (uint32_t)ye>>8;
- spi_get_hw(spi0)->dr = (uint32_t)ye;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMRD;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- //spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
- DC_D;
- // Flush the rx buffer and reset overflow flag
- while (spi_is_readable(spi0)) (void)spi_get_hw(spi0)->dr;
- spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS;
- #else
- // Column addr set
- DC_C; tft_Write_8(TFT_CASET);
- DC_D; tft_Write_32C(xs, xe);
- // Row addr set
- DC_C; tft_Write_8(TFT_PASET);
- DC_D; tft_Write_32C(ys, ye);
- // Read CGRAM command
- DC_C; tft_Write_8(TFT_RAMRD);
- DC_D;
- #endif // RP2040 SPI
- //end_tft_write(); // Must be called after readAddrWindow or CS set high
- }
- /***************************************************************************************
- ** Function name: drawPixel
- ** Description: push a single pixel at an arbitrary position
- ***************************************************************************************/
- void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
- {
- if (_vpOoB) return;
- x+= _xDatum;
- y+= _yDatum;
- // Range checking
- if ((x < _vpX) || (y < _vpY) ||(x >= _vpW) || (y >= _vpH)) return;
- #ifdef CGRAM_OFFSET
- x+=colstart;
- y+=rowstart;
- #endif
- begin_tft_write();
- #if defined (ILI9225_DRIVER)
- if (rotation & 0x01) { swap_coord(x, y); }
- SPI_BUSY_CHECK;
- // Set window to full screen to optimise sequential pixel rendering
- if (addr_row != 0x9225) {
- addr_row = 0x9225; // addr_row used for flag
- DC_C; tft_Write_8(TFT_CASET1);
- DC_D; tft_Write_16(0);
- DC_C; tft_Write_8(TFT_CASET2);
- DC_D; tft_Write_16(175);
-
- DC_C; tft_Write_8(TFT_PASET1);
- DC_D; tft_Write_16(0);
- DC_C; tft_Write_8(TFT_PASET2);
- DC_D; tft_Write_16(219);
- }
- // Define pixel coordinate
- DC_C; tft_Write_8(TFT_RAM_ADDR1);
- DC_D; tft_Write_16(x);
- DC_C; tft_Write_8(TFT_RAM_ADDR2);
- DC_D; tft_Write_16(y);
- // write to RAM
- DC_C; tft_Write_8(TFT_RAMWR);
- #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32)
- DC_D; tft_Write_16(color);
- #else
- DC_D; tft_Write_16N(color);
- #endif
- // Temporary solution is to include the RP2040 optimised code here
- #elif defined (ARDUINO_ARCH_RP2040)
- // Since the SPI functions do not terminate until transmission is complete
- // a busy check is not needed.
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
- spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS){};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)x>>8;
- spi_get_hw(spi0)->dr = (uint32_t)x;
- spi_get_hw(spi0)->dr = (uint32_t)x>>8;
- spi_get_hw(spi0)->dr = (uint32_t)x;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)y>>8;
- spi_get_hw(spi0)->dr = (uint32_t)y;
- spi_get_hw(spi0)->dr = (uint32_t)y>>8;
- spi_get_hw(spi0)->dr = (uint32_t)y;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_C;
- spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMWR;
- #if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
- uint8_t r = (color & 0xF800)>>8;
- uint8_t g = (color & 0x07E0)>>3;
- uint8_t b = (color & 0x001F)<<3;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- tft_Write_8N(r); tft_Write_8N(g); tft_Write_8N(b);
- #else
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- DC_D;
- spi_get_hw(spi0)->dr = (uint32_t)color>>8;
- spi_get_hw(spi0)->dr = (uint32_t)color;
- #endif
- /*
- // Subsequent pixel reads work OK without draining the FIFO...
- // Drain RX FIFO, then wait for shifting to finish (which may be *after*
- // TX FIFO drains), then drain RX FIFO again
- while (spi_is_readable(spi0))
- (void)spi_get_hw(spi0)->dr;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS)
- tight_loop_contents();
- while (spi_is_readable(spi0))
- (void)spi_get_hw(spi0)->dr;
- //*/
- // Subsequent pixel reads work without this
- // spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS;
- while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
- // Next call will start with 8 bit command so changing to 16 bit not needed here
- //spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
- #else
- #if defined (SSD1351_DRIVER) || defined (SSD1963_DRIVER)
- if ((rotation & 0x1) == 0) { swap_coord(x, y); }
- #endif
- SPI_BUSY_CHECK;
- #if defined (MULTI_TFT_SUPPORT) || defined (GC9A01_DRIVER)
- // No optimisation
- DC_C; tft_Write_8(TFT_CASET);
- DC_D; tft_Write_32D(x);
- DC_C; tft_Write_8(TFT_PASET);
- DC_D; tft_Write_32D(y);
- #elif defined (SSD1351_DRIVER)
- // No need to send x if it has not changed (speeds things up)
- if (addr_col != x) {
- DC_C; tft_Write_8(TFT_CASET);
- DC_D; tft_Write_16(x | (x << 8));
- addr_col = x;
- }
- // No need to send y if it has not changed (speeds things up)
- if (addr_row != y) {
- DC_C; tft_Write_8(TFT_PASET);
- DC_D; tft_Write_16(y | (y << 8));
- addr_row = y;
- }
- #else
- // No need to send x if it has not changed (speeds things up)
- if (addr_col != x) {
- DC_C; tft_Write_8(TFT_CASET);
- DC_D; tft_Write_32D(x);
- addr_col = x;
- }
- // No need to send y if it has not changed (speeds things up)
- if (addr_row != y) {
- DC_C; tft_Write_8(TFT_PASET);
- DC_D; tft_Write_32D(y);
- addr_row = y;
- }
- #endif
- DC_C; tft_Write_8(TFT_RAMWR);
-
- #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32)
- DC_D; tft_Write_16(color);
- #else
- DC_D; tft_Write_16N(color);
- #endif
- #endif
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushColor
- ** Description: push a single pixel
- ***************************************************************************************/
- void TFT_eSPI::pushColor(uint16_t color)
- {
- begin_tft_write();
- tft_Write_16(color);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushColor
- ** Description: push a single colour to "len" pixels
- ***************************************************************************************/
- void TFT_eSPI::pushColor(uint16_t color, uint32_t len)
- {
- begin_tft_write();
- pushBlock(color, len);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: startWrite
- ** Description: begin transaction with CS low, MUST later call endWrite
- ***************************************************************************************/
- void TFT_eSPI::startWrite(void)
- {
- begin_tft_write();
- lockTransaction = true; // Lock transaction for all sequentially run sketch functions
- inTransaction = true;
- }
- /***************************************************************************************
- ** Function name: endWrite
- ** Description: end transaction with CS high
- ***************************************************************************************/
- void TFT_eSPI::endWrite(void)
- {
- lockTransaction = false; // Release sketch induced transaction lock
- inTransaction = false;
- DMA_BUSY_CHECK; // Safety check - user code should have checked this!
- end_tft_write(); // Release SPI bus
- }
- /***************************************************************************************
- ** Function name: writeColor (use startWrite() and endWrite() before & after)
- ** Description: raw write of "len" pixels avoiding transaction check
- ***************************************************************************************/
- void TFT_eSPI::writeColor(uint16_t color, uint32_t len)
- {
- pushBlock(color, len);
- }
- /***************************************************************************************
- ** Function name: pushColors
- ** Description: push an array of pixels for 16 bit raw image drawing
- ***************************************************************************************/
- // Assumed that setAddrWindow() has previously been called
- // len is number of bytes, not pixels
- void TFT_eSPI::pushColors(uint8_t *data, uint32_t len)
- {
- begin_tft_write();
- pushPixels(data, len>>1);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: pushColors
- ** Description: push an array of pixels, for image drawing
- ***************************************************************************************/
- void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap)
- {
- begin_tft_write();
- if (swap) {swap = _swapBytes; _swapBytes = true; }
- pushPixels(data, len);
- _swapBytes = swap; // Restore old value
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: drawLine
- ** Description: draw a line between 2 arbitrary points
- ***************************************************************************************/
- // Bresenham's algorithm - thx wikipedia - speed enhanced by Bodmer to use
- // an efficient FastH/V Line draw routine for line segments of 2 pixels or more
- void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color)
- {
- if (_vpOoB) return;
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- //x+= _xDatum; // Not added here, added by drawPixel & drawFastXLine
- //y+= _yDatum;
- bool steep = abs(y1 - y0) > abs(x1 - x0);
- if (steep) {
- swap_coord(x0, y0);
- swap_coord(x1, y1);
- }
- if (x0 > x1) {
- swap_coord(x0, x1);
- swap_coord(y0, y1);
- }
- int32_t dx = x1 - x0, dy = abs(y1 - y0);;
- int32_t err = dx >> 1, ystep = -1, xs = x0, dlen = 0;
- if (y0 < y1) ystep = 1;
- // Split into steep and not steep for FastH/V separation
- if (steep) {
- for (; x0 <= x1; x0++) {
- dlen++;
- err -= dy;
- if (err < 0) {
- if (dlen == 1) drawPixel(y0, xs, color);
- else drawFastVLine(y0, xs, dlen, color);
- dlen = 0;
- y0 += ystep; xs = x0 + 1;
- err += dx;
- }
- }
- if (dlen) drawFastVLine(y0, xs, dlen, color);
- }
- else
- {
- for (; x0 <= x1; x0++) {
- dlen++;
- err -= dy;
- if (err < 0) {
- if (dlen == 1) drawPixel(xs, y0, color);
- else drawFastHLine(xs, y0, dlen, color);
- dlen = 0;
- y0 += ystep; xs = x0 + 1;
- err += dx;
- }
- }
- if (dlen) drawFastHLine(xs, y0, dlen, color);
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: drawFastVLine
- ** Description: draw a vertical line
- ***************************************************************************************/
- void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
- {
- if (_vpOoB) return;
- x+= _xDatum;
- y+= _yDatum;
- // Clipping
- if ((x < _vpX) || (x >= _vpW) || (y >= _vpH)) return;
- if (y < _vpY) { h += y - _vpY; y = _vpY; }
- if ((y + h) > _vpH) h = _vpH - y;
- if (h < 1) return;
- begin_tft_write();
- setWindow(x, y, x, y + h - 1);
- pushBlock(color, h);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: drawFastHLine
- ** Description: draw a horizontal line
- ***************************************************************************************/
- void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
- {
- if (_vpOoB) return;
- x+= _xDatum;
- y+= _yDatum;
- // Clipping
- if ((y < _vpY) || (x >= _vpW) || (y >= _vpH)) return;
- if (x < _vpX) { w += x - _vpX; x = _vpX; }
- if ((x + w) > _vpW) w = _vpW - x;
- if (w < 1) return;
- begin_tft_write();
- setWindow(x, y, x + w - 1, y);
- pushBlock(color, w);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: fillRect
- ** Description: draw a filled rectangle
- ***************************************************************************************/
- void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
- {
- if (_vpOoB) return;
- x+= _xDatum;
- y+= _yDatum;
- // Clipping
- if ((x >= _vpW) || (y >= _vpH)) return;
- if (x < _vpX) { w += x - _vpX; x = _vpX; }
- if (y < _vpY) { h += y - _vpY; y = _vpY; }
- if ((x + w) > _vpW) w = _vpW - x;
- if ((y + h) > _vpH) h = _vpH - y;
- if ((w < 1) || (h < 1)) return;
- //Serial.print(" _xDatum=");Serial.print( _xDatum);Serial.print(", _yDatum=");Serial.print( _yDatum);
- //Serial.print(", _xWidth=");Serial.print(_xWidth);Serial.print(", _yHeight=");Serial.println(_yHeight);
- //Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
- //Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
- //Serial.print(" x=");Serial.print( y);Serial.print(", y=");Serial.print( y);
- //Serial.print(", w=");Serial.print(w);Serial.print(", h=");Serial.println(h);
- begin_tft_write();
- setWindow(x, y, x + w - 1, y + h - 1);
- pushBlock(color, w * h);
- end_tft_write();
- }
- /***************************************************************************************
- ** Function name: color565
- ** Description: convert three 8 bit RGB levels to a 16 bit colour value
- ***************************************************************************************/
- uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b)
- {
- return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
- }
- /***************************************************************************************
- ** Function name: color16to8
- ** Description: convert 16 bit colour to an 8 bit 332 RGB colour value
- ***************************************************************************************/
- uint8_t TFT_eSPI::color16to8(uint16_t c)
- {
- return ((c & 0xE000)>>8) | ((c & 0x0700)>>6) | ((c & 0x0018)>>3);
- }
- /***************************************************************************************
- ** Function name: color8to16
- ** Description: convert 8 bit colour to a 16 bit 565 colour value
- ***************************************************************************************/
- uint16_t TFT_eSPI::color8to16(uint8_t color)
- {
- uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table
- uint16_t color16 = 0;
- // =====Green===== ===============Red==============
- color16 = (color & 0x1C)<<6 | (color & 0xC0)<<5 | (color & 0xE0)<<8;
- // =====Green===== =======Blue======
- color16 |= (color & 0x1C)<<3 | blue[color & 0x03];
- return color16;
- }
- /***************************************************************************************
- ** Function name: color16to24
- ** Description: convert 16 bit colour to a 24 bit 888 colour value
- ***************************************************************************************/
- uint32_t TFT_eSPI::color16to24(uint16_t color565)
- {
- uint8_t r = (color565 >> 8) & 0xF8; r |= (r >> 5);
- uint8_t g = (color565 >> 3) & 0xFC; g |= (g >> 6);
- uint8_t b = (color565 << 3) & 0xF8; b |= (b >> 5);
- return ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b << 0);
- }
- /***************************************************************************************
- ** Function name: color24to16
- ** Description: convert 24 bit colour to a 16 bit 565 colour value
- ***************************************************************************************/
- uint32_t TFT_eSPI::color24to16(uint32_t color888)
- {
- uint16_t r = (color888 >> 8) & 0xF800;
- uint16_t g = (color888 >> 5) & 0x07E0;
- uint16_t b = (color888 >> 3) & 0x001F;
- return (r | g | b);
- }
- /***************************************************************************************
- ** Function name: invertDisplay
- ** Description: invert the display colours i = 1 invert, i = 0 normal
- ***************************************************************************************/
- void TFT_eSPI::invertDisplay(bool i)
- {
- begin_tft_write();
- // Send the command twice as otherwise it does not always work!
- writecommand(i ? TFT_INVON : TFT_INVOFF);
- writecommand(i ? TFT_INVON : TFT_INVOFF);
- end_tft_write();
- }
- /**************************************************************************
- ** Function name: setAttribute
- ** Description: Sets a control parameter of an attribute
- **************************************************************************/
- void TFT_eSPI::setAttribute(uint8_t attr_id, uint8_t param) {
- switch (attr_id) {
- break;
- case CP437_SWITCH:
- _cp437 = param;
- break;
- case UTF8_SWITCH:
- _utf8 = param;
- decoderState = 0;
- break;
- case PSRAM_ENABLE:
- #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT)
- if (psramFound()) _psram_enable = param; // Enable the use of PSRAM (if available)
- else
- #endif
- _psram_enable = false;
- break;
- //case 4: // TBD future feature control
- // _tbd = param;
- // break;
- }
- }
- /**************************************************************************
- ** Function name: getAttribute
- ** Description: Get value of an attribute (control parameter)
- **************************************************************************/
- uint8_t TFT_eSPI::getAttribute(uint8_t attr_id) {
- switch (attr_id) {
- case CP437_SWITCH: // ON/OFF control of full CP437 character set
- return _cp437;
- case UTF8_SWITCH: // ON/OFF control of UTF-8 decoding
- return _utf8;
- case PSRAM_ENABLE:
- return _psram_enable;
- //case 3: // TBD future feature control
- // return _tbd;
- // break;
- }
- return false;
- }
- /***************************************************************************************
- ** Function name: decodeUTF8
- ** Description: Serial UTF-8 decoder with fall-back to extended ASCII
- *************************************************************************************x*/
- uint16_t TFT_eSPI::decodeUTF8(uint8_t c)
- {
- if (!_utf8) return c;
- // 7 bit Unicode Code Point
- if ((c & 0x80) == 0x00) {
- decoderState = 0;
- return c;
- }
- if (decoderState == 0) {
- // 11 bit Unicode Code Point
- if ((c & 0xE0) == 0xC0) {
- decoderBuffer = ((c & 0x1F)<<6);
- decoderState = 1;
- return 0;
- }
- // 16 bit Unicode Code Point
- if ((c & 0xF0) == 0xE0) {
- decoderBuffer = ((c & 0x0F)<<12);
- decoderState = 2;
- return 0;
- }
- // 21 bit Unicode Code Point not supported so fall-back to extended ASCII
- // if ((c & 0xF8) == 0xF0) return c;
- }
- else {
- if (decoderState == 2) {
- decoderBuffer |= ((c & 0x3F)<<6);
- decoderState--;
- return 0;
- }
- else {
- decoderBuffer |= (c & 0x3F);
- decoderState = 0;
- return decoderBuffer;
- }
- }
- decoderState = 0;
- return c; // fall-back to extended ASCII
- }
- /***************************************************************************************
- ** Function name: decodeUTF8
- ** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII
- *************************************************************************************x*/
- uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
- {
- uint16_t c = buf[(*index)++];
- //Serial.print("Byte from string = 0x"); Serial.println(c, HEX);
- if (!_utf8) return c;
- // 7 bit Unicode
- if ((c & 0x80) == 0x00) return c;
- // 11 bit Unicode
- if (((c & 0xE0) == 0xC0) && (remaining > 1))
- return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F);
- // 16 bit Unicode
- if (((c & 0xF0) == 0xE0) && (remaining > 2)) {
- c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6);
- return c | ((buf[(*index)++]&0x3F));
- }
- // 21 bit Unicode not supported so fall-back to extended ASCII
- // if ((c & 0xF8) == 0xF0) return c;
- return c; // fall-back to extended ASCII
- }
- /***************************************************************************************
- ** Function name: alphaBlend
- ** Description: Blend 16bit foreground and background
- *************************************************************************************x*/
- uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc)
- {
- // For speed use fixed point maths and rounding to permit a power of 2 division
- uint16_t fgR = ((fgc >> 10) & 0x3E) + 1;
- uint16_t fgG = ((fgc >> 4) & 0x7E) + 1;
- uint16_t fgB = ((fgc << 1) & 0x3E) + 1;
- uint16_t bgR = ((bgc >> 10) & 0x3E) + 1;
- uint16_t bgG = ((bgc >> 4) & 0x7E) + 1;
- uint16_t bgB = ((bgc << 1) & 0x3E) + 1;
- // Shift right 1 to drop rounding bit and shift right 8 to divide by 256
- uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
- uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
- uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
- // Combine RGB565 colours into 16 bits
- //return ((r&0x18) << 11) | ((g&0x30) << 5) | ((b&0x18) << 0); // 2 bit greyscale
- //return ((r&0x1E) << 11) | ((g&0x3C) << 5) | ((b&0x1E) << 0); // 4 bit greyscale
- return (r << 11) | (g << 5) | (b << 0);
- }
- /***************************************************************************************
- ** Function name: alphaBlend
- ** Description: Blend 16bit foreground and background with dither
- *************************************************************************************x*/
- uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither)
- {
- if (dither) {
- int16_t alphaDither = (int16_t)alpha - dither + random(2*dither+1); // +/-4 randomised
- alpha = (uint8_t)alphaDither;
- if (alphaDither < 0) alpha = 0;
- if (alphaDither >255) alpha = 255;
- }
-
- return alphaBlend(alpha, fgc, bgc);
- }
- /***************************************************************************************
- ** Function name: alphaBlend
- ** Description: Blend 24bit foreground and background with optional dither
- *************************************************************************************x*/
- uint32_t TFT_eSPI::alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither)
- {
- if (dither) {
- int16_t alphaDither = (int16_t)alpha - dither + random(2*dither+1); // +/-dither randomised
- alpha = (uint8_t)alphaDither;
- if (alphaDither < 0) alpha = 0;
- if (alphaDither >255) alpha = 255;
- }
- // For speed use fixed point maths and rounding to permit a power of 2 division
- uint16_t fgR = ((fgc >> 15) & 0x1FE) + 1;
- uint16_t fgG = ((fgc >> 7) & 0x1FE) + 1;
- uint16_t fgB = ((fgc << 1) & 0x1FE) + 1;
- uint16_t bgR = ((bgc >> 15) & 0x1FE) + 1;
- uint16_t bgG = ((bgc >> 7) & 0x1FE) + 1;
- uint16_t bgB = ((bgc << 1) & 0x1FE) + 1;
- // Shift right 1 to drop rounding bit and shift right 8 to divide by 256
- uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9);
- uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9);
- uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9);
- // Combine RGB colours into 24 bits
- return (r << 16) | (g << 8) | (b << 0);
- }
- /***************************************************************************************
- ** Function name: write
- ** Description: draw characters piped through serial stream
- ***************************************************************************************/
- size_t TFT_eSPI::write(uint8_t utf8)
- {
- if (_vpOoB) return 1;
- uint16_t uniCode = decodeUTF8(utf8);
- if (!uniCode) return 1;
- if (utf8 == '\r') return 1;
- #ifdef SMOOTH_FONT
- if(fontLoaded) {
- if (uniCode < 32 && utf8 != '\n') return 1;
- drawGlyph(uniCode);
- return 1;
- }
- #endif
- if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors
- else if (uniCode < 32) return 1;
- uint16_t cwidth = 0;
- uint16_t cheight = 0;
- //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- //Serial.print((uint8_t) uniCode); // Debug line sends all printed TFT text to serial port
- //Serial.println(uniCode, HEX); // Debug line sends all printed TFT text to serial port
- //delay(5); // Debug optional wait for serial port to flush through
- //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- #ifdef LOAD_GFXFF
- if(!gfxFont) {
- #endif
- //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- #ifdef LOAD_FONT2
- if (textfont == 2) {
- if (uniCode > 127) return 1;
- cwidth = pgm_read_byte(widtbl_f16 + uniCode-32);
- cheight = chr_hgt_f16;
- // Font 2 is rendered in whole byte widths so we must allow for this
- cwidth = (cwidth + 6) / 8; // Width in whole bytes for font 2, should be + 7 but must allow for font width change
- cwidth = cwidth * 8; // Width converted back to pixels
- }
- #ifdef LOAD_RLE
- else
- #endif
- #endif
- #ifdef LOAD_RLE
- {
- if ((textfont>2) && (textfont<9)) {
- if (uniCode > 127) return 1;
- // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements
- cwidth = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 );
- cheight= pgm_read_byte( &fontdata[textfont].height );
- }
- }
- #endif
- #ifdef LOAD_GLCD
- if (textfont==1) {
- cwidth = 6;
- cheight = 8;
- }
- #else
- if (textfont==1) return 1;
- #endif
- cheight = cheight * textsize;
- if (utf8 == '\n') {
- cursor_y += cheight;
- cursor_x = 0;
- }
- else {
- if (textwrapX && (cursor_x + cwidth * textsize > width())) {
- cursor_y += cheight;
- cursor_x = 0;
- }
- if (textwrapY && (cursor_y >= (int32_t) height())) cursor_y = 0;
- cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
- }
- //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- #ifdef LOAD_GFXFF
- } // Custom GFX font
- else {
- if(utf8 == '\n') {
- cursor_x = 0;
- cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
- } else {
- if (uniCode > pgm_read_word(&gfxFont->last )) return 1;
- if (uniCode < pgm_read_word(&gfxFont->first)) return 1;
- uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
- uint8_t w = pgm_read_byte(&glyph->width),
- h = pgm_read_byte(&glyph->height);
- if((w > 0) && (h > 0)) { // Is there an associated bitmap?
- int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset);
- if(textwrapX && ((cursor_x + textsize * (xo + w)) > width())) {
- // Drawing character would go off right edge; wrap to new line
- cursor_x = 0;
- cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
- }
- if (textwrapY && (cursor_y >= (int32_t) height())) cursor_y = 0;
- drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize);
- }
- cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
- }
- }
- #endif // LOAD_GFXFF
- //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- return 1;
- }
- /***************************************************************************************
- ** Function name: drawChar
- ** Description: draw a Unicode glyph onto the screen
- ***************************************************************************************/
- // TODO: Rationalise with TFT_eSprite
- // Any UTF-8 decoding must be done before calling drawChar()
- int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y)
- {
- return drawChar(uniCode, x, y, textfont);
- }
- // Any UTF-8 decoding must be done before calling drawChar()
- int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
- {
- if (_vpOoB || !uniCode) return 0;
- if (font==1) {
- #ifdef LOAD_GLCD
- #ifndef LOAD_GFXFF
- drawChar(x, y, uniCode, textcolor, textbgcolor, textsize);
- return 6 * textsize;
- #endif
- #else
- #ifndef LOAD_GFXFF
- return 0;
- #endif
- #endif
- #ifdef LOAD_GFXFF
- drawChar(x, y, uniCode, textcolor, textbgcolor, textsize);
- if(!gfxFont) { // 'Classic' built-in font
- #ifdef LOAD_GLCD
- return 6 * textsize;
- #else
- return 0;
- #endif
- }
- else {
- if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) )) {
- uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first);
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
- return pgm_read_byte(&glyph->xAdvance) * textsize;
- }
- else {
- return 0;
- }
- }
- #endif
- }
- if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0;
- int32_t width = 0;
- int32_t height = 0;
- uint32_t flash_address = 0;
- uniCode -= 32;
- #ifdef LOAD_FONT2
- if (font == 2) {
- flash_address = pgm_read_dword(&chrtbl_f16[uniCode]);
- width = pgm_read_byte(widtbl_f16 + uniCode);
- height = chr_hgt_f16;
- }
- #ifdef LOAD_RLE
- else
- #endif
- #endif
- #ifdef LOAD_RLE
- {
- if ((font>2) && (font<9)) {
- flash_address = pgm_read_dword( (const void*)(pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *)) );
- width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode );
- height= pgm_read_byte( &fontdata[font].height );
- }
- }
- #endif
- int32_t xd = x + _xDatum;
- int32_t yd = y + _yDatum;
- if ((xd + width * textsize < _vpX || xd >= _vpW) && (yd + height * textsize < _vpY || yd >= _vpH)) return width * textsize ;
- int32_t w = width;
- int32_t pX = 0;
- int32_t pY = y;
- uint8_t line = 0;
- bool clip = xd < _vpX || xd + width * textsize >= _vpW || yd < _vpY || yd + height * textsize >= _vpH;
- #ifdef LOAD_FONT2 // chop out code if we do not need it
- if (font == 2) {
- w = w + 6; // Should be + 7 but we need to compensate for width increment
- w = w / 8;
- if (textcolor == textbgcolor || textsize != 1 || clip) {
- //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
- inTransaction = true;
- for (int32_t i = 0; i < height; i++) {
- if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor);
- for (int32_t k = 0; k < w; k++) {
- line = pgm_read_byte((uint8_t *)flash_address + w * i + k);
- if (line) {
- if (textsize == 1) {
- pX = x + k * 8;
- if (line & 0x80) drawPixel(pX, pY, textcolor);
- if (line & 0x40) drawPixel(pX + 1, pY, textcolor);
- if (line & 0x20) drawPixel(pX + 2, pY, textcolor);
- if (line & 0x10) drawPixel(pX + 3, pY, textcolor);
- if (line & 0x08) drawPixel(pX + 4, pY, textcolor);
- if (line & 0x04) drawPixel(pX + 5, pY, textcolor);
- if (line & 0x02) drawPixel(pX + 6, pY, textcolor);
- if (line & 0x01) drawPixel(pX + 7, pY, textcolor);
- }
- else {
- pX = x + k * 8 * textsize;
- if (line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor);
- if (line & 0x40) fillRect(pX + textsize, pY, textsize, textsize, textcolor);
- if (line & 0x20) fillRect(pX + 2 * textsize, pY, textsize, textsize, textcolor);
- if (line & 0x10) fillRect(pX + 3 * textsize, pY, textsize, textsize, textcolor);
- if (line & 0x08) fillRect(pX + 4 * textsize, pY, textsize, textsize, textcolor);
- if (line & 0x04) fillRect(pX + 5 * textsize, pY, textsize, textsize, textcolor);
- if (line & 0x02) fillRect(pX + 6 * textsize, pY, textsize, textsize, textcolor);
- if (line & 0x01) fillRect(pX + 7 * textsize, pY, textsize, textsize, textcolor);
- }
- }
- }
- pY += textsize;
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- else { // Faster drawing of characters and background using block write
- begin_tft_write();
- setWindow(xd, yd, xd + width - 1, yd + height - 1);
- uint8_t mask;
- for (int32_t i = 0; i < height; i++) {
- pX = width;
- for (int32_t k = 0; k < w; k++) {
- line = pgm_read_byte((uint8_t *) (flash_address + w * i + k) );
- mask = 0x80;
- while (mask && pX) {
- if (line & mask) {tft_Write_16(textcolor);}
- else {tft_Write_16(textbgcolor);}
- pX--;
- mask = mask >> 1;
- }
- }
- if (pX) {tft_Write_16(textbgcolor);}
- }
- end_tft_write();
- }
- }
- #ifdef LOAD_RLE
- else
- #endif
- #endif //FONT2
- #ifdef LOAD_RLE //674 bytes of code
- // Font is not 2 and hence is RLE encoded
- {
- begin_tft_write();
- inTransaction = true;
- w *= height; // Now w is total number of pixels in the character
- if (textcolor == textbgcolor && !clip) {
-
- int32_t px = 0, py = pY; // To hold character block start and end column and row values
- int32_t pc = 0; // Pixel count
- uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel
- uint8_t tnp = 0; // Temporary copy of np for while loop
- uint8_t ts = textsize - 1; // Temporary copy of textsize
- // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area
- // w is total number of pixels to plot to fill character block
- while (pc < w) {
- line = pgm_read_byte((uint8_t *)flash_address);
- flash_address++;
- if (line & 0x80) {
- line &= 0x7F;
- line++;
- if (ts) {
- px = xd + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow
- py = yd + textsize * (pc / width);
- }
- else {
- px = xd + pc % width; // Keep these px and py calculations outside the loop as they are slow
- py = yd + pc / width;
- }
- while (line--) { // In this case the while(line--) is faster
- pc++; // This is faster than putting pc+=line before while()?
- setWindow(px, py, px + ts, py + ts);
- if (ts) {
- tnp = np;
- while (tnp--) {tft_Write_16(textcolor);}
- }
- else {tft_Write_16(textcolor);}
- px += textsize;
- if (px >= (xd + width * textsize)) {
- px = xd;
- py += textsize;
- }
- }
- }
- else {
- line++;
- pc += line;
- }
- }
- }
- else {
- // Text colour != background and textsize = 1 and character is within viewport area
- // so use faster drawing of characters and background using block write
- if (textcolor != textbgcolor && textsize == 1 && !clip)
- {
- setWindow(xd, yd, xd + width - 1, yd + height - 1);
- // Maximum font size is equivalent to 180x180 pixels in area
- while (w > 0) {
- line = pgm_read_byte((uint8_t *)flash_address++); // 8 bytes smaller when incrementing here
- if (line & 0x80) {
- line &= 0x7F;
- line++; w -= line;
- pushBlock(textcolor,line);
- }
- else {
- line++; w -= line;
- pushBlock(textbgcolor,line);
- }
- }
- }
- else
- {
- int32_t px = 0, py = 0; // To hold character pixel coords
- int32_t tx = 0, ty = 0; // To hold character TFT pixel coords
- int32_t pc = 0; // Pixel count
- int32_t pl = 0; // Pixel line length
- uint16_t pcol = 0; // Pixel color
- bool pf = true; // Flag for plotting
- while (pc < w) {
- line = pgm_read_byte((uint8_t *)flash_address);
- flash_address++;
- if (line & 0x80) { pcol = textcolor; line &= 0x7F; pf = true;}
- else { pcol = textbgcolor; if (textcolor == textbgcolor) pf = false;}
- line++;
- px = pc % width;
- tx = x + textsize * px;
- py = pc / width;
- ty = y + textsize * py;
- pl = 0;
- pc += line;
- while (line--) {
- pl++;
- if ((px+pl) >= width) {
- if (pf) fillRect(tx, ty, pl * textsize, textsize, pcol);
- pl = 0;
- px = 0;
- tx = x;
- py ++;
- ty += textsize;
- }
- }
- if (pl && pf) fillRect(tx, ty, pl * textsize, textsize, pcol);
- }
- }
- }
- inTransaction = lockTransaction;
- end_tft_write();
- }
- // End of RLE font rendering
- #endif
- return width * textsize; // x +
- }
- /***************************************************************************************
- ** Function name: drawString (with or without user defined font)
- ** Description : draw string with padding if it is defined
- ***************************************************************************************/
- // Without font number, uses font set by setTextFont()
- int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY)
- {
- int16_t len = string.length() + 2;
- char buffer[len];
- string.toCharArray(buffer, len);
- return drawString(buffer, poX, poY, textfont);
- }
- // With font number
- int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uint8_t font)
- {
- int16_t len = string.length() + 2;
- char buffer[len];
- string.toCharArray(buffer, len);
- return drawString(buffer, poX, poY, font);
- }
- // Without font number, uses font set by setTextFont()
- int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY)
- {
- return drawString(string, poX, poY, textfont);
- }
- // With font number. Note: font number is over-ridden if a smooth font is loaded
- int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font)
- {
- int16_t sumX = 0;
- uint8_t padding = 1, baseline = 0;
- uint16_t cwidth = textWidth(string, font); // Find the pixel width of the string in the font
- uint16_t cheight = 8 * textsize;
- #ifdef LOAD_GFXFF
- #ifdef SMOOTH_FONT
- bool freeFont = (font == 1 && gfxFont && !fontLoaded);
- #else
- bool freeFont = (font == 1 && gfxFont);
- #endif
- if (freeFont) {
- cheight = glyph_ab * textsize;
- poY += cheight; // Adjust for baseline datum of free fonts
- baseline = cheight;
- padding =101; // Different padding method used for Free Fonts
- // We need to make an adjustment for the bottom of the string (eg 'y' character)
- if ((textdatum == BL_DATUM) || (textdatum == BC_DATUM) || (textdatum == BR_DATUM)) {
- cheight += glyph_bb * textsize;
- }
- }
- #endif
- // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font
- #ifdef SMOOTH_FONT
- if(fontLoaded) {
- baseline = gFont.maxAscent;
- cheight = fontHeight();
- }
- else
- #endif
- if (font!=1) {
- baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize;
- cheight = fontHeight(font);
- }
- if (textdatum || padX) {
- switch(textdatum) {
- case TC_DATUM:
- poX -= cwidth/2;
- padding += 1;
- break;
- case TR_DATUM:
- poX -= cwidth;
- padding += 2;
- break;
- case ML_DATUM:
- poY -= cheight/2;
- //padding += 0;
- break;
- case MC_DATUM:
- poX -= cwidth/2;
- poY -= cheight/2;
- padding += 1;
- break;
- case MR_DATUM:
- poX -= cwidth;
- poY -= cheight/2;
- padding += 2;
- break;
- case BL_DATUM:
- poY -= cheight;
- //padding += 0;
- break;
- case BC_DATUM:
- poX -= cwidth/2;
- poY -= cheight;
- padding += 1;
- break;
- case BR_DATUM:
- poX -= cwidth;
- poY -= cheight;
- padding += 2;
- break;
- case L_BASELINE:
- poY -= baseline;
- //padding += 0;
- break;
- case C_BASELINE:
- poX -= cwidth/2;
- poY -= baseline;
- padding += 1;
- break;
- case R_BASELINE:
- poX -= cwidth;
- poY -= baseline;
- padding += 2;
- break;
- }
- }
- int8_t xo = 0;
- #ifdef LOAD_GFXFF
- if (freeFont && (textcolor!=textbgcolor)) {
- cheight = (glyph_ab + glyph_bb) * textsize;
- // Get the offset for the first character only to allow for negative offsets
- uint16_t c2 = 0;
- uint16_t len = strlen(string);
- uint16_t n = 0;
- while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n);
- if((c2 >= pgm_read_word(&gfxFont->first)) && (c2 <= pgm_read_word(&gfxFont->last) )) {
- c2 -= pgm_read_word(&gfxFont->first);
- GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]);
- xo = pgm_read_byte(&glyph->xOffset) * textsize;
- // Adjust for negative xOffset
- if (xo > 0) xo = 0;
- else cwidth -= xo;
- // Add 1 pixel of padding all round
- //cheight +=2;
- //fillRect(poX+xo-1, poY - 1 - glyph_ab * textsize, cwidth+2, cheight, textbgcolor);
- fillRect(poX+xo, poY - glyph_ab * textsize, cwidth, cheight, textbgcolor);
- }
- padding -=100;
- }
- #endif
- uint16_t len = strlen(string);
- uint16_t n = 0;
- #ifdef SMOOTH_FONT
- if(fontLoaded) {
- if (textcolor!=textbgcolor) fillRect(poX, poY, cwidth, cheight, textbgcolor);
- /*
- // The above only works for a single text line, not if the text is going to wrap...
- // So need to use code like this in a while loop to fix it:
- if (textwrapX && (cursor_x + width * textsize > width())) {
- cursor_y += height;
- cursor_x = 0;
- }
- if (textwrapY && (cursor_y >= (int32_t)height())) cursor_y = 0;
- cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
- */
- setCursor(poX, poY);
- while (n < len) {
- uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
- drawGlyph(uniCode);
- }
- sumX += cwidth;
- //fontFile.close();
- }
- else
- #endif
- {
- while (n < len) {
- uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n);
- sumX += drawChar(uniCode, poX+sumX, poY, font);
- }
- }
- //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- // Switch on debugging for the padding areas
- //#define PADDING_DEBUG
- #ifndef PADDING_DEBUG
- //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- if((padX>cwidth) && (textcolor!=textbgcolor)) {
- int16_t padXc = poX+cwidth+xo;
- #ifdef LOAD_GFXFF
- if (freeFont) {
- poX +=xo; // Adjust for negative offset start character
- poY -= glyph_ab * textsize;
- sumX += poX;
- }
- #endif
- switch(padding) {
- case 1:
- fillRect(padXc,poY,padX-cwidth,cheight, textbgcolor);
- break;
- case 2:
- fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
- padXc = poX - ((padX-cwidth)>>1);
- fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
- break;
- case 3:
- if (padXc>padX) padXc = padX;
- fillRect(poX + cwidth - padXc,poY,padXc-cwidth,cheight, textbgcolor);
- break;
- }
- }
- #else
- //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- // This is debug code to show text (green box) and blanked (white box) areas
- // It shows that the padding areas are being correctly sized and positioned
- if((padX>sumX) && (textcolor!=textbgcolor)) {
- int16_t padXc = poX+sumX; // Maximum left side padding
- #ifdef LOAD_GFXFF
- if ((font == 1) && (gfxFont)) poY -= glyph_ab;
- #endif
- drawRect(poX,poY,sumX,cheight, TFT_GREEN);
- switch(padding) {
- case 1:
- drawRect(padXc,poY,padX-sumX,cheight, TFT_WHITE);
- break;
- case 2:
- drawRect(padXc,poY,(padX-sumX)>>1, cheight, TFT_WHITE);
- padXc = (padX-sumX)>>1;
- drawRect(poX - padXc,poY,(padX-sumX)>>1,cheight, TFT_WHITE);
- break;
- case 3:
- if (padXc>padX) padXc = padX;
- drawRect(poX + sumX - padXc,poY,padXc-sumX,cheight, TFT_WHITE);
- break;
- }
- }
- #endif
- //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- return sumX;
- }
- /***************************************************************************************
- ** Function name: drawCentreString (deprecated, use setTextDatum())
- ** Descriptions: draw string centred on dX
- ***************************************************************************************/
- int16_t TFT_eSPI::drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font)
- {
- int16_t len = string.length() + 2;
- char buffer[len];
- string.toCharArray(buffer, len);
- return drawCentreString(buffer, dX, poY, font);
- }
- int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font)
- {
- uint8_t tempdatum = textdatum;
- int32_t sumX = 0;
- textdatum = TC_DATUM;
- sumX = drawString(string, dX, poY, font);
- textdatum = tempdatum;
- return sumX;
- }
- /***************************************************************************************
- ** Function name: drawRightString (deprecated, use setTextDatum())
- ** Descriptions: draw string right justified to dX
- ***************************************************************************************/
- int16_t TFT_eSPI::drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font)
- {
- int16_t len = string.length() + 2;
- char buffer[len];
- string.toCharArray(buffer, len);
- return drawRightString(buffer, dX, poY, font);
- }
- int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font)
- {
- uint8_t tempdatum = textdatum;
- int16_t sumX = 0;
- textdatum = TR_DATUM;
- sumX = drawString(string, dX, poY, font);
- textdatum = tempdatum;
- return sumX;
- }
- /***************************************************************************************
- ** Function name: drawNumber
- ** Description: draw a long integer
- ***************************************************************************************/
- int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY)
- {
- isDigits = true; // Eliminate jiggle in monospaced fonts
- char str[12];
- ltoa(long_num, str, 10);
- return drawString(str, poX, poY, textfont);
- }
- int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font)
- {
- isDigits = true; // Eliminate jiggle in monospaced fonts
- char str[12];
- ltoa(long_num, str, 10);
- return drawString(str, poX, poY, font);
- }
- /***************************************************************************************
- ** Function name: drawFloat
- ** Descriptions: drawFloat, prints 7 non zero digits maximum
- ***************************************************************************************/
- // Assemble and print a string, this permits alignment relative to a datum
- // looks complicated but much more compact and actually faster than using print class
- int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY)
- {
- return drawFloat(floatNumber, dp, poX, poY, textfont);
- }
- int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY, uint8_t font)
- {
- isDigits = true;
- char str[14]; // Array to contain decimal string
- uint8_t ptr = 0; // Initialise pointer for array
- int8_t digits = 1; // Count the digits to avoid array overflow
- float rounding = 0.5; // Round up down delta
- if (dp > 7) dp = 7; // Limit the size of decimal portion
- // Adjust the rounding value
- for (uint8_t i = 0; i < dp; ++i) rounding /= 10.0;
- if (floatNumber < -rounding) { // add sign, avoid adding - sign to 0.0!
- str[ptr++] = '-'; // Negative number
- str[ptr] = 0; // Put a null in the array as a precaution
- digits = 0; // Set digits to 0 to compensate so pointer value can be used later
- floatNumber = -floatNumber; // Make positive
- }
- floatNumber += rounding; // Round up or down
- // For error put ... in string and return (all TFT_eSPI library fonts contain . character)
- if (floatNumber >= 2147483647) {
- strcpy(str, "...");
- return drawString(str, poX, poY, font);
- }
- // No chance of overflow from here on
- // Get integer part
- uint32_t temp = (uint32_t)floatNumber;
- // Put integer part into array
- ltoa(temp, str + ptr, 10);
- // Find out where the null is to get the digit count loaded
- while ((uint8_t)str[ptr] != 0) ptr++; // Move the pointer along
- digits += ptr; // Count the digits
- str[ptr++] = '.'; // Add decimal point
- str[ptr] = '0'; // Add a dummy zero
- str[ptr + 1] = 0; // Add a null but don't increment pointer so it can be overwritten
- // Get the decimal portion
- floatNumber = floatNumber - temp;
- // Get decimal digits one by one and put in array
- // Limit digit count so we don't get a false sense of resolution
- uint8_t i = 0;
- while ((i < dp) && (digits < 9)) { // while (i < dp) for no limit but array size must be increased
- i++;
- floatNumber *= 10; // for the next decimal
- temp = floatNumber; // get the decimal
- ltoa(temp, str + ptr, 10);
- ptr++; digits++; // Increment pointer and digits count
- floatNumber -= temp; // Remove that digit
- }
- // Finally we can plot the string and return pixel length
- return drawString(str, poX, poY, font);
- }
- /***************************************************************************************
- ** Function name: setFreeFont
- ** Descriptions: Sets the GFX free font to use
- ***************************************************************************************/
- #ifdef LOAD_GFXFF
- void TFT_eSPI::setFreeFont(const GFXfont *f)
- {
- if (f == nullptr) { // Fix issue #400 (ESP32 crash)
- setTextFont(1); // Use GLCD font
- return;
- }
- textfont = 1;
- gfxFont = (GFXfont *)f;
- glyph_ab = 0;
- glyph_bb = 0;
- uint16_t numChars = pgm_read_word(&gfxFont->last) - pgm_read_word(&gfxFont->first);
- // Find the biggest above and below baseline offsets
- for (uint8_t c = 0; c < numChars; c++) {
- GFXglyph *glyph1 = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]);
- int8_t ab = -pgm_read_byte(&glyph1->yOffset);
- if (ab > glyph_ab) glyph_ab = ab;
- int8_t bb = pgm_read_byte(&glyph1->height) - ab;
- if (bb > glyph_bb) glyph_bb = bb;
- }
- }
- /***************************************************************************************
- ** Function name: setTextFont
- ** Description: Set the font for the print stream
- ***************************************************************************************/
- void TFT_eSPI::setTextFont(uint8_t f)
- {
- textfont = (f > 0) ? f : 1; // Don't allow font 0
- gfxFont = NULL;
- }
- #else
- /***************************************************************************************
- ** Function name: setFreeFont
- ** Descriptions: Sets the GFX free font to use
- ***************************************************************************************/
- // Alternative to setTextFont() so we don't need two different named functions
- void TFT_eSPI::setFreeFont(uint8_t font)
- {
- setTextFont(font);
- }
- /***************************************************************************************
- ** Function name: setTextFont
- ** Description: Set the font for the print stream
- ***************************************************************************************/
- void TFT_eSPI::setTextFont(uint8_t f)
- {
- textfont = (f > 0) ? f : 1; // Don't allow font 0
- }
- #endif
- /***************************************************************************************
- ** Function name: getSPIinstance
- ** Description: Get the instance of the SPI class
- ***************************************************************************************/
- #if !defined (TFT_PARALLEL_8_BIT)
- SPIClass& TFT_eSPI::getSPIinstance(void)
- {
- return spi;
- }
- #endif
- /***************************************************************************************
- ** Function name: getSetup
- ** Description: Get the setup details for diagnostic and sketch access
- ***************************************************************************************/
- void TFT_eSPI::getSetup(setup_t &tft_settings)
- {
- // tft_settings.version is set in header file
- #if defined (PROCESSOR_ID)
- tft_settings.esp = PROCESSOR_ID;
- #else
- tft_settings.esp = -1;
- #endif
- #if defined (SUPPORT_TRANSACTIONS)
- tft_settings.trans = true;
- #else
- tft_settings.trans = false;
- #endif
- #if defined (TFT_PARALLEL_8_BIT)
- tft_settings.serial = false;
- tft_settings.tft_spi_freq = 0;
- #else
- tft_settings.serial = true;
- tft_settings.tft_spi_freq = SPI_FREQUENCY/100000;
- #ifdef SPI_READ_FREQUENCY
- tft_settings.tft_rd_freq = SPI_READ_FREQUENCY/100000;
- #endif
- #endif
- #if defined(TFT_SPI_OVERLAP)
- tft_settings.overlap = true;
- #else
- tft_settings.overlap = false;
- #endif
- tft_settings.tft_driver = TFT_DRIVER;
- tft_settings.tft_width = _init_width;
- tft_settings.tft_height = _init_height;
- #ifdef CGRAM_OFFSET
- tft_settings.r0_x_offset = colstart;
- tft_settings.r0_y_offset = rowstart;
- tft_settings.r1_x_offset = 0;
- tft_settings.r1_y_offset = 0;
- tft_settings.r2_x_offset = 0;
- tft_settings.r2_y_offset = 0;
- tft_settings.r3_x_offset = 0;
- tft_settings.r3_y_offset = 0;
- #else
- tft_settings.r0_x_offset = 0;
- tft_settings.r0_y_offset = 0;
- tft_settings.r1_x_offset = 0;
- tft_settings.r1_y_offset = 0;
- tft_settings.r2_x_offset = 0;
- tft_settings.r2_y_offset = 0;
- tft_settings.r3_x_offset = 0;
- tft_settings.r3_y_offset = 0;
- #endif
- #if defined (TFT_MOSI)
- tft_settings.pin_tft_mosi = TFT_MOSI;
- #else
- tft_settings.pin_tft_mosi = -1;
- #endif
- #if defined (TFT_MISO)
- tft_settings.pin_tft_miso = TFT_MISO;
- #else
- tft_settings.pin_tft_miso = -1;
- #endif
- #if defined (TFT_SCLK)
- tft_settings.pin_tft_clk = TFT_SCLK;
- #else
- tft_settings.pin_tft_clk = -1;
- #endif
- #if defined (TFT_CS)
- tft_settings.pin_tft_cs = TFT_CS;
- #else
- tft_settings.pin_tft_cs = -1;
- #endif
- #if defined (TFT_DC)
- tft_settings.pin_tft_dc = TFT_DC;
- #else
- tft_settings.pin_tft_dc = -1;
- #endif
- #if defined (TFT_RD)
- tft_settings.pin_tft_rd = TFT_RD;
- #else
- tft_settings.pin_tft_rd = -1;
- #endif
- #if defined (TFT_WR)
- tft_settings.pin_tft_wr = TFT_WR;
- #else
- tft_settings.pin_tft_wr = -1;
- #endif
- #if defined (TFT_RST)
- tft_settings.pin_tft_rst = TFT_RST;
- #else
- tft_settings.pin_tft_rst = -1;
- #endif
- #if defined (TFT_PARALLEL_8_BIT)
- tft_settings.pin_tft_d0 = TFT_D0;
- tft_settings.pin_tft_d1 = TFT_D1;
- tft_settings.pin_tft_d2 = TFT_D2;
- tft_settings.pin_tft_d3 = TFT_D3;
- tft_settings.pin_tft_d4 = TFT_D4;
- tft_settings.pin_tft_d5 = TFT_D5;
- tft_settings.pin_tft_d6 = TFT_D6;
- tft_settings.pin_tft_d7 = TFT_D7;
- #else
- tft_settings.pin_tft_d0 = -1;
- tft_settings.pin_tft_d1 = -1;
- tft_settings.pin_tft_d2 = -1;
- tft_settings.pin_tft_d3 = -1;
- tft_settings.pin_tft_d4 = -1;
- tft_settings.pin_tft_d5 = -1;
- tft_settings.pin_tft_d6 = -1;
- tft_settings.pin_tft_d7 = -1;
- #endif
- #if defined (TFT_BL)
- tft_settings.pin_tft_led = TFT_BL;
- #endif
- #if defined (TFT_BACKLIGHT_ON)
- tft_settings.pin_tft_led_on = TFT_BACKLIGHT_ON;
- #endif
- #if defined (TOUCH_CS)
- tft_settings.pin_tch_cs = TOUCH_CS;
- tft_settings.tch_spi_freq = SPI_TOUCH_FREQUENCY/100000;
- #else
- tft_settings.pin_tch_cs = -1;
- tft_settings.tch_spi_freq = 0;
- #endif
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- #ifdef TOUCH_CS
- #include "Extensions/Touch.cpp"
- #include "Extensions/Button.cpp"
- #endif
- #include "Extensions/Sprite.cpp"
- #ifdef SMOOTH_FONT
- #include "Extensions/Smooth_font.cpp"
- #endif
- ////////////////////////////////////////////////////////////////////////////////////////
|