From 81e85a1a4e4b1b7c5bbf1fcffe967a60639778c0 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 26 May 2017 20:35:31 +0200 Subject: [PATCH 1/2] - Added integration of IBM Trackpoint --- keyboards/handwired/trackpoint/Makefile | 3 + keyboards/handwired/trackpoint/README.md | 7 ++ keyboards/handwired/trackpoint/config.h | 75 +++++++++++++++++++ .../trackpoint/keymaps/default/keymap.c | 7 ++ keyboards/handwired/trackpoint/rules.mk | 25 +++++++ keyboards/handwired/trackpoint/trackpoint.c | 5 ++ keyboards/handwired/trackpoint/trackpoint.h | 13 ++++ tmk_core/common/action.c | 34 ++++++++- tmk_core/protocol/ps2_mouse.c | 29 +++---- 9 files changed, 180 insertions(+), 18 deletions(-) create mode 100644 keyboards/handwired/trackpoint/Makefile create mode 100644 keyboards/handwired/trackpoint/README.md create mode 100644 keyboards/handwired/trackpoint/config.h create mode 100644 keyboards/handwired/trackpoint/keymaps/default/keymap.c create mode 100644 keyboards/handwired/trackpoint/rules.mk create mode 100644 keyboards/handwired/trackpoint/trackpoint.c create mode 100644 keyboards/handwired/trackpoint/trackpoint.h diff --git a/keyboards/handwired/trackpoint/Makefile b/keyboards/handwired/trackpoint/Makefile new file mode 100644 index 000000000..191c6bb66 --- /dev/null +++ b/keyboards/handwired/trackpoint/Makefile @@ -0,0 +1,3 @@ +ifndef MAKEFILE_INCLUDED + include ../../../Makefile +endif \ No newline at end of file diff --git a/keyboards/handwired/trackpoint/README.md b/keyboards/handwired/trackpoint/README.md new file mode 100644 index 000000000..764ad984a --- /dev/null +++ b/keyboards/handwired/trackpoint/README.md @@ -0,0 +1,7 @@ +# IBM Trackpoint demonstration + +This is just a simple demo to show how to integrate IBM Trackpoint in QMK. + +Some documentation: +* [How to wire IBM Trackpoint](https://github.com/alonswartz/trackpoint) +* [QMK documentation](https://docs.qmk.fm/) diff --git a/keyboards/handwired/trackpoint/config.h b/keyboards/handwired/trackpoint/config.h new file mode 100644 index 000000000..7558c03bf --- /dev/null +++ b/keyboards/handwired/trackpoint/config.h @@ -0,0 +1,75 @@ +#ifndef CONFIG_H + #define CONFIG_H + + #include "config_common.h" + + #define VENDOR_ID 0x1234 + #define PRODUCT_ID 0x5678 + #define DEVICE_VER 0x0001 + #define MANUFACTURER QMK + #define PRODUCT TRACKPOINT-DEMO + #define DESCRIPTION Simple demonstration for IBM Trackpoint integration + + #define MATRIX_ROWS 1 + #define MATRIX_COLS 3 + + #ifdef PS2_USE_USART + #define PS2_CLOCK_PORT PORTD + #define PS2_CLOCK_PIN PIND + #define PS2_CLOCK_DDR DDRD + #define PS2_CLOCK_BIT 5 + #define PS2_DATA_PORT PORTD + #define PS2_DATA_PIN PIND + #define PS2_DATA_DDR DDRD + #define PS2_DATA_BIT 2 + + /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ + /* set DDR of CLOCK as input to be slave */ + #define PS2_USART_INIT() do { \ + PS2_CLOCK_DDR &= ~(1<mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ + ) + +#endif diff --git a/keyboards/handwired/trackpoint/keymaps/default/keymap.c b/keyboards/handwired/trackpoint/keymaps/default/keymap.c new file mode 100644 index 000000000..22e46d98a --- /dev/null +++ b/keyboards/handwired/trackpoint/keymaps/default/keymap.c @@ -0,0 +1,7 @@ +#include "trackpoint.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = KEYMAP( + KC_BTN1, KC_BTN3, KC_BTN2 \ + ) +}; diff --git a/keyboards/handwired/trackpoint/rules.mk b/keyboards/handwired/trackpoint/rules.mk new file mode 100644 index 000000000..0609dd304 --- /dev/null +++ b/keyboards/handwired/trackpoint/rules.mk @@ -0,0 +1,25 @@ +MCU = atmega32u4 +F_CPU = 16000000 +ARCH = AVR8 +F_USB = $(F_CPU) +OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT +OPT_DEFS += -DBOOTLOADER_SIZE=512 +BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000) +MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700) +EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450) +CONSOLE_ENABLE ?= yes # Console for debug(+400) +COMMAND_ENABLE ?= yes # Commands for debug and configuration +SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend +NKRO_ENABLE ?= no # USB Nkey Rollover +BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default +MIDI_ENABLE ?= no # MIDI controls +UNICODE_ENABLE ?= no # Unicode +BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID +AUDIO_ENABLE ?= no # Audio output on port C6 + +PS2_MOUSE_ENABLE ?= yes +PS2_USE_USART ?= yes + +ifndef QUANTUM_DIR + include ../../Makefile +endif diff --git a/keyboards/handwired/trackpoint/trackpoint.c b/keyboards/handwired/trackpoint/trackpoint.c new file mode 100644 index 000000000..124995a64 --- /dev/null +++ b/keyboards/handwired/trackpoint/trackpoint.c @@ -0,0 +1,5 @@ +#include "trackpoint.h" + +void matrix_init_kb(void) { + +} diff --git a/keyboards/handwired/trackpoint/trackpoint.h b/keyboards/handwired/trackpoint/trackpoint.h new file mode 100644 index 000000000..b5d73d7db --- /dev/null +++ b/keyboards/handwired/trackpoint/trackpoint.h @@ -0,0 +1,13 @@ +#ifndef TRACKPOINT_H +#define TRACKPOINT_H + +#include "quantum.h" + +#define KEYMAP( \ + k00, k01, k02 \ +) \ +{ \ + { k00, k01, k02} \ +} + +#endif diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index a534f818e..f73b0fe80 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -34,6 +34,8 @@ along with this program. If not, see . #include "nodebug.h" #endif +int tp_buttons; + #ifdef FAUXCLICKY_ENABLE #include #endif @@ -311,11 +313,35 @@ void process_action(keyrecord_t *record, action_t action) /* Mouse key */ case ACT_MOUSEKEY: if (event.pressed) { - mousekey_on(action.key.code); - mousekey_send(); + switch (action.key.code) { + case KC_MS_BTN1: + tp_buttons |= (1<<0); + break; + case KC_MS_BTN2: + tp_buttons |= (1<<1); + break; + case KC_MS_BTN3: + tp_buttons |= (1<<2); + break; + default: + mousekey_on(action.key.code); + mousekey_send(); + } } else { - mousekey_off(action.key.code); - mousekey_send(); + switch (action.key.code) { + case KC_MS_BTN1: + tp_buttons &= ~(1<<0); + break; + case KC_MS_BTN2: + tp_buttons &= ~(1<<1); + break; + case KC_MS_BTN3: + tp_buttons &= ~(1<<2); + break; + default: + mousekey_off(action.key.code); + mousekey_send(); + } } break; #endif diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c index d9ccbecb4..4ed3cae1f 100644 --- a/tmk_core/protocol/ps2_mouse.c +++ b/tmk_core/protocol/ps2_mouse.c @@ -72,12 +72,13 @@ void ps2_mouse_init_user(void) { void ps2_mouse_task(void) { static uint8_t buttons_prev = 0; + extern int tp_buttons; /* receives packet from mouse */ uint8_t rcv; rcv = ps2_host_send(PS2_MOUSE_READ_DATA); if (rcv == PS2_ACK) { - mouse_report.buttons = ps2_host_recv_response(); + mouse_report.buttons = ps2_host_recv_response() | tp_buttons; mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER; mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER; #ifdef PS2_MOUSE_ENABLE_SCROLLING @@ -106,34 +107,34 @@ void ps2_mouse_task(void) { #endif host_mouse_send(&mouse_report); } - + ps2_mouse_clear_report(&mouse_report); } void ps2_mouse_disable_data_reporting(void) { - PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); + PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); } void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); } -void ps2_mouse_set_remote_mode(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); +void ps2_mouse_set_remote_mode(void) { + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE; } -void ps2_mouse_set_stream_mode(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode"); +void ps2_mouse_set_stream_mode(void) { + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode"); ps2_mouse_mode = PS2_MOUSE_STREAM_MODE; } void ps2_mouse_set_scaling_2_1(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); } void ps2_mouse_set_scaling_1_1(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); } void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { @@ -204,9 +205,9 @@ static inline void ps2_mouse_enable_scrolling(void) { #define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) #define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK) static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { - static enum { - SCROLL_NONE, - SCROLL_BTN, + static enum { + SCROLL_NONE, + SCROLL_BTN, SCROLL_SENT, } scroll_state = SCROLL_NONE; static uint16_t scroll_button_time = 0; @@ -228,10 +229,10 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { mouse_report->y = 0; } } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) { - // None of the scroll buttons are pressed + // None of the scroll buttons are pressed #if PS2_MOUSE_SCROLL_BTN_SEND - if (scroll_state == SCROLL_BTN + if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { PRESS_SCROLL_BUTTONS; host_mouse_send(mouse_report); From 6b994ecd82f660feb44bac376ae7d0147d40d818 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 26 May 2017 21:27:11 +0200 Subject: [PATCH 2/2] - Added schematic for Trackpoint demonstration --- keyboards/handwired/trackpoint/README.md | 3 +++ keyboards/handwired/trackpoint/wiring.png | Bin 0 -> 7217 bytes 2 files changed, 3 insertions(+) create mode 100644 keyboards/handwired/trackpoint/wiring.png diff --git a/keyboards/handwired/trackpoint/README.md b/keyboards/handwired/trackpoint/README.md index 764ad984a..a22fca295 100644 --- a/keyboards/handwired/trackpoint/README.md +++ b/keyboards/handwired/trackpoint/README.md @@ -2,6 +2,9 @@ This is just a simple demo to show how to integrate IBM Trackpoint in QMK. +Wiring used in the demonstration: +![Wiring example](./wiring.png) + Some documentation: * [How to wire IBM Trackpoint](https://github.com/alonswartz/trackpoint) * [QMK documentation](https://docs.qmk.fm/) diff --git a/keyboards/handwired/trackpoint/wiring.png b/keyboards/handwired/trackpoint/wiring.png new file mode 100644 index 0000000000000000000000000000000000000000..45806e007bc4ff87592e86d72a8fdbbf96a6a6e3 GIT binary patch literal 7217 zcmaJ`c_5T)+kZ5r%~rA$HLBA_(L(l_DaVlzSwhNWDOC1kof+y#aimB}n9(U)!w|BB z=`&{qEoOd+u4BF%sXfZ36^B z;>M?bwS*wp5(J6h)~y0}QqQK9fdAI}oU-?appDYPe7fN+X`TKIYA zrv<8A+e|q*kGoJ1hnaMNb4v+vaJ04sQ_%peUpE{teq1yyn^a=j&?8BK2)0D~1FR+CdT=OSbmv&xc zV+nLAH>-D5yTG0G$N3oj&_Swm%lY(uQ~pX}!CVSk{oqw>tzs#Cy1^c~Oo2OlK^Ewf zI;?kmC&QpH(x>)B8AwTF6&9bG+LyNl%5$u6q2) z32DMzy+>~*JZ%$7t~S=|80uP8ziJ*R#=kl8vPTeotH!wgHwJPxRL(nJR_>TJrJR5L zzDDQ;hcHD`jpNA!P-%H`io>-w6zAUaN(rS}w_~4HSrSRitlBXMP-Zy_%Sb`ta zW_?`^ZIvaN!0Xu72{7Ed$(rQov&>P}Z~HfNn~Y8n%rCSxPYs>%^Si!m$>qR&KK(lQ zs1o6A(uib}_FKl9!_J6tx;+`%`^xDO?+vS*r%iR&7Tvuj7EX^&it<%XGq+43$)4%# zT!??X2kJ*1vC*$P-k)n$fybv`^*mz}M&>uMHzVK3ePJlzo8x#$e{QIxzz#Zk(D8^v zv%VlNN$_^gC`9$SmoCM!qi*@A|BTqhT1Wg+n~BvMwUk=gQ~x0P2j3gw5Tqs@-?~5L zWeqPomqCZ2Oy_c5Pps!yWT{0#kh>>ql}Dsm8gmwcP^m;v0jR9}%zE(NyQlw_nd9wi zAqe5TlBM7}e3wc=&e|c$&om`&E1!;rcblv!m7OTJtV-PlSv+rP`7OR-H9W0ou7LYU zBJTc)n0i*r zv)&|Dz?2nZ^`&oO-dA-tB{4<93;QP8EC}$Rwu9LY*icD0 zq5$F4j@7)u#+^att>fSY(VOkT0xX+}{AV*W`1_TaN~exJEWIcYdjg8_RCYC%$I~A1 zI@CDUwQs?Hu{@!$>KF~IP2IJPimNBw#^risD(IMSt&hb#!S|izacCO7TcJ~q6@Gak zg^GorlWB1-5}1V$_R}R^na|A-L0#gZDF5Vpt#}w&r7)&&7?M|?^ zocdF6eX@33nLlaO0jJIgcDOALBi_!f;hE!oiZ_z4$a+7xdKNc1#jH~} z5%$e9U6b`Bl<8wOG`wh(PUnf5-JHwkvcO;$~aU_VfAlKm6)LQOQqq6BgucY&lkXdcVK9-#(O zsN$3kw#24@Cci(Ed4FdiS8tkTRYj1*7fMP(4;r^zlb;@^r4!~4cv%;sHM@#7LhEkO zq%d!62G7?v4aP>Kf`QO@uEw-MB5`Z_0ayj&2Sa4ux_L4o9FP~_$1isr@+~8 zjqcthN^_jSuaTLRAl!uN)5HmpB`Waz7k`=&&6iMijK=3c7S4OlG5Z2=HhI;Ow!)_` z;<%d6=q+Eh;jNSGi+@9T!s1SN8;IsT_{m7mrfWD1q*WM{9kOpPw%>p?AOeMVbQ1q% zB|i_$^UP|zHQku?uc|`mL8!+qxlX0MUSx^Y8h;-HGYw~{12B9+9=?Mb0O$XXRowm? zEH*;)1bl-tj&~=_vI{9GEAK9*KKec4m>_W4JOXjw|9bPQ5O_KH7dfp+@TU^#u3*uw z9?_aM3-*0wz1tV=GJ6l-U9_-l8~xRwy)y&$sS*o^zkM+9aMHVN#>2-?p?KGD2yR-3^5&b5BQK-{~lO#ckcLv(t6!~1wERx&VxUB+Jm7-#wS}buZ;sc8EoEy#M z6L1da<9iZZ(r}xG;0(Fu?pOkDag}xq7UQ}GY|Y-6gB+%cUEJiI=}~r@c;2H0$w?l5 z{KW0R3!q>>>IgQ`ijgttZ1Y-2(nFX+QrDl&OIcUQq$j%HoMD9g2RDj>F4{70w7=tT ztTwTlCeqzBZ7@qR`@A;7JRgaxSLnS})yHvsP5b84pVmfTSX`^R-EMY;v_P}Kj9W`t zw=WTnP#-zodzBsHlzw%aJ`U%FBq!X?jvY-lMbAb|9qJ(0f?TusqIfhT)+puq*v4N3 z(ptoti@>=Q`-<1OA)Rlyq}(G8Ujr}gZXP<1mUICD+fZ0~rR)uPu^wK$FlvA~_PdMR zN9|(;z;CY`N8Dx~U_!~o?2bSuq3vfQ?B$uXk~Nr=>(}-<<`8M(y_INMG=F?83m<0x zIifdM=If0JMHhJ5!M(}eHX%>npVmD9)aC>(v^H+a_QD(xd(^+74IIbwWd z@|T45V(OyXR*ij)l4rGh>nNK38NM>=k9BLHuMkrIiFW*6}tY!_I*GcyMtHSCOFlH8`FQfNL|L1A)$ifl`DOwyf9j!&slg!9IgI z;48Ek`1lpLdHOqLwxJ=LL=4OgB%hpZ#B!L%TQ~M$?C_YF zmxS`QA*_od0RiaGwO6>o09-*NBvU>j^whT;Jlr#+ogtc3`?TMckXQ&RCl=X*JQtV& zH@y}fLj8zB^6PJ*FT*bSg3|+mbW&Wc1;F9;e!-4TaYp@n98LspRU;#AA;RMnZI<9` z8=pJc!=rCbi%2sx{JAs`gXj|xU~{@8s2H(D1a=!5NB8t}e= z=zdEMd5!Hz-T7*xsh0ay00~U(3l-LtE(dVi=G^eBqB^58)BVzBGgFz}d*V~pa;nju z1aWnb&IeHqa7aZY{YS@Xcr275sVGYJv3muAnixbp7SnI{S8S z`tnUFA)2Ips~>bd8l}1|RZn81Va9xq`T8z2J|S4S4Pe;41CB4PE2oO<(qlRjxtB$Y z^KgSF@`f(4YD0sr&`NQU{8`PBcYtCR4f9`EAdD|hCgBaF7-eHaamycCTO2`!y$~Y| zv+1NtT3Z_X6su=br%uHVoI_VQPM}t)&PhsT9&o<;td0_rhD-eJvaNsGkoE@lp5@w! zDjAIP8NPnY9SW_~jEwl~7ACPqshRu%+V-4P zpc$vTthvRPNTkQC$!xTEwfst~NH}vj5wbp^9^v9Ec(j0h7AldY_-3!L(I4f4!jdC+av(E9WoC?^T*1CMyohBgR&? zk_21QrEOQOSo4S~9gI+&bB;Kf__oL!hf&RTGL*X`Eope?nl0Ftl4I0N@=5mdh^7iO zZIxcBEK5kmpmYY^zqKbYbm!qZ9rqt*%jY7z^3m|DxB$$6Qp~E9QS@bkxNt#`Z9WLe zWvyV5rUlYb;bv>ed zuK(LI)4~wbHj=qS#vZ}kxP$hko40F}PMN`YdV`jia%~xmmT^hzdp7z?a1JwAZC8b= z-+chK})Ag2)vQ^ML(k!{0O^mS4D_k-P|_GmhpG{W54|{GOu!I zU;6CC)9{Ehy40tuc|Fld-@C(5gYLJ67~h>fZ#3%zPNc(YL$&NKG%J*Qd8U#YCxbqt zXnC~Dt*FdxW22bIs@t!@#I5%dJ4p)qg~l&;Xz;aH6ZhPX_5KSKRQj08$4Kg4F5N1Z zB6)R(xHzc5eoIz+RLkUrhS>{bK*{iyKztZfi?;H*;(TEbo%40_9p$l+4&Y&TIJXdG z>m4=;H}YLnT%vOXcpc{mUO$S5wQQkt)aR7kJ1M}7$o!@@5=guJwrc=EezYzDmRt!c~I?CIUueZgUr7l>KOt@q6vosRP0g9tKXnU3PR0s{B|>Oj3?f{4oL1UOllO z&s^o;YA`~59mn-OpCiRsbl)np*L=t^XUE(^pT6APsK1Wew`YDvUD{bKG-X*pMx@LH z8&h^g3D+icR%xZPP_niIP0#u1=azWAOz*87;N|q!Dp_qCca}zyN-2v|leLL)U-02Bchs7H$xxmd!rJd{qr)_wc>Fyv+v6y>d zET;W5O|U?+V%)kfY*jvjhUlyXm4+)Um}$SV=4p^uzWuZHrrt}Xjn23;Ys@8too>H= zOAp>vBEK{X$^Eq8FzHz_-Zy#0HdDxI9;kmBYmZ9wA&-7wOR6TrCL0EMT4!wO-C>)O zKw}wR?h+Ent>lUIcEr_gUVf{>c8uq8q=YhqkXINv9uSPT7!8v5kD(iPT=Sl*Dg$EV z8CbL!2VYvkaGl3)zsQzj#H{Mmv>n}5R`83E4z|mv*^r7p(o?%m&vOf}1*Upb(MpFu z#GU7UDBR(h6XK}~p?o_F20a@5zwrfCmrKpcr!-}mnyi5`R(3d6#m8Ke+9TiAiFjsw z1`;j-oO#M`=Gxx0tS0-`b8m8Ekm*W=u^~CGfDscuEL}yas!ov(O&~LuY>{Lfojxkc zn5tRSFEQ5Zjh+}-iY_~rrwM)XD+P?@!EM>LN&h;a+EpuXeaoYf+@fMdLB)FW_r@M^^tJX`N1=$SFl*`%0Dj=va|Z!Z0<4XNivLdFF?6yilQq5H8ZD2%$u3lI=vu3k5oG_h8RN>WQn*tvBWJ~5Xis-%GU(>C z{eMj$p#1IZ%sT859wmT5M<3mqU(`&_9H#be!>XKsiGxk!ab8yQx?i{$Q8UkJ5a}kf z70;GegGW9NGoump&H6kJ-p=8DNs;8c)|&d~*!A@ylnfOu_hO`kr?9L2ND-pp zhdE5zY)>TV0KPb-Wsa%Zz6v5}T=RwBYC`ci`(9^BqU?afcw`K_ z=v)0xAc0fYyM5!*@o$sv8)BgM$_0iPu>UN2%n0nAP;uQ5xB%-y>;BtkxDnxbeA)Cq08-_hMfB%6ED)c0%P+RA*sPjUFFx=vMnVxB96$8ppmxZpNf}^o#GJrCPefYfr z0qypcnCZeth5Ojo1;2L-fMQu>!C2kDMC1=0EtBEv$O?n|+pW%ovyLB<1N|kp+%Qxu zHI*g%UE0M{6;`k1IUYwYa=u2Cmr>68K~`-K6m4cGya4u<2WpDFUoLx8<1x|oL-WTD z=b#0zzRRBN<2Gv8;x8!?DHyC_Md%$ljG-L}aLC>9w<9hpCX0_*>!sTU`9G8<6~cu6 zm*oIDkEiu!Ygi4hfyb}#?V^z$)pVB>4nG3g58*I7{Pi0w?)2TQ*-LrFQ*ZZB0A?SMj7Pa$VlV)P76lH0$oL={; z#Y1Xp3C)pAx>3da-tW1^1pBq4SYy^Ax@dGFid>n~KC%jWFFi~6n@v^E>O8&xzS2BE z#&D$eUN_;)JkfP|2n!!n_KnB#9G19Pl)MSo9(+)_guCf0Mc|n1y}rF-B=DUm6#n>o zDmw8v=pQoe&!bbQhC%(ig#z8blrf>y1X5u?*gfc-(a&oO*B{L4M_xnWabQ3Gk>f({ z32*^k0P=n18ubvA*WX`sgs%L5x;Ye9y`rJ#xG>?@q>fsI>adGVb1j19>lJs{ z8@X#-s2eH^e<5L8EbMdt^FsJt3DpKH{qy3#4-iiAe+&>#@lOjs@BFmjH!q<1RYu)> U)?fra_d&*nXMW8)dFj^w0E3z>EC2ui literal 0 HcmV?d00001