From d3b92742c183e753f325db59479c9d244d8890e2 Mon Sep 17 00:00:00 2001 From: Ebbe Date: Mon, 23 Jun 2025 09:38:16 +0200 Subject: [PATCH] Added current code and libs Signed-off-by: Ebbe --- code.py | 183 ++++++++++++++++++ lib/adafruit_debouncer.mpy | Bin 0 -> 2027 bytes lib/adafruit_midi/__init__.mpy | Bin 0 -> 1502 bytes lib/adafruit_midi/active_sensing.mpy | Bin 0 -> 332 bytes lib/adafruit_midi/channel_pressure.mpy | Bin 0 -> 591 bytes lib/adafruit_midi/control_change.mpy | Bin 0 -> 622 bytes lib/adafruit_midi/control_change_values.mpy | Bin 0 -> 541 bytes lib/adafruit_midi/midi_continue.mpy | Bin 0 -> 333 bytes lib/adafruit_midi/midi_message.mpy | Bin 0 -> 2343 bytes lib/adafruit_midi/mtc_quarter_frame.mpy | Bin 0 -> 593 bytes lib/adafruit_midi/note_off.mpy | Bin 0 -> 647 bytes lib/adafruit_midi/note_on.mpy | Bin 0 -> 643 bytes lib/adafruit_midi/pitch_bend.mpy | Bin 0 -> 606 bytes lib/adafruit_midi/polyphonic_key_pressure.mpy | Bin 0 -> 667 bytes lib/adafruit_midi/program_change.mpy | Bin 0 -> 584 bytes lib/adafruit_midi/start.mpy | Bin 0 -> 322 bytes lib/adafruit_midi/stop.mpy | Bin 0 -> 320 bytes lib/adafruit_midi/system_exclusive.mpy | Bin 0 -> 599 bytes lib/adafruit_midi/timing_clock.mpy | Bin 0 -> 329 bytes lib/adafruit_pixelbuf.mpy | Bin 0 -> 2789 bytes lib/adafruit_ticks.mpy | Bin 0 -> 694 bytes lib/neopixel.mpy | Bin 0 -> 1315 bytes 22 files changed, 183 insertions(+) create mode 100644 code.py create mode 100644 lib/adafruit_debouncer.mpy create mode 100644 lib/adafruit_midi/__init__.mpy create mode 100644 lib/adafruit_midi/active_sensing.mpy create mode 100644 lib/adafruit_midi/channel_pressure.mpy create mode 100644 lib/adafruit_midi/control_change.mpy create mode 100644 lib/adafruit_midi/control_change_values.mpy create mode 100644 lib/adafruit_midi/midi_continue.mpy create mode 100644 lib/adafruit_midi/midi_message.mpy create mode 100644 lib/adafruit_midi/mtc_quarter_frame.mpy create mode 100644 lib/adafruit_midi/note_off.mpy create mode 100644 lib/adafruit_midi/note_on.mpy create mode 100644 lib/adafruit_midi/pitch_bend.mpy create mode 100644 lib/adafruit_midi/polyphonic_key_pressure.mpy create mode 100644 lib/adafruit_midi/program_change.mpy create mode 100644 lib/adafruit_midi/start.mpy create mode 100644 lib/adafruit_midi/stop.mpy create mode 100644 lib/adafruit_midi/system_exclusive.mpy create mode 100644 lib/adafruit_midi/timing_clock.mpy create mode 100644 lib/adafruit_pixelbuf.mpy create mode 100644 lib/adafruit_ticks.mpy create mode 100644 lib/neopixel.mpy diff --git a/code.py b/code.py new file mode 100644 index 0000000..59049a4 --- /dev/null +++ b/code.py @@ -0,0 +1,183 @@ +import board +import digitalio +import time +import usb_midi +import neopixel +from adafruit_midi import MIDI +from adafruit_midi.control_change import ControlChange +from adafruit_midi.note_on import NoteOn +from adafruit_midi.note_off import NoteOff +from digitalio import DigitalInOut, Direction, Pull +from adafruit_debouncer import Debouncer + +midi = MIDI(midi_out=usb_midi.ports[1], out_channel=0) +led = neopixel.NeoPixel(board.GP5, 7, brightness=0.5, auto_write=True) + +encoder_colors = [ + (255, 0, 0), # Red + (0, 255, 0), # Green + (0, 0, 255), # Blue + (0, 255, 255), # Cyan + (255, 0, 255) # Magenta +] + +# Encoder Pins +clk = DigitalInOut(board.GP20) +clk.direction = Direction.INPUT +clk.pull = Pull.UP + +dt = DigitalInOut(board.GP18) +dt.direction = Direction.INPUT +dt.pull = Pull.UP + +last_clk = clk.value + +# Buttons +enc_button_pin = DigitalInOut(board.GP17) +enc_button_pin.switch_to_input(pull=Pull.UP) +enc_button = Debouncer(enc_button_pin) + +next_button_pin = DigitalInOut(board.GP15) +next_button_pin.switch_to_input(pull=Pull.UP) +next_button = Debouncer(next_button_pin) + +back_button_pin = DigitalInOut(board.GP14) +back_button_pin.switch_to_input(pull=Pull.UP) +back_button = Debouncer(back_button_pin) + +mode_toggle_button_pin = DigitalInOut(board.GP13) +mode_toggle_button_pin.switch_to_input(pull=Pull.UP) +mode_toggle_button = Debouncer(mode_toggle_button_pin) + +# States +current_encoder = 0 +encoder_cc_notes = [1, 2, 3, 4, 5] +encoder_bttn_notes = [11, 12, 13, 14, 15] +mode_toggle_note = 21 + +# Functions +def encoder_sweep(direction): + sweep_order = [3, 4, 5, 6] if direction == "CW" else [6, 5, 4, 3] + for i in sweep_order: + led[i] = (255, 255, 255) + if direction == "CW" and i > 3: + led[i - 1] = (100, 100, 100) + elif direction == "CCW" and i < 6: + led[i + 1] = (100, 100, 100) + + time.sleep(0.02) + led[i] = encoder_colors[current_encoder] + + if direction == "CW" and i > 3: + led[i - 1] = encoder_colors[current_encoder] + elif direction == "CCW" and i < 6: + led[i + 1] = encoder_colors[current_encoder] + + +def startup_animation(): + print("Running startup LED test animation...") + start_time = time.monotonic() + button_indices = [0, 1, 2] + encoder_indices = [3, 4, 5, 6] + + while time.monotonic() - start_time < 5: + for i in range(len(encoder_indices)): + led[encoder_indices[i]] = (255, 255, 255) + if i > 0: + led[encoder_indices[i - 1]] = (0, 0, 0) + time.sleep(0.05) + led[encoder_indices[-1]] = (0, 0, 0) + + # Fade up and down the button LEDs + for b in range(0, 256, 10): + for i in button_indices: + led[i] = (b, b, b) + time.sleep(0.01) + for b in range(255, -1, -10): + for i in button_indices: + led[i] = (b, b, b) + time.sleep(0.01) + + # Fade in to start colors + target_colors = [ + encoder_colors[(current_encoder + 1) % len(encoder_colors)], # LED 0 + encoder_colors[(current_encoder - 1) % len(encoder_colors)], # LED 1 + (63, 63, 63), # LED 2 at 25% white + ] + for step in range(0, 101, 5): + for i in range(3): + led[i] = tuple(int(c * step / 100) for c in target_colors[i]) + for i in range(3, 7): + led[i] = tuple(int(c * step / 100) for c in encoder_colors[current_encoder]) + time.sleep(0.02) + +# -------------------- Startup ----------------------- +print("MIDI Encoder Controller started.") +startup_animation() +led[3:7] = [encoder_colors[current_encoder]] * 4 +led[0] = encoder_colors[(current_encoder + 1) % len(encoder_colors)] +led[1] = encoder_colors[(current_encoder - 1) % len(encoder_colors)] +led[2] = (63, 63, 63) # Mode toggle LED default 25% white +mode_button_state_note = 0 + +# -------------------- Main Loop --------------------- +while True: + enc_button.update() + next_button.update() + back_button.update() + mode_toggle_button.update() + + # Rotary Encoder Logic + if clk.value != last_clk and clk.value == False: + direction = None + if dt.value != clk.value: + direction = "CW" + midi.send(ControlChange(encoder_cc_notes[current_encoder], 1)) + else: + direction = "CCW" + midi.send(ControlChange(encoder_cc_notes[current_encoder], 127)) + encoder_sweep(direction) + last_clk = clk.value + + # Encoder Button + if enc_button.fell: + midi.send(NoteOn(encoder_bttn_notes[current_encoder], 127)) + if enc_button.rose: + midi.send(NoteOff(encoder_bttn_notes[current_encoder], 0)) + + # Next Encoder Button + if next_button.fell: + current_encoder = (current_encoder + 1) % len(encoder_cc_notes) + forward_color = encoder_colors[(current_encoder + 1) % len(encoder_colors)] + backward_color = encoder_colors[(current_encoder - 1) % len(encoder_colors)] + led[3:7] = [encoder_colors[current_encoder]] * 4 + led[0] = forward_color + led[1] = backward_color + + # Back Encoder Button + if back_button.fell: + current_encoder = (current_encoder - 1) % len(encoder_cc_notes) + forward_color = encoder_colors[(current_encoder + 1) % len(encoder_colors)] + backward_color = encoder_colors[(current_encoder - 1) % len(encoder_colors)] + led[3:7] = [encoder_colors[current_encoder]] * 4 + led[0] = forward_color + led[1] = backward_color + + # Mode Toggle Button + if mode_toggle_button.fell: + if mode_button_state_note == 0: + mode_button_state_note = 127 + elif mode_button_state_note == 127: + mode_button_state_note = 0 + else: + mode_button_state_note = 0 + + midi.send(NoteOn(mode_toggle_note, mode_button_state_note)) + + for b in range(100, 24, -5): + level = int(255 * b / 100) + led[2] = (level, level, level) + time.sleep(0.02) + led[2] = (63, 63, 63) + + time.sleep(0.001) diff --git a/lib/adafruit_debouncer.mpy b/lib/adafruit_debouncer.mpy new file mode 100644 index 0000000000000000000000000000000000000000..ae577e09f4c424326077c4b648cdfbed31e01468 GIT binary patch literal 2027 zcmYjQZBrUo6ut|HxFNdi;<_U0ii)&d@`A7^Ce}AJ(N5D9mlbFT&}B(tXWA|{ znQA)IKhYo1U2XHB(@)JmXuhOVr!Ri*bf)c0XZopU7s0~ZIp;p-x#v9h+_P~z>Yuj+ z(wX$0T+J&&M%pb^i=re4%loLq846AYuZECY$%_vwLMFerhlslWsDixBQznFJu3DCe zrwfJjZb3rCN?FO5is=HvH;dpPr?Owp7qf_5U%8hqRHelg6cqEa2xZIrO0HBC>V#mv zgh;-j136<=MKO+7Bt?;AG>BJ}v?8H{1hEH7jT*=;Kv1aToKQ$t6rp|%p{{JCj%BKH z+Tb@)^MoMg(#5QlIY;}1d=ctAP8ZGrMyM7q(t8A@l+6~T^J;D(+pK(Wn`j(G4!Km3 zkYi6O6p+Uh)F_Tvu`0__5qf{0ZtabIMXSUx6qbXH1|GZf|5IWT_yfjr{cg@*%g$ zHc5!MQAj`9&7^N3S`Z#fa>eMXfCxd5rE&?pw^@Nt#8x(!;|X3!ZOm;XP@k~53|?$0 zaSnKecyexep-J!x8;kL~DPc9SE~FB1G;w8`D9fd?BrE&qfa=SagpzFBJ(CxW38+og zZaQ}JN(GTc>B;$neB?F!#ybcVbjc1=hYqG&qB%t=S7s+BvUw#}-3^MRM-z<+o|tQV z0P*@nuGS~AIfg+vgdDcX;N;a8&ha5^hgG{cKD6Z9+KdkmFXWHjBP{gfAfm6Tgq5%b zEIln=D{b}KXxp|**aKKktJhB3x06FE;UL-wJYem)`1zoq^vWm5aX5=A!k#>l*zQ(N13?N=RV4YxnYvSeSg%iy0irnZ^ zukA#+z@mS6jN>varfLjH-t=Px6}Iq;I*TxkamNyV!)R{z4C3!;Z7y1b;KJrykr3(541Q|4>iGBlImc(i@4YTdaS?pBx(F0>LqEWMquAh0*t# z+e1!+Fn#T3K56QG6`LpL^f317M00z|@CHpvW-nJx%3vFMsucHw;ywZOu8a^@eghCHy3sUPUj4zn3gyKyR_ zR#`&;dY{#kyV`;g%uzZex!H0j#DqyYX{giJpN9bb1b5M#RfFWKX28j{zMyiuML+q zqvH|vWi!fNMEk|h%O}`uZyW~TyD=DA|FC~yob`_`aNNlJ@aV$OJXbH*du)sWHO8-> ztJ10A+Ml2-_OGf_<9w8jbJi6s1%CANdC-I>o)=@2vw5 zR=~*h7u?XeY3w2F)HnRQb@C~n0`lM+ehJ_PC26$5Xvvzm)rMb*sHahl8ZrD}L_LEy H4T%2%aWh8T literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/__init__.mpy b/lib/adafruit_midi/__init__.mpy new file mode 100644 index 0000000000000000000000000000000000000000..0dc7de9d04909ae94f5ec96a5bc476339430ac47 GIT binary patch literal 1502 zcmZWnU2_^$7(PqFM@X_97ILy}X@h(;G)bWlz}luYfi-O!V!KUiN?P5(vQ4&4mUUTT zsW%JOnDItuy!T$O781QSP5*;q$I%PNU*I3`T>@%HW_Eeb`|-Tb`<%@?&_v#zDpg94 zwYsbeJ90%%2!gBt7UF6Hc^nH$1L2&kl(fduZRFx)QAe(VT+ID(oh(8#e!7CoFM2#1kV4ov%-JLMuZar+A0B7#P+}m zJ#7_R;eb$kDyyng5y}l+sv*Zhp@3*j5+!+8Ld{Q`(a2-1y3=2!SJfJ$`ztWQNlXxs zTc}A&1u?7e21l+0QEQ2r+msaPnW|k!{<&@NQLOH$*U<_Qgk4Fifq~G71woV4Dxk#0 z3|6(ODrtHHwS08fMpznmfwgnBNwuyv8_j(4T3u?cH9v9e)W9dTBtDgN$6<1!fAxul{x^`9H4(mrI}Lpcv{*M3hk9h6c)uF#O%GPJ z6A1Hzpl(;LNEKusTT*sQ+j1o+D=H-VhS*6z4&`qohVOQ5J+Wr*(Hu){%p2pOiS>LT zQn{HjuniC3L2Snk?8L4q=b52^jo1PMWFRm|1_O3t4>*V;;3Up~i@1un+-u&c-?@D8 z7WH8hyQio#!vQyO7x4(04kI#iFNN@E+D1lsk=oPQ*yw)D@I5!k{?M1h`_3mDFV5~0 z??n>Fqa?xeQ??nzW4df$Px)Jn%XhH1Jd23WdnrYwDMEW`ACt0m(WTS?{Cm6}hzwdN zWhdwODQb1rK|(1fiSnXrk3BY;`|~rtWNMc7V6XAs)MTXl<6@CmoBxd~bl`P^Nr!=6 zYMZRTW3pohCQIO<4^4I)9?y>^%Q6`wO_}VeA58W%lX+p`Glt0qcyVKBgiabCY|NWJ zBJLGJgieMHVLEa7d}a|w@VDHCd<72bsEM1dG05Jx!h*nN!z&lMtkky>&3yZ zUgvV_MQ#x^kX+fyW+8i*xspQdkF2&{>IQQ)3&gv1<%noDD~3F65HZ zvdqkxzEdFGclu{eGkt#l1i)VKuPk-c<{p_omMbvV!h;|f^xBHh;SaX6R53;|ZvR_w z1cS1+O9L;DUmX~~a?21o;N!OY;HtUi3mpEr&IURn)x5mmy0Bn;HjPYS*?q+1fG*+B zrNz%5{6U36$?IX`8^almT;Og-qmdQs0y)#?d1-m(2G0teHXCmHBUyBud&p$c=(sH` zGp{;_Z1}(*JhT!ZDmP>LqX*2~L7K|iioDpWgTyTiqA={r^P%4YYK#!vFvP literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/active_sensing.mpy b/lib/adafruit_midi/active_sensing.mpy new file mode 100644 index 0000000000000000000000000000000000000000..0c0c571e0d17f688828a5e1113b2360d29478b6f GIT binary patch literal 332 zcmXw!OH0E*6oqe6Q?>SyKpE--ls-TzCMd>*f)J``u@Ot+qN_=WAu}y>qeeG^ zf7;ZV-8q-iK?qQ>==J3YZZciN&?C_Ned41MM3~!JSQom@f2f_F-}Pm=Sn-)>)5gl`^n0Y zl`swK9;&08hg>brIR6hdL7<<3EB3*3& literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/channel_pressure.mpy b/lib/adafruit_midi/channel_pressure.mpy new file mode 100644 index 0000000000000000000000000000000000000000..c0125793cbe8ee70fdbc2be7b02934b99d69c337 GIT binary patch literal 591 zcmX|7U2oD*7=BwUln+^<>`<#ZDEQ=Rj;__!Ww%C)*VS69E9;0Nv@Feq4LP&oFe$d(usbyeT>`1g%%R}#TwD!|*>tn}*VDjA4B z&cSLoDDc0Im(aCWV&LPK+cSU0{&stE^0}*=trDTTB+jQpKAf`i@jX|JxFYY05C8sg e#X!N+SDi{R6iq*|C3od?1b$_A*6-4iQU3wl;;EJZ literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/control_change.mpy b/lib/adafruit_midi/control_change.mpy new file mode 100644 index 0000000000000000000000000000000000000000..dad085c6f4b99788f59076144db48bfa6e52528e GIT binary patch literal 622 zcmY+A?{3my6vj`BrTiNd%3gt?Yz#C3R~&)G%*4n#_9p^y0ix)KS17O01ZdNiC491F znwY5f(yABWb?hFDw;-@#;VYEDgJp z0TI+0gi!tb_`FVZy*nTfTT*y@yZQEovQUPEc%u?mBFJfEAnOLv)*LowDuLjwH_WTS zrTv7AU^j=guB;P$*&R&@(KJQFilRXTr#h%~qw=ZUPd|Dvd_9R!%v{QfyVFI$XT8tD)j>w}w* zz&srqhN>SH3Io{~PJ4o+j0@|M3YB$RqO3`a)?Utx;UdAZB4NS9RVEgt-ff$~TBiRc zX>oLp+HxgnM0dD5h}#7eZWV!J!gR@nm@pG{A3*0qqCVEPy?I@f+KRa0Kxj zgQ6VEc{p$0g*MaHW3-XBRD`b3-R2{>;JiJ12Pot#QYa9P73mU%Lbl}k^yJr9(|n%r z#S^T@Yd*+igw(_DPK^EG#5|F$EI6A!&inIV4jt3s*;j9`Puywq!}Zb8o6d1_aq|3k z5>K3{f0fcwcRYcFxfe;={D#eYZ9e$tx6QLQ@5#GLlw`d=^o8!-H}`GFYCH2b=XK2X J5-QDU=`S1$vkU+L literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/control_change_values.mpy b/lib/adafruit_midi/control_change_values.mpy new file mode 100644 index 0000000000000000000000000000000000000000..2415eb71376641cc4557f0f8c9c6883b46864bea GIT binary patch literal 541 zcmYk2O>fgc5Qe8f1C-E)5~iU-rP=~VTS)W*7q<2Wo36d?dR@o?Ex`?qr8bTnr&7da zL7+&xP-aPx9fSLKDy$HU3_NM8*v=A)T2 zUBK4HOXtuz1l0O!RLzQVqBV51u13?+M%$6_^@o5l4o{9Gqbkszh?Nu^_WDAoC2=O9 zeJXesF=!<;hA#Vj%6%AvZFrRYh{;$J+Kjex@ZD&PH zV~;^kGR|nqno*=mQSZ2ceJ@j@-`9P~PBIpI1L*q9ql2c}I}MK{wKuJ^H<#qILXbZAY_)p3(EP*PpP)+VfSA$7K$~v{$^a))7fj+Jum9<{EL&9m+n$-mo9bpiYmAI zCyRP)MU6r~bZkFde}-3UX2)zk^A8$(zG9slc=G`8)^}Y0fvul-`x@{3#=C!T;}_l| z<}J2~p?IH|ceqJRfLp|b*dgXUJ|N~8w~68SkeCR&#KicBm`{krEO3XIZ`eD@{{rN8 Bk^KMw literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/midi_continue.mpy b/lib/adafruit_midi/midi_continue.mpy new file mode 100644 index 0000000000000000000000000000000000000000..140487cb52a01aa59898502b1c4461313001945a GIT binary patch literal 333 zcmX|+K~KU!5QV43qE;+RLN*vlBnTIbZ8YLRJxIVPks3+sfzt}@+HNAW+1;8D4_dvL z_@^xjUM6qyzRA4T&BGp2F2?@&i6=~wDf5}N7{rTalFbro#&alQyWi{ERETjvq4Mib zmz#cMw#_!6?vjTVrvVd^a73A^LmLSb-qckSMQb{DigX$GvO@QB8D<|B@y(2f z&qk%JJl5WgLBs#nQ>3<(-CR}0>Ikjj^?kq_?lB;(q@LukR?^D(Qy2|B<)a3M_O)}_ cYc@-pSVtP(Isja#r>}Usp1xrt#l@lb16GV(?EnA( literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/midi_message.mpy b/lib/adafruit_midi/midi_message.mpy new file mode 100644 index 0000000000000000000000000000000000000000..2c7dec9ce4f111cd0d139ac1f66b722f07c13db4 GIT binary patch literal 2343 zcmZ8h?Nb})5q~6*5JHC2BXN;qIh;>I2uYSe5yUaJD^3SSydOvg+NOte9H1B^&E3g0 zlsI$xPcB*Y33Wly9B!4DKJ$=OpCG^k$^p zeV*Ol?*4Y~B6`rVpg*5jN-PVxl*F#5mQn%rk6q_QF|oq?vm2nz*z51}_W}K2dIK27 zQ=$a0sjQUBq!Vkv7|UhXcwmgDkqu1JMmCjR0r*6ej!x7d0HGT3^wo6cr|F?8u}{#)l>^$3_4gnxt!Bz_~1-u)1HZ4aE!DT1PAk2HG2a1W*{g-|q*e8#moI zZgvBuJ78E!NC{wn(=jXY*ChZitng|6dRDjuj5lsxym1qi&0gaL5se9fVJs`~*$mPq z@X4vz5IZ$IJUbKvw)!l@EYATYqFl@mWb%RhMMHH0%AArB&-USwk-^Eyq46pM`ED#L zWU{;m5kIWd#wfvIMq`J%@_l)oZeUfCvf}wbU?nB3=8}FcvmU7L zc3`l+MHt?KhSkV(_BUncupeJ1t69)0#VOXr9;XJyKg`Vm&8HM3N_Z&i3{Z2xn4lMA!O%+-&+n9?c>lTb(r7G072E zZ@1jG-Ffv(Gp5CZ4uHQq;*zljtP#^;daTK#J7usp;0^XhywR@1b#^_jw>RNU3!}z4 zbLd+-vM{Ro;5Wbh~?lL;d@1RE~KUDLh%Ks8t>PPe{t}(GBE1>u&Y%%@nO*p0hHF_g=--l)h!X_DD?Pv4 zl;yC=7KQSM&SJrK68#{<%{LoiRL(3GEGN1AJlP7-{k6WXBJ=OR(N~U%yZeSX2daZt zgBkAU7-M^TRQ_m@=ni_m|O<~7Q_GtI^3l@7>jw|th&?BWs3+SOJ zs#Eo_o-P(F@1Sdsw&2nBYZnlv?XQiVj?wXn$*F1iQ<8EfySr$TjJoLQr_%>z<>)c> zLt|;@QSc;G2?NoN}-7kCe++9N%&O1h#8Tq-~~D{CMVx{8T<*4ymz<^4-&&TC0`vOFCMt)Trs2eo`qTz8S>WHe#S)C5n~Z za(`ow{@E8_e)X4wnXezx2l5{y`|?P~eXA2)qCM}|9Nx1)b?#AULRu-L{d$y~gXiI_ zNBb>3_f7N!Y^k~aIix*gm~Y%|AE2+n=k)YLI{GJ?qULtdEGUK=hsFmX&0$43I-nxd z-+y**SFJ)Zn2nv$toC?OaWs9jm0Tnv}D8`_MYos$i&2&lfDMx4T|UJX8S3qPY~!EFUj zql|c4ZC9e!E!tTs+N^M{6BOHR{Qzxh-iNidd={0Bk&zle3r?X>tR2I>T72XUL_S<- bgb1S@-C(C0yF~ literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/mtc_quarter_frame.mpy b/lib/adafruit_midi/mtc_quarter_frame.mpy new file mode 100644 index 0000000000000000000000000000000000000000..fe374b5c30c1a8bc6155887093b0d2f58920f6b9 GIT binary patch literal 593 zcmY*VYj4s}7(Oi&%4O_8*^vou$R#ll+epAfjUTuSw>XRh7DYdtb>$42P|Hrs5GxueADa_9wjj0t;g%emQybyzg^4Pcs1a_n4MEl+Wo*HL<1+RY@}yd@+-$Nhm(2 zvPQ(|9BiY`QR}Ef3_~6fQ2mb~u4q`>?81-4npgvS9aHJvsI*riphU??HCCdVOKi@k z1jICBv>p}*`Ni`Rrm|`fd?`<6gixwetm_mcFg}}`#K0KDaIatQpY(uTMi^fbYN+}L z4~H02GS$6FdRWW+^Drj5X#lh#b?UvBAbNc8>P7z$*pbLWSk!DTpiB&q@N(Rk0Pfk? zG^fT>NgAos< z@?{n!bM^(=%Gn>$&H^DP3m6otFenzNiaCmJ`PT8LLaE&#Z&eC~(tiHCn+pGM zQ+(oX5x6@c&&hIy@SFG7ZU2|+M&sR})%5^=4P32(X4_3h)`{%X`?2V*^(2?gC(@3v kGWV>82*LuC`@k2g;62aARy_1{9RQe#}2Iwz~{0x z2`u8;;qGCLT9($MfUj0#jaigIdA+Gs=vu%0DMGb~EZw81H*jG2s>CW9y;Cli}mgg}@ynw4g&0l0cl zsn_?8YL&)waC4ZDGs-N(90d>}gwe4XOofN#{Etgd{( z!+A3v% zlS+u6mK`aZ$yC3}7cxXt977^rLK2dZk`pjayMV)KcZ~0x6hDPP{eXaHz=P zg~)P|FL4-oy7008^NZs=T?ySyNV4K=-cN0$@~fLs;aiFGvxy?V%qs|xwG@Oz1s*R`9G<;@5kn^;!e>TT1YsL(y82f^q!}NJyr44#oxa? iRq|9hCzLqdeY35gl~rfk^WBy|Z6U>XS~I9L<@Gv literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/note_on.mpy b/lib/adafruit_midi/note_on.mpy new file mode 100644 index 0000000000000000000000000000000000000000..47ebf8b82cddd20768987b7058582b0858e2d917 GIT binary patch literal 643 zcmY+A-)_=i7{=eWQcGd%gR)O1IM~0qFa@{34(5rBZEiZy2}IF@Z(aF>CP3@gj)Wsy zriqF1URw16ypG+2@fIxmW8&GH=l#9U^X93Fkj-(A)QAa$~B@q6|_~mJF^}@p3$yu*_7P?#2%Xzq^SX* z5$zkAZjT|R_0-{z_F*|sn5tWpjMV-arHmPj7zTp`A*W-TT7*E1G@6xWs{y!rP^s7V zj%t<0b8y!&AtTBx-53TCB7{-X2&Ur0a^_#S)i-Pl@U_F`Vf1LP{f z<{jzT>T31F$w>#|3Qi&s&mjqgk-RQoyyPMrTXIc&=NzY&oR4|#0URUw)LR4&M>aV; z6QAGYOB_a?CVcMw`sO%K79w}kQdoA@)^aPkLiT<__+H}tl=Q<-g%g=o@aG~({<$@Q zw&N?(>vtFXV&HtSv-7sS+X$rae^PbdPev~vcFjd;Chcq_?s-bgQ)Ew>{qx&XBu@#i e3nfl--)zfhA?uVq-);Gm7Lt9ZHHAtOUi%A8Gq$h* literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/pitch_bend.mpy b/lib/adafruit_midi/pitch_bend.mpy new file mode 100644 index 0000000000000000000000000000000000000000..422d8c78987b7746c03425ca520939375210762d GIT binary patch literal 606 zcmYL_UvJW26vj`%@?TbH_X>iF45ETUB*2B<2yAnUK(+ue=*8PoUZDxlrY%djT3eQE ziC?DGOTWp!!!rE@TIQx#=bYsCJkQC~^1+kGR9zSgU(}_fMzaYo@v?9-!7iqubqUcN)D9U=|U^Cq&gG zdEr6~#wt-{cPqcDrT+zMGg;RF-8$R|BkjHJ`~Cr#;jqP8HIw# z%A58e&ycx?wsrt9{R%L2%v1FuI!1H8It-6R>TEZYqA!v>|2&^>&H1w+#9}DU(1>OH zOrYpNT-M}KBx@>YdyP=k^K}X6s%Av9D7jlR4Ej-MekbqabXzmxL_jb4;cAe zsrt=H_~Q@r;A{t(!1uZZL&IVHA3tC2`?JRH)5~V_)3CMgaG{%DEdB)(P8!8*ruZzL zve}5u25k2J^_9)K`02Gf&VOx|qPI$krcwz-(~pdr?O22JpN=`WVgima*eI$NCH?`Z CKe2!S literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/polyphonic_key_pressure.mpy b/lib/adafruit_midi/polyphonic_key_pressure.mpy new file mode 100644 index 0000000000000000000000000000000000000000..c8646896d3cae7f3d4a3808d8a92fa261a05c2fd GIT binary patch literal 667 zcmY+A-%itD7{=eWQo0Vtw{?6Dm@@vU8L|bkaeya|0YVsLxGge0_$=M$*0`?gKkQjkV@fX0Oo(>iLuPrI;^B}~;VN-ovzfKtW`Mht^Nf{+WxrWPR( zBei;|-lzdCAC^u}_bVr*+A()5tw?d0=q-R=x7a+=Z0k2&T`W1wZ7X(8CE zV~0S=2wpDq!&N<%o_0@Hs&qwDMq=@W3da{~Ze4G%z7q}oL{RmQ#M0yQ^ z*(j2KZV#d928#6R&Gmt}?0&f3-F@BMtA$eJKdF2WB&TjZ^~@z{dcoaDJn)s6ugJbK m^XIp(NWKzT7Ydx_o$tu#;i9|g2VNr>Hjo^+jghG^)bBjQ>08#YfrIgpU3DD+kS;Cbq z^J0l#rs$>LWZ%K~6)bFccTUdpJm<-;5rDlX%v)(BeWf$a!V_(zl?{h7BNjpA&^?B@Z^3AzYwcp6?QJ}T#dB}3X~|CX%V{7VQX#>2pf_ms}Ng7 zPstb#3z$lpN${04o)JQ+PO+|2NMJmiTg1c|Vz|?-cY7T`jk9{YebQ{zJ0HL)B8;yH zH8p+eiFk}DF?4S#J+Ef||1`(CWdgcSSR13wllJ@W890&1LReHCHXx5pNK8!S?jx|T zRm(EWSEZ7oS?X*k%KD_V0aU7QNHsJnd&Dm0mg+TF;SoJOT<20rX0UI^nz_-Bw8Q%f z%&tGS?5EkA^q}@MpKnYCBZ$XQf@hJy z2YIgOL&>aDL(!~bpzQ@hoo8^#b3^w47!)cqC=!2E_Ei`Zb7lXv`uoPVYspY59pvm> zPJH=unF=O$^03?v@!YSY1@!Hu5d8S%_B4>Szug`mf9^L(m!{+vJ~FLCrYsfVU* z+Mv2Q41GrClncU&9*b2%0Ac(>7^m?w#-L-&ND^nsIgh=?QWzDHrEN5mAM^+(i4GQ}qWkL4E-AXL7i@Cd*@$lJg)TM{k zyEg8I-<4FC`_fLSDIdj WL7VOL6;<2m8`?^dwg;#-34Q>8U|B=} literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/stop.mpy b/lib/adafruit_midi/stop.mpy new file mode 100644 index 0000000000000000000000000000000000000000..3ce31af63928099924091434d0151cb458caeebc GIT binary patch literal 320 zcmX|+-%Eo~6vvM)*S3~Z7?(wZ#(umQDMj{BFUg7;&1h&3d%A6U(+ip6y$gh(te2pF zI!D>t_wfC2&gYD)u%`&x!e2b5E6Q<1eQGcsCwh`W3)z#4iA@+=1Oz(k4o81e<4`ws z6KYPuf|iniGEUO6#ym?1AdFu~%4qzIF(??PB#Db;9GEh8T+6+83gkD~mU9Em>E-Q} zdkx+HHS8(o45YJ=^MsumMnHMETIyaL8KtsemF{Djdc_ZS84rt#YjwTg;d9t&3lF__ zc{=pJ>$xIo!fvH2B5|&4pv?iGntKF_q>9HCB&kxndIIyACw%lkmcDk*N27sSM-4?n VTmAeMHT(G++Rl-@52!WsegJ@dSaJXW literal 0 HcmV?d00001 diff --git a/lib/adafruit_midi/system_exclusive.mpy b/lib/adafruit_midi/system_exclusive.mpy new file mode 100644 index 0000000000000000000000000000000000000000..cd6d6e445a1aee88545237ea79c983dea34a3dac GIT binary patch literal 599 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 literal 0 HcmV?d00001 diff --git a/lib/adafruit_ticks.mpy b/lib/adafruit_ticks.mpy new file mode 100644 index 0000000000000000000000000000000000000000..939beb4a645ade849dfa87c6c04a669d5d33a495 GIT binary patch literal 694 zcmYLEQE$>v7`-hkl!C17*aZiPq}zi5LqpTVxTryfWSM9r#$a7cWu=TpprkD`#0PJY zxMcnr*t;+L1wP5+euBwnjBj{p2PQYU=X~co=lj0BAh?qzg+{Z{vId5uI)?Va&i994 z-R0b4rjRe>Wx#q>wQGa8J?QJ!iD8=-pdF*DgJjq2nU2{rG__{~e#HRqn;Oj~i2JZ< zv|3Bt(QO+*RXx!y+c0~o3RqRO^uCGF^FvqU{Y@4#x71bWVuTw1&w=}h@v;Ha)H_ZC zXi<+Afd5N?df0ZHzP&4o$A;4$9OX5$D=x1UpDfSbGb|0C|8nTG@iJaU9vc9a@NmZH zIr!{GCu8D;TOIQw__p(d+$G*;P`tV`P6=YJ^5QEmRG*%5_o`?7I5egaOJ<2wAWcG2 zVb|cTZ2)8YF~m~18cb7=QVx#l+&af*$;j}e6MIy0Gyu(ilKt@`F5s8A)nih1E zG((}sD8}H{U7od^n%(>XLrs$ANQQ|yT5Z%7P!7?B6U$# zq*JjLR$4G(X|x(JRjQN@)uyEJgFv}?2==mEQY(Nf(vhTmj7S&-|RD%WbF3XXXAc6f0aEPESC zux#ul!A7-xuu*j%(5@(F`yc@gjwFR-DJu%FWmP(=YIU*E0JhZBYhx(pZT^ z=!C1ya+vmyTrEOm{c0mpk}A;6$hNeqT<5RG5~ev|GcJY~%wtzP^4ZLOdXL}QeK)n&BUxDOOWwc zycS|9ZU%H@rIyWWCDx*jhLAmI@Lcl_ks+_0*o!p7K^)umeP`@%E>+xS9-!CAk{?JM z4U=IsLPiiG2sw!}9|eS+MwcsQBseE9AAjJR!;d5S>d`?%AOFZ!q5orR7 zlK=8^{qfq0do|%-U`NTAuKB}rf$izl;Iu#Jp9&UIh2U9g_xndLIS!8`li2wpS;TLi z;kz*dmyN<%jQJIfvlBnXnHR~mT+i*n2A9|Mx?cG7Pwo#L-@_&}nTr{pz2trwSbhVw zeml?o_4|2hyC3!&2M(^X>BeUE`gxq8MS3m|>q9qwj(4C)S;K3Wtl{+;=#9F+L!&>S zsWU`=jDNxu`)SYmX?|>WO}l1#F26fKscSE++itJwC-czd-x_+3QLhkTlS@M9bR5qn z^e4XAz|EO1dsB}y#V$J+hho>|XJ-eehuiE@41FUftPR^whUXK>6sLdH zy$rUwIa?^9KSj4tn4O41H^#)7S19s|0=P2(@N@vc{v2=gVhlwP6RJ-8LPG!g0H^6~ g;nZngOz7VpTwuu2E>res;=bO+77C~rGf)Ws0FTmb7XSbN literal 0 HcmV?d00001