b*4vr50E{P&cW`%&-e8(
zu&wI$S?l)P&d$JQU>N!go#@-#br86+z|Q$^wPlJ@cP&eY#Nr16e*an>$S?|KEYvHaVf^}yy{o2gvGJ~si*;}sN`5(yGGDlDD=n}(R=*S&h
zo&(Nq+?faK>9#Lcs)9Sv1iX6OrE_?
zMp3Rk9zj@BCur}&@;A966OSGElC33rkFBhIX^xyujP1sKe6W^*b$!e_Evzq=C!u}V
zz-VH9-Kj|q=B|(3>@dnbcJp`RKD`V37*EpL@5yk&B4yd(q*cuhD5)x!EaQ?qomCa5
zgAM~Ju+GQl8^7M{gn{f%%Gm*g8U_Zkvl~|{9n8Ap_dxaYdJ@&+_`%(u#REs{n4OF|
zspqG@<0QDwiY&2G(l$S7j(j<_w4KOh)Zn!v<3-kt$|^0}17^~j;CAD#%bz1sSap}b4zFXWjvZ0Mh7I%momS}`BEo0IbY&9F$*-wY{PSl*Ijy4bUsXQ
z_2$)4RtoyhtnZ=gcDU<%=$aV1>PI)T+(#n2+{gcq*7pc3!ZEnnvP*Bo
zXMmMmdLz!SinB{^#P5Z#*`+t)tD!f$^hTUtsb-hnh(C<#W|!WGe?rn*dL!Ns?qrwV
zh+j=r-qIWKhf#&>(i?HyWcilfi2sOA4v@I~Sb8J=O>&DR_GW0%xcC?8hPU)a{A&8_
zExi$6MmM~rH{y4&the+={9bzHExi%{HQgw+Yhf=m=-BvX3XhRssi8r0;-%zzOK-%N
zu_dS5>^UsG5kH0G3?)~@ZzSn0y%GPAUd^`87R{>=sktvw-JXDf1XEaeV0Hpq=_I{vL2ai&z!f(Ob|W#t1Rqf)+6wTHweXc0St#oPrgV)u~eE@%<^
zDS7UK7O|n!;x1?r599cMT~E)dJ9^_Ze@jX7PR;cSR#yP!o@ifz%GO#nV8D6^nNmd~Trzo138TOgJfnMQ$4_+w`ksBZR{
zSw|Ng9*MKVivT>vV03#bmMdsSkU4U6zI61MYb@H7+uifR}kfb
z7LTI&Em@1ePEA0^gi?j*)^O?xq$8Aq{6Dmy#atN1f)=q)Fm__g{{X*u49=pR6U;D<#Q5fWYy}%r7PNQ=1Jbvk1xYMu
z5$i_{t8_t&*kJURx1dGrI`Z5FEn*v?$y?AOb|NL$8(X@d#raT)1ubHI>4v+YMU1gm
zyag>{eEl@$E@%WlulHb5nzd~Lp#rMj>DZIFb
zt}a2l1&@9S@qNE&-&JfW
zoF?0V(L)T?Ew&TA5bbBEWUM!|Mf>x8&Cnn$XhG%C?1C0sVWTK|SPW}KSkZwJA{$;7
zpc>Kaf)*5t%7PZryKq0xcPpIe&=}t-j1Dt)tQZ&5iVinaD0VLTK6<#B)v#^~i$q79
zgTm3j;Lqdm#)+014Wj}YMh7&Mc^X(GI+m{qMETqOr95JzY~R)pg4L5{_xT&8J%LZPYr0F7SKLDpnXO_`%F(e)kVu!Q~QVb
zvls`m6Ft^wpA*nNH=zAEjt*IOhDDH_*U7|J&K>Rs)kuff$WW1`X1PIb|yA}EgX*ZeVZRJIuHnSl09u09#{
zr@Q(@`)1W=M%AOquP0GCK^V$Km;Dv8u~NQg3}6G;-KCQ4&H%n-ZFi@#PWDhppUlFg;Ehu1&2$-9?kJc}W!@;59_WpkoD|I{;0dU|
z{KhXY7%vdJi(vB+>>LSZ^vw_0RZ8v7546I3nes6DWGv1%UT81O57c`hC)QB=Dy#n^
z{Eh!f9BWvBg-Z_b#)0qu^S4i9|D=HZlT6!2jE$2_+d8JFPck-=rl(KgWGmxN-U}$^
z5wS*WOoRSgv5$j|VmZRnoKk7W9Aas=T5^b`jRRV(w5e9UF_|_d3yjINoU5ff@8wVU
zGdZ}L#3aoXW2ElzsUN)2Wqn_Plx)(fc=dD`x^uHn>o{q{ka7&JqqnKqsHW^MrWw8+!9POk;^2cJkNY
zNg>8MVutZfnSaf3X=3>dnQ0L+#>#H<$3dB17&_{``L~huoJ;
z+rX3U*y9*_#+z%64a*F&YmL^3>G5lgR>$fu3s1btHvWd_*##Yc#XjECbAzi#Chi;D
zTFK#YgK0S(x;GfDI&^R3SxScP&*#5hLDfdL)L#o(zd%;
zA*92iAi)JeI$t4#pVxVBN>tMud1pcv@bK0OK`XgSfxtaCi7qsSOV_a+qj?~Os<;A3
zniWEr*I|VaD0No|K@x2tf5YAF^A;YtY2M_c=UqBEG``QRIn*ojCM~F$chr>0FHH`O
z==1aQa_L~%XXj0ve)RmBDd$cOP3ZI5*C$?4bNuA5OvX|iuWdhi%F**CPnw!O{^%*8
zNqshNpB6sj7_75#eD&mYLQfBG0X_Bj)sxpU!ztWua;D5%J$aq6?i999YEK^@npEhV
zVswjBuQ7Krb5CoT9GY3^j8QmmF?G(HI&s0y$y3gmyf!ql4a-wXa3U6kh$&=r3#_+9De`Fe8~`guNG@8i$k7MXoM#*bV%gM1dCoaq@r!W)*7(ZL%khtsYFGZtgxE>>BII%7L{|ZH>o;p#
zc3lomWw|`JT{u~F)~?javBMaiL^Kc64w3y7@>x82c%yi>BA%s5sZO@OxhvxipVd^!Fs*nM~F9=v_s_eieHukR~`bQ
zQp7>RZ*hpcn()hV5VsqCgm}40J49YF_+>eu`Enf_ix@U(hsZO(UzUSgeuRZAv03;n
z4v}Yfzbps)lZGE5^5Y}68Ik96zbpqoKQf{Z#IYvr5P1go%gV>d(kp+*xs|WHyI*db
zud~an7kqiyuer-C-hc*W&3D_pO?30K@`lHoHkYSyGs~=f9W#wIZ*F`aoAX{H_?bKJ
z3<96mmsz}W4`eZfYGs+lE9%^D=y_cm{E}b83h)v$$S~i~msz}Mg5z0_^iT%&WPHRDfJ=oU(A#VZ$)h&Hb&Oq{OD|7~51MnYxk94ivzYQMi2ub9W}g+V)YB}5K3{}UuLZQB>Af3T%?lREOhzzs<1#Yf+rKIJ
zXeT2h+YD}$K#5HHABslmHbC~kD9bvKJ3igM{Wpg$b$xITz^nsaz&;ssfyVN=Nw*Fh
z(ll^nc&2=D9i*89@lLyrZYohj7$c5$|K~!Oy3zOCDr9?1CZ}wpxdPgpIb1L1sedwX
zJGNsiQxjki@dFXWx>90nWDWfvjbfTR^GSS0i7A+k9UF*h>c$(y{8MJ(&ls6eO)MFZ
zZ5RVkFi7SnO2)1v>6`
zWJ5@&Kj_0Mk>2o)i2e$+D*f$Ls_+^BmxZCvVu>@(i43buRv1RS`Ww^-&
z;K7u)?VE4vMSZLv>q|TpJIk1xA>3yTH2KJq&25*{K)Jff_yXkkW|+IVa%+&`x4R#9
z^HGp?@!Oea_jIKF`o3L)_nF*A_wmm6rIEDm9*P)SzJhM@Jn;N>KS2Yqezc1p20Xjh
zBJGwz(wa2fvWl6|&EeH?pk``v^z%Wyn!I~n@;T8_Js$NhFiH~)KM
zJCAkxUpaEGLe9Ur{^9oB8>8e??s1=>D@XKolhrcOviNL?@9t0s>%sc4uD<5CZb#su
z&SLUHEU>wDnE5{u>lDvLWMkjj9b%dK8Xo+Pu}yJ6`L>R+P1zFJEsW@s{;gvy)85jK
zl;Lws#;U~d^fqdn-yHsJpxx);
zpl}F|9Q~vb8yms&XLdg8OyzRcdsYh=YPB<
z&B@DNKar^`+PE^=>yR>8hoh7HYJWT%eik$y!FhKQ%ce1(tva}_Tq4lrvwQ|>j*XRHOv
zNt{mTA3(YobG7D6yf^UAB#m;ifbl@gAIkr|Via>7`FzXUF2Qd=M3h^m*h~cf3q&;D
z{hBYY?@yF|fj9!!378vM{!qo)
zM93{9mZCnIf3D(}l+P~#?9qsur1>u@MsS_X^1X@RFDF8OMsbJoFCmUK*S(NQoc^{bj9-(
zFH!u8;&&DAReVg5vAn70HN_7V?5h(E#ff7#F8*@f3k?X?cmK2wLJP0{K-2^-4TNpu|%I&eVK~rwCf&DFQcWzQj`mE%6kA5>F8*
z@f3j)PZ22b6oC>?5h(E#funi+0OeZ}pu|%IN<2lN#8U)HJVl_yQv^ypMWDn}1WG(b
zpu|%I@~2Gdm3WH4x0RN7il8N)B2eNf0wtazkUw#F8*@f3j)PZ22b6oC>?5h(E#
zff7#F8*@f3j)PZ22b6oD70U4FJoee<@t2CvD@q(i@Fk8SkZX%lzNg}$iX#;#Db7_~
zp}1DDK~dr)LQk90*C>8V@lHjFg9y3DmHuzVKPrBt7{e_k{YokJS3E-TD8)I7Cn#1b
zZczM!Vw>XSiq|VjoI=?7k^sm3-V8yYD(-jvgu2ig3JX3L-
zV!Ps36~Cu=ui|5hzg2uu@z08XSL}`(dHU5yagd_K4MhG_rROW2qFASRIuYlDGZoJ!
zV(e^J{$+|^Q@lm-KE-{Ce36pU8H!m;x`pg1^iT0aBK=c-x1PqYBE=z!;}j(>AM7tux=B&u
z@Imjnq=7q#(0h^cuU3>ed?lf6;D)Lt0?j3P`@ikqx{v1UnZjb^(yy$#s5-#Qt@|0l-sMg
zkBD-ARQ`vGh-@N$7ZM@gS8)Il@`IFLrdY1HhzR+miYthaU#a}{idz&fP`py{2E`vJ
z{zCCNBCY}UDgCzMYrHRjJ-N@pIh!vok)B8deT>p8ls-l2%}Rek>8q9gveLVizEA0A
zmHwU5A1VEb(nY)vpnW3kEA7V9TcPwR%HOQ?7nHtQ=`Sn2Tj~3hepcz9B^Xk5u_pM3i1r#tp!dX(+Sh7fE0VCT#bq8s@HT7JKCCZi$wvwpsFrjwI(_s*FN
zG3Ap=UAZT9=bksdu7S{Y-ZzvkN<6d!`cwAQjy)}fIR=@Ty7B>d+4_WrIt#?(`i%Oa
z9I9wSq#dw+hzthjrA>4D9&7?%zMtU;l~m
z|IZ!Y(O}E6{c}diKU2TX#>3~EZ~k-s>#l0q3{Qj>rFLdpX_6`RFqa
z_CWpa;Vj6YfC!JL5kZ%h6x@T8$)||QmybAhJP$bA_Q-M05PA`Fu6b0Z)K2HqVFx-t
z$?-68=gfRQVz=(Wb1TMrEx22(!OG5=1u*Ewsq{`hot!ZO@i-4??{oK0aB|}L(6kGh
z;%<6r+Cw}{awg5T%z;iaDAZX@JvZ3hTwHsHOArSxk(h!@y9km!OcK%W6NsCK$I?vT
zDNk?P?oH;=iAf-xU=Y2y38L4{)r&VER6t|z{pVxq(LdL_!cq`Zli?n8c4%^L@1Axq
zdm5hi9TW_5SCkEbhwr^|3l*cDeX|Ads%H#HbQSBop;~u{2Sr;`Ms9J0sy_Bedu}Nnj8M_I-p9=Xa
zoKmMATH{InmSTklSq|fn#CzIw1d%zMc_<(6rKIC9-d4P~l1Zl#Qt<*M^PM{=+(*d*
z=XnYjDp};bLGmCa`#D@8EncK#v2!t1^;NRO*+T9iN)B^|liN?p5zZX=A0J@9!=4y4
z+PRk8V*4W@$2k%>ZJ^d@qQjro;zN`?#<`2+Fq`&5gQhvxv+M|48f(xjXC$jI(oPF^
zw$n;CN^P#%6dH7_b2f#?*nF`CLGB!eCyaYR?wlf$)9pV<*`*F2^~Yx@xxzV%P8a$
z{49Q-=|2aG?nSx0NFj2Qbd)N)e;t3Adpmf^5`Qj&+;K4NhJi@9BGm`QtkffD1q8Xn
zUk!2>Zs3PuJ-?4XSVZ0`3O6JkL^|9=T^KfrYoIuM(b>>~QImK8O2TbF$6rM6Nj!j>
zhc7l%G64}pb2Ln-0&>24SmqH~I+sHfXEur!gms88xw2CNtiJ7QU_}n2v6(x8R8{RfisD6pNQ1$SR
z3ZaS<43HJRfWt5}sKn~E66);1knhb@?`r%(bF$^~BIS~%>%F!I#YjTnB0$_oHBgFv
z`;@UQdb0^2dL{X+iI2~t)#cwo{>$XEKyRi{>J32LIP+@?u)014s`~@7Sa*9L%SuI*
z)f2e|YzSMjp>hO>UTh4X9u@;@3R!G(AB!YdEr2+uqrAw8NMcl@h5Fo#q!aCx_#PNh
zsR?^DNveQ6h5*9kW+U}3>Kg5{1DP@Yl=TRTBUDs^ubV}SbdE|aLvHk7Lq!rlWRbq_
zLxO`X3N6t?4Am`>MwO%e43$jmV7dOUi)0TgMCH*#`O9@|5p3;1K0-w$KBm5bv`#Pi
z16Op=t>R_A6{1jd@K9vNF2kQ!kdIJNiQ}nin6YCe7Lgims8C`$WTJ<&p;^xmi$q79
zObt)t&q(--P*Fz1sDOsi0S#rI1{R5qQ8s|
ziT2H^&y2V&rZtmRi0Yze@|Vomv-oo&h8{vi8SPt58EuQRy-`4+=(*o#nF-x69f3rs
zC{t#8pv(?K>2Y|zJ8OtX7Z`nx@#sQB!6T}RUi1>Q7oG*}_BA*r>|e`thnBF;;~#7X
z@q=IcX-=dgNd6oN`)QU~O?F;{t`+{68YY0Ye4U52g
z3OirhFdA;Ah7U-JhMQSJUeL~qa6lEx53=%>&R2{N5amMZd_mG^_%bzILQ*t*nI-t@
zCw$-#FO;S4@ahxZyAln2#p8YKz0mzeLjg5RAt@RPSfT}F5k8l(?81F03uT;{3kz`e
zuzAY0?-gYh#LmOc^@xqKd#LOglA`P$mPjHC8aRdvms7*X)Np}l*acCF&p?*Za6UEg
z^4MrNpCzsV2@RYn3a_SyXE_8`nkGT%)!;wGA~G~ip$1-w7!9Ye#1Ql&G;nS$e2y9h
zq8LIU4@Pz)L>Xh}6v!A2^QhrMl2VI#Eb$|wfpdRhKmJbp6k5@qZrTC78tm_}i1;v#
z8j9hi(J+lAR)d5OJpUA)N)3NwEyf!kQ1WT)TyfZF7)K3!N!4f=#}d6@92$5IEc_ZZ
z{1`>-cGC_>&H`g8WQ>Mg)Nl?-sl_gqc))1j{CV(m)NlrC(M>eieZ}=Si}jTvaf+C6
zkk|*)u+16#5U!K=O|W>f_L189t4lt004mmc~zkUxY-@%yv^ujokO&uQxSI6~|#
zVk#eIc|w6>Bh%F5^ad$xb}Y9w)ai`xGa47JLQ@W5OR;rBZ|NrKmKhP^pdlHAt;c{xMig*+$>zquKbh4b&H$WF*29
zKtHynZs!5rm@Kn%W4?ely9@qa@M^l?^Muls{=MLz-bHzy46f{gFY|jBe9qoo`VW3r
z{&D8*if>`w=&JsWpTXaI0Db}L#EsLÐtyvEB3Be&Zyy&ds0EJukQ4II~>S2_IP&
znjD8>$Cx>+r$3wsWd}-LyWrtS+tzYIsbpsyB8wp#f4xmhMTkSO+g1fZOC__V_;^J&
zUi`FUr(eX&P1+&yqR8(TW#u^(N)VsI4hINbh(;*-xQJE|R21h;v+V`Eh@Bn~UovTj
z$crk!2YbnrymrBENW%jHBe_$QIMHMiy3i1zraTd?AgG2UalFYUs0Pnp9$AaA(_dnR
zNjpSd!ukEBEWfY`p~Z-2V28g16Eh~`5LwLElfF_BmO5S76$CAn%$D+caxd5~VwZLV
z`lB52!qD#*WkZsOb_90A&UOU!kZiOg@OYC==t4t;8hDbxXd|eGB#{pWkxftyUOTQr
zUKMuwORP3&hseuNzrU0{Px9IYFG3pr5-ySKj6-BGUpx9rMOgX*VOJ2eR5Dx2Ye&v(
zd_+mVh+&g<@v=K
zwH-VCBJx2R(hiZ=$$q~md%NV}NCiHH9S#t>5RFjuaS^Q`sHoRtdy)4dc6va3$)p`3
zue1FgP&Ooa7-7I}*x>=8hh$@f0a?t~GQLs~mWm0xf}o|6*-~E1@LaJGJN+W^n+moJ
zkyr12zbJc|Y{TqoHXhbVzHvvaGjRD`AFZEvfBprw-8Ql4KtNAX(+`b7+z
zv_s@Qf!{C64wO8MB;euL;TNG)vN4i?D@-<_3k?x!7%ZX{1l5ova!nZ=kp$J?^)Jtv
z8?j3}0-H_RA@UBy?=NL9lRUH|@LKF_N5FNGjdlb+VzLQcXoyh5l_FX}Pz_1q!zP=c
z8a#h_4u26l{UyF+(hiaLJAQvD8{Df@(+-
z$D3?|YViE!HN|4=^q088q#YvfmHhtlI^%l7j}UJ#X@|(0q+HpDgx_uv<(nL9IiU;D
z2t_}|j?q9+QO{f6RLNI9)*_sBW#h$7PchySA@ZXiRK_9lcFOM*WqC);sgZazb~HF)
ziezUT;#W*Ip$iQWY8Wq~6$I6gBwlN>397-XLM`&P3EQgz&sF%3?adyzy2FE=&-kQm
zn~HqK$950rYU=RiV+;>ZXseTN3bWtr&FxIc7Yw9L`TDKpvq~QD^TNJp3sb?4A55O&
z@z&Nhx1^g6__gPCIfB0LOtYTv%@N9K^SM6|H`9UkHi1C0T543_0H1E|RrZX`nlpzOwImHE%`%W^mm&c-)O+>`3f4V*fUF4$rS+=YYBjySsHA
zR*t@CM|pAH7*2)xpD~;cQ2%TUl+{(u>0op@&xB#Ywc2{CvO3dLS=~^V*-&qpMysq#
z*CXPP8>h*O3nvkM_-lKY|cMoW*z3Rf9&OrnTvo)mvH+Wv{Zbv8o2~jR<3`4C6gnqt-QSNRL`qRa3Qb
z6du7fH>_zP;zMjRBOGuJZ%%K_r0c73xJzThjz3(OSjAv%ske?@u&j7y@wn2m(lNzj
zMvtCQR#rB?cvxdox+z_k#(Xinc-XA;>e{M$ktrKFrffJnuBmoYRZH4xSbbWf7x_#2
zlg(j<$brU5$CHZp*}5EUY!%;t>UjL3*T-fLZyCus(>2TM{4P#u1G6`(s@G>4O@~y<
zP?w{;KD{}|s{8f2@9=<9bUSr-G1IcU+4b)6V8*ZSbmj}`g&v+T4%PK!I~vUiThj=eiA<773Fzdr5h@Z(MVtgN9~*2rY?v>>Xqx}K;jz+nr8Vi*nYESwVpy!Es`|A!)K%HPB}f)7D-Okuhcgx~zGa(+zy2$e
ze3NbAllwqCqbDYsZ@deU&+@#k!LJk6V5M<8F57z^Z#ru=8gjfM>MyBqa=
z%a`FMXF$MBQsvI-)QkF9KUd#sq}?(|TIck|uaV}Gkfg{FPsQ%nw*vZDkos`R@9AqW+4yU=i*bp0
zp|7B8Yb)4pnvw-WP*0y-mv;tuzT(!3@@zeD5$xH$3~9Fvl2+egmQ~DzZZ7W<(0+ZZ
zppRpT^}wf*p1%Lr-nBqiRh{W`AK^xb4G79x4-ga;LK32;feJ|o66K*7Fcu|Tk{c39
z?v3}}pjdo@ZBu+;arGs`=(L?WRj0Ie6fKJpVfmca&S)JUU0sZOt
z#@DwP#~)X_Ss8ep_0tEoleMQ$x+jp%@2n1dj+p7AjAy!6eF<$kqOVz<1?6~~ivTWM
zV!hc9h-?$v=izmBUWi*IP&TY^V)ea_-6d(;Yax-um`_pamLwqR*e5H
zxOLP=J8C^>biT7<{F}g)I8J;=MZOQn18K|0_ixrwo{NC&J1M501m5FIKOfw_b7FiO
z+nOmhTIU_i>JSe5PdMxkl7F=JyJ?eTPJSZ}o}a2X5abG5*)!_T3SA?^`GT^>_fY
zJB-duyhu3Tw1LLZD9MN1axzKga^COh1!F(-hQ!{u^-JuVGciunZF&zo>t&=jai(v;
zdmIz~A{O>ufivx5%F!qCFf&L~0Xr=u(VY{$(PT2Z&Kw~-we{6y
zU<+92Q@BJqK@5Pjc|+v2j^AZRiNn!lgx^*?Ke}W1A@Q;3R+K9yBK$fc2Eew9?tN6M5G&o^Ot<4a1oL6
z;*SV-Df|#|BH95H6Y47_LVgL5Hkdw3UW98NaWo!&E1Wi17=9kEk4%4=a0L;1t^-nj
z3pvsuxp{BEQT?zsk}$*@8%e+kOb0w$h^e6AvxW173x)N<<-!(Whmie<`aUDPLwL84
z3*{L9bs_s3`45E83V$ekLwG>=fskV~Ge6MmWq9gT`_6OW7EDBdl8KN0d@5pGrdLyCVye7pG5;xCK8
zPK5kh!k;PrKNW9mJE1)9i~mXSr{XOT>oL-7@guNJ>V{0ebyludmdM95z+>{9$qir*;S
zExtwk8{*#~LjG~#lZxM|_~*o57XOL(FU5aDg#7P>e^C5i6pznQP5n{A%&*#Jh-)Unjg-@pmZxF7f-s9}s_3{3+pH;eI0Yy(=`ftZ@8>
z;bxNMA4f#ID=Z=+{#?Zyn^xcz;?;^@Mugm_g)xP%CqnP%6uwD#uj21l{5J8giyNC)
z$ma=iwDoSqzpD5i;ftKNAYVLs!gr_MTSRg*-vXbd_y)yaBYva!dhxG_Zx!DmzEk`S
z@t=wx6#tX>D9%@yKau&1&k}DCzefB<@%7?g5#K7lLwu+BkHudTe^1=la6x{!OyWz}
zEb@Mr<-pqvY(SHcr52y9mNM6!QFa0TmzK=9kpD|AEH8K6va$;*DqOmigKw=}FfR~5
zMsfk%%x4+w#?*Ncc#H!#1#fUM!S=bOY(#upziDayhC^d-9ddX0i@STmc`l|b*Y1JI
z6WC6NhPd=-yrUBut|0{?*Xk`-jd7buWBx?Ya28o>tEseu7U!FVBaI
zsM8oW*|2w<$zb`4#%uQ=;Zuz1u6<`y?R&dicsDJ5r}XXa^$=VDJ1%p*Z~6TS*v8K1
z-+Z;F^xq~Nyz}kC`=9;fkJH8e6i*LELv*Jz`F3xHg!9~OsDTPmv*Ecp8~!-7>+#aJ
z4-Bq>uW(~CmKUQ8P<-&=K>C36?V>8rAj{Hs6t<~=k4l{G?ffsT-EZvf85DSd<|<6;
z1K;jrn`G1JOugYyVS4d~Lu1mHqG?St+)@IWf*t1~lC8CakJ6}xd7)z(WjpA5agQ}&
zlRX{>csw?p&U!sW^{_$^wuTODhGV;Tn~ZuLNR#KJUU||sz`*$)ICZn%;rQd|kJxl=
z{+(~9m)thfNiVc{6&7xM1xiuD!i~=vk5|dUduXJUnVMogeGzlM28Y;J-VJ+4EI0it
zqbz*^TdKsiRN*~)ZGq=`p0HPGS$6OgbboM^?NNBoomL(1?pSwE-2#}7=%w-~72eX2
zsUQt4JT;YCSxNTeUJ89@)c&dHc7DF54}bnIz2Xl%0IfNfYk^z~H@pIiAo4xy&BtS(*>6y}a3I^rL;bdqhm|`tg?w6X6UoD^
z4dfAh6d28!lQ9nTv|$jSw9gX+q)iP8S^!IiHEo
z5FHh{ma0aIj*ILe9VO~U#xwC4(W1ymY91>(B|-~)dE-Q`_?=+
zu+h-+$Trf6s!>IxkcrP0ofUbHu~PyGKycEW2w!66P30z=pmQU)Gx4-Qm7((@XEU}q
zK$9u3oE)Lu&%Ck#mngz=a)e6@@@58ZH;ETSxa)CVRe+5foKzp-0>!*)(T2!K(zz+v>K8W?3fi^A3d&1a<&3n?Tu`}duw)76K!r>tc
znS7^r1Zg|@67uka&{V*pQst?4;U7b}9J64%KXir@{t}`>rF@GCv!L*nu{k~w!7<1W
zo@a~*2hXQLW^|AtUnfrWSa8ViQIOy?kA;VfAuFc#;G{uL_`gY~KL=W9R%P;R2uu%L
zfPlczw~60p=8Q0QP4>YTxXS2o;k^VZF9V)F
z8_5F8SmYZ(&uDW3_fLlBVf;oeXNDUNB9FXK&nN`^kpVaV*$WtffXxi(4C3@g3cQvd
zX;zaqN4x->#9;9uabG7|u=Gm;-G1h#OiS#Hk>H>wF41pb4;6If@i
z#N}5qT%j_$0&%vkfhl7aP-OHK3Pc&5z~tc!%!iP4Pb~0s^AsKXbLt+)be{;gP|7ie
zOM%Cwu$qUtv1LZnz6x{Upc5FOTpm~8dw~yry|LcpP-`|qItu1u^`=P711t*>n
zDtbM%^!?Cz`A>(I%?h1Y+!b2-Xz=XOp;h?}=}+AUed$o`>!HEXdRFM-;!t%ubZT&7AXL^8{1h5|X?#sQaYNj#
zO(x?Br*6@*ss(j(-5PvG9gnrwHM^6Woyn=elT-MQze?AT!PW~z94W4dHRi*4?*o=<
zv}vVVa^vKZ@*AgGb(1DHyZxgbn#bVj*n@MFCvIO?vv^@+ZM?ZNfiFgu#G*~DvF1uQ
zo^bIounBWpqbYY)EEae12?}HTD4={zqP@K>)s~1?x-j|Rd9!lOv2?5{-A_<@D1TKV
z*}SkVm1>Kxu5>%vQXSEBQ>&Y3aXay)bu0~~U2)h6Nx4&M7guxbkI$L>TVqXYQe7R$
zUOv~X2lFL6te5h06Y=!Ycr$WHN8_k|rtZy&SSo%_+U?3jy5=)wpEk;SAK0J
zzTbwG5I5e{fpuwKsa+^`t7MKkdsl<5j21
z@MHDlMG1~h34Rv&k+}K>x4J8}?jzAfCG+a$Ep`_r(r#@>XZj;h
zYxLE(b;M|z;3IHGpJ~CVZd-h9w7sp_onPX%#-bQcrlk6eRv(_>K>9L{s4vLF^;oi=mbV^?hFW|)(Cvw;3nuwzm>cVU%L
z6_HJ^7q%8q|i
zk9SxQB4T)U5`p;kUK`^LBUs9Z+Xhg~*K_WY0K
z_lB9&{Ahd2ysq~4N^_Gk&ASUp;YO^z#ce_OK-G7A@&m|5+dE+4>+sUJFGc>Cp4BAc
zEp4m2(Cd7+PZ%>eYBgoz1}MSFZogdqCpM)y+3i=;TH08arFPvM(_GwnYm_pmze=N`v5_dUzG5k
z094{B0iOgM%QeN5PtU_65}bNTn(Tv3)#hWWKj$i$@vk$QOs6l!#+4t
zTb}Ixm&^a-J$~elU+(zfq5J?N^U($6`p?PjKQ*m08g<`ZiRbj*`;1*pUFa%&1A;{(nT{5Q_U{|Wd}6>*a1&nI#zf?t)3u&E~gK7%#zN1V&I
zgu4p1gh~1eG$M?TAhGGjM!+{c?_+>pdtPoiMIj_WfN^XGuBKvvh*x@kv*Q$3VfYL5
zL&R|#Cx3lFCzxcY4{(y_&nI%Ngd5>ydx^a0+M#4!zhZvR%+%868lLeQmc$q;;j^(kg
z1&5#$zX$Q#j-PcrG(X0VyM68Rg>!o?ZUxI4vu@ULCC@he*j8*2>)22|_}NzaIsEV9
zXC0f0i+*f7&49nsCvPpYXAF*;{SL760``l@HbT~-I>JmVVG9TUE)7ks*<}u%m3Uem
z?PVrEYfrzI!F(Ac&&E>F+77i=%QL0JDgYSLzrG8$=Aqs*fp2p$alS1syrSZuu^#ql
z`>p+3tN)pLvOCzs4%&b#LL6^*1Yh--Uq>{#278W}Win2$`t-Ms&-9)NRkrPsEdP63
zQyh=w{sA_3@E$dq`eeE`UZ^zI*DhIzeLb{|K*mz6+4v%}g#+I*V2=TmJQZCVlUe;t
zJxoi3`S!{%TXUFwGSoIHG~f(ht7RGq?TUtLO(fHJHiLt>HqAF4_EjAp)Qu?a}Y*-H1cKj
zaXqJB-y9sEf%X-6xKFx^=Xz~`VB@TgZ-DvpEo#WNGfe+x^4$r)m7#)1pwFd8&c^Kk
z_v@PqeeCP3$8h{?Jzj?2%E0Tq41EvMBWL5@1gD?Ujg>etP45D
zoLnX#WOkp(Q0N<#CGdr?Tf;vng!gE)i~j`B#gF%mtN4EnyEZ
z=wb}Pv0^^MflNPMyod<>=ZTjHtALbiAfM>j&u4kN$bsETcMsD|(nnIz|1E|?-}i_`
z-n@Xghw0F5rV~-qiD;SRNe42>hDPZs%
z+*p!N#5_ac{O*PEj}npo`#`4SCs8cd^TJmdj`F=pJ`ww?5+V1#(0qFWd48Ng`Qbpy
zj}r2G7s_)xWXhKlAwQc4x%uJ^K*}4t=BW2Nh6B5WUlk6*aSLFs#Nq6)cJW8+c@A&_
z(*co{!D+&B;Y?w*uuh1nf=O@YLXeM%oBjuG`XBHPh2Jgwn(&*#$AsoukM!mm4K)1_
zxL@%cV_41zk2mlP;bdXCutvB<7!`I3IVMq_{g3!J!bgQa5WXaQQ}`<(zks3~`x)_c
zVUe&(xIkDhTqW!jephIo5<$-^;(TyHz5HN|_y=J=k1x3CH^9l_WjgM2h)BzC^oXY4
z;8Jo0InX>8g4}AwuMs8`&;2B*{}%C0Lhc8{@U2Ajw}-?Z6aSw0F7Z9$uZX`U-Xs1C
z@!yDlAa3mH!+&bn%WotR_251h#IuN~hq1GdOCa~N2mlu-d
+
+#include "initHooks.h"
+#include "epicsExport.h"
+#include "iocsh.h"
+
+
+static void trace(initHookState state) {
+ printf("iocInit: Reached %s\n", initHookName(state));
+}
+
+int traceIocInit(void) {
+ static int done = 0;
+ if (done)
+ return -1;
+ done = 1;
+
+ initHookRegister(trace);
+ puts("iocInit will be traced");
+ return 0;
+}
+
+
+static const iocshFuncDef traceInitFuncDef = {"traceIocInit", 0, NULL};
+static void traceInitFunc(const iocshArgBuf *args) {
+ traceIocInit();
+}
+
+static void initTraceRegister(void) {
+ iocshRegister(&traceInitFuncDef, traceInitFunc);
+}
+epicsExportRegistrar(initTraceRegister);
diff --git a/Trbnet/trbnetIoc/trbApp/src/initTrace.dbd b/Trbnet/trbnetIoc/trbApp/src/initTrace.dbd
new file mode 100644
index 0000000..8083c0a
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/initTrace.dbd
@@ -0,0 +1 @@
+registrar(initTraceRegister)
diff --git a/Trbnet/trbnetIoc/trbApp/src/scalerN.c b/Trbnet/trbnetIoc/trbApp/src/scalerN.c
new file mode 100644
index 0000000..909799d
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/scalerN.c
@@ -0,0 +1,121 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+long scalerN_init( struct genSubRecord *pgsub )
+{
+ return( 0 );
+}
+
+long scalerN_proc( struct genSubRecord *pgsub )
+{
+/* BK this routine performs the scaler summing and profiles for a up to 16 channel array */
+ long *ptr[16], *out[19];
+ int nelm,iscal,jchan,nscal;
+ long totsum,sum;
+/* long sum_arr[100];
+ float pos_arr[100];*/
+ float pos;
+ float *pos_out;
+
+ ptr[0]= (long *)pgsub->a; /* input arrays*/
+ ptr[1]= (long *)pgsub->b;
+ ptr[2]= (long *)pgsub->c;
+ ptr[3]= (long *)pgsub->d;
+ ptr[4]= (long *)pgsub->e;
+ ptr[5]= (long *)pgsub->f;
+ ptr[6]= (long *)pgsub->g;
+ ptr[7]= (long *)pgsub->h;
+ ptr[8]= (long *)pgsub->i;
+ ptr[9]= (long *)pgsub->j;
+ ptr[10]= (long *)pgsub->k;
+ ptr[11]= (long *)pgsub->l;
+ ptr[12]= (long *)pgsub->m;
+ ptr[13]= (long *)pgsub->n;
+ ptr[14]= (long *)pgsub->o;
+ ptr[15]= (long *)pgsub->p;
+
+ out[0]= (long *)pgsub->vala; /* output (0 - 7) A to H are for sums of input arrays*/
+ out[1]= (long *)pgsub->valb;
+ out[2]= (long *)pgsub->valc;
+ out[3]= (long *)pgsub->vald;
+ out[4]= (long *)pgsub->vale;
+ out[5]= (long *)pgsub->valf;
+ out[6]= (long *)pgsub->valg;
+ out[7]= (long *)pgsub->valh;
+ out[8]= (long *)pgsub->vali;
+ out[9]= (long *)pgsub->valj;
+ out[10]= (long *)pgsub->valk;
+ out[11]= (long *)pgsub->vall;
+ out[12]= (long *)pgsub->valm;
+ out[13]= (long *)pgsub->valn;
+ out[14]= (long *)pgsub->valo;
+ out[15]= (long *)pgsub->valp;
+ out[16]= (long *)pgsub->valq; /* output (16) I are for across sums of input arrays*/
+ pos_out= (float *)pgsub->valr; /* output (17) J is for weighted mean of inputs, array of same length*/
+ out[17]= (long *)pgsub->vals; /* output (18) K is profile array, dim max 16*/
+ out[18]= (long *)pgsub->valt; /* output (19) L is total sum of input arrays*/
+
+ nelm= pgsub->noa;
+ nscal= pgsub->nou;
+ totsum=0;
+ for(iscal=0; iscala;
+ ptr[1]= (long *)pgsub->b;
+ ptr[2]= (long *)pgsub->c;
+ ptr[3]= (long *)pgsub->d;
+ ptr[4]= (long *)pgsub->e;
+ ptr[5]= (long *)pgsub->f;
+ ptr[6]= (long *)pgsub->g;
+ ptr[7]= (long *)pgsub->h;
+ ptr[8]= (long *)pgsub->i;
+ ptr[9]= (long *)pgsub->j;
+ ptr[10]= (long *)pgsub->k;
+ ptr[11]= (long *)pgsub->l;
+ ptr[12]= (long *)pgsub->m;
+ ptr[13]= (long *)pgsub->n;
+ ptr[14]= (long *)pgsub->o;
+ ptr[15]= (long *)pgsub->p;
+
+ for(jchan=0; jchan < nelm; jchan++)
+ {
+ sum = 0;
+ pos = 0.;
+ for(iscal=0; iscal 0 )
+ pos = pos / sum;
+ else
+ pos = (nscal-1)/2.;
+ *(out[16]++) = sum;
+ *pos_out++ = pos;
+ }
+
+ return(totsum);
+}
+
diff --git a/Trbnet/trbnetIoc/trbApp/src/scaler_rat.c b/Trbnet/trbnetIoc/trbApp/src/scaler_rat.c
new file mode 100644
index 0000000..9da954a
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/scaler_rat.c
@@ -0,0 +1,49 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+long scaler_rat_init( struct genSubRecord *pgsub )
+{
+ return( 0 );
+}
+
+long scaler_rat_proc( struct genSubRecord *pgsub )
+{
+/* BK this routine performs the scaler ratios */
+ long *ptr[2];
+ int nelm, jchan;
+/* long sum_arr[100];
+ float pos_arr[100];*/
+ float pos, sum;
+ float *pos_out; /* ratio output */
+
+ ptr[0]= (long *)pgsub->a; /* input arrays*/
+ ptr[1]= (long *)pgsub->b; /* divide A by B */
+
+ pos_out= (float *)pgsub->vala; /* output (1) A is for ratio of inputs, array of same length*/
+
+ nelm= pgsub->noa;
+ for(jchan=0; jchan < nelm; jchan++)
+ {
+ sum = *(ptr[1]++);
+ pos = *(ptr[0]++);
+ if( sum > 0 )
+ pos = pos / sum;
+ else
+ pos = 0.;
+ *pos_out++ = pos;
+ }
+
+ return(0);
+}
+
diff --git a/Trbnet/trbnetIoc/trbApp/src/sncExample.dbd b/Trbnet/trbnetIoc/trbApp/src/sncExample.dbd
new file mode 100644
index 0000000..df61066
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/sncExample.dbd
@@ -0,0 +1 @@
+registrar(sncExampleRegistrar)
diff --git a/Trbnet/trbnetIoc/trbApp/src/sncExample.stt b/Trbnet/trbnetIoc/trbApp/src/sncExample.stt
new file mode 100644
index 0000000..235f3f4
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/sncExample.stt
@@ -0,0 +1,22 @@
+program sncExample
+double v;
+assign v to "{user}:aiExample";
+monitor v;
+
+ss ss1 {
+ state init {
+ when (delay(10)) {
+ printf("sncExample: Startup delay over\n");
+ } state low
+ }
+ state low {
+ when (v > 5.0) {
+ printf("sncExample: Changing to high\n");
+ } state high
+ }
+ state high {
+ when (v <= 5.0) {
+ printf("sncExample: Changing to low\n");
+ } state low
+ }
+}
diff --git a/Trbnet/trbnetIoc/trbApp/src/sncProgram.st b/Trbnet/trbnetIoc/trbApp/src/sncProgram.st
new file mode 100644
index 0000000..1ba2989
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/sncProgram.st
@@ -0,0 +1 @@
+#include "../sncExample.stt"
diff --git a/Trbnet/trbnetIoc/trbApp/src/trbHello.c b/Trbnet/trbnetIoc/trbApp/src/trbHello.c
new file mode 100644
index 0000000..4933b6b
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/trbHello.c
@@ -0,0 +1,31 @@
+/* Example showing how to register a new command with iocsh */
+
+#include
+
+#include
+#include
+
+/* This is the command, which the vxWorks shell will call directly */
+void hello(const char *name) {
+ if (name) {
+ printf("Hello %s, from trb\n", name);
+ } else {
+ puts("Hello from trb");
+ }
+}
+
+/* Information needed by iocsh */
+static const iocshArg helloArg0 = {"name", iocshArgString};
+static const iocshArg *helloArgs[] = {&helloArg0};
+static const iocshFuncDef helloFuncDef = {"hello", 1, helloArgs};
+
+/* Wrapper called by iocsh, selects the argument types that hello needs */
+static void helloCallFunc(const iocshArgBuf *args) {
+ hello(args[0].sval);
+}
+
+/* Registration routine, runs at startup */
+static void helloRegister(void) {
+ iocshRegister(&helloFuncDef, helloCallFunc);
+}
+epicsExportRegistrar(helloRegister);
diff --git a/Trbnet/trbnetIoc/trbApp/src/trbHello.dbd b/Trbnet/trbnetIoc/trbApp/src/trbHello.dbd
new file mode 100644
index 0000000..64eb038
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/trbHello.dbd
@@ -0,0 +1 @@
+registrar(helloRegister)
diff --git a/Trbnet/trbnetIoc/trbApp/src/trbMain.cpp b/Trbnet/trbnetIoc/trbApp/src/trbMain.cpp
new file mode 100644
index 0000000..53f92aa
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/trbMain.cpp
@@ -0,0 +1,23 @@
+/* trbMain.cpp */
+/* Author: Marty Kraimer Date: 17MAR2000 */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "epicsExit.h"
+#include "epicsThread.h"
+#include "iocsh.h"
+
+int main(int argc,char *argv[])
+{
+ if(argc>=2) {
+ iocsh(argv[1]);
+ epicsThreadSleep(.2);
+ }
+ iocsh(NULL);
+ epicsExit(0);
+ return(0);
+}
diff --git a/Trbnet/trbnetIoc/trbApp/src/trbSub.c b/Trbnet/trbnetIoc/trbApp/src/trbSub.c
new file mode 100644
index 0000000..17abe5e
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/trbSub.c
@@ -0,0 +1,615 @@
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+int mySubDebug, trb_inited=0;
+
+int oepVoltage[8][6][4][16]; /* voltage, sector, plane, mbo */
+
+/*static uint16_t tcp_port = 55555;*/
+/*static void atexit0(void *arg);*/
+
+static long mytrbInit(aSubRecord *precord)
+{
+ if(trb_inited == 0) {
+ if (mySubDebug)
+ printf("Record %s called mytrbInit(%p)\n",
+ precord->name, (void*) precord);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet %d\n", trb_errno);
+ trb_inited = 0;
+ }
+ else
+ trb_inited=1;
+/* install exit handler
+ epicsAtExit(atexit0,0);*/
+ }
+
+ return 0;
+}
+static long oepInit(subRecord *precord)
+{
+ if(trb_inited == 0) {
+ if (mySubDebug)
+ printf("Record %s called oepInit(%p)\n",
+ precord->name, (void*) precord);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet %d\n", trb_errno);
+ trb_inited = 0;
+ }
+ else
+ trb_inited=1;
+ }
+
+ return 0;
+}
+
+static long mytrbUid(aSubRecord *precord)
+{
+ uint16_t trb_address;
+ int status;
+ uint32_t uidBuffer[4];
+ if(trb_inited == 0) {
+ status = sleep(3);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet\n");
+ trb_inited = 0;
+ precord->val = -1;
+ return -1;
+ }
+ else
+ trb_inited=1;
+ }
+ trb_address = *(long*) precord->a;
+ if (mySubDebug)
+ printf("Record %s called mytrbUid(%p) A=0x%X\n",
+ precord->name, (void*) precord, trb_address);
+
+ status = trb_read_uid(trb_address, uidBuffer, 4);
+ if (status == -1) {
+ printf( "read_uid failed: %d %s\n",trb_errno,
+ trb_strerror());
+ trb_inited = 0;
+ } else {
+ printf( "0x%04x 0x%08x 0x%08x 0x%02x\n",
+ uidBuffer[3],
+ uidBuffer[0], uidBuffer[1], uidBuffer[2]);
+ *(uint32_t *)precord->vala=uidBuffer[0];
+ *(uint32_t *)precord->valb=uidBuffer[1];
+ *(uint32_t *)precord->valc=uidBuffer[2];
+
+ }
+
+ return 0;
+}
+static long mytrbRead(aSubRecord *precord)
+{
+ uint16_t trb_address, reg_address;
+ int status, count, i;
+ uint32_t data[2048], *outpa, *outpb;
+ if(trb_inited == 0) {
+ status = sleep(3);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet\n");
+ trb_inited = 0;
+ precord->val = -1;
+ return -1;
+ }
+ else
+ trb_inited=1;
+ }
+ trb_address = *(long*) precord->a;
+ reg_address = *(long*) precord->b;
+ count = *(long*) precord->c;
+ outpa = (uint32_t *)precord->vala;
+ outpb = (uint32_t *)precord->valb;
+ if (mySubDebug)
+ printf("Record %s called mytrbRead(%p) A=0x%X\n",
+ precord->name, (void*) precord, trb_address);
+
+ status = trb_register_read(trb_address, reg_address, data, count*2);
+ if (status == -1) {
+ printf( "read_register failed: %d %s\n",trb_errno,
+ trb_strerror());
+ trb_inited = 0;
+ return -1;
+ } else {
+ if (mySubDebug) printf("trb 0x%04x reg 0x%04x status %d data %d\n", trb_address, reg_address,
+ status,data[0]);
+ for (i = 0; i < status; i += 2) {
+ if (mySubDebug) printf("0x%04x 0x%08x\n", data[i], data[i + 1]);
+ *(outpb++)=data[i]; /* address */
+ *(outpa++)=data[i+1]; /* data */
+ }
+ if( status <= precord->novb) {
+ precord->nevb = status;
+ }
+ else {
+ precord->nevb = precord->novb;
+ }
+ if( status <= precord->nova) {
+ precord->neva = status;
+ }
+ else {
+ precord->neva = precord->nova;
+ }
+ precord->val = status;
+ }
+
+ return 0;
+}
+static long mytrbReadMem(aSubRecord *precord)
+{
+ uint16_t trb_address, reg_address;
+ int status, count, i, option;
+ uint32_t data[5010], *outpa;
+ if(trb_inited == 0) {
+ status = sleep(3);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet\n");
+ trb_inited = 0;
+ precord->val = -1;
+ return -1;
+ }
+ else
+ trb_inited=1;
+ }
+ trb_address = *(long*) precord->a;
+ reg_address = *(long*) precord->b;
+ count = *(long*) precord->c;
+ option = *(long*) precord->d;
+ outpa = (uint32_t *)precord->vala;
+ if (mySubDebug)
+ printf("Record %s called mytrbReadMem(%p) A=0x%X\n",
+ precord->name, (void*) precord, trb_address);
+
+ status = trb_register_read_mem(trb_address, reg_address, option, count, data, count*2);
+ if (status == -1) {
+ printf( "read_register_mem failed: %d %s\n",trb_errno,
+ trb_strerror());
+ trb_inited = 0;
+ return -1;
+ } else {
+ if (mySubDebug) printf("trb 0x%04x reg 0x%04x status %d data 0x%08x\n", trb_address, reg_address,
+ status,data[0]);
+ for (i = 1; i < status; i++) {
+ if (mySubDebug) printf("0x%04x 0x%08x\n",reg_address+i-1, data[i]);
+ *(outpa++)=data[i]; /* data */
+ }
+ if( status <= precord->nova) {
+ precord->neva = status;
+ }
+ else {
+ precord->neva = precord->nova;
+ }
+ precord->val = status;
+ }
+
+ return 0;
+}
+static long oepReadVoltage(subRecord *precord)
+{
+ uint16_t trb_address, reg_address;
+ int status, count, i, iv, is, ip, im;
+ uint32_t data[2048];
+ /* int oepVoltage[8,6,4,16]; voltage, sector, plane, mbo */
+ if(trb_inited == 0) {
+ status = sleep(3);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet\n");
+ trb_inited = 0;
+ precord->val = -1;
+ return -1;
+ }
+ else
+ trb_inited=1;
+ }
+ trb_address = 0xFFFD; /* OEP broadcast */
+ reg_address = precord->a;
+ iv = precord->b; /* voltage number (0-7) */
+ count = 384;
+ if (mySubDebug)
+ printf("Record %s called oepRead(%p) A=0x%X\n",
+ precord->name, (void*) precord, trb_address);
+ for (is = 0; is < 6; is++) {
+ for (ip = 0; ip < 4; ip++) {
+ for (im = 0; im < 16; im++) {
+ oepVoltage[iv][is][ip][im] = -1;
+ }
+ }
+ }
+ status = trb_register_read(trb_address, reg_address, data, count*2);
+ if (status == -1) {
+ printf( "read_register failed: %d %s\n",trb_errno,
+ trb_strerror());
+ trb_inited = 0;
+ precord->val = -1;
+ return -1;
+ } else {
+ if (mySubDebug) printf("trb 0x%04x reg 0x%04x status %d data %d\n", trb_address, reg_address,
+ status,data[0]);
+ for (i = 0; i < status; i += 2) {
+ if (mySubDebug) printf("i: %d 0x%04x 0x%08x\n", i, data[i], data[i + 1]);
+ ip = (data[i] & 0x0300) >> 8;
+ is = (data[i] & 0x0070) >> 4;
+ im = data[i] & 0x000F;
+ if (mySubDebug) printf("iv: %d ip: %d is: %d im: %d \n", iv,ip,is,im);
+ if(is < 6) oepVoltage[iv][is][ip][im] = data[i + 1];
+ }
+ precord->val = status;
+ }
+ if (mySubDebug) printf("return from oepRead\n");
+
+ return 0;
+}
+static long oepGetVoltage(subRecord *precord)
+{
+ int iv, is, ip, im;
+ /* int oepVoltage[8,6,4,16]; voltage, sector, plane, mbo */
+ iv = precord->a; /* voltage number (0-7) */
+ is = precord->b; /* sector number (0-5) */
+ ip = precord->c; /* plane number (0-3) */
+ im = precord->d; /* mbo number (0-15) */
+ precord->val = oepVoltage[iv][is][ip][im]/1000.;
+ return 0;
+}
+static long mytrbWrite(aSubRecord *precord)
+{
+ uint16_t trb_address, reg_address;
+ int status;
+ uint32_t data;
+ if(trb_inited == 0) {
+ status = sleep(3);
+ if (init_ports() == -1) {
+ printf("error connecting to trbnet\n");
+ trb_inited = 0;
+ precord->val = -1;
+ return -1;
+ }
+ else
+ trb_inited=1;
+ }
+ trb_address = *(long*) precord->a;
+ reg_address = *(long*) precord->b;
+ data = *(long*) precord->c;
+/* if (mySubDebug)*/
+ printf("Record %s called mytrbWrite(%p) A=0x%X R=0x%4x d=0x%x\n",
+ precord->name, (void*) precord, trb_address,reg_address, data);
+
+ status = trb_register_write(trb_address, reg_address, data);
+ if (status == -1) {
+ printf( "write_register failed: %d %s\n",trb_errno,
+ trb_strerror());
+ trb_inited = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+static long scalerN_init( struct aSubRecord *pgsub )
+{
+ return( 0 );
+}
+
+static long scalerN_proc( struct aSubRecord *pgsub )
+{
+/* BK this routine performs the scaler summing and profiles for a up to 16 channel array */
+ long *ptr[16], *out[19];
+ int nelm,iscal,jchan,nscal;
+ long totsum,sum;
+/* long sum_arr[100];
+ float pos_arr[100];*/
+ float pos;
+ float *pos_out;
+
+ ptr[0]= (long *)pgsub->a; /* input arrays*/
+ ptr[1]= (long *)pgsub->b;
+ ptr[2]= (long *)pgsub->c;
+ ptr[3]= (long *)pgsub->d;
+ ptr[4]= (long *)pgsub->e;
+ ptr[5]= (long *)pgsub->f;
+ ptr[6]= (long *)pgsub->g;
+ ptr[7]= (long *)pgsub->h;
+ ptr[8]= (long *)pgsub->i;
+ ptr[9]= (long *)pgsub->j;
+ ptr[10]= (long *)pgsub->k;
+ ptr[11]= (long *)pgsub->l;
+ ptr[12]= (long *)pgsub->m;
+ ptr[13]= (long *)pgsub->n;
+ ptr[14]= (long *)pgsub->o;
+ ptr[15]= (long *)pgsub->p;
+
+ out[0]= (long *)pgsub->vala; /* output (0 - 7) A to H are for sums of input arrays*/
+ out[1]= (long *)pgsub->valb;
+ out[2]= (long *)pgsub->valc;
+ out[3]= (long *)pgsub->vald;
+ out[4]= (long *)pgsub->vale;
+ out[5]= (long *)pgsub->valf;
+ out[6]= (long *)pgsub->valg;
+ out[7]= (long *)pgsub->valh;
+ out[8]= (long *)pgsub->vali;
+ out[9]= (long *)pgsub->valj;
+ out[10]= (long *)pgsub->valk;
+ out[11]= (long *)pgsub->vall;
+ out[12]= (long *)pgsub->valm;
+ out[13]= (long *)pgsub->valn;
+ out[14]= (long *)pgsub->valo;
+ out[15]= (long *)pgsub->valp;
+ out[16]= (long *)pgsub->valq; /* output (16) I are for across sums of input arrays*/
+ pos_out= (float *)pgsub->valr; /* output (17) J is for weighted mean of inputs, array of same length*/
+ out[17]= (long *)pgsub->vals; /* output (18) K is profile array, dim max 16*/
+ out[18]= (long *)pgsub->valt; /* output (19) L is total sum of input arrays*/
+
+ nelm= pgsub->noa;
+ nscal= pgsub->nou;
+ totsum=0;
+ for(iscal=0; iscala;
+ ptr[1]= (long *)pgsub->b;
+ ptr[2]= (long *)pgsub->c;
+ ptr[3]= (long *)pgsub->d;
+ ptr[4]= (long *)pgsub->e;
+ ptr[5]= (long *)pgsub->f;
+ ptr[6]= (long *)pgsub->g;
+ ptr[7]= (long *)pgsub->h;
+ ptr[8]= (long *)pgsub->i;
+ ptr[9]= (long *)pgsub->j;
+ ptr[10]= (long *)pgsub->k;
+ ptr[11]= (long *)pgsub->l;
+ ptr[12]= (long *)pgsub->m;
+ ptr[13]= (long *)pgsub->n;
+ ptr[14]= (long *)pgsub->o;
+ ptr[15]= (long *)pgsub->p;
+
+ for(jchan=0; jchan < nelm; jchan++)
+ {
+ sum = 0;
+ pos = 0.;
+ for(iscal=0; iscal 0 )
+ pos = pos / sum;
+ else
+ pos = (nscal-1)/2.;
+ *(out[16]++) = sum;
+ *pos_out++ = pos;
+ }
+
+ return(totsum);
+}
+
+static long scalerN_copy( struct aSubRecord *pgsub )
+{
+/* BK this routine performs the scaler EXTRACTION */
+ long *ptr, *out[19];
+ int nelm,iscal,jchan,nscal;
+
+ ptr = (long *)pgsub->a; /* input array*/
+ nscal= pgsub->noa; /* input length */
+ jchan= *(long *)pgsub->c; /*offset */
+ nelm= *(long *)pgsub->d; /*output length */
+ if (mySubDebug) {
+ printf("Record %s called scalerN_copy(%p) \n",pgsub->name, (void*) pgsub);
+ printf(" nscal %d jchan %d nelm %d \n", nscal,jchan,nelm);
+ }
+ out[0]= (long *)pgsub->vala; /* */
+ out[1]= (long *)pgsub->valb;
+ out[2]= (long *)pgsub->valc;
+ out[3]= (long *)pgsub->vald;
+ out[4]= (long *)pgsub->vale;
+ out[5]= (long *)pgsub->valf;
+ out[6]= (long *)pgsub->valg;
+ out[7]= (long *)pgsub->valh;
+ out[8]= (long *)pgsub->vali;
+ out[9]= (long *)pgsub->valj;
+ out[10]= (long *)pgsub->valk;
+ out[11]= (long *)pgsub->vall;
+ out[12]= (long *)pgsub->valm;
+ out[13]= (long *)pgsub->valn;
+ out[14]= (long *)pgsub->valo;
+ out[15]= (long *)pgsub->valp;
+ out[16]= (long *)pgsub->valq;
+ out[17]= (long *)pgsub->valr;
+ out[18]= (long *)pgsub->vals;
+
+ for(iscal=0; iscala; /* input arrays*/
+ ptr[1]= (long *)pgsub->b; /* divide A by B */
+
+ pos_out= (float *)pgsub->vala; /* output (1) A is for ratio of inputs, array of same length*/
+
+ nelm= pgsub->noa;
+ for(jchan=0; jchan < nelm; jchan++)
+ {
+ sum = *(ptr[1]++);
+ pos = *(ptr[0]++);
+ if( sum > 0 )
+ pos = pos / sum;
+ else
+ pos = 0.;
+ *pos_out++ = pos;
+ }
+
+ return(0);
+}
+static long ctsRegInit( struct aSubRecord *precord )
+{
+ return( 0 );
+}
+static long ctsRegSplit( struct aSubRecord *precord )
+{
+ uint32_t data, *outpa, *outpb;
+ data = *(long*) precord->a;
+ outpa = (uint32_t *)precord->vala;
+ outpb = (uint32_t *)precord->valb;
+ *outpa = 0xffff & data ;
+ *outpb = 0xffff & (data >> 16);
+
+ return( 0 );
+}
+static long ctsRegUnsplit( struct aSubRecord *precord )
+{
+ uint32_t ina,inb, *outpa;
+ ina = *(long*) precord->a;
+ inb = *(long*) precord->b;
+ outpa = (uint32_t *)precord->vala;
+ *outpa = (0xffff & ina) | ((0xffff & inb) <<16) ;
+
+ return( 0 );
+}
+static long ctsRegSplit4( struct aSubRecord *precord )
+{
+ uint32_t data, *outpa, *outpb, *outpc, *outpd;
+ data = *(long*) precord->a;
+ outpa = (uint32_t *)precord->vala;
+ outpb = (uint32_t *)precord->valb;
+ outpc = (uint32_t *)precord->valc;
+ outpd = (uint32_t *)precord->vald;
+ *outpa = 0xff & data ;
+ *outpb = 0xff & (data >> 8);
+ *outpc = 0xff & (data >> 16);
+ *outpd = 0xff & (data >> 24);
+
+ return( 0 );
+}
+static long ctsRegUnsplit4( struct aSubRecord *precord )
+{
+ uint32_t ina,inb,inc,ind, *outpa;
+ ina = *(long*) precord->a;
+ inb = *(long*) precord->b;
+ inc = *(long*) precord->c;
+ ind = *(long*) precord->d;
+ outpa = (uint32_t *)precord->vala;
+ *outpa = (0xff & ina) | ((0xff & inb) <<8)| ((0xff & inc) <<16)| ((0xff & ind) <<24) ;
+
+ return( 0 );
+}
+static long ctsRegSplit8( struct aSubRecord *precord )
+{
+ uint32_t data, *outpa, *outpb, *outpc, *outpd;
+ uint32_t *outpe, *outpf, *outpg, *outph;
+ data = *(long*) precord->a;
+ outpa = (uint32_t *)precord->vala;
+ outpb = (uint32_t *)precord->valb;
+ outpc = (uint32_t *)precord->valc;
+ outpd = (uint32_t *)precord->vald;
+ outpe = (uint32_t *)precord->vale;
+ outpf = (uint32_t *)precord->valf;
+ outpg = (uint32_t *)precord->valg;
+ outph = (uint32_t *)precord->valh;
+ *outpa = 0xf & data ;
+ *outpb = 0xf & (data >> 4);
+ *outpc = 0xf & (data >> 8);
+ *outpd = 0xf & (data >> 12);
+ *outpe = 0xf & (data >> 16);
+ *outpf = 0xf & (data >> 20);
+ *outpg = 0xf & (data >> 24);
+ *outph = 0xf & (data >> 28);
+
+ return( 0 );
+}
+static long ctsRegUnsplit8( struct aSubRecord *precord )
+{
+ uint32_t ina,inb,inc,ind,ine,inf,ing,inh, *outpa;
+ ina = *(long*) precord->a;
+ inb = *(long*) precord->b;
+ inc = *(long*) precord->c;
+ ind = *(long*) precord->d;
+ ine = *(long*) precord->e;
+ inf = *(long*) precord->f;
+ ing = *(long*) precord->g;
+ inh = *(long*) precord->h;
+ outpa = (uint32_t *)precord->vala;
+ *outpa = (0xf & ina) | ((0xf & inb) <<4)| ((0xf & inc) <<8)| ((0xf & ind) <<12)
+ | ((0xf & ine) <<16)| ((0xf & inf) <<20)| ((0xf & ing) <<24)| ((0xf & inh) <<28) ;
+
+ return( 0 );
+}
+static long WatchInit(subRecord *precord)
+{
+ return 0;
+}
+static long WatchReset(subRecord *precord)
+{
+ printf("Watchdog detected timeout\n");
+ kill(getpid(), 9);
+ return 0;
+}
+
+
+/* Register these symbols for use by IOC code: */
+
+epicsExportAddress(int, mySubDebug);
+epicsRegisterFunction(mytrbInit);
+epicsRegisterFunction(mytrbUid);
+epicsRegisterFunction(mytrbRead);
+epicsRegisterFunction(mytrbReadMem);
+epicsRegisterFunction(mytrbWrite);
+epicsRegisterFunction(oepInit);
+epicsRegisterFunction(oepReadVoltage);
+epicsRegisterFunction(oepGetVoltage);
+epicsRegisterFunction(scalerN_init);
+epicsRegisterFunction(scalerN_proc);
+epicsRegisterFunction(scalerN_copy);
+epicsRegisterFunction(scaler_rat_init);
+epicsRegisterFunction(scaler_rat_proc);
+epicsRegisterFunction(ctsRegInit);
+epicsRegisterFunction(ctsRegSplit);
+epicsRegisterFunction(ctsRegSplit4);
+epicsRegisterFunction(ctsRegSplit8);
+epicsRegisterFunction(ctsRegUnsplit);
+epicsRegisterFunction(ctsRegUnsplit4);
+epicsRegisterFunction(ctsRegUnsplit8);
+epicsRegisterFunction(WatchInit);
+epicsRegisterFunction(WatchReset);
diff --git a/Trbnet/trbnetIoc/trbApp/src/trbSub.dbd b/Trbnet/trbnetIoc/trbApp/src/trbSub.dbd
new file mode 100644
index 0000000..e974d80
--- /dev/null
+++ b/Trbnet/trbnetIoc/trbApp/src/trbSub.dbd
@@ -0,0 +1,23 @@
+variable(mySubDebug)
+function(mytrbInit)
+function(mytrbUid)
+function(mytrbRead)
+function(mytrbReadMem)
+function(mytrbWrite)
+function(oepInit)
+function(oepReadVoltage)
+function(oepGetVoltage)
+function(scalerN_init)
+function(scalerN_proc)
+function(scalerN_copy)
+function(scaler_rat_init)
+function(scaler_rat_proc)
+function(ctsRegInit)
+function(ctsRegSplit)
+function(ctsRegSplit4)
+function(ctsRegSplit8)
+function(ctsRegUnsplit)
+function(ctsRegUnsplit4)
+function(ctsRegUnsplit8)
+function(WatchInit)
+function(WatchReset)
--
2.43.0