From 719058f5aa4c040f7ee486d071bf72e73c311f95 Mon Sep 17 00:00:00 2001 From: whowechina Date: Sat, 4 Jan 2025 18:54:11 +0800 Subject: [PATCH] Support for 3 aux buttons --- Production/Firmware/chu_pico.uf2 | Bin 158208 -> 159744 bytes firmware/src/CMakeLists.txt | 2 +- firmware/src/board_defs.h | 3 +- firmware/src/button.c | 82 +++++++++++++++++++++++++++++++ firmware/src/button.h | 18 +++++++ firmware/src/main.c | 73 ++++++++++++++++++++++++++- firmware/src/slider.c | 13 +++-- firmware/src/slider.h | 1 + 8 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 firmware/src/button.c create mode 100644 firmware/src/button.h diff --git a/Production/Firmware/chu_pico.uf2 b/Production/Firmware/chu_pico.uf2 index a7955af2aadaa9a2bd4c0fe5eef64a592f4225c0..a99646835421e8e9748559d76f60593a84c7743f 100644 GIT binary patch delta 22550 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 m&X>r55AG!isWwDFRTw?fmvqEfRH zy0xuBW#uVL>ljJd#p0N!Ps=)>*3rC#*RgXvo!ylI2Il{+*)zl5ec$&y=X;*N&-1$0 z?ES9y{k`wHziVykJHzVFhBe0H(QhaCFdoe%P~WNZhG5;&A@B54iT)?b$%#whNgF~; z)lkGl=3*T}N`_EmF1J!?jH;S|n9)0t?im%*joit-tX!sxABKPfp~ya@Q#o|4yrGJ^ z$a_^(3>T#iCyLa=m}Fog45;<-LrYj}JU^6nVJ2MY=qLYg@8`meS2-fIW!!l4lziTU8e*L7z_fy@D|PTJ$;=Ssc$zUBwXlKBWE%a{@$xV zu9PS9ZLG^ymXv2j8P__H2^o>$sykBH-=|E8X-B*8Ze&U*RtxHWJRF-;)_9w~V+1lX zSa_g&1TsN7zZ(nx?kQvk3CDUdLkWNF!;DfTjPY`fbZp(%9u@k|-NqJX0BG>eWZNLL z4?HxHLTK-k7+G4gnazh(!Vqs(q2_@44b|&vLEDSWijMT6^g@*o(Wlv?-mTiD79Q$} z6rSsj5K4Q)guS5ivK(z=g(3>oRf5sP z3H_hveqI`j7=r@o){jMu4xX0+39Xmed)aC1U2JFTvxj_LkNaK&^J&kkj@L?dv#&Xt zfcCKNWXvFg)fOh)00kA`>Tux}X;1AJJF#H!BB+3TtW>o*2H) zl}L?u#Y81VeE_mZ3pxq12Dcm6UaO6v67BQXCMgr`udGc{>+SW%81+A_|GgA7ni+Y# zLoA^O4Jm0cVwpO1qJ52HhBYyKybBaXib{~cdMTvP`~}fW#UR?Muv-|NHQtU)yI96G z-=#5G*02*!>g`Kh*woB+7T8%P1GR7ML;~aeRI~o9gPpy$ z&ZM^%volsa4!_UTDvg{yTxrzVQ2VaVVs@YtX~ZU@ku;e)!}i*6YZ1G}MH{10f?a3B z9h^M@IoR{APu1w_jhznGYP_(PvnL|P6mMJ7aeofcg_tud!i8oZK{v*YOs}}Et*Brp z4Nr1b%t_Q#b_@axsKe~Ohb?4rc9d{0aMqy?#$CkfjHRqb7~ZQhO=ppTf(qa1i*++b z_3Nba^D zFhWd(4p9ajVl@!y7&Sok@Q-wswtl2*gHEDrr3%9YbvJaIqm5J_;(m@9PM_~FI^wJD ztKyj0IO=d8mlvCSC)az~jmN5mM|ww~$68?M5tjMBc2n?VrT>Wzo-FX4ax37;qTUh2 zs7qv+;IuIjp}z1~%P?T8^nL197!Zs=_xIx0Vc3Fa)1hb^OU5&Q7jBJpJb5Uw7NsY2 z+*cb@j7B7MG}Y>gP)0&Wltal?nxaY+93D??!yMXfH83cm7>}og>OKak59yBHS4%^g z8|_WCYAACfr(Nl|?!J|anA>1>X&zz(NN)kTT4ys#f$3RS!qitlE~%%gz7oAo-rh~nnD~)fc+Y6c|WFuxjq`KDdl1QTg5qN;J%@I~QqC3%G}NSkYf+M}nbhp{E-& zo2+K5I9R%lBE}1@Bf5r}73U~NJ!&g=O#zgADh$=UcL&@>|CyIG_2o>?i`78Gex3R`-( z=EV3qNB64aU98DzWkvQ;y-5ZbB%Bp#`Lj|iwuH#hl^GX1Dw(qJO5uT?M1#p$$lf<= zJPMDFuqRbU9ose}Zt=FkMcsV}n!Sm9`UYW?ss$IPPLY&?n(w)TR#MZk6% zGQ{4mK)h)0HGhsgyWE?q9;whnPUBrLFPvFWtrTi~f2z)g$xJC!`xaCqLm^8E3%wx+ z=%YjjL`fXLRi&gDB74n<5}LeZc*mo!7N|zP-9DSmbyUpRV>P-|f|7eNWk_93FC|#L z^(-=<>qvJb)tX#N;RhIj>J!%HBaV!U7)B;5XpIo2^0PhpnCg|nd7s_S zX++}qX*EzL!a24#-a+1<{9oRW=#BQje?KF@AgZE5suFtlxM#37HqrH*n=~3yg&~tU zZA!$DV7n(3ybIcRrVr_2eTZAmtSW)J^Qp|}(wm*w^tkmx%Pw|*!c#W%?U~L|C@&G} z&j0pQC%(hZK4l$muV~rLKCtPi4P83f`H91TKKB>d?H3r2 z?5x6G-g0+v4jd*KA*zgtu&R68$35!LyzJwejb>;iTm1r_kRaN4*Z2z#b`**SL>qkE zO`|bIB`gNE>We|xZzdeH4Y@E1RRNSaJ}xbFoZkt&*FeR@i1i*VtM}BcVZ>bw3{U0U zuc;Z*z29Ei&Ega+%Q$L3{N_b;u8>}Y##g=QD zJI=nMkvKgyVqhGsO0!U}^>f?P#;AzCa_-BtA%n{^5u@@CR#wzD8wM*FlFVFp+8rEY zPD{MyEr!tqGkWW>Vr0-)DTVL6N@JTNu_~lPuNQ67%WN{IQYXFKlV*lG;^p?6(_-oV zeN!`PQHHX8wyDNYZdVDuKJKd79QThtSl37%U+w#8$ftuiCOtLj%f17$SAXq0Ht6Re zPugbW8;N@Vq^6G*)yK-zr>Ddm>iegx@curoG2I-)^<}J;s(ZSR`#jy8^-$juc#PUN zb$&YNC%=j%E6N=eAR(q*DSQDdwForxZY9#9Jm*>`$7BYVmm`u3gRNSX>29CF7PCpv zS<|6QHvP9{H{zPubcAzU1}hsbbos_RlIGxy%N-1K`V-yU-pp9rT1g=Xn;q(-*hGqa z<5LPw2}gy04U~=$M|v^g_}<6;mdS))_qyCkg|slchhwth(x>&b+B_ZVX3g{A3@xna zo=~-+YL&l}nxWO9Hl@`JT@ke_MYDKs1{ISpIyO$?Sk$Ssl4jaC0x>i!5SW)Vi1cC7 zh)8cIeH!|+E*^-1e*J7#KJ{lWcRDMJ;l0c4Z7q|+mF7|Bl3-#?Du0pHDdQ-MU1v{* z0hnVfL6?%1N|vI3>L_b^C}!~BBlLyX>h_i z$bD(aFed@G%Fi7K+^PV#&PzE|_8Y)Uy1_v+VmKyyK)F6%G(28nI9HXO5_hiGXHfg4 zogq0p*`R&Z%k9Xv)CC0ztxJoZI<&M9mc#vOgBnpVmoD$eCJH7c#4RlRB{^L9xj$9$ zGfuY8cc_?TE373cimP@gcBtTgC8rYVJZeGFbAORqxY2#vuvrEB<8Do|S}^oH(E^*E zkx{VIRSQ3L24st%8Y6!%d{l`!XJ8!_svJ~XCL;pLMgP0RBFoXk= zWcW>j4Z<*lTm%_pbgc>q5zxZ3-HKCWLA8&=6Nk}_unByzb7^tFVjQgxph=dX;mngf zbcS;Fdz(1r#cnmLeLQB2lpkn9Ctr zpo0;_>L@|Gpl^@2jZ_f?&g^!hXpmkd^~EfdoC)xyW;%Ld5m6Mh%r2+d=K8h)!{yGKh{a zNF2eL3oQlvp^R4}%4~qVuGQCdzmMz%!o5WMVgEA>798#;zdfz}T~~TFLT_&j@OXOr zyQ2EI=0a=u31B=2)QPy8h2!XVdK2LNILV^ZC?YV*5EK`tU57%%{@ai$G1jF5RRZk* zY6jW|bP#jT70=Cm&Fkyp`h8t%d~W~jaTZ<)t)H=vr;w=;wc?B+=U~WjA{hS=jDJqZ zh1vqAWu=X%q$K765H|zFjrQI2i_=lulO@}A4xb4zITgqkf5e5tJ+6R+DbiY>mP@Vh za&xC;rJtp+E>|I%Kpc4-e#7LWn*h(qL`5p<5Ilp5c^69U>g8@vOJ+9rQn?r+78>Dr z&tcoI9pMagxo%}3tU`|oG?t>!nr*nuZKb(!i+XRmmlC}|tAQGTwko)lrCT!hLiP~Q zM?l0qqH`!Sa}k+GwGVgff?&b@k0Nu*#gs=S?kSPFXZqayO0P0Sdr3PLPv~sv?^5)K z!+zo|@5UB_+S`pXfAXU?bbsS_UZfK1Vu6l>QYEBh0{*Y*cO{dmErj2tKo%eYwzE$h z!sd()yg#H|e}~vO?vPnowlp!=G5poo#EtgjJ z+}p7P#snx%Dl8~I#6DuA2!5mlyi_;QMd}Ay`J}2BN>+oMD^L}iAZ-MCDGlikLV6fz zTPo6>h4doOukgGRI?HXyUl|VL9OS)_uQmY>2GKNyE7ZP@o~qp<*nehwhYkC{qu^HZW}kItz1^ zZX`^W=`be1#Il#>*cu~skmeTGWJi;?YE&He!otUB zQ`P5gWLza}6Z52P!s(&&AU2-lL>U19^QFCEahvrXXe#8GXF88Ey=&u!#GUfn^b}GLTw;40j@3UKnRvcA4H7jSC=nhKQ*Bg?q8kdCA`}6F2bgeNc~umf2@qZ_Ls=!QLyUpAw-)5@jOio!LF79 zSm&Yd%eVXYZ~=j9q$aHQXkhCA;T*|!cY>&Hf=u0`9{M#8GLiUC2pFebCskFS8`B70 zZU!O^!KX%Oe;Bu{{vA!=U?@~jKS@+ENv7g452xFxR7UqYf&mm*KTZ}oC(Ae+JhaKR z($SN)JIGllHR?%^rpNGD!Dg{>h-;&KQBJ;0&ZcwVbG&&N-ILY?6*)Y(3;?}0k>4ic z-{Mg>z#62*zvj9udi%);ZLrOyQ3y42Be(ucJJ_MMSV-*~u(&{!S0I!3M-N@Znqd{K z^8`3IOYLa%(C_(TjHcQ&2{2X^#L5J12Zz*Gu){!UNM-C4k&^_6g9u;Y#y>ZdV|Qf5 zxuBM6No_$JS`Vpf2to~E+?E~B(R)qMs^N$zB#F~DO6&PK4;?%x39;ylL}f)1Wt@4J zhZbX=g+XDQ)V@9DxOYKyI2^O$TRz{gX^?^oS1Y-Ndp_Xy?t!+@XBp@Roc1{>jAjq_ z#~0`U1SKMZ5*dOQNVA3GVQI6~PZc?*$~gCWXe^|8-bM8ZA(@=ES*r164^2W4vQ*c853LclccVK?E`{Le zr;Ea-%Y?n*(Y)5@uMom0w)Pn!;|v+&!CxYCBVhSZ=$cXhX+Z32QWM_t&>MXR-R6PU zIC|7fQP@n0ut;Dig~2^86{0af$?$t=I4n|uPz1*w`j#FJ#SB0L=x2#?W=Z65=9W{~ z%Kh4sL2qLdt8zN+LC=y1&0A839QM#pI{(YLJ?X=N0Z3miiY%9je79R;va#HXkgT_* zCLTGJdoCAFYFsKSnKe5Am8&(YWcVU9QrRAE$Sm}Ah4s6RW=vBUUoX zKP-jyL35lHLQ+JO6`@?8Plt&3j#=EdAF%XOKkGK3ky#f8oKPVmu8<-A$U`sBN3D+? zde#==3gJ}G1mHcSy(Wgd`Wlh5M#lM7BS?P#s|V<9Hl{t@aNn#DKd1d%T2t+1z__9P6*@-E z&Eu-WBoG#gf)~mJpN2@$V(*(2CIX@Rekrx*Y$mSfW}bZ!Gu*FdGc?(bnuKO{Ux1VJ zk#?!-Z%zQ;kKf!0%MzS1>U^7|0v3s?7s*tgJE(=zeFg_k5gG2vxyf|Bab(Fzhhb63 zKK){`>|$BjZx4a4^WRRPo7pP`4t7v*{YXH4BL#KQLm%v*Qa8Dge-U+&^Zs3G;bjxlGmd_0-@8xmT~RqX$8dK?yOD0dKg(0xnsBo5%1T z?w>bD(<;ve`*b)d3h-Z%ntE#tuHx>$^%uG=@%?;#wcwy}9*h--mBG&Y z&*X&Q$WXCZ)Rp?(6OVuh*qx01>654i*i4kbMqmOAomU>(`7-t|KcQ*h=wtwiFhUPY zG~wdXQbnWYXahIu7eT`aN70B&K@UR}0&G&ER#Jj9|K_0|wQo+&44{-h}tyr&z2Kx~NzmJ9laavDAc+d;) zJ;J5;x8MfuQoo(9nu0AJcTrFhjy7))b#9R8+)VxICg=LZL)cNVI3Ds1J163MqZ-By z_-?}n@LhTgd4vm<2JDERBESqW_`#i*v5juh#CJqAMeYe<(myIHdQ_r_H&fU{!`+y4 zZTn&A^wU4!D&DLFo@d>|GSRse?tnPofCqT98s6W-`nra|ou&bG8%1>+W$I{PU6KMz z%;9AN?Tgncu~c6;F!{RP@?(d$54nvdQS*3=)IPl=33nT!}eBo~C_lmo3*|C9*nDH)_#U^O*0+rB(a z9|(Da*Xm^Q;&4NZXArEHQ0HV61)&unT@?Ru9GZz*q^iKZ<`W1;0R-&mp(7CSM5^);}Zac}Av(0X@o&dQ%ck5XV2> znHPXkypN9LvTj5jmW*<|)+`g21y?^iHt@w+IL+8WhJ)584#6D@1J#H)MWG%Q+o;!l zU4=cWL+I!;_5AiMoUSI7u%VtmmW8vzA|Vn2_f?rHzB>z>B6P5#P0xBOEUyqh+oT~o+GP{{SXHWLqwWQ96DJsZze)j$xdo_{7A=8*&l zHvio{L>&Bi??_o~=Hf}IWj&|e*r;(#x4i^{tq`Lshk#Nw;PFcVNh@~pTXONE4Ear# z()Eyr7waJ^rRs?6OhieGblE6F(=GvJ!4Zbw@VX05o?$iIp;)A^!qqTrj_|hYs(Rct zeEt~xVgT!nF>q-t*@-ga+T(%~6-*wxMX&6Zc_j~96J~V(3aC|p`YU%3vuO3kJUkiK z@PEm}_tV1+i@BO5n z?;D3rwBDIfw$b*BWU6Zt(KgA@PQaxqQgRc&VFES{-2@Rj@^dSsv{B(ma6Y{#(dO-N zO=)8%@JA=$`Sg8D;>U$sHAR7T`v;sH^5s^zq?lOscXtp9kv0d^ZsqeQ;mJ{zaPzwg zh`g>D!vAp+o`fgxUrxehYJu&ovH3@Te|w92Uc~ym1glC|$!A#cXxzwGTk%AF9$d!4 z0CBp_9dJq`|F#t`r+-TzR}v-j5wD#fbE^%{H68Ci0B#L~(tF+DH-pN5kFk_h3Gem4 z;IFer{&gFkqH+S@M*deD9u}Jm^C|QSBQEOeS^(O~?@-<8Ulbv~D1pqI3vd=L;qNWL zi|`=+F9mR9+{oW3z&W}@(CL(p1Q!~iY_B&o4y?9$trbT^2U{mqyqW4KbxkSaN3rzEsz$5+?K2g??C1z%^As_kJP16O!)>ah^s%R=N#|^B!4W@!A5JBa3l*Tv{J8 zizd*1tmN83Y#;9|#--8LJK$2ZBfi$EX&XdZkd;4KjPHeE0(GKK7)eKZMfBY(GT)Wp zsx%_OlZKdLXfit>Z-E%fE=UXEH!ve79MT?%=HDv8E9t+x>r95V`=^Gggx40z;7)^4 zH>37~2AwSnE<~Uc|4G#SCz6Em&6uf)d{0w^ZWi z=n|+p@?L_aTxQ!`Y{6E3<6Jy6Vvql#C8==#1CvV3zCIUE0hS-<;$iVbl&dv-nhMcI zxMYg@x@tVgP(84<&U{n!%9|3eAk#_v$w6lHa}_e4#P3x3x{ml(8j|gaO-M z97OB@y2wvlimz+TP3=*m?+RXXe*h;B4SMs}7H3ccb2P7Y$@D*jD+%vIz}w;8%lysgv-lPB-W9S|P>bK7;0DRrT3kX~ zGthafal5q7ua*g2hf^rV#}}@{PBp>kiRRy3hZoaUmdgI6>&QUE(SInK_MyzQ^>{U4 zdVW0~g-iLrt;cs{M|!RipSEh@vXl}P*~~~OWP41t6`IR~;4hVlEDY2=ASrib(dmq8cgMy7sWEc25 zAH(^Sub*G}7~WxQ=(iwp5pXyAGE57PqKA^6OL(^hWxdlee{)mII>ZfZfAyb;pgxg+ z;>``P64=V$+ki*lDg4F;yc|#Fe{8^a(&@<@+!dCbTk+a@nNOa?bMbNhsVDJn%~S4A z-4K%{_WRdKg?|xM{Y9dx%{kz_=li6te6CM)U(h>q{cnk%?&Ifd!U=b-m$9$ut210% z`!Aee?R1W?Us)mgWn8GxX#P)|@FR5MeY2Mgu|-SQ*9|iKTVNvElE00@O`#LlCuFU6 zD=-}GK*LYL*Eyl8<+Yn+QvL``suf=^jIEkKA;hHrt7!jUCHC{?Mwm!PWOtxDby84U zW#YC&D{khW-;N*G;HHzPJYErUs{X%3q5mZlx&!o+#SpoT>etVEpOsnh9L~gf{LJU@ z7aB_rXTQ+mpXtQy(@9a{Ntwi5xFId~56J(eO&$CzhY7MAzJBzd2gHcibH>5@vKapK zE_}Dfge})x^J_!K^V%IUllB0@6YlYFDHsjdt^Yz){e?_*Gq4u2KUR9X#)m0$p<5~NQ4yHZ z4mZ%M;Q3hKYleIo&}uNZ5{Q^cZX(q{ekpkd{AEDLfer($1U--U?{Kexw61>^|KeV} zk)G|CQKd8KS4y1GECc^CfPcibY7=dIq&~!?|C{KHzsa1j59iK21b{XHIf1r<(ppH{ zfUH2j0PQ8u0NhzfiE&7enN)bL1R`OWiSXL zBjF-c5Tcd8@dj*yZ?Vs_$^&}_w)pxpqLwogG*Cc) zUc`M~f}1xV!MEaIuIrxAWf9){p3KOPvDJ_NU%C9Uk8ul~YDmhlvXYRc{*oyFl1zRZ zK0blqKWl}nB7nOV4uJ^vAAm@l3BJnP@9Wy{RY7dY(|VWxGuq1#bi~6qu_I9Sz!s0! zek8N;7;ePZ`1g(+`fj>BRiT8dYv;8wz#eK@J{S0UPPS@L?LAW3sKH}WXnk1vd6;am}nXVIf z6RdaMJ^>{bvpNS?Pf6#h<1*tu$C*P*AUH5BXceTI7`UMj=kk_7)$vuttsZxQz zfbTes@20!DgdS*u&Je%eEh2Zzke|itRjVO3RKUM}7C%fMU-8(=mfB;|!Mt6j}R{-;dvMO>bk3n3vbdCRz_z-O^VNLbuM?mqvihu?D%KS?i{ zXJ`LC@4&neMqYbPX3u48jadK!?&(6h?}0V|9qr=RUB<6!Ci>dlN`r-z^^fBD{}N&R zO9BHOEPa>$8cK&wsmDHgpNq>m+{(8nICR~+lAO(kI5&g&mTp5f0WqEn{UC8 zsIo7p+UvYA(71T*b(y$-0Mll+DRFlJ+8y$}{%29%&oX(pf%R*MbP&@5Hn?$eDD39L z2wCA(EM@^eU)yHdZ%P{@~ilf`N z-godGrFe1T>3Bvf32WQd4YthK=4wM!06|en8Cbb8z2LylWf%sr0f3gR{ z{U+1=>ZPH>cyL6oh`d*Z+zX5AO8$8-L=-Cdze2(v?1xK3x4k%1qRWFLqDF(&A)P)DWcm4AO6aNYXPNoSmn~fMKo->R>H!3Lxb{sz zYh+?$3FuV|RuI)1DSzxf%1T?Ky6UpCxFQ9 zc5J-pL(vaxeWCAg>Sc564ljYv(V2@WJY3HJ}Zl$wb+Aey74+NP;g+hA*Bf zi7i+#pUKW)vMt%U%&4*Baz~HL`2*h=Pi-4igBI*vh<(|{*eSjuG;mZ7=fE;=C&J$~ zDP1&wIg?*B^)9A#x!CmJ3hUsYvm<0$lPPmtIb7ze0;&N@j)V(-K<$zIvSg}7r%J_0 ztxToVs#LW~tx*L$HbmBJQoyy_sGWEXoMf)SJ8K8SpHuNOilbkm3?V}uE+KzPNR6hK zmKk4uelHwhlKhj&3Tj6n|DkWfySoDU1MgJL*c!-Rd2CbN`au4Su*S9;@*zcfIHM+R zjglE?q~hy7-i&lB1N5#WAABZF-wM2cRl@fIApH#TZ%NQ6`l_cJtRz|`$3r9-vi<9(XbdkilGL++T$&0R6SLr<6F|GENX|2 zznVr((k+95V$A}kcHx4R%<^T-qCm?xPytPBo9YUUjg1 z{11Z<{-^Zd8~o>H%2+TFP805GLAq@~2@u~m90npG_rSl=?;%|g&{UvmLPvo21Mz(` zQ zV(ir`YeEf|*QUuvi%c?V53fPtGnXw{w*28`FycQLVy=S-7HQ?N5=3OY^-uG)Oa-xW z&lfO81Fb(LrX>G=p)x498Ym0OZ6R_b z@c(E@z&#^k>O}7hmU!p)fIk4Cgns}0|MGh!l($$cBY`XyU$m8Yy=+=e_Ei3P3so2U z5roc;1Dygo3v>}E(3di(Iy^o+_`NaN)MuEpV4Z)Wge?)N-ysqUI0Mcd6F(R} zwuiC*2+(n$cA$$uw}5^D%7mtx2UH93z6PMJK>Kz4o?Pll-HSFw2ZZ9_cmS>!O22;4 z$BWwHCE9q)7%EQns0W$<$yeu5L-=`Ps7bM7Jv~M>f(;h=vfZ#9VZrI)$K+9|N-X4h z__=wMExL_`Z@TNq7n@r6m{ln*-2IzGUYkutLbp<@53j3#csY=64oQBk*bdlLBhqAUHa{TE@WfLYcoaSbg1@uq>$=DH%9a6G zX(FsN8La74CUr~4&z(+{z-6oh)2TbKnLjg~nyL%$z`563?nySGmu%4&b_|^A@!DxJ zca~8Ts9q1htc*&>|KfL-LEX0VpO!)MI>!IIj2dR#;+f?Rb0pTDhWjS>Ku9OCc8fjH zmF><()wN7564nh|IklKYkY)+Uk6{Pj9JpLUE}8@{mXMn-PJZev>Wr=kKE=R?slo;p ze?&IW0i*8;j?yC};;P|3ij=qGcV(mJ$lqW3-TU`pvn?$@^b`5-{PmLGDgg8RgZ#_o z)IxI!>`ZEaoIoR>;lfl;+OJhRXgk?}QVIZR4Sq93zL-un2gk8`*gR|kY6jW|bOh)G z&^e&nKrn8{@-?%m66(zwzGXI*KI)l0NcRL>I6DvNZb(59C_!l3^AIKgdb=6v-UJFh zZ{W2RR1$Blq#{H6(@_~>Wn@UaNBBpbfQxJ}qwE860@VZU2Pz-TPphO7OUM2l7Cq-g z*{^>C-uM>j#zN4(=pwY~(-4xlB)dLh7jr7HzBlf3oyd(sox{r zOdzn%{9b1zl{_$aWs1l$CCGql>3hv{sj3hcubnMvsPDlJ@dD<0EA)Y-R+gl&_>%9P zLk$i6y$RBYZpXqz0|5w9QR2T)oJ`z)RY^4PmW9x9^WcvzS_4!FX`n4aglLoqdXz*j zZ*h_$Nl+v}g^&h{%n!~o*|HLgNr_}A5uidyLrQq + * + */ + +#include "button.h" + +#include +#include + +#include "hardware/gpio.h" +#include "hardware/timer.h" + +#include "board_defs.h" + +static const uint8_t button_gpio[] = BUTTON_DEF; + +#define BUTTON_NUM (sizeof(button_gpio)) + +static bool sw_val[BUTTON_NUM]; /* true if pressed */ +static uint64_t sw_freeze_time[BUTTON_NUM]; + +static uint16_t button_reading; + +void button_init() +{ + for (int i = 0; i < BUTTON_NUM; i++) { + sw_val[i] = false; + sw_freeze_time[i] = 0; + int8_t gpio = button_gpio[i]; + gpio_init(gpio); + gpio_set_function(gpio, GPIO_FUNC_SIO); + gpio_set_dir(gpio, GPIO_IN); + gpio_pull_up(gpio); + } + + /* make valid initial reading */ + button_reading = 0; + for (int i = 0; i < BUTTON_NUM; i++) { + sw_val[i] = !gpio_get(button_gpio[i]); + if (sw_val[i]) { + button_reading |= (1 << i); + } + } +} + +uint8_t button_num() +{ + return BUTTON_NUM; +} + +/* If a switch flips, it freezes for a while */ +#define DEBOUNCE_FREEZE_TIME_US 3000 +void button_update() +{ + uint64_t now = time_us_64(); + uint16_t buttons = 0; + + for (int i = BUTTON_NUM - 1; i >= 0; i--) { + bool sw_pressed = !gpio_get(button_gpio[i]); + + if (now >= sw_freeze_time[i]) { + if (sw_pressed != sw_val[i]) { + sw_val[i] = sw_pressed; + sw_freeze_time[i] = now + DEBOUNCE_FREEZE_TIME_US; + } + } + + buttons <<= 1; + if (sw_val[i]) { + buttons |= 1; + } + } + + button_reading = buttons; +} + +uint16_t button_read() +{ + return button_reading; +} diff --git a/firmware/src/button.h b/firmware/src/button.h new file mode 100644 index 0000000..273c928 --- /dev/null +++ b/firmware/src/button.h @@ -0,0 +1,18 @@ +/* + * Controller Buttons + * WHowe + */ + +#ifndef BUTTON_H +#define BUTTON_H + +#include +#include +#include "hardware/flash.h" + +void button_init(); +uint8_t button_num(); +void button_update(); +uint16_t button_read(); + +#endif diff --git a/firmware/src/main.c b/firmware/src/main.c index 592db21..228354c 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -35,6 +35,7 @@ #include "slider.h" #include "air.h" #include "rgb.h" +#include "button.h" #include "lzfx.h" struct __attribute__((packed)) { @@ -82,10 +83,15 @@ static void gen_joy_report() /* to cope with Redboard mapping which I don't really understand why */ hid_joy.buttons = ((airmap >> 1) & 0x07) | ((airmap & 0x01) << 3) | (airmap & 0x30); + + uint16_t aux = button_read(); + hid_joy.buttons |= (aux & 0x01) ? 0x200 : 0; // START + hid_joy.buttons |= (aux & 0x02) ? 0x100 : 0; // SERVICE + hid_joy.buttons |= (aux & 0x04) ? 0x1000 : 0; // TEST } const uint8_t keycode_table[128][2] = { HID_ASCII_TO_KEYCODE }; -const uint8_t keymap[38 + 1] = NKRO_KEYMAP; // 32 keys, 6 air keys, 1 terminator +const uint8_t keymap[41 + 1] = NKRO_KEYMAP; // 32 keys, 6 air keys, 3 aux, 1 terminator static void gen_nkro_report() { for (int i = 0; i < 32; i++) { @@ -110,6 +116,18 @@ static void gen_nkro_report() hid_nkro.keymap[byte] &= ~(1 << bit); } } + + uint16_t aux = button_read(); + for (int i = 0; i < 3; i++) { + uint8_t code = keycode_table[keymap[38 + i]][1]; + uint8_t byte = code / 8; + uint8_t bit = code % 8; + if (aux & (1 << i)) { + hid_nkro.keymap[byte] |= (1 << bit); + } else { + hid_nkro.keymap[byte] &= ~(1 << bit); + } + } } static uint64_t last_hid_time = 0; @@ -172,6 +190,28 @@ static void aime_run() } } +static void runtime_ctrl() +{ + /* Just use long-press SERVICE to reset touch in runtime */ + static bool applied = false; + static uint64_t press_time = 0; + static bool last_svc_button = false; + bool svc_button = button_read() & 0x02; + + if (svc_button) { + if (!last_svc_button) { + press_time = time_us_64(); + applied = false; + } + if (!applied && (time_us_64() - press_time > 2000000)) { + slider_sensor_init(); + applied = true; + } + } + + last_svc_button = svc_button; +} + static mutex_t core1_io_lock; static void core1_loop() { @@ -199,10 +239,37 @@ static void core0_loop() slider_update(); air_update(); + button_update(); gen_joy_report(); gen_nkro_report(); report_usb_hid(); + + runtime_ctrl(); + } +} + +/* if certain key pressed when booting, enter update mode */ +static void update_check() +{ + const uint8_t pins[] = BUTTON_DEF; + int pressed = 0; + for (int i = 0; i < count_of(pins); i++) { + uint8_t gpio = pins[i]; + gpio_init(gpio); + gpio_set_function(gpio, GPIO_FUNC_SIO); + gpio_set_dir(gpio, GPIO_IN); + gpio_pull_up(gpio); + sleep_ms(1); + if (!gpio_get(gpio)) { + pressed++; + } + } + + if (pressed >= 2) { + sleep_ms(100); + reset_usb_boot(0, 2); + return; } } @@ -211,6 +278,9 @@ void init() sleep_ms(50); set_sys_clock_khz(150000, true); board_init(); + + update_check(); + tusb_init(); stdio_init_all(); @@ -218,6 +288,7 @@ void init() mutex_init(&core1_io_lock); save_init(0xca34cafe, &core1_io_lock); + button_init(); slider_init(); air_init(); rgb_init(); diff --git a/firmware/src/slider.c b/firmware/src/slider.c index 46cbc82..fd6d9ed 100644 --- a/firmware/src/slider.c +++ b/firmware/src/slider.c @@ -27,6 +27,14 @@ static uint16_t touch[3]; static unsigned touch_count[36]; static bool present[3]; +void slider_sensor_init() +{ + for (int m = 0; m < 3; m++) { + mpr121_init(MPR121_ADDR + m); + } + slider_update_config(); +} + void slider_init() { i2c_init(I2C_PORT, I2C_FREQ); @@ -35,10 +43,7 @@ void slider_init() gpio_pull_up(I2C_SDA); gpio_pull_up(I2C_SCL); - for (int m = 0; m < 3; m++) { - present[m] = mpr121_init(MPR121_ADDR + m); - } - slider_update_config(); + slider_sensor_init(); } const char *slider_sensor_status() diff --git a/firmware/src/slider.h b/firmware/src/slider.h index fb2495a..92e5d07 100644 --- a/firmware/src/slider.h +++ b/firmware/src/slider.h @@ -10,6 +10,7 @@ #include void slider_init(); +void slider_sensor_init(); void slider_update(); bool slider_touched(unsigned key); const uint16_t *slider_raw();