From 9b39b25e7f8a74d795625371cadc56676068f48c Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Sun, 26 May 2024 18:18:57 +0100 Subject: [PATCH] Add automatic provisioning of the frontboard, from mpy files in github TODO: This currently still builds the files into the firmware, the github action needs changing to mpy-cross these independently --- .github/workflows/build.yml | 2 + modules/app_components/menu.py | 10 +- modules/app_components/tokens.py | 6 + modules/firmware_apps/poweroff.py | 34 +++++ .../frontboards/TwentyFour/EMFTwentyFour.bin | Bin 0 -> 31212 bytes modules/frontboards/TwentyFour/FONTLOG.txt | 139 ++++++++++++++++++ modules/frontboards/TwentyFour/__init__.py | 0 .../{twentyfour.py => TwentyFour/app.py} | 8 +- modules/frontboards/TwentyFour/tokens.py | 42 ++++++ modules/frontboards/__init__.py | 22 +++ modules/main.py | 45 +++++- modules/provision_fb.py | 80 ++++++++++ 12 files changed, 371 insertions(+), 17 deletions(-) create mode 100644 modules/firmware_apps/poweroff.py create mode 100644 modules/frontboards/TwentyFour/EMFTwentyFour.bin create mode 100644 modules/frontboards/TwentyFour/FONTLOG.txt create mode 100644 modules/frontboards/TwentyFour/__init__.py rename modules/frontboards/{twentyfour.py => TwentyFour/app.py} (95%) create mode 100644 modules/frontboards/TwentyFour/tokens.py create mode 100644 modules/provision_fb.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2908417..6f11fa2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,6 +65,8 @@ jobs: micropython/ports/esp32/build-tildagon/partition_table/partition-table.bin micropython/ports/esp32/build-tildagon/ota_data_initial.bin micropython/ports/esp32/build-tildagon/tildagon.txt + micropython/ports/esp32/build-tildagon/frozen_mpy/frontboards/TwentyFour/app.mpy + micropython/ports/esp32/build-tildagon/frozen_mpy/frontboards/TwentyFour/tokens.mpy - name: Create latest release for tags uses: "marvinpinto/action-automatic-releases@latest" if: github.event_name == 'push' diff --git a/modules/app_components/menu.py b/modules/app_components/menu.py index ced6654..b2a35e2 100644 --- a/modules/app_components/menu.py +++ b/modules/app_components/menu.py @@ -4,7 +4,7 @@ from events.input import BUTTON_TYPES, ButtonDownEvent from system.eventbus import eventbus -from .tokens import heading_font_size, label_font_size, line_height, set_color +from app_components import tokens def ease_out_quart(x): @@ -21,9 +21,9 @@ def __init__( change_handler: Union[Callable[[str], Any], None] = None, back_handler: Union[Callable, None] = None, speed_ms=300, - item_font_size=label_font_size, - item_line_height=label_font_size * line_height, - focused_item_font_size=heading_font_size, + item_font_size=tokens.label_font_size, + item_line_height=tokens.label_font_size * tokens.line_height, + focused_item_font_size=tokens.heading_font_size, focused_item_margin=20, ): self.app = app @@ -91,7 +91,7 @@ def draw(self, ctx): ctx.text_align = ctx.CENTER ctx.text_baseline = ctx.MIDDLE - set_color(ctx, "label") + tokens.set_color(ctx, "label") ctx.move_to( 0, animation_direction * -30 + animation_progress * animation_direction * 30 ).text(self.menu_items[self.position % len(self.menu_items)]) diff --git a/modules/app_components/tokens.py b/modules/app_components/tokens.py index 717f0c9..5c7b6b2 100644 --- a/modules/app_components/tokens.py +++ b/modules/app_components/tokens.py @@ -41,3 +41,9 @@ def clear_background(ctx): def set_color(ctx, color): ctx.rgb(*ui_colors.get(color, colors.get(color, color))) + + +try: + from frontboard.tokens import * # noqa: F403 +except ImportError: + pass diff --git a/modules/firmware_apps/poweroff.py b/modules/firmware_apps/poweroff.py new file mode 100644 index 0000000..97f3ad4 --- /dev/null +++ b/modules/firmware_apps/poweroff.py @@ -0,0 +1,34 @@ +import app +from app_components.tokens import clear_background + +from app_components.dialog import YesNoDialog + + +class PowerOff(app.App): + async def run(self, render_update): + # Render initial state + await render_update() + + # Create a yes/no dialogue, add it to the overlays + dialog = YesNoDialog("Power off?", self) + self.overlays = [dialog] + + # Wait for an answer from the dialogue, and if it was yes, randomise colour + if await dialog.run(render_update): + import machine + import bq25895 + + bq25895.bq25895(machine.I2C(7)).disconnect_battery() + + # Remove the dialogue and re-render + self.overlays = [] + + while True: + await render_update() + + def draw(self, ctx): + ctx.save() + clear_background() + ctx.restore() + + self.draw_overlays(ctx) diff --git a/modules/frontboards/TwentyFour/EMFTwentyFour.bin b/modules/frontboards/TwentyFour/EMFTwentyFour.bin new file mode 100644 index 0000000000000000000000000000000000000000..7dbe6a1d61750e7f1e1105be442572512909d248 GIT binary patch literal 31212 zcmd_Td3aUT)d##lMUgTGkTC&-Fl1l|HVS zo+EmoF;R~jiKssQ;zo>38#cMLVkBVoucx_W$6+Acg(wt9UFhZ?qfr3y25@NO4>FQY z<1Y)4LyZ-XN0Zd0d>X8P0=oN(+*4>q=9;JGQ6Kfx0vWM8cjNJ=_G)T;i#)lmk%Bf0cYV7Bl6X=IGUV`jwR5uZnFyo)}G#|y)AT06y~7Dwcs zoBz1YPqFz1+C~Gzcwq^^tC!sQuTtF$akIlC^1@ITic?7FLJ8F50@l@q5@{skrwb*S zk!0HbwT$$kIZ*-n(|84>(57!>WB|RXo(j-SjGr!K(;UV|7ks?iw*sWoLG_8rv_w5V zmF{M&cA;r>hkCr&jFgy>nUq~0gzG|g7@*wTqs@@%>@yaDP`nyzy{2 z@LBX^^ug%yXbMr+de=}r@^Hy{ZgC@7{!I`+OT^ydgjVQQTOtT zOY9pS|1RuZ0#HFqZDJu>%8%bd9qE4JCD6VrSMa!ZbYf?J(a4xE4Ih1m9Kx%q{#7P;(1$cA^YD8o$B0d zJ77_3nodJ$;J)Y(nt5di$qSbRzP1V9vETlzpA+aw?dfhxR`2QE?pG0S-DmxLda%(@ z`qz%%`(Lzr-45)IcBkFZX;k`PkI}( zI|F~^MyzeLtag9xhE3L~{ijyYj#ewI*82x->UL`UDJy}pTXl;WWLd4cv>HdfPK~op zb=_d?i+MAq6x{14ebcw`oB6K?tD1YqNLcY*tm?i(r5oRFz8JF zL(tkzZ`STRr6%?k?Zm`d@x*GgYpq1ej**GA?%H}B^*)(to$9i|+Rqci`e<0?vatHr zLH^d(>bDLZTzwEPT-gQR8fQ^5e``#f-5ocdC;~R_fAQ%cKj{Li{tMtmuTSqa;Ro!0 z+jR3EC-?)mwsX9={b#~kn-tkJ|J6l41KyO|8~S)?B{g__zJD?|J8XS){M9uFw;X)P zqRp*eYQ1alYOCA9EPsQ)>`Ck7?vu-DOWW72c6&yAkZ^M9Nvl7FTJ~(=46xdCZj(s~ zC$p@RT|Nlz?evc!?%Ut)cHY}~*s)sg>hemX&l^4MR%oFX-l)CiI)@f5ZWLY__d6$W zCOVitkCsu&L-aU33!X0>HEUAjAUzeasQL9>uW#NV!HQ`&XqdgTWQ7&KFMb*AJoJur z=-BdOpU|suf&I}q+8-TDr8}Wgu!=b9mugt^cc(l$sYdb* zP@q(IcPga07v-M0N_BUqc?OtIzpE!NTp$L>hMl85?Las-cF)$=#?F3vJ2d1^EgD9C zV$tGBTeNs%(c+Coi#HZ69>OXXEuOSRi-!=2MT>`45sMa2+M>miwrKIjqQx7F7Ejuu z#gn#Z@uV$Uys>EUq%B%Jtg_g+cql!wXz|9P#gn#Z@lY@N9&OQj011DGk{;Xo=z4qo zv%iiAZ-Dkbz5Uq=`>E<(ejtIKh|Z#fs0(dvhrzVgskp6KHObpbtlEJG%P&|LO6939 zTJ>`1Pa_|-|5&lk33S5@i)n+{xbSO>W+_&m^L>U-{Q6IC`NH>#ph{Ubh=G&2Tl`QD z>On6tm3shn53tGZ0n;NMQ4boXCf|cb8X(gE*#?-Zyo(9Th&MB(KiZMApVBk6Nvf~BkG~R*UnW$EsxK1SW)xjoxrZ>OnNB#1-Wd* zUs*IO>@g!fU=R0c@F(fchO!O5_ebEz`Xt>a27o9ZVt)RS3!5PCwI6MJvS!QHCorOTM2X}bIj2`jpA3gNgj5fjhg_~^u@c4efPP0-(kRUMe83O8V>aW`@PFT z)C=sF!wyw1u%Fuh{QRfV}HVbCo_!fEw(h-m^deI}!8!LjVih3F14G zuTiwP9Y}XyPl{EBjMsz_hesm(e?o~^pu9N|3)DbgO6HFy0;}S^CjzSy%OnD;GM_|X z_2MPD$1(S$)9+b_CqliCV(&c>T3z3hZ-4^DNQuzuGWkR*GLO$y44H^^31=qKe5C;r zX@MD8C^NK^F!4xRy;5F9A9~y-x+6@XBtx$xL$4%ERp^yu=#^yXl|-6eNu=qOgvpDf zBpG@oVHHBJBtx$xOkQk3lA%|Up;wZjSCXMu5@~uR8G0pQIlOi|857SQk5$0O3`YLs zM_{BDMF0fd$4|s7*};gqwB$s*NI@tWmZ+l5Kzj zxYl5#WT=#FYCcny#ZQJxd6IpAWZ*}9fMkQ8WT1pyAS3&V*)V$^42GUfpxLUMBa3Cs6)+8Js7S{ z_=n>$AaV6yq3lb?&vZQ2PoKjxXV=GUOs19eHe$xlTD>0jIR3z;FtLd!8$Z)W zfN*~p?ugG%@tb`ytT9K2%7~4peEya#_uwf9hSm43ef&GyhQG>hb{Oy~sG~4|IQAH^ zy=J(FBL%_?`6(yR73#e!y-ua_GR#cAm9n*+PtBH&3UjDqo%rybm$p|wS#52gC*!uq zt(%AdVHB+SDVxJ3zQ>WL*tz8qdjv+Tc7xJF32`NH)*vdWPN*L7vWFMi9I^77`5r&i z2cjqHq7Ot*13eY9^#Rk0-sl5i)PQ3yrK@114@B=TtT*~V;+8Wb^?}4`pupT*NXykd zMM@|1p^3r?c3&(vXAo%G8}Ubczw1@z1OT-9rs(pnKQ6 zKVxLkfKXqoUEHv~Si1&#Q$6-K`oftMZ>KNTE*@iFtn?zUqA!$;=(@gG@&uNYzF4vb z3Kcf`Vu1&6$>zAT-bgHv{W_k3MV~iX+W6D{&w>w^+A)X;=~ZySUC;ILt=O~9q0VQA z9{#bb96esTJP}@pwGkR#-?rkSnlyG|NSFxX`T1Q$(dK_xD zv4iz)++)t3*o{LGdc-0!u*og!Ijqj^2rYitKU3MAen3K7wio@dc1eQu!`d}asN}sL z*3RiQyFX^IVHDQh^75b{Jg^8vrYYvLekgtS%`|7_j{1%_3NkSf2@zu8^V&ZsHeP{C zwCMbu;eMQ0U_ipRML?2-Z*L=Afk57-&uahRGvLJ`iNPzTOLrZ`yyx4)uo=i09BBQlJ6N z^Zh~Y`ponFL2mIS`h(mWD5QJY}Ri)|T?TU^POLL_K=thb!)wwk^P- zi_{D6D;OH#kqCfbD8(qW6r<2msJ9Z>6bSVa_K{MIP^VylBDpD8pxD6_EKmdRc38So zus}`@+XFDoG+yA>+nNOH&wc@E1jBWRw*2E@lEC}XUD2h{#}Hg2-+<9D4A5*&3EEV+ zwwrUq@C3)>1Rz)xk_H3CfHjaN*YvI#{=U_2XS-+VlM^pmHM`yq?>hP7N$WFuzV)_N zt8I6(@x%EY+nW?c+!%-zqYj84PLV6XA>JHra!sS4)#31ntv$~ap7FNBtK@rxpCL%L z*XQOFb_D$&VH+_ei?D)tIQQO7Fs$!yJZw`=i=fZxDlx45 zLgJ8tfzSZpSsaf6z_XZ=0qn&w!Uq7)C)tx306dG=Jpg!?$Zh}}Gf}w%fM*UlZKOCU ziCwJzla>Tm#YL}59CQNab7T8IDMQ~L+$$!#HGBXu;>}@_#n3Y#*+O19;s5zRAU0qF z9cD?O`(fz+0I3s)A){>zm|85bd*}`Itq0mXDVf( zx|d#<^q9kdcUfB*;#4p`VIzCloo=NWnJ%Xg3Fn=u{Z)2oMgnE$Qh3u+6U#sCsPeXYk~|fSP0gF|4W}5Tj(t;`?on6P64R zTos4oPk0xD;9dNIN{5fWAp&7@z--fwCmtKU#_F)G!_)Nf(Pyk<+t#evcI@e6)<^Vo z`)%#ljJA#?9-Br3+fTDPB&Lr}Y+u|yG!TBK&}$$_DF$&MNGVR~K#)?xw}Buf*8=QR zpuL7Qf5wEVLFA4jE=QRdWHDc~Y6eF)!*<*w-0S|ha#-X8_Mbm%)r--x+D$9!A6#9u zJQ7MZlAB5is<@B}))GcaMUqF#4XN-_Br%l=*IKwP6%x^yB{voRv&=aa-m>svDh*NW zmx|@EfyO=Q%4DZvU1HW#5#8_tZA8elB@3%~zuu$4J3rc~c!M<(odq|s+4lYlh7=XH z2{~H!_CziuwFsi9)S|d@y!gpTw4(GA_BtW`_#0R?+K+rN^n&j}h{7lygjt%xY-Qjl zw0^DioaUU6XW)J>_~=lx2z}D2@HsI^QQ>b z%!z}+vr=1yg57#|yThWuo@sk~y)x9}xcvWa?x4T;RD?7Fd#J!Mi^@VkzDv2mr=x6V$*$a(UBt)ZDT`AIDC%{ zEul2zU)nq?BVkyyplFh}I1P3AnNjdko^sey`@$P9O?pfK)HrTZg3p|Q%11cxL39ti zlqaGt`-j6h*WEgGWMRL!@;EQ6MNp}3ei^Xpd(S}wa8jGFCcEn!-}@e%yRejzCW47( zf1ly7mI!lAg=(+4hd*I^f)ZX}BcMcz3+;ds28b0AXULH^{xG^f`kQF!w(U0r>o48p zD^<{L^+;9)#aC595>$beO2rt20)ei0hCV*V3S>1D$TP=60T^FNM+9JeHK1dM0B9;9 zc>py13r7k8&{PB3Z4ST$aKLL1!gT*;as?2F2yz8Okt^`2lvje0;MI}PAiP=ReGuL( z@;=BImqFkbRu}eQJax7`xP|?`pT7|GpP|2c@V?-G$t=Ols>~A8ia#70Y`!(vd~2}z z)?o9kU*pEXBk(P@LI~<2?#w%;1yNv7xt)I|#X2qwZ$!$J0D?izZ1d}5QE%g$BO{=! zd1OE}oCkbUl7<01aGog@NBHKZ-B8zkcCnrC_0QS7XHH z5mCaSAxJfd6&?Zu&4G`73m%p^H|T$N@aFXT5qE}~Mv$kmnjIZ?xSFZ}Jb4M$R%1Cn z-^>e?n+bEaZBUC2+L-gBCth`$pxh}=1;=P)L-&Y^YrQjVU8@U8$E?@kCTdj?_$ z8L$S>^wxb_XAYN}CmI{ek?6)2?}2@&x30W~8MgSb-<8;l!>sSR9v^--c3X;dBxX&_KKkgq_0{>~ z`!1dQ_H*k<+=|rCTRqXrQ^sXce=2BH>2vzt+PQ1z68fmq->pv78QYRBOuAqt(S(NG zZW!1UDeiAxzPM-i2iB33%TDg3H=6|ZL>tq(Xg6|UyTULhVJrUlgk1^eCY`ee(`_+b zTMkIEn#Z*sd0qT<66uX|UhEE$$+ z$j(fpf<4GrnDd#$`Hc?y%YAQ={cj0fS&seJz(3w{!~{T8n6{&C&VcuC&c5)!b;#0i zvBTrI0WY-)L7{JP6%Wcad>_~KFnOPyX%7K!Si&I&p#7Di296w#ckHD44>=x$+7=_e z9`&X}2$?(%E;&k+c=;Hp$n%kSkj`&gEC9-sc^7+J%sR})m!VLewzZ?xD{AP7^#;Rzg{`rgC19^pkY5PScNNHOssXCX?J-n$zQqY|+rO!E*$fm=*4L$>q7LiZ}xrj>NnP2TGR004Ig!~YFpI~p~Sd!t8@Da?c3A9OW@2Rdr4sS zdV1~NckE|Tj||yR=Hi*#Q05wNl#hfsK$XvIsKL4HN7+z=8YonH-bNCYdk=7Fo&gr9 zZUnY#owkBS9C^Bn*HEag?9m=)CW)Jf0}(D`jc)JiQ579XPDs zrOWTo?s{%c&C~w990tNBGZ18c4)O~_4#lZVse|Q+$LPQ_=Qa{tiZ>&@R07#Ck&6Ro zQhZtmsaFl8s)VhB9FBM?4*CV8TH%nb(BdEmE6p$tazbodUJeK+?K%z*o3)M!4W_{|+0 zO@t+y*bI#&(S%HaALo`Qs8m!;+rN^&Kk4HVjy=O%herK0MrW3ApA_ujC)jwvv04R& zl*A{7MoY%yOXy$fgQ+rL^`^peiRW^+f&mUiZAdfsV%ac=m``BUl+SxSG{n0Psr#a} z-E6uEMuP#5eGPmih0xsPBQFu=RHyi~ViXcNKL$rSj2uUp?m;NP?HwL>b1=Dyfkfm7 zL&Hpr^bV7I7M!VSrj2K{svwG^C#B7^NLtuF(sTJ9Q49Vh!lXWn-~eKPVYnN zBd{K+s>%3ENrNf{htzkuUjQOAfRhhus>o?MQX*l4$oxTJL{e%6mAfCv@aF9TfMZ*z*O9^{8WKiFeXD;O%pnzUtMKm0E zuE(*%aLAy3^F)=pA5N3ao3#uMM=eR(1>uWRbUcXiO4?Jus4`5v_V*E9J#6Ko0aDIe z9rruYT4FufmvGm7TVU=XdU|oApgXqLkh*)A=Xs>=o^R1U<*q$=EABy+VFYZ7D2EYn zwuQ$=fa_%PBfxbU$TUE<0Vb&BjKI1icQL{!{1Hask3fY^)cXkNA7RK5M&XZukn4|@ z89Pt^`j^gMHD)hEPb1ZyGpL+=DcjBxw&$1HA;R zX-FT5#ZN;rP3VD=XTXc~+1chya+sK=u=+|rv&Ss@nRB(Gz9g`L#$1tKBrLkFE65GLRq1nX_ z_DGnRCU)@3Gox%`lg&U~sqRihhzl|2zz`V3*=YR}Az~HpHW>a-!K#dKe#ebGQ7h|$ zak;Y|H-gJ0Aj0aGyDn}K~6KsPt_?0j6__#S?&pqf?^asHVTSSCN>HpBmUSZh>RYYt_<`jh>X5e zZZ3Idq{_T!wgC2MOks29|Ekb_HbYtIRn;`w%xAQj&uBBB(PloQfnIR}N1OSKM$d^% zbu{EuW;hx?q^xT+NWg%NniKs6i$?zEQ5#Cuw^}zF+@X7;{6?O^hU9xWcgzJoTatU6 zdgSy-pfSCRC_k4Qp=VslFz9W&d3aC+O?(OX3G4rn^f#m<0I-Y6#h~zY;9lu8KwBN6 zV??W5ACpGj)5tW zR*Eq&B^t;yK(+y`1_)(f?GiX=ASD0&c@Q@P zL7)bD(MM-wB$1xvPPq(NVd0hxgxlgMW&kbv@sS3|G(ffia_GIY@_4RVX$G|4x94Oe z-vEX5l)7gkjZ&9je3{uYfJ_a*_^J^d;$;AtdIY9cUGfZ|k(mKxO307_MuKb`*#a+37X~gBd1#utF=2H0jFm7Azu6% z<+|6%&8*iZIBEVLgYK-GZek$fa<&ZbQF>Lh)_2CC8f&!HSfjPZ8m%?fXsxkEYmGHp zYpl^)V~y4tYqZu_qqWB2g9B$`fm|@jx%F8!c>w=y^4wu7Gh~ku?G`~rj5DhkXI3%JtOD## zh10Q$6Qvo-$@y8)A3PoQzCsWxPR=DbITDF;5Gv_D4niGvS2*^(>f~?`D!Lbh@rkR2 zXth;Nj;xKPNt_(k;k5IcvXF!2 zq9Ym}V#&i_=^t)u8qv9nMFXTJbvr`#oJN(76%!a#(mkOHSnaQYb228bj?fLUk6g4E9f%Ps%yK2Ip1y7Zv61cz1v<{>z&Qr66QoR zdsaRJ9@<`nNw_OU63EtOBvQzPizU%SCX|dG$u~fOaAQzTi-(!x?fU zRvgKhOZx|V?_Yykuo0{aJ%GQI29g=*Sa0A;02%bREAE$feG8Vsn-eMXMCTJJ>#Y{M zTl}52ocgB+~>| z_*uZS^dx5i&(fTe1w6N7Gm!=KiptG08JH|&V1!IrK(7WSn>SBYh{}R05cePpszBnn zENB2dQf@}H=a8i{cy=~c8T0=e!3XUf3Zw9H;DINcz|rVPS`odAQi^C6t>XBC1(CN% zd0{lIp>}Q)hfAyq0-r=%(u4Su$}Hbw^`)Y7z0PKAPx)JPag^OG+4021OYu&5&jZ;v zpRl0;d=Ij$T2dLPhOGXdVh$~##2mmc#GHN6|93I3V}6v&|1Z@P$~HP7+vtRBqZ6`? zPRKSoAsf6Z$%kyC6S9p?$Tm758%!(8Asb99Dkapn6#P;rjQp8S=+q@ibb>|JshPEXKOB#0U}t(I+MC?H ztKM^7oYd+kK5dhj)js;(A}JmImrj7~{)tXFp7K8Hgx68Vech_vy(zr^#EKK{X6!S= zl#~Y|I$=C8COMh$K$HYNnd9 zFvHwDQ#t?Ru@y_Afbn2#!QpsJNdr1#HXeA^_mrFW=#1HT_zC)3I%75-o*qxko`A)z zo=F zqe~e52R5O@&1WEx0pfmq<*!lq3OYw*TP{k<+?Qh0dq}fz^2Osu7-TAJf}17)PgNLz z-{Wvv-by)`f>x#DD`A(j!&2B~Rb{|K8Or$(g62a@gWa zGalD{xrNW+h*Y}n#q@szB#7xZ9wXh3W<2hH=B6y0yP>GrkcmKDeQfsilv?ah7`I_FbV$&kX(Ifx)Qw!+Hl~h*~+*~fb*~KnP(oK zuULHodh1j?OD>w*YQ zw1#p>2U$7Dl*$5g*!Z%A&4KZi%|1D7eANgl2;a!1J}QlwgG{N!UpdH>O3QZ+GNsZC zoCBrDAq?I#fL{7e09_=_F~M36ilib|Imn$#+fNR1r_!Z^Hai1=7u9?8PPZIHcH&3n zAmG)2-ouiET|at6?_tS-PT0;-TMkr##CkbU1sW(ez;qQe=D_0XOQp)+$bp!POV#k0~YNYRryN}?Zg^73d^8Vz&+2}jbvr&&zIt#Ceg~f}B8~4S= zF=G=q+QXhYR%5H@^bUy`qeX#;`^|Yualfy2kfLotx!-+{ja}1WYy6XeM%X^z2yUQ! zA_H$1_PhEC>8Zfk0O5PM%YyeWOQf(InO&7NLZ7)r3S4hO(*v65ur72z+Eo3(6Wj)A zhjNW!%{7KK7lu`0{9N#u_*H85`K!1hs zJkUZ^K_28?8us$g6rpdnRMsdDVlK&|Jczl}q_APY0JaKz@<2*yZ^(m~izAc=G1ox4 zQYm>5b3Kx6fC=Uklhro!Jdpb!YppzxTS_*0aP0NSbXAwh1G)93QdR88gS<=CBM}&Sp1HZwj39r=nk^5?TnLv33hK2ZKgQ(FLrO@Da}avFdQPe z`CueD79ig+Qa%_-->exaAB-d$O!5sQVZ(`HqE)=VOH2h_pBr6Lit_5d41gEkAMN=XSZ^|25hLdF;T~3>N~w#vX1LcT<( z3qf4TSrvk~8c0_jQ6c0@k7OHQg7VM`L0s{y3PId?ob4$DarH>C8JVukdLf9bFO@2_ zTnOTdel7%Y_2U(0#4|Tnnvp8C!M_mlCG`tzK{1G$tLoi_tf<*C7DB$nmna0eg`)}~ zUyMT=J#DlW-q~1$FLnpCM!5}N{X_5{FChQ?+5EeWL%wL0INSRlc%shPMjw^!avKSI z@a|*p-;GN@t$Jk7dD1+7`#^qks0dURH=_tNl@PcHc$P?^2zb^&rU9}Ipab3_AX9>o zB1nn`rmKjf2*}hUrAl^+fJ_OTi-1ghsltrtV73T;i@s;J5*cjoSE{K9I!Yq(BH&O@ zOh+yuV5}z&;=<0>p$<;zu|*1;r?*EK2}(d%N>EL=U0yfCa?joOtqSspjSZ@52OrK% zv-v5X?+JylK(Vrs&+Gxa?MDdid-flFw`&9#|umZABt+4 z2-JyqP6X;?%l|}h9RoI6{S@lhLB5JQAR)|Z*_KuCe*saVsKZxBxHZ8=a8QR{AUwz; zSbKPYJqdTtLHQb9Fc+PC3_FQI=*j;D|+9?u1U@80sS%sMHMOBfMWw{OQiPA5Ed8@3(fT-p$EC0xKL zrdr>@xhsy#Tc42!uw6bAi#z=6$+#~2D|z1pca))Dz0)h5_DuMI+o!R!K1mv?x!EIZ z^`yM(6B=Z;5RT$4b`to+aEBZBsY#0(1Jbm{n{*k#u~Dx!-`?z{zUbnf68;i311oiJ z>81gvOHX@pnhR#YXW%$2)PW&Tj6>*U#k4q@BN#w$D$W4wq()xFZXB!TnuGO^MR%PE zoJTx%E_wiM8xJ;mpZoAVK8-}SE&m&tQm*L8)-Z{`^chn&cG)aFxufP?KTs3h9j%GJ z7A>9S+!Ew`OQ0=!y4%vnst*L+k3QG>kw=;phPSa)01wW;P*9GsLRrVQK9BtzPJY*1 zt6TT!-3QRrT94aaV6nJh)YQSQjc{l(#6f(U$q)w(^ipCz88uev@|uhshy=xx!Sf<1 zlaUO$ja}l&;CZnilaT`v)jb(zUAD?jHqq8(NP&d^lOYA7b|ym#G_XJbdkS#f8u^d0 zJC5~7EWB)}G;=Zqq}`PBNP$hj=xfoxDVbpodQd3`yu1&=x`j%sldH$P;qi`yS}+n<&Fpj>s3b4M#_BLv*228C z+d8p%-9NTfKT%z`KpaZsZ^Gt1lv;YxzoJvsDvtrge%P+0WyA9^!M^-QX|~ zngYTJb*6xD8tAD4u_@F`1=3(juNdt1so;b@)U5C1`3qBGR3gg z6ePyQ08Igp$!R20u&Y)-uC3k_Fq>Y^T;&5yG1h7dEWYFura$S{TMI5}!~heuw+9p?11b2&oMY6@A&lS+nE4 z_jaCm;RJ7n>bR}r>TGU@;~g|MF~CjL!gUMLiOP*YHdl+S4k=?MBy}q3WObvF7rI;+ zd;lutBoh3eN8Kz$n!F3kI@jZ~(FbCe_2bkKCvb2e9x~Dlgrnd9P;LOv0CN?$z&BNrG8MeR{9{i8CrBZcZSttT zjU$3pp($_4ks3XEtgwjybmu^933CGP%NCk8#4c>1spQ@9F5;#>Y!&9?CA%SWT!i?S zUb%8rYjK~9*pzlZvni)wQ)<|zoQ!TM>e{%ZaQudL!%S%+{?f>(pZ=K(>ZQY^jwVzshPOmuq z0X^Q?+8*~#-ieeG>R``D*$ct3S~mAqf{`*NBzKy{j5PMEo~K8C>hbvjFgIaBg2Lvm zhR`%a_i2Xi(>MTU!c8-Dp9aAf)ie##&6n(AMiO@pBSE1=?`m@eclciwy<;pg|A*-D zKC(K|<5S&4^zhU#L~jgqypYNGhr~G$jM%dCmjOAPXCgGeh_D=>!LrQd4bZDOMWY?b zMdT;mj&SHl z@mI>n>~R*)oqs4>{3z@42L~TJvSrn3i}&L5R(xw)yH)8&ld5NhiXn`W^DKriYCt#J z7en)lXI>12FM7ThT0q|uR6Jh{g)ah9427?OGy{w>z-R-cD-Br;g|BbUFu+&?j59!% z0md6Z2m8g4?!}y+FE%bjv61d#Bi+T23Nd8GU1vFyaB^j43+F}McD(6lRWW^%hYIi~Jg ztRQ$qY>N4M@ak#Lq3IN-EcJ9y`O9k&0Zj*$HPDj+YNVHH4xEl$frPHpp@gM~JRP|L zJ(8^Q3De0|+ITv10!O~nkror{IUPiaUMHVGinM_M`SfQ6AU$)vj1-!CiYQuNMkbp1 z+^SCRoKBOK4xbJsEPmZ|C}H8c=_V|l&UqWolukFX=XB)9^vG}JJ$4BQ5@08Az}9v_ z6a|JteLYsQrRI&Wbzs-WFP`3f`Z1x7NH@pkVpyRD>y+>_tb{q7#GaWj@%bAJNSTt! zElOAn>p&>s5dH%t{O2f(oX{e1@#3I-;#JP1^T7_MuDJ*H6!iQ5)trhgFVfU|=;(9=rcqwm!B-bNuvPLFvP8@#09Y7?5R{>%+m++M{oqlHrnYkSlV z+l2sff}Zc6 zF+RD|9i2iYV3JekLAVklxh0TXNimf`awV88f#ixZFM;GrO`!z#P28{&7-&he;2>1$ zat#rVEzymmQ@7tQx-LZ>hyH=usg&|V*e8x*8L)QJvR1oe)&>HHqg`nS_U#Cnu=z9S zayK0#{O8Vpk750Sf@h`>aXp1=P97UECMR(^f&t5+8L{!5tUQn7PT7Uc0H1gxpZF4u zyrCJ8L5YcGKn69S73>TsSn)+?7-KiX7`qw9*v&A;ZU%5TkDE(p7^^n}IFtZt25_i> z0;SMqu=eB9;S7Vr8Ni|7d4|z`GmQ3|fsjh-4l|(rG=Ov#J1{eWn^hf^J#`ko{f|f= zdIa7^>1x%SgAtXhlv8$rOox#vYsW|(dP6e}-DhGxOlA8H+$iU8G8_N=&2WVLX-)PA zt^M@ww}-y{s2YyzgErUbt>#U;$HZLM^E#_LjW`;6Bz6r5_m3a1`af`jgE$YQrm!YH zGK3ER52ICr`wBYy42145)3`%V10#3Pf1r`rt*nFUS|CYc3J(170KGYg!cM{?9Iq*-79i9u$80W^S<@i><|3*?rDv{^>4&SK{l z8EIUargGG?pjY)si5Y=&tM2hs`kGhRyc^JhP3I1;RQ~|M)AezpOOw>5jk`CtT2lPw zn9H5NbFl|;DCu}iA@+0`STo5&>)f_RTYyKo^F8t7#J z-NEicK*ScfK#S;k7iiHyrU9}IfG!K3ybCHzMCKa&xCTEi7$KbUarPR==7~5P zVGe7XqI#^b1TF1f?4;rXRxRo?j}o zO+OC9y>bbiF%BO=iT$w1(DBJ{d{VI(4sKhaAX;%5s5{+@)1ka&RL;};l0Dc0*e*_K z$q|%nH0kSZ`y3UPn%$i@AYi!}y&|}0DSOLuOq~4`iww_O^kFIJE}U5kx@(}9qF|{Z zcd5~brA8l?8hu!5^kFIVp)}i<8huy_a!YBf)ab)f*c5T_N5@c!E>3xa~T|a zk)1Mw=Q4xmGK1$bgXc1X=Q4xmGK1$bgXc1X=Q4xmGK1$bgXc1X=Q4xmGGlkj44%sj zp35M5jBvXgcy5yo(X0Bhvx?(7nUnDlZK*g8hqQzxj^kf5Kvqp!xxx}kBd!t>)OmVW zQz#tAsR}nzDB|hyc3biE_%ILg^h{BkcO5Dz;Cn<0KoEY)fyI}2P)?9zAJUO;N!RPu zydMK11$=^&8P@F_c3GNA!GTr-}#)y3w#vahivo9%72!=3+-^Oh6$*?%tl27mOD1Y;Y5Id z!+zlr@zyUi(jT^Y*PO(R4B*_|S#A5a$#tx5J*`PCQ(7voTT*_!b%XN`a=NK-9a`@d z*KGvHEo82PhacA2<~ynr52n2?r$7j6fwA!;G7}YR;nY8D%m>@xk6CNw8(R-Oe#qKK zD_ZVuv9>=P=~&v2goI2Uxh*h19+wInO8_DqbtonO(uo{O$v~(A>?b6s0Q+e`XPYZb zwizu@DhjB8j*@J11wu}74=N1TRT!?TFkDw*xURx*U4`Mg3d403hU+Q}*HsvKofc=CsD@?Yz0!MSPlVh_k5I#gTNAaO-bjB#EYWGT#*~9M+;NS}c zv%Fzivdz3RShCFwT-`k+N89ni7*b`3`NVp$+pfH@Cr2W2o3Z?40k;_ofAJ?cn}Hwf z;e=#o$XuRci42r2T;4Rqw}92-uDR;%Knfy(H=>KEC;m#gCz%->m(B9_egtja!{}Jmt8`F`~`UCJul36;`|cBgZFk z?CF7U5_@_eoG1`%RZ_91hZ#%A>49Dna(c#Wd7zhsocLW0dZQr%gi0)BXEIC@{|3$H znZJqfi6uUEx85R=CUZFCJs#T}W+^0aQ~K3N0Z7>N;|RP$L?(?7)9(1;*uVANSF+2x zG1?+}JvFH(m)Ly@Rl-RYH?y?NUr1h>6`dN?Q40t{1QMior4mRGW~(%@L#4^dR3dhe7^KqVWGa!9 z(IdJapb|M59pPD3I@ar779Fhp^z>I7k68OIzItNA*`)`OeE4wN>7%D{bmYhFU+%Ck<0Cn7 z3){N5qqWFkKu+Ak1jJi*cq>StAH`5M1-K6KAkJ&tWLrlLtod~3nU~I32k8BVhi=&1 z$vPc#IzWk?hl)1-E7vd3Q7>f_eNHk)ARK&7G7iCRo}SdML%U2d$5QfR0pil2$Mw3k zaM6iReq|t31??wWIIE!jG|)>qz*V4^7`rN{IPpcROn$Y>iM55^IJW=T{x^lyKh7HyK^jw? z@E{{{7QxkRr%XH)^?&ihb{KJ7)Fq5=8ANxPNGjzAJ80F9ZIu+$B&mtji3Wb#_G0Wg zKDkS5Q)o71N6JjI;r9yj&xYTt0c^|T;=*jOhz4@hA@j2her5wd($_Q__|X8ild$N` z23o|T&4#2%P%|5nA~c;1Nzo%EW<>8UpAAXjd+a$_>DOGg;Hp0ViW1btzv{|5n?}T` zjAH*E!j7EQ%Rn86vl8Y*bpip}iS*Wk++zK7-Q$b1%Y*-=Ds-WKZT(Aho~)Bs_MAC) z?%X~X%Itm2z-Q++jJh}uCPSErE&q<}?BFg6PKWvoc--TGX|IG$S?Mp!`o<53_IBos|2GH7S+Fx6%n}e=C?ukNkDNZFi=9(jh=0d?r zE9qP?i9|_rpXe&{<><%JXA0utDFmUM zmzaxniRzwfyn?w{puR`9pw9*Wi0+*W{?S0O0ZI%|ZUD~!sz2PG2SjZ~kUF-5y)h{G zx!MEF{h5-KGiQ&uypNTOk}mIs1rWS?7Nz^Jx;f&a2~nY!e-duUf99YE7&(BN_7ve` z)&2XxtK1c=?%{@zQNg$QrxIH*;B!Ziy0jZTIk?$zVW9c(p!+C(nh-CHgyw-3a^U|w z&_X=Dd7yo_!TvnZLh_mOz*-uB zLStIY11+SGF%Ptm{LehlLf@llG0)Iq9%!NO(X^NctEWdaE#^U%^@yg$e9&U~aL|I! z3Km+-`{ES`o46ep)?+A8W3$9D5O%po2$y`<)DXGPiucC_rQu4bgG)Z%Nqn>4J7>So zkFN(^*YgV*7-}v#{2p~PcV`Ke`M_!3aEE)k2~k4xfnM=W=RCs01|UES~lPEg|KMKdTOP#-;6#j zBRB#tXnhmAd*IR5tJ+xK)~l^|FV#zA6fwR6Y*SNRKWtUpBTFZz>l!R08Z7|(X#j1`%zg`iG0D>|Fsfhy*iYXx*#J`& zbru*^umGk+=(PasC(2;~aHvPLDp-L2a8@byLZGBEGJw*6%E@z=JHe1)z^^eL4McF2 zeNp{eqI(Za4eAm64_qTTe+<9E8FcZJXnaZaRgOlhfa||mVjibe{N~U?AWG)55Nqds zNf^mhoUjl`kT`B3kRaq zqcfMj|Ni^qa?hWW+eR!pb#c$duMXA92%m^(HKjJ+HoVy61WKppqt~MAMJ_RWSybEb zc*9FgFYyaStmM+qnp8u-!Ma3Q{RV{7fG2=`CuZ}TSgeA}Oq}48#~*&j9pH?}iV1zK*nw)M458n+GH zKnp9X7ye5cKG~G;?~z&bLxYnI&a~WXHL2~ozxBD)b0~!m zY1W}>YOK}1X`pF)>V3g#exc2=>(5_*mVd_1=J!}s|5A$|nw{=uoo~6fOHI=aO;H|N hf9}ZHO^2-G_)VJ=w7aQwuIb5GkfNFVmJL7k{{VLp@-hGb literal 0 HcmV?d00001 diff --git a/modules/frontboards/TwentyFour/FONTLOG.txt b/modules/frontboards/TwentyFour/FONTLOG.txt new file mode 100644 index 0000000..facfe4c --- /dev/null +++ b/modules/frontboards/TwentyFour/FONTLOG.txt @@ -0,0 +1,139 @@ +FONTLOG for the Raleway fonts + +This file provides detailed information on the Raleway Font Software. + +This information should be distributed along with the Raleway fonts and any +derivative works. + +Basic Font Information + +Raleway is an elegant sans-serif typeface family. Initially designed by +Matt McInerney as a single thin weight, it was expanded into a 9 weight family +by Pablo Impallari and Rodrigo Fuenzalida in 2012 and iKerned by Igino Marini. +In 2013 the Italics where added. + +It is a display face and the download features both old style and lining +numerals, standard and discretionary ligatures, a pretty complete set of +diacritics, as well as a stylistic alternate inspired by more geometric +sans-serif typefaces than its neo-grotesque inspired default character +set. + +It also has a sister display family, Raleway Dots. + +Also, the characters set has been expanded to cover 104 Latin languages: +Afar, Afrikaans, Albanian, Azerbaijani, Basque, Belarusian, Bislama, Bosnian, Breton, Catalan, Chamorro, Chichewa, Comorian, Croatian, Czech, Danish, Dutch, English, Esperanto, Estonian, Faroese, Fijian, Filipino/Tagalog, Finnish, Flemish, French, Gaelic (Irish / Manx / Scottish), Gagauz, German, Gikuyu, Gilbertese/Kiribati, Greenlandic, Guarani, Haitian_Creole, Hawaiian, Hungarian, Icelandic, Igo/Igbo, Indonesian, Irish, Italian, Javanese, Kashubian, Kinyarwanda, Kirundi, Latin, Latvian, Lithuanian, Luba/Ciluba/Kasai, Luxembourgish, Malagasy, Malay, Maltese, Maori, Marquesan, Marshallese, Moldovan/Moldovian/Romanian, Montenegrin, Nauruan, Ndebele, Norwegian, Oromo, Palauan/Belauan, Polish, Portuguese, Quechua, Romanian, Romansh, Sami, Samoan, Sango, Serbian, Sesotho, Setswana/Sitswana/Tswana, Seychellois_Creole, SiSwati/Swati/Swazi, Silesian, Slovak, Slovenian, Somali, Sorbian, Sotho, Spanish, Swahili, Swedish, Tahitian, Tetum, Tok_Pisin, Tongan, Tsonga, Tswana, Tuareg/Berber, Turkish, Turkmen, Tuvaluan, Uzbek/Usbek, Wallisian, Walloon, Welsh, Xhosa, Yoruba, Zulu. + +The Roman Styles also include support for the following 17 Cyrillic languages: +Balkar, Belarusian, Bosnian, Chukchi, Crimean_Tartar, Erzya, Karachay, Kumyk, Lak, +Macedonian, Moksha, Montenegrin, Nanai, Nogai, Rusyn, Serbian, Ukranian + +Documentation can be found at https://www.theleagueofmoveabletype.com + +To report issues or contribute to the project see the source repository: +https://github.com/theleagueof/raleway + +ChangeLog + +6 May 2024 (Tildagon Authors) +- Convert into ctx format for use in Tildagon badge +- Rename to comply with license terms + +29 August 2020 (Caleb Maclennan) v4.101 +- Repackage so license files get distributed properly + +27 August 2020 (Caleb Maclennan) v4.100 +- Re-release of the entire font family in more output formats +- Collect all the developments from various forks back to the original project repository +- Build and release using Fontship + +10 Jul 2020 () v4.026 +- Release on Google Fonts +- Add VTT hints +- Fixup Italic +- Fixup compose/decompose for several glyphs +- Fix diacritic placements + +17 December 2016 (Alexei Vanyashin, Cyreal) v4.020 +— Expanded glyph set to GF Cyrillic Pro + +15 October 2016 (Alexei Vanyashin, Ivan Petrov, Cyreal) v.4.010 +— Merged in Cyrillic in the GF Cyrillic Plus + localised variants range +— minor fixed: adjusted win ascender +— changed italic angle to 12 in Italic masters +— added Cyrillic kerning + +24 Sept 2013 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v3.0 +- Added Cyrillic to the 9 Roman Weights + +26 Jun 2013 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v2.5 +- Charset Extension, now covering 104 Latin Languages. +- Italics Added +- Re-mastered + +27 May 2013 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v2.4 (Beta) +- Italic Masters, ready for iKern + +1 May 2013 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v2.3 (Beta) +- More diactritics added, now supporting all 104 Latin languages +- Added /Delta /Omega /estimated /infinity /integral /lozenge /partialdiff /pi /product /radical /summation /uni0394 /uni03A9 /uni2113 +- Lots of small bugs fixed + +11 Nov 2012 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v2.2 +- Fixed Font Info and other small bugs. +- 'Heavy' style renamed as 'Black' +- Hinted using the latest version of TTFAutohint, currently v0.9.3. +- Removed the KERN table, now we are using GPOS based Kerning. +- Smaller file size for faster loading on the web. +- Al '-OT' sources files renamed as '-OTF' + +7 Sept 2012 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v2.1 +- Fixed vertical metrics bug + +11 May 2012 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family v2.0 +- iKerned +- Remastered + +30 March 2012 (Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida) Raleway Family Beta v1.06 +- Initial Beta release of the family expansion - Not yet spaced or Kerned. +- 9 Weights: Thin, ExtraLight, Light, Regular, Medium, SemiBold, Bold, ExtraBold and Heavy weights. +- Characters set expanded to cover 95 languages +- For detailed inspection, please refer to the the FL source files (The OTF files where quickly generated using Ben Kiel's Font Generator macro, for testing purposes only). + +20 Feb 2010 (Matt McInerney) Raleway Light v1.01 +- Initial Release + +Acknowledgements + +If you make modifications be sure to add your name (N), +email (E), web-address (if you have one) (W) and +description (D). This list is in alphabetical order. + +N: Caleb Maclennan +E: caleb@alerque.com +W: https://alerque.com +D: Fontship build system + +N: Cyreal +E: contact@cyreal.org +W: http://cyreal.org +D: Cyrillic expansion + +N: Matt McInerney +E: matt@pixelspread.com +W: http://pixelspread.com/ +D: Designer + +N: Pablo Impallari +E: impallari@gmail.com +W: http://www.impallari.com +D: Designer + +N: Rodrigo Fuenzalida +E: hello@rfuenzalida.com +W: http://www.rfuenzalida.com +D: Designer + +N: Tildagon Badge Authors +E: badge@emfcamp.org +W: https://badge.emfcamp.org +D: Embedders diff --git a/modules/frontboards/TwentyFour/__init__.py b/modules/frontboards/TwentyFour/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/modules/frontboards/twentyfour.py b/modules/frontboards/TwentyFour/app.py similarity index 95% rename from modules/frontboards/twentyfour.py rename to modules/frontboards/TwentyFour/app.py index 0285c28..8df6989 100644 --- a/modules/frontboards/twentyfour.py +++ b/modules/frontboards/TwentyFour/app.py @@ -1,10 +1,9 @@ import asyncio -import display from events.input import Button, BUTTON_TYPES, ButtonDownEvent, ButtonUpEvent from system.eventbus import eventbus from tildagonos import tildagonos -from . import FrontBoard +from frontboards import FrontBoard BUTTONS = { @@ -28,8 +27,6 @@ class TwentyTwentyFour(FrontBoard): } async def background_task(self): - display.gfx_init() - button_states = {button: False for button in self.BUTTON_PINS.keys()} while True: tildagonos.read_egpios() @@ -41,3 +38,6 @@ async def background_task(self): await eventbus.emit_async(ButtonUpEvent(button=button)) button_states[button] = button_down await asyncio.sleep(0.01) + + +__app_export__ = TwentyTwentyFour diff --git a/modules/frontboards/TwentyFour/tokens.py b/modules/frontboards/TwentyFour/tokens.py new file mode 100644 index 0000000..44ecc12 --- /dev/null +++ b/modules/frontboards/TwentyFour/tokens.py @@ -0,0 +1,42 @@ +# From https://www.emfcamp.org/about/branding + +# Display +display_x = 240 +display_y = 240 +display_height_inches = 1.28 +ppi = display_x / display_height_inches + +# Font size +one_pt = ppi / 72 +ten_pt = 10 * one_pt +twelve_pt = 12 * one_pt +eighteen_pt = 18 * one_pt +twentyfour_pt = 24 * one_pt +label_font_size = ten_pt +heading_font_size = eighteen_pt + +line_height = 1.5 + +# Colors +colors = { + "pale_green": (175, 201, 68), + "mid_green": (82, 131, 41), + "dark_green": (33, 48, 24), + "yellow": (294, 226, 0), + "orange": (246, 127, 2), + "pink": (245, 80, 137), + "blue": (46, 173, 217), + "white": (232, 230, 227), +} + +font_name = "Arimo Regular" + +colors = { + name: (c[0] / 256.0, c[1] / 256.0, c[2] / 256.0) for (name, c) in colors.items() +} + +ui_colors = {"background": colors["dark_green"], "label": colors["white"]} + + +def clear_background(ctx): + ctx.rgb(*colors["dark_green"]).rectangle(-120, -120, display_x, display_y).fill() diff --git a/modules/frontboards/__init__.py b/modules/frontboards/__init__.py index 69513cd..b8c6210 100644 --- a/modules/frontboards/__init__.py +++ b/modules/frontboards/__init__.py @@ -1,5 +1,27 @@ from app import App +from system.hexpansion.util import read_hexpansion_header, get_hexpansion_block_devices +import vfs class FrontBoard(App): year: int + + +def mount_frontboard(i2c, readonly=True): + header = read_hexpansion_header(i2c, eeprom_addr=0x57) + if header is None: + return False + + try: + eep, partition = get_hexpansion_block_devices(i2c, header, addr=0x57) + except Exception: + return False + + mountpoint = "/frontboard" + + try: + vfs.mount(partition, mountpoint, readonly=readonly) + except OSError: + return False + + return True diff --git a/modules/main.py b/modules/main.py index 8ac719a..3489474 100644 --- a/modules/main.py +++ b/modules/main.py @@ -1,16 +1,39 @@ # main.py -- put your code here! from esp32 import Partition +import machine +import os -from system.scheduler import scheduler -from system.hexpansion.app import HexpansionManagerApp -from system.patterndisplay.app import PatternDisplay -from system.notification.app import NotificationService -from system.launcher.app import Launcher +import display +import frontboards +import tildagonos -from frontboards.twentyfour import TwentyTwentyFour + +tildagonos.tildagonos.init_gpio() +display.gfx_init() # Start front-board interface -scheduler.start_app(TwentyTwentyFour()) + +fb_i2c = machine.I2C(0) +frontboard = 0x57 in fb_i2c.scan() +if frontboard: + # We have a frontboard, try to mount it + mounted = frontboards.mount_frontboard(fb_i2c) + print(f"Frontboard mounted {mounted}") + if not mounted or "app.mpy" not in os.listdir("/frontboard"): + # Provision the board if not mountable + import provision_fb + + provision_fb.populate_fb() + + +# Do main imports after mounting the frontboard so they can +# import the year's design tokens + +from system.scheduler import scheduler # noqa: E402 +from system.hexpansion.app import HexpansionManagerApp # noqa: E402 +from system.patterndisplay.app import PatternDisplay # noqa: E402 +from system.notification.app import NotificationService # noqa: E402 +from system.launcher.app import Launcher # noqa: E402 # Start expansion interface scheduler.start_app(HexpansionManagerApp()) @@ -24,7 +47,13 @@ # Start notification handler scheduler.start_app(NotificationService(), always_on_top=True) +if frontboard: + # Import the interface and start the app + import frontboard.app + + scheduler.start_app(frontboard.app.__app_export__()) + + Partition.mark_app_valid_cancel_rollback() scheduler.run_forever() - diff --git a/modules/provision_fb.py b/modules/provision_fb.py new file mode 100644 index 0000000..2f533f8 --- /dev/null +++ b/modules/provision_fb.py @@ -0,0 +1,80 @@ +from machine import I2C +from system.hexpansion.util import get_hexpansion_block_devices, HexpansionHeader +import vfs +import requests +import wifi +import display + +base = "https://github.com/emfcamp/badge-2024-software/releases/download/latest/" + + +def status(msg=""): + try: + ctx = display.get_ctx() + ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill() + ctx.text_align = ctx.CENTER + ctx.font_size = 18.0 + ctx.rgb(1, 1, 1).move_to(0, 0).text("Provisioning ...") + ctx.rgb(1, 0, 0).move_to(0, 20).text(msg) + display.end_frame(ctx) + except Exception: + pass + + +def populate_fb(): + status() + # Ensure the board isn't mounted + mountpoint = "/frontboard" + + try: + vfs.umount(mountpoint) + except OSError: + pass + + port = 0 + addr = 0x57 + i2c = I2C(port) + wifi.connect() + + status("Header") + + h = HexpansionHeader( + manifest_version="2024", + fs_offset=32, + eeprom_page_size=32, + eeprom_total_size=1024 * 8, + vid=0xBAD3, + pid=0x2400, + unique_id=0x0, + friendly_name="TwentyTwentyFour", + ) + + # Write header to 0x00 of the eeprom + i2c.writeto(addr, bytes([0, 0]) + h.to_bytes()) + + _, partition = get_hexpansion_block_devices(i2c, h, addr) + + status("Filesystem") + + vfs.VfsLfs2.mkfs(partition) + vfs.mount(partition, mountpoint, readonly=False) + + status("Wifi") + wifi.wait() + + for filename in ["tokens.mpy", "app.mpy"]: + with open(f"{mountpoint}/{filename}", "wb") as fb_file: + item = requests.get(f"{base}/{filename}") + if item.status_code == 200: + fb_file.write(item.content) + fb_file.flush() + print(f"Wrote {filename}") + else: + status("Failed") + break + + status("Remounting") + vfs.umount(mountpoint) + vfs.mount(partition, "mountpoint", readonly=True) + + status("Done")