From de53747dddb02d5c24f4bb1a1937ff5f8ae3ec3b Mon Sep 17 00:00:00 2001 From: Dhanya Thattil <33750417+thattil@users.noreply.github.com> Date: Tue, 14 Jan 2020 17:40:46 +0100 Subject: [PATCH] Counters (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mythen3: adding counters mask, firmware still takes only number of counters for now * mythen3: checking if module attached before powering on chip * bug fix: loop inital declaration not allowed in c * fix scope eiger test * mythen3: renamed setCounters to setCounterMask and getCounterMask in API * mythen3 replacing counting bits with popcount Co-authored-by: Erik Fröjdh --- .../mythen3DetectorServer/RegisterDefs.h | 3 +- .../bin/mythen3DetectorServer_developer | Bin 152172 -> 158944 bytes .../slsDetectorFunctionList.c | 91 ++- .../slsDetectorServer_defs.h | 11 +- .../include/slsDetectorFunctionList.h | 6 + .../include/slsDetectorServer_funcs.h | 4 +- .../src/slsDetectorServer_funcs.c | 87 ++- slsDetectorSoftware/include/Detector.h | 13 +- slsDetectorSoftware/src/CmdProxy.cpp | 135 ++-- slsDetectorSoftware/src/CmdProxy.h | 10 +- slsDetectorSoftware/src/Detector.cpp | 10 + slsDetectorSoftware/src/slsDetector.cpp | 58 +- slsDetectorSoftware/src/slsDetector.h | 9 + slsDetectorSoftware/tests/CMakeLists.txt | 2 + .../tests/test-CmdProxy-eiger.cpp | 75 +- .../tests/test-CmdProxy-global.cpp | 27 + .../tests/test-CmdProxy-global.h | 4 + .../tests/test-CmdProxy-mythen3.cpp | 203 ++++++ slsDetectorSoftware/tests/test-CmdProxy.cpp | 647 +----------------- slsReceiverSoftware/include/ClientInterface.h | 1 + slsReceiverSoftware/include/GeneralData.h | 55 +- slsReceiverSoftware/include/Implementation.h | 3 + slsReceiverSoftware/src/ClientInterface.cpp | 10 +- slsReceiverSoftware/src/Implementation.cpp | 27 +- slsSupportLib/include/sls_detector_funcs.h | 8 + slsSupportLib/include/versionAPI.h | 2 +- 26 files changed, 742 insertions(+), 759 deletions(-) create mode 100644 slsDetectorSoftware/tests/test-CmdProxy-global.cpp create mode 100644 slsDetectorSoftware/tests/test-CmdProxy-global.h create mode 100644 slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp diff --git a/slsDetectorServers/mythen3DetectorServer/RegisterDefs.h b/slsDetectorServers/mythen3DetectorServer/RegisterDefs.h index 51f889b67..c2c87312f 100644 --- a/slsDetectorServers/mythen3DetectorServer/RegisterDefs.h +++ b/slsDetectorServers/mythen3DetectorServer/RegisterDefs.h @@ -82,7 +82,6 @@ /* Config RW regiseter */ #define CONFIG_REG (0x20 * REG_OFFSET + BASE_CONTROL) - #define CONFIG_COUNTER_ENA_OFST (0) #define CONFIG_COUNTER_ENA_MSK (0x00000003 << CONFIG_COUNTER_ENA_OFST) #define CONFIG_COUNTER_ENA_DEFAULT_VAL ((0x0 << CONFIG_COUNTER_ENA_OFST) & CONFIG_COUNTER_ENA_MSK) @@ -119,6 +118,8 @@ #define DTA_OFFSET_REG (0x24 * REG_OFFSET + BASE_CONTROL) + + /* Pattern Control registers --------------------------------------------------*/ /* Pattern status Register*/ diff --git a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer index aa2ed623f6cfbe184f34c7f36873388ac5addf1c..bf2226b28ae8b6902a79de64ee3dadf85f952ff0 100755 GIT binary patch literal 158944 zcmeFa3!EHPvH0J!+dFwD6G*2g5Y`QZ5Z(d9Yeja2@KE6r6%`PLKmq|mh-BdcA{n?F zjq)&XQ4#PO6%=3BT#SmyWk>HSQKLqTkU$=@yp;d}63Bc0->RFS#9bL!NoQ>RXyI;UqHfAR^bRLTke>YPtIa`)h&jx(O?)C=nLr}0jc)5jU>?B(p~ zq`}B<m{`_iQocWDl;> zG?@bL-_6l-<#(ZIEWeNCcS%dRmn3va8Is0P$hc8KYT{l}_}hn{X`39+|9O6s6w-I_ zv;a{r(M{{i^^|yPWX$)y^(h;P? zNux>fw-@Okk|#I(9UEMnaa{K!X~npXB)yj;e~rOK{~yTzLt^)Xf%k~rzuRDGmwu$9 zNGBK$G1}%&vm5;>H=!-9+RF1yArJ~u6Kgu$PLiEDn4GMO6aypQ{Z zMu60536)(EyT6b7LhSx4+^>$^hrE;Qn@B10TOa%VOmMCU0)LYKOy1AL?i;ut8M`0F z`(tDG_wvs8*!{P-pK*PlA9isDI`8HE*4XdA;Qr*;eLMH3$L^Lf@tQ{&ej3SIBQo?7p4fH^=VZ z&HH^11<9ZA``>teSnU39+&9JUzs~&uvHNqmKQeZI0{Kmd-QP-{6Jz&(;Q6y+_rK@& zsj>S>{N5J3|1I~q*uCiO@UIDA1L?-t@B8um?Xmk4x!-(Po$8CBj_>Tk{oS$O9q#AH z?-|=JkGUb5O*(hl6zA--FSz8=>1WSu zn{-***=GljmVJ=y&I_`edFgo1IpeYmr?;KYuahQEo_zkho%1i9F=e_lW6EWhU3wYV3(4@Pqt2c= z^SnvZ<*5tWW}bhjbK&$UZD&t!yL5&#^TG?JPnsr~PrGzd+vU?IUpV=EXPQ)Hx-)ai zv?=GcIg`%4^s+W*hUN=FZI@o`Tyn{z8P53^OlgCFw#%mR>?Kn!nF-xzpH0EjFFkwO zrRPm*yYSNK&bb#(pWL1MOv(LL73KX;n zLoS`s=3Fvq8ktH~!iAX^DsLvW1(%sq&bx%VTm{*e1dm)kedbJiYC5DiGlC2+pE+&H z6iB~p%B0E8q_#^hI-*n#W9D zff*s=rAe*jFPU`Vbm!kMyRc0qqHQt_00DBNOjo9yc=G#?J?`v74?6S^(E9FqGcTvE z(}lw5o?B71h-01o6FaW^UpKxRR|)EVv)o(daNRj|zgq__DQ6-yWrQ&PuDj(c4Bd6k zhw0<;cO?C4Z~Bk?O%PZNDgI6p*o=Ua1-AYr{cyAxbNn4WzRnqA`LqgbM$ZI+&5$`s zU@=ViJ6T{eVkQdQH^84JuozYRoi4B$d}j%4gZnuGi;>3PWP!y%<8P|KLjri3z*f;2 z0uK%FZ36ESz*h=vhSfC!i-F2tPGB=0+XWUwh`%`kiy_0`jRKo-HCJFWT5l8B4By)Y z79)wjy95@4lfQWan?ZTEz-D~jE3g?)KNPr0A9v;pJSu<}2)t(i-!HJW(Srhy4)A$_ z#W3ctQ{XWHyii~pP!|a-#vOl)1s21Yza;{TQODm>fyF4~Z@Iu`;1>iI1Dn661vdNY zd4bIqSS_%POKSu+qj{~sWe%Kv2j1tU@~g%>ImbOdmua3e+w+}V2D#59am~*klW9Gn z-f8XF&GC7M=T^9N`IXIMo%KNp*w)aTrVeT9l%|ep>YRoLX?T)`M`?JLhKFf*nuf<| z`equwr)h^Y?UJUQ(zIKec1+W*Y1%nWyQk^TX=EXdY^0HuG_sRMmeR;p8d*y>k&wkS zvYAF!)5vZbSxzI{X=FW(?5F7qY5GQ*zLKWzr0Gj(`c|60mZtBe>5FOlW}3-fn*N%m z|EB5BY5I4X{+{kbLIb7I32B#v&Pby}(&!-2%(-**?hkL6*}U)@pIP9v*878Qy4W9l z%Eir7ov90)e7!&9kDmd)QsGPt9vXvpiNU+Z;9)V?i^0QVupfi7F?d7_-Yo|29)m~5 z;5}k+V+?**3~q|Sqhj!$F?g>SJURyN9fQZj;C*87*ciNT4BjsW?;nE?h`|TO;DciD z!7+GT3_c_V9~y(-9fQZm;KO3@;W7A#7<^<5J}L$`$KdzG;G<*kdt>l1F}NiLx5nW2 z#o%LO@NqGCLJU4W2A>dvPmIAQ#o+hH;19&$560k=WAG^fyw=I3-M&A1w0Ta$Qg;iw zr!KeDOF7E|{e!;wnCP1y%|{i~xyL%_qFauqiylk&e0;oliwDTNW6QnkZla#4*5&kn*FF1`8|$6i z9M8?K^6K-;ssD27w!CqOlc5Y(X<2wf#{J!Z_U47(%ssGpR1V$Xy661yuFhghd-I&V zGw9gc5AW{`%a5%`e>v$32 z_BI^jMT9%RaEuob?hwN!;F{;87=w|;SvN@=!?%8!{GfVA@Xd3MCpQP*5wKw?ILZ{JZDJ8FLv;IYs%l;(&e~3vxVPC z!|Q23u9=Orr7JSonsPsN@xIXFfLgyv6#A16?LhYGiG1mu6BOcx;)*|mD^nBWv_O>7yR?OFxBNOZ!d@+PAUM$+ULVJLgE*@IAk%zC0aY4Cru&_L7cgpyQbs9nU1_ z_!WKd^?GN}vmJ%}0N3%J>nP+l!Jp?l3f|v~h1_!@bN!^gS??dn)C;q^a)lUfHMkdN zb$L&=6uhTe3eMB9-(KRkmuGdgrK$58=y(B{YREZqZS0F|{i9fr-wtocW%Dn^-g}bw zo|@G);Mroqe+fGJ=9c;|bM42Ke7rtfpXA!W^(n4tuB*A$bA6Gk%k>{zQ(P%a#ufkX zTpg~@7rXrDI%t;xv@5c4r?uBB(DzDA9$pFfRMJM5t6omIuh=`U^3JQXx+c)GREAy+ z-jTBX7m9`E`JFNjWQ11#so=hGctWl=2kqH8s9bvnva9m?I(fVvYsc3U?RY9W1m4J) z&^%`!NBA<_&D}27#*z79Lc>A3<>o5?*29YpEd^h$!jlbLg;!5@bU`ON7J2SJEs$sF zJD&9&V5Mapw5*HKvMxajws}CyC}`PB+k3d%I!xPrH?HvKpsX`2cxGRo*f|t&x>s?I@R4+eAe&7xR-WT z`3=zFIxDsrL;ISpO^kc!u~h2=S*Q6?H?ydP@wG@jGv-|L`MX4H9%V#UB3Zcm_`>iphHQT=VZ$ho$POp)f1gAd3u{#3aECaGoY_n z7=OeMoC)bUnZ|+WTxg_E1oTZUr7x0iqfh2R@;vXSc>j>-z02%9#teT;tX^BX>*a0Y zH&WSpy-vOQQLnz}@jmEtu3ES2EZ>d1yD?U`jaIky)NM36hJ4r7qf_V3&B!<>GA>Ex zeInzdN60ujAmeZ1y`N@dxKWCeHXJiFmkXXnK6y^tHPH7trDb+0ZzBC3YdepAC3(<} z8IP;Kp-7w1A6Ir{Dc_08=efrI$OrAEdEZ>hzliU~Kk2WGtOYWnf^14iXD{PtPo<67kHvmITXEv?u;*o@eG{%5i4wz9^+Z~ETd)5M0$ zkQR`BO8Ob;=cM~dzaTw8`X%W>68stjpS+F) zFTQKM_#b$YhnD|I@Zx`r7yPEQ-yh?}e0YJ+$DhwL@CLceNFGr=e_{1xJaqHLf_tC* zHh}i&*Uhsazkp}t=aU*=fM@sdyyg`=?_kTj9U;#6_{$g{J0$O(WlU`4M&_oueO(Tv=AFa-MxLAJJWM-E`VDgsbTV?R`dj3gG*QO#*IF_q?|!j& z?`GWK-L`qRI&RZ9G9LD61Y@(dQ%A8;DbEo*%yrtahveFsa-Hkx#{(SIr|;ekexrZ> zZ8zE){&Q6sUNUXp_IBoXCyj7iHr#w5-+}y5ZdIuCw5?sg&D#L2>l%Hi!EKiO)h>3pK+N!4UGf1_RHojYjEUQ_@D8(3aoAR zQcFhWA7%StqAzJ3)>W5pcT_Mw4RhwH9U}K)hg9TMxiU8Qwv6j)FT*)7u$iszC;Mr4 zJ+ALv83}t;d=ox-5B`YQY%S=Qj>6Qw^pSVd?|>tJ(JyZy|89TLT_+MtLXxYbD`Rko zt9EVg;rY3}_+99g^#Run>`hr8aIv?<_7u5u@ee4>`he(7m5a3Tb2GAqttWjX@Sg;- zja{T`9&S@0A2RNAzSiM1&uEviKO=aNllbpyL(eb&`@n(7@fOM=HKFqw2RPZOawQyZ zOxnrF`bAS;?)x~|CZ6S*k@XAYU)Ma`6j#frA>L>3=e$9Vzwav9&gREYvBV+Y4 zTUhEQQ&#T{%wpafE*T!7~9V}y;tiAYKXNk-N{2XrOY8_+q0kf0c z@8(nPcXBD8e5DQYzpK*65;mLr-B#YE9UhW*L_diAC3bVaaiOjHrqrpihdSLuo$ju& zPWMo!yKAUZ$$SjkJ{`=-Jm!=h^E;7;!GmZgWEwbVn|-Vv^ap=aOeSQ`70zuhraj~D z9AxjvylH)`J=X{C_>|{Uo-4&#=lRo z+P4s28goByW05}p*3qBeyPL-DIbSvUp$|G6>+u0l4}W7vVN6{vtGYmaBMlDr{h5b~byR-df)Vv^7sP@-FCFSLpzl7b%Z)C=nDyXU)~#eFCz=4 zf8Fn)W9}{0G0qy~n7-_7Mm9{J_NMHfc^}Xb>3(c*8Pik_i@@}&q#TyjyGi~1J#^i@ zNnO`ZWp2mNU0!C&(w3AJvwMiiP&;QFx{J6Cg}qPBTkMlWKjm-QO?fW*Q^(n3O(x8K zi0m=+iu(38wkYq;VZOwaEISW7R@Q4I7C~gpLzVXqk2aRsC586{^(<4Vhcj$X9%e$Db#}$84g2qK+ ztCKH!7`f~yRIEEZi|Q_LSa)EldkN36JN!`ghM*65reeOdRl1MyQD7GsyGhzHtXGhC znK^t?F0B8F?YoT*nOK7kIddoKke{GK?km+Ht>YWsSvuq==#cx~CORak-#!m*pG(r# z3;Q&g&usF+XRzINZZe<$AfM}#`RpWpo22av&^G67O507)c4LyZ8rty&^7&#ipDO$> zl-dYAkJH;R-X;0}C1|^OJ7`PTFFTaB=ds&-?6%>IB_xlr%)?e=EllH8hPOI_Uvch_ zGVW@z=ga$-)JA5kjQmP3m|qG1AnP$hMTZkB9OO0mM;VF#Q@_=eA4zP(Qhbff{|7Z; z0|)ERQ%zU1PVKX{uD&>ltsq|+BV}xpwXB}Xb$LeeXD-tO4b(~JUfJApBb;E3sRdgi z=eXjt#LiFnJBNm2R@t#Q>A#7MSB<+_UCa1F&CiA})$EvgR#&Od=2%_Lj)~~oT1ubf zBXOMKPY^q$+HXLiU{} zMmS}kORODxW)n_46q~Ki$+(ANLm)%6VPUwg9UJfF8(n5gMK++>Qa<_QCXT@8gdBVV zTar|^e5I2tJFrY{{#Upk094kQ-m0M_pJXAN+_+;VSU z=73}I6Y!h1Q|iWyFaD^v3u-jZ>8KjDfj2br&YYSD&|LCW&H^{njg(%e7P=>_4?MK3O^z+{TKYAmc0Hh zzIfIkv`--;GKXl@G9I)t3Y1ZZ`6~)m26bpAzaWODrQj1wLpi(nf?o<=VpCoK&y_L* z{H^JX4-c9jZOSyyZyKr3KDsBqiH0081w-}zHhX5tXr8${cxK5Md1kKGL-PNMOFl)) zPiH;!m@m4FI24cg7|lcI5+67B600E3Qs1n<41HMdEb|}d>N?B3x;(L%QvcRv=#+8P zzm@u*r1k%;)xV2;x?=V3vih$;|Ew^%{hK{2F)&ZYo+ZXd^&4`~{Ak~dFW0a=1lIPT z-oQ%d(jqY`&=lx6p-0-IN$FW(Wf1G)6E_s~ji;;(WJlWrU%vNpi^dcw-vux2u?GAr z;JGTV1%E4ie4+?#@bT3maX$2w`R-6pVt(XzVm&;GDd8Ue4OQH2_RbRCS<5>l<-NqJ z$UD@}lh_&VwNA_V{VVCL{{(qI(znSYrpG5W&rgr=Ugv%JUE1*tVD7b@coy16`A;x* z5%20R=jyi7UbI=nACuGPj4u}J7V*Vm-Talb(@JZn*X>!07mJ>?crjg*B1SAXTJ&1K zj8AM<_Z)F{lf;d={WZqL@tge(7?0BhqJ?+ z#o3#HHLpzGIo{w2Zr*877+H1Fx<)7Kb)t8-D<&y9r$o2A#M;T+KU`yxwJ)_LHWQBo z-^Hgh0A0F>xD0<2vc_7A_et*#vz7^vD$U!r2L|l?H&}Yp;_6H@6XB> zTc)#E)V(axJHEYx+?Vx(Qx;`pHqNDQY~UI0HxgUjCUzb6r}9YJOn%!a?P+$ z{B77V-sV|d!aJY#7u!et-w_Q>MuYLOGxXVDFRQ+e-V5?WPMhE%y10x@l;m5&=3a`7 zX&fl^P`JUtHbr*~Pe=5o#XkxyQ7m$t*ISI&`x?#2nAnvOug$I`RvusUtd#685_?*F zJW;*FJdW;x_s~$nd+y8f-tzZ1pv#F>gSYTT?EQdWvKCdoeZqB!0poc7NFCQsGMa?v zn_~8IWQ&&aDkw+FYaow4N0x1qwb*V0u-*D&1Cl)CFft?~~{w;#lRm&f@1C(eG*YUAfPd!OObp z>N0p)SEVm2e=g{$-Jxwio=3ih4@0(!jCbL?*Vwz#S2o0S1MQ}Aj*R$kbQGFzmo-+# zCTNZPp%Qy5{!p%wKU9DJTvp#%+MZS2xiMDW7kX$*`fab;E7pfXo=g8wKV@IzH|xE! zhr}%e{Bs#uJnAC*+uUai_pITB&;Kyo3x?CRUgPnXd*-p~v2j)U*1eVoJSwZ#!agJR zkH*ZG=`+ZUj~!H2r_p8}eXYA+nNAD)_JSUGAL+|p=(HEhSGmX_@8wx6kjy` zsHkhAGGFa0ddfxSq;A}6-^y@LTd}t$!n@AGRG^E@AMlXTDt2O-7;CX#y)~p)NUxG! zBdu*g@8Ngo=VXT0=bVD*)&21QALckJ7ej1KU<5eY$$gr3CeFrviYqp+fKMv?agk z_#^WUbXZfgZX>Z(qQ|%fG*fqCuaviS2M6|x>BqDYZsef z81ljUozHh<1{1^6yl}QtHm^yRR~>oP#qz2P@}j=g_d+CNiJ13Dzf>JKnmz{1xe2rb zzM)I4ERh-PfT%xX1Id^l#98wZO1u)cbg(N#eYDi42Y ze(3-BaYk$b_04?_7~P`q7l7&O3f~A!zf|~3z|xN>x7+7k6gW$)8$NIPH$0X-Yx?}H zKkoK<|0nO7&ztwLg>8)cveB!tmN6e4F`8<7!OwhCAIHOA6Skk|Go1r)&74X7!#L${ zSY8%48ri27H>!2N23Zsu#RimoT(0De-J3s4fKb=#HoIz8VulnOo+d<%F(^hD*i9^pCMQCxfl5n8AEquWGzBq zu|M!%vLCFY%U?UI%a=V{XK=Pe6+SS&4;5O<_N%0ignqAcAKEDDQ|JZd%_CM{X(Ptt zNUkVb+Fy0G?hS@VeNFbu#F9(9h%TfL)7F7pGanrqwb9mX+tHb_G3&SNt=4es;*y_Yuj~J zp4mWA+nVn{^`gz$)c3;LllI~LgT5E(r227H?Ld(Y)z$Elxsdt}MZQJv;SY`EnD(Y! z6Z(&L^jY{#-J@sA$~^h`#bTk6*hHlh9U*ln+s`Yku|@JLz)^%ZNv252*YT z;}f+vo7 z$P+2@1Hp@k&QKSQHad}QpFOk@pKK4U%F@z+&bgw?U5@0MBzq6B-JyMO7*G1=m<@ss zQNBu_4Ew6|N&1K4rB8--iu6gD1JN$3hgdiB*^3^vOBo$1@|*i1x{7hfr@iHQ=T7cr z9gI3gw#@U^x7C($0=+DKyG)+4U!A><>^0}g`k2ULsHbJmvW?|Ie;;Q&GaDxwFU`jB zo^L5g(!DCI4^CjuHGIwFcQL+!>!z^Vmomk zjjh1#;n)f+^MBR=yJWuSvrpfd&bZ26{z^QRakW;ysSPN;k-*jo_;bAR$LysH=_2W z4l+(xq`MqlSCrD_hHEKCS4h)sZx&6jqT>gl;|HSSNy@8hj3%?=J42exj>r9{{181X zJ~e$O%8lk;-?8`17Z<%}zBuv!2E4HL z`o29cW9ItUc)dR0n~c|L!&Aqy{kOtANn+XD&(gQpw3UCYkJGq07;{8NJIBbJE3nlA zoi>E~*`u0sLz#~~%zpFVwPFu6iOub8Dr&qs=ac9f6J-= z$+Nu{8Sc>7bAL75fic`t!%5!@^IKuKy<)g04HrM#>p8>4&-PkvxM8t(Uoo7Xfnqej zZn*xj=QbIxA%=4f(YlE|>e%{rJKL+_(|Wd7uA#5`rb=`}c(zweW<_3uSP1mW9x|p^ z*z+BW7nHcbxGd>>!K2^Pw@4+}drC{Db@zHl{Mp{$S_=N(L@y9ioc(m*Pv8BJ zQLQ*%yhrJ)j|RG4X@4}(bMEuk={aBCBiM|OwWzH)firM&1n8;`{3|+s7VX0|v>C%W zi<|=x(Xv-5Eh?vDtn66KnU-xaXWG7>2<+GNdA%s(fLIyCl4uzRSsAg|IW5Ct=d=vY z51ZiRS#!u|((ms@Ifuo{c`tmY?z|uPMF-@9nB*g@T#N4$y{qL~e4oyXpA5=^kJ9fg z1@pa-cka_-Tie+dEmkgPgs2}@%dPxwWRJBPEf#AT(PFWdN=pZ{5aSlT^8tHj6>_mE zCKsy$xd`fvj)w;SuSK0F4ZpS{>k|9sj!=6XSq|1+!gdr{;7s03NjaxlIm^grS*)C8 zK{?(M#%0zH{3Vs-ie8lEgb}`t>*P#tK)5={=xyu8a zNoigllq)d}+E=c&=bqrXCt~zHVb2lM5Yi&~D~;bB?nqp+#1Rf|$T|LF%zYN1PaY8* zFo$FNz)gQ*O-=mMz}dTiUu=o$73P&cBzRVTA8P$KXEd!KzZEgsR|GUEJ&7?u>+&Cm zjFL7`c(&!Sk~~(%>a{Y+BeE-!F>Bj9eh>ea^x^1i&N*{9V}UfE)Ja-OT1|4kzVpdhT-Dl_uYnzkKf-jTzvfg zZ^I3X<@XcA#mDda4HqB3|JQKw@%z^S?rl4MKdk-U$z9j`@mpo=F=XrxN}`ArF5V~MV$zvQOZJI=dYUBAum$vHBj3r_e_#vMV-EBau<9>l@Qb@#k8 z+pfQnYa_oC>+AOAcdq)oTzT&|TsueddtGonp6i4x@5{aXF87jueLizMG-#O@2IFu= z`$W!8?aMrwbBa7U<3O&=1@&F@RXDzKO<|*?R7YQO%D%dubAzw@{C(zT!?DAKSLsVk z*IW|lvf&LzhuzOT0Nux0q~>q9XzY60+9EdR(e~UD^mp}vcJ=SptdcLHt zy`XKa(H73rp*zz8A{^RnJ6=an?w zRh0J3>Nr8%ovin1+*R7*uKIvO-{`vy_hsY^d4tEf!oz?$4@TkPz=I9W0*CaE1Pr6zgPOlpX*BLf2frH{4IQUh_saS zG-(ZKGpX;bj8CK{(gCC+NfSsDNoSF!lG;c)(v76sNq3XxlO7~3BrPEoNUKTfN$!8* z;2@18jU|mIwUSOIolcrennAjTG>3E>X&&i^r29#oq{XD=q~}R%NzQG2^MRBljV6sF z9ZfokbQ;0 zrjpu7Ins@!+evqm=93;IEhH@=6-cW|>q+ics6S~WX)I|xsg-mx>2%U$(hSlyq&cM9 zNb^WPB;8NyBrPT_Cp}MEOLD$S{YhEUXwo>+(WH||r;*MfO(R`NYA4Ml-9@^Ww1AW+ zEg~%?Jxy9e+Dz(uJM||ukq#goNt!^KNIHu&mDEPck!~d2PP&^kpY$MUA!!MzKw3>& zPjbIT{YfK9V@cylt)!Dlr;{d=W{|ES%^}@Jnn(H}>3&itX)$Rz>3Pyxl5+?3CuyG= zO&?(ckHTYtcQN=tU_NN3`0>C44L%CEpTRA_bTED9c;I@2KLG3)d@Ar3^ErG3c%#8* z0KZ}I*}!WJJ{R~EgQoz$Wbj46FBm)>_<4gb1AfNfD}bLg_-f!)2IqkJ7@5*J8+e() zUj%;C;G2Q}YVdyoFE;pVz<)IOF5urA{7vA84gL-=%3bsS0WcpzQ+Ph`Lk9l>_?HI% z8u)&Le+T?igBJtyQ9gb5G2kB?yb}0_20sb>J%gVG{*J-_0RFbYF9FXpcpWewCeu7O z1K(kA>L;1>R}D@B-)8Ut;9CsN0N-q|56lPIG@nM`(2uki@NC161-{@P`flEbyrYUk`k;!CwG=zrk~XPcZn)z{eTLQm?*`^W zhDy)(ftwAU4}65dKLs9d@B_ey7@P+_$l%`s?{Dz$fyWyBXW+dJ{wwgF1}_7Cm%%H5 zM;iPjFdsftdY%IwZtzRMyBfR>IAib@;6VmAEXbt$8$1ZOkHH?WYw#YxDTDV0-fDVg zU*Js!9|*kO;6s4d89W~NRfC&>UpBY}c(uXD0sr0L6M>&K_+;Rx4E`{1!QhVpuQ2!% zz>gdJN#Mr}J{Ne2!50Ak#o%ece=_(o;6E6ACGbLnKMVXDgRckvwZUHi?lAaf;0F!< zGVm`9z6j40^DZsFyK!cJOX&S!HvKd8$23#s=@mKPce8L@VN#b4t%!3?*V3w zPibxiKEvSSfj?&O2Y^3f@TtHP4L%JxoZp-Y`~kzC1AL;vQ-CKJd=c>b44wgejKNm` zzsKOu03T^^4)`#GKM#DU!8ZaQZ163>2N?Wi;C&7L8t@o{{|k68gTD>jWbpTZ_b~X! zz`Gf|0N6M97r?^|?f@QYa3^qRZ~qQBw6_-nhxYbkz@fdp95}SMyM9`AzMyTvyspj3 zJMOv{vXPH2#2pknZ#Tq!6dZHxl6SuVj`?;8?rCst0yq4{tk;mhodhnOz+D55eYz$2 zeG43Wb4zdw!LdKL1osBG{t4V3FJ;;DR{Gr4FK4}h3EVtzgA%y(nyfcCfqOr=Aqm_R zaG3;dIk=$-T>UFqZ+w;{dXPuPR_Xcp;1nwu` zMkH`gf!i&CJM6Wrw|fFN1>DF4?&sk4NZ|eot}%hDTbuRXmB2NEYf9iw0XHgvyAa%- z3Eb`A_DbLuf*YN{9kedXH)Bfq@+oj*61Yxq`y_B{!HrGe&U`(~H)%@qyAs@f3EU6B z?VrH?4%`6=+-7hGCUCpGk@XHr;7$Q|a02&PaN`oVAAvh0f%^lvLld}7;NG3U?Y}%A|5`x>}o6Szg-j!WR)05>6l+jDc)J3fK? z8n_b@xD&Qyy%Q6-hrpebz#Y3a>%BjL`xCeiByg!>*85-rw=cMp6S%X$osz({gZsAx z?ib)rP2g68o0!1umCtg%e<`2O1ozcD+;CA^{*85ljcOA+o1DN6>CAdl61Zc*ou9y64(@^k?zrD%y{QS@6mS0{1kyPbYBx!mM{$ z0`~!MGZVPafNM+Oz76j31nw{3u1MhC0Qc_++}^*-dRHcJ9|U(*0(TX-s}r~>zt4J~ zN#HL2W7fMSf%|W8pH1MN2X}1(H{wrOZ&m{L$3JAfTmm<6QP#UIftvvC`ULI@aQ~6O zy^k{56S#J8vlF<7z{#Hm#p{I1nzKfw6x1b0^gH}sLL_w@ws^Wgp~fxGXo zS??PO-1sF~Z(aiTU*Nu(z}@z@toN-1ZY#KNCvb;6n)U8Z;3k8+CxN>Y+;)o5c9SH7w3EVfqeLsPF0o)G~xKoy9y&ooUjo^Niz#WYa`|kwqB5*%W;AZmf z`~+?zxc|v#h|$t-2FcmCvL>YQB)ZnyQP8!>jS^pOv0L%Ar9`Zk+DozZP`%$~4Q>$Q zJuxiLULM3~oiJon^!+%2tE@9eG$dmglKW{`cl0#2Am_L-df1PldknPv*Q%6XVQsZy z`N?=#)*-zu?7iCBp=UmXe3A9e#(i0LW8G5sACCdvQX~$U*w(!ywkk<)M?vFY`pa{~ z#mZjU&9OQZOY0!73-Qjv!_~J-xJhT_m8sx zw+3}@rw707%5R?hb`s|eO>Cb3+a}I` zI!Vq%=tSNgSS;V;u=u-$Kc}1qNxF|pV#s+;_NuVit zws_Wk4iEaN#rw-Tzs3gGzEI(DZm`6A67Pp>OT3@NYDi2+`@kTkqkTva)6w3Km<;d} zz)MWW@yLd@{Wft==!}D|*jMt_ZWL$HxP%iknb}QYa#XbHxvs8rI9VE z=LW4O{fPJ3|0({nSp6e>3>Wbvz!iy=*F4x?NDLg`O=~O=-%iZDd^;`NtDHP*Va!PQ z_8R?rkVBjZarMB_zWjrYj}_!ezo`=EKRQL_aGbqou^AEnEjB~X!I*PI<=F7V+36Ca zo9u7l`4W-bbH;?yPah4=HP3U-L@uTM?1WSIl~|y>#Jcdi^yA@gbOe1k(*LIS$5-iB z(x11^LLP}HmG~l&EB0}CEaMXYNPDn9l(9p~az2vfzD!L0PN`cMUt)DU_D!y1U(O+U zgL6n;=NuAJy#3%+rd->(1GdVUA;LrSf%f;To*U9YOzXzH;F0TYJ)Ou>xY3xT?ygz}MC*IAt1CHrxy?@)-Be#JVR?3#~i*}@(f36)X z)v-NA87f1fb1bIyV(Tj^mlo41vL$*0*^+(5#B7z&CVK{}%2;x|kM*BQv`HMR^bNg2 zqYE6yiwUjU@R*FGA9#q(bwQ_!E@nA9h{+OtOI`A_`)^Yp`fTcLQJ;}(jT1@%j2f%{7%YFuXvq2E4v2SiGOn&el#)8 zjuqMRs8@IWf^*qbZf@eJrlSx@`Ye>aP~m1&O(v6b$o3he<+GVWD92O>Ea z>Vl!2FthSlX0BzMfADY1wHGSTIu>$b-MD4{zjE+8%cVGBd9)d%T7NGbfjCH@Pney4Va<|TGV`g-as^TgdGf6jGquFo|3R-c#;i|_rat?I8W zcEKO&)0%SsRAs(lbM$CVWpng2?JDIp?(SrAx69t_;2g!l{l@hFrToYf^~mdST@IWNWsZv9-q&ysfC2VRIx13x$;EW3Csd#f5sadT7j zY1&<$3H?lA9-_a~$Y6Ls!O2sPyzXU;>hp^6a7~r^h(BRNY+h>n>XkNWvnp~Y^QuVh zHky1?827_(tkk4)YZwbSBPyDYz#HAW;xaC6qg(MS);zaJo+sT4dnB}{wiyG^>q;kQ zg@|6*hR)-WFVX!X^I{LH93pRTSidhC|E)bE8^_vH`}zUM(t3Cx{p256?c<^RsID0y z@<;ybi-j@6x9uzPo66SuB6*l>_51hA{#TQQsDFk&oVeYPJtFY8i7mM)rdMpPRFk~C z6?53pvF}oN^$4D2Z|HLY-{n4-tEq1Szo3(H_pv-^XPE;}NX&t2;zbR%smdm8 zr2Rt1M0^{R-NiWDvn`xFBf1xT!duf)kg;6)EPKxixs>c<3inkr2gV;MXCn)K@NPNB z2X4%6JAUXlbx!zmu-0(U&lwy0WhSH}zfcqRSvh}4c^&$@8Hat&e~e_*&MuNTLMcb) zp2CNce!@5=XH-aE%x~h#m?*SKpVYh$vvw4JC}Tj>7wyb2{I%V3bCf-cj`!Ebo@E@4 z`v;S}kJEFG_ze2uuVTy(b%*n7A0FBsWZRqOW6z9X+?O#)@|ODPef-=ho>hBsJN=JU z=M(TSl&LpO7uPUGgfwZJz0cY~`elXrOHKW+248~Gb5f};h-Aq8VXDs$qb(=STdeD7 zUb+5&4`}F(ho~L(Z&mcP==?IiX^Go)ejJ?17Rp-`Cu?$|W$!9w=h@$CeeZPZdwqK7 zd&cXi@7Y{&yXJ|t^7oux@OMA@`TaH2|NNl-e3OMfs6OeYvbv{2{X<>{{m^{9ml(a) zR*^iI4`aJ{R>PQ}GI@D*8n%0mUqjoW2hDC_yu7-48|Ht7ZdQK9^zF6wPKAD6Qy;Iv z-cWvCXS7tXeg0q91Mz;KdZv%Ve(&;rIUTRDHS*sYNS`aSc2=v*-&kGdRSz?73)c#@ z&CVJ$s`VLUuL7-Q>8qhHB&ja!S)Jb6ZMFYLY~ z{jzSm@ckHWmXl(SUZ{2ND%qP>^-8<~@BDvCWRYmr&!o>IT(Te0@g`psU-!9D+Ca`402 zj=-v%0Ul2+C~n3x`X7P27MLUvo+1z{t5eeyVnYSY3)>D4Bl=#;$N9pzy1Gt zh3~$+Pb|3xwRi{fYDbL83wx=HA2-^~_Y>LoHs7mhOs>^GNxuwrNsnXli514=g4M_T z>X;kytfKv#(->KqN2&cN>l
xNq~No8GJ))KY^YYA_Kp6qe_8dhQaI<&fcCvDUo>+=61 z50Co)dDv?^s*)VOZwK>mN7%Hn^X{vT5g({ddrda&4xm4GY%j;S55EcYzk~Haeqt~A zcIKPFw;j;#&WXLGf6|*k|ITXnomK7*Xs_Ivy=<>(Z$f+R0Q#M?dr5!W+mrtM)Lzp6 znKyy{8rIZwtc}^6J?=wE?%Qa$dQ`B_#dlB=JGocjPbly$RnBwIHc1R6aVheg`2Slk zVt$!ifBZsqUWNXNXb;ED_m}M9*k&)tf0AD;cC@DT%Nk_8N8UCP6AK^k-N_l!8h;nY zrpR8pXunm7-4lz2`f7DPCGGDCJ?-hJK@V0dBb@JvZ%N~C2FM=Bpq^ozVea!j`x&;4 zqZfSq{j%$UWqsPLdEaGxu{Z!Xj1jXqfG}TtTV?mkg=>p4F>Td@=bAf3L;3aHhHNUCyA^`d%dW z`2fDyeq-Nt_iw~U9Z0|2P$WJJpP-(Jp68zUC*qLV&!XS&#Fo|gv+nou85dn3>v+udL-M-Bt(cBYp&lnRQOc z2C`yxmNhCDKPdf5=hEnjY%(^iY&({fr@%j2Nmjb~kh5<>1$xc-PrfCI{Dn01IyNx2 zAIX(-=6kzFOj+K>mY(;daNeSh0ko0&ms@Fb-tFsLmuY;L$x1BVTWG`7RimR36!*t#M)BV z_%}#oe`QbOf#zYcT%jKGX&3$e$Jz1?LiU5p_dUqV<31`A8BE54m6f~Xw>V;L-fl7L z<@WSe(o;g4^Q*z-byW}JnDld%5BQn16{32fSM(dmJfnSHWF6QgCH0x;apAG>CK}H; zW3#i^lG3q%d*0(*h;s28<@{G=%OzH?+`50S-)FCi^1$>=W7_&l8NC#jnX+x(Lpzjf z?__)QXkVD!AY+T_*k70Sm3H*A?$5BkqW;IN#YkuMT5s-*x;$K3m(Flp`Dg1=t4)o3 zSL!$PVU5>uiQSjJSz_CTdn;;*CweE*8vFLVeseyi<0_4<%1`VMy`sDIT7}PIPbsh6 z3Txq<7cBOSFM3(x&dE!^bBPX;Z%oS`B7a>GoffQfN?f}3n?IVYRj|8s96f|_lst#a zUL>v=XHKTEOuVt{EKJEBC>LJX=r? z`u{lUbfnhh1*?nMSy8_+JIk#_4qwLp&0zly!Tu%n+Gc?UZBy#1*D`JG@{EotmG*tk zfge1h`##A>$0hQSJqfZGNX}OZZ4=qUpgefZcu;BY0q^M?R`!~aPsx0CGC1}_Eap3A zy6;S2#>41)Ju%xU+Mk!cs`8qq$yC(NwpUQjuon9JiX4edL5Io|`;Wr01-@Y4<~d`h zNIm(6vNI>NcbjN$Z2MNeg;=F*+y5AqZTlb7>;={Kz*cgZGpS5K3w+dkb*{o55a-|d z9(Baym`(QXqk?tM3i~zW9kJ1+PHG#7tWyVRXX=)6-}j4>`Mma7+A;e5{iVOFt#9jQ zy&kg?-#+fO%$Ac;a4Ms974*)>1HGdqk7%GHO$Gij__HpC3Wthea{Q}s(uq&WLoQqer6A_>YMAW{>JA>=bBCz z{Z-PoC(^dafwnEzif#M4we8$0ZOa(vV|PS--1ZEn+50W!Rvo9p{fpnKlE1Xw##sKg ze^K_`$~@jjpE<{+xApP;%y>fIk$9zuC&V1-zAJQ3)ZaT)9x^^-lZ#Wr><`rgmF$lxfgady`{Ospt4g{7J*#`4Wt>142rPTnqWOKyE~zL>p-r-+ zN?TXb6Z=rFm`&n*YCCO`XRLme^n=-DGR6gauw)z>I(7o{7l}*LKK9a48e1-Q4mzSW zw236P+^xl?*+FxfcC-C;%uL$;!{8hG!rv;oFBYr+n(+f&Bzs(=z7d<-gmeF1`L%XH zU6jWgdZz0g$Lp;<*J-Elx}mvh?3m8gYmw_({fqJO5V)$nBf4M4K^Ys+<7y9VWISXX zQaKvXbKTx*o^Q7=WmwO3sA-(4bxvQ+ZmBePl6DdugB7 zZSAM*82oms+ul34ZZ)i(sXd`{EbC9bjo}|>w9DABB{n{oFMYe)We1E8<$S0mey&Pm z-T0pS(OazxRQ8YVnXa0~x*Fuf+uG9ex=wPR$8n`HG9mPj)+!@4&>hOR^7G_UdLmsC zqo*c)Sp!`)@$j zGES6@=U|Sc{)ejPRx=KZtt#hM%lH}kSS5y{tSwVhtbmhpZ!*4Ud9kq@`%C;D+dX#g zp#5uV&sVZPz8Ki^kw0&))uGaS9lNB&pLH32i4b>M0FU{wlgTf@FQh&N^Is4b7V;f> z)VE!7X3AF{pe_1k+IQ{Y%#cbxufwPZ<=rm6`<}}BzLhnghq5a9zjh1C(mi!$&haa$ z*Uy5oCJgMMEc2B`zC81lg*+2kZItgLz-!@?v$%}k?fQZaJU$TSy{m$U&h+N?IYQE_oC*tvrld&25 zrSE$Jza;14`DB&+{0U>OtPML)cb|vvv2NzEewK@!k?*ly=&@EN>vsOSVqv&^ z+vbfTFlRlEwC~)k<(oGn%A8Be+L4}1%DeKtBw}5NAt?rH!|(e{<@kh3wiIi_Qm((j z=ztzsr*GUHI%K_OJ#=Kt(7|s?2k$B!>!D+V(ecSDbX2gjLf=rY#+h2j?yIdGca+V( zGse4FR)-39U(NPVt?LQMmHLNbIw|xQN&L9#rb_Fm5(6c2xfz)&Srd%)z0X;FO>Uz3 zr>#$K_dILh=9S)S|F_C}wSJXL>W$8I2Ru~v+d8iQV8LB`ot)Q#uCwoM>9ZO?(v9P} zPSMf9vl&0Re)wnNS>@X(zhU0Xv)&N$mAp6RGG6Avf}eS?%O7%0u;y~B@nb0Xq1SXp zv7bYa)_JFV$0v+Ajc5Yr582!$`DhHu9iQ1(fAi`c{hkoNcLsAtjs2Hz|9HEQKS}j1 z-wX@&B(}TG=Y%IoeVhKW?E(0P(YPyl?0QZ29)MlDY4nE}E#K*x7OB(t5euEpvzF<% z>&GwroipKvC$e5DpJ^Mh!s#5qH!AD$nei*0a3(C{TZr}GzqZ_IU(R}+@XTqQP_G&txS-TW?#0vceecNs;oC$Z3XJ4Mr<{kHwSOb{!UL z*I{Ma^;bRDKa%N1maj*?UMyeF^0jYX$#^4iLo!Bm_Ou782LF=UMSn9|Y>aS2f4lj0 z+`B659eS($*H0LIGQZyuYeqHD9qM=G*V8@IQ`7vs2D(C95gk=|4_3>W4=^h=-bE@>0n)tahY`=k4mmO{U?Toq%fBV!W+zVOr z+ILfFU7|Ic3UOZTJ&j#EpgmMK?^jA!WIM;`a%+h_szJxqq?->l`mOIqe2uL&zook5 zh*EkYe#YpjNte7;{CrO-{X3nX$Cc9aj^pPCO6lL}{QOWUJv)q_1^krn!cW4 zV0|_HReT4O>ph46X?07%d$FY;W&6+Rvzh!o>}6feyD^+|C%6~E3I0Wi)s5|SIp28q zJik3ZtE)Y<`=1ZWb9qPS%-`!1_#k_#-z7o)+WYoUzkg8PKVtR!ht-e$-KxV=14sF8 zuE}r6H%a-;^A|QXe%xtle;MD(z*0Yh)N4^oKI2ozMJ>)yc_xen)Or6E*F^LF;5XY( zdX3fn@6hu1*q;5rTisuhxVF}z?n^CQ?Ju*3L+&~2!mHh?WrE33~0)?IX;w$%sObJ924`V9TR9}Jy*hehd5(7ATx3dcQza>eJBHD8s`xjS`v z9Qy0=ZOy^|wHx$6=lF$7ozC6yZQ=7;a0d0dlV|XGEjVkL(|JbV^K!rTYiAJtuGxG~ zsVv>*1BvK1ABfU@PMLlh>Zg4i`Z|3(QHN4qKN0a->0TQ6?IOCxZx_-nbqMLE4oWw? zo{gNBr8~42Lw=imrgR?~qq{G9wO>rH?pL1f-tc~HmUj3Abr9a~vCwIM0)7kKcf#+b z0q>>$6CS4xMNaDS_#T19-&js&!u}oB!TPt>fwNNhUNou988(Tvk=Far1Dprb`dxXx z^sH%ZBRdacjP6Ip?-_pA==(N)HIy5_kns~v4P<=iz-`ysOm5J-!MV{UH|YV!`}x){ z!Z~?ZM{6fZ4bUg&1(DC0_aK1^_L<7sDU z{URN0^-~=^&~$X@TbKSnkg=P5$273^w$;w>k?|3{j7i(2w`&-iO8iiZtPT}?4JtcI zGvlYWcNKm-Qp%5{UHZ0~Gs#|xYHho$v@XfE-R||M8f3Jjow`ctN%FSl^}rhF+97@C zxzhS1`CGB?46e|3z`x~vXN}dNr@k||7k%gTQhp@c_Z`)Diluc)w(VQqcly5fZQ~n` z&kNeC#q*4b&kJJfroQV(^$%@ zC@}B>Pj3ZB;`Zw2hK&bx#1MaT&ZfmI-!(T$##Fo^s7@# z>yd2poz}0;D5WdO-sZCUAQ!l5eC@}v`FSSV8?edhP~prwZ(R#}j5-P@$-1$`j{wUa zs&qP$PyI3a?T_X;sgiZz#&`1$XI8d;h;PtCpW5I3AIf;_7g2Z+FmqdlGr;gt;a!1g zBZY?p%Nhpd5 zBQ7{?-%4jq^-nqeKk%y&ha>SO(q>xsy<>GB^AJ27LK@T*)qAYfdnJ5c8LRioU~OOh zC@<2Ml<%$L8EEnfTq&bD@9KU8uM6CYmV&>cqcAm;7oPRFPd6YhtL$8|L(0pFp83DT z=oJ|uPDW`L86jRpVUZEyW)v0~VSl8;A|vcs^j>Y@%xThE60*zwKF$dxttV|DZ6s|X zZ6P9s3X`jh$Q3@K6|=g0>Q$DHM?92qUoGlBJNVfhL(_b%#PMWXy?V#* z;{6pZUHM)5II_O$!?VUgtdVn`F)(L=nXTSx{I3w>BXI~qhsJb}hn`u=HFGBYl5Yts z4`OE`2l*Gt-{LtYTw6Jw<4I_FG8WJAWYFg6PX}c-j-uVA%m%Jfm!>{WC*K(o+~D2H z>^+R0>4^B_7nGLZtmMHY8 zizAEHz%7m}JzmP`ZZq#0`kb`YGacP+HO<;e1<=KE%l^0?k_ezeb?%ToXVNakq!LM*cOjsTkMN%F&4XGA7XyT z5dSFfmKNli7%#>I`hVH;nzWyycl0WH4!EShl1Itef`6sGL{B{<^^MuV_gTH3;I}7Y z^?D-EKWaNX1n+s*TQ2W&#U}6`Zz=eX$J&$MJnpq$F1LR9K>4;*Tj6l>B%iqsW1#C~ zoJlsuf*X9WjZ0!jpr@4=Vn?7O6&5>!F+gFlBN%rT7CQnPN8#9bDs)Ee{kXL^af{dp z!~Dl*JuPKRT&>V!eRK{y%4zJ_ud3*5v$vvg$n34Ke2Jyhx=wd8ZD)MV=^S~N+C1(E zVz0Kt-WjyHC8(3|1KUmW7k*&BDJ=X5?JeO)Xm1HWu(!(Af2hEk<6s^We4EprmN**Zhjz z_D;32zmmN}N0I!6RyK;jR%g7_o1D_c)!i~OTUu!57rZ& zC3bn0Uq=jc7`yCR?DEdgzmHizt}u@DTK}#r-)9?5|0;jqw7DQMSxNssWA)pS`gdpg zA6~NhFlT`w!%P9}@d7*ru%r^hwa9Z(mY zn+z+ZD;jrVbh%rK1-A~Hz|LSGHapcLeJ^4=?t<+&6nin#x`OXYt?&l3e{2x@#|C0c z4#1X_-#8XY%- z7u9Fua~{*iN7GGWQ(t|{n5O3W&yJLHkFLIDG-plpVUD;j*Zm!ynRoRqd)~`Fq>)$O z(ljsl?O}dWOKH&x5Ni^iiJwTD9cWCgyK$aXR&;=M*YV`I7apzR*V z{@FG8<4Wm?^dk0k*tcpLgVv!J`=b~8;jbt4rXTex#^hr93w)3I%SlE*ehhzoOgGr~ zs&w9bx}&jGjXmvWJ+%Y<)GyQH*|yep(R|Z*l|Ck*Z5(k?<-W1k$#|mky0d0g_9NT4 z8RcymGLzP zzje?1uBt+x*(wozn}YnetH0H%JD^kRI>+j2yozMjc%{6NI*}qd3Hf7f7xBm1t|l2z z>>EXXySyUvYswv4j|`j|$lU{T)0sB$BOU!U84I(zw{xnKX_}I9#*jXVA;a~L;r`EXvaS`ryD-2-YoN1&@4rjG z%yZtQ;LGZ8IoprD%pQB0U6SYQ2}kF#W5%5gq8T)#(CLQ8|$5DEW3c3;z=qKv9I;N9QeW$-?JED3D&?Clj>#?ay zJn?GuJJ&!5v2(x~>k*zj|HBmV87QU|4n ztE}~SQ|B!fo_olrcUsfp68Ug*-SU~vQU9jD44@DDuNLv$=9eO?x|SR1-@eW$mCcx6 zO#2Xay2@r2K5dWuS8F#p({=4E#xv`uYlAYRP9^=d&id;zbjKKU$KL3T(ahWSV&1kV z^ESChCuo0Np|TdlG@wJ|`|yHKKP9mm>?v+t%=#KSUfZZ&#% z?uwT7be--)cHLDi?fys4SrR@k{l`JE(LTtl|+-ay^gxmE4z;(^iqwV9qGArT%Sv@-aDW>Xy?MiAKW*J1()>!_(UHW04jku{3JqoFU7*>ZfJ zXMArRmgK*zb9heca@t`o`O^mMH{ZQAunYIHwlE)g)E4F=5A$;A=l71tXByW#*~rHD z=$-Js+s3%@(v&mu)1_&c;Z{#iId{(pew$q8x%hhv_}%5%?uGOB4#f|85VcZDcM_0ZaYtLC6PbB|#R!{m`dv1a~$6BbwhD6Uj zWAwGzb0^w!vhMnH?764yxr^+%57=|DwJoJDjO7W>13AT>W8KeR9m{XE<@Yhm?^Js( z7E_}6Sxia#WP9#I_MFASMD?&(nDnvs+(+y=SyNjRE7#7mPao;vENg}p^n5vcWW{#s;A-~B z)WYJR>^wTHAuINXj0b9?a1F*!Y>$weZlS$Wpog0IiT*H@3PFMgg;Xq#_gtgmCN zPccs*$vgr3zc8HfTzy}AF|Kl7c3dl0Uu>S(xYo1%6(4gnzwU8T#+-`to8(-x9Np1a zgq@L?KSXxe$4!Q|!oRJ7zeHt{xvS`somqFWKe4GY9#^%cdOP=fmNp$hTW0aU`}p67 z=a+jPcHA)RxLvX1hrU=W5HFBz9PMNd zs?TFx1E1|=(ogXleL1k>i9;k0v2O-ohb@Bc=38Cl6g#2HGb5dO8JE=jNQ1_EN*~+y z`G+|J&E0np!8tJ)d{j(n9la5jIPa5ShJ~iLkm-q|%_De;^u9mKDp0sBr-ZggL zBrzaT=d$^KrEj+Rk+HPL*u9${*&jQw&phbAx0`2oXS?C=G^t*m|HT75=4HOvj`KT* z>HIF4zs$Q|D~jFU#CccB^RneH;as@e8fll6do|xSQrch!G+ep5*s|;D;;h{((tR6r zFUdf6X3yp&yFzzEEAO3zobIxySlo?vK9~63uIBl_zsQr=yd-@xhg#PQ`fi8M%!^sy zD)_H=@V$>>A}_K3nOmk>(QOS)&@i@nX%qD93i9_?y)gFE-(a(*HRq)bD zUj+}=wP<{H`ZD@Ru}GVd=R*7o>bvMDOg#DP8F}74`Rl>lmEVK)6y^xbZ^E(Pr;J<^ za~t*DF#Zug+da3bGM=1e;|X(OiJzcvm~YI+6Us}U3T@=ucu@5`MSh}j>LSb6{Mk{y zp+6fxg0{K(6Nq0EpL=g=PtNZF$ zSEV1s>N3a56B*yYm@9Uc_z%r5r~V=MqkbW2ANrlN^Y9xwvf7^IK*#P{j*Y~vuyPkc2ZYy76N zM&ABLyBFV<NaPi}>5ay$Dif$r`8FG@qxhh4l!1HeZ2$>Z|k%y&?y^EB0`&-v3;M_mRO~ zy?;f8_gORO)%)jHcpsl!uij^VQnvoY-uCMK6Dqu)?&bT3S9l*EX0OU0Q~rIQa|Wdy zefSvIXo1e=Gm6XSLpZyG-f1*XWTLjn^0lLwa7bdROQ>Wy>GY zi}LA*CFTFb$~V7mRDS5!mGaBgHJeiB$>bOm3OJTekdV zy(nMh7r6`h|FD&BzVoR5<~vv2Ri^KkE&mt2C_j|@u>8eVzSP7kFRZ{-bR=$nj5&y&STjZ~d?kZdU8NDc9 z)^bGeg#3Te%9nAKwf(64&=#V6(F3yfGG++2iQQ`+%tN#fud_T%cSZJ;=`OV=b?unE zdZ9VXe?Wwqz$<3oTD&?F-7h8K3vI1_d$p~ zC*?3Ew2SQpUValhNY+$K#$e$oHkACX`vl%)Yn&&1DHEPc9)3e>3}tl6xqcfh&V}=H zb7mF*Z~RjutZhx!BRLIaeM_+mzaH}-+C4^FS^mVvU2iD9p$xvEA^3&{;~N@; zZ)hOCA^9fhtJsl@YwUaL^45{RuGMO+qT};h>wfqI(f!SjxET)}%zRhox|~0s8>;xF z;Qzn&-ak&RqRJb-J<~~Mk`N}4Fae_8U_u7TOeP_aFh(-JdXj66 z@Ap*Iy>)wfBJld|$3N1^oqJE!sj5?_PMtbcb?RQ|CZ3JuJO}TmSK(NXX?*VF@wV?Y zVgBBTSFp*pvb z`VR{! z-kkX5`a)K&IcmEl99Hk-Zv;%$17r)jnBS=L`sk$!hi7M)PvdXFKjbkp&(DLhW%6i5 zKCk_cZ8+lv+>>8~p22?H<_`5O0lde5&brLOqiQ}tvZnc_PoVw%{khfe4mn$J_2If6 zR|(hcxbDJr2-gu@$8bH1%XtrMC&<0%z%8NKK0sIKFwx^0FQUV2AD}CBnC$~JsKaa@ zpr{VBeSmiBuyet4L(3oQuw_nK7+^w)^D&6;rWH#fH^PZ7X1bL&bPW^f6I7GnLA0p3CM=_Z^C#0 zziRaj2HCR!j5AIcpMKQHd~grsBkTFdM{IY{W2di1OZxXj3-fs;v^lt*AavpR#qZ*ox(9m5tVcA052CY(&+(4>_R$p% zbu9E8#|Ze?)VE?h;j>$H47BLRJNdz9@OvKk9R|Ny55sSpzt#8(+6@2yf8noX%Xsu* z?bgtTH5~98V>9^K_#)d-*=94s%ackzj=A8=>%pISGm1y`D;Uo{1^>>u&k0uD69lgz zYgKtVm(JI1Bs8I|W_~dXu4E5vw6z&g(-YIgviFe3%I1PIY?GU~JcgO_w zVE4ms!}!Fy!@p?WZ2uzccO2(6|8vl#u%XQw2)`vmT@zjin*;iR*K0qDHDTmMynAK7 zdmCg(zenR;(7*StaAa)&Hg`AHIYig#eP+m>vnkvjy4C4ccJTXPv#rEfj5P(WD@Z?R zI7R*kb^dxjjru5Es^`c=JW()9UAgJ+(l*E=PFhETe73I?}$PoqPm-i{u6C;9LwII5RWB^g4fw z_rH@r_h|YpKQ^IXuXhN4+AI0M+}8 zds2tlHrtPMm~FHDyAHE$wx8-S+h#kV!)%-FzjT;wv%RRo{$OpklgehB!AD@`wAm`Y zE92R1nAdo1cxKJ2_HE~CA90+sz+6Z2{EgNv80VMYc+XMueRAm^GYzX`4hb1EuyZP3 zc5BR*F`71?NqfF7pSA+lf~ec1e2n8}Et0;eq9ZQFe#&pR9dEo5>lvhr?^eKEjeYpY zN%8wZf0uF8X}=A80S@O+URf9DvS1s~7Gd9%vhp_jhWng&UGS*NTYwEqTcIj_-X;CcyH!-qr8YFt}z_2If6R|(hcxI7+hu9@AZ-=xFrKHaUu>^|MA z!|Xmipu_AwJ)*-<4(-S((?$a3^X7}lvRM;PEpWf3cXE6>Z zPSK~Wvlz>l!0tT*`K_+(m!agqklC18n)((==V57B7OFqHLGTBM!%Q2hw67y zu2};|e-u9t^c8u3630TU{VWM%J(gjFiNi6y<}mhAus@2uPpoAryrq0T{G&#!K{aA6 zO3J)LmkIl?@mIHSF5pO+SnH6!UOU6HzOXqCtNuQT{=>Xc4)zlxnDtQ~6VEV&rs-$Nh7J90uajZ1( zYk*J5EqIU9wjVX(?krUKRZDMhW|rDzs=3{!uRa{={`$cU4}RsJLbpEjkC&S|9flA5 zl6tYBolP(NQ^@4;yJ>)Z2)>i&yf?~xTiea|==Or$&bc0Sv$U7qrx2UvRP&Hms>6?t(tUwFOrnE>DNur~Ce9YYpbJI?UE#pVMKs z4trRK**fftI?UE#M|7C2!~Sm_X6vwT=rCJ{eM^VgI_#JZvvt^0I?UE#|DwYFV0GA! zl@4O$d@sPIsu}~D*Q~Xj--5@#0gu5?;qii6#p4$rg+5eg z^o7SSsx$huFXikYc-Q#SN%*5dx8oW6@93|vuS`BmbUqH+%2E1V@^MsKiA{7f`Xt(H z$vmtj;qLzUi{j5Eab@az=pg8I(MK|dfuFy+Le`ruWEzZLjgS}TDagdH9z8yPfy$5X zp$vy;@4;Uc@$LVj;v0b@`#j5#7H#95M?Ci({&}zS-Vvu|N>isG8Y<&6!I+S&H)RXWTb8-{h5JvLmU!|bu)Ivr+@4RIZ2 zj}7BG%pMzV)M576kk?`M*ihDC_SmprhuLGpEh_8}c5Jv+K*D*0B<(e1hM9kr`w-hl6) zqrQ#c1Lv#4JLoqvH}+@%KYSW=KmLeL4?b}`75k06$GCN>^xfDiq+NOV{uNlWM48z1 znRCpn9KVEq>L$$_w2Prj#&EQi7l$_T;#kL%dOW%>NVivSLpS7N=5JPjCfKe>*LDbg z{?z*je_1qF`Xg7$8Rdy{CXSOYVVnf-MbG|EO&9lXV8eTK8NVgSr&l+tJvg3)+nsY8 zv&WCNZTYGz=aVt-5`Q_^*7Mgum%eaP#<(S+8PsLo3fV`&Jn8We#t_g$--a;cNBN&( z&EU`xwZFnSn4$Gop!JuU)<-n0dac82d%f1t_~I?VRs52*h)&7{Xh50b11mCvasPYD z_q?i|5txhWd8oxp@XqIl)kkE`hWj#+s$K=Y}=)<-gc=yb2qJM4ITM%?W(qXcxkEK33cQAWZRZ`OWVGKGc--k3vC~okMl3Ug>1Kd6Z?OER_880 zd=kDUM;e}mUkJ}t6R*1tdq>V;=dyVY?4fxM{7hHCx2P4*F5_vJUI_oJb6(hn`TteG z`Ra=K&uw!qt7%`=_E<0SInuBn@BG?-bYau{6WdTvoIUv2HYdz|v(U^_&v8Hd_&TTL zI5pwBF6dm&^L1E{Z@azu0ktoAW>fgeKW|uazT>t%wji|R45z6ZTLNP5KlXL%PRQA9 z%iEs0g8u0<=uce7z`Fj-Q;pWTzM3ESxby#uv~bRF+wxiXc)!XLsn05B{=fOOk~WXl zn?S3kb4deftH=A^oG{M*HMKo-H=_-sOSUVPC*~a0)HR_*ng!`CiE?@PFr=F9o!QGU)cZf&a>rs=h^aF?Em6S zBa$Y;HeOaT(Li>{eSzvi5@t%X{4Zk5T4$>N*3ECgvmB*LoS9N0V4nB6x4>)hc z+!oKs|EaKEKR*B3OEyfMf9-~;$nfysaGSfPc>cAmQ;vi1OC~i1nWUS| zmE3$Goh`Yg$&{POP31GGQp!yg3b}$il`0nF6Dc>HmDp@*S|hi>#(snKbNlxpdG-=_ zBvsgxD!5jZ|A;hxnN#t+Tgst?sa#=Si`yN~PNWLCa*=_FT(*?XmQyUnan=+U%H20Gw0 zzTRz}UNgP08*ECHz@*+Gw%#P^q=(1xnndyZKd(wreD%mk^BsX4~BdTZp-sX|@ zd)RHa5!~SIbBF4-PxHdQoAzgRJPRY6%fdVD9q($GGrE-v`rMvkj_qc6f_r2 zWhhbcQhF?%NtgDu5xFZ4VJoEKNf(krmKNRdLT*Z0u*Dt9q~gVtTh1rr5W{iJE=odl zGF^0&hU;Dd-hjYs$|+nu2-H&Z=oDoo&(lxQK!{rg{YF&!pVF>CzT|rg_rPU7haSurus&g&0V+IEtV4r^jXy=q!j&)^ zn$AOxAw6r77X{lAJ&Fz1lb%K_8nKirWZO&;Jy6)zqVuC3ZYd4T zMWh0*^f>g%czVK3l_p!=o85^*D(~*NCXPM}C{ZrC%}MtH{A(U}H*9d6HtHPo2;BU% zCf(X}HU)OFzpvFNLw;B(aU8sU-C5JRQSw`ZzaynwUhBy= zw;yV-C!WsCrLx@Zxm9gIb@pw5?f(lN!d*YcgId>@RI477H)=hXnqG3MYKi_fcu%6h5 zFkbCC>=42kkK?3H7kV)Ul?k^a0o_zgm(b0j9L96VdpK3pC3octDH|S271H_1R3V;0 zHcoFA)TEPca$hz+1yx_*5P{Y`Rh$x$v3TOfg3vtMWi^gRprv83> zsgRz)DCA-IG@z4ErZ9FQt(z6uGU;`k9p%xUM~!mHKr*jf73U{2`T6uDa^);Kos5a9 z-d#$Phf@=6(kBAENM+*t-1slX_#ovo@9bS&f(8tZ4=i~T*q)djq3!i7jQYB z4>@(X8gQ+^wG!8ATJJJ)A?w(wx z1dB;B*|`w*4mD3%x&q7r$+LbWS1u${v>RM0tz}J8{deo@Ie0;vGG~KFGlFkF%pwbEnvuRl9)Pn(u$yDOTVtI<= z6lxALMC=0&SrgE+Lu$~0%w3Z!BtfrM38K3>5VW`>lVZkVq#jF^_NG!C|c+41&M9shH6XD zCu1OkVIL`$^kz{rr35sI)o8pXo-T| zZj)rxM#H3{jchE{Kyx8iZ!e)c3MK9{LJ^JLH>VVlRl{v!E~kTpK1e5nyT zQ;PEP193*jSLA`p5R3e?1W#v?%iB4iFHl!em6Z17Q#2=(%_TGjZ7w1J-=c+}^C4$m9|?Vpf(+O>?XT zFN)wrellK!A&B2_q@#OqG#cw_wVq)mjO-qXM*1b#d#3SV!o~0aoJ_&GPZd2`1iw|0 z7_cu=<*-mOURYrL5Q}zUm=x1V^rZ9@Y#z+rFydTt>E-|HP#0w96gbF7Xm^W~>G4ug zy1!Fz1&JNdq^VjjSPT-x`T`8GQhHCy&O;^WDi;cvv8xD^pnf2S$tUG6huIa^WEAlu zEE|=Xo5z$lAxe0BYP_lVw1r#W56~(GhEMS#O(UC99(U|t=kDwpgc@*n>{mRPy9}}E zIki_@LM=3Rgf<<^T2{u3+$J(NioDL9KkGVPz=}vJo7nd<>bobAd)fGuRV7Zz^d87d zLGrIRiZ3W^8bz&bfHgE3!5%Gs8ftMD);H};(~Uq5seCc_vX0b<$>b0l5F+ym8+tSmSP0&s8KM8}~xm8&gwUJco{eSc72lLFd+n1$ZR)%Ce$@ z1px>1U7mX_4MmX;P-z#s9~y<}EqB8F3Axf~gSHLij@!{+l=y=1@TbU%2N{U9RS zIJ6-tB{C8eF>I$W_aDj?i?Xb(0^CF)UYw*%8vQn2&SFr3D5bC>rNqr~6Y&hz6_J&R z97p7vI9;P4Q5}W>D<+_Zd;2@KMjjyGjCiR)kjR7qC18oBRdBBx?_=n$nf^v z3?GSh3`b)fU009xj=%;0V;D9#6bSP0^c(>&+XW*$(?>^9f|b_*2?ezseM*KbNTmZ) zV?Dzi{SlK6c~yone}+Yed$(^#lS%$n!VF$VcejvFiGZlE5xOFMeSvhR!twHfFb!^x zjdb)6^;Oc>Q6+ap&8)e~MLe)mBL$x@ji|iVLs45v{d)YAKha$thgXjgO?l#Q$ z?nqz9?pQ|;gv9X4!<{RR=|)C717(SD4ZnUH#Qq_lP?J&W!7_Nx&X|@}~j$=9{ z1F^nH4^)YkDbwC6RLP6xi$+voiWkAORq7l_(;w*=86A#v`;1k2dEuyBC66_YJ;Q_j zs;_7|JG!EyXl}3lSRb8Fe`G*(5E@qTtb6xBM}KcuY`9}!yU}06gS}pz&2wZ|FFP$2 zlEn25c3ow|ETgYu1XJ|BUY5~2mNoYCf7YoUJI%2l4wmMmTnfZZfzg%%%x-j+t=s)Zp6TN(VzD zQ|apRy9P%G*w=t3d>k6>8;Qh*dUr+0sGgVw$1r?h0N5!qpu#c1vD#}GBPzH&JdBae z&|DctnoYxDfE&EVYZg__)%|=rb8S6>is#2s*1VE`T@K6BTTy3 z7ojrm@x}x6Gf`O#>lz%|4Jgq6m6c^E?DOmpN~P}CN{o@7a$GH(oMU+J0BFVT$~POEAj3}^aaIM+Q@S=GWT z@X_^W;Y!#nJZ4)BSBDe78|J4^oyxZ|tP*dd&eO(YSO8BHR7HL|tO5_z%)*nf0GSC2*px?sNRI#mnz z@rQPFj3^tEyi&Nqu>Ou+c6e-LM=vZgB^wIAyLV@Ax9A@~4?m1$4fPI1*Z~bqHq3a8 zLR8p+`A%gR@p=cY#E1yoj)4IgR=swc9Zvk65$Ncl9fMI$=`?O-n1?qU>4^-3b!3Oe z?HnCOXVT52>s&3YLbt{?v|_rc^O!4+hwSocetcpQIoYM*=c!s*!Dgb7rU^KE?b!E;K!w11oe)lzaM7sxa8nr$y(TK93;l( zxP_+zuu3r-m)o}%CPCmuyj2YN5pspBZQ-?Wf01>L0+__b3iva@eaep*&0;k^H<3;6 z2agOx%_55D;D{X@dKBafxkM_J&pMw0r zW*nA}80N^vhXw1ne#GgOP{;8+DUBoOY&Q<8Jw0rC5KDXdZA~vi6>RF1o`O@4gn2Yd z8nc&C5ifD{r|acTC*))CSFJk}nWtg$_*it!R z53Ni;xfZu0lfnLMGO(=)95^mf-d=Tj7A4MMl8x8ynu0cWuehtApkV(bKd2mJp9^(m zy{;+98XXx>(ECSP1ISj2?)^5cdyxVyQGws0ePo!xFIFXI87V(|wbt*u&!PWXtD^xb z*tfC!?u7-D`uxM1XbuvbVk4-vaw8WIUbtoY{s#&cO~>WOBKAy0Rt$c063z&dIrtc+ zvZ=y^Y+zy^sz7Ahmy(J6@>L&?TdtO4sYJYtjctn5De$ChuFK0lowX@dnLjoItn9gG zH#-gZWVR)^ccy6O(lZnb^D}h>wSj#<(F+FOqCst>u>rtetX4Hv2d zPM)U!`aYF`Xz5p#aVWyE^3$%AzEkMzJZGU)N?GGS2g9#iU1!h*@2D$My^=KPHais zsF2V&j%wd*j+*d}rFQXnSn1~K(OVf2EK9{In?PqQo+y<;Zm_C4ZVG2SAV;(^DiDyr;YAYGC0%t` zxo+DBT#xugj(T=@C7#O5#mZ)z3(w_s$cvU+S0-1aI#qj=3!Oe}i21NzrryI8k0la9 z<)g#OS%#*R?$&#+vVVjkVH2v&*8$~sF7|LKmvb=|vnpQw44$c^sW+_pv52lC!bJO( z3R7eBOsd2+{%jRqtpOiW7Fxw0u!(7GFH6`9JQ88N3ah!(I)U<3W7=-AUfm2{hW>(3 zadfdu6`Kh5aXX&ALNaQ3E_PIbL5I64GzYV5aV0M_EBvo2y?~7qBgVhkzPpwAkP2}E z)FUZC@jsLyh=f_rs8(6C9WSfbnii%L84C|`Z!%q70DpI|V1oQEvgm&dcmK;>=Dqfq}nRt?*EnCyBHV)g{=z>7J zsM27IGKi9e?6kLd)xIv-6ZhpZV|KZwRaHsUDYI}C-L47mj~8z=3JbPhAe`x`+YD|e zntCpL6UQ`WzCiXdZ>)N_#_`N}KQrHiIyvJ)X{uv;GAU9@b*P+yWt_*Uw#+&g2iiC? zOsm^It#%y?M|8kcZcl11WQD67V8xb2`324f63Q=6pBs#q^-yi>U>gUMUslg+_Yxe2 zC(;vfOrCRljdzbG&ZMu3gItX4Xg>#dd0=L(YzY~&O&z^_lt08QJl#ez^{A2;?E;gP zXWP$#7p&Xt^5EDv>1B2bx&)7zVO;}U=57phknMwP1P(a9J((v4eU;cqEv_HoJ7z*%NOifubC9Thmk4vy6BQUVi zdnjkfNoK^#RC0!JzH!#!I}qf_g*V46rKVsFVm3yT-k4fGo)v5S%M6y6mxY6Io#x!E zeB6#Q0YoaSs^z*I z&!y@k*CXaka#tXk_ z;??5T^S@&4iSqsqQ3IZ?#K!4wbuFOk!$3%x6TKqgI4i4D5}@|fUS{s z>Z9ovQm=LJd7W7kOh_qkv(vtdSieOMRZ^=1<5kG1f?KsDZ*|bL84C5-AGQ2=^?W#! z;)+L5HoEmJws#O!#!P4(bas}5gt0i+DXm6ZGB4{K`F-TKY8u$<%HM4=hf^{%-b>@9 zJVToc@)xHP*(c<61&Lff4GL^e+=WhJ5*^Fkym>RwiCY9lbJ|_ICYfC8%7G8~>f*@8 z7~()6T1Bl?z&{R_7kf+`2q4Hbm@W*`W2dI7a8ilMoO?m3v~Q%ftqp>kkMGU4t#4Vs zrg(vS#T5a3b(U8b&Ay)=C++AilX09SkZB6^qxPvZV@F2$uA;w@q7B=}Wax}2mU|;_ znZy|VTMdcvCJ#(g=FG&)qY9Fh2ZwK*=}W=kl-*s5_sX{-y%ji}Rx07IGjo|kT3#Kj z)SAQSmf3hgNi%q&c9@NflALGLK4oT^3@I~p8Zm2C0X%>G`=)Z7PTv7uUX3uDcD!!` zZi?kR9Bs>EW>iKBQ^xFgKYuQ%xmhggLd+`5vEx{tKL!;sx_P}4%Q(<-7!aG1IABfX zHi76VsLM1~?f0i-Vb|~lj-rB$*#t}_b$I1>qJNLZ}h?>YB+(9Cn@KkCH)=fmt;IN3LB{##Fy7n>2ckgU%?&a4}Y* z#JzY^iO&nORR!-+U$n3l*FN%8lcO|1VbS4WcX4Ihk2-Qbw0GoPd$+;UE~;Vlvi^$bjNBk?{%c9@iXmNMSmcGBpE!viE!?|{2vutVvWlLucnyS=aN6tZy)Y{v_ zshX`3)GGDOr}HV=rKY=kJQ-ALFXE-Zimj8y4AjjxK|EUL#08U0nd$5e(7VV4Yx~$u zu(x--d=w6*MjA`)->7#U?M$Ix4Nc}sc%hqnEtiGFQv*}Ub?$cl$tETNhz)6YxQA)- zl13#_-W>+bqfPQ2PK~EZ3+@k|8pYRJCJpKH z#>4?Ud=+W?Cl4plz*E*spj>7G(el zb0(o}MAPO|GY0vF#z>PmIdjNV@-Uvn4QYK`WqCE>U?Gn{LT9o2JL+trvht|M*17$d zd&cF3O+@h1$MGV)e95HeqA@g$IuBV$jidTPYicj|9miw@NyR6y;DfcCv3L@%yug|c zlElYAqM9eF*Q_mcQfROOpb*S=_|0c=>lA`dTa;SvWLA1p!F@z$0&y&g^_Qh2ok7J>S; z=N8xf3Me^Ck26N1;h9$QhvSZp)Po|14ZMb@8luFQq0<2*ll0jcN{o+3r@E@yAwpxJ z0##8E?&X7*(1|liwXAfUhg-rdpN0`RZ&tqJ(^U_$bT@?A2sM9$5ZXzJ132G zxX@u#wOlEDh8_-;6^$5ZKeN;dXAAmgpp{g|hd4=>@ZM+(zgxb+!*XKgf({o0pxnIP z0=Gi0{=@OCh&6OK+BF0PHP<`XWRVNBw&1eg_jr1odiCQJUXLlRiRv}M;&CpDd_CT| zupWV6HOG{-c;^d;6cg+rdI8+&)2+P*YN4rXWXL!WsPudvF*4-ah~WX9!p|}; zuv`L)A0lmLCF5%)v3w=(_7dY!_Apd~iyu127Mgb4fwyO7F0fuS7fnR3cc5hX0S49*MBoe(+?szlwPCP7hx?virRT~I|YG@jF zrkz`LGfNxJdHw=kkTV(^lUQSD-mtOwX7wsl5XS8=^AgxKMZU=gXHf8} zVzUSP%5(=alqrmJT5tS+`z}HKFlS!gurSourx;s*jn>v1C>b1ny}d_SZ=ezvKV}%4 ze)_=ssZCaR=Ngx;Oopn6zEs15!$0m2*Z%jdB|;8*ke$XgxfqqwgAGR}74dZj;lYg#_lT(C52I4SX~ex(_n#y`!0 z(;WDN^%5>;Jw8Z`s}9#16Loe zAzV>hyKr5H>v~*CT$8vmxbnD4xTbO4jB5tht+;N-bpY2vTzBBQ6W3k1?!k30uKRHD z*VKwX@)bP+xL~Y8#Y|z zZf?1xrPWyp6vb=~E@0t(AxGZdDG*qKdyVtAh*a^dpT;+|bsTRhejFo*ir(VQKDT?O?VzWrkvVq5m$3;GyaCd3swRtTsQA5W>6O{AZ<8Q_aWYD z7I3fwN+WNf`FBd-ysMe6Zoydyto@&OuI;#jfBy`lVC{zvNT%}|kz4Ie4EgXLgv<-i z4}Xd=q4{?slLdUPOXKN|@P_k|PyIedUa|&%o%-J*S@^Ph7*a2PH}h{@{i6)u!so^H z!zAT$J~!0gh`-@BJ};|J5a*42UQs`Tzu~QXUdaL13BQTYZv9V))6VDB^&jDL2cMhj zyYV;N$>(+TALeuSMv&H8zl*i+*@C~D>fb{A9i($h{UJX0@_B3hdBnf+ZTQ<>zmc@{ zkKnnx{&C_A#PQryKfrtjufX5!^~;HKHA8mPzm{ote*k~`>YIsw?QVoe>wm!K>ymih zRlkVOZzc`b)qkG&fBZ50y}tfjhR4?7Ia&V@pRXr9ll3uRhR1He-;7f`g~H}7cmNR# zUAFSYi@FdoKin*T8NQeeLTb*SP%!R70E^y$9Os9leEhyVGF!pjZ*bQFfkLo=Axl0( ztanrF=7-s?OBSKL`R`%Cl3y|3_sU~02wHF+DP25+sQ-oQOlQI05$pdjuk#tQWCyWc zOROc&GW2y4`c{P2HQ&R~%TQWf3m@l)!+35W?g~6C_5L8{wFo%t?Drw6{&h7M1DGFX zlC%GmA*&>0$=P^bxSGLB7V~kVl)490EZi)QzeKu)Z{*`*V(kMctO_|x#sDw6JB^Sf z=YzII_eg?;eEj$U#4Sk@;ZuU}8isyW5Ek?CuZeK>g?wBQVsI@#`MUTGY=v5ysEgM> zg@F0tf5qR1uj0?oaY^-@+BoAc`z=|u0e=>M;hTtCvI$8SKT5PEPvP;5^}@9pAe_<5 z$J&dS;4OWKTW}Ftr?!@;Z&S)3OvN3ptG!Te;k_s!+)x_@#^O!D&Et}4pL7;nkLR=B z!L%=h7=HE@KweT)!{=p_C?j-bEo)@-Pw1}Y(+s;D@#?2k7R91MWf|S~W#n>NWt~=8 zr&ZQzl@(A~RQ5||s9nP0-7Y|^(FkBAJ@U(BQU0c7Xd72{i~3(5G2)wqP4#WMe9PNxQ*6@c7|Zx z&byKs-oOkW^D;aO^{jPCB*_1 z0jL5lX952gK`Ee(IV=XR7lm~JKSbf+P8i&I9of_BENazJFG^GtQBfVWV8|j1^>b8p-}JH#64pba##;67#60;ZRZl@ z%vB(>VR>lnxe9aXJSpoe+74%H5|%`gz1>mD*Q)xD(kdpXb!pfij@h zppvI6UZus+vQ=9gk}%I>?4kf;*>>|aYat3`?Sgl|Jp{4(VCT6TC=>5_JEpcP-ruz#+yXHoTA(Dz2+GmYScBZ0FQU`cICtZ3DD>+kXW(xL{fXvm zsHJ7S`kzUUO(YV|`pMi>YJDa)RaEbvSU)9iyIntK=F!c19=%?9XsHOKDwdj&9`7&0 zi(H#!imjs%x;~vvWXgEg^()Su`L55VbH$C#J_R_2S)Oj5$d=a^_Z2y}Utca3Od0FZ zkBk3p1+C{>wf$l9o3K=CA_#yM^q-I-okJkTO>j4cqa_)9`&1JZlDwgIlGLL2)Np!I`?dL@#$UYcs$bN-skZ*% znmP#Vqo+mqclE?q*;h`BFhu?LD#A2ZYkyK3I%j+Tj;nh6diz9zzXb8Faky6ZyOi*H zwZEhEo^+9o%{bbQ^I@t}qt9$?7Nv+jq`M7mp4ycx@?EtHue=SWYp6E+cHC;_Upc?; zs(1EX)pu3x!k^cyKI_rGf$g>RSJqu|Re$aNx~+8&)b9Uz?fxrk_g-0h-rMV*>APyE z?z4!>)@`kAeEU0kfANL44awh{FbD_ri*a#{70V$vzi#pQ0wc&+W?o(UV{G7R;ERiH4&R_8-CVUA~ahYr?;x8h;p4<+_H^7p91gdLBVMPc{U@lH45 z+i@8yS*14R+#L#Y(-7s*#y>?lvM9`ajQOte2`hR-LWZIbMneB!r^4lD;>OD3 zu~atcK)vEP0B`t$g%iU|^kaByBF^PF>SXjZU#1x^In=eW)J?H`PF~vLFpnZ$ohF&! z9Sb;!%=Km-5{;FdSgf?4PW^%=r%Pk`Qo)Jws}@BGWchNKD~25Qq;cTUi9rqBh?hG_ zJkNqj-mw^84aPj-kBzqj6iNE5ABC|inH`qzu_~HQK!3|YS zsgq`w1atgzGCa?Tcf#N`jt&k{PT;LSF&t#(_Yd$wv6!$5gyYj6*m%Wh*n+ctVASo} zut9ApxXlx8^B`WrH@H#V$Hinp1)EjH-RALZ4&Nz`CvI#;{`&JK&ErG8U5MI~#y4xz znRIF2nQ@dps@)ee%bnf~`4vbuWi@pJ9RKSIq@3u=Uv}F;I@P+_7?&C%rd< zQ~6vz!PhGk(;F#bWR;SYKrye_c9Ytl$}*hWu2cMSMn_c5JfWf~LW1MTOC5>^4$e^K z(60QzbYf4bTDwVIRO^}Eq8r&42zIg<`_yHdM2K-(J)5&wqa=w4y1X$oVmYrm2Tdk0 zRJslL2|ca4l=KeOefB^SGbz()rCc1*g&3FOLcVlTK}7@LzXVEp_DB=}Yg@^uv_G4j znXosIpx9V(Z#>WTy@4S_FGgMYhoG5SYxaysP zv-nK>&bymn6xXiGbVcX9ikvpCLD&Tqfpej4T62Le0hxQhWq1PJyiqZSS?Jv+mV0*J z#RUZ3xV1MI!l;cf>gA9}lD|+n@Wu>-Irs>pHiDl+7)jQt9C*7*Jx=1rq}F~V5nCl_ zl(#Lo!cN&a_ijE#am_>BM$f(5PdaMqY09W^TJL5dOkd+{xSRJOTp{Or-k1r4O%6mi zS@a=};UQ<(1abN0ATH3z+h57!$YZ#DS3UCfBrXybecj!B{H2QF?FC$lSMnrzk04Bb z%==DUA!n4gdvLL`ue+O1s-#ig4&jn|zwT~77q8yTg`}|}yfZ6Skav}G#@Vp;ZazM! zqewmpB^vK!oy~{)5k?&F;TUd2u~-5~{E)yB7mqC8YC%9ccGShAiuH(PY#lC^%)64@ z5f_gN(_;=o#1o2iHQ-rc4!d~Vf{Vet58(oByfFj27651cmaS4jvIU06Ru8U`2>NF6 zSIfyIe)P@auNE!CAAPp?t3`wGXMCw@#ghy6koK*r6)!Dll#2xo_^d5x^kCUI7T++2 z*NO)i8jRay0xy#LBOB$0cv_pvhm7}H@hF2o!u@DEfnk*4cmJ8H9<|u^AQr zI`EA!@k=G%_-WKSX9?`In)tH?rtcYlwZeb&o=Xk9T*7bm;By3i$%7jOHh*fJ73NXy zwGI~OtY59eeQy6(>zwZcc&ZiM><864ukiti=U%t}t94%IJg8VBfnn!A#jnC(5T;a_ zA7Peg_!R=bE&^=$6>^q3n*sM-qEghLJub&%$%3NMXTeQ3o{<_4d zKdk@1;qhjacK}Hk|2*Kj%K+m}ctHg}iN9+mi2wB4e0;9=o1e*l#qB}-dr@hV|D{#% z4<$nZdbW-OMy8~Pqlo#L{2#nMh~NGmAD^Bb=4bFH|160A+y{L8>#E>yh5L%lpT|Dz z75261*0odq^5cI`U75FDA@JE-Szi53{1N}B1s)IhM>bFdGeh#5OP_r&Y zf1q2(5VmpJkk`+)CQ9&#Sn@DBkm`>db-8Nv|a zJ9Yf803X}n!`vcjO+rWL`dt9{xJB=!fL&DnF`b?}JI8zc^t%DyY4Ixsc=eBb`fdii z^%lpuUZ=km@TRz*{sV;9hn$ym{3ih){c|;Rv;L0&UU8T^G>YF}1KhMKCab<39lS$$xhos31xI zDB$)hlsUol#{h?05h?MG^Hab(U>ceBoQEO*2{is;iC^rT1Ng~r`0}(F@H1$?hje@| z;LIf<=eUM<13m$Hd0NBcfN%XP@Cf{1`DMUI>p~uVZwK5u-_P%3fTzFh^ZV0;ZwNWh zV)dEn9|pW)25q48{~BOt5I%_-egg1g(4X`!BmNHohwlw}`1M%X&iqkG%ss}R3%J4J z$2!0(-c;i}gY;~_4S?O7L7%37E92jb{;SK|4tU4E`Sl$HeAtrTQNZhd0v>4mNx;t( z)kJ~i-vW50RsQ<{-;T}!l7;?z0f!+UEN>~~{|)fy zj{-gz@#QH2_#w~>5tI590N>dO9%_Eh02bd-q0ezX26)+JHDZa8|9=JenTX#WM*zEj z=ga#sz?&@oJqP$0oZN0lyOTdy%ysf_2ac|P9bvD1mOG09w_E8i0Q`s-e~!}xIQmx5 zpwn*z+-KoO0PnKkU4ZX`JaX%wP^&PQM56!CJq44g$XS2=tl8{{-M;R{4(r zKK?1_GadgF;6u=7uFmg`;3Lmm@OM_t8P4;FPg?YxQ4jm*jmT5up96RX%H@QHR{_4= zDsMgDeAMqxI{^1>^7Zv@z;}&djL`Jl0Qhl?CtGxW?*_c`X6PH;z8?bI4f$35>1^jO z0p9_8%hmXQ2l&uQe|-5e;N;ISCh7D)0Gzk#a{}+&uJJpBgc2*LK*2KcC#-#N}Mz)wt}O||}r173~Jcvz>u8Su>(Js$$R z<62+;e;V+*PQSc|nEqq_`14PIZ@1Dv3;4uJUmn7o5@9^QLzlM+9X?^-Bz)$}cGNj`_5BSdiP zk@|iU@G}yzgJ@2dChfe`GW=PdkXfSX_+n*7!PHs=gz4{rwi_}BdLtOxMc z2EYAx0p9X!pT0EU#T$?iKc;^R;MFxg{sF+(xjy^}z;{{t<#T|KSp0t!@CqxxZvi&; zTm#1IeGabHd*P{Lp29b^2!k-@C-;->(3_aE%YoZ$N!6#(YQf;~c<~81Id}wHEO07%!W2 zewP7mwd%hE@Pp|5M|FL60d9aiKB4h%1biIwbg$M=djOl?1$ej(@C$9ez5ijrPoh2R z5Xbr11H{K9Y)0Tl=V8G29|w;Bv%cQ|oblR!x$^_SGZ+kwzWPtV2Y37SWoRkr#dx<# zr#}<0*?XkEIT!Ht=&wfKuLHab`SZ85X1Q}Y;B`Or+q0MWR{2rDw}0N3r#Rs2w!&W4 zhnRsFTp;V2Q>Z{06*rHe~xnm z@RP8|jJzHLe00dSAAb%wS@7kv2AwVnVZUFu&v}Hs{FXZx0d9Y-kG}=*laR-UG<}1_ z{~MH{;Yq+dHUJP9{TXo5%I_V3A87~wwY$Vf4skn z@mTLTtmCf*yk*88U-tlh;d%6FEgzfFpQbH(4j}$s*gJ-vj|0BdivK+G!~D{;&$j?y zcO~f2`TYR!K@0ymz^$$R{B{0v=u<1+1$^M^XfMsLui}2RSM|>Z%um)M{&)&`>iAB; z&qDr;KDid~%@>B`Tn+iZ2k_+ge0}mx!1u>|{dgzfCp`H*$N3E41CFmxz6f{)?0-|g z??G3I}Ef}9nfBzWc z;|SB`eHQS87QO!fcpCP#(f8j6d>`zscAei(03RRm``e3v4_oQaYJ~iF^qk}T5c7%0 zt@xFQpZ4OHJL>@-v*J4e`}5y(oB_bkp#1Cg__h;pd#_)90`Prae&;xO!1tnm8+o50 z{C3~ox(%>1<&STF3V7yG=qJsOj{!a&_WAV%z}@dff70^)b-=CA=Y5(V#{o}Ae0}m$ z!0X-;a-P%izXtp`j6Vz^qK|48xzh+Z|7G7^UJdxxKgQupoqiMG zr!9U(0AKenzC4TqZrJ0G_mhC1#d_R5nx3}hL^Nc?DTfk3R z_4|9k_y2FdzkLI66#B{4`5y!PH0ope>wf|s`iwtbyac%QHq5tmeU_Yy@zksTInD~e zFIn`w0r34+{AR$%zvt_#?SM-t|BiWzzfr)(r-}Xb&43%w8E)6*r2%(Ce(%!sz7=rz zD?WXH3izJQzCH67fa^8_S@0d_bAX-y;q&_+7!P}Ii^MN>z5{rfh5sLblRw57uggzB zj$AALMa0iwljI?tzVSTBtF<2X8o&oFey#@mq&2==0r&-s?|16-{eW9x&zkWy2Kc~E zzrF>)lOcb-=}!RPkM(CXxya{1z_-5z{M7k<9Pke8ceon<9N={p{oeqb{|$JiD7$kYF?2mCDfSJLS(2iyRA@)-?Z3HTVsXCsfhR)W`7`MVK6 zW7(H+z};5-KERVt`touRaOsWyc>58+_r1pF-vfY$tn^<6e4Pb933%6ozCHIdz;{{l z`8?p~toB+0davIGp6U9m1-$x8zWuWi@T8T01n`Ltf4+DP;F1-81K@Rfe|0I0r9FTh zYklt)z)gVL5zO_zcLRR#YJWWa7~sQ@-~1xg-k$}$82b~qYx=$jc*ZL4C}4ADQpP{P z=I7$!1;9sk`Rz0BHIN_Z=L3l2__+*l-#=l@)bOQ%kHH=@^4<;D>GbC-*8;xdAAS2E z1NeYN&n$b@3rdpH-NX4Fh1+~#KV9OS@B;7eBY>F{to~@ z9>@Guk7pm94|)2U-+zCG_~d{1{RLa%&bog`o|^tT!1;b(p3VZi;tIe1YXINt@#h?; z74Yp{etak3Enh{L&Tk0t^mIu4QOS?pgtz9{7QhFr{ND@sArN<$&hO6w z9|XU4X&ByP@Lx9)-mWxefa%1q!V{|bVFHfr| z`4(&}S)Q8OXG)F?bW6cK!yWyRn1W_ylkl=BW{T!37(L~ze6gmFhZ7QVexYx0du#~) zq@}*xgcs1sb1Mw6(yEUYBh{?1*f_E+l1aI#DI9S~D9=w5N{2;6;;q@2UAlRLM$2XK zpkMtR>n`9cDg^{|^hG1X9WlH)t)k(cjw@#6UwA5VyT=u(P8tHrUfM5{bs59i4p-I}lTd;05b*n7 z{8)2*=yqIlCHRuhjbT%RWhWaUic~{KeZ{@(IXR{n99Xdd}dPxeiKY0r&94E zzOs^x;k(E9_B_5l;}pu-&T?^|M9X*2R7#K$3sC0EPi$u{Q^H4^qB*<+9^Zz6Q?==b z_*xH==`S?HB^I9BWGBAl%#%9!;C*ES7-lI>$k%+l1jx#KJX$pb+>|v<&bV^3?Tz-w zd@T^|#|M|PsVMzeAtK^$PXFLyu-*07Y`W>#N+yB>q`6d94D=d^pSO|;maEJA7#9m1koFxM=LZG|4=K6gN5)3@8K6>SciGM^ zJw3!%uaEGfmm{TA9v`Yl2NwEKI6uz>$K!-E1$~`M1Q^J#0fF3X5_Q72h@7!1ymxghg8HF0Q@^L&} znA(d^-^8Gt*#Z)eUJvhSxHQ8PyC5O91gJ)mVyvDUONq-i^CU99bB1onw1#GUCYx!> ztPj4amcyw7rA}3?r{H=YU`8Tyqpw-LQACd;J#a%G-~kOvNqUOHi7$U?^@G6yUEuP| zW5r@3o~_yobt}T5A9UcGqRyUTwu-KnkIsp%>7i0_%Ee47l@E}KgBlnMgF)z-mf8l1 zeBZuSUqW&9uBe+oaZ?!w9(b^#QiRcd#!=oLMb%g^SjJ}os&Q<)2tGtcB%b9{LBN$h zKs4Fc!#;^7!oHvDkMud|VsC(sd^uB0#q#NCXdV`wSK}63{&V>l zzp{X?icx8tAMOcMF{uTwS9+;YAYJJ7N~xKQcv8SA=hMN!^kHRmVN;~kwh)UC21!E+P=1j3TiNsT= zJo+HUS)lIBHJ(hsR+8fu9GYVrT16dT^g;{k&K~IKB9OZ7wtg^-k^!DM^N16=^F*mQ zzA;d&HV9)C972Ov){)W$4Z#@DDR-rY3FB~j zIyqiU2go5dj3kceIHdvYQ7U9BdoN8UcD{jJsh4Kh6tp<3DI|rp6)$H>U^?vmcqSoT zqlot?=)#i0!eDpgW2rqzZfa$7-`L7Dz~N)3uMIM8peSdtjEVQ<>F)@ejKd;dSybS zrX@-$W3WEb3>fyMr%4*AqG7ESBm?F zKtM?BuN&|Wtod)SfoT1BQGXXxZ4izee8G4OD&R5Hv zMy%FkL@{5zS3MFTJ=!EO<}8s!!SF!|4<=fA%9Y6F_xXCcD4#nO@~v6K6r@Nxqp^9V zf%I3aF}%v7PF&@M3J4~j*HL9bWiC(4c|XEB1`iH@o7M62OXSmRAl^0~cW zFAYreorx(Jn`*F+=_b&VGf=v*a@6RA!D{AXtObad3VM?&Z6v3QFp&8TUCmpgdPhWY zi6O{(+jcH$#-VjMRfJjtVdgNL?$PYasig1%k;!5%hVh6a9~(lIs!VmmKcyydz_lpW zSg>v~uVKpI+<`PzD0<&mWm|Zy>);e%Izc-{dV%_uqGVWM|1k{4xScHydBWu9SKo`6 ziI|W2@~gub*GiaDngxL2IKHs14j%ICVvHw2r5==Y9C-z{fKrJ<883H0FBDB6!G0IU zSy&8HJo$)-47zwgWI*0NSQF%=(eJ%O!dGq2%PgK1sWLrM#YyBOwAmyNJ>x@{g$XsC zt~N{(xeCb)E(Fw26(g8PRr;}NdPG8VYiqD5W0n~}c`{TBOAdUKS*MJ;qJcTc#wu5g-tKk+0I)R446}E#ElH7+=&*=o%Cj#TI3{hs81IWh$#Nc?B zGUAG;FilNGp*C5CZknutP>gbFsKQxNd=;%i#j`o82nFnM9Qp>0zVQykEUd-=*O=N; zjiQgd6^kmCD1}LhB=gor1(%4#&ZwA$K#?H(ehjiSk7VGI*(^ixK{Pd|5emR;(Ie<#Re%|n?w7JKuI&jklCV`Rqo9x)!~3?(IFnK9X8mg6o84dZ zrP5n7gfB$JC)Cpza8lVU#(eO3?$v*`onGKIvkbMp7g&~M zHb&GqdX;iF2AD!Jj1FO+!=40})475lz~g9Gu^5A-!=T$N0DH0sb4GGfI?C@|-1Jhf z3JK)Q-a#t88A-8HI<{BU<~GAB#7Rsb>}~3fR()&3)0i;xWT~q+uV;8YSjHa#(_my` zaRT%O>BXx|I9fSaoe5e2V2B!VRR-McWaR=29}M6|G_s$9f>2`{H!cuCYaF|BMDduZ z=KWNgR7x^fV)_`cw_&a_+mSolL@BgSPZco&za}=*jOR8$3WcIG0(~% z(n-J!6Au2v&*A0%;F{!waKZJ%S+)un0JxudKgRL*dRz-|5w8_^aOZVgJewa}P2@*6 zJ-FQo-VpHMrY=V{Og!(rHsgZ3k>K&&7&Eo-AwdMwB8lL@E!o+I3sHi{cV?Ub5&YzX z`4N}D?YQs?wj87QE{*I$amkZ>7|(ECQC$3%5uf>vjhBGu;@K`2pp(EwI*G@3Z>$8d zTXh(261Nz4xQ)tlC+>VF$1dPKheS-fOve##FD}vw*BUv?-UpxJ>+o!T#OJSo%i!@H z9*2Op*hC_ZJmK$8a2Y)MCO>i(d|co|YJMikJ1jh&VeC7g&Pi3`y<6k4zI+$R&A?kv zCg`8Z@BM&T3i0@ki2Hx0&edx)sW+cLii>z`JH88G1>TxbhiCIM`F#Qb29NK^aOc4L zH1Nnf=ErvjGy(4zp4o2vF+b-204|fCIwMr$tTTmaJlw?B%;53e1g+s3IgiIU{>W!0 z`+Hm(uYqSMqVrHT!pzTPeFOn4AM`cQSNUe(%@`!y4c^!AtntKWjCedRV15PW@rz}>|C*m`F4uYq?IvTA+??-vL#&y4%}(i-OxHn#qm zIJk=j@ZPno#<`LWRDlOK%>dpL=heuYkqn-x?|B-})ORbK(LQA&fy{Dw;h0?@zkhLS z9DY>7{D{LJ?-tq4gR4>BRgQ!I&L81o)@gW@FZ{8x~Dk#W|;`9 zl#|`3O4Bq7ylqcM%az}Sq6z#yf!`&qQb?~+RonK$R61xFmZ;G#nh=MjAd60{B{{o_XkrMM9aInD`O z-*522c9lybi7M#d(fofrX(XwcB<~C*$=|WT#Tjqc7Ouj(@UO{$_i{akG|29Sru|9d zNJo+0L)wodfBTXSA$fAc-}{1#a~Ri&q)B!^hU-*=>+LF+A*A84`(eO)$Lit>+OMOyP9Pm%_u=J81NP#2AW39U{-l4%-#)>m=zpKPVc?~2`joBL(4`;c$)euMl+ek)?Xe*#oj?EX^Te?E3!!~Le% zeFN{iCM-hFZKO=>{`=hDa#c|G5lGGPygw%P``z46h}~bq{p8sFh1@sC?!Qfbr^fF8 z#{HSG`_Vi~~Rwx%fTf*o8839p#*J z${8O#XU5EnXMSeRg4UTApYg#H=3X>!<{8t^ojcPx=bX=6c+tFb7PL;kxb>WKf=5d} zNOtE1*)6!}ybETwI(wTM9{F(Ed`7&0_<_QIJLE`aWH&Y|FW7o9WrqVuM=&berwbMBmZ zGkS7gAh};WbNUSDvkT@KlS2 zpG(e?pRi)V9A(h-*5I;W=6M%Vq06BC!r+lh<}FxYPtAiKXMT|3B@5=xoH^f_-g?m- zo|`e}v&y%Kkr!SvR}jV$WytjN&YMZ`=bW?Pl5=Cfk-w0uc`V=+coFhlTGSf;!s&D7 zIiI_DPOAz;>kRlm>*ASmqdZrhoOJ3b$DeS{5r-aeIB0$Myaks~%Xva!bkD75))d1{ z@J|Mwo_{^~9$aat=e<(zl*0Ao)AMc>l%$-~p(sO=zb}0K8w}G`&WGsV@;8}2wLg7F z{+b2eH-K9NHYI$rz@{st4~`R~jlZems+{qbPqV;g+_VU62Fu9;ivhylsREm^a=O4~ z=$s+27*G72DXjHeMz#{_qQi08Y zx_gyxK3cRjh+_R#_{I`HXXcPU^5Um z3T#HYbul9T=mqFGuNnGR8$7PyNsCM#4?&SJSGP39fRv*@IEoPAqJ0)!TZMG{bKOA z7`%TB9v_1bh`|$L@WdE=U<^Je1|J-Q4~fBt#^A$Z@T3@gcnm%w1|J!NC&%FT#NeZ1 z@X;}NN(??G1~__!xXb3~q_RC&u9S$KaD<@X0aw zloWdEE|q5o4;BAj!QWi`eR1)SMs^WWi@rbU0##f^3WjB zi4!hgK3LwJQ0iUx4eFU{UQM5O-A|u#UA2>I_uTwiuR6b)`md&LtLuk58Om^#mStbg zxc3ccYh3od+;5kU&7lum_niA~?kqI5HMZ}cL9gC))F5YM{_tw21=?%K&nG{h{Cx8B zDGNTVc54FN%QG4D`c2R&v`SheI$U^?e!j_Z3!?W$U+34lsoX$I{Q@X7!l!KHymR`gxhX7#)t@4Ju!HfF(Sg%8jdj{ z!VNVXV?=}-VK~N!2=em)vZg-25%5Sf7ysaHw zZdIdoqP2Krawc~B$H`1tT+K+2y3vKC&Og5+7NpmJbi<57u zc6{BsSPNc+wT+PA*m$u!?p z?M#!h;d}nR>e6(a9nj&{^^=Y#pyP=c9Zw|a_&vtRE7i`>Cp)_GwXWkm)zOvP1b?3H z=<=Q^bmi8G%ng+KX1!;Tspl4U=hnn<&x3nmVYl~KQ)Aq={B~4LE}MTY_TFQ>_xQr@!A};t{1>64Hn-A$iR(bF-n&L`XGOqZ~aCNvoUFi0o>Y!Z))2_(Ih1Om#L*L6W zd3ZVCQ&AgTqIx;y{?Xpqz&jfjcDFF$R2kY3yd!1%&lS2FmvqWFkP%w_$AkO&Q3<*F zOVFO3Lrb-1AiFBBuaU=Vv37hd(T=B~L*R{!361RsIKr1vZtfZDRe1GSM>lk$W0B|8a{_smzB9u54zSYlDzv;Bqvh2EE!g7$En}f& zKW*<(Zu3ZO_dU77pF^|G$l#fYJadq&RjgrLT*GhO@GhXC>iqIFY=nl5F&Z`|XuuxV z_8og*K=Ug+|4OW_UJ0HTdt7v?yQT1?KY(#B?X2}{pu=_6>@bGbnyyWZd+4#0Gdb%t zKImrdZ(@8cP!?%%ioQII_6KfDsXmf%J>^a?np6kJ>cIFZI!JUxKvxa4mC*H@(S>Pr zVGTNzqGn+h5Ogjy(kBA?8jI0`zhW(JbJIi-eb)0x5etUt*2hz8~jEpS+Ccq*Ffr3iyj|bAw|wu!opL&uQs#%grxqD2`Q=S0RO$y`rleB5XmM+ay8H+b)`Yz#M6angq4 z>vFl^S>%)Fv|R&zpHo^sUd)?FzsK6nqhCoLv}4BO>TfR4CiKTgJF=ATMCJ2b{UGFn z_R_qk74t9RyYWx@D`V@Eeid@c*r|41waKK~ZNZo;I@N7!qpkyxpFnqGV>fU=VTZA} z()YIX*c;e@f$fT|Nk3jK_D9qwOdm~d&N-chj!fhH#fuu}?~DC8AO~&j&;?HhG+;|U z>0`gp?{>6Z(^kj6$`se1^ut|QruaedUr;Z#XQaJ@GD`Hzoq6_h^1YgT+u#-Hp8sm< zs=2$V>qOGkq|UoLx;l@`Q)v1;f#3AK&z>(fTqeIi?_AN*B|eMJ|KhzXw9jUmtIehfo^!(I ze4ed;wJC%B)+NsiZJOWbg8Uq8N3kizo|F8Mb!d;to%(^OZ)mgrCp`ENJUAU3$@>L$ z`z2{9=~tvXNWUiCN%{@xx1`^Z?jpgjq43G;Nbuq^$E7vnO&0%QBxZ$b2U1pA;b8Pr+ws$Mzmb+=(*j!b0 zkKH@iY@Dx}E<(@y%)6*#VDmGt2*xNU)x4MRs7zThAE~9R0kkbi_1n$Gc}Dup@>E;v zpRdVmT>X2;J^jHf^H9bkbeZ6O^GC;B{Ct+axFfDAh6~@VE`f9N8SfL!59mYUtJA!% z!v02{8{6-t9VOkv90Z+=9IO5oc_y7MWBDshnWA^w`}c0f4c={Ce1qdQd^h7^pGGh? zYn!wiHmbHCc9`q5VGqf*Gvzv8q#qAAju#q)w&rU^_5wI}lj|(KGL>?hr;L@~^0&Iq#sSD#!&tp{9tvpC z-!>aPUl2Q|j2u0O9F0Vd_CStE-iy-T$#03t67vF|IYt{ewZUI9o8Sd`4%zwje`MVC z(!K*TZe~Xt+v7R4XI?0D$=o6Ii?}Z|bptoJ_%VE~_fTjYO#PYjeW=EfXKAmD$5mi$ z;}@GUGG8g#Zxek_>u_)H{lOg@w980malm)(r9H~>s#F<&>2DcdsJx5^`dh{q`&UN7 zz7=1Fj~*KK5wY=_&_^9zvuo*7N77G$BmdIxzE1u<{-v8w!hb}PtE5X~aER;e+SbSO zi~8}q&?{>Qt{d2=vWDQ+8jKz7;!hB}Rn`zh&#GLkG=6SHwy+H&-D|cyc9gD*g#A*+ zsm@o*_gnd0ZSEzd`}L3^$niGHA~m2R>jyj8*>WWuZ+zOx$QnmOE%yVQYy;17&Bz)D z@~`V6Zi*}GB2q``OHx01NAhd@o2zZE^;&E7Qk@#Bm)XuzuabR7e5UFnMF&))19)Ej zjI_P_6S&sz5$J3g3uS%A-@Z^}CgA7OR<71DHh(a?+Wk>J<^C|2^2t})Aa_D9eJo+) zxj$;=UHa)1c}Mhv*lS{E51bU*wr@$D*7s4TTdC7671rri>U2v5bt;;_F&9V&b2tyV z^_UNeJPaF3J0a7+LECJ$de8^_H)1j&bF^?Sd;#qlf5$l}nA6KVYg4Q}HwEwbl;=~P zGg|Bu^+5zaJnRU3;(KWs*msMS$zLXk=`N5O;PSz5i#yr*5AKV>%C-{4U z`6ADC78a)H|0(#Y{D|>~zBG7Ju14s5YumDKUXPYEy7rZGLGJpPA-ZX0Ir&<>@1BcVUX28{1RFDMX{{pN7TH#WaXF0$}ip_vXYeJFGJgxlC<^14oT*7HTf`? z+-Z9zna@9y&li*V?52K|r0p7LYk!B*c0IIRm!z$NcD$B+zLLzR7yfq@j|F|}2jL$yf^C-q=lE+x~2(BQt*rJ~o^0&ak>leX#SRx^4~X8qv31_}@dHYOcpGplonJOe(6jX$)9#tV!_o2NuH+B`+)y8ZCi=FboxUJ1W$ zVofphd7OR(^X)1p;~s&Z0KN)uN9mfP@vhbAvN?52C?~Xq%8B?^|2vCs0Xg`@;^jW6 zWck`h=>zzNrR>PZ6p!18tram>2IW4Tx)!Sj>ZQw8DFj|WF5D;PT>axrvHM!zbUW3%UU_U zY3))|%_|{ziLd#WuK z^q4QYjQ9kPxCzZe=n`Kh_p*j9&r;v4zY2X=?X2=2=IT1DysA7gdQ$)9Rp^vS)W4bf zpRD!&iq*fHe7a-x@3#7{LI12Vx&4+sE3pxe#hxYhL**7ZXne3X!1D~z;Qj^A-DBlGy?Xe#G%iy^x zuLXYte0-z;ZSZkJf%p&l$`ZHElUNY>ofrU5Vhy;5e|3tx(cW3XI~#e2q`a3H26>12 zc@k5>z1C?pzkeg0^&cVc2WlHUVm*9PoA-L%6y@;)&crIp+1Odp`x=S;H*m$%Jg0gH*xVa%eh(Z|(y$^G@L z`>32syKLh3%}rf{H&K6n8!EpculimUu=U~a-Jxm2i62z*8o<5DRrE}V3!lN?>7z@c z-{l@%65d}wkbClSoj*9&v(_Z=30&{5&Sytv^4Sw3oKwfzHft(>YB(d+gTJ@;1*8^)_nY?qN!7XmysZp4<$hAaue%#e{9MQWw6|0h*Q=;2lVz9g|@bHZ$9ZzJ9 zLv4wz#Hqk{nY#~0m)_5Mz5hmmI$xcYIlcIL+Q7-XGT&|!eals1--G*pzRUZ|c(;B7 z>m{*#B>!Q=K?$x@`Dxr_GUva)Pze0lD{7DzqYZo`_w}!nr#=In*aR{zy91z8VUy`U zm`rcycWjVIro%ClXSJOfGp|Q>qOmZ!ejW37N~}saW^3Fe?`9lgYZ$9tr#%(<_Lmix z9r<{yY_VlJ3kBWR5WVw=y@TAB^mkGgWn{K2qHk>G8Sb|bbK5F54)&+=NZL$(+am30 zcF>fpBYjrxk%ew=>%wl~olpCV?IV89h=z4WgYmI5v@^^%)$?AEA9C6N57EUXY@H}kIct9O`(b8zpzW@sqlJ@+MfZ~6P1(dEQ2!CQDE_I^+wS#v1eKB2#P@Fbp} zqT|{Sqe!eLh^tFzzY3P^wflhX@T!%W@`Vr*&82X6#MtQEY@MTBz zdzw8s?o%c3vVQh_3B0VI(U+A!2N`W;+a1~tm6N*X>=Yg`%EAVw(s{YzPWXJuPfb?25?c^~YfE$O%YYOh!y z3VAO5L-}26{AOKG_7=EZ0sq`?uGB^LI=N36?n%Q5pPx0{bB5D3J>&6Nee+oL*rZkKlNnW=bGk&Y9?1IWdmQ4->3_pTE^?Xr(cow&cOC6a zJcau>SF?S!KVr+evVM(SyHWZlcB<^jbDy#2pYF%=6L|hbd;W!fJkOpyHy=DNx};Bf zWX%^Hul@g9#w(GH5;4=l>oCSgujm22!mCmEEkrL!+l)dtg|M_ml>bjGfBKHdWn@2C zjDOEN#G0-*oxnBH30fX)t!+*@631ZeK57zhLKYY+kb|MwsQf#u{Br#!eE;Q`o}vvK z=c9+T9OkpMB|1#UADMTc!x|bbKERh48sbdk8qiGLiLp`M{>jQV{TSH+rXOWbX3u-* zzpz}P1^uTwQ~BRh|03SrZ~2S8Lf?(@-vUkI_ljsDZ>5_$NnOIcsh`drjGsk$ud%$# zjGJZcykz`A0ewUpYJVC>djYct8{Zy&h8L|2DW5SVl8x;F{b5YcWM{GT?Tp+DuO%)- z-+#s4mo`LyMDN?U8on=lBoB+JwYUz;D|}|lLvH3&=K6r*v)dcjnWq`e{bS74`Gf03)Xg*8(Fq3J(URjTIgSENw!$J^s^z zz**vB@Sh?p@L2Z6=<{_y?eU+E;9c{d@;-Km>C2Ia1a_OoXT|(I#C540!B1yh+VPnC zhwUeQL+wefnNLvvFcz}j@{%P*BH6e7B{KIFf3NUc{Z_m?O!&+dx*Va)d%j8K=r-hDd@1US zL9Ui?FY+TYCUaQvYYQx68NM*~oOE>i8y9x_vM=QCqv2b5J}_3)2`wf2RdT*fzxN8{ zOB+Rf3caAb`HC$sxnr|9(DRKZ5_xpbDO%TjkfRDjxKE*`h_~r z$|Elt-`EhzjrPS7bGP;Ajp68xVd#vZ_;iQh(-oNhB>ar(80w8rS{-eyjQWm^l{!!O zgtSFdcW%r8wK1IEj#e8(+hS~qxQ|kD$vi5E=?QH$nOljy7{uumuNjTyxBVvgvS zFa1t$u|4?##Lgq9%45-Yp^g)M7wS0CccG3GeTR8-#%t5jQQww%iHx1l+iR@KtF-MP+IApg0!iA`LsoSy ztW?{!T6s2}Mr~{JP}PfO|LZ)Sbqwvp2L*jE(n(*me9G7qA{(l!;U#vp`k_R=rBC5o zi{zO0rd<>Ik9YK0_)XoTXG_XF`T2!HS3U7eN+&u(>QJ(umszigjzoBb$X{Az`cu1IIn*4iKMD6>|TSkKKZE%V%C z$kX1)(-`E56!{e3MMP()3x8mABHKRu^ddglK0TGCl>wcLM3=klmmMejo3I0+eOMTS z_ScvVf^OG-Bz-dMtI{XwABvYg8QLk*C&iwoT~rUT2II5eHR^{Ybg0O$Gj>lMcYNAg zp3e>EUe;8oV`R%bZGBs987I)o($*#Nls&QRr(!=VSJqlY9zs1W`yy>D5BmGhjAv%! zMB}B|INsAuU6M4uowcSG_I1M7jPqbR;2XFe8k^ub@$PkunPPA0^T1pMK3(iViEpP~ zk(`L_#Cz1~@dse*6+IJge|TH; zTMysmeXYmK)Z>{B+QV$wzgj)ahKlMD+EC9FdZmfJL%U17#=vZDaoXxcSAE#WCv9I=*J+%4(8oj;BUvb^_k#XalBUF72l2hTRm7Lk58Y2T{7v@dm$lJi z>)7rmOPn>3(Cs?5K2uz`ws60R>2X<~3FlpB(2m0IaBk6oscKxd@4LEb6L*R%J?D7{8Zm96!SA`8{=o2%oi97(r443!*|(ttM9sp2J=K6 z^I~nWEockfml3{$A5GsGV((y6h)*VJzpcSL`pigs#`;1;leJ3=dnS}7S$hcc59>49 z-Zi@_de`i#w(wniYCF7JZ|`FFi2o#d*Ze24S3}E{GfXHqntSbU@0kr2y=Q(M@g)Yl zu=bj0&&!y(DK=hj3V0ynwa%@?M^nmvDKk%!xG48ZCnb9lonH@d>bC}Cj_Byzn4a~Y zK&K6-uUtL0F;~ZY>|XY?-q(yh&>%Lq_eMeEgE<31*9>(ZKKSwC(-5EV8y$h%9d7lo z_K)n2u>F}vYkN+$=d8^;!~Sn=Ue~|0l7V#%A(=;5y~%Tz~eIw^f-P9M3yewoApdoy+|`t;FvM-o)+0 zlII5<`CasC&;G8h_*^nqI?g!K6w;}rX{1(CJLzW95>h8=B}sIxw&jV3?s$IC2Ml*a z?70sc?vNPnZM1DwdCj;-&s^Ml&v1?LAX8=$_aBHa+49~6^WkyjbpeNt{u8Pm(`6OF~5NsL)s zmUO=0(eLS7vK}sWmhO?gQEACEXR967A~W9qHg);`D|&(W)NjrU&K~(U`h7Qki3ibh z51OtQ+8+$`ocr__^eiFo0c^&Hn$%Wo;hc@!e!+QM-rpH_7ScXkLz^+2v&dfKh?egc z)1q>EtCby(Uy`ydeo5Q+6M_AjKCd5T{3KQeaS2++Ppyo29F~+}aadXgXB4$Kc}M02 z=~Mbq&eB*p$HI5&&ijF1bZ{<+Z@t6HwOBFLyHc*jis`)gv7jt;z4Uua!F(^|ox4tK zYui76cTldJL!f?GEw}u;kv-O7v{>9;M2p4kDJ>n)LcCP;&VBaITI6DFOfJ?2auL)S z9S;ru-wQfV8g*4i)+LV09j*2_vK*Z05VoVp0_S^Xipu$mm9vU`R>jI$6_n$xU|eSH zz+X{LzKB11qR=JfntufTBi|2M8*!F_yemBRxcV!M*5^91LPra8vXbww>UlrN+icq| zqxWI*df5EE(yk9%e^EL(mtt#`o|#!x*JteAmAtz$R@armyUqo*+6EGrq`Z65gNFl< zBQraotqBz9KY?=;70o-r`ciS!xeb!Y=_uyR*Z?rO7{gyz*jxw1a4 zePy#f_Xy8D5~J@Cdye(-kQT{bX&gJskr-ErNgGDomH!ZW>~pn__kiH=Yb_q-_`nT+ zVQp6Y)4J{dd`$_Pu{$6MOw_r4_A-^>-+Sdd$DLsiXK139%{Jw_&w5a@$q}K;o{?Wz2V~H_kM)$_9Q`*8MzgPa|IZN?o<{3QCIWp83C<+@kix!SJx z$hDr|i5qom`JJo&E?3^Whim5;ey<9yCvt7c^1j^5?{Y8sSLZV)hHH|a3C7{F_DSqK z6i@a=b0&(|C`vE-DjZ+Arm#^`s-rJBWup2cYkb`s>@znTg&i()tMrAYYc2?M*{B-P z2h`o}GY6ylSc{C~qOt2dYm1^e4{fn6XbW9KT0E#nw?dze{U3~%>5MGSo3ZR?wY;M- zD>-fR^Q|14iw1KV%CWg<&-iAu!_5V0&#aCU z#Bj-apT_W{Erw?RIP{Ia+xD}JoK3Cp)xdfd9(DOLaIN951xD}aGuHz%?^gJ0KZDoI zGvo8P#NH6Gqn{Rk@P3R}z;gaZtH|EBzh9)^+rPs1R!ECUx0CK9b&{5ow5+dFF7;6O zUw}D7Lg9Y}4(b0Ua7h2RfkXPg3mnq_J>Z?Be}eRnd#j4+|8p_@&tK2DL}IU+lOc^E zO(0DsHIq&yok^NOnoqid)K0pQw3u`|=}uB7X*p>%>1onNlJhmjJ5rW3jx>ohm2@)c z4AL~xT+*eaHqs)}&7|8%OG$as{iKzob)@yAt)$vToDENEARSDaLTVwMPCA=3o776m zk**`%M7o8vgmf2a8EFNni}XBc6UqHL^(T!XO(0DsHIq&yok^NOnoqid)K0pQw3u`| z=}uB7X*p>%>1onNl5+#~CuK?FNRvoYNhg!eAWb99C0$BtBP}A`OuCJQ8DQ9ZZ@+Y9XCYI-4|`)Jn>ct|Q$9<5;DHAJ5||F8&)f-IZSdW|j=`P4+svnMAMh4~{{sBF!4Cj$Gfpbw*r6D;Lii!XmAer>jqy9 z{8fX$0(`B(Ujq*PMBf0u+VI~2{-VL(2j;_CO3#mguQ2#_;L8mDIq+u<{tfT~gFArd z8~i6=KKP~i+z))d!G8nhLrjW)2zZ9UtAVE*ycYP=20sS;NrRsRKGWc5fj?^Sdf*Qm z{0i`C2EPu>N0qd!t-z-koceht{eFXMfln}aIB>JUBZ2vVmcBa%xY6MKfR8qKBJgB` z4+B2j;K{&;8hi}!K?XMgPcZmI;Qb9g1$bYB{}Ff}gFg&B#^5u7`5>Cob2jiOgQo-U zVel;AjKLQI4>hJ9!03N%uhW1T z3l;t-Fm{2$p8&qj;B$blF?c5MmkhoD_@51)51cdj5@3Ajn$P9Hmm9ng_;Uug0k;}_ z4e&o1{8iw22LB821qR;)Jlo*!0M9h|2f*hV{A1vA4E`A~Yj{e-uYk`o__x3xGq?lz zBL;T@pKkDdz~TJmFTnp`_`d_6Wbi8B7K7IUzt7-xz{eT<4DfpmehHWu0j1|v;P)83 z1^5Vq3&4jNoc?7-zEz{o4+frSa0Yn1!6Sk9GdK&}VDR3+dmFqj@SX-w09OALVTnD%V61bPZO-SHA`fApjn7}OncVGhdLvRNraGl@|PT*b# zcSr)~y_WS3P2f%jcUS^5JaN}RkdXp2l7I5!L;LZhi zR04McxT6!eKY*K(z-<6`Oak}8O&(TLJFa1n&Ktv)*wD+-JaX z9z>DeSO=~-ft$W1>%A|5yAj;+3EaKlPDtQ3fNM$M_I@MlotVJg2=4s}-21j>y^|8S z-+((gfjf3v);lGEyARwyByd~7eIS7ww>|5fn!tS=+y@i5h2Z`%fm;ghv;^)caHl75 z^@S{FgctMqqu@TAz_o$;&#GaGy%xJ_PR53ETp3=Ol2y2RAK&+X!xY0ypXpS?}Bg z?i6t6C2&`On~}i%4BX5F?lEw)5;*UVS?@Cm+~eS8CvY{LS#M4PHwE1J3EaitE=b_! z-jns_CUEWGE==I=05>mzoAjrwcTocOX>jusxHfSAl)(KO+{Fppv)~paaC_aG^;#3S z6Tn@P!2J`r&n9r+1oycF?jCTLCUDPzyDWhly)5fpp1{@Im-RlMzzx1X>s^t+{Uf+5 z6S#J8S0!-20k<%LyYRoWUM_*V9o!cZxOL#Zn81ztbJqLk1g@Jh+7h^N|C8mr3B~&0 z)8M|8z7?s9O861dyIeLaDD7~BmBTuZV9+=CU6ge zyD5QlmuJ0iC2$9V`?mz{OmN>$;I0C9a{~8saNkMb4)|Nv`}YLy!w+P=?A7;;Qj~P zj}y4}J(%_WBZ0dX+)om?7r@<~z}*e*rwQC@^xuCbaD&iSKg(x`t;0gycRL)(bt2%VRzqqlbMIx;H?}pWRFOW!6N?mYmtVp8{$n5ZPZ9bFo~GDw~yo>lg^ZjIHUwYU!Q4VRM7T~++t zQrV*%^4iubqqTTjuPj^F=yu_j=BFlRYj%dwnXG zmGAlPz>Df!z>DFMC$WI=SK?viJw1zzeKK|)Sp(;Lv!;%WeYv>a;{WLPyEhcS`=)sI zGV$@lh>su2dcW+IlxvJ{@O~w+xD9TzlOo2NJ*Z9H>{lD>5i2inW4qtb*go31{Gr-2 zw=Bv`Yh04qcgvz-X9mCR!Ec`Yb~0zqoZh(PPYs*_bh7M=??m2yyIjuRx45}wzowiT zNxJ_@V!wG#_L#6{AH<=B-%Qjv06C`%9#5!3Zbb&STI}r2M+W`W;`C*GJ}+?`wx3hi z&xc5yCUJVmw#4a4jD^Hvv<(SjG1`U)u^4RwiKPJF0$ySj{p|P;Oq3X&oW!W`yY%BxuXhA}IMV;7_kY|=zmopEeIfEF zXPzTZ$d$wec`R`fw@7=iuakZ)W##Ypxi1k5zgz0o6ZfM0`1M;{$J*_WdawU}t@m1L ztxJlxAH2$xYCCuE_AcmEH2wy!(*svz!~wjEZ*e#=?4 z`n?b5KHuRCr;NPcV&64%2Orn%d~U~>A-9IuQ_7a{i*}@(H`k8k>e!Z|43#0#IbkfS z^%a%N@azF(%i^45KQOUYMYPFYzg}f5Io`+mPdVBo{#5#gUZK$i4&%Ip*0BFXJSHRQ zN1o{h?T1fUUC^nbi&>`Tdq+L-O1YLn^4*1^`p{=n?}++L4eArM%lcy77uCh=52?G_ zNEs)ivNjAo3Qoo@*?X$zC+R)9m~TgkP6~dvc7Nl@vCanv**7#(PX3=cXI^B3cf{@x zeS*$Qx!Zp!->yU^*%SNGLFk;A>{Lw-#5u87yk^O7r&o%r{7;YS1G>;#c5k9zgg zFF2c9TW+`tMeew-W79CMJ^a!HgAM&L#k}(;P zKEfCr^+y|n<-63$_)GXA`dsXSzI9Bcboss0CEv(?Q*`xWFZ9~(@X00hs>4U1lXxc5 zd1I_DqJy@@cx+>l=6@Tk+k9N#^i-tdUSz&g$9yNleqd66>=W%nvA(p!c*$?d z>*`=1`wrtJu{hG#^bBVDVrY-c{!=**PtG8lFf^B`Kc8^~IEq(2>8CP3iuNN+B8Foc zX%XoRl0zCoy6tUF`98{<%kP(xZYFK~74d;w$B~`~KAG!OQkEojm$|mu?k{7zAI`Hf z4-xoKvEvOs$Z^yT68r?77n?}n{dqow_vQHz-iPO9%#dfs@O%g}Cu^xT{3xCe@q6%m zh|iE`h#v|Z;s^132oIp|&`wd`IcRdxcpmCz^{M>A=2+D>cRX}yPwc{BOKIQXa!y>g zoOPvge}u_>(cX0IDBGJZb4Rs3uy@t=__si27T2;jYZNeZa`}Gd4z}homaoh=UyJqc z@a!Gc1!i{~w^Zy7%}eZ#^cSfwbHnj_O8%V3;CwMt?^}IhJ}kZks@{x(6|;&&$TcnZ49U{0W<5^HSRnue3><^&)pNuZraEB9o6Y<9_&^ zjf!+`1!DncJ4N#mc%yqxT*jpxbSr+visu%|GllzMkA(Kr4r2g%UFqbE5A8eTB|e8} z&U7O3CAwc^UhH9&L*(ss>-Vk3e{0Xk#YC9af8@WZ z&^3P4j(tUbQ`y>7AP)vVa~mTWwKIn#K2XY$xu@`<^hwS8Kdc?aAIcaI^+h}D3x92o-2A6Ki;nj<#-3#yj{66bypPi} zO?(Em_^TN6L*0>oulNvc?=WMmjt$r|;~Dp5Op?5%etI82FN$YH7woM6QO2WEzPY5H zd&_ij1!F`g=h|j>SUX6+WSofFEH;0ssQ*>qOHg|Lt5_FA^sq)CZKwMDJ+$R%i3`{8Ow{jnE4Ejqu1Z(8DUn=cN|pbO=e%`7!y<`pY5H7ou1=Y(01rSvs)N1U+SX`uSO>;zhe6K6?>;lKd-2d zS72`_KVLIi%Gf^tuj_$$KTth0z+oIKts8W_7Mpqc5c*t+wX;fPKJ}i!PhO_qsUBwD z7OoX)n|*TN*xYT%UKv_T(pN!WNRF+}jV^T$&icic(z9)Q?97;tHf?n>J2TQHHnzBx z_{@`M>-NL$OVTgvMr|@zD>nx^GO)P=yE#^$Ay%K>=05d|mD1t&e67o7R=(%V zJjHvXpy$cqXAAr&eefvE%S$;cwarJqXDsc#%HP7A?2Urhlh{y$v-$Ii{hn{f+C%gA z`Y8u{{vVTrv6aa|?k3j}o|Tk?K6tc)92~fdghfC4G*`CzTnK zKWg@@rXzM7lk>L`m|Z|t~0*adZZi1h*=y!m@odQlJPj9p9+5$ann6}!Q8)elwLP|g?RTN z#JdkB-ksE+cz17eQ!3npK~NP=5sD;ABnZ4uJLb& z$o|T{#skg6V!1*+ChIKv-HuPmw*%RODBtBEFOU1EOk^+_3szF@lHbsXwRxMxte1)# zET^Z0w*10jrFB&w2QZ|K7s zuj3NCFMYGfwhQ-GRO07(H_;mVX1pukijV2Ia$~FV6Z=E2=x)9C!e_Ckl-F*V{UMwK zEcT2qdRgMm$xFXai4Kx)L(3i_|J4FIEm-H2xOBBmjyG8=V|VE|dN|`Kd5)63NL({c zd#1ibys_&nOUWK69Vh>>mvPeUCG=}>7Di|@a|2$yF8;~O1XWX?eK$V zbl)fW=(t2avL`|I0?GMGp=~027?cOIjR)oS9`K&dVP&rw`4r7(XMkfr#B#nrru)tW zW;~3(vlFwOqWyWF@1>nhrlNMXy@F}ZrWX2ZMUF(KphIPf{YT;00$;Fi^PI6$pq_mD z*l7>#-3Hn_Sf{_fm$GgDV^p^7e@wF%RNDhv$z{%@G65~{QS+7Y#Agpk?xTE1I^uE6 zCcDk}TV}t8ydyTc)Jbgvk#*`I?M&TL?j6PRdF`{bWAyvo#lNeqZ|i3L*7J#P7WZ3b zOUWoWmC>p)dgtST-ccPxy?bn@p&9>GlgWE}*D=DgA~|eCCTKs^H(blgAbLV|&EI>G zgL1lNtjPiG6v+eQtJ=%pisS*=3FSfC6x|xx9qW46ImD`^MZy6CT>wmpfqMK5UE zaxL4ouUXsHe6IX_i+1p_JEA^rdj@6ix0KuKI2G<+^n1x)+HOlMf7`z(`)*|(@1xIh zW79kO_zpTc@Lkb&Bwi`v2{A{y?+V=$_4moY4)#hjM#*03zUFHs?d?j(DCkpppq_f| z!~Re`P|p6C8R&tXwm%w;S7q#vXz#O(6X*ij2Q7QnqWOKyE-5QZp-pm1FKt~;PaHtK zVm3)`>Q34upRoFAzlq6$*(9M|CSzQ%2TR7Gx(O}JUnDL~``CF$YizmLIp~Py&?b`D za<>wjW*5zA+RXOXF*9lVkA!dN3xB)lzF4gOY~u&INcOl!eIquv3FrR(@@wsax+st5 z^-b5ij@JwNuG4Pe_2qrjRS~Z%^)JT9L*QQR9nt+V4$9bo9#?yScvKmORE~0e*X`}* z`A+*%uIalD6^&Ds&gpxzTguIyq@6^^pdWqg{J1@*?eul4quCIV9x@xEx3!;=WAHnv zZvVE6>sG)f>R?GMq`dEYWC3fLn`Kl?s?v>x^vAa^6s+2un&i>%rg<{V~{=6Ei zLm9hJo-Oic5kC^VPrTQ^l<)-&w*1P>cjet+j%;V=4ZpJ}-m9WobvgL|P+i{hf2c0U z?R;I{F2CGP`z=m-i|X<`YruQ320Vf_U{b%=(_(%L7r0k{>CX}|VkgL2D0=L4s}pCn z`RilzVLP*}c~-Sk&v!VM4(8b z`FNZe=f50V1F^H?;xk%c^bFo9BF@rPs@`L(!9$!&;pJvQ8 z-;U%JtOry7&l|6LS^L(Q2*zAluXMWQd~J&_U@gaEO(z#Sx7}k6%VYgU){^{J3tgk+ zdn>OOfH{9~jD34$Bi~^eUE-`v)-&|1Oy2cUeA{RvKEhWE!FuI2m+t(U7VDK#uD{vn zfF4;puHOqfWG#9VbYx4=!EZ_j?Dc`TYe%(P zV=|8)Pu9ecH1s(H+Gj)=gCz4!%v3D4*}m_`|n$OFkOc@YtmjRiBRFTQ>5I8-DK$>~W1pm+#Sd zBgmhm`j+olg?bX(UE^njCrN#q{#T1jf68dwgFN=Qq9-nWj~*KR;YQ1gebXZJO&-0> z={$RtekXnMviqEtYah|?qqmM;<8%(@JBL;I%;YtXI4!GI>i5uFzqQ(FTg`U}-F#;0 z>OVVepW@vbo>}&1r{%AF(=(mVY+MOEdX0YXymiktPRqZMXD!cX^N#x|@)<~+ei{DA zH|ql)@C}sxs~v9??InC3W%b(d?yQ&8shZfV`r=)enI3seFu(W6*Nf%rS-$oiCK+!emPN*h&e$H4l5>#?d>(2S?QOK!7~zIK zU>hUco6GEHdAoe7`x$*Qzuy(>7!}YR>UZVW!F|(H(fqsux_*wsVXww~{!o3UpjWy7_XW-^RL# zud(&dIA8npPgX#8k#1gCOi#qm7(EsBzY6H8h@bylO#g1@=e5Q3yzBURLoxlkouA(- zre~M&vkO1vKKLo?@lo!bU+s;_t@iffyMKG~-9K>t>5G@^+Lgr8erWM>{iYDUyX2g) z$WQp)->9Fkb66jK!si(4o{RYjp9_37>2KmYpj_`M{7=s}b$Kr|bxGO&Q~GSCc~ACN zKF_-`Ty8kH7r+Vr1&JSx?Z5a>Iw;TO9ho!d<_-vakbTwfS3&*S zYWt|)vy}I2tbWg0{n&G?Iy_Z7)^~FaeoekXeTqw#HPnCHX=r;1-^!5UdA`)^{-%7! zr;hhGId$?(7@wx|{=0kTWWjH?N50eQ{tUD{6Wd4rjMe=`iM493b6;%gZhMJ+1#-{% z3tly6t^u>pAmdd9a3^y|@dpaNP2gb8HUVBYC=LIkG-REW_-9#fOSNY_*U5P78}goP z>XL6m>`?CqYcq{E?3-;|a_+ds8yYh1i-j)#NvYe_*>JAf*uFpVbbte{tuZ%nWMlii z*EP1^2hRqO0$*&bygIL@xlZ!Hrl(x$P15gT@qOytS4KGQR=yWmlV9uet!KYFznbr( zul7^Tt8rPacGLMs8z(rM+zQ6&xUHe{lyduD_&!|E8g5KZ|JT~eY`{q8*qE+>c=$ zTEDZ}>0BN7k|v-0u+w=a_$qurk38bIW0t8eY2!-Zy@By1wLZMcY5R8IOKKgx%4zw| zYV{?xRpp(b19%VH&aFE+sN2idR#u-D)?M`5!&V<;&q;sP)@SGk{xIm|+aOAJg3gU& z);R82l$(Nvtof>h&b_G1!_Z%iZ>t^u*PhS=os*ZXbUOFKw}sDZ=~>k4+dPBMYw6jm zoX)cXpO^csKR842cU{dleoE49K9GoR^MNSc(@OMH>1U#!4sht}^zB3)ih2D=#A~H{ zW#G4q=oY_SNVn7>q?^7tNs#ot&;X2Sj**1`I>)`9ao`1UWU z?--lrPoM`lqa=T|JYRhNv9^(&(J)^3NaFVlzqPZ$#;=-E;}gXY+qeI`i^#37@-Q+vIhPAitcBYJskKkoY+9|zV z!PrzZ*BNPbDC28T*-@GqKefGk;m4lE{7BlR@2EMG#P|2swquLy5{qp-?u9zRm_I+3N zos){|l5E?zz3-e}Oiz-x75AMAbZ>lK(AL}j$MNxbL2RA;%wm~~cpIM=)Y+IbT86j8%*|^{HIL_yPF|;e9w4^O%ET&om_aQlGxeT@Y)lG)%MlNxT4i;-a>) zeN`cy;apkHvhb)+SdXH3o>|4bit;jERpb+WE8BcznKqwST#sa%C;L;MZB;=XbS#3` zMPt%ui|I=8SNl~Ze&-74d(-{u%Hp~td9346seV;UzZ%$&e#IPwID_5SufAmU>#JYc zT&dT7_0?itCENX7)33f+T#sa%@3wyRy<)nO{H?fOy;Zi}KA|mb^P(Rc{X07^!p~81 zUIacl9`(5fRDljD(rv%!y$zyqwJL7gS^fX3xc+U4dEqlNnWaM$DZBkGo31+t6%f@q<(PU+pEtjIcD~$rz@blh@XRt>3P@jv#yx_-7cTm zVtU?n{H!mgf4B2;%L8FxwYP+`F(7yx6$fU zW=!5`om%Pnjhtbox|MxFE^x2$wI9dk=b314zzJ4|GUu>)uQqkb{-fElZY=R5yeoUC z(&pA27T=I;? zKEMyo7IjkYdBzX+Z^>DIk(}DOZNwDp{22c*@j3ewpEHhqgrxqgb7^}Ld!kojZ1hU} zhzm~Jx7_(hgHn$FEPgfOa3tPD+Dz+yVXW@+eg_YSlZG}#^`39_ew2DY8msrC!P>t1 zQC^@eDc@VmGtlI9aixsLysP^Wyl!x7n!5ZoF?r!xkNb2D^0L;>%DSwytmrxPD~w)| z5#nT&c99X{RTLH(A#O%tkrDPsDl9U>o<(m%6Xzh4Hj`|j1SN1hq6Y_8N0xoPi3}xyYatFjE}@22pt;JK^}UJCfCd-=$CxoHsHrK z@-32J|BvQhAb*SJxbE}i<2fFKmd9f89FGNUp8ltx%=)pkyOdeORqC=X?R4_(8^I0R zv&7!R=$Vd)KYo|e5}ee;kaEl{LPnL3e+RS@`J}10ic@yl5Q8{>7^L*6Y&nJQaFyt}iPIuUDU@pZwv{!;-xJGCxd>6xPF zOVv?~4|mJclx<@(C&C87M<@Whfp6>G{zep!BW{6IZ z^R1&XO!mfduR4h{K2`58FRhd6Cn58%(smnyKK!P~FqH`#!)Rk2!}xxbe8)!0kTFcg zxsv=qZW@%WR7Wu`MQITTH;NIDnYn@x(t0ysZhjW(|?}A^LyGGlaCC zqIdKvdJed#zmiAMd3S%Oy+ltvA#xkDgSS|{9^tn~V*2orK>w)ia5uc?U2nC#&lQ`% zd$_5~e>m1J`OV{A`{ioumsL|s+LdZ697Uewv&dl#be&A|xB=)|##nH}4zqDd>G#*PiVqWsuv_Et0wnY|U3FR_$b*LhB+^{j6>onvlRo5vkZ?A1=#J43fN1$7dB zV7qDl!Vl~>g@qrXy(M;4Xm1HWu(wLqzfS6(&-f2>e)@XhPjHsL)_L?5(f(5Tz4^SJ zwo&_s=V_;&F*US*Z2XVrtKs-BXM2k+Mqc^x@LFt8QZ)8!e*GN#%h@}0l#o`jZKX~{ zHd;9DV~2^25X}v`135PyAcKteW~a#6-aCxH^eg$!E&kUhiCtdnR}sS;#xA=SySzK} z?>Q<*jVo%R#G6?H3T zqsQu2H0J+9-*u{}-F9bx`bcqqipC&|JKE`X+68sdxyjkZbVcJ%j4pRuVTW(3_qm4i z0=DA_Y{xq6#Z2=WzIC+58^->zq3jr(@+`6~TNrzJPW%eqdazWnR^-o`$pF_(Y6VR7)=z5I4>w$sUL`t9k}2kTWzRH%H=?7N8$Zc+fS&XRU?Zfl5o(&(5D&O!hy6~qW;0y2{Za2rzhCQJ zom%UX`t4`DlJj$}BIOci<$%{VE2qmRPN?-*dd1yc{uNjC*hg0!SH7+`9))rh z*}KD-vrNOr75z&}(jnhM6q*$u(4CQUdjucPtK`0eUC=M1aju-+90_k2LnLOiNN-+V z+?OMHi1p>28nfTTI&3Mv7WK*G8uHafyVPr2OqQ`{%gSmaF-A{C zV^H#J8unFr1?C>e;e=}Dnx|pM0{?bVI@2n1?EStedLk>b+c?|F+;w)!Sx#C<+C&=i zsg%<|noK&GbT(-|sf~0KN%qodeHKj}>+DnQq>n~+LfkhD$G)ft_Z`FW?a&DKeZxtg z4B!2c;bcEdh`Zfze494H{oHV)W4JpECvqIV`#Zx8kKyu$8x+IcV>t2ohwuJ(fQ#0L zt_;4{tb23@%Xxe$Qi=Uia_$-XJU#Y#x+KwQUR859dt1BN%hl~}Vb9+7s^D9#RXJjc zrO)YH6n)Ua?`Q=2R-XN=vYsS;Qhn!KGo0TgegmDa{#ECzPQKG~eC)joj6naxi^BR}e{Ew8%MpI)c!M8=ePcUS{wuwdkFU<( z6f2)`S|m*blc7!E^x*pqlsfW$~B0k#MUiw1nkwRXiOrP^LKLqb)(uTwj>zH!( zbs1Uvl=Y=FMzw9kzG=Tle1COP2c?Ir_`$tdi=8-NW=0X`AGj)k9^kt7xi!W+hF>z zzoCF%E58z1)pf3D%pY{@*qq2_+-D%Ni4CK&k%dn?Bmcd%o1AyKF(!W-gEFK}Mg6tP z`s*rm$9Qzd{^*Ty*tGj$)9#B+EBELG?XPQ8)*Su59kM8Po#4}t%Q`muEvMek+57S}+rk<*6gSk3ne=YSPjlVaQ zk?XL%@nNP}Go)=BWZk-`?>er#c4}L?O802GZuitS|BPuX!sn&`ID3d5)pcEbkArhd zWj))o_Q9VeKB-9NS&P#4xsCBh%KqUO9Pd%&dNKEpa$ibLr;3~g_O!^B`u^}&#^ki2 zM^2lNQ`h8lpvkFQhb(8uw^83-%SiNvM|ZL>Olor)=UabB&@BDIeH|Tz?=-Z_eCpt! zd&DQLzT z<{!nDCjDbLZ^hv}9Ir-_Et!esfAZ7k}?`eqT(ww2$ZF z@4Vgc>_k12c<$ z=kT@rFUFqZ91rcAzqRM4*mLo8tFy z_uF%<6Un-H^xP9hU#mTLiajT5QtM*Rt+VIOx93i^=i+{Up)ZVc2+vA5&7NaT#D6}P z-}9E=$1J}O*>myrcFE7y+ta7ob04wiEKVS*hs6n`kGJPOYR}1f!}?gccGh=#isK~X zS0v8M4QwQIK4)(qz*({QL`1J)e`Q=Zp9=L`o7jXHz533KX@Aq_H{oAE-<8z!rR`8^>^;~ByBpHw#?$2 z^zluO%CGi3?6{HGaeH9L$#3X3kG{&pzv^tM<4SbH1Nk7hS^yR>gXZ@Hw#J(Af9d~ea}9oqGhg&fsXv8$=OhbL`W zi3N<^H^}<9)VXB-->A(tJ}`myn6Q820|zlz8n77pZ|mXNE!iIUhYhNimwe@5k9nCd zw&Rk{kvhLi<}dT^R|;bHH*gk^^1NjED>yUj#(LW2(ft~493yQo9~v%wzRcdt1nBpI59^{jE3I9{lSKLb;xr2Sj!*}76O6HaPe)~4)L05bDsYE~5GgiS%Cw&<_ zc(qAmSJM~MM+ybnj69d&Ur^sgN7w16ekUW(yQh99n7i_O;A>`%!2Bj0`+dsD?akaq zeK(AM#1{6a9+rvK1`u@^OVBUocf30kNSnAedu@6&ZDmF$ZC6*lDFjAZcIkRuPFY@ zVfE&tI9Ox@S#UZt^(iOoI&Fdc32(QH3?K_{BxGS^;Bylnr}#d7o~<8h`H8PaWR2fc z*2vr6V)x?Pl6-~!$MBEn8CUdCaKox{jz0rm(sb;&Y1npL$5-dFw4>vlyLh=g>z&)M zT%Il2FOq!>n??NXVVt&ZKtJ_W`h{MR1Kt&TxL@yosm%Mx zV87n~Y?=32Gw9d*v&y{h_Vaz_Cnf989*KUH|Nb)Xr~CQ-QDxr8huN?4$CrNJ=L|M! zM;|^0Hdn=B2Kc;WVc%bV@qLb)*YCD(H=gIFwncQ}! zkb9levtA_nYoPd#@x|S0<=DL2$Bt2bVe@WpJv#s8CY4#KtNQRu$iA%6scnNDB4Yry zwUa)EzPP@?y0!E%WMAfz(4ghhzm!kGjhtVVJ*RL=RhV;B*^)AzQN|rym zALY{zi^~6%m2ZCCsQl2cE9IBydnL=?Ok4L=fAT6Szr)H`-5jew>-gcE$t}@$OP0T? zALXn3B6lJG@3ZpFcOKQ>eCMjWO7#7b<^QH1<%e<~mj8g2uQo-j{X<(JSMCCmR- zKguVsBK|*O<*RKHE8o_YwEPmfr)2q;^`m_9Dk}d;E8oWNi2vdEE%H}Fca<#vtbUX) zYdNBKLjJ#G<;%E=Efkd>+Cr2sdO+4*#t+9fv3t#fd5HGm*DVjzU6Gw;x=ZazT{|YP ze(2GXb;D*V+qXC$F{+PyT(A~o_E%J&(Edv5qfj34d1+k++xt4M$M_-kx%e>9Y5lPu z)b3zCHr(SS`{nTmb@?;8mP;%jwkY!y)*CkvL!$S#_Uc_#I!;^Gx2#T)jc0W#>(|+i z?;?di%5l~*3)Q%s(m3%ZtTC!gYbS1Dc3;A~Ny zGx2`94%z6Be`+slTa)!jPD5GWR_MmB$2^F3kI`0=Ke2JwtHU>x!8bG<-_S68LqqWm z4Z$}g-)r1}9m%-Ho}g~;Rr1%hT8-m!e0~$3soLQWxEWc$WWFnNUC!pt)hT`@cyyEO z8tHFYuhS8k3zj0zopQG6=t{a?J?u$Jo{$$aA_>pCvEc3TEY#8w)mzDYC zH|i{3nYV))u8mX1kPP&;Sa<4kD@wgphfSL`bdfc8n$#C%) zpi>POj{*9S;o>nsA2VD$2I!N98x7AxTBaFpWDGacaPb(R^9>h|0lLU=HL-VF1Dx<& zdDdS)@Y@vwbXg!fPEFPc=8!ReP`J*Za={t{>ky19L0s5u=Dfi47uKEI8r1&Q@mOT8 zAaN7OhQ&8A9uRXHoKLT77TmM{gYl``mwdPu<)i+5@=@CzdgAYwqUAHYh!)9bXK2~T zcsH2wZV+`Dh%T;07Y{%er_sfNL(hB6w*nsku?my3LCgr_lJsA_S34Aa8`HUsH|-1W z#u85=&+QL<0RF|cHhBgg>~-p21ok(hbIB(d+XH{3+n;X)yawF^p}UrLAYn5U`v|cQ z^m`dHcGIQ;kLUZgA|FD7=mUR~>7c{1%o(9;Wlcuu0^afvu;?E2klGMp!@&pDS@OJ$ zcgT)2CF_WeMbF6?L5$77NsK1~H-E(9_-Yk7UATmrfX9NJrUjgypMmRlRNjG zs#B*WRGn((r5MhkSkcsh0QR<(0fTy7rJs zYv#KAv}Uf0Jfpm_&y>%yhj;f*wDU#qJJF``E`JT)v3Gq;!^L5s8zU{aP7b~jLY|v zzF>Tv%N$?lxCwK8wy&Eo*Jt~N33Gk6Crp^@v;B(+bA7h&n=sdBd&Y#hKHL8`VXn{i z6BFk8Y(F<)uFrNthyBj_Y>`{V-*3Nr?ZQ4=<@d+~y^!&y==zGC>($@EHloj7gE?T1 zb%f@xjBSAqtxn(l7{|b9AMjr>pL=lGdKp7ne;F{pYw!Dd82^jEX4j)SeYW(`^!aSs zb4~vA6)+b>+a~#=AGdRnT$?I3;u5@1d1>cUYtop{AYc5>Jp2l_;bSL{g15c(gt=|H*Mzxk`YIFVw&`IL=C7ow%oo&;zx=qi02f7QtFr*iD9OmrB zSiKy6?-}SPUQxxbM0=L@L4O_XW6dw&Yrgn7%r&*^@%C*y*SG&{t$v68bKUMFUpohm z_9*K-&{pJZ8TN&k`&k~vd@REV6Ni0z%~8BZ!TV9X`@~$9##_PXqu*PDIjA+5ixRu> z0h1^Ezcs(O6@E&+k~}fjA#J^Oj{6|ta~##}eH!hDw2=?r%L2c#eLdUEdg%JA*RJ{1 z$)`k4p*TAh;u&9DvtK_4n{ZqEYNoSs>k;?rCdi};ZHp65fAm#V(z6W6#p)Y+sa_Hf&U2e;C6l>s@ z*UK7xwe5wkM=XtB&jb8J$el9heT|H_jo*BasjnAMUl{ArHcNe(_Y~r@oN65Mo7%9y zy*FgTmi=)=dAPRW+KuaaTzOoFa2>(*0Is9BzJco*T)qwaOVjpUzvMv^=Gw5oHDRs| zd&GpfHth2z%(Y=(GGVR_`>F|ZZP;Tb%(Y?PG-0j{`?d*lZP<5Bm}|qH)?vT1HtdJm zh8?}|?1gPu<@zM}8mlp%DeHkaCO!$90a$FtFLth<>pa`^!`eU5w2jT6ox8EZKiPMN z_D?Jg!1PbVSGbA(^8$PB96y_DO6K|5m3&)&>PF5Pfe-p4^h?Aa`Qki(BxKKRKmQxh zG~*O?>|_^c!?}QuQCyb2im6q{~*uVUu*}u&C zdr|LSrj5n)cjFq!Zq134SdRwVj%U1oM|*{TW$82;ItuneY5Oj9rF311PjnDA9d)*R z5$NIW{oChcJ(t9lY42f!VAsVSNgoDz{^AOmZ+Z>Wp#NF}eL1=ZI`NCoKDBs>rpGh- zq7n9)Sg(qBb-j*X0~~qJvkGZZH~xOabLN8mUhDLD+b_rYrW_|BkCT5W{gjmBq?U*9 zdZpnN_L6&lgl{~rWqCR+e6(>5c(P+m(Q7NKCX>f6k;gCpQ16eY%zvr#h}J-cCr+Xb z%tfO6-n~Wq$BWzjvxOMXvPv7d#LzkcS|^NTeIYxKK#vf4Y+wX-P zLwPwi=Xh0Q2m5Bn#y$^_N5F$=$9J0akQ4h;@!u$W^joJ&-;H;L^eg9Hvlerfdd=v9 zeP(6xF9+Xx@kZFv7fwnaw>&b3vMgFF?@=&LdNhJQ1pIJqLlpX>*Pmj} z;K5`1{R+omme*f^SB&L^*UuVW&0L3H_hznR&5O4JSIdiXQ;$$DzytD>HL#*H==Yz{ zYtO6t8KJSL8HYNugzSR4cG`%H88L43`F3UeHN&@=OZWN4xJh)DbH+F%lw&~AV|nIT zI5O`ur(_-qXXyOw|->~b+xz=#?Pj^1G2KAx!5@XC?)quXH zDd{m*TaNb=Yk-TsU)Cqm2aqu^#=TOGpFmfB?&!+Dm~xo0ldmf;m~yzXsnnI$3SHrN z8T`pN)WHMy#mN4g2j8}qSy(&?Udf4_)cvttnI&az0lUNsWtnpc_;ou%a?n!kW;vSO?UKXOHppAzy>FRA;@g6JzzOfb-?Gi=W@AF0E-_-*&tYbdELNg0qWm zd90yn@pC)D6ZQ%G`%V?*J1&eypXa;hr#7jQQZ>=9c%7@c7Y=jhZMQXlQolodMN@R$ zU5(4nQC{2eC6VQ4sHSdA-^*O#@vqX(K_}k2y6u@OxR!hly3aWW%)!rnXN@xlujdv6 z+{OQwyl}qpt*htZ<1CcrQl9l{@ecxC$(zsXUEtO5xxA6Q)#JPf6cLf!4IplRx9;D~<3>RL*&n2_Jiylr((wJ};<@i^ zLp$)xbfZbLi~cm^!nT65n^s4$P6^+tUyc2XEHmEQV!tByieKR23@g<8MXi)SY2k`S zKaKZ-pZ@F}ZO89B{OQLw9&WqsBdf9Q3-?zm(40dV?nisS8+CUCebwzu8^yH1c`w|0 zhdwh3b@yw|jH2#|4uK!ElPLLN{Y1aC)Id5hXttr1;le=?*C%m_w`HbhWMpWh&D&T! z=epJzr4W9xgkRG!GT1k`D~OS}Z8Lp?y+ckQ@V8b8+cH0_wK9l#T{6?%(>d za|yz>RtdYfO4zn4VVC$}UAb~5>1A^zFJDM!OI~R@!vOS2)n(b;q+) zsY0$?WMCqfEv2*N6mwB(W3fT*LE3!0So9|1#dN|erHZAZmz(r@hj(>&@odtYC>Iwd z7clcOpBi?@3(5WQLdx5dDiqVXY+HT3*E+j#wxJthN|Yd^zG1H;nJmnY80hG7V=|f9 zhKAmBVWtW>#*OACOAAExZr2~&4r)vWoKTLCZ^j)mn&Vb*(;V4 z3A9;VC*&0W*}~(M4YWxrU}JKVmzvE(kD)yqlNW~T5-o}q)|;M1EGn^-DrDPi7L(8u55y*I)N*QidOHm%j4&T>(7WFTEM>8>f{pa;O4-K3R< zkHY7uE-M(x91uGIF46c=4zHAk%tfdwIwp`$oYy&;a zYAA(cq}9gOtwL`j{*IP%d1EKryaAZO-gr8*kje6P<#Nf11F7{5TF;Dqr4GXMZ1Jmg zCYLNjMOo&}sZwHdGPN(0&fZkqJiRX&PgI041bn1Q(q_9;lksw<1QVR__Qf-0O76j^ zQqPeX<~VpiW?())uvn=&%>DHvj90q}dl2D_$FT>h3#}NP%9PiUfNd(KOK9dW4wE_1 z9!V8V&Rw}e%7uqhg>-&8RfuOmM)hUEO*-i%4`kyrF!cp?5vbi$#c36ph$n7p@XMDi z&rG08LLV_%h(j+tR4$3w@(1yyLV60lkdG1YfJQ={Lf?tBURHF=rZ;hJl+Sw}CCVj3 z$^3kET#(E!Zz>Z%;Ke7=+&sfkh=9#EIUg?|2KmikZysveD`(TCqEp`pyAExn8P3id zKo||bD0;Imfo>J={q~inMQ`^Nr{myJnR_-hg}8LSkc#EX@cD^%F>bu0)i5rR&hidA z0s}QZlUMul8J$jW(pkwPKaF&SG+ZsUFPUJFdh7wLeZln;dx_pDrZr>Ca9eYs2to{tdO z(*VDP7NjgHjc#3N){o}Og+z+|zbCo1Y)tC^UVS|~Ay`FHws>?0hzC>9w$L9>C*0Bs z`{Sk^&J{|!MD=0X-RO8*Gz+KXLE{MvzcCLwt*|hkhXz#-0VJkViJOY$8TL0QIot{9 z=h^j4!CnsQ&I3AkO|Fmxzou!64W>bF@kXb`9Yv2jkt*#^rLtbDxO3Xvd(wZ+j!_Uzo z>C2*IQ!b0uc)TW_E{Q9NzWuk5o?jPkxvSI6r1qsU(%mjxC0n)cF|Yg%lU|b$YNLZu zQAaM8uAqgG(Qd2Mm+(CXV;l%VGmX}_pcawks{E3Wn}4Z|7G4Yj>WjPz#(YKt#40@Y z=W_W?w!*xoVkurI`C{1Q72yH+;Dz2yxmcpBnL+Kszl=lmt&dZMb_TRxUeTMkNDHb~ zb~5M|JIesn77Jb}r%K#Ym!?5=&^clWHqo7sC$X2-KHK&pbVn(gKvIF$h`%UV`Sift z0yIz2$u$%Voh`W!U6ogBs7?l+EqWdWlRfaT7)o z$<(a)mN_vW`RRBO&I^7cJssUc<72U|R_7T#;^?)bV?6^B>_4-kwBgdp0#2sjk*12i z+|eEDEYUe#=t({ti%3V!4C{xPwTDi)m`*}#(lhAaG2Vc6z4(&Lzwlre3J zVBtK(59M%FO9`bg(h=TFEK6A#FHU+Qa}&gODt%&ECkq(Gr?QCyFQdHs61kU+Pm{0J zDVg2}eJKe2dfUju%4SgXcpRdkdj#~p<-*P^+*-T(TRnRBE4a;%# zg*xpYg-)5tMl=3Lo8bsU#t6-HC-kI{(s-$)R3!Q-PR3FXnuQ?FArd->_cQP?bD;aN z=H@&`8A@ey9v}2vfHwtWk4dqfS&ZScQ}p~cCY4HPKRTI8AhnCW5&o%z>*q&`G!{rd zluu>Z#5l`a$Yl(d=!Z2OwE70j`NAxKZ`_^Yd74F#@m>SpFgG*9318Ryf{srwDxVXoJFSsRZ3x2N2{Ci z67dY?!a&MKP9pO49GcKG5Ixa(re;%^4kRkyh4|>Nr^0E}UQ2=?rcQ~E)+E|Cgl|js zcJ$#SR@{e1x_V;c!`&TYJ%o1+4Rv>3+XG**b7*Kxsj~JhRXUkTFU9qmAfq{;}ZsZ@^)iW0B?iuUp8XFpk zja@t3gRoJA_3Rz%85!*8kB#>2;;py8V;AumH`X_Rjwd!S)J>)}jo!YI0lWn3iS6kb z8SNVywBe&YBM1pXo$x-89ULF%>=`k1eHvpuqhlrv9ac<01NRMd?COz_aQ@Z8$!m8< zm(OEIw|>56q;ISzHqx`J51#i3qCuOzWDumwi2{!IOTFkax-e2E9qSkwi*EA89{_@3*wAn&$j38d1i-8p^zckSHjW$|T7zU1 z+;;S99daO@4nmFfj&uz4*mR&(8AkdH8yo4{wF^}y^s9tfypHZ}VV@cSRbeG`_4N0L z(wz#&rvqgg+7%n^7#Qxay?=VzV>nQ8Xg&9BG zGtxJNR$$BS!i?|k>F>BU*3k|JtiPuhro`x!t#2Kw^~K1=AnGtJi*VX1We%ko=;;_8AL;211gmNJ z;V4|Cj17;yBSQnatr$K#y2i#)-G2SCJciCd&!E^KRIHX+_qBr^1ASewk&eM#)_#o) z_4#GC&pmtl*l1~xB(8s`>nay!9{nAo7^3(0F^|6CK+eNMBM@S*vDF3xaL-^zXFm@oij}FlD24`E1-ZLnC6d zUHtwb+LG>WSe{Y0J=ru8-*s)5Zfq6wFe;I>MvgWOM=M(LVf=xPQTAP8n=Gykb9q9U zV>X;JwYYA$w!yH-G`c4LuA%Wkwl(019EZpIM|)z!eS3Q-sNR?Z$IyMD1K1-vpu;i1 zaq4RXJu0L;GJ>AX@?054o^8dUgB!ZWuNGa#h2kU~lx=jNZdza5ZK)}%4P(dkUf*mQ{#5+?m=U< z&IRy>ddI}yFb0i0^!L!1_xk+-+L@RvhII`MUkfPI{F@wmHCt2LUBwd-o{`IT+_m6{K_!m4G$R?$MP>FjE#2>!yM4{GHG?m z!{JOH4(Gh5&Z}B@1wNYoJX{Hzhexv2a7{SzyWxHY+-bU%VU>7W4NVu1VIe#*P!;q{ zSOp%qnTID~Aw21nD)3C$JUpk|K99t8%1vKN^q{w+%l0MIjcVbf@8hDB{f6JlFyg^r zpgZj8*B-m(w=#@)Fy|v;hGk@-@hZcJM;p=8H%Jo}8iP~|C%*Bj4YHb;Dz$yZhjgY2DEH-F4A+N-aRzNA)Udk z4D<0udU|_CAUcY};C7CWpfQvg;u^iG>Mrc@4J-Yl_TrHS<<(J|3qMd@Pyc znva9Tcn|F0=>W_=%*W*`NC%T3@Ou2&39M=3%vW2(by&h7^A`mOiIWgmTZ5%MLBx0# zv+TL4Z2A_+$O_a>j`)l1@MeZ@#q)(+B9%&VK1J5r`S_THGZTJzOX*K~#EUXbGL&te z$YGHrrWDN_rJi==%O10ek5h~-Sf;3_>8jvmbA_2W){}8Ev5Cv<@Nx@t(pUvkm@2b| zG1-D?KF$~h>q19TrE)=L5`BuL19`nd$iCjdf>kV91LIIY+O9X>==o%JF z$7#hP-i3;;Sp2bRyilLcVZB=_n<`Ani%Gm+DiGOS*T+Ob{<@9Fon?O$sYJYt7uHm% zQ{YM7oNt%+Z_dl6O8S`OcgXWy-260GNPr#TO$g079n zdnL18F32;UOkyD_=9CMxFo{$qgPcSus^G$$=BB(NR`_Avib1PFGnt-BmuP@Ph^9>Q zmQLDy=0!jbj_$z503%l{;|*&`mI5K6UHoX)3A5M4N=;f9Uxt-SE`5G0Bf@#}CoTz%ru?kvL{@&hqX+2RxhT~Xp6|T4 zvd(jKoG*zb-jz4wt-@h>Q-ER88?pN_vajF|^`|QW@-q zi)!L#u-^cBL@%QP0ragblJG9M1c!y|cGn}D9>2(5&ke7{)3iLyShjgseY**?=(%-e zaz&a`{qC_r_2WfX00()RcayRbiHy+rn6Pq|p($;<%{x_jFN7@N6Y7_$gL)0L_`{`K z&O=|!qWI;rc(#zX-0;>XdQ2G+Cf2W1n3>>;qe@)6uB&2YW@sHGGp(|wt%+&em4fgW zxIEvkjH|XJRE6@>l^I$`Y0F^oGF*3d~8M8=#2l}=vs7Y|l1H+x1j z-8Qo-(Ja&>U3tXoP&Zxi0xcRVH|os1_&}__KDjtv;y{93L|Ec54gIJAdL77fA-U+J zrxdPUCcHJwx6RWpEEZOg37y-#GJqMgML?s?D+k}pS{YOngc@ZTM)U z$JY}2l@~gCP_?P}b>+Q@Qws_fe)z%MoaWMF0@%(x(VJ-etdMb{=b8f#~wPTpG>8s*^ ziq##negUgDFtXOZg!I|Aj6NN`&S4&&sUsPBRG~$`z>@NP`vvgAWt*QL7VJ&?#7@DN z;E@>SH6UfaWq}QH*A`oa1CE571;?zHJn^s+X>)FJQi2_M!&yo1W1Vrf!KHzHYx6c$ zxia?0Yo*i-JS&WB=pI|QC8!H0)~>;_SblvuIOrqk8qK5Qb(9f^Nt3*nOc&$aA?YJo zI-{-+sXH_ur;B?==ObEP+qz0P`HqzoW@Ud?sJ`p8?w-?J--99i%>IL+d6xzm|~w zy;zE7*7sp96cnnYUXYzCxK(rVXWDF?AyZ%cW6oMvGq%j6IC~J*jczj{>>EOnF{;=E z`zwe?ZhkZ!L$bDt`WS4!b7k2$v>Hc|3T{1^J6zYP37D4Ly;| zr@?`{TD3tXrqQsx%PzYN=)^4oqdDzeurZmuz?03BSkGE2#U~I422m?|)Q>e}@M73v z;y{1`*a|b5L3`ZPQva#Mbk2KKsdQkpwXF?`n~(3$wry_Nys`Ky?}{rz_ioWXzg%DukS>ABS%|yO-MJ?qebrbVr4R8ZCN!W##v&|p`HJzgm+%4Bnw?EUrUl z9*1LA`g$am$&fQ!rcpcZ6T%DTiEl2)xiC5;%c~LQ@{V&9u#~Ty$70m-gze#w!sanQ zKA_L(DKCo&Qm9#FK5iWI3(rsZtrAlruyW{Po08Z#OXD_$u4xA5GL0GVTT(JfYUP5( zl!6S;9Bzl+;PGqdiY<)C+a@O35{b5CGT6rmp2m|{eXDC~2Ggtbi#d)-fOj+@ln8Bg z!9esyb?ho*KI6g*j$zu9%j6N#wgn|(N`kJ{WyUlcne`)`(TA-U|YR7 zZ3f3QC0X=L3((~g!S(=e5}UF0U>bWAEOqXi42%dWAc*3MPk3VxHRk})L1StVIv|EZ z^Op1uq&Vql@Vu@P4vox?>HJ!&;$xWA( zvm5kF50@dEHXPp|{Di|QxeAvxj2kd#>65n#9Fd31W1v^Mlc2=h^g+DlkFZt>cdVf0 zT%E4wi`{m0x)7S9pOrjA{d~sU^lrI;BQ&a{bpRAHYNI-)wmy=N@V3y z4Tm&zxZXqA6r`R?l`d3v#l~;5e{%ONN)6zTZsj!X)i_|?83ziyRPMKQQpn~r7Rh3V z_|{v~isadDkGv4{!kKC$_A8_42|$OLQv~kZ5R!;91G^`CKk+91*YD|c=E!XNQ>8<$1~w>rtvduG{y%Ba7L@-Z|nR)kBiBCu4U}$8p z^t%v!md&0N+STxMu7rcSyz9uCta`vua+9}U)>^V68 z+_R_9$K@T{s>d2Ix)_LX$C#e(6emTmL1Eu^fKCk;B;A#(}37gEg9S&`iYOeG? zHSNu?y>9XbFvg0@K{Z4O(#LTSSiWS_w|L+x%MI5U92QcOD8BHT+Rt}Y6Jo(q@hMDf zU@zK4Jc;8E6c&zUF^>Qi^>|1h6V;$nsIUU#(>%om@XREJOt@pTr0=;BOGtiGL&JkZ zW2584!wsruaHw;`r#f)}tG@8=)U00u9r$WI;tS_kaVXD@x5$ZEe-4Gi z$dObcg>C+r>=-bseK@~WK+ajNQeq@3o@s?X7JHaTWBg$rar{U%M2WFogaRak(fI@= zCcxuDtg7S?VX#nuswfEe>EIA8S%6TDl!^0kOL)6c4G-ZyPHIn8l++%dCtWhiAHocV z7F<=u9nSuldDaVRP>iZZmC9%NVV6)*iJ|(lQ;K*&&v*K$CEf6$PSPa&6FIR~lcza2 z3tu^L!9g#Ko8MZn6pgdoSgcgUT(LLSH4KGZ=$Xt7cPpTZgv*k{7fAk=P}y=gl|DxvLxVn*ti*j;jGVij~R}&**;AB-8yQ9Lr+9 z74KnE7|s>*Tl5q7Kdm3Xy?&rq_Rp1b*V@YP5EHZ0Tv&~93C$9Zsk8p2yZ%-WC2{5t zP%!ZuPoP%@x@>IUPyO=OwNr_pXy`;x$h&WWdHLPKaDTrRZ2dLH zT5q9du>1Ajv2prAjJT|Qg|iu?51p@TN#Xo0PSIF`I*ZVmY1heAohU3`Dq?|00najR zqUx{nm%QQCJ?AaQa>*Q`H6UwoEa0DkiQ~1HTIXwfF_<=5$Y4I0eNr9{E0Uv#_}c^s zr=8iO#^k6rO`|`zU$|qhDGx(@9mz3th(CJe)@M>0;eT#S^}pfa9RSVC2(2- zrzLP&0;eVLUnhZ+_>r2u<0}rzUOYf(8LlQwGM|C_9e;-J+~GdFUOqLVp1eRQd`3ha ze6>;>_#UiLYANoGxbXcl`PJfY>xLSIDD@2ftipW>E_^3UwO^#4qqx@r-hm5WYnD8L zn)mLlQ7@f5nS1)R!e5SjJqLI%;NRx=p+8jW!?>>gBK85``b~dajpVEuAXx&c=b*EFsSt~{<1u320M zan0d6gp0puD|p7`{@5Qx#G-5aPrJ30Wbp?j za1ndMXx)+(2&{bo&$S&_@bBBv!_|J^b|JcG8K~7xGUS8%5V9z`IQmh>L>B)kh%DiA z-87!=h;Cv2^*rGvdhtg5RrNnbvgoCEGo=15{=JOPb@hM4@a=qFR(~~Fxt!09^*7>g zw2jZJ>h}`ob$ni1e=Gh*ckp=~J5v>XJ)gb$e<4mgpEuOMm(Lx1ZmRFX-)JYFH`RZD z&)r+WT5ElRrSIL2zuW5b#NSOmx7Xjt=RQ8~sK16dSH20)?e$y8+rTKEyX!wsoWVGr zd+P^?Gjs+1?y6r!oT~@%yu1E7hF|-~!0E4l74fgT79nHx|AWuhC-J*r_1IL^#xq7P)q)nSkIEyISg68i&*CoYx$2EdcK7I z0YdAV?`G&l$gQr0kBg&GJU0?|Egn|*e-MN3J*zWUQZMVzuVIqKQ6^dW9)_%!kmW1! z+^~Vc%a`$StK?b)7Y&!mP)m1o+2-#cU~%;O_}lnp{P_tk zDW0mm0m+tK`VvLeia*Of^G}Fdelb&hmT1eL#N!#8MQRZsoYBX}+9oFW{eHwPxsa`N z41bo-G4p6N+RR&Btw43reaIo&Slb6;%eDb6k4uVuQZ2aw&nst{&4~!ZSH2#|%WG=* zyy}%86Zv7}ay(o66S;GB*@ht&zez9>RlmTKF<8pT`P%1G_+%wjL!e(GC-{vRUc{WjAu^wzTu8v%Aw#HnsNb)-KH3(j5kQeo>)X1w^ zB0J9(mKPD9MQUIB!A_7_y-3y8fis}ippd63I0{&`;1I|npZ?MieHLM{$pI2!4olwg z<_M(w{?4RliHk#%@p;1yv;LmlGf%4>w7gD z-)pmelcyt)s#t19dhF-MAyLiZmYFDoZpJrxGi98k_Zw3u-Obr_uDG>1-~h|g%d^c> z+4AP%fg=6E&E;aj=CK*-T>Sr*(Pkb$`2Qt4RZ&x{HY-*WwV4&DbVY7$Nw9v4rDQTS z*)mP{SXjj)x}9RFP)?L$y?y;X2!JsNo{%D)L*OD{9Vo`I1Tll}CFx`UvL+4(@Bvff zVWUAVUy9+piIm3Ui5)r$uZpL!ts1~$d|5YJ%r;}L16wh1yd%Oeg=4v$CbwukHSF?g ze^?tiYuCW;tNQx;`fKW-ub)R;jk=mj`)f3Kvz|=RN+a~QHe;Uz7GY|MAj7TAqETSL zEmzj=zq0m~Z?1c$|El4-k0UBux1)B=o8Qv+)6cwVSpL>T!8jT$ z3cxW?ov+U9dtB+3am$6#2*?jC5=dujxcJzY$?W z^9O_41U%we_u^EzJa&JgJQ+)6lM1SbB{jU^7b9r0Ks%N%ArTJ~ElMD>m-Ub_ zP}rBonqd`#t-J~QfF+*GDTQ_{#$Dv3i6sr#NKz!{^IEfQ2MMf)FJh%}3{4cv^gzpL zg>24fgSsqiTI3UL?G~J5p<-M=jDTePK!)d;C^SocP@PR!#S-NL8fd0G12$uc%q=k< zb|AEI(4&@yE~b>p2ulh=)1We35{>PHIPpVa9r6@5h{muNfX7Z^dqGS@1;%mWD&{b; zpuC`V4UT(VTej#Cy4O7AH4ovuhM}$cJ}K551#H#@$A`1CIehjBUvX{*eRHa8^W<<} z7ozszbJF@?kk?PAVbHQhNc("ij(=Yq94esv$MULdeg_3P?_6j=MLlo(FFjNy0| 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 diff --git a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c index 62189ca14..e2f44656e 100644 --- a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c @@ -38,6 +38,7 @@ uint32_t clkFrequency[NUM_CLOCKS] = {0, 0, 0, 0, 0}; int highvoltage = 0; int dacValues[NDAC] = {0}; int detPos[2] = {0, 0}; +uint32_t countermask = 0; // will be removed later when in firmware converted to mask int isInitCheckDone() { return initCheckDone; @@ -364,8 +365,7 @@ void setupDetector() { // dynamic range setDynamicRange(DEFAULT_DYNAMIC_RANGE); // enable all counters - bus_w(CONFIG_REG, bus_r(CONFIG_REG) & ~CONFIG_COUNTER_ENA_MSK); - bus_w(CONFIG_REG, bus_r(CONFIG_REG) | CONFIG_COUNTER_ENA_ALL_VAL); + setCounterMask(MAX_COUNTER_MSK); // Initialization of acquistion parameters @@ -529,6 +529,66 @@ int64_t getPeriod() { return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * FIXED_PLL_FREQUENCY); } +void setCounterMask(uint32_t arg) { + if (arg == 0 || arg > MAX_COUNTER_MSK) { + return; + } + countermask = arg; + // convert mask into number of counters (until firmware converts to mask) + int ncounters = __builtin_popcount(countermask); + FILE_LOG(logINFO, ("Setting number of counters to %d\n", ncounters)); + uint32_t val = 0; + switch (ncounters) { + case 1: + val = CONFIG_COUNTER_ENA_1_VAL; + break; + case 2: + val = CONFIG_COUNTER_ENA_2_VAL; + break; + default: + val = CONFIG_COUNTER_ENA_ALL_VAL; + break; + } + uint32_t addr = CONFIG_REG; + bus_w(addr, bus_r(addr) &~ CONFIG_COUNTER_ENA_MSK); + bus_w(addr, bus_r(addr) | val); + FILE_LOG(logDEBUG, ("Config Reg: 0x%x\n", bus_r(addr))); +} + +uint32_t getCounterMask() { + uint32_t addr = CONFIG_REG; + uint32_t regval = (bus_r(addr) & CONFIG_COUNTER_ENA_MSK); + int ncounters = 0; + switch (regval) { + case CONFIG_COUNTER_ENA_1_VAL: + ncounters = 1; + break; + case CONFIG_COUNTER_ENA_2_VAL: + ncounters = 2; + break; + default: + ncounters = 3; + break; + } + // confirm ncounters work with mask saved in server (until firmware converts to mask) + int nc = __builtin_popcount(countermask); + // if not equal, make a mask of what is in register (will change once firmware changes) + if (nc != ncounters) { + switch (ncounters) { + case 1: + countermask = 0x1; + break; + case 2: + countermask = 0x3; + break; + default: + countermask = 0x7; + break; + } + } + return countermask; +} + int setDelayAfterTrigger(int64_t val) { if (val < 0) { FILE_LOG(logERROR, ("Invalid delay after trigger: %lld ns\n", (long long int)val)); @@ -992,6 +1052,33 @@ void setPatternLoop(int level, int *startAddr, int *stopAddr, int *nLoop) { } } +int checkDetectorType() { + FILE_LOG(logINFO, ("Checking type of module\n")); + FILE* fd = fopen(TYPE_FILE_NAME, "r"); + if (fd == NULL) { + FILE_LOG(logERROR, ("Could not open file %s to get type of the module attached\n", TYPE_FILE_NAME)); + return -1; + } + char buffer[MAX_STR_LENGTH]; + memset(buffer, 0, sizeof(buffer)); + fread (buffer, MAX_STR_LENGTH, sizeof(char), fd); + if (strlen(buffer) == 0) { + FILE_LOG(logERROR, ("Could not read file %s to get type of the module attached\n", TYPE_FILE_NAME)); + return -1; + } + int type = atoi(buffer); + if (type > TYPE_TOLERANCE) { + FILE_LOG(logERROR, ("No Module attached! Expected %d for Mythen, got %d\n", TYPE_MYTHEN3_MODULE_VAL, type)); + return -2; + } + + if (abs(type - TYPE_MYTHEN3_MODULE_VAL) > TYPE_TOLERANCE) { + FILE_LOG(logERROR, ("Wrong Module attached! Expected %d for Mythen, got %d\n", TYPE_MYTHEN3_MODULE_VAL, type)); + return FAIL; + } + return OK; +} + int powerChip (int on){ if(on != -1){ if(on){ diff --git a/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h index 9eb0f64c8..4ec09e64f 100644 --- a/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h @@ -7,14 +7,21 @@ #define CTRL_SRVR_INIT_TIME_US (300 * 1000) /* Hardware Definitions */ -#define NCHAN (128 * 3) +#define NCOUNTERS (3) +#define MAX_COUNTER_MSK (0x7) +#define NCHAN (128 * NCOUNTERS) #define NCHIP (10) #define NDAC (16) #define HV_SOFT_MAX_VOLTAGE (200) #define HV_HARD_MAX_VOLTAGE (530) #define HV_DRIVER_FILE_NAME ("/etc/devlinks/hvdac") -#define DAC_DRIVER_FILE_NAME ("/etc/devlinks/dac") +#define DAC_DRIVER_FILE_NAME ("/etc/devlinks/dac") +#define TYPE_FILE_NAME ("/etc/devlinks/type") #define DAC_MAX_MV (2048) +#define TYPE_MYTHEN3_MODULE_VAL (93) +#define TYPE_TOLERANCE (10) +#define TYPE_NO_MODULE_STARTING_VAL (800) + /** Default Parameters */ #define DEFAULT_DYNAMIC_RANGE (24) diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index 331d91373..1932dbe03 100755 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -198,6 +198,10 @@ int getNumAnalogSamples(); int setNumDigitalSamples(int val); int getNumDigitalSamples(); #endif +#ifdef MYTHEN3D +void setCounterMask(uint32_t arg); +uint32_t getCounterMask(); +#endif #if defined(JUNGFRAUD) || defined(GOTTHARDD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) || defined(MYTHEN3D) int setDelayAfterTrigger(int64_t val); @@ -221,6 +225,7 @@ int64_t getMeasurementTime(); #endif + // parameters - module, settings #if (!defined(CHIPTESTBOARDD)) && (!defined(MOENCHD)) && (!defined(MYTHEN3D)) && (!defined(GOTTHARD2D)) int setModule(sls_detector_module myMod, char* mess); @@ -424,6 +429,7 @@ uint64_t writePatternWord(int addr, uint64_t word); int setPatternWaitAddress(int level, int addr); uint64_t setPatternWaitTime(int level, uint64_t t); void setPatternLoop(int level, int *startAddr, int *stopAddr, int *nLoop); +int checkDetectorType(); int powerChip (int on); int setPhase(enum CLKINDEX ind, int val, int degrees); int getPhase(enum CLKINDEX ind, int degrees); diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index bd2e1bee0..0b21ceabf 100755 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -203,4 +203,6 @@ int set_veto_refernce(int); int get_burst_mode(int); int set_burst_mode(int); int set_adc_enable_mask_10g(int); -int get_adc_enable_mask_10g(int); \ No newline at end of file +int get_adc_enable_mask_10g(int); +int set_counter_mask(int); +int get_counter_mask(int); \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 9c15707da..d494ffbb9 100755 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -305,6 +305,8 @@ const char* getFunctionName(enum detFuncs func) { case F_SET_BURST_MODE: return "F_SET_BURST_MODE"; case F_SET_ADC_ENABLE_MASK_10G: return "F_SET_ADC_ENABLE_MASK_10G"; case F_GET_ADC_ENABLE_MASK_10G: return "F_GET_ADC_ENABLE_MASK_10G"; + case F_SET_COUNTER_MASK: return "F_SET_COUNTER_MASK"; + case F_GET_COUNTER_MASK: return "F_GET_COUNTER_MASK"; default: return "Unknown Function"; } @@ -487,6 +489,8 @@ void function_table() { flist[F_SET_BURST_MODE] = &set_burst_mode; flist[F_SET_ADC_ENABLE_MASK_10G] = &set_adc_enable_mask_10g; flist[F_GET_ADC_ENABLE_MASK_10G] = &get_adc_enable_mask_10g; + flist[F_SET_COUNTER_MASK] = &set_counter_mask; + flist[F_GET_COUNTER_MASK] = &get_counter_mask; // check if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { @@ -3837,8 +3841,29 @@ int power_chip(int file_des) { #else // set & get if ((arg == -1) || (Server_VerifyLock() == OK)) { - retval = powerChip(arg); - FILE_LOG(logDEBUG1, ("Power chip: %d\n", retval)); +#ifdef MYTHEN3D + // check only when powering on + if (arg != -1 && arg != 0) { + int type_ret = checkDetectorType(); + if (type_ret == -1) { + ret = FAIL; + sprintf(mess, "Could not power on chip. Could not open file to get type of module attached.\n"); + FILE_LOG(logERROR,(mess)); + } else if (type_ret == -2) { + ret = FAIL; + sprintf(mess, "Could not power on chip. No module attached!\n"); + FILE_LOG(logERROR,(mess)); + } else if (type_ret == FAIL) { + ret = FAIL; + sprintf(mess, "Could not power on chip. Wrong module attached!\n"); + FILE_LOG(logERROR,(mess)); + } + } +#endif + if (ret == OK) { + retval = powerChip(arg); + FILE_LOG(logDEBUG1, ("Power chip: %d\n", retval)); + } validate(arg, retval, "power on/off chip", DEC); #ifdef JUNGFRAUD // narrow down error when powering on @@ -5715,7 +5740,7 @@ int get_clock_frequency(int file_des) { #endif default: #if defined(GOTTHARD2D) || defined(MYTHEN3D) - if (c < NUM_CLOCKS) { + if (arg < NUM_CLOCKS) { c = (enum CLKINDEX)arg; break; } @@ -6499,4 +6524,60 @@ int get_burst_mode(int file_des) { FILE_LOG(logDEBUG1, ("Get burst mode:%d\n", retval)); #endif return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); +} + + +int set_counter_mask(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + uint32_t arg = 0; + + if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0) + return printSocketReadError(); + + FILE_LOG(logINFO, ("Setting Counter mask:0x%x\n", arg)); + +#ifndef MYTHEN3D + functionNotImplemented(); +#else + // only set + if (Server_VerifyLock() == OK) { + if (arg == 0) { + ret = FAIL; + sprintf(mess, "Could not set counter mask. Cannot set it to 0.\n"); + FILE_LOG(logERROR, (mess)); + } else if (arg > MAX_COUNTER_MSK) { + ret = FAIL; + sprintf(mess, "Could not set counter mask. Invalid counter bit enabled. Max number of counters: %d\n", NCOUNTERS); + FILE_LOG(logERROR, (mess)); + } else { + setCounterMask(arg); + uint32_t retval = getCounterMask(); + FILE_LOG(logDEBUG, ("counter mask retval: 0x%x\n", retval)); + if (retval != arg) { + ret = FAIL; + sprintf(mess, "Could not set counter mask. Set 0x%x mask, got 0x%x mask\n", arg, retval); + FILE_LOG(logERROR, (mess)); + } + } + } +#endif + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); +} + + +int get_counter_mask(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + uint32_t retval = -1; + FILE_LOG(logDEBUG1, ("Getting counter mask\n")); + +#ifndef MYTHEN3D + functionNotImplemented(); +#else + // get only + retval = getCounterMask(); + FILE_LOG(logDEBUG, ("counter mask retval: 0x%x\n", retval)); +#endif + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } \ No newline at end of file diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 7ff422517..da6863319 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -910,7 +910,18 @@ class Detector { void setBurstMode(bool enable, Positions pos = {}); /** [Gotthard2] */ - Result getBurstMode(Positions pos = {}); + Result getBurstMode(Positions pos = {}); + + /************************************************** + * * + * Mythen3 Specific * + * * + * ************************************************/ + /** [Mythen3] */ + Result getCounterMask(Positions pos = {}) const; + + /** [Mythen3] countermask bit set for each counter enabled */ + void setCounterMask(uint32_t countermask, Positions pos = {}); /************************************************** * * diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 6c49eecd1..452b66609 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -26,8 +26,8 @@ std::ostream &operator<<(std::ostream &os, } void CmdProxy::Call(const std::string &command, - const std::vector &arguments, - int detector_id, int action, std::ostream &os) { + const std::vector &arguments, int detector_id, + int action, std::ostream &os) { cmd = command; args = arguments; det_id = detector_id; @@ -38,7 +38,8 @@ void CmdProxy::Call(const std::string &command, if (it != functions.end()) { os << ((*this).*(it->second))(action); } else { - throw sls::RuntimeError(cmd + " Unknown command, use list to list all commands"); + throw sls::RuntimeError( + cmd + " Unknown command, use list to list all commands"); } } @@ -55,7 +56,6 @@ bool CmdProxy::ReplaceIfDepreciated(std::string &command) { return false; } - std::vector CmdProxy::GetProxyCommands() { std::vector commands; for (const auto &it : functions) @@ -703,8 +703,8 @@ std::vector CmdProxy::DacCommands() { case defs::MYTHEN3: return std::vector{ "vcassh", "vth2", "vshaper", "vshaperneg", "vipre_out", "vth3", - "vth1", "vicin", "vcas", "vpreamp", "vph", "vipre", - "viinsh", "vpl", "vtrim", "vdcsh"}; + "vth1", "vicin", "vcas", "vpreamp", "vpl", "vipre", + "viinsh", "vph", "vtrim", "vdcsh"}; break; case defs::CHIPTESTBOARD: return std::vector{ @@ -1151,69 +1151,125 @@ std::string CmdProxy::ClearROI(int action) { return os.str(); } - /* Gotthard2 Specific */ std::string CmdProxy::InjectChannel(int action) { - std::ostringstream os; + std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { - os << "[offset] [increment]\n\t[Gotthard2] Inject channels with current source for calibration. Offset is starting channel that is injected, increment determines succeeding channels to be injected." << '\n'; + os << "[offset] [increment]\n\t[Gotthard2] Inject channels with " + "current source for calibration. Offset is starting channel that " + "is injected, increment determines succeeding channels to be " + "injected." + << '\n'; } else if (action == defs::GET_ACTION) { - if (!args.empty()) { - WrongNumberOfParameters(0); - } - auto t = det->getInjectChannel({det_id}); - os << OutString(t) << '\n'; - } else if (action == defs::PUT_ACTION) { + if (!args.empty()) { + WrongNumberOfParameters(0); + } + auto t = det->getInjectChannel({det_id}); + os << OutString(t) << '\n'; + } else if (action == defs::PUT_ACTION) { if (args.size() != 2) { - WrongNumberOfParameters(2); - } - det->setInjectChannel(std::stoi(args[0]), std::stoi(args[1]), {det_id}); + WrongNumberOfParameters(2); + } + det->setInjectChannel(std::stoi(args[0]), std::stoi(args[1]), {det_id}); os << sls::ToString(args) << '\n'; - } else { + } else { throw sls::RuntimeError("Unknown action"); } return os.str(); } std::string CmdProxy::VetoPhoton(int action) { - std::ostringstream os; + std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { - os << "[n_chip] [#photons] [energy in keV] [reference file]\n\t[Gotthard2] Set veto reference for 128 channels for chip n_chip according to referenc file and #photons and energy in keV." << '\n'; + os << "[n_chip] [#photons] [energy in keV] [reference " + "file]\n\t[Gotthard2] Set veto reference for 128 channels for " + "chip n_chip according to referenc file and #photons and energy " + "in keV." + << '\n'; } else if (action == defs::GET_ACTION) { - if (args.size() != 1) { - WrongNumberOfParameters(1); - } - auto t = det->getVetoPhoton(std::stoi(args[0]), {det_id}); - os << args[0] << ' ' << OutStringHex(t) << '\n'; - } else if (action == defs::PUT_ACTION) { + if (args.size() != 1) { + WrongNumberOfParameters(1); + } + auto t = det->getVetoPhoton(std::stoi(args[0]), {det_id}); + os << args[0] << ' ' << OutStringHex(t) << '\n'; + } else if (action == defs::PUT_ACTION) { if (args.size() != 4) { - WrongNumberOfParameters(4); - } - det->setVetoPhoton(std::stoi(args[0]), std::stoi(args[1]), std::stoi(args[2]), args[3], {det_id}); + WrongNumberOfParameters(4); + } + det->setVetoPhoton(std::stoi(args[0]), std::stoi(args[1]), + std::stoi(args[2]), args[3], {det_id}); os << sls::ToString(args) << '\n'; - } else { + } else { throw sls::RuntimeError("Unknown action"); } return os.str(); } std::string CmdProxy::VetoReference(int action) { - std::ostringstream os; + std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { - os << "[gain index] [12 bit value in hex] \n\t[Gotthard2] Set veto reference for all 128 channels for all chips." << '\n'; + os << "[gain index] [12 bit value in hex] \n\t[Gotthard2] Set veto " + "reference for all 128 channels for all chips." + << '\n'; } else if (action == defs::GET_ACTION) { throw sls::RuntimeError("cannot get vetoref. Did you mean vetophoton?"); - } else if (action == defs::PUT_ACTION) { + } else if (action == defs::PUT_ACTION) { if (args.size() != 2) { - WrongNumberOfParameters(2); - } - det->setVetoReference(std::stoi(args[0]), stoiHex(args[1]), {det_id}); + WrongNumberOfParameters(2); + } + det->setVetoReference(std::stoi(args[0]), stoiHex(args[1]), {det_id}); os << sls::ToString(args) << '\n'; - } else { + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + +/* Mythen3 Specific */ + +std::string CmdProxy::Counters(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[i0] [i1] [i2]... \n\t[Mythen3] List of counters enabled. Each " + "element in list can be 0 - 2 and must be non repetitive." + << '\n'; + } else if (action == defs::GET_ACTION) { + if (!args.empty()) { + WrongNumberOfParameters(0); + } + auto mask = det->getCounterMask({det_id}).squash(-1); + // scan counter enable mask to get vector + std::vector result; + for (size_t i = 0; i < 32; ++i) { + if (mask & (1 << i)) { + result.push_back((int)i); + } + } + os << sls::ToString(result) << '\n'; + } else if (action == defs::PUT_ACTION) { + if (args.empty()) { + WrongNumberOfParameters(1); + } + // convert vector to counter enable mask + uint32_t mask = 0; + for (size_t i = 0; i < args.size(); ++i) { + int val = std::stoi(args[i]); + // already enabled earlier + if (mask & (1 << val)) { + std::ostringstream oss; + oss << "Duplicate counter values (" << val << ") in arguments"; + throw sls::RuntimeError(oss.str()); + } + mask |= (1 << val); + } + det->setCounterMask(mask, {det_id}); + os << sls::ToString(args) << '\n'; + } else { throw sls::RuntimeError("Unknown action"); } return os.str(); @@ -1335,7 +1391,8 @@ std::string CmdProxy::ReceiverDbitList(int action) { if (action == defs::HELP_ACTION) { os << "[all] or [i0] [i1] [i2]... \n\t[Ctb] List of digital signal " "bits read out. If all is used instead of a list, all digital " - "bits (64) enabled. Each element in list can be 0 - 63 and non " + "bits (64) enabled. Each element in list can be 0 - 63 and must " + "be non " "repetitive." << '\n'; } else if (action == defs::GET_ACTION) { diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index bc1c51496..4e4a3e0f7 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -529,6 +529,7 @@ class CmdProxy { {"digitest", "imagetest"}, /* Gotthard2 Specific */ + /* Mythen3 Specific */ /* CTB Specific */ {"flags", "romode"}, {"i_a", "im_a"}, @@ -785,6 +786,9 @@ class CmdProxy { {"vetoref", &CmdProxy::VetoReference}, {"burstmode", &CmdProxy::burstmode}, + /* Mythen3 Specific */ + {"counters", &CmdProxy::Counters}, + /* CTB Specific */ {"samples", &CmdProxy::Samples}, {"asamples", &CmdProxy::asamples}, @@ -938,7 +942,9 @@ class CmdProxy { /* Gotthard2 Specific */ std::string InjectChannel(int action); std::string VetoPhoton(int action); - std::string VetoReference(int action); + std::string VetoReference(int action); + /* Mythen3 Specific */ + std::string Counters(int action); /* CTB Specific */ std::string Samples(int action); std::string Dbitphase(int action); @@ -1526,6 +1532,8 @@ class CmdProxy { INTEGER_COMMAND(burstmode, getBurstMode, setBurstMode, std::stoi, "[0, 1]\n\t[Gotthard2] 1 sets to burst mode. 0 sets to continuous mode. Default is burst mode."); + /* Mythen3 Specific */ + /* CTB Specific */ INTEGER_COMMAND(asamples, getNumberOfAnalogSamples, setNumberOfAnalogSamples, std::stoi, diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 8d8525afe..ef292712c 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1188,6 +1188,16 @@ Result Detector::getBurstMode(Positions pos) { return pimpl->Parallel(&slsDetector::getBurstMode, pos); } +// Mythen3 Specific + +Result Detector::getCounterMask(Positions pos) const { + return pimpl->Parallel(&slsDetector::getCounterMask, pos); +} + +void Detector::setCounterMask(uint32_t countermask, Positions pos) { + pimpl->Parallel(&slsDetector::setCounterMask, pos, countermask); +} + // CTB Specific Result Detector::getNumberOfAnalogSamples(Positions pos) const { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index e50065973..fcaacdfbf 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1720,36 +1720,6 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { shm()->useReceiverFlag = true; checkReceiverVersionCompatibility(); - FILE_LOG(logDEBUG) - << "detector type:" - << (ToString(shm()->myDetectorType)) - << "\ndetector id:" << detId - << "\ndetector hostname:" << shm()->hostname - << "\nfile path:" << shm()->rxFilePath - << "\nfile name:" << shm()->rxFileName - << "\nfile index:" << shm()->rxFileIndex - << "\nfile format:" << shm()->rxFileFormat - << "\nr_framesperfile:" << shm()->rxFramesPerFile - << "\nr_discardpolicy:" << shm()->rxFrameDiscardMode - << "\nr_padding:" << shm()->rxFramePadding - << "\nwrite enable:" << shm()->rxFileWrite - << "\nmaster write enable:" << shm()->rxMasterFileWrite - << "\noverwrite enable:" << shm()->rxFileOverWrite - << "\ndynamic range:" << shm()->dynamicRange - << "\nflippeddatax:" << (shm()->flippedDataX) - << "\nactivated: " << shm()->activated - << "\nreceiver deactivated padding: " << shm()->rxPadDeactivatedModules - << "\nsilent Mode:" << shm()->rxSilentMode - << "\n10GbE:" << shm()->tenGigaEnable - << "\nGap pixels: " << shm()->gappixels - << "\nr_readfreq:" << shm()->rxReadFreq - << "\nrx streaming port:" << shm()->rxZmqport - << "\nrx streaming source ip:" << shm()->rxZmqip - << "\nrx additional json header:" << shm()->rxAdditionalJsonHeader - << "\nrx_datastream:" << enableDataStreamingFromReceiver(-1) - << "\nrx_dbitlistsize:" << shm()->rxDbitList.size() - << "\nrx_DbitOffset:" << shm()->rxDbitOffset << std::endl; - if (setDetectorType(shm()->myDetectorType) != GENERIC) { sendMultiDetectorSize(); setDetectorId(); @@ -1821,6 +1791,10 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { sendROItoReceiver(); break; + case MYTHEN3: + sendNumberofCounterstoReceiver(getCounterMask()); + break; + default: break; } @@ -3531,6 +3505,9 @@ std::vector slsDetector::getNumMissingPackets() const { throw RuntimeError("Receiver " + std::to_string(detId) + " returned error: " + std::string(mess)); } else { + if (ret == FORCE_UPDATE) { + updateCachedReceiverVariables(); + } int nports = -1; client.Receive(&nports, sizeof(nports)); uint64_t mp[nports]; @@ -3888,6 +3865,27 @@ void slsDetector::setPipeline(int clkIndex, int value) { sendToDetector(F_SET_PIPELINE, args, nullptr); } +void slsDetector::setCounterMask(uint32_t countermask) { + FILE_LOG(logDEBUG1) << "Setting Counter mask to " << countermask; + sendToDetector(F_SET_COUNTER_MASK, countermask, nullptr); + sendNumberofCounterstoReceiver(countermask); +} + +void slsDetector::sendNumberofCounterstoReceiver(uint32_t countermask) { + if (shm()->useReceiverFlag) { + int ncounters = __builtin_popcount(countermask); + FILE_LOG(logDEBUG1) << "Sending Reciver #counters: " << ncounters; + sendToReceiver(F_RECEIVER_SET_NUM_COUNTERS, ncounters, nullptr); + } +} + +uint32_t slsDetector::getCounterMask() { + uint32_t retval = 0; + sendToDetector(F_GET_COUNTER_MASK, nullptr, retval); + FILE_LOG(logDEBUG1) << "Received counter mask: " << retval; + return retval; +} + sls_detector_module slsDetector::interpolateTrim(sls_detector_module *a, sls_detector_module *b, diff --git a/slsDetectorSoftware/src/slsDetector.h b/slsDetectorSoftware/src/slsDetector.h index 82a55f1dd..5edcdae2e 100755 --- a/slsDetectorSoftware/src/slsDetector.h +++ b/slsDetectorSoftware/src/slsDetector.h @@ -1862,6 +1862,15 @@ class slsDetector : public virtual slsDetectorDefs { /** [Ctb][Moench] */ void setPipeline(int clkIndex, int value); + + /** [Mythen3] */ + void setCounterMask(uint32_t countermask); + + /** [Mythen3] */ + void sendNumberofCounterstoReceiver(uint32_t countermask); + + /** [Mythen3] */ + uint32_t getCounterMask(); private: /** diff --git a/slsDetectorSoftware/tests/CMakeLists.txt b/slsDetectorSoftware/tests/CMakeLists.txt index 3a5c0b501..82ae54b8d 100755 --- a/slsDetectorSoftware/tests/CMakeLists.txt +++ b/slsDetectorSoftware/tests/CMakeLists.txt @@ -5,6 +5,8 @@ target_sources(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-rx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-eiger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-jungfrau.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-mythen3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-global.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Result.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp ) diff --git a/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp b/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp index 63789d09d..e4366b8b4 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp @@ -5,6 +5,7 @@ #include #include +#include "test-CmdProxy-global.h" #include "tests/globals.h" #include "versionAPI.h" @@ -42,13 +43,13 @@ TEST_CASE("Eiger transmission delay", "[.cmd]") { proxy.Call("txndelay_right", {}, -1, GET, oss2); REQUIRE(oss2.str() == "txndelay_right 5000\n"); } - } - // Reset to previous values - for (int i = 0; i != det.size(); ++i) { - det.setTransmissionDelayFrame(frame[i]); - det.setTransmissionDelayLeft(left[i]); - det.setTransmissionDelayRight(right[i]); + // Reset to previous values + for (int i = 0; i != det.size(); ++i) { + det.setTransmissionDelayFrame(frame[i]); + det.setTransmissionDelayLeft(left[i]); + det.setTransmissionDelayRight(right[i]); + } } } @@ -134,7 +135,7 @@ TEST_CASE("overflow", "[.cmd]") { } TEST_CASE("trimen", "[.cmd][.this]") { - //TODO! Also Mythen? + // TODO! Also Mythen? Detector det; CmdProxy proxy(&det); auto det_type = det.getDetectorType().squash(); @@ -147,7 +148,7 @@ TEST_CASE("trimen", "[.cmd][.this]") { proxy.Call("trimen", {}, -1, GET, oss2); REQUIRE(oss2.str() == "trimen [4500, 5400, 6400]\n"); - for (int i = 0; i!=det.size(); ++i){ + for (int i = 0; i != det.size(); ++i) { det.setTrimEnergies(previous[i], {i}); } } else { @@ -279,22 +280,6 @@ TEST_CASE("quad", "[.cmd]") { } } -void test_dac(defs::dacIndex index, const std::string &dacname, int dacvalue) { - Detector det; - CmdProxy proxy(&det); - std::ostringstream oss_set, oss_get; - auto dacstr = std::to_string(dacvalue); - auto previous = det.getDAC(index, false); - proxy.Call(dacname, {dacstr}, -1, PUT, oss_set); - REQUIRE(oss_set.str() == dacname + " " + dacstr + "\n"); - proxy.Call(dacname, {}, -1, GET, oss_get); - REQUIRE(oss_set.str() == dacname + " " + dacstr + "\n"); - // Reset all dacs to previous value - for (int i = 0; i != det.size(); ++i) { - det.setDAC(index, previous[i], false, {i}); - } -} - TEST_CASE("Setting and reading back EIGER dacs", "[.cmd]") { // vsvp, vtr, vrf, vrs, vsvn, vtgstv, vcmp_ll, vcmp_lr, vcal, vcmp_rl, // rxb_rb, rxb_lb, vcmp_rr, vcp, vcn, vis, vthreshold @@ -348,6 +333,48 @@ TEST_CASE("Setting and reading back EIGER dacs", "[.cmd]") { det.setDAC(defs::VCP, vcp[i], false, {i}); } } + REQUIRE_THROWS(proxy.Call("vref_ds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcascn_pb", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcascp_pb", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vout_cm", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcasc_out", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vin_cm", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_comp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("ib_test_c", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vpreamp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vshaper", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vshaperneg", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vipre", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("viinsh", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vdcsh", {}, -1, GET)); + // REQUIRE_THROWS(proxy.Call("vth1", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vth2", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vth3", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vpl", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vph", {}, -1, GET)); + // REQUIRE_THROWS(proxy.Call("vtrim", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcassh", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcas", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vicin", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vipre_out", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_h_adc", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_comp_fe", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_comp_adc", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcom_cds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_restore", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_opa_1st", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_comp_fe", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcom_adc1", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_l_adc", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_cds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_cs", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_opa_fd", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcom_adc2", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_ds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_comp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_pixbuf", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vin_com", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vdd_prot", {}, -1, GET)); } } diff --git a/slsDetectorSoftware/tests/test-CmdProxy-global.cpp b/slsDetectorSoftware/tests/test-CmdProxy-global.cpp new file mode 100644 index 000000000..c0104b85d --- /dev/null +++ b/slsDetectorSoftware/tests/test-CmdProxy-global.cpp @@ -0,0 +1,27 @@ +#include "test-CmdProxy-global.h" +#include "CmdProxy.h" +#include "Detector.h" +#include "catch.hpp" +#include "tests/globals.h" + +using sls::CmdProxy; +using sls::Detector; +using test::GET; +using test::PUT; + + +void test_dac(defs::dacIndex index, const std::string &dacname, int dacvalue) { + Detector det; + CmdProxy proxy(&det); + std::ostringstream oss_set, oss_get; + auto dacstr = std::to_string(dacvalue); + auto previous = det.getDAC(index, false); + proxy.Call(dacname, {dacstr}, -1, PUT, oss_set); + REQUIRE(oss_set.str() == dacname + " " + dacstr + "\n"); + proxy.Call(dacname, {}, -1, GET, oss_get); + REQUIRE(oss_get.str() == dacname + " " + dacstr + "\n"); + // Reset all dacs to previous value + for (int i = 0; i != det.size(); ++i) { + det.setDAC(index, previous[i], false, {i}); + } +} diff --git a/slsDetectorSoftware/tests/test-CmdProxy-global.h b/slsDetectorSoftware/tests/test-CmdProxy-global.h new file mode 100644 index 000000000..32a56f42a --- /dev/null +++ b/slsDetectorSoftware/tests/test-CmdProxy-global.h @@ -0,0 +1,4 @@ +#pragma once +#include "sls_detector_defs.h" + +void test_dac(slsDetectorDefs::dacIndex index, const std::string &dacname, int dacvalue); \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp b/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp new file mode 100644 index 000000000..18511ed60 --- /dev/null +++ b/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp @@ -0,0 +1,203 @@ +#include "CmdProxy.h" +#include "Detector.h" +#include "catch.hpp" +#include "sls_detector_defs.h" +#include + +#include "Result.h" +#include "ToString.h" +#include "test-CmdProxy-global.h" +#include "tests/globals.h" +#include "versionAPI.h" + +using sls::CmdProxy; +using sls::Detector; +using test::GET; +using test::PUT; + +TEST_CASE("Setting and reading back MYTHEN3 dacs", "[.cmd][.dacs]") { + // vcassh, vth2, vshaper, vshaperneg, vipre_out, vth3, vth1, + // vicin, vcas, vpreamp, vpl, vipre, viinsh, vph, vtrim, vdcsh, + + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::MYTHEN3) { + SECTION("vcassh") { test_dac(defs::CASSH, "vcassh", 1200); } + SECTION("vth2") { test_dac(defs::VTH2, "vth2", 2800); } + SECTION("vshaper") { test_dac(defs::SHAPER1, "vshaper", 1280); } + SECTION("vshaperneg") { test_dac(defs::SHAPER2, "vshaperneg", 2800); } + SECTION("vipre_out") { test_dac(defs::VIPRE_OUT, "vipre_out", 1220); } + SECTION("vth3") { test_dac(defs::VTH3, "vth3", 2800); } + SECTION("vth1") { test_dac(defs::THRESHOLD, "vth1", 2880); } + SECTION("vicin") { test_dac(defs::VICIN, "vicin", 1708); } + SECTION("vcas") { test_dac(defs::CAS, "vcas", 1800); } + SECTION("vpreamp") { test_dac(defs::PREAMP, "vpreamp", 1100); } + SECTION("vpl") { test_dac(defs::VPL, "vpl", 1100); } + SECTION("vipre") { test_dac(defs::VIPRE, "vipre", 2624); } + SECTION("viinsh") { test_dac(defs::VIINSH, "viinsh", 1708); } + SECTION("vph") { test_dac(defs::CALIBRATION_PULSE, "vph", 1712); } + SECTION("vtrim") { test_dac(defs::TRIMBIT_SIZE, "vtrim", 2800); } + SECTION("vdcsh") { test_dac(defs::VDCSH, "vdcsh", 800); } + + REQUIRE_THROWS(proxy.Call("vsvp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vsvn", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vtr", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vrf", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vrs", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vtgstv", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcmp_ll", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcmp_lr", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcal", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcmp_rl", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcmp_rr", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("rxb_rb", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("rxb_lb", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcn", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vis", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("iodelay", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_ds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcascn_pb", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcascp_pb", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vout_cm", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcasc_out", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vin_cm", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_comp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("ib_test_c", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_h_adc", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_comp_fe", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_comp_adc", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcom_cds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_restore", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_opa_1st", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_comp_fe", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcom_adc1", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_prech", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_l_adc", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vref_cds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_cs", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_opa_fd", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vcom_adc2", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_ds", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_comp", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vb_pixbuf", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vin_com", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("vdd_prot", {}, -1, GET)); + } +} + +TEST_CASE("clkfreq", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2) { + REQUIRE_THROWS(proxy.Call("clkfreq", {"0", "2"}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("clkfreq", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("clkfreq", {"7"}, -1, GET)); + + auto value = det.getClockFrequency(0).squash(-1); + std::ostringstream oss_set, oss_get; + proxy.Call("clkfreq", {"0"}, -1, GET, oss_get); + REQUIRE(oss_get.str() == "clkfreq " + std::to_string(value) + "\n"); + } else { + REQUIRE_THROWS(proxy.Call("clkfreq", {"0"}, -1, GET)); + } +} + +TEST_CASE("clkphase", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2) { + REQUIRE_THROWS(proxy.Call("clkphase", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("clkphase", {"7"}, -1, GET)); + REQUIRE_THROWS(proxy.Call("clkphase", {"4"}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("clkphase", {"7", "4"}, -1, PUT)); + + auto previous = det.getClockFrequency(0).squash(-1); + auto previous_string = std::to_string(previous); + std::ostringstream oss_set, oss_get, oss_get2; + proxy.Call("clkfreq", {"0", previous_string}, -1, PUT, oss_set); + REQUIRE(oss_set.str() == "clkfreq" + previous_string + "\n"); + proxy.Call("clkfreq", {"0"}, -1, GET, oss_get); + REQUIRE(oss_get.str() == "clkfreq " + previous_string + "\n"); + REQUIRE_NOTHROW(proxy.Call("clkphase", {"0", "deg"}, -1, GET)); + } else { + REQUIRE_THROWS(proxy.Call("clkphase", {"0"}, -1, GET)); + } +} + +TEST_CASE("clkdiv", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2) { + REQUIRE_THROWS(proxy.Call("clkdiv", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("clkdiv", {"7"}, -1, GET)); + REQUIRE_THROWS(proxy.Call("clkdiv", {"7", "4"}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("clkdiv", {"7", "4"}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("clkdiv", {"0", "1"}, -1, PUT)); + + auto previous = det.getClockDivider(0).squash(-1); + auto previous_string = std::to_string(previous); + std::ostringstream oss_set, oss_get; + proxy.Call("clkdiv", {"0", previous_string}, -1, PUT, oss_set); + REQUIRE(oss_set.str() == "clkdiv" + previous_string + "\n"); + proxy.Call("clkdiv", {"0"}, -1, GET, oss_get); + REQUIRE(oss_get.str() == "clkdiv " + previous_string + "\n"); + } else { + REQUIRE_THROWS(proxy.Call("clkdiv", {"0"}, -1, GET)); + } +} + +TEST_CASE("maxclkphaseshift", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2) { + REQUIRE_THROWS(proxy.Call("maxclkphaseshift", {"0", "2"}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("maxclkphaseshift", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("maxclkphaseshift", {"7"}, -1, GET)); + + auto value = det.getMaxClockPhaseShift(0).squash(-1); + std::ostringstream oss_set, oss_get; + proxy.Call("maxclkphaseshift", {"0"}, -1, GET, oss_get); + REQUIRE(oss_get.str() == + "maxclkphaseshift " + std::to_string(value) + "\n"); + } else { + REQUIRE_THROWS(proxy.Call("maxclkphaseshift", {"0"}, -1, GET)); + } +} + +TEST_CASE("counters", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::MYTHEN3) { + REQUIRE_THROWS(proxy.Call("counters", {}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("counters", {"3"}, -1, GET)); + REQUIRE_THROWS(proxy.Call("counters", {"0", "-1"}, -1, GET)); + REQUIRE_THROWS(proxy.Call("counters", {"0", "1", "1"}, -1, GET)); + + auto mask = det.getCounterMask({0}).squash(-1); + std::vector list_str; + for (int i = 0; i < 32; ++i) { + if (mask & (1 << i)) { + list_str.push_back(std::to_string(i)); + } + } + std::ostringstream oss_set, oss_set2, oss_set3, oss_get; + proxy.Call("counters", {"0", "2", "1"}, -1, PUT, oss_set); + REQUIRE(oss_set.str() == "counters [0, 2, 1]\n"); + proxy.Call("counters", {"0", "2"}, -1, PUT, oss_set2); + REQUIRE(oss_set2.str() == "counters [0, 2]\n"); + // put back old value + proxy.Call("counters", list_str, -1, PUT, oss_set3); + REQUIRE(oss_set3.str() == "counters " + sls::ToString(list_str) + "\n"); + proxy.Call("counters", {}, -1, GET, oss_get); + REQUIRE(oss_get.str() == "counters " + sls::ToString(list_str) + "\n"); + } else { + REQUIRE_THROWS(proxy.Call("counters", {}, -1, GET)); + } +} diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index 862272ea1..83dd8f1ce 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -153,311 +153,7 @@ TEST_CASE("type", "[.cmd]"){ // REQUIRE_NOTHROW(multiSlsDetectorClient("daclist", GET)); // REQUIRE_NOTHROW(multiSlsDetectorClient("dacvalues", GET)); // int prev_val = 0; -// if (test::type == slsDetectorDefs::EIGER) { -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold", GET, -// nullptr, oss)); std::string s = (oss.str()).erase (0, -// strlen("vthreshold ")); prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold", GET, -// nullptr, oss)); REQUIRE(oss.str() == "vthreshold 1000\n"); -// } -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_ll", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcmp_ll 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvp", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vsvp ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvp 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvp", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vsvp 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvp " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvn", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vsvn ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvn 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvn", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vsvn 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vsvn " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtr", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vtr ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtr 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtr", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vtr 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtr " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrf", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vrf ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrf 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrf", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vrf 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrf " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrs", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vrs ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrs 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrs", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vrs 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vrs " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtgstv", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vtgstv ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtgstv 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtgstv", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vtgstv 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtgstv " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_ll", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcmp_ll ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_ll 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_ll", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcmp_ll 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_ll " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_lr", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcmp_lr ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_lr 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_lr", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcmp_lr 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_lr " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcal", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcal ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcal 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcal", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcal 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcal " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rl", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcmp_rl ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rl 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rl", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcmp_rl 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rl " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rr", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcmp_rr ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rr 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rr", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcmp_rr 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcmp_rr " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_rb", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("rxb_rb ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_rb 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_rb", GET, nullptr, -// oss)); REQUIRE(oss.str() == "rxb_rb 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_rb " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_lb", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("rxb_lb ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_lb 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_lb", GET, nullptr, -// oss)); REQUIRE(oss.str() == "rxb_lb 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("rxb_lb " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcp", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcp ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcp 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcp", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcp 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcp " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcn", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcn ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcn 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcn", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcn 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcn " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vis", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vis ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vis 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vis", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vis 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vis " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("iodelay", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("iodelay ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("iodelay 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("iodelay", GET, nullptr, -// oss)); REQUIRE(oss.str() == "iodelay 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("iodelay " + -// std::to_string(prev_val), PUT)); - -// REQUIRE_THROWS(multiSlsDetectorClient("vref_ds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcascn_pb", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcascp_pb", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vout_cm", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcasc_out", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vin_cm", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_comp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("ib_test_c", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vpreamp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vshaper", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vshaperneg", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vipre", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("viinsh", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vdcsh", GET)); -// // REQUIRE_THROWS(multiSlsDetectorClient("vth1", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vth2", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vth3", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vpl", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vph", GET)); -// //REQUIRE_THROWS(multiSlsDetectorClient("vtrim", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcassh", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcas", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vicin", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vipre_out", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_h_adc", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_comp_fe", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_comp_adc", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcom_cds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_restore", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_opa_1st", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_comp_fe", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcom_adc1", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_l_adc", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_cds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_cs", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_opa_fd", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcom_adc2", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_ds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_comp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_pixbuf", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vin_com", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vdd_prot", GET)); - -// } - -// else if (test::type == slsDetectorDefs::JUNGFRAU) { +// if (test::type == slsDetectorDefs::JUNGFRAU) { // { // std::ostringstream oss; // REQUIRE_NOTHROW(multiSlsDetectorClient("vb_ds", GET, nullptr, @@ -878,291 +574,6 @@ TEST_CASE("type", "[.cmd]"){ // REQUIRE_THROWS(multiSlsDetectorClient("vdd_prot", GET)); // } -// else if (test::type == slsDetectorDefs::MYTHEN3) { -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold", GET, -// nullptr, oss)); std::string s = (oss.str()).erase (0, -// strlen("vthreshold ")); prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold 1000 mv", -// PUT)); std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold mv", GET, -// nullptr, oss)); REQUIRE(oss.str() == "vthreshold 1000 mv\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vthreshold " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpreamp", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vpreamp ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpreamp 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpreamp", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vpreamp 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpreamp " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaper", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vshaper ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaper 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaper", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vshaper 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaper " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaperneg", GET, -// nullptr, oss)); std::string s = (oss.str()).erase (0, -// strlen("vshaperneg ")); prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaperneg 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaperneg", GET, -// nullptr, oss)); REQUIRE(oss.str() == "vshaperneg 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vshaperneg " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vipre ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vipre 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("viinsh", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("viinsh ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("viinsh 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("viinsh", GET, nullptr, -// oss)); REQUIRE(oss.str() == "viinsh 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("viinsh " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vdcsh", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vdcsh ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vdcsh 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vdcsh", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vdcsh 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vdcsh " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth1", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vth1 ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth1 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth1", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vth1 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth1 " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth2", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vth2 ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth2 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth2", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vth2 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth2 " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth3", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vth3 ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth3 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth3", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vth3 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vth3 " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpl", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vpl ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpl 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpl", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vpl 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vpl " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vph", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vph ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vph 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vph", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vph 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vph " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtrim", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vtrim ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtrim 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtrim", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vtrim 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vtrim " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcassh", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcassh ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcassh 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcassh", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcassh 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcassh " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcas", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vcas ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcas 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcas", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vcas 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vcas " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vicin", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vicin ")); -// prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vicin 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vicin", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vicin 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vicin " + -// std::to_string(prev_val), PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre_out", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("vipre_out -// ")); prev_val = std::stoi(s); -// } -// { -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre_out 1000", PUT)); -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre_out", GET, nullptr, -// oss)); REQUIRE(oss.str() == "vipre_out 1000\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("vipre_out " + -// std::to_string(prev_val), PUT)); - -// REQUIRE_THROWS(multiSlsDetectorClient("vsvp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vsvn", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vtr", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vrf", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vrs", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vtgstv", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcmp_ll", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcmp_lr", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcal", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcmp_rl", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcmp_rr", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("rxb_rb", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("rxb_lb", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcn", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vis", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("iodelay", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_ds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcascn_pb", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcascp_pb", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vout_cm", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcasc_out", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vin_cm", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_comp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("ib_test_c", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_h_adc", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_comp_fe", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_comp_adc", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcom_cds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_restore", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_opa_1st", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_comp_fe", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcom_adc1", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_prech", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_l_adc", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vref_cds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_cs", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_opa_fd", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vcom_adc2", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_ds", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_comp", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vb_pixbuf", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vin_com", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("vdd_prot", GET)); -// } // else if (test::type == slsDetectorDefs::GOTTHARD2) { // { @@ -3896,63 +3307,7 @@ TEST_CASE("firmwareversion", "[.cmd]") { // REQUIRE_NOTHROW(multiSlsDetectorClient("delay 0", PUT)); // } // } -// TEST_CASE("clk", "[.cmd][.gotthard2][.mythen3]") { -// if(test::type == slsDetectorDefs::GOTTHARD2 || test::type == -// slsDetectorDefs::MYTHEN3) { -// REQUIRE_THROWS(multiSlsDetectorClient("clkfreq 0 2", PUT)); // cannot -// get REQUIRE_THROWS(multiSlsDetectorClient("clkfreq", GET)); // -// requires clk index REQUIRE_THROWS(multiSlsDetectorClient("clkfreq 7", -// GET)); // 7 doesnt exist -// REQUIRE_THROWS(multiSlsDetectorClient("clkfreq 4", PUT)); // requires -// clk index and val REQUIRE_THROWS(multiSlsDetectorClient("clkfreq 7 -// 4", PUT)); // 7 doesnt exist -// REQUIRE_THROWS(multiSlsDetectorClient("clkphase", GET)); // requires -// clk index REQUIRE_THROWS(multiSlsDetectorClient("clkphase 7", GET)); -// // 7 doesnt exist REQUIRE_THROWS(multiSlsDetectorClient("clkphase 4", -// PUT)); // requires clk index and val -// REQUIRE_THROWS(multiSlsDetectorClient("clkphase 7 4", PUT)); // 7 -// doesnt exist REQUIRE_THROWS(multiSlsDetectorClient("clkdiv", GET)); -// // requires clk index REQUIRE_THROWS(multiSlsDetectorClient("clkdiv -// 7", GET)); // 7 doesnt exist -// REQUIRE_THROWS(multiSlsDetectorClient("clkdiv 4", PUT)); // requires -// clk index and val REQUIRE_THROWS(multiSlsDetectorClient("clkdiv 7 4", -// PUT)); // 7 doesnt exist -// REQUIRE_THROWS(multiSlsDetectorClient("maxclkphaseshift 7", GET)); // -// 7 doesnt exist -// REQUIRE_THROWS(multiSlsDetectorClient("maxclkphaseshift 7 4", PUT)); -// // cannot put -// REQUIRE_NOTHROW(multiSlsDetectorClient("maxclkphaseshift 0", GET)); -// int t = 0; -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("clkdiv 0", GET, nullptr, -// oss)); std::string s = (oss.str()).erase (0, strlen("clkdiv ")); -// t = std::stoi(s); -// } -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("clkdiv 0 " + -// std::to_string(t), PUT, nullptr, oss)); REQUIRE(oss.str() == -// "clkdiv " + std::to_string(t) + '\n'); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("clkfreq 0", GET)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("clkphase 1 20", PUT, -// nullptr, oss)); REQUIRE(oss.str() == "clkphase 20\n"); -// } -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("clkphase 1", GET, -// nullptr, oss)); REQUIRE(oss.str() == "clkphase 20\n"); -// } -// } else { -// REQUIRE_THROWS(multiSlsDetectorClient("clkfreq 0", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("clkphase 0", GET)); -// REQUIRE_THROWS(multiSlsDetectorClient("clkdiv 0", GET)); -// } -// } TEST_CASE("frames", "[.cmd]") { Detector det; diff --git a/slsReceiverSoftware/include/ClientInterface.h b/slsReceiverSoftware/include/ClientInterface.h index 2df26832f..96e117e13 100755 --- a/slsReceiverSoftware/include/ClientInterface.h +++ b/slsReceiverSoftware/include/ClientInterface.h @@ -119,6 +119,7 @@ class ClientInterface : private virtual slsDetectorDefs { int set_udp_port2(sls::ServerInterface2 &socket); int set_num_interfaces(sls::ServerInterface2 &socket); int set_adc_mask_10g(sls::ServerInterface2 &socket); + int set_num_counters(sls::ServerInterface2 &socket); Implementation *impl() { if (receiver != nullptr) { diff --git a/slsReceiverSoftware/include/GeneralData.h b/slsReceiverSoftware/include/GeneralData.h index 2ceecc4bc..427b2c790 100755 --- a/slsReceiverSoftware/include/GeneralData.h +++ b/slsReceiverSoftware/include/GeneralData.h @@ -208,12 +208,21 @@ public: /** * set number of interfaces (jungfrau) - * @param number of interfaces + * @param n number of interfaces */ virtual void SetNumberofInterfaces(const int n) { FILE_LOG(logERROR) << "SetNumberofInterfaces is a generic function that should be overloaded by a derived class"; } + /** + * set number of counters (mythen3) + * @param n number of counters + * @param dr dynamic range + */ + virtual void SetNumberofCounters(const int n, const int dr) { + FILE_LOG(logERROR) << "SetNumberofCounters is a generic function that should be overloaded by a derived class"; + } + /** * Print all variables */ @@ -528,16 +537,19 @@ class JungfrauData : public GeneralData { }; class Mythen3Data : public GeneralData { - - public: +private: + int ncounters; + const int NCHAN = 1280; +public: /** Constructor */ Mythen3Data(){ myDetectorType = slsDetectorDefs::MYTHEN3; - nPixelsX = (1280 * 3); // 1280 channels, 3 counters + ncounters = 3; + nPixelsX = (NCHAN * ncounters); // max 1280 channels x 3 counters nPixelsY = 1; headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header); - dataSize = 7680;//8192; + dataSize = 7680; packetSize = headerSizeinPacket + dataSize; packetsPerFrame = 2; imageSize = dataSize * packetsPerFrame; @@ -547,6 +559,39 @@ class Mythen3Data : public GeneralData { standardheader = true; defaultUdpSocketBufferSize = (1000 * 1024 * 1024); }; + + /** + * set number of counters (mythen3) + * @param n number of counters + * @param dr dynamic range + */ + virtual void SetNumberofCounters(const int n, const int dr) { + if (n < 1 || n > 3) { + throw sls::RuntimeError("Invalid number of counters " + std::to_string(n)); + } + ncounters = n; + nPixelsX = NCHAN * ncounters; + imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit + ((dr > 8) ? 2 : // 16 bit + ((dr > 4) ? 0.5 : // 4 bit + 0.125))); // 1 bit + dataSize = imageSize / packetsPerFrame; + packetSize = headerSizeinPacket + dataSize; + } + + /** + * Setting dynamic range changes member variables + * @param dr dynamic range + * @param tgEnable (discarded, of no value to mythen3) + */ + void SetDynamicRange(int dr, bool tgEnable) { + imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit + ((dr > 8) ? 2 : // 16 bit + ((dr > 4) ? 0.5 : // 4 bit + 0.125))); // 1 bit + dataSize = imageSize / packetsPerFrame; + packetSize = headerSizeinPacket + dataSize; + } }; diff --git a/slsReceiverSoftware/include/Implementation.h b/slsReceiverSoftware/include/Implementation.h index b2fc2863b..a5206593e 100755 --- a/slsReceiverSoftware/include/Implementation.h +++ b/slsReceiverSoftware/include/Implementation.h @@ -149,6 +149,8 @@ class Implementation : private virtual slsDetectorDefs { uint32_t getNumberofDigitalSamples() const; /**[Ctb] */ void setNumberofDigitalSamples(const uint32_t i); + int getNumberofCounters() const; + void setNumberofCounters(const int i); uint32_t getDynamicRange() const; void setDynamicRange(const uint32_t i); ROI getROI() const; @@ -271,6 +273,7 @@ class Implementation : private virtual slsDetectorDefs { uint64_t subPeriod; uint64_t numberOfAnalogSamples; uint64_t numberOfDigitalSamples; + int numberOfCounters; uint32_t dynamicRange; ROI roi; bool tengigaEnable; diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index c56e7ec0a..15e0bbb18 100755 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -174,7 +174,7 @@ int ClientInterface::functionTable(){ flist[F_SET_RECEIVER_UDP_PORT2] = &ClientInterface::set_udp_port2; flist[F_SET_RECEIVER_NUM_INTERFACES] = &ClientInterface::set_num_interfaces; flist[F_RECEIVER_SET_ADC_MASK_10G] = &ClientInterface::set_adc_mask_10g; - + flist[F_RECEIVER_SET_NUM_COUNTERS] = &ClientInterface::set_num_counters; for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) { FILE_LOG(logDEBUG1) << "function fnum: " << i << " (" << @@ -1319,4 +1319,12 @@ int ClientInterface::set_adc_mask_10g(Interface &socket) { } FILE_LOG(logDEBUG1) << "10Gb ADC enable mask retval: " << retval; return socket.sendResult(retval); +} + +int ClientInterface::set_num_counters(Interface &socket) { + auto arg = socket.Receive(); + verifyIdle(socket); + FILE_LOG(logDEBUG1) << "Setting counters: " << arg; + impl()->setNumberofCounters(arg); + return socket.Send(OK); } \ No newline at end of file diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index e8dd2d98d..55e0c4fb4 100755 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -101,6 +101,7 @@ void Implementation::InitializeMembers() { subPeriod = 0; numberOfAnalogSamples = 0; numberOfDigitalSamples = 0; + numberOfCounters = 0; dynamicRange = 16; roi.xmin = -1; roi.xmax = -1; @@ -1287,6 +1288,26 @@ void Implementation::setNumberofDigitalSamples(const uint32_t i) { << (generalData->packetsPerFrame); } +int Implementation::getNumberofCounters() const { + FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called"; + return numberOfCounters; +} + +void Implementation::setNumberofCounters(const int i) { + if (numberOfCounters != i) { + numberOfCounters = i; + + if (myDetectorType == MYTHEN3) { + generalData->SetDynamicRange(i, tengigaEnable); + // to update npixelsx, npixelsy in file writer + for (const auto &it : dataProcessor) + it->SetPixelDimension(); + SetupFifoStructure(); + } + } + FILE_LOG(logINFO) << "Number of Counters: " << numberOfCounters; +} + uint32_t Implementation::getDynamicRange() const { FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called"; return dynamicRange; @@ -1297,9 +1318,11 @@ void Implementation::setDynamicRange(const uint32_t i) { if (dynamicRange != i) { dynamicRange = i; - if (myDetectorType == EIGER) { + if (myDetectorType == EIGER || myDetectorType == MYTHEN3) { generalData->SetDynamicRange(i, tengigaEnable); - generalData->SetGapPixelsEnable(gapPixelsEnable, dynamicRange, quadEnable); + if (myDetectorType == EIGER) { + generalData->SetGapPixelsEnable(gapPixelsEnable, dynamicRange, quadEnable); + } // to update npixelsx, npixelsy in file writer for (const auto &it : dataProcessor) it->SetPixelDimension(); diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h index c814599c1..d2e2504e1 100755 --- a/slsSupportLib/include/sls_detector_funcs.h +++ b/slsSupportLib/include/sls_detector_funcs.h @@ -186,6 +186,8 @@ enum detFuncs{ F_SET_BURST_MODE, F_SET_ADC_ENABLE_MASK_10G, F_GET_ADC_ENABLE_MASK_10G, + F_SET_COUNTER_MASK, + F_GET_COUNTER_MASK, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this (detector server should not compile anyway) */ @@ -256,6 +258,7 @@ enum detFuncs{ F_SET_RECEIVER_UDP_PORT2, F_SET_RECEIVER_NUM_INTERFACES, F_RECEIVER_SET_ADC_MASK_10G, + F_RECEIVER_SET_NUM_COUNTERS, NUM_REC_FUNCTIONS }; @@ -438,6 +441,9 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_SET_BURST_MODE: return "F_SET_BURST_MODE"; case F_SET_ADC_ENABLE_MASK_10G: return "F_SET_ADC_ENABLE_MASK_10G"; case F_GET_ADC_ENABLE_MASK_10G: return "F_GET_ADC_ENABLE_MASK_10G"; + case F_SET_COUNTER_MASK: return "F_SET_COUNTER_MASK"; + case F_GET_COUNTER_MASK: return "F_GET_COUNTER_MASK"; + case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START"; @@ -509,6 +515,8 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_SET_RECEIVER_UDP_PORT2: return "F_SET_RECEIVER_UDP_PORT2"; case F_SET_RECEIVER_NUM_INTERFACES: return "F_SET_RECEIVER_NUM_INTERFACES"; case F_RECEIVER_SET_ADC_MASK_10G: return "F_RECEIVER_SET_ADC_MASK_10G"; + case F_RECEIVER_SET_NUM_COUNTERS: return "F_RECEIVER_SET_NUM_COUNTERS"; + case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS"; default: return "Unknown Function"; diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index fc525b4c8..cef067710 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -8,5 +8,5 @@ #define APIGOTTHARD 0x191127 #define APIJUNGFRAU 0x191127 #define APICTB 0x191210 -#define APIMYTHEN3 0x191210 #define APIEIGER 0x200110 +#define APIMYTHEN3 0x200114