From 3124b2917643b6097054e75fe4cda2df0e675eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Mon, 14 Nov 2022 00:59:26 +0100 Subject: [PATCH] git rm --cached lib/libssd1306/bld/ --- Makefile | 2 +- lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o | Bin 7092 -> 7104 bytes .../bld/intf/i2c/ssd1306_i2c_embedded.o | Bin 20104 -> 20116 bytes lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o | Bin 16548 -> 16560 bytes lib/libssd1306/bld/intf/spi/ssd1306_spi.o | Bin 5916 -> 5928 bytes lib/libssd1306/bld/intf/spi/ssd1306_spi_avr.o | Bin 16720 -> 16732 bytes lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o | Bin 2196 -> 2208 bytes lib/libssd1306/bld/intf/ssd1306_interface.o | Bin 8680 -> 8692 bytes .../bld/intf/uart/ssd1306_uart_builtin.o | Bin 10360 -> 10372 bytes .../bld/intf/vga/atmega328p/vga128x64.o | Bin 28540 -> 28552 bytes .../bld/intf/vga/atmega328p/vga96x40.o | Bin 33624 -> 33636 bytes .../bld/intf/vga/esp32/CompositeOutput.o | Bin 2304 -> 2316 bytes lib/libssd1306/bld/intf/vga/esp32/vga128x64.o | Bin 2540 -> 2552 bytes lib/libssd1306/bld/intf/vga/vga.o | Bin 3256 -> 3268 bytes lib/libssd1306/bld/lcd/lcd_common.o | Bin 23528 -> 23540 bytes lib/libssd1306/bld/lcd/lcd_il9163.o | Bin 51224 -> 51236 bytes lib/libssd1306/bld/lcd/lcd_ili9341.o | Bin 38508 -> 38520 bytes lib/libssd1306/bld/lcd/lcd_pcd8544.o | Bin 15596 -> 15608 bytes lib/libssd1306/bld/lcd/oled_sh1106.o | Bin 17052 -> 17064 bytes lib/libssd1306/bld/lcd/oled_ssd1306.o | Bin 32172 -> 32184 bytes lib/libssd1306/bld/lcd/oled_ssd1325.o | Bin 25464 -> 25476 bytes lib/libssd1306/bld/lcd/oled_ssd1327.o | Bin 26560 -> 26572 bytes lib/libssd1306/bld/lcd/oled_ssd1331.o | Bin 46700 -> 46712 bytes lib/libssd1306/bld/lcd/oled_ssd1351.o | Bin 32348 -> 32360 bytes lib/libssd1306/bld/lcd/oled_template.o | Bin 22540 -> 22552 bytes lib/libssd1306/bld/lcd/vga_monitor.o | Bin 20376 -> 20388 bytes lib/libssd1306/bld/libssd1306.a | Bin 1573852 -> 1574372 bytes lib/libssd1306/bld/nano_engine/canvas.o | Bin 377256 -> 377268 bytes lib/libssd1306/bld/nano_engine/core.o | Bin 23308 -> 23320 bytes lib/libssd1306/bld/nano_gfx.o | Bin 107164 -> 107176 bytes lib/libssd1306/bld/sprite_pool.o | Bin 36140 -> 36152 bytes lib/libssd1306/bld/ssd1306_16bit.o | Bin 62876 -> 62888 bytes lib/libssd1306/bld/ssd1306_1bit.o | Bin 195580 -> 195592 bytes lib/libssd1306/bld/ssd1306_8bit.o | Bin 62976 -> 62988 bytes lib/libssd1306/bld/ssd1306_console.o | Bin 15248 -> 15260 bytes lib/libssd1306/bld/ssd1306_fonts.o | Bin 16688 -> 16700 bytes lib/libssd1306/bld/ssd1306_generic.o | Bin 64856 -> 64868 bytes .../bld/ssd1306_hal/arduino/platform.o | Bin 2292 -> 2304 bytes lib/libssd1306/bld/ssd1306_hal/avr/platform.o | Bin 11416 -> 11428 bytes .../bld/ssd1306_hal/energia/platform.o | Bin 2292 -> 2304 bytes .../bld/ssd1306_hal/linux/platform.o | Bin 1124 -> 1132 bytes .../bld/ssd1306_hal/mingw/platform.o | Bin 1124 -> 1132 bytes .../bld/ssd1306_hal/stm32/platform.o | Bin 2192 -> 2204 bytes .../bld/ssd1306_hal/template/platform.o | Bin 2200 -> 2212 bytes lib/libssd1306/bld/ssd1306_menu.o | Bin 51752 -> 51764 bytes lib/libssd1306/bld/ssd1306_uart.o | Bin 10932 -> 10944 bytes src/framebuffer.c | 361 +++++++++--------- src/framebuffer.h | 63 ++- src/framebuffer_config.h | 6 + 49 files changed, 254 insertions(+), 178 deletions(-) diff --git a/Makefile b/Makefile index 8e29944..c00d65f 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ size: $(TARGET).elf # Build the display library lib/libssd1306/bld/libssd1306.a: - $(MAKE) -C lib/libssd1306/ -f Makefile.avr MCU=atmega328p + $(MAKE) -C lib/libssd1306/src/ -f Makefile.avr MCU=atmega328p $(TARGET).elf: $(OBJECTS) lib/libssd1306/bld/libssd1306.a | $(BUILD_DIR) $(LD) $(CFLAGS) $(LFLAGS) -o $@ $^ lib/libssd1306/bld/libssd1306.a diff --git a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o index 669f4b21e66b1b931de826968f8a87565db63d41..eccac94b377eed82fcfcaf05b543e5e05668e0e2 100644 GIT binary patch delta 241 zcmdmDe!zT!0;9!7MK5-?^wiAs)S}7x?4r#2#YL0-*=3M~Sb##wn|H96@OTC?FfgbA zF{3^MLpPAtg0iOoX%i@WDUh~=vNr>1J1F}gkamW$Pi-z0>1SqKGnrMwpYh1#P#}3{ z@=_rAW%5^va>kU&xsv{jJ0|Z1l01`nrTiHUCdWzz1J!JlQf3w7U|Z}QT3=CeAFG>hc?vWN?6%YeDd9tFUFaVK6IZXfn delta 227 zcmX?LzQufk0;A4GMK5-ilGNgo$%X8qlLOeL;hfD!*h_dky%`u7)PR^#pMjwsNNYja z9YERy%AN_NEurk?K-vz<-U_6hq3nH|8%6q=85c|zl<;TVF*y-PUYNWQNWPfNC|S-J zF}YIGpK;CPlR%PTvZRzhqsrt=sbHX*y;91IT$3M4sWU1}=9E@voH5xDNR~{F1d<_> T8>Q7HSj2!%WCYp+1u!N6>VhuA diff --git a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_embedded.o b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_embedded.o index df7463c1935f470736ce305fb2312bfb088ff121..b4fa735bea1232fedc2f812bbef0400a91ee7f96 100644 GIT binary patch delta 325 zcmeB}%Q$5&;{*l9nvII_Lh|XUndzxT`pE@F`C0lonMojAT%2NPY+$BeT$DU{rjRrt zHJi^0eb%avVqjoU17gP03=C6%v=)>-7f9@lbdnQWKU0j#wC+y0?8ATUjj*o$(CN_ zjCVF~^b%)ebeVk8yPS!`X0nryA5eaxk3VC|Hxwt=$u18GMn`x=mTgRTa|H;@j1vRN1z7@|OI9v}e( ziA)Tez3n);87E8*_4H?)F?lJF+%x$rkTjX>>Q&BoVe?)uaYjaq$ydG0nf_Q$_Ve)r z%Fp%jXN;Kq7D(=xZ0j4$C^31WuQFrYRj^HXEwnH=h; O&RPR>+{ej`KEeP2Ge@QX diff --git a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o index f6ab8fb0e377bce9d7a76eced3e411fa1a264f7f..58668b715d26ea3b920d6ff393dd6b4ecc8a76ae 100644 GIT binary patch delta 266 zcmZ3|$he`Aae@NljE#zJ{A}r|ndzxTljrk`vgj8VB~NbPmqr)cyoLXVLTD%h1A`h6 zGj3*J=m*kTQ1%QUtp{bV1kx5z_68tr3uPYy(oRtJ6(H>nW#8S*Xqe2!xL|UswLjyX z$yBIwKo2Yb0(j)na_A&a;|MTnf#jFTv3CB936s|XNtelgf#inC zzV^Y4A15!gS7ucfU|nFT2X)pJKo`E7 IENCYT0HrcYjsO4v delta 293 zcmdnc$hf4Dae@M4&qhTze#w&5;u8Jjf};E^{hZ7s5H2oGF*G(Xo9x3cjazo}0sbEf zq5cdE3~E5kxS4^W8AxkE**!p756Yekq%ENAB|zF1%H9T~ouKR!K-wM3zPOp!Fqw;S z%H%?8f5r=w4+2Ss$$~cJj5d=yZTuN0OulI|pK;6NO51YAJ(E8I$rqC|?fe--Chr82 z7Lz&c{TY``jLhfwUHsJq1YXLD@@zv;~yC9Z1_k z*++r26O?@!NV`MXcYw4Hl>G`wgX{oV`5s6|gV@|a0tjk=jtCcc%fzTM*;Uw|(O~ja z;p2=6lVe578B-=-74c{6n5-)5&v;~VDUiG~`KV|xBje#LX(+BTxv(|?KS!z(Beju#{WzPW8dQkRCAZ-L?ZwJz5Q1(6`4KfmB+z}w{ z0%czV(wF9eb&CVvEyZzen1`7?3oPM%~}#&~Bkr@cR;%H&8Od0_HN zASp8Wr+qM^&17E(Wk%)6g%0XKBW420C6f;V$pe#L0?7@N1s&BTYJh&40JIqfU`zm4 CL{FFi delta 381 zcmcc9#CV~Jae@LP!$!qpLX#DRO(jcGi%ayA3ySiy^m8(kK)AR##n9NmY_hemG;Z0= zrNWyfc^QB}42T&QFfd4OHr0L3TJI0!szHUCfwUHs-2`g%0 z3d-IAq+OuwQ$X4i%Dw}n{h;i3Ksp%8{tl!gK-PiW@(0L?g-UQSGB6}T*>XU3I+U%w z`KYlwC!@k-UR!@goyoC4GGOvrAh~DqUm*Elvag*#(;uD5^X$qPFH9D-_h*!toC+kj zOx_A4IVQ6@1Tz{;j&x9F6rWt{pbj)*DUh5o`7Ds!GWjczTryeKQJu8_=%WdfKiUZc E0Ptp6fdBvi diff --git a/lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o b/lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o index 89428c36e501436a9fbd0652939356813330da6d..08caa11314b4098c89b03dc39e54eaf0090a5f03 100644 GIT binary patch delta 206 zcmbOtxIl1%0^^U3ioX~qXE901r>AD7rxxia7Zl}Z>E~o7fpBqgilMQAnSOCm@?qf878!a$brWElAD7rxxia7Zl}Z>E~o7fpBqgilMQAnSOCm@?<7X z6GCb>H*?QiBTh0%{dMj1H4$%K9@FOnwO@k4(0d^JkQp+zBLYCf@{- z9+NfY%NbuxUMTO+$TRsPkgS;OsNm1IV)8_VV8;KGpDHLbF>y`iQd9$KGgMS(yf8Tu VNKTmC2qYUOuLP0_lP@ZY0{}4+PMZJ# delta 343 zcmez3{K9#H0^@;=ijO!Z+j1KFmZTP!=qDExFv4I(benx(7s(yZ6 zN>QSI08lKPNRs7pI=h{hT+sc^QB}42T&W7#Jismx@|5C;9@pYEYp@Agu*u zw*hHAD0@1Pwt%u10BKt&dkc_ug0fElX?H05B9QihvY&1il$^}MXfk=JtUqJQZ?rQS2wM>8-mr~xr!Bm=`#Agu*u&j-?aQ1(I~Z3Ja+0@5~6_D&$}2xVUY z(r!@pb0F;vWq$+G0Z{gTARPr_^8g7TC}LpPd|YlLE90HXl`8&B43d*isrWIfOqNvj zXEd0c2_#)6?^G>k447=F=FiwOxe-VTOuh&teI_fa2Qvy!E>%}%JU)4*x;oH^gFrH6 X@=G9@Gg(kW9jL|mj)DQ;%=>|=0 delta 262 zcmZn({1Grgfw5wv;#w}2lGNgo$@<))lizaLz&V>exMlbmO*W@Wy=Tr1Wnf@X17gNV z28K=`tp#OI2GV*^_EaEk1Z6J+(l$``S|IHRWgh|3Zcz4ZAngrhzXH+$Q1<7|2jvd4 zGG3V6s^ZV|MPl+b6+cFa$*QXUj4G2$fuzOcqpIbME|YE5{23c2_X0_l$#;RI!(?6c wU`F=Ijq1vbyC*MIR|gt#7Dz@+{t6@$Cd+E51J$@{sI&4YF)(CK{-`Pp0EZ4e6951J diff --git a/lib/libssd1306/bld/intf/vga/atmega328p/vga128x64.o b/lib/libssd1306/bld/intf/vga/atmega328p/vga128x64.o index e7da81cdd439572338a2c7324c79b552ed7a8706..d33afdef7ce72020c82f0f14205247d689a01f37 100644 GIT binary patch delta 463 zcmex!kFn!E;{*l92OAY1%UbGZQHPO%Ve?7fe$M(R zAXg14GzCa&LD?&Sv>ueb6G$6D*~fvj8I*kqNP~<78Fv#%+d5Gs+s00!fX@qFMfoCX-Wv+($C3E0^#D~6hmVJv&pe?(zs)=Vbr_F(78tVPsI)eATy~vpxjKRf7t30BJ2Kdk&D+gR<8GX(K3mH;^`ivX232 zD=7OckhX)eF9T^0DEldp_Jy)P0_h+q`!A3VXJBvwyM>LBfguJe!3|_5LfL{qb{dqe z3S?(P*+xKi0hH~ySv6v^0HeU~EnaPS-{*x85SSFWb z`7rL7d@#$O@xo-mY=6cVn-jCs85!qHKABSv)b5z;50st=B)3d{2qXh08|DQwx=n7) nQ)cvK-vh(J_e-CpzMo4+6v0P0i^Aq?0Z1k1IqpYqYbDBBvyE`YMVHeXG*7Gac`ELc;{ zs4=;-#-Gt=@=YLFGg-6NpYhJ*N+9`S@<||BFp@=hQbvzfELpOJCK zfhf PQf0DavpUdX$7XQ=p@>@D delta 412 zcmaFT#&n~NX@UZy#YROjWyzA%;u8Jjf};E^{hZ7s5H2oGF*G(Xn=GR&jazo}1my|N z^}!4b3~E5kSjEWD4y3i9?AbtC56WHxq>Z5LT|n9l%03FDt)T2PK-vz|a1SoPog!Y%wz<149f{f&<7-gtGa7>@+A_3CPZdvh{)N0w~*V^TTv& z5k`T@vNh$5GLxs)_%k|8ehMTDCY#p!GhUe73MB7Lz6vCBCac!@Gqy}F1(I_n9|e*D zn?>vU85w&fFKs9XO2{_)GrCO91(Fey_X0_t$-GU$jLwr2o0J(HC$~1KGlooF3nV8@ cz6vBWCjSMJ5|dS%)mddK7#L(GUu+Nt0N}u5vj6}9 diff --git a/lib/libssd1306/bld/intf/vga/esp32/CompositeOutput.o b/lib/libssd1306/bld/intf/vga/esp32/CompositeOutput.o index 11b90f50442b2fe21a486b26a6b1459979895ec3..8d3dac488aec765fcda35e62342277f3d1a22549 100644 GIT binary patch delta 183 zcmZn=>Jgftz?ia8v6)FeJvB2uwMaj?peR2}KPNK@go}$)42=!U^oxsN`WX)$}d^6dQy_|8uf4t0qOtPBiOfSO@|5y}7nH-TaqnJCkHM z0|SE^5Hs>KFmwZH11Nje=CiE%jEoN^+p?E4PMN%w-Jfy6WLAz~#&we$IfN(Ya0oDp ePOjxpXVjRy6i8-FKFgubdW4mMVanu%Y{CE;!!5V~ diff --git a/lib/libssd1306/bld/intf/vga/esp32/vga128x64.o b/lib/libssd1306/bld/intf/vga/esp32/vga128x64.o index 02ca036160ef8152b584310d20a28fdf336f45e2..df50295d44d22a5b38eec582cd55667bea970eda 100644 GIT binary patch delta 264 zcmaDO{6lzx0%O2N#bZpC`WgATsrvbODMg9;0Y&*)smUe9`uRDjDZ1&YndzxT`pE@A zQT?3EBoHnxPBAn#Fw-wCN}l|T$wHohn$6kFx=g%Q3=9lnK+MPwBqlFq-R~I=WT-(! zCIV?KD0=~r)`PNF18EB=dk>Jdg|bfpX(uTA!sfMX`HYM$lVv%|8Dl0-jGXWhfbz%XTUBfBsF%nw5& delta 224 zcmew%{6=_!0;9`D#bZp96`9Q?OHzwV^pgvU^0V}FGLt~KxH!eo*uZSEEweOk+0Et5 zx=g$bKp+OhjQk7?vXeKm?)MA?^3ESIs7Lt;9!~jg(HCR>||F?WyUR&Gda~6PfVT&BsnJU1dn+a diff --git a/lib/libssd1306/bld/intf/vga/vga.o b/lib/libssd1306/bld/intf/vga/vga.o index a2744dd1b735e8a837e97f9d2736c1599ebb50ce..4be526c46ef46a1fc576857c4544837014bddea7 100644 GIT binary patch delta 264 zcmdlXc|>x80%OQV#qUg$qnV}T(^E6kQ;YPI3ySiy^m8(kK)AR##n9NmOux7&d9paO z79lm8`Q4~mQzRAYU=;;Y$sX>LBfwUHs-2<3BW5eWyJmLT~U_DF# delta 228 zcmX>ixkGY-0;9)9#qUg$gP1j0N>YnUCO0yRPEKH!hI2O0Vzy)EWdH&(AZ8S0VBp{U zl#QLy(;3KBg9?=cX)P$b0Z5xb*%N`ZC6qlKNZUc#bAdESKghVnn@u_7nHbkh4&^Fm zTrv49mp|i~$+F!3j5j9dat8y&4{|HB9${u+5C*b@C;#CV0Lt+4s51skHsw)g`olaq djz^7^hmC<@-sFj#!jtFl2(XrLFfd#M@c^U?Fi-#h diff --git a/lib/libssd1306/bld/lcd/lcd_common.o b/lib/libssd1306/bld/lcd/lcd_common.o index 48cf0482fde35828862d045a32a1c4c20f5fbfb7..cb064f351ffaf30c679c702d771d2077290aaa2c 100644 GIT binary patch delta 352 zcmaE{o$)E9gL-cU1_m`C zW<0{c&K$WgiF99#HlrAnglf-v`n` zQ1%-j9S$-IWbs!ZCk86<3rHtI+3buA3~5ldG?1MQWh-pf_4&-jSTR{K+@EpFUy@Mq+ioCqWhCU1-=XPh%xGqRjfV)DXBf5w2xAA#hX$&OL}j5U)d rMg=qKO@11s%(#0pXS6!wg~^6M^2FpwFxdzsJtnUNk_#qZj1~s~t=d;S delta 376 zcmeyeo$OG%cb7MJKJ7Zl}Z>E~o7fpBqgilMQA+2pxW(zs8At~~*$;qpILIiF#V>)J7^uWMAe{(h{|3@&P&Pj!14A~HEwb6t=Q9^$&Sc$i zf5sJ)Ys3AS{@6}F7w*TnVX|z5KO@8BTp+13d2d8H!j$lh;Q2GrCOv3nU** z_KosqESNkuDwt7e^2aD;#`Tj$qtzLYOtuA*dnTuX$zC97GkI&YI_s1W28NB36C;HI D@}FOy diff --git a/lib/libssd1306/bld/lcd/lcd_il9163.o b/lib/libssd1306/bld/lcd/lcd_il9163.o index 8ab3724915aa8e80da0d4cccdfe060ae3ba93dc0..5e0f171fda1712c6708e272d8b896d51500f3221 100644 GIT binary patch delta 451 zcmaitJxGF46o$W(Lk$fzgposvP}Ja0p-@8*1PM{MpP>R9zRbjm@@KH7EC_P@Ii3VIM4H3?&aJw!;~>hhLx^zHoK=k6by%gF=rqW z+uL&Pgx6aWk8ij~U0!EA7QmXv^52_$+GE*0oY6FGfQLRwJ7Et?r`QhZbM}aImhF|k zW{*qXu_vTUY@hTqdsh0Dy(s;~UT&>wef+}*zg+yXb?J7}v`uLX_qOyY}zy1)@Li3T$ZTUpTxqRe@enMrg%D2hO5b|S}o z1635SUSKx!mz8^>DXdl#w2wwrQ5S4AMNfz_Z&0o+kpn$-J56J(K1hD(Oam#V4>{&3 KUYNb0NAn-6_lJQ1 delta 443 zcmZ{d&nv@m7{@=4aU%yxtd*H8YUW4ZCBIHq4(1~cE*!8aY{>UpOIcDJX?jx*TS+@` zaL|-e`@!0F*-jj-TpT#;A3%A&^|?Acuh;9-Q_m+6wOm9k(RRALvpcj_BcL1ZmF=Ca zb$4)W*&JQ>_Yd}Y(5+ej-zMXlb#vbTmX{>P8Y`L$xg#O0=}m8;;Up>cnqa z(lvY;NhQQHvgYRi)yysCrML?FegxE8n8V}@*~6)NHJg0kdu6R zky%RK<{pTK5Xgrqh)P~kEnEdjSwxr#lnZmz0ejIwBk&fTG=mWH5a-NMq?mj7C_3xv KAB6x;^G$z%?1l>f diff --git a/lib/libssd1306/bld/lcd/lcd_ili9341.o b/lib/libssd1306/bld/lcd/lcd_ili9341.o index f99a00c24b816f32b5055cbc3ba93b56e65f5eeb..013e123ce0a5f8b39a6bc96618e005079779e9f9 100644 GIT binary patch delta 413 zcmaE}hUv!|rU?p+J2on6Xt1THW~QeWO>Wc>W!5h)nyjlKgCxWP6iVJaO(Q6<-iLvK zK@Er*iy0Z(fV38r-36repzPT|+6c;C38c-S?Das}3d-IFr0t;WgFxB?%DxPweWC1! zKspG@eh;L>K}LZr{sH8~KqdYH=|m`-i;;mL4a$}Sva_LVoy~Kro(nU^Om6KfXWTRS zZ=XM-!(`unf5w!_bAjZP$!~$=n#r~k{27-_?gf%AlkWmalgYXh{Tc5}t_6~NCZ7e8 z0+VGY`7=sv&Yfh>$Y?Wp?c{RC6O&b^_%nW)TnZ#DCLaZoZzhXQ4Q4c)oH0=g0kfNll@00G=)@Bjb+ delta 381 zcmX|)El5LQ6o&5^D}re%2Fr%HdmS=VM4VxQK{UvxGpJx$&|=(VxS-gyxS!X1aX}DG zlN%;igJ3aPH5hCIgAP^%gBI}}91P#{Jck3{`SwF?KU9v2e;sq2aDFqFhjIFlbO!#1 z;KIo)@6TD573Y(jSVcOay+O#rGarLglz14Rn=^OkkZ{L!CUt4|$G-vXN8N$SJf) z2dRpYCmfLtypmxISB-QByVV(yQQV;*_ZT}d@__?#1kYp>F?U6Vu;UKOENZUJGY@1F VE!PfxB@prA(u8Y9NsYUw91x5K;`Z<|NAY5FWVrXn&re9o?JlRE9 zmynvx`-ICxd94^27{q{>u?$FTcGUD|ulE76)SyCbKw1mR?gG+!Q1)yfZ3Jbn1kz?u z_68vB0A=q6(ymbUNg(Y7WnTx<{!sP0~IIceACTJUgSvW=CCVj(Q&;OARX22Bfv1>@Fa!2W8I&(ne7BN+4|pWp4n|AR|G>?FP~= zQ1&q(?FnUH0n&a@_9Gx23}wFt(h(q|K$<@QIk8ZQzd$+($`)i~U`U6u<$>%RDBEbW zpxI$|#wU}n+WIrfOjfn?XN;I!3M6k#J_;m1Ocu32&Zsc?u6;SlwAj;^`Pv2AZ-L?&jr$EQ1%iaZ3Sho2huK3_AVgp31y!E z(tc3(H6R@fW#0$V5g?;LZg~Ra#6l%L0_h|uo0XA)AsxyV2C{RYY_-j@W{24sZ%lq@ z>(3}K+0f3P(PwfakUTT_B9MGCS<(JDqsZi!_T`KZCMP=hGZswV2qbwXGdlV+hD;80 s3}!T$ywp*dF?sSyM|H-E$sd8F!(>S(b)YUsAZao=6G%!-p6DbF01~rFtN;K2 diff --git a/lib/libssd1306/bld/lcd/oled_ssd1306.o b/lib/libssd1306/bld/lcd/oled_ssd1306.o index b425ac75f984f77840e3b7667591b9b3f141d4c7..2eaf5105faccc511db6ddab024395a7683890fb4 100644 GIT binary patch delta 498 zcmaivPbh<79LJv@xe?`0ONmXqMeQ}(5*Nj44m`rjfy=hHHBGdc&1^Y|a*4X18!gXhwk#j+s8K{>9V7B2L+egXEoih=+D delta 498 zcmZ{ey-R{o6o=mfLJdkuP(wp$kQCXg6$aH32oYE}siCF8RQkYtE8h>bH|h^)uzq_K z)aIZ_5HvLj(a_)`wDbWrIJ%TeN4RSj&hL57J>0{+Z&9&Dg+VHoJyj39UjLGw%;;)- z|4`diQ#+gO%48D3$v{X^x3#^bs-+W$F?EIK$+(_TwNx_U|MyKL?Y#)P6h6IN^s6X6 z71!EF*U196!}98gIV$~xIWE1xoREIW3`xIb&PXpY!_ps^i_)K%%hK!2Rq5}{_4cav zU%t56kb@?3Q+fv}%9iwg_LTII%57q{n;Ll21r-o91OkQ=XGR#Oh66PtLeKD+0)wU# zwi%{RJeqgA;uX-*%ByO4mh$AdO5w|z7PI`;8~5zbdcIc?-Powz>k`vYBX Bk(2-c diff --git a/lib/libssd1306/bld/lcd/oled_ssd1325.o b/lib/libssd1306/bld/lcd/oled_ssd1325.o index 5799f31558033f0cb7c261e0fba3c8e6f6a3f153..8d1811edaf5bb121662e80c21b3ab346fa688ee1 100644 GIT binary patch delta 395 zcmexyjIrf7;{*jposEhv(v#OnOUb9FW~QeW=_eNyFv4NR>aZ&Q* z6lpy|YBt}OeyYi9#lXNI2E>dXfW+pDuH~HdzCe~5RHz+DYeCuFKw1yVo&%(fpzKvZ z+6>Cx0Hi@if{fb^q+OuwLqOUS%DxDs{h;gzKsp%8ehH)_7#QThn%@CAu~3QMKspJ^ z=HL9(UznG1#^j$d{)`2aJ!8umr%XN=>(6*&vS6G)W6I=2Ah~ApMj*LmGGn|yW5eda z_;g0b4U=~!lrtJkHca$q{4==`NIsZ+5lH$>R!jq?fS7MJKJ7Zl}Z>E~o7fpBqgilMQA+2oDV(zs!MjbVkM{laD5p zGpbCsP4s8{Fu4~Ls% zYBpb%xoBGN%fP^(2E>d%85r7uv=)@z4W#v;>^VT%2+Cdsq|Ko04M5ro%H9s7?V#*K zK-vS!z5=8{c7V)(45Wjg>`y>C9Ap$o;x~{J1C?N4WMD{yvU!2*G$>mU$j*kc^*2Wb zPv>Pcnfx)qpOI&>W1>H!%H)ZO<%}MaIg|VudnQK$$tjap0!f9*KY?V%WY1)OMu*Ka zlhYX)3nnwBmNUjou1xg@8gUXx8cdc<^JiQ!IWsL7D6%(AnXz~B!!&iq1(P|`)frtT g8v@B4lOuto#pK3xb%`~x3=CyVK*vA<&}m=*03m8=4*&oF delta 394 zcmX?ep7FqW#t90H5*rm$Wh6^di%ayA3ySiy^m8(kK)AR##n9NmY;v}YG;Z0=_hl}c z*1Iz>FsK1B<4*>LY9OrzW!D2~Jt%tukT!y{=K*OmD0>Nzwt})(18F-bdmE7UfU-{j zXkoj#k;Drwtq1-%fo8m|C&)!J>kX?MNwMt&>ks@@vH@#S3{Wg$fb3-SM~-Rke!1E zWFNtUvh%Qgq|&=G!Es5mljb;MdP!pweB=uF Z#C2saowL8}b!mr+a!`XS$bk#}jbAdEe$fB` delta 455 zcmZ{ePbh<79LL|^oD>Ilb zvv*ro4s%crE@}=AN={aj+_?F!o~x&x&*$?zPd(4`Q?`}MwuDQZ*KUUnQ}1z@3sJLg zesyhSxi7L5s?2CK>>1Dp;nkb}KeY^tkFG9aQ~FPgS0){N|p7_kQ?O54^&?oqG6gmz$sb8FWHK~l_7p4$uX43Zg{T^ zslhHej2AM3jFv4NR>aZxgZenx(7 zs(yZ6N>QSI08mY8a!Ij%eoktNE&-jJbyQNE>wOs*7}S86QI?UR9Y||I+1)@|56Yec zq>Z5LRY2Md%H9B^t)T4fK-vY$J_Mvaq3nx5+7HTp0HlMV?3X|~0%RS?;&(t!EL7q* zkWPZK`574)(xGhG&6XLb`58+lvsU;s{+JvJBxNQq1(H6KzXHjW$*z_Dj4LKj1(H7| zKLwH#CYx6IGoG2;3M6eNU#&XMIA`+Q>TEGLAZ-O@uLjaCQ1&(;?FnTc1=4;{_7xx<3}xR1(h(r* zKo&m&a$=zp?}2m@l+Db@z>p4Q3vPDJIL*(PFfn>*I u!P;O(mC32K%8b`0ch;%{P1pz|WhUPQk~WhW>(m*~Ox6UFD<%ili30%SeN#OE diff --git a/lib/libssd1306/bld/lcd/oled_template.o b/lib/libssd1306/bld/lcd/oled_template.o index 24886e4d3f5c8d9559dc8e14f3d8ae6cddf20e88..70f7d28ccfac190a33b37b769272ba7e88b734c2 100644 GIT binary patch delta 400 zcmeC#z&K+A;{*l9gpG>s5|cMbNXe(CW~QeW=_eNyFv4NR>aZ&Q* zbP0VzYBoQX&{g5JVqjnp17gNgKw`73?Q@QLKOjpDD%1g_wV>=CAgu>w&jr#(Q1)sd zZ3bm;1kxZQLB{O>(k@W;VIb`ZWnTu;AUi;69s}uMDEkeNj$mMr1511aa$=zp|A2H7 zlr6M*p<6dMqt9gBAb-Z1$+bb{j0+}z1+qU(b`ADt)R{aLNSaK38tl)+U^Ce)#ExQc{&Y2tv fB)?3q1(FjcF9nhUlh1~$vs(BwFsM&n7%B_^qxxwO delta 406 zcmbQSfw5-;;{*l9kd2D&5|bB6==qkU7MJKJ7Zl}Z>E~o7fpBqgilMQA8H0XCer~FM zeqKsZqJ98SJ~g?dSU*1}HANSvp3UzibX9m6fItk08BZ}Vh-}uhea=zu0pzMdg=&Db z7L?rpr1hZei9p&2%AOCT&7kb1K-vn*UIV0EpzQ5H+7rq?4y65{?CU@}7|MPCq$3y@ zB|ZV^Bq*D0^IErVZbpa6mO=iE1(Q32${D9jW(@Xcd@?x@NGeQT2qZNo ze+>3#`eHrVDa4QQz~qS`#~D9NjtnhlyfXP>s6SAHVwgW;#pJ>;f2KdKlMjUjF^WtU m4OeEYnQR%Z&NyLmB9MGBxf4jXOx_42Stj2Ek~)(aBg6s2G;CA= diff --git a/lib/libssd1306/bld/lcd/vga_monitor.o b/lib/libssd1306/bld/lcd/vga_monitor.o index a0085450551b96d23c5b7269bed6a3ddbca15bd1..11d65c4a321e8d4acd27be7e0964be1dd5713476 100644 GIT binary patch delta 372 zcmbO+pK-~2#t90HA{!OML?`bRm6A_S%}h@%(oZfZ%Foiz$xH&_;^GuTV*@k&;-ciq zWum%-)NKABx?))$uJ!EiTbdE-1>+($C3E0^#D~6hmVJGY0*P{M=Oi z{JfN+MEwAud}?w@v3`C|YKksSJ)8fCZcyN500J=}W<0>aAhda>*=6>6Hy~FHDpUoe zwV>=eAgu>w_XBAoD0?oDwt=#j0BJ`kdlQfbnFTT$h#0(~?2|w`0LnfGq(hL|QAgMCB*Iyg}xEpC3 diff --git a/lib/libssd1306/bld/libssd1306.a b/lib/libssd1306/bld/libssd1306.a index c11f68020976b9031eb615062b88e7b33776e420..390ee8c697e5f6de6d9f9079f34b1fd2c402e3b5 100644 GIT binary patch delta 19206 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 delta 18711 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 delta 1295 zcmZ|LZ)nVM90%~<_v~BJt~}T^LT$|<-LP>>8hNluX^0&jY~|lEOk{URglzdYQe5xD z=Fhfcb2m1-pTjmz?IcYk(>BrF(mSxT0r=B{kqja{(XXzZ1FVj+!@6a-nU(!V;57Q+kzopAf9;H<#f2C_o z{zcbYyizV!%Cc(A!UX0`CQo7BW^xhpE|WdXdrkH-2TfkYe8}V#%<>>Pe*<%)$#u-9 zO+KWGEbF`}PIKX+$zkTO$*l?J>zwT`)p!Ii>s2ZbDWL$aE5rl8un@LT0ezLMhEJ$L zM5sen2%xfs979NGMn(w3+e$jnB=lfJm-lICcBrA5t8t>k#A@sj^9)9zKwf4aJRGDj39CRoQCJ^?8e~g zU^flFuoSj11|5;p3$ZT3J<}0ksj86`;;6hu3J?-LBO^?L_cjTmN!Wl9VJqC7tK|-JQ!p{9fmVT zVyG2{&>hp))dy5{%ha=Rty}NsNUpnFoCm*94qI3beUB8tCwLGMYLFG`P}xHQ2nj>T z5Xbjol=bo-G>meD2Ur56idY~VX z0r-T^h!DrmQv7(tsdG^InB8iGghph97I^!4MI0mjtdejKkYNOcG*ZGST!SPJexU-k z5P*I{I^YxDAtK};`-Bso!tST6K44Jz1ZR?@QJd6j)h+ZUb&)E;NK((_VSfY*?q_5O ORl++2g#cQg>HNQl`kQV5 diff --git a/lib/libssd1306/bld/nano_engine/core.o b/lib/libssd1306/bld/nano_engine/core.o index 3f9cba127a771fbc77e29c08c03d865859e6d1f0..4f3b6392c81dce7e9b25e029bbc87eee9dab0c0f 100644 GIT binary patch delta 376 zcmeC##yDde;{*l92^$rsNKXDIDJ7qtnwg$jq@P?+l%J)albHm<#l1cih+Sa42T)m0g25!E$g`w{edhss8A=6)`GI90%<)cdl`_nfUjzms=@w@9g|Ceml*y?;(q{73$Y93%lMSPUC(A?$07Z49)Pd?kqtuxgye8L0sWEPuyc8%@GWl$j Ty2KA}28OAuK-WP5Ba{XJQ>AAk delta 363 zcmbQSjj?AN;{*l9mW_&2BqzU@)b}k(EiTbdE-1>+($C3E0^#D~6hmVJGY0*P{M=Oi z{JfN+MEwAud}?w@v3`C|YKksSJ)3Q%s^xhZfItk08P_o|h;BY=SGi3n8lcqJT+=%TX6O9BYF-+w|T#+p2qyb?QE2yL8{O zy}BRR0o?`GtNWQ9*8Rqg>HcB^x+_SC89v4LG_7<}6yZ3H&^7XkI#>^xRRk3$xKOxJ ze#H1Np%_9|kw8h|geSqg<3Qmry;@AglO9NfCu7P2*IBc$yk%3pZ)9^HGY51z0jrI41S(8$3e3tJ+~!J!CCFo*`r1|!JM3yFqsX;vJ5ROjg( z6%9d&gF{ON4sI3w0Ywc35jX@k1U)ajYX>i%@B7|+_rB+KyI!~F`be+1qH5t%^*FWl zwB}n&saqSq&E%>W>2zXbba=dQt@i%^w)(9u-#HY1x_MB{rZ{RVW90Sj2YK$6Ydh?a z>;u*>`;48CU1cX_->@^X8*EtiBRePim0ghi#l~d+vT;SJwZ~~UKpL`#G*4G}5Ol(I z#H6q-DC1TTK-V!7LR>I~iXaElnL$JZZ!iTRGzCux78yVCf(yJbcrKC+euHM|9$AAj zq~OQk^_D>$h?e-;lafzQ%}h@%(oZfZ%Foiz$xH&_;^GuTV*@k&;-ciq z>3Z6P)NH=5CuzoO#lXNI2E>f&j0_B$SyTB1>%D+nHK*q$$#;QlhsnB~{){=3Yk_3NMnEiTbdE-1>+($C3E0^#D~6hmVJv&kFvq;bn` zeyt~I#>)T%VnEEO&d4CJSumAfu-*m8Rf7su0BJ2KyAw#8K-p7)v?Y|i6iC}a*;|3M zGn9P{NP9rp7lE`dlzj_G2SM5Qfpj>O{T4_kGB9kOU-nRdkz;aWyFa7I04 zKjVzag&pOS3p!XPzv=K{G?{GK>Cc!jxf4j{Ouh*u&rH_r@@Kp;xw5OAalzz|Kz7Dt z$8LW{pUD$}B+ulB-N8)X8779{qW_yc%%xWD?(a2Ub z5=TgDwT%i!4l2Lk99DkEIi~!c zb5i*u=Zx|vPEGkMr#aVr=7UozuW>Fb|KVISpEH|?gjiP>E$m_CF7{3331Q{to%8(_^W^G7ePde6#xJL delta 484 zcmZ{eJxD@P7>4~cBEi5RGE2gKNGwPzFx(8TgApAfhg`z4Kto7U$fjt^Au`@2p;b_5 z5edSfU8wd3qb)@(HHCtPz6)pVz}U3>>{qss{m%BwZm|RE=hT1c@nTyZ^pi#tl0C{DmTfCm zp615s4f=+lEd-b`y|h0ft?3i2bv972t0h5JKL7%Ap8UYJJMKLy`BVFpoV zreSWWHzO^f{k}!1wa$<0+k);9U{;Z52Jyo*z}FGvM1~nft#eEs?0gA&M1ffab=8M9 gx|`%iwmU`3D0gkNhBh+^b5HFRrUemZ8dp8jAKjUexc~qF diff --git a/lib/libssd1306/bld/ssd1306_1bit.o b/lib/libssd1306/bld/ssd1306_1bit.o index 58a2c5250277f3c5985aa5940211d4c5f9f025c0..204a9165d2c9ae13ebcf294a2fc28f9e408b4fef 100644 GIT binary patch delta 667 zcmajbPe{{Y9LMqJc|Z`<>JTx+QBh>*Y*``^4I~mwFc0ZLNDt06Cyrt}=s{61s*5DJ z_;g4T%3C`G#@1o*J17z5-9z34FHKFCziqnF=R2Oe4?Miy&mVsLcuw4!*ZG=-OM2nU z<*>8()2Y804n@MDm_PVD_H4{Q9vPMykB_w8zS-`N$AXKmoTk(6%$1!~+0jE&b$69g z7dUluwNj}_z`W_2dC2uOyEjLhY$xaq+pF}JZHKnoUZWkhf6z|bo3z{Z4(+wQPy1{a z=zvo9D?d}_V#pqx)k+0zH?T)-``A(29qgFx?$o!J=HpYH!(i6*>R(6-pHLFE(X&f_ zV@b#(E2I(FBkwUUj9^Phqh+7uFfI77A)JHvFG(OOY$8KUwGU?w%p?5{g9qGgLsFPT zNw|ZaLz2Lf@B&$38G#(Rhk0QNTf#D0{*g6I3$xe|{=j=gx)2q7$Q+pu`0ScmjJoE5 z_8{qU|0+tZ`OfdH=gkB!2MS~rUkf}-qpDcB(l4A~rDz`OCnyxn6~2b|*fjDPIt34+ YLL1%+=aC_v>pMn;s`#{a@S!W?KMM581ONa4 delta 606 zcmX}oF-Tic6vpv)k0~S?sSZ}L4iTX>Mv9ao2vx*dP!ZEo2eSwwRRa~IO|b#Np&}6k zg$SQcQd}Zr5rpU9Yh`=9%GkIM}eD(po!L>ONuzbf2LEC~Ue2xoBLFs~65Tu9u|rZV8S$crh9ocL)`ud0KiK)?Bae+o2bDbr=(}*tw+->Kz`HsEIGcU83iF6Ym8lfqN BxKjWC diff --git a/lib/libssd1306/bld/ssd1306_8bit.o b/lib/libssd1306/bld/ssd1306_8bit.o index b8d6660cf25a6e59a5da6496e7828c8fafd5967f..2de132304e9b99dfab9edae46125f8d94bf8912b 100644 GIT binary patch delta 530 zcmaiwPbdUY9LMK3y9a+(B1wq#r=>ku|8kJBt64>xm$)b?mi#U3D#s-kO8N73pd9Q8 zvZ`Cw?PNyE4m8-jg{7k- zi-fA4<(&aJa6aw#gL?_;I5-|GOvJ>OG&#YE~2_pC>t0MTw?I)`~(M zymZK|CAL%c7Q06F3A|WVl?7r0NQs45!ivf8d zn-s+_yMlX6c5T#i8!DkyT)qm`x{qAFi;6L*i%r9d6WvE{kRh;V*wAliWJA~xRDcBU zt;em<;y!x7MqE%Ho|qcy-UJP4#nmG#;g@s3XMn>5XOADfYTgt*~W1%4| zrfigjkv(>bGS_o%SrEU`**bN;?>qO@J?AV(t;MLdRv?cDg?lZq?6T~cq2Nr_z|{2Q zXw~>ge|!dmgEe*4KBU??|L=y{?C_Y!;K<;Va??l-r5~*3EHrcJ)t_eRa@|XGrS3ht zR`((8(|t-e=?>Gj?n}B=_YJLd-_sqs9lASyT>LKYT=eM;OAKQ`cP4vScX7xcS;&_~ zM4puSxr6*@KvFOfRZ@yDSr3n+%-AmaoB(>9B%C-cl7w$Z$r=35N-nWMCcq&Z(Dy8Y9NsYR1SL|OEUi;^cl6qZI4+UzOPEK~2tz`&pe#EjVt z3>`pP3(B4er1hZeoj}?M%03FDZJ_LvK-v+?z6+$?pzM!8+8fIL1*8L@Y-UCVhEOP* z1IUhIU@!w)ED7YqLnYLJ>=Y>56v)nmvR#1eJSaPCbE9EA8>7JFhvxo_8zviC_)orI z!7{nU!iVw7=?Agu>wuLaUZQ1(tBZ3AWR1=5aC_C+A=24z15(%w+^J0KkZ zWq$|Kp-}c8ARWcPUfUfLoNLoeI_pjk_#q(1(HW5yIKV^Moyk-rOc>4d9Rf^ mqs`=}Kr&!5ueCbkoXMs@vSxCuwYtO}Qw9c4pj9vcV*&tea!#)R diff --git a/lib/libssd1306/bld/ssd1306_fonts.o b/lib/libssd1306/bld/ssd1306_fonts.o index ae5f3b43f71b27082b53dcaf8c703b1d7501f6d1..3b750ec0e0b08352daa8924d8ce748ae773850af 100644 GIT binary patch delta 212 zcmdnc#JH!4ae@M4%0|U=hLisrO0lJy+e6t$Hy^c}&B|Ca zInlnHv0?H}dw<5B$(jzqjOQlTIw&*loxIRNo$gW@ w{)`QiO&x+64^7_aAUt`Fg8<{k$!i_d8IMf93MT(LsI#81WMG&uSp$@&Et; diff --git a/lib/libssd1306/bld/ssd1306_generic.o b/lib/libssd1306/bld/ssd1306_generic.o index e716c3b2f43f79b40d1d54d6416736bec91b1e8c..a73b7027a987b08ecbad662dacec26f2f464a97d 100644 GIT binary patch delta 435 zcmaitPbh<79LL|EsX5GH7oydSvIw(C66MuOYIzb)9N4Tit;TkclXelMOy3o57R60( z?@2ij2Xb0D%+1O{a&*$?zJ%4g#%S+jkYN1=r)uAG#Hao+iNH`St z1Xtp*WluB`FlQpM!^`L6lR6MIVb8+*=d8-s_36y2KLZpCx47U`m& zhLJA{O2PXn=mSaSJF?6zxV{9PVU>A>Yi17ilBlUWN1!xGUC>H`d>}*M$gpAF@X;kQ zhM+qXm=37lf=02&Oe4>H)xAGqq6Hk5*Z7eASI_|#nNeuW9Z+SO49r&ANX2@^O*6f2O=)Q+0qN+9T7 z+S>N7yEoPr|7IYt+|%1VfHAf9|5NQ=P57+}k7}NDVp6KKaH68lH_XcxxwXq~mwm+U zl6}VZ$d0hRvg7PQ**EMF*|+R**%|hf>=%u)kp^l)>_bpD^2`vtpMr7-Ghgw{+(YM= zpeXj4*T^vM;3x=_afQvoBsq~T2=c(H3%bCZE-8i3T582Vd7g*A7acyRhzvlV6LIhxBZ MOX^)wipZAizatBfIRF3v diff --git a/lib/libssd1306/bld/ssd1306_hal/arduino/platform.o b/lib/libssd1306/bld/ssd1306_hal/arduino/platform.o index 57986e1c6d40480822b6c0c3ae09975605720a06..9364dfb499e5ee12407ccf6fbb59eaba5cc08072 100644 GIT binary patch delta 206 zcmew&*dR1PfiYsEq8roXJxo&a>8Y9NsYUw91x5K;`Z<|NAY5FWVrXn&re9o?JUNZY zhLD=g@0nPcc&!*17{q{>ksnA*W@Mc$84YBpK}DtlX#*&G<>sxd`HYMYCabcSGftU2 zm))On!Q{8>!HnA`J8~$q$}%%B2m@KdlWRBx7!4-(a;UQwurM&>P2R{RJoyZV0P7J} J28Jmh9st)PHpKt{ delta 197 zcmZn=`XV?%fzfB9q8roXg-q6xC8@B)C>cRPzC^7Z!ewz diff --git a/lib/libssd1306/bld/ssd1306_hal/avr/platform.o b/lib/libssd1306/bld/ssd1306_hal/avr/platform.o index 53f2b0f23021df3d96784f371dd0e4ae54013571..754997283a7788c0a092453ae728c77807871f53 100644 GIT binary patch delta 246 zcmbOcxg>Ie0;9}E#qHc|>8Y9NsYR0octlzBi;I#cf8>@%7u&4L(=VDB%D}*&2E>dN z3=I81S_{ga52W>=?5#lB0?IxHq-~+>i$K~5%Dw}n-J$F!K-ve&e!E#z=`tIm!sM44 z{)_>WEj9faPfYFvk`9w^YL+v;nH;DEVlM=eQzm}|k~=0lY6mlZnLJfnnQ{8$o!aV* eYbHMgl1nCY>Zmh*m~03n8zx5rNrB0YI^qDufIcDs delta 278 zcmZ1yIU{m{0;9l2#qHdZC8@?DKw1yVUJ0ZvpzK{h+7`+_3Z$K&>7|qJ^7}S86k)MHKDv&mSvR7{2%9_u}_+YXsdpYBj$#dEL85c}`%O1?QZL%YW vGOH{z1A{P-B|N!?Lx9m>axaHEYXJ)bL*C?#Y{HYza0sv-VP#;L0^$Jxho&^p delta 171 zcmZn=`XV?%fzfB9Vk47eNosM4esV!kewKbtW)cV&7pE8+8<$s z3=9lvK+MR`z|aY#4WR6~n-8+)GcsP8Y{*{D*fDt}yFcTU$v@eH8COmA@;DlsxJ2m@Kdlix54Fj`Fh a%dE~S!NkDeFj){NX2T-D8Uf_RfOr7E!zYFS delta 120 zcmaFE@q}Z70^^#AimPObi&G4Z4b0**5_9x(GV@9+^b2wlOVaX-a`loYo|2X@;DlsxJ2m@Kdlix54Fj`Fh a%dE~S!NkDeFj){NX2T-D8Uf_RfOr7E!zYFS delta 120 zcmaFE@q}Z70^^#AimPObi&G4Z4b0**5_9x(GxO5R^$T(mOVaX-a`loYo|2X(FQs+0dPacmA?%wS>+oIH_Pc=8!$0Y;h0cbU~04JNa)s51&o S)@4y=4Patmh?)G6Nf-eCbS5GI diff --git a/lib/libssd1306/bld/ssd1306_hal/stm32/platform.o b/lib/libssd1306/bld/ssd1306_hal/stm32/platform.o index f657f0d886c5ec8976aab75e78293bd3e62922c8..526734e54c5aab85b13d6216c307f86b72965b53 100644 GIT binary patch delta 183 zcmbOrI7e`T0^^sBiiS+`>8Y9NsYUw91x5K;`Z<|NAY5FWVrXn&re9o?JUN?5nvj~! z^OPfL?CSdWiQ?w$ePc{*fIGaTREe_WJ`8`Mw`iDKj~cLtP?)m4RUjP%{iLLKy(8)-FN- delta 160 zcmbOuI6-iN0^^H~iiS**C8@->Gnpg< z85kJUfS8e=fuR*h8$j99H^;K(GcwjpKFe0ls504=-Jj85@>KR<#zm6_IfN(wVHaTB eJDHb5o$AD7rxxia7Zl}Z>E~o7fpBqgilMQAnSOCm@?Fv4PoSDJE&$vYXd2 zF){Hn0D%|~Gx9SqC`{hV(k~eTG49@QKA#WVbGUb=YfyJ_NaY%wsJh$j+w&aJ5BqmY$0aoasV{DIV(X5*KW*YLo3(eZvl_ zeqb-Cer7MLuCc?ao9tE9@9cHepX^Q5KkRKG`u{%eAt83u!-zG1YYmedUnNN)EWJqD zLylQQi`ffbSyBwya)wNNbBCc(#a)1}E-8g9vw*ky26-^q7^eg14G*2;m}w%<457rVpv`ol?{)AOZ@zio delta 372 zcmX|&KS%;m9LL`;m0SWVgTSSTGTZ_W46+6lYLExTQIJ7W?Likeh3gFo#rGP6B8|5G zTtiTVWqNl*LqpKg)a(*C2K_D`4e#^$Jl^}>+Mx?ObTC50*Q0Y<*x1@JaH$QUqNV;X zj;HOfQrgiEH{z9?5MqK4MSFzFPN}xoY1KA+TJ;%wR`m@#*azEt_Ppu_yQun&y{P(& zy{!71T@qs8Z%iaaSv~YS3+GOP;`n)zltJ-XQVGY*D|DD)WSf#!P;HuIA@U+=20F8W zIx~+h^8tmHq!^A`CT*gxEomET?co1A_XoyZNt4)hO*%n`yN0YMX&qH&4WHf;B{1cW eQ5m|QBm;X)3w34&ugp7i{bVHeC`2z#-N9eQ8EBvY diff --git a/lib/libssd1306/bld/ssd1306_uart.o b/lib/libssd1306/bld/ssd1306_uart.o index dd4a820f1ae1b3bae10d680f97cf791b3f211fad..2522aa784b3c2ad0d2dcc5b4854f436fdb89e434 100644 GIT binary patch delta 283 zcmdlIdLVRy0;9)9#hYA{ZMmi7(^E6kQ;YPI3ySiy^m8(kK)AR##n9NmOux7&dGb## zEkbHG7jT;h@LDl2Fo*#$V>Xc3yis~Kv#lqPr3Mvh2GRyl_7os(3S}<_(jcuMZJU6! zJ(PWLbEkYa8>7Z#Q8j5ssDR`vIc6DEIEFK3)HIakAh3O!T`jdO$Gn} delta 280 zcmX>Qx+Qdi0;A1F#hYA{O}I5BOHzwV^pgvU^0V}FGLt~KxH!eo*uZS^PcCWPvYTtT zO$2xufItk08M7G}_&4vBp3Q9Q4CJaoh01}n0hHYVq)nmh=|I{F%3cPf?V;?go2SZm zvoXp{R#fw6+%dUO&3|%%8q4G(YCeo1lLgh^Gqy}-)F@}1Fu790pK-&0xlTllN*W1NA-BRA)RhnNv$0Xp$k2)R`O!W;bf7ORQ05VCZKA+6M(NCIGd? BL@EFP diff --git a/src/framebuffer.c b/src/framebuffer.c index 74bf27c..37bdb9b 100644 --- a/src/framebuffer.c +++ b/src/framebuffer.c @@ -4,138 +4,134 @@ #include "framebuffer.h" -#define MIN(a,b) ((a)>(b)?(b):(a)) -#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a, b) ((a)>(b)?(b):(a)) +#define MAX(a, b) ((a)>(b)?(a):(b)) #include uint8_t fb[(FBH / 8) * FBW]; /** Fill with a vertical pattern, 1 byte */ -void fb_fill(uint8_t pattern) { +void fb_fill(uint8_t pattern) +{ memset(fb, pattern, sizeof(fb)); } -void fb_clear() { - fb_fill(0); +static void draw_mask(fbsize_t idx, uint8_t mask, uint8_t color) +{ + if (color != 0) { + fb[idx] |= mask; + } else { + fb[idx] &= ~mask; + } } -void fb_px(uint8_t x, uint8_t y, uint8_t color) { - if (x >= FBW || y >= FBH) return; - const uint8_t row = y / 8; - const uint8_t rowrem = y % 8; - const uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; - if (color) { - fb[cell] |= (1 << rowrem); +void fb_px(fbpos_t x, fbpos_t y, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + const fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; + draw_mask(cell, 1 << rowrem, color); +} + +uint8_t fb_getpx(fbpos_t x, fbpos_t y) +{ + if (x >= FBW || y >= FBH) { return 0; } + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + const fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; + if (fb[cell] & (1 << rowrem)) { + return 0xFF; } else { - fb[cell] &= ~(1 << rowrem); + return 0x00; } } -void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color) { - if (x >= FBW || y >= FBH) return; +void fb_hline(fbpos_t x, fbpos_t y, fbpos_t w, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } w = MIN(FBW - x, w); - const uint8_t row = y / 8; - const uint8_t rowrem = y % 8; - uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; - for(uint8_t i = 0; i < w; i++) { - if (color) { - fb[cell] |= (1 << rowrem); - } else { - fb[cell] &= ~(1 << rowrem); - } + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; + for (uint8_t i = 0; i < w; i++) { + draw_mask(cell, 1 << rowrem, color); cell++; } } -void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color) { - if (x >= FBW || y >= FBH) return; +void fb_vline(fbpos_t x, fbpos_t y, fbpos_t h, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } h = MIN(FBH - y - 1, h); - const uint8_t row = y / 8; - const uint8_t rowrem = y % 8; + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; if (rowrem + h < 8) { // all within one cell - uint8_t mask = (0xFF << rowrem) & (0xFF >> (h-rowrem)); - if (color) { - fb[cell] |= mask; - } else { - fb[cell] &= ~mask; - } + const uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - h - rowrem)); + draw_mask(cell, mask, color); return; } else { // First - uint8_t mask = (0xFF << rowrem); - if (color) { - fb[cell] |= mask; - } else { - fb[cell] &= ~mask; - } - h -= rowrem; + draw_mask(cell, 0xFF << rowrem, color); + h -= (rowrem == 0 ? 8 : (8 - rowrem)); - uint8_t whole_cells = h / 8; - h -= whole_cells * 8; - for(uint8_t i = 0; i < whole_cells; i++) { - cell += FBW; - if (color) { - fb[cell] = 0xFF; - } else { - fb[cell] = 0; + const fbpos_t whole_cells = h / 8; + if (whole_cells > 0) { + h -= whole_cells * 8; + for (fbpos_t i = 0; i < whole_cells; i++) { + cell += FBW; + draw_mask(cell, 0xFF, color); } } // last - mask = (0xFF >> (8-h)); - if (color) { - fb[cell] |= mask; - } else { - fb[cell] &= ~mask; - } + cell += FBW; + draw_mask(cell, 0xFF >> (8 - h), color); } } -void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { - if (x >= FBW || y >= FBH) return; - w = MIN(FBW - x - 1, w); - h = MIN(FBH - y - 1, h); - const uint8_t row = y / 8; - const uint8_t rowrem = y % 8; - uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; +void fb_rect(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } + w = MIN(FBW - x, w); + h = MIN(FBH - y, h); + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; - if (rowrem + h <= 8) { + if (w == 1 && h == 1) { + fb_px(x, y, color); + } else if (w == 1) { + fb_vline(x, y, h, color); + } else if (h == 1) { + fb_hline(x, y, w, color); + } else if (rowrem + h <= 8) { // all within one cell - uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - (h - rowrem))); + uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - h - rowrem)); - for(uint8_t i = 0; i < w; i++) { - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, mask, color); } return; } else { // First uint8_t mask = (0xFF << rowrem); - for(uint8_t i = 0; i < w; i++) { - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, mask, color); } h -= 8 - rowrem; - uint8_t whole_cells = h / 8; - h -= whole_cells * 8; - for(uint8_t j = 0; j < whole_cells; j++) { - cell += FBW; - for(uint8_t i = 0; i < w; i++) { - if (color) { - fb[cell + i] = 0xFF; - } else { - fb[cell + i] = 0; + const fbpos_t whole_cells = h / 8; + if (whole_cells > 0) { + h -= whole_cells * 8; + for (fbpos_t j = 0; j < whole_cells; j++) { + cell += FBW; + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, 0xFF, color); } } } @@ -143,109 +139,64 @@ void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { cell += FBW; // last - mask = (0xFF >> (8-h)); - for(uint8_t i = 0; i < w; i++) { - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } + mask = (0xFF >> (8 - h)); + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, mask, color); } } } -void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color) { - if (x >= FBW || y >= FBH) return; - const uint8_t w0 = w; - const uint8_t h0 = h; +void fb_frame(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t thickness, uint8_t color) +{ + if (thickness == 0) { + return; + } else if (thickness == 1) { + fb_hline(x, y, w, color); + fb_vline(x, y, h, color); + fb_hline(x, y + h - 1, w, color); + fb_vline(x + w - 1, y, h, color); + } else { + fb_rect(x, y, w, thickness, color); + fb_rect(x, y + h - thickness, w, thickness, color); + fb_rect(x, y + thickness, thickness, h - 2 * thickness, color); + fb_rect(x + w - thickness, y + thickness, thickness, h - 2 * thickness, color); + } +} + +void fb_bitmap(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, const uint8_t *map, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } + const fbpos_t w0 = w; w = MIN(FBW - x - 1, w); h = MIN(FBH - y - 1, h); - const uint8_t row = y / 8; - const uint8_t rowrem = y % 8; - uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; if (rowrem + h <= 8) { - for(uint8_t i = 0; i < w; i++) { + for (fbpos_t i = 0; i < w; i++) { // all within one cell - uint8_t mask = (map[i] & (0xFF >> (8-h))) << rowrem; - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } + const uint8_t mask = (map[i] & (0xFF >> (8 - h))) << rowrem; + draw_mask(cell + i, mask, color); } return; - } else if (rowrem == 0) { - // Optimization - uint8_t mapc0 = 0; - - // First - for(uint8_t i = 0; i < w; i++) { - uint8_t mask = map[i]; - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } - } - h -= 8; - - // Middle - uint8_t whole_cells = h / 8; - h -= whole_cells * 8; - for(uint8_t j = 0; j < whole_cells; j++) { - cell += FBW; - mapc0 += w0; - for(uint8_t i = 0; i < w; i++) { - uint8_t mask = map[i + mapc0]; - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } - } - } - - // last - mapc0 += w0; - cell += FBW; - - // last - for(uint8_t i = 0; i < w; i++) { - uint8_t mask = map[i + mapc0] & (0xFF >> (8-h)); - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } - } - } else { - uint8_t mapc0 = 0; + fbsize_t mapc0 = 0; + // Draw the bitmap slice-by-slice based on how rows of the bitmap intersect with rows of the canvas. + // This could be optimized to walk each row of the canvas only once, but the code would get bigger. while (h > 0) { - // First - for (uint8_t i = 0; i < w; i++) { - uint8_t mask = (map[i + mapc0] & (0xFF >> rowrem)) << rowrem; - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } + for (fbpos_t i = 0; i < w; i++) { + const uint8_t mask = (map[i + mapc0] & (0xFF >> rowrem)) << rowrem; + draw_mask(cell + i, mask, color); } - //mapc0 += w0; cell += FBW; - // leftover of the first row in map - - // last - for (uint8_t i = 0; i < w; i++) { - uint8_t mask = (map[i + mapc0] & (0xFF << (8 - rowrem))) >> (8 - rowrem); - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; + if (rowrem != 0) { + for (fbpos_t i = 0; i < w; i++) { + const uint8_t mask = (map[i + mapc0] & (0xFF << (8 - rowrem))) >> (8 - rowrem); + draw_mask(cell + i, mask, color); } } @@ -259,3 +210,73 @@ void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, u } } + +enum SevenSegBars { + T = 1, RT = 2, RB = 4, B = 8, LB = 16, LT = 32, M = 64 +}; + +static const uint8_t PROGMEM seven[] = { + [0] = T | RT | RB | B | LB | LT, + [1] = RT | RB, + [2] = T | RT | M | LB | B, + [3] = T | RT | M | RB | B, + [4] = RT | RB | M | LT, + [5] = T | LT | M | RB | B, + [6] = T | LT | LB | B | RB | M, + [7] = T | RT | RB, + [8] = T | LT | RT | LB | RB | B | M, + [9] = T | LT | RT | RB | B | M, +}; + +fbpos_t fb_7seg_dig(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t digit, uint8_t color) +{ + const uint8_t mask = digit > 9 ? 0 : pgm_read_byte(&seven[digit]); + const fbpos_t wi = w - th * 2; + const fbpos_t hi = (h - th * 3) / 2; + + bool bcolor = !color; // changed for XOR + + fb_rect(x + th, + y, + wi, + th, bcolor ^ (bool) (mask & T)); + + fb_rect(x + th, + y + th + hi, + wi, + th, bcolor ^ (bool) (mask & M)); + + fb_rect(x + th, + y + th * 2 + hi * 2, + wi, + th, bcolor ^ (bool) (mask & B)); + + fb_rect(x, + y + th, + th, + hi, bcolor ^ (bool) (mask & LT)); + + fb_rect(x + th + wi, + y + hi + th, + th, + hi, bcolor ^ (bool) (mask & LB)); + + fb_rect(x + th + wi, + y + th, + th, + hi, bcolor ^ (bool) (mask & RT)); + + fb_rect(x + th + wi, + y + th * 2 + hi, + th, + hi, bcolor ^ (bool) (mask & RB)); + + return w; +} + +fbpos_t fb_7seg_period(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t color) +{ + const fbpos_t hi = (h - th * 3) / 2; + fb_rect(x, y + hi * 2 + th * 2, th, th, color); + return th; +} diff --git a/src/framebuffer.h b/src/framebuffer.h index b0dcb44..c0cb1f4 100644 --- a/src/framebuffer.h +++ b/src/framebuffer.h @@ -13,6 +13,9 @@ #define FBSET 0xFF #define FBCLEAR 0x00 +typedef uint16_t fbsize_t; +typedef uint8_t fbpos_t; + /// Framebuffer backing array. /// /// The format is the native format for SSD1306: array of bytes representing pixels in 8 rows at once, LSB is the topmost row. @@ -26,16 +29,62 @@ /// and more bytes continue rows 8-15 and so on extern uint8_t fb[(FBH / 8) * FBW]; +/// Fill the entire screen with a byte pattern. +/// Use 0xFF or 0x00 for a solid fill. Other patterns may be used to create horizontal stripes. void fb_fill(uint8_t pattern); -void fb_clear(void); -void fb_px(uint8_t x, uint8_t y, uint8_t color); -void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color); -void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color); -void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color); -void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color); + +/// Clear the display (fill with 0x00) +static inline void fb_clear(void) +{ + fb_fill(0); +} + +/// Set a single pixel +void fb_px(fbpos_t x, fbpos_t y, uint8_t color); + +/// Get pixel color +uint8_t fb_getpx(fbpos_t x, fbpos_t y); + +/// Draw a horizontal line +void fb_hline(fbpos_t x, fbpos_t y, fbpos_t w, uint8_t color); + +/// Draw a vertical line +void fb_vline(fbpos_t x, fbpos_t y, fbpos_t h, uint8_t color); + +/// Draw a filled rect +void fb_rect(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, uint8_t color); + +/// Draw a frame (unfilled rect) +void fb_frame(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t thickness, uint8_t color); + +/// Draw a bitmap +void fb_bitmap(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, const uint8_t *map, uint8_t color); + +/// Draw a 7-segment digit. Returns its width (without spacing) +/// +/// \param x - pos X (left top) +/// \param y - pos Y (left top) +/// \param w - full digit width +/// \param h - full digit height; will be adjusted down if needed +/// \param th - thickness +/// \param digit - digit 0-9 +/// \return width taken +fbpos_t fb_7seg_dig(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t digit, uint8_t color); + +/// Draw a 7-segment period. Returns its width (without spacing). +/// Digit height is (w * 2 - th) +/// +/// \param x - pos X (digit left top) +/// \param y - pos Y (digit left top) +/// \param w - full digit width +/// \param h - full digit height; will be adjusted down if needed +/// \param th - thickness +/// \return width taken +fbpos_t fb_7seg_period(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t color); /// Output the framebuffer array `fb` to the display device. +/// +/// The user must implement this extern void fb_blit(void); - #endif //FRAMEBUFFER_H diff --git a/src/framebuffer_config.h b/src/framebuffer_config.h index 56f495e..fec08c7 100644 --- a/src/framebuffer_config.h +++ b/src/framebuffer_config.h @@ -4,4 +4,10 @@ #define FBW 128 #define FBH 32 +#include +/* +#define PROGMEM +#define pgm_read_byte(adr) (*adr) +*/ + #endif /* FRAMEBUFFER_CONFIG_H */