From d07901835e1c636f9b8563a72064fa2f157b3069 Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Wed, 19 Nov 2025 22:26:52 -0500 Subject: [PATCH] separate display to its own file --- .../index/12x16_font.h.125E97BECC4A2F95.idx | Bin 0 -> 294 bytes .../index/16x32_font.h.59EAA6A309366CB2.idx | Bin 0 -> 294 bytes .../index/5x8_font.h.956A417EECDFFB55.idx | Bin 0 -> 292 bytes .../index/8x8_font.h.73482A7FF5D55E58.idx | Bin 0 -> 292 bytes .../FrameBuffer.cpp.99F4EF88006CE0DF.idx | Bin 0 -> 2348 bytes .../index/FrameBuffer.h.972498C5B5CB9A30.idx | Bin 0 -> 892 bytes .../ShapeRenderer.cpp.D8C300930C859AF7.idx | Bin 0 -> 2552 bytes .../ShapeRenderer.h.57908B8BFC3E1D28.idx | Bin 0 -> 1190 bytes .../TextRenderer.cpp.3DEF76874B13532D.idx | Bin 0 -> 2518 bytes .../index/TextRenderer.h.0082D7C40364FA63.idx | Bin 0 -> 1340 bytes .../index/hello_usb.cpp.617ECCFD7A3EF432.idx | Bin 0 -> 4184 bytes .../index/ssd1306.cpp.78D1B7CFAFD58788.idx | Bin 0 -> 4694 bytes .../index/ssd1306.h.EB52EF331888230F.idx | Bin 0 -> 4374 bytes CMakeLists.txt | 7 +- display.cpp | 86 +++++++++++++++ display.h | 73 +++++++++++++ hello_usb.cpp | 98 +++--------------- usb_serial.cpp | 0 18 files changed, 176 insertions(+), 88 deletions(-) create mode 100644 .cache/clangd/index/12x16_font.h.125E97BECC4A2F95.idx create mode 100644 .cache/clangd/index/16x32_font.h.59EAA6A309366CB2.idx create mode 100644 .cache/clangd/index/5x8_font.h.956A417EECDFFB55.idx create mode 100644 .cache/clangd/index/8x8_font.h.73482A7FF5D55E58.idx create mode 100644 .cache/clangd/index/FrameBuffer.cpp.99F4EF88006CE0DF.idx create mode 100644 .cache/clangd/index/FrameBuffer.h.972498C5B5CB9A30.idx create mode 100644 .cache/clangd/index/ShapeRenderer.cpp.D8C300930C859AF7.idx create mode 100644 .cache/clangd/index/ShapeRenderer.h.57908B8BFC3E1D28.idx create mode 100644 .cache/clangd/index/TextRenderer.cpp.3DEF76874B13532D.idx create mode 100644 .cache/clangd/index/TextRenderer.h.0082D7C40364FA63.idx create mode 100644 .cache/clangd/index/hello_usb.cpp.617ECCFD7A3EF432.idx create mode 100644 .cache/clangd/index/ssd1306.cpp.78D1B7CFAFD58788.idx create mode 100644 .cache/clangd/index/ssd1306.h.EB52EF331888230F.idx create mode 100644 display.cpp create mode 100644 display.h create mode 100644 usb_serial.cpp diff --git a/.cache/clangd/index/12x16_font.h.125E97BECC4A2F95.idx b/.cache/clangd/index/12x16_font.h.125E97BECC4A2F95.idx new file mode 100644 index 0000000000000000000000000000000000000000..9802ed5c2ff1b81b03c779eab6042626f8abba5b GIT binary patch literal 294 zcmWIYbaRtqWMFVk@vO*AElFfyU|4aZz$HH;`sx-oALn L4IQ2OJ_ZH=tV>ux literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/16x32_font.h.59EAA6A309366CB2.idx b/.cache/clangd/index/16x32_font.h.59EAA6A309366CB2.idx new file mode 100644 index 0000000000000000000000000000000000000000..c4569e11467556610e97675bd615a88d9d00a165 GIT binary patch literal 294 zcmWIYbaRtqWMFVk@vO*AElFfyU|C7z@33?0ltQM4 z*$Uhd{+0rdmq+X{*n1(gvApQYxoI0?H{9ZRF6($?&dD`K{~J5rANO-Ux;AcOMM}zx zuV#E|0V|KMs5AT>7$1;oe2byDGB-&P=o;yRPL@kbZXe}k0J@c#RfJUzOfYZ)<(L>5 znOPZ%Qqzj{kW?~qK~w;RK%nT$r!_Bko;nK@X5?U$fd~SHQ*#nQ?Bb&2Vs0SK#O%&d M9~xS^dl3Tz0Ck;UPyhe` literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/5x8_font.h.956A417EECDFFB55.idx b/.cache/clangd/index/5x8_font.h.956A417EECDFFB55.idx new file mode 100644 index 0000000000000000000000000000000000000000..2767bc69b141a6c84703db698a02f82f09b0e287 GIT binary patch literal 292 zcmWIYbaRtoWMFVk@vO*AElFfyU|5r`}1sGd5_b;v-#;bM)~btl=Q z?n|xzJFtW+DbDrr@j7$DhwJP6+O>M(eFy6r*>+~+E?e|6?u5C-+?egL<;IGsuNWUJ zQsFvR%%}53i_h5*VA zpYtGS`o)@L`}}(u$Bo`G6j$aZDFWSM!L5r`}1sGd5_b;v-#;bM)~bthT* z0PpgDjU4M-oM!p>sGL1hoJqxF|qV?$?>`IBd@0Tpt@j^1&!L6Lvdwpk|NM8KW=@v-{;r*o0kFTQf5{WRv9qCzzLLNVq|1y zWhhEbE7k+@ESa8Y%bu&6#K^_W$iXND6afR60YG7pZkTXUYEB}EU0jr0%nhWOn7wZ2 M3Z`7OU}s9}EDMZ?T8?|lNq?Y!iRUD}#lrAnM+V-8}ydCeE_q^xxywCZ*-{13`GyYy49;Rdn za*yDh`11PFrY*e#aC$2MTls0%^KCtAuvMG8ml>{*MJi`ySGjd`04XF}zbv|P3F z*t(x#?t6yyo{IGT*P=lcuNd!FG2AWUp7wO13)}E?WSpJMPUi0$uI9OV!<{IxlzixR zs{0GVBwMG}DEDdE?my#C#@bDPvEG{9o|M8Kc#<8hdiTzBt8l0+Jxca(zm3bD0Iqz# z?Q(D&@AS5=YcG<2(eKjud!mUrRIOO&jBq8Xb(7HD*`fVuEfEqCq1VskRkuZkeL~6= z1KVAf8m_#SWh`7XOj(rEt&4%)ItxW(s=h%OvxD=&v4*lUdRm ztnz#kf(@qJa6o$}7ZuXL8zWSBBl zH4xGe5NwxjZ62wW7#yRs=0`>HF{jY995<6e`MH#HZ;BtPhWl80AFqEkUAZ~9a8H_K zY zpQrV9japIIpnSsa#bAtCPxqQOnh8wkq`=b&o9%`pFYd^_&N;iTM!bCVQlL&<6JOwY z*!HrhmhklvsfW6 z@spIcvnP`VzOyoo_MhX9_>~~cx1~O_sY&MNdHorE%V`4R9?F->l8V< z>?}K1nJ^=g_gjT@mC45}Z7eD+evfquBVMx97!eBg)u9Gj$%kI5xNeMT|5-wjKW>PD z^VvPftpsatk6P^-^9`fw#6lh$ER)r&e4J9G5zRkd@{8R2!D}|@bz;4A;@Niob>rvo zkyY1L_njE-v-ISLJ$y1YTiw1oI-4`)vSP3>Otqk7EaSwm`?C?XzWYtS(b2V!@5?!V z)$I482CRCR=6vCn(0gBR;lqx~=Z(exXSRLabdc954wxelMTzl=&L_L?56rhltgn<^ zZSMT@XrSO}?_AU6`is`3HCwFe2Wui)BFf_e{wM#~e!E+@PoI}KcZm|%$#YzG!RVr` zdGl^p4NYne38+hxww-Pbycw_Yh{3r~TC%--(`Hf#H7oGu5^h#jwQk6RxOau`^|n6C zw#li)%*=(?$E@k zI2((p@h35CqUmqFL#*nI&qnewQCpU?^tR4Df1+BNJLOh`>1fBBB;A=$k@D7;j@-X@ zw~#*GbM6fG3fb*B{rtmK(bjp(yrGbLb%u5>hu>915yV33=+}*pzRC+SUJJGf-OtXP zzp%RFuP72JH!bSz)P*A-!uwL&>>LXxzI=Y$Q1Vr!s#tOv5=(^+RQAtbkU^;&Vt2+X2Q&aEyG7#a-Eda%s?_1EC?0R&4W<_s)<{A#F_;`&5D;OB3rPaG!)y# zm~8xQmjvG0do#t=Z&2jmf`vk(U{hFR*0(9~(L2TN2n3OXT>F_t=e5Zixv&aF1;rP@ zP?fH#hsTE@l|n`F!5GphbQE6&Lp_Qfil>C3A>B|9KQ4ww6eDyIa=@( zbKH!t08?^dW#{;}@N+12Wzo2f@2J$3?czFqGNrDp6xZ=AmAbM=T*qTm>dNwP9Zy%O zD;vXg{7JzMi$I7vK39p0#$rfdsjDS OC(nF%9UndbL;nF<=Z}y8 literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/FrameBuffer.h.972498C5B5CB9A30.idx b/.cache/clangd/index/FrameBuffer.h.972498C5B5CB9A30.idx new file mode 100644 index 0000000000000000000000000000000000000000..fc4d5881af98a43f3f02d6b8c461a7373ca9e793 GIT binary patch literal 892 zcmWIYbaN|VW?*nm@vO*AElFfyU|k&%I+Vvg^GgIUamJT8AVe>H~a zw#s~)7F3nvqu-jTd#g=LHN@X2Sv_no;Vf!^lE3XQJz(c@N=F0 zn}1m^u-doBZoT2Z>xW&hEkfpI~jMJO`pV2T$!6>0rU%Jn8O|Mi7Q3; zm{^z?IC({QrN9IO2hguTV5H)Em|b7aL7a()2_nKN%p%MRlm5N8w?6iQMWp}}2TWRz zQ;!cOZD^~`FU!+7Re*^dCauA#Apnyu{Nuh+?9Q460!&;mX+sf1ahUYS$>l+a7w_0VWG>& z$q5Qom?5xG1qy>g6DAA`O`tF+6k)=!Py`BtLJuYk3q7DPDAZuWuuuaEgF*`?3=1uw zFesE@!Z4bd3lcg|hx4Eq$-^nkDhxNNC^aV$q^!6oxtJSBGjaAXzP#_z^zk+W0{|kO B80G)~ literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/ShapeRenderer.cpp.D8C300930C859AF7.idx b/.cache/clangd/index/ShapeRenderer.cpp.D8C300930C859AF7.idx new file mode 100644 index 0000000000000000000000000000000000000000..f233c05c06fa6f6aa2524bf824b80e50469a6028 GIT binary patch literal 2552 zcmYk72{csi8^`C4b!43x%Ot{B$7Ibq%2<0X+1DSk%Qj&~O7h1bdorm+WLHs{lu-Rh zw(MI{60KS(+ep!W{5m>w&$;*9&-;F#@AEz9ea^iO7Ut&P5HOfYfW>iAV6-ng3b*k|+6`IM z%|4MI>n;gPRa1S4bFEws38Bifx7a7dXG3QyDiXaJ`}DmNCTz~2xigyTG6_V10M3Fg zXF3ntXIBoiq^mKkmGh3{QEga z86M84*s=bE`YEfG(7G47Ab zT%*4BU?k3lKiru~U-~FMSj@ZUcURHrPa{6FIp#0d-gRXV>RRrFm$7c9=6kr zKdTfR>zMXrQmZ&O{@B}bs?T+gi)ijyI-d~CNVl>2*zlXKxU%kHiG(ZK&*tqT5~f+pCUwzM`H%!=NdUL>z%_8Vp12A13gf!`X-ba30y!p;pviL zY3Xd={K`Z~QNT)@=*H7fE%yg1Bh7@{jABmg=i~;6?e~$_%igw8)V#KLiAg%mJ5Cm0 z!p0*mNXgb~HfG9Fj&KcXpX+=7U1f|vPb1!HSe&bIX=M7;a?qy2^r~~5_vIlXp{G>f z^nz;}X_qOqfkx~EpUnB{?806Fa4X+bzRaH1 z-Bc3R{_L_Y%{WKRxPzYOmw_B}DDIcDL5jSUc@aISGG6$~E7ZIa!%(O72(}T$gzZ{~ zuHtt4A+MgK}TUlsVUAn=Y<7*~>x=-ro&@NX9kjl86KAxQ#BuE!Q))eNMyT8m8 zOOwZv4qNd1J2dx?*=ZI8MdIBCvEdyli~(tc-s`Zju3TMT%=`DS7sjz$q&Y+)S>+T+mx_&16 zyn0ynLPiF~KY(&&vhLnNyH0$XKN)4sKp^{q(#7<3cA(EKfV}ED!$AdI^=t73{E9KY;B1IkgabJ1tke+O3?|Rz0;sNjEaaEzHclI-XzeA){qr#PS1J2(Vq} z8KmoTxu>fj>(bnAs8xT;dem|qyR$Zz_w!)w5azYwwBcsN%v#^wgq5C~;`;b7pYjrQ zfGtZlYVni=li#l#Nbp}$?UH#d+hLq`wpcbA3dN6LeeYKdsZB60^Z1D<^`d`OiZV`? zl*=sDo|jAU+mKv+UMx)`eGPsWS;K+cKq5>E}k5TUXxkrQ=RE3!MHZZF7hX`)OZjYC~q)e&+%z@vEfvosy8v zrv9I0@C&I;rkM5cexDRcHEU&&_piDeU98s(F~fe(mli0`u~_=5PSIH@B8(DC@{42s zN!(P$0!{22F7U!Kp)(LH8-kg88{Zut8~19+Uw=IS_{zs_@1c$oC2_EbEVu zh$1qDNCc88WQU*nD?A{m4$c?zxADSG{}BQdUSj|_ zM<VG?DLjVWVxBY?5=9cRfJSn zcL~A-)?I61Yl&^ow6%_pPWFrx{;ebia1$02IDp%-q7&SM6@B1`S&(QzG+~KNJVV_ud3ChR7xXv%KNie~I)e{s7AVtQ_k!?x#k&#m>X)8Ag-3|`vM#879q z4w?+^eOnqpPP+FxbBj1ONw+0s$M~1w4Q^I1XaL2@nT7fjtNYA;1lUfk5C2 z+(8lq4g+7{4}t&*908#q64-%5zz2{)1o$6_2jRd8I0HWr1t{Psa0Dm8F<=W^KmtgF fKs1N}|5#WaFjPNiVrFV?Y-E)S5v@5=A=v)`#rPOo literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/ShapeRenderer.h.57908B8BFC3E1D28.idx b/.cache/clangd/index/ShapeRenderer.h.57908B8BFC3E1D28.idx new file mode 100644 index 0000000000000000000000000000000000000000..fba88dbe4378882c38d9f495739d18635ca447dc GIT binary patch literal 1190 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 A*Z=?k literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/ssd1306.cpp.78D1B7CFAFD58788.idx b/.cache/clangd/index/ssd1306.cpp.78D1B7CFAFD58788.idx new file mode 100644 index 0000000000000000000000000000000000000000..c9d29183dd3fb9748d63f099d8a1f83bb90d6e89 GIT binary patch literal 4694 zcmY*c2UJtp7R^m)5fUDcgx*6hLlKoG2tF`?q69@niV^7`NC*T0L0Z%xSb$MSKt+_I zG!;bA!O<@QGKgjDZLo~`QAcM)RPeuN{>^%_7HhHh+4tOY&pG$p2hZQnF9@Yj=CAb^ zrNm_LO#@_GNm##f=;tqC6$jEf_wzHPZI7v`P zYi>$M%T7(~P41dI>snF_7-56g)zeJuRl-!$dg~0Xw1t!z9_{%sw72`Opi_EZYQp-R zEzX@3#Rnc>3%UCB{JgC0BcTaT%Z)>ZCN5Mb9C`B(t5ee*+4SYLSDE{VWAW(kM;;_5 zi?1hWfyQr{ia_Ji{HvujGOnnzhv-wPdv96X&ST}cWqzHPD{3bpFHHXqP~78L%V0O z{^#FP#&0)SCAzODpC!5Lexl6d*HCJ|zJ30@1J$XeV`oP*&+8Q0`Dw~85`E1aZ44aA z@^rrw@_O{ami7O52o`7xcB&+KEyjjWe*k6yH($gh}^No$$mG%=7lap1nQqL}L* zy7yhmMTgD$6GytUUOt!}DJ{BpJ}$4P;EuQ4+|$4F6>57bF|PU%k5vM1Pp#Q)&C5*o zoZEf#(Yr*^EQbc}!eEuL;uo%Qu_=m2MM3JjI!$dtt_|;{PtWnMJi1^%TSM*{_To$lyF(TJWSXdw@}C;p-Z3s=&Nbb?eb$$DX^@lY{f_ z&nx6cZY|zlxpl|O>s5V!UdXs?Ga&LVPAJND2+SMgUd%Qh=FON{Z!>ei;ok0B`P$s( zj1&B4&&-x?yzt4U+}Bz+`rD<;Q`N^@mao4VW|d{^Khu&ztvGZaVYPuW7d?@75LG=YUQ1%8Ir0*5+*=&+j~^;w!lJbFlT^ znhOQViUWcdFL+NF+8_5jKeW62+;*tTmA9ocpyfq<;uuRi^y;^xBKHmYH~gBX>9rGo z*KyV!zh+%|vZFaW)+2jVexdd5u7)>bD>c`JTs`g-swrWP%y=GD`DuY>^X1TCV@hTv7hy?!lOe^qon+EZyV1^n#Io z`-OqWMu~nJ&aZ16&-o}{X{^>y*etd=tkFpMw(7OfmYp>@w$lpo2fR-fYlRzasB`i3 zc8io7wlle8_0x@SLRa~$iM0}|nQf_Kd=HB|C+WB5eHc>YFU_-g^Y1|PvTL?C3moPY zt8HTYd!_z5)!uIyeP!zHG9K&FnkP35>0mYu@YDisK|SSraub2P<3z!0EN(!#;oL_O3h zgt|>CX#!{y&=-RZj15{))a$#k%XrCOyEUkVQW1?oV~GJziKhxBf9#P^pSow)A=DzN zL;@HR;#9GWSXsy$e6A+(J3S8}REbm+hsNoNK?Ea06Z%Pf>U!0by1xOT?vP5l0NMq# z#Gn8$3V=G4)%I>#wBViG3xv8^Dyso#4KNggOh%>-6gfLL`giVo_!6O(NJR$$dJwS1 zAdnG=K+$Y}n~J^x#dipGyHwN(&`zK&26>D;78Iq�uJHP$&uQHSdNlx>12jDKJOO z&0u1T%$53Asj}nPb#R27W9NeCdwqk04yK?_5f@b!XMEo&|7q9BjP#aVkD0*r!(p5ByRzn086+W zw??=|c#>e0Ta*_G^4<6{`1%TGpgrJ&i5$KPWuh7+pS8fD7P!FL;PyJ8R0ohB2v!}? zgT%El1FcEHFQ!D=N`Xcxu!aXwv`cnuGwm}cEcS@KA>1VF*|bCM3s-A`*F|(qATLzo zS|;5Pxhdd$1R9}FiaiRAB11mPCqtpO&=j^MzBZScs|{}r4%+~;4QRt^`Fx(8`*hbm zZ(?(rCCveDKCdRw$6T*)ArPP77gD?niR zaiSB@I{^Ym22OMVdKW<8(311!xp~D7rV|NQU@EXlClfh{=8$4<01gdc4&3|Gj`W51 z>)Qpyx-{K18|fQBq2N$xEA${ik(X#Ogl!Y2(~jS~mqGNCF=A{=+N~C#wZI%+Gnhgu zJ{^chf|TJZU{D3jVV1s}-IgD5)g_y#Sgua4A1b9k-FAVfM5h4L$B%%!HmHp6-%57_HKxlLSTd8Ygi z1Hf1$%kg)A#tpy{`rDOdGhXp->uq9V1H`}x9sq~U0Br^)uv4bvKTOTkE__Tp=v+sx z8;l%>;jD1-!xpIFopoM@9CltPO5kQN6AW8sQ@&kc?$>8&dw4@d=Yk?X(KYo1arz1Q*?z9;& zn}Hgv3r@5EX3G!6alkwd)Zj?K72SZ@4b)&W3$5LUKkjTCCz2jv5Fx7$TtFmU`Yj4~ z_090v9OR}rL98eO8b!bcMx1!zl`$GM@P)9%qwyv%vFS0%eB!wfq(=*Mh(E;mKOq1A zp_PK@OLf~d@~Xr@45CxkCZEAA`6t0f8dXkSK~af5Ls^BvR7KQKbrxGgQ%hS%S5M!- z(8$GVVFD}=<6${iE|!L+W1+r&^WE+Iy}al7c+Oq01$c15CP4Wg^b7#< literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/ssd1306.h.EB52EF331888230F.idx b/.cache/clangd/index/ssd1306.h.EB52EF331888230F.idx new file mode 100644 index 0000000000000000000000000000000000000000..ba46c70ada0c3853544a03fd3efd1bf7365e88d7 GIT binary patch literal 4374 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 +#include + +#include "hardware/i2c.h" +#include "pico-ssd1306/ssd1306.h" +#include "pico-ssd1306/textRenderer/TextRenderer.h" +#include "hardware/gpio.h" + +#include "display.h" +#include + + +using namespace pico_ssd1306; + +// Implement the methods declared in `display.h`. + +// Use in-place storage for the SSD1306 object to avoid heap allocation on +// constrained embedded systems. The storage is sized using the complete +// `SSD1306` type (this file includes the concrete header), and the object +// is constructed with placement-new during `init()` and explicitly destroyed +// in the destructor. +namespace { + alignas(SSD1306) unsigned char display_storage[sizeof(SSD1306)]; + bool display_constructed = false; +} +DisplayManager::DisplayManager() + : display_(nullptr) +{ + last_echo_[0] = '\0'; +} + +DisplayManager::~DisplayManager() { + if (display_constructed && display_) { + // Call destructor explicitly since we used placement-new. + display_->~SSD1306(); + display_constructed = false; + } + display_ = nullptr; +} + +// (No singleton accessor — the DisplayManager is constructed explicitly by callers.) + +void DisplayManager::init(uint8_t i2c_addr) { + if (display_) return; // already initialized + + // Initialize I2C for the SSD1306 display (common pins: SDA=GPIO4, SCL=GPIO5) + i2c_init(i2c0, 400 * 1000); + gpio_set_function(4, GPIO_FUNC_I2C); + gpio_set_function(5, GPIO_FUNC_I2C); + gpio_pull_up(4); + gpio_pull_up(5); + + // Construct the display object in pre-allocated storage to avoid heap use. + display_ = reinterpret_cast(display_storage); + new (display_) SSD1306(i2c0, i2c_addr, Size::W128xH64); + display_constructed = true; + display_->setOrientation(false); + display_->clear(); + display_->sendBuffer(); + + last_echo_[0] = '\0'; + refresh("> ", nullptr); +} + +void DisplayManager::refresh(const char *current_input, const char *last_echo) { + if (!display_) return; + display_->clear(); + + size_t input_len = current_input ? strlen(current_input) : 0; + const unsigned char *input_font = (input_len > LAST_ECHO_VISIBLE_CHARS) ? font_5x8 : font_12x16; + + pico_ssd1306::drawText(display_, input_font, current_input ? current_input : "", 0, 0); + + const char *echo_to_draw = last_echo ? last_echo : (last_echo_[0] ? last_echo_ : ""); + pico_ssd1306::drawText(display_, font_12x16, echo_to_draw, 0, 20); + + display_->sendBuffer(); +} + +void DisplayManager::set_last_echo(const char *text) { + if (!text) return; + strncpy(last_echo_, text, sizeof(last_echo_) - 1); + last_echo_[sizeof(last_echo_) - 1] = '\0'; +} + +// No C-compatible wrappers: prefer `DisplayManager::instance()` API directly. \ No newline at end of file diff --git a/display.h b/display.h new file mode 100644 index 0000000..af4fb56 --- /dev/null +++ b/display.h @@ -0,0 +1,73 @@ + +/* display.h + * Generated from display.cpp — public declarations for the OLED helper + */ + +#ifndef DISPLAY_H +#define DISPLAY_H + +#include +#include + + +// Display API is provided via the C++ `DisplayManager` singleton below. + +#ifdef __cplusplus +// Expose the C++ DisplayManager so callers can use the class API directly. +// +// Note: The implementation constructs the `SSD1306` display object in-place +// using static storage (no heap allocation). Construct a `DisplayManager` in +// `main()` and pass it by reference to functions that need to update the +// display. This avoids global singletons and makes ownership explicit. +// +// Example: +// int main() { +// stdio_init_all(); +// DisplayManager display; +// // pass the display I2C address (common values: 0x3C or 0x3D) +// display.init(0x3C); +// while (true) { +// wait_for_usb_connection(); +// run_echo_session(display); +// } +// } +// +// void run_echo_session(DisplayManager &display) { +// display.refresh("> ", nullptr); +// // ... +// } +// +// Forward-declare the SSD1306 type to avoid pulling the full display header into +// every translation unit that includes `display.h`. +namespace pico_ssd1306 { class SSD1306; } + +class DisplayManager { +public: + // Initialize the hardware and display. + DisplayManager(); + ~DisplayManager(); + // Initialize the hardware and display. Pass the SSD1306 I2C address (default 0x3C). + void init(uint8_t i2c_addr = 0x3C); + + // Refresh the display content. Either pointer may be nullptr. + void refresh(const char *current_input, const char *last_echo); + + // Update stored last-echo text used when `last_echo` is not provided to `refresh()`. + void set_last_echo(const char *text); + + // Non-copyable + DisplayManager(const DisplayManager &) = delete; + DisplayManager &operator=(const DisplayManager &) = delete; + + // Implementation details kept small in the header: pointer to the concrete SSD1306 + // type (defined in `pico-ssd1306/ssd1306.h`). + pico_ssd1306::SSD1306 *display_; + char last_echo_[64]; + static const size_t LAST_ECHO_VISIBLE_CHARS = 10; +}; +#endif + + + +#endif // DISPLAY_H + diff --git a/hello_usb.cpp b/hello_usb.cpp index 5dfd059..626ca0a 100644 --- a/hello_usb.cpp +++ b/hello_usb.cpp @@ -7,55 +7,12 @@ #include "pico/time.h" // Needed for time_us_64() #include #include +#include -#include "hardware/i2c.h" -#include "hardware/gpio.h" -#include "pico-ssd1306/ssd1306.h" -#include "pico-ssd1306/textRenderer/TextRenderer.h" - -using namespace pico_ssd1306; - -// Global display pointer so helper functions can update the OLED -static SSD1306 *g_display = nullptr; +#include "display.h" // Holds last echoed line for display static char g_last_echo[128] = ""; -// Scrolling state for last echo (marquee) -static size_t g_last_echo_scroll_index = 0; -static uint64_t g_last_echo_last_scroll_ms = 0; -static const uint64_t SCROLL_INTERVAL_MS = 300; // milliseconds between scroll steps -static const size_t LAST_ECHO_VISIBLE_CHARS = 10; // visible chars for 12x16 font on 128px width - -// Refresh OLED with current input (line 0) and last echoed text (line 2) -static void refresh_display(const char *current_input, const char *last_echo) { - if (!g_display) return; - g_display->clear(); - - // If current input is longer than 10 chars, use smaller font to fit more text - size_t input_len = current_input ? strlen(current_input) : 0; - const unsigned char *input_font = (input_len > 10) ? font_5x8 : font_12x16; - - // Draw current input using chosen font - pico_ssd1306::drawText(g_display, input_font, current_input, 0, 0); - - // Draw last echoed text using the larger font for readability - // If the last echo is longer than visible chars, create a scrolling window - size_t last_len = last_echo ? strlen(last_echo) : 0; - if (last_len > LAST_ECHO_VISIBLE_CHARS) { - char window[LAST_ECHO_VISIBLE_CHARS + 1]; - // copy up to visible chars starting at scroll index, wrapping as needed - for (size_t i = 0; i < LAST_ECHO_VISIBLE_CHARS; ++i) { - size_t src = (g_last_echo_scroll_index + i) % last_len; - window[i] = last_echo[src]; - } - window[LAST_ECHO_VISIBLE_CHARS] = '\0'; - pico_ssd1306::drawText(g_display, font_12x16, window, 0, 20); - } else { - pico_ssd1306::drawText(g_display, font_12x16, last_echo, 0, 20); - } - - g_display->sendBuffer(); -} // Define the maximum size for the input string buffer #define MAX_INPUT_LEN 64 @@ -65,7 +22,7 @@ static void refresh_display(const char *current_input, const char *last_echo) { #define ASCII_BACKSPACE 8 // Helper function to handle the echoing and resetting of the buffer -void echo_and_reset(char* buffer, int* index_ptr) { +void echo_and_reset(char* buffer, int* index_ptr, DisplayManager &display) { if (*index_ptr > 0) { buffer[*index_ptr] = '\0'; // Print to USB serial (ALL CAPS) @@ -82,15 +39,13 @@ void echo_and_reset(char* buffer, int* index_ptr) { g_last_echo[i] = (char)toupper(buffer[i]); } g_last_echo[i] = '\0'; - // reset scrolling state whenever last echo changes - g_last_echo_scroll_index = 0; - g_last_echo_last_scroll_ms = time_us_64() / 1000; } *index_ptr = 0; printf("> "); // Update OLED to show cleared input and last echo - refresh_display("", g_last_echo); + display.set_last_echo(g_last_echo); + display.refresh("", g_last_echo); } void wait_for_usb_connection() { @@ -101,7 +56,7 @@ void wait_for_usb_connection() { printf("\nConnection Established! Starting Echo Session...\n"); } -void run_echo_session() { +void run_echo_session(DisplayManager &display) { char input_buffer[MAX_INPUT_LEN]; int buffer_index = 0; uint64_t last_char_time = time_us_64(); @@ -122,10 +77,10 @@ void run_echo_session() { printf("\b \b"); // update display to reflect removed char input_buffer[buffer_index] = '\0'; - refresh_display(input_buffer, g_last_echo); + display.refresh(input_buffer, g_last_echo); } } else if (input_char == '\r' || input_char == '\n') { - echo_and_reset(input_buffer, &buffer_index); + echo_and_reset(input_buffer, &buffer_index, display); // after echo_and_reset the display is refreshed inside it } else if (buffer_index < (MAX_INPUT_LEN - 1) && isprint(input_char)) { printf("%c", input_char); @@ -133,28 +88,19 @@ void run_echo_session() { buffer_index++; // update OLED with current input input_buffer[buffer_index] = '\0'; - refresh_display(input_buffer, g_last_echo); + display.refresh(input_buffer, g_last_echo); } } if (buffer_index > 0 && (time_us_64() - last_char_time) > TIMEOUT_US) { printf("\n--- Timeout Reached (5.0s silence) ---\n"); - echo_and_reset(input_buffer, &buffer_index); + echo_and_reset(input_buffer, &buffer_index, display); last_char_time = time_us_64(); } // Advance marquee for last echoed text if needed size_t last_len = strlen(g_last_echo); uint64_t now_ms = time_us_64() / 1000; - if (last_len > LAST_ECHO_VISIBLE_CHARS) { - if (now_ms - g_last_echo_last_scroll_ms >= SCROLL_INTERVAL_MS) { - g_last_echo_scroll_index = (g_last_echo_scroll_index + 1) % last_len; - g_last_echo_last_scroll_ms = now_ms; - // refresh display to show new window - refresh_display(input_buffer, g_last_echo); - } - } - sleep_us(100); } @@ -163,30 +109,12 @@ void run_echo_session() { int main() { stdio_init_all(); - - // Initialize I2C for the SSD1306 display (common pins: SDA=GPIO4, SCL=GPIO5) - i2c_init(i2c0, 400 * 1000); - gpio_set_function(4, GPIO_FUNC_I2C); - gpio_set_function(5, GPIO_FUNC_I2C); - gpio_pull_up(4); - gpio_pull_up(5); - - // Create display object (address 0x3C is common). Adjust size/address if needed. - SSD1306 display(i2c0, 0x3C, Size::W128xH64); - // rotate display 180 degrees (flip). setOrientation(1) flips screen orientation - display.setOrientation(false); - display.clear(); - display.sendBuffer(); - - // set global pointer and show initial prompt using larger font - g_display = &display; - g_last_echo[0] = '\0'; - refresh_display("> ", g_last_echo); - + DisplayManager display; + display.init(); while (true) { wait_for_usb_connection(); - run_echo_session(); + run_echo_session(display); } return 0; diff --git a/usb_serial.cpp b/usb_serial.cpp new file mode 100644 index 0000000..e69de29