From bc9112f298c3ae7964ff2c78f33ff7ea6b36efdc Mon Sep 17 00:00:00 2001 From: Michael McMaster Date: Wed, 31 Jan 2018 21:25:50 +1000 Subject: [PATCH] Fix sync timings to split read and write period times --- CHANGELOG | 3 ++ STM32CubeMX/SCSI2SD-V6/Src/fsmc.c | 6 +-- rtl/fpga_bitmap.o | Bin 32724 -> 32724 bytes src/firmware/config.c | 2 +- src/firmware/disk.c | 7 ++- src/firmware/scsi.c | 3 +- src/firmware/scsiPhy.c | 81 +++++++++++++++++++----------- 7 files changed, 66 insertions(+), 36 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 57009708..19c4ab24 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +20180131 6.1.3 + - Fix bug that caused stability issues with 10MB/s transfers. + 20171128 6.1.2 - Fix synchronous negotiation bugs diff --git a/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c b/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c index 1e200f7c..5261aa92 100755 --- a/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c +++ b/STM32CubeMX/SCSI2SD-V6/Src/fsmc.c @@ -81,10 +81,10 @@ void MX_FSMC_Init(void) // 1 to write back to fsmc bus. Timing.DataSetupTime = 4; - // Allow a clock for us to release signals, plus 3 for the synchroniser to - // realise the cycle has ended. Need to avoid both devices acting as outputs + // Allow a clock for us to release signals + // Need to avoid both devices acting as outputs // on the multiplexed lines at the same time. - Timing.BusTurnAroundDuration = 4; + Timing.BusTurnAroundDuration = 1; Timing.CLKDivision = 16; // Ignored for async Timing.DataLatency = 17; // Ignored for async diff --git a/rtl/fpga_bitmap.o b/rtl/fpga_bitmap.o index aa8447bf1e496a1cf2d12df11701fc359736f2f9..046632cac655dd07f3545bcd0a4d0f066f19b422 100644 GIT binary patch literal 32724 zcmeIbe|%KM)jxh_?%my+%_g~l5F$n#LZATxE)X<8fFYn#L|t1{ii!*V3jS(DY*7&= z2~_-5qD6|2(Xg(^x=5mbcl`^;_-pO5y_@9X)z zKL3>Sl6z;)oO|ZXIcLtCnR_?RJ$1rqLWrr91wj=gIx4uw=4L8Y_Ete5a_KNlm^yRj z^h++I>0?g4bK|}e0YBg}^upy@ms~Splc+QIZ=A1(!bPv%qamEa4ZX_xsakMB$N%eoH z=w{gX-^lHM*0V@{Bhzm{%5T6OL1iV()Lnf9Pn0QtT}X3O`?nUeEY(p2@l09U+t*nh zMfEQigMWpRhwc3^roNqwhzb9xaY97H*BVfj-gfm7Mn$(> zOO)5}%3}$juC7aI+mb^y)?#Y$J@yV{oEC$7Vp-#IP4e_D1xwK%D`fCmsfhABSSpWP zur%KBzZ;Q|;w(DhZLJ}gA-BfrPc6<`%+c|Fi_y~Zt6Jldr%LZKU+((0yY((t5@QH`gWw1cH6t?sv2#fbtS`5!GW%IIYHS_#hGkC;$g{u4WJ zvv{=@=Bb+|>`O2?_}6$WpW?EGM$J;HM2>TiiVAfk3M~Lc+wiqvF8Cc@A*txTYZ$X; zM9@qsoR|C8vgHJI8g8^U zN2EL=fhWcsB=piH-=_(nToQU=BC}v!YFjX2!*^f&X;Je$m}C5AO#xWm9_ymH;V50& zI#JWwIy@U*xeh)m!TZfiHZK6-5h*F9EoG$PdNz*=zdSwjWc1Zh0b5y779?gUgV$~? zKIZ3ZvJG#J*ltVgmq{*_*eZF)UGQ{ZDBnHnTp$#Ma)$p#a}!G`xsb;fK>g!QyD^Gs zGL)GU=KX(wW$RZ`vfdaxI^~&7FtLpN#?~X=nwyPJm0wAzEuN|qd6+$3=eDY!w^)pc zG%gZ68SU)JQgKV@7r!yEQaJhAKCVK_=P_`hkJhDapq5AXDe?-nDEJ;6AAZ?Z71IGZ z4>4N?ZLfkt4L|D>+=;i>C z_m1F3QL0*BPBf|Di<&l~pNLmiX1k$YselY3Q7D5DW5uq75VG*D9h<-_kkOC8CA{s@mZfBCBf&{K&o{8W& znMS$8E|R{pzn(FaFs9hhjIHXa#bl>R8gAI0G1M(_)1Dj z5Ba1V4p1^94vQC8zNDZ9b%db0!ySnuThf8?w|B# zl~;ru|t>M&gVW+P+7Mb zWCRt<3EuY&no~JUFj^m(G^jyJ7(f2loO$5nJjv{MIb&VwqbyFM_H}0IiR-Jh3z>Ga zt8=`BlreY!+OkkH98zlXZ@bZRgEzG-NEl{WE#Q|L9&p>$r~@>j)V45^PZ6o{UD#v$ zGN3HB>DzDLwSx@jhgQFF_DlWFJYEEG{_K6fXEjnHJCs>t1+!P~f!DQ2&R z=v*$gjM*mK!bH`|mTUt{na-B^Cc{OTJzQAj(;Y?XYVKJn)C0yI1(nXrA6g}_EAxRwED$CKN7 zIV8M?`sf&SzwRa~XLEX3%E6gWX1DNIa1ULASl0@6;h>X&vBLK+z{ z3qzvBV<)N#Q)up=vmCr$4ce;|yAv!j!))@~g=74*6SyQ=ug3JT9Xn+gxGI!B^)2l) z#u{R!i@7MeF85^YWO?CQX&Z=o8KTC)f2hb-^C40@BCgk5i-w|0w&f?$0(D~cVCB_C zds(%BK)glKiOv~a$mCFLw7U7dz06YMABW(g_?+)$G!G@{U~`Rytj0QXOtvCN=nfE%%)1dca)R@tI!!x7-mSOmv-(;95Cdy?$~doBx$^|A29DO zPiLhh>6on{qVE{_J0oIA%5TS0iq52#Zd!xowcle~F_dZ_EJI$%*@lp?ZY{6y0An>+ zL?a)`)cGnPWkpx&=8-Wfe9b$yB`??Bj5wnjxtA@oE){g?1juX)TT34^Sv227F!mi7 zlEJ62*#n7{Cl~Rk%5Qp6+J?+UD&I~*u3>p-S8^VOq(RNO6hnfhz`=qZu`sSOMHnqQ z5q-zxattDib2MTlgQUdaj)9}P3>1YSplNtjqfEKW#>^;2VUY2q!Sau9Z zMbG0!CtOnkNvf?AVR>6Pv9G}-sqDike+HajGIU{AC0vn!SaRi|7#vms*H0wkRqGvxg9e)eDXq67+k&6 zuz9dbB{k|5-N4eIKtGxr;MyaJCr5ByVd1xa+0@HJHPYegOT=%tdysd)nuJ|h(P=9z z?mLl%;SpNF;uttTA#!L$AfThe4a^UqkZiW&o^$J%UAQ@;3pfz_)E>I(AdKKVcUJ

32ISy+y*xv6RC`Qhw*q3@Gm_&|ej4z^8B3G7~fH`fo?7_Ico$bHzcU zvS@1PJ(-lVbMfswSb(ZZj=Gz$j^|RbDKnI$W!ZQsFEi+SOaiW+fg1V%;-~}fU`e5- zv9Zun8jF^C@yKMv$nd2sWd`I$L3t0cp!-K(tao)%G15R`CU==}si;pqB+G!Fo9rc8 zuuzFy`p2_7~81zz^l?VOSMUr4xTl~As58a+;s}@WXQB`_JDYgzp$?X& z`^-cRl>YqB-i0nno|e|Q5&d;p?`LsKUbMAdS(Cezo_T8k6n)xflcABrey|3s9t_hSv@js?(JT`2~ zYKLo>PBv_?lvyXjaa%2r@z96cn4o_M>m?Q9*q>|P1}f8FzODUR@ma1}FJfuv=yG-n zeBtx5M#@)K3AdObB!*~-*cU^r99qJlbleH z$~MW2ohs*x36NMXXEeLo0SsaYG#R+f;2q$rw z-bK*sNdpwpG(f2eGEs80aX8&}>&JJ*BkE0mf0{J{G}v76<~s>%m=eKKI_q9Zw{ru7 ztSV?XIOfh&$ZnGrpQzz10j=XBd}D~o3z3|?Ft4nHODI3O|{ku#TXj7#j)ylgo(S3U7JqFQ~+!GOU{c1p}=9fC`*o zWP$Hcu4x{%iFnMcEA(3O>qX6X(nxwWD? zy%)4-QSvgYJkK4WQ6G5Cc#HPvyn9iP^mq+hBj5qynsf1XYMcMV zw^4n&=#Vmuw@?7~6kWtyli7;eEsLD{8b_dB(|7k$OT!oOYDNiDCmN(GYq1?+NAwGv zgNjsZKnXlxL5Cky7;(Wv*JHfyu(ll3aNt4v2L}ebeVZZz1L%2ie~nbOsrMrG&8`N^ zE1>zop1fxZiat?>>*&OJ_?bZ@jQ>C>pY-k-M+oshHma6qX_ebHx3M>*!aT>*@HomA$ny* za1X>hd%6}tKwKqW#fuS_KAz!vDjKh=cj&FNGdxOnSKQ=DEB)P^GyQmi{9Qr!8$ z8fj_2YQmT8EnBL>Xye+K6=V0T5tmSYvC~!HJxp_quqN z)YYdf)KHLV8O3zWk|Jh-cvCLCG7J)J2EAs z=i%xj%+(qSa8TM(%V=noBG2K4BJPt9=$ITJ>ubT17mk~j6JiP_%5!cH;;#cte7d1 z7qZ(g*+1g}Ov~_>X`a*4P{G>SK#%!lDvle2Sa;2Q%!cDykH-Yb7-|+}3X(5AF$QIEGi}bk`@FDe!kZ@o+mt0t9&17KMzI zyA4hx##SW%2wy;&ePXv~e7sMIOxjNZ-opB zT zoan7c|LrgVj2{2R=y9%gHe6BAf)1Hd>JttrQGp}IPK_=V_t0Z79891kug@#Glhm-f z&uh8P4&%&TDxk)utMJ8y6ZGF4x0DpIXI$=xHcN(!Jnh=26z;dtD1(;^yy45hL!&eh zgXVTv9Pd-#=z*qLp}_~hK3$aNQ82892Y9tR3yxS^YMzh|6~BP^2(1hzgL z6j665Yw=h*OWzB=6=^NLbh>8;w%X$SBKrw_Hlmv`TKTn(fZ2t3A@k? z6&2ok!)};&Y~@z)(?H?h2?eP_uMgcc9Sg(nMjt3r2HoTy|M{0_Q^PqwXO=M>pd5Tl z4lF3i`D~mSFLpfi2-+DI{xHBHb7bw271F7V*<>*9`gH-xN+LdMft=>y`x8W_etRmT zT(Eb$ahrH>7F3X?E-QIFM0X3V(CfzCYYkTcvUX8>ClZgFMOCeo|HPQd>oWM*JqxHA zD+MN@u^4>dFaZV8obz~I4*8K$|DiJH?wOBmWEZCL`BJ3wjYiS`ekvewX-zg>lIXfx z!x?EimIfX;EeeF6?_&bGCtjq1T}30M@;bnOGGdFHzrJ zMtrgrioWs;x>WALY_5*7jA=qJ`~Bm2o-cL|_ybt5Sa}G+2~xejNEjd(oQ=_0z8Foh z>HtTyNDZJn$D@*mR|oy6)VVpHApiQ&4g`3sq;P`H1Ucr@ihz}f_bY}GB44pCQD{18iz4UUwR|W~1Ic6aXit^f z)CVX{x_?2+P@=iiH?cFMPJE6&9g5s`@(3LhQwAOgL0teOGZcl7(s3Wu7kT69bg?H< zYPjXD{V-Qb;zc~yU^y}N6!@q|v6dnOCpzWT3|_4L(Q65WPxne@V<9|r!ZIc3#)gj; zdGN1Z^A*qqla?XcQSP4Y2*CRC&G8gfK%XhQ;d6WCr7RsNgYx`%b4e=q*M|c2lR0$e7ig&0 zM02`mY)gk<_?(lW%p*B|-84yl$q%=?;hgk|57k4#J~&uc-!UfI4xL))`D~0FzX$#N zHY&;`u_;YsjpIwDR# z$fQ_eS*ej9L_`$}l0yx-wIk`yZ_oj)_ez)?tPD+ip!gR9*DkWX6Nx-q)gUqMhGaJ(k{T zJNYmUeR$ws{_vn^^Qic6dxjBshC>o<-KsdER$cNcdpgwTP5v?nVG>@wA5Sre-p=?m zj_d1p-DKc=@|P()7}v|2*-lZXHFT&QY#5{_tdJGD1iK%MM_+K5eT{ljw=LkME?RZarU_gOFwA81b#x1(4KnGVJmgVfbGnNmoB_QMbTSd++>*jcE$CM*RDCY9sfeW z^$Bt5lyE_ucJsvwT#kEkI9wezSeXD4!}$gFkkKA^AC0;NMTqKPSuh)yu+e86wrHpH z@F+^1MeaDvo_K~-&fZ^3^n=IiA*GS?_te{gdUv$0LVL3Jmnu7Z9$mLRlmx0fjnKHs z_Hta2Uy3idUL_{<*Ti;3RuP`Gj7xvSRtf>;;rXueU|O+eU7f4R9kMRlGlJ}Q_Ow8L z|G&n;bBWHVA=hZ4@rND@9>}ACTQ{S^pksBPe~iw=?>`|5DC~xlWT5R=^Nf#Xxgk&C z2GFB}{JZv=1U>l7s6ZIg*Gh?aN#~Jn%qOwAKL!hs`8CepccRxD|9CT2d!mb%xvIp< zUu))Lf)3eYvff6uMU*1{9P0k1rnm6&9XleV-i8KO;KANgw?1t-V(n2fKLqD7ku|51 z{3vM^Nrm#Cp01nh!}i8T{hxz5n#KQ|B~KmQ!BV1>8CM79tGhH`m9xHW5m^xwSF+_Y z_I_d;0;ICHZ@K7i!hZwHESbsNzb?zsEUb->Lg=H)|Gk)zGK-bLe{Vjju8%7JKQ5}H z`}^;svu$6aIGP$|wcjMaj*?A(!6X;5phQ87-iVH7BoG;>&)htGDXZ@0a(iQdtJ5k9 z*in3iL#YlY;pvGF*PC7j#t#?F%6Dh zHf<|-$fw4F5-cA=-t|{jF(5neijj8rLDa|tAIdH5e4+BS?fDvak%E+{HcZ(ixGTWu zrp*GIy>LNwDQfbmJ=d)bP-xDul&g+we-Bj)R!U~6kP67HoGJs<{)V(B_4r?w2phmg;{=k-(yOwnqeNflt$MT@P5UDLMUiQY4!4Qn0Qd@7n#jyMoMPG(lhAC zG z9`96K9T772QiFjac;H4FHV;?80so*&hTo((fjF*pEfofsO{x77H{wu{1=aMr@O;uu zCn^_D7X7~3*p>nh$(IL~i4IDXbA*PJZ?(1&4Y}pkX4_&TQ9U)io;41TFb_TvgT5<$+pdus{Col+RM zR={)&90GHB0o2!SfTvLYeb$1Amy*U+iL!U`9R34n47`DwJ7GfZ5<0qS%K>aE0R>)Z z9Fle4O3kie1hZ^zXO>isbP8{1EYiO+p-3yy=i;^wzofn|?}w5(UY3Ohc{Lhy0kqyS z*Z@Z%%d4@;4(!8J`a?VwAgYf=bVKe-UARHvak##`tE~i@MgYOgx?-6zhJ)Ml;4~tg zm7aBp?f9Y*oKiwu)P`T&ytJ96Tn~iPYVp;i_Bv?{x$un^vMdpD)Q0C{0xTz$PQ$LD zCe0^%uEM~Js}fY^c5lb?7Q_QX3sKPR#`W<6CcxT5XF)@swP0fdi|3Hi8NwcOHnQBy z=-Mz#8Hn3GN)x>?=m93Ep#zo-p6Hx^kaBSVmMYr;)i|vMOhzHK|JeZdK2!D^+`vLZ zmk;yE?)dcs&;ma4sP4ui@=ve-OmFDasT=8lyOLb_8hElCFcGU69C?2FBvm=JoM&=*S`x#xePI0!ekU`5d| z564Z(u6~?i*#M7eVZ?&)itiaTcUwe_za&G-#~dF73>>E+02P2E5v+rqn4@r9XZH9h zV9kVc=Z|^BE#GKzJ+U6IVi} z*>-2d#Em>5#U|2S+aAH)xF1ak zLt&At8Ji+n5e_6cmtLIxAs0>yPW&#khZC9_=N@I~6vHZ?N#mZIA1LxGwzs1Ss37f! zb}R_h65VW;Ykb!;y&kJb*wE>p8#c*=%4R;mgH;eq=WvO7e6c=Eii+861|D$k+bG1# zHlwUj@`;9~7htg^cZQC@AkMfYKtm?+U^zdkI95_*+bM3 z6+n4zI35Ddnn@JkRxIP*sMx z)Q=@V2zGF;H}p`z3?bziPoM+L@udb!#juS5uj5@kHwJKGLT@~t0McD<15 z^#)G@FA^`c|_}tE1*?{_TpDkxdHAJ-9Kc9!Hn7Xes@i}9&WGt zjD6F?FEI;dVPSA&iM><7MJD2F^xM|`i*ZOY67C)Kj2^_{a$ZD z#nheVC$&1e9X`rYeJV6{k9Z#Kkak7xb~zu5#7IhEp>3ReTlyfBfkLL#O`ctopTBDR*exQJc6j(5XzRS}T)IS*pvr!apS ziCJAz6Nsh8gE1yc!wyG>ZWP=pmvX>;d(-g}c|I`r9w|a@e?G#5Ao*tPgG{ zeJd>aF>|JVThmaAneC8{KU44~6?t^m;yE?g_w?Gmw}s3j0cRi#Xi1Za(C8%5=4wxj z3%qxJbvZd=(Apg*QVi)WGPlT6VEIZjTdN9v;&YuP`G)kPQx?y}+mt%;*KPuKiA`DY z<691%6xO&nO@DhjWGE+I7xsDIlk$(#co(VmbA%V--2EUm!w}Zu15aFb z_E~R6@jP~CMM+I^)d{FzI|NfY6m5GRKL|{HCkVkzFQ$B=HtpIuw&}Gtv7t{oCpK_X%hpiL|qinpC zj@Fv@@^Q=sbC2{KWSRwG~?3gNDY#am<`qgj@M$1K;5@~_a zVfH)#gUD5*>hZgE{ev%Lfl*JK*}z0*U}19N6;6OuV0&N|#0cy7IV+s? zq{}vRK_gYB@&2n2UwLVXg`!l!po@N=U>_p0B3d=2G7C7xLmO*CWs!Nk%Ay{-fKJCgFpKwC1SZrQrk`d)p|E*oC8~Vl0%x zIvz!v>2bnV!aH>5Qs@#<-AgT?Sp8$IyC8{7QwGlYWCsd;ro1UM!pvz45Y^B8*b_-e zxqX&2a`lJxZ{k>+{FUKa5JH#j&Ay6kDCcrM1u*&3mAy~HoL(D(8yc*8L+7E5`fY2A zqMkgxd5q{YA$?*D8;etZs-)wr{vhEk;@-dipCF7=(I_7|rPFwMqmoE^mSY{N-$fyO z2emGR&zd#)Cpna+5*obm)es~$ET^N@@3?v^gOLaokwD= zmn2Ge;&%h0vZ6)IqsXQF@CkJyC1IGpV*>O^|A4OVAb0Ey12>v7x^v@SAHYnwmayP9 z{W#T4-x=-obA2U#@G~M!E(K|#hDcC7B<>748@q_sNa@IgDIB#+ME!sYmq)rdf}KF| z2Zwmo7=iCDThxr;rpqvIwnNE=~4Rs^11fc(#995um`_t7&uR%`ObGDqs%+tl%XZbxxWQ z+$@e-K4F%t%24YXq&;{B`O*EeAOuz9y*UzH)a(SV>F|NPrCM(uKCiEoV)S++0$|Nb zkE$DBpm>gfqUR(PR?pY!(d5LRdpnF3M4(65qDYRO4Xi)#qK#a?VdFe_&oxU)#K*c9 zkBz$qiFM&J{6@!65$2^p;OOR?KsxV&T8!GwVnubO)1=&D6Wp#e>h6suyrE}d*+#JR zXyzCrP1BzJ`6#a(6szD3Uy?uIhLm^A(6d8Ix+kHwDY8LRTvom&+9-(fP8Y)B%`(eb z=w!r2Up#(v!762gd@I=DL8<0jDZXk@nWBMSsH1FAGSl#FS7E-f#hMDMBN{ame7lqZ zH$$ZifxUj)g?R#$y?(<58OgVU`dU+6rWTHMvjuMSvrn_g=tSFFMl4(W=a;N(#H-Rj zg|E~Zuq*u&V3q0ry&a3^KU3#d{CRF#_`2TAQ8;An0K3+7=v5g;eGUGpluW6=A|DyN z!VYhtk4Bu($SRR@#LKQ24?d=YQgmLu3$?)3aRAK?NK_*fq2mm83rF;cD6{`oOO=sO zu!3z0Xz&d(GfZY%$r<=JR2f{pa1^j#Pk8=+c5OR)5Mo4YdmfW8#2eB-wPyt=8|UEr zM?17|R&D8UUB`*Nhn*2v8b%F&`{|$Ji4Jw^QJ*gKga!ssBp+n?kqJRQg(DNg*ep1! zZfa)JS`aTaG?SOyOPF@PxTpA=dC)Js6V9@?#InzM=gD?AOaP9za%akSDAwX7C%xS?L zNq-XZ4?nk=u@?AT$!X2a*O{vBGCJKIe^O`p{?n!z{J2de*h~!FXYsljm=2@LdtVhP z1mZJNJKM-Ktp`cW;IbyI@Q7cWLfL}uqJMQ9O6Fk~+dSyA-J<15uUv?NT=dl^Z^%F! zAZC7K02&mZ6&wX})H(yK#U#6Ewy9a@tS`eij&%iv&A_|(hX4S-oNlT3BJX_(^2gl$ zji@M`v~h%B{aff#yOynNLk29)GyaZ;@fjyeS#P)@3-Ymari9U#)MyNx+@5m-bk_8; z$7UbAkt|ti%OUE!2xR!kWyq5ondN3i zv!H}oitqYN8}d1>CN$V{sn)q#;RfGKP`e<7F-(JcafJ!Wig!Ffla8_L5#k<-!;M(jM>H>d_kIo zon=7T38@E;M&?a)`rLyW6Tb3hYWBUbVU!?MSVtn|qb6YeqB+bZHn=R(4AY<`zi3uE+jk{0cxT|Ir&Af{U?(yt#!mSyv`z8t zziohd1ck8)LTKu1Isy^712ulKiJz3b(mIkPEsE7+;LRkbca8xoAKPtk1GvJ$SCFQ} zFTY`FTI0;(=S{{ogqx+d1@x1Jg@xWek*)U-9qiC0E@e#btA9EawaQpN#M^-WXz*1F_+iP4H}Xp``=70jO#qTvvJF{ zT%K$=df7qIPVeprrY^N>!zFZc_f1d+LkL)hMzvx?m4&KxL3jEog`Dl!KouSs z_O#1A35=V`N8fzak>Nqy5*&bjXHF`h4 zNm)_wBb^{|=&H>3DDXGqBK?2tJp+c^g%BrP(-4r~_x!!Bz>PY%)nF883V|m+WGzqS zVOSQr=oa4y6LLO{qf`Iv=5&$!E5lMs1ABbX@%{_0{vk`%cYiOf@#IOnVhS`U@;^xV zRX$W?Y(lZZEk%QnFWW^IQiW5f%f}|O3jsnQ`QVkaNcho5`-T}YUR=M2Qw6kA^a)WZX_MNeIN23ZS!c_};pG|{*EafibErosey^X&7_@AG< zeIm{;V#UpN{JB*D$QX>H%7VJd=ESm}*!U6P}sD@sBK5es>dbjYT*hs07kVfx(7o9594GdQ>5wrlkRmeWlew3WDFtw{ru1`02rFBfXlm z?EnZ*;8ZTak2;V02d;$IgYZjuhdBNH9f40^86BMj9rlJb6ybE@%6yFhkFLuTF1aZr zJ-_|XmCQ1c;^6_DAbIzD3u4jpmvarTT5m6h(zR?_B}uzZP=MzFVZ5AZGzD7G3i}r$ zoG)jUq%at2EJswcEZb1GAnI;msiI4F;Wu7l_@0%}GK3NvXNM6DoFMxtF>rlxic@On z*4K*5VC>*E7MbGY?&l1b2c88_-n+R)7;@J{&S=FEW96nyn2=2e6s&`sGGheXL~XhN z0lnaYKu{UJeDO>)kPWi@i^cFJ96Dnt24o3Ot~x~E;$C;nzy%C%5*Ftrc`yl>V9`szmQtP(f+n~BiW_(dq^;GYRm?OkiDeIc+rlg6b!69R#C z7?h8$QVwgHCjy|@aFWetnk=7yv+Ei>?NL%lJr`e^x{y+&nGlciK_40Hd%{UP%%AzN zR36n=6Y71ND6>M!cmxxYm6F2WmXP?1oXQhp4f1Spd}%e|ZSKn=APa6c{%AZPQI^7E*)N z2hHu43{z{-1b***Y6!=5aP8NZ!Thiwr3~iLSVuo??0}$zV)K5p)(BIuiYMwuP0DbH z{)lE6d`0y87aEo@riCNX&{ogKTONvde$K>K9xAe=H_YN7HsalYl?U+W;nM*wq@s;u zo+T$3<^@Da3X2nstI7G@cT3m-0PaoDWt#AJw8UH0_?o)-6~kunD5dZYRdxE^UvsQW z0~cRwzha;46jjMVwC>t-h?&+lT=2S!uf=GbSpg!#%AQ;K8vbIC=$nXa3~G%x zIPQzy?j1&s^kIvEKiF_w{KUQ-ya>ZVgoby~dpMflQfT)rr!ygC~ zx%b`zje2nPu*pOs+t=+kCMYHbT2I@`V_`?BYzq%1R0yoT|<)OdoH&7Bh0y~eD5 z4`$>#oanh-h3Np_vp4K4WYoPvac9PP?GtBffDusN#uNtaAC@!a zrI2O(-FA)#cl>x;1Y!NLB%76$jCav>95$kRZ6AK|(+^tlV>I~mND_Z4YON&%tx~$( zFEP~k{b&1tW8EkS1hjs!o0%=dnAJZpfz>43w>$<6#sQ#XTLI$U_BEvJZd5Zlu>mD%M$5(D)7J^@ ztln~Cv$Xfwicd7qh^pPq(;!dhR5KT z299aq-&X^TI3_$62L65Re{AH(Gyn}0ieve}F-JJ2fq#1q9Lop(?OouQ0*+~*5TDB* zJ0Cda2gfwU$5<#h2G#G4-5 z*IxQ{#P!o}x(uHoUw`8@GpA0&eddhJy{@A)OvWOH!B=7g!yFv7$_IW;UpTEi} z-kCXb=FB-~&Ybyi@1_gR8FQ`>Vk%`oP$`Ml0@C0DuTbtLrQ{=%T4>DFIdf)QF^y)7 zIOmEVT|TX!-7ngAK%Z#8KK;(F=o_Wj)Y)?e*{Cd!j-Jr>{N5M;pl>uvBd5-pHpu?| z)SE%g4bHav_8$~IYfu!tTjsC-<@_Iz@coSFa&i7_s$WRdhQz6&oFdh~H5>l7a{IS3 zGrz=5ol^4h-(a3^(5#|gTd9a7+3=))6L>v(#_;n0lJUPL zW9eju&$mk&x#QZC{SCN(BXvo0xL2_^@Nx^&doE+2+8cJCkb6memN^smU2?_ zc*C{}jZKj-+1HLfg(Xn|<*u+Yl;*(C{o$~WXoLf8supI)zpx4U$-Lvb3?Wh8^T=kA z+!Ud_0lv{IQYUMO?t$X1EQ3YIYe-qvsVq++^^?WQ0*rSiJsu5PB(gSzVJR`4S=wCl zRmihPw*VJwHXOxuEagdv5P?Z6^xm4VN@E0;7zdAKYZYnx3%ba6ulb0CgcQzj3vTcw zmIT#XNkvKp#uHsub5cs@B*QOf{I)X@m{@XzVmw!<|8rf5%j0eUG%B?Xf!v)F0 zid4oROl~SV*)@vY!7>4shC^GZ7~(=JqWVsFK*+i~T1VWL<#iZE3cgkYVTs;f5ocS9 z+{7>kSY@v$rd+Nd8t}#=W4$1nw{Lxf5$YEnsY?C&TL2(n0zcV?D~&40qGUIr~Gcb1)A2U8!?V@OKa7Hc8}~*r#c2n&iztoDTl6iU#lT7XblNK7U9Jaa27wE8* zkn5uYo=3y+%cjUSs0xkv08iT&;30s1jnya#61L-8DM<1>y^pkw^32Nb#lB5Th*NM&fX-$n@_M&0%V zOqfF#DlYnVO=L3i(Td#;>``@6N-D0J$-@)#l`7a;-W%|wst})5Lj9}#J7Olcbm0K9 z7IoGp~M_CKsb#|v+psY0NGg?)9LK)yIfue*tQHJ<$uC; zqKg$xC7SkWmW$4!OP+Ix%BY#`=Yo{3l)_hTW5oRa6iaE6_Vss=@w1eMMh+UpeXEcZ zOk56)EB(6;S1A+)ML7~tB^~xGhJ1Htjg8)YjF9j24rxskrHVtnwxg1Q&m}xdp!(wb z60i*|d`=}L{pg49Adm9majYfL>n&XALhmUpc2rW%h@)sV>h|~B0*gqL?B58Z`wRZc zC4fTv9VWM$eMZt$C08Cl3=}HALzR||aI(LSiwp$>TPkGa1S=q_{66M@c=^7(n{1*I zCxR!ymNdjcHcXwTC8arlLXX86pA(LD&|uR;Wnnm7C=-{BBTe-*Xo3k@%3re?9iX@6 z-O3^P$c{vTOXm>vUXPq8oI5RPQgZ&THHs^;!qh{drMMt7;+UHU8l`P|XZ>o;vJMnmR$Qj(6bl$By^PDV;mOwBD&RnQ+MP(Y~m zu9PPI@b>OIiHhRAorKE}?DwH1P8D6|o{@y5s^_tkHjy?t1P8la5TXnW+#O~&C0G>q-RfSkYWz)a@iShxHTGsGPE(14OPVt zr+EmIeuvp3Sj_ccNwPh{z1w}(1D7I`H4Rd_fI++L7Y;^Tk7JfUHalZDTrgP5$Tcl{ zGvy==YFQv)OZv?OW#&|2UT{t6>+K%6)HJK8kZox*N^BmpBgW}OupC};>valt#5f0- zrCmUuCcu~pY4SXqXAh-%LP~4I^)8ZV0&GdtfzJG|a?h5O-Ly2tm7V8KYfw1I?thSn zhO$Y5C6x_3R!htWBR+D*jLt~YRK$w=U+^VSf-Db0%CKcT_gt%#)bXbW5a>kBu}a7=owb4YWN{S+?y8xMAOcR|Y2zzx)Zru?|qMOW?-xhmb zc(fl{0&J4^J@x?oY%z{fZ6%rW#%^m1_r;3oK|H;WR|AI1p1UU|DH&##ST%+Oqv4Tm z1s;*?rWacKRzYp0fh2P$6laJy(ax}DST6%T_M^_E?9VVf;>wQ8 zT(s*SC_5dOCNp%M_DnuVVYRrh-w>seG;i_&5ZQLjt@cCdlZ&ppc{^L+AT{j-W8>kR zv^l0C!-XPF`((oQN)fu?*$czixjhG&l%Bo+08w2lVNhm{pp2*+x_gb#6g{9w$qplX zzm;w!W7*#;UTt!Z$jiUn_i!SrRu%pMC80_tDh$4ZrXG~UCRkp)OcogFrZ8x7=GS3v z%K`PI6($x?3|anXqh8h#sjH5p+EF+0?09YFdDUP|+RLirfAcaXl?+|*IYrHi`~F~R zhm?oL9%)U{M3R4u_er{87if_>=bfD=Vqcx;oK_GK`)9;UG%Px0e`){mzisN* zP(Q-aWNo1k)b--!M6!*m@4GV-iAvX`g1=i%D|?HMX(g!-6{NX;IEQhDhFwbIyd*P> z(KIFIRFfMt-1i`^0) zVAK7>{`NAf;nh!w95u3hzs(*iL@iiicKBXNw9@*!d=Rs+Z!KKsETrpb?(J|QcUJAy zDvyTD|18sakW~7ZW#*@|94Kr!WVtND6Ie>XsE1-Ur*56|Fz`*glj*0?6IiML4-lOSdPYZn^pVJpVTJN9@A|j~<3&@`HcAYZ z|KfT)?fk4tbiTZ2-bFy#lpPp9RAZcnjLx_UiGr!~Y#1@kLqlzp>F$Xz)Y)@ucuzTY zJqr)81M-P`V^n+lJ#cm06ZM`K=ms)KJpsFoWWm{QvSbXxlqViS$~Q13wI3xZNu$j$ zt=u>BZrIY_e*c_emvCoz)S^A(`}eR5FKw@aG+@Te|0b%%!cm{@sbMjSHNkfQxyfP$ zV>R%F?RZk6N?|brtk+w%zM7}-aacQkPw^wY$>F@O9BxLdaQdCto zZ}jLO@qly`_enT3jtAorJ3^#KqfYO+V%PU+Vb&SH=E>xOzhr5Q+SQOA=ujRd&Vye% zSbJgxd`L0Hj#hPW=hEB)4o9R>> z_lUs@#N5wEB#C!Z*dYcfSdp68%_W3DMb2ZE0o~+s#+(&OVzRWswST7mYZKeU>aVT* zHe`k?&-plO4&Xe1^UD3lrGE?9;G*4sQ14W5`#lwb{3&9v8=P7^RVv{qZs_|~^DqV3 z?vn-hX0W{~$4&kJ~-5>tBuV=Oj6CKgLi3c0sB0sK%dbmfV%@i*@F>K91!~3aZp4k=CV{? z9g>OmNtV@xkkZWe@fD+_v-f8fF^|-tP|VAbp?Xsqy;?0}9M^h>5svIkCHcjK%(}^# zNomySu4nc|-l*Hq%EBd#}7fgC(G7ZNE8HIJ@WG5)9iqu7!il29(k=Q+Mci^-x++$9TAwuh}H{L_B z>{#R_*OopqN_mm;ON_b)-QJnDTVW~9?TXWaP0{#!F5ad=Pw8+UbKZH$453|F{l~{F zlM?N2UPGqN8nPtg>a{u_y*eFW%TlJrLfS$fhmCH5Cm<>*BXfBt?tE6nlIUYn8fX`k z$!9dEl+bLm@2&+)SU9|>7VbxeFE8xTVLST3F6`cO+@+TKl%kq$N^`6-4)vPqA6z5%4QX2&cz?4o2-YFy3xy8YrsDDQBY%OcBttk;N zZC6YOu%~|Dn;4}|x8Jf0C8aX!d^JgJV=*gp6<4StyJILy*gvK*JXBeg-pfcGqIN7% znV67KT*{yr`xy^wc8@id-MG16+c=v^R~nz-BC&SVRZC*6ZeLXZvbc{1z%RQEr|>b? z%GrwtiJgk*+L!LyG}*wWj4XmPeIAJ|M@gflr5x!6UIjau}!ik-cFtp7PDNn|To2=H(5L zD~GDvIJmVOn0|rLBz|@5MFj_*dtNs#GUQGFkULwp;SVNWpp7`bJ!S`aMCvzdxRTMq z>i~$wHifXMr0jYWC|LUPN-~uq@zcq!-qI?d)i7ej62xrzuG029>rN(h4 zDR|d*>EQJxKjskP>-zWr9qv}CaL?j`=!lmg3R>4>2=fZ(?slWnPu}4pv=j&YZp~vp zH<1p8!~@e5zzI#8I!J{~Gf&7US$WkxQ0(B_okZCM-Gk+VAFmUmanGN%J#1sK@*QPc zs&-Ag-qtP|DQv`o4SZB7AI8g>h~McB&qMmy`^uC_KNZ_9CF5wOJ#r|HJhP1{suMDU~*Ap04lw4zl@aS2S2a_nIlm3dioR zy@$^c9U&#Kw&hy@*B4ddBug@O`BtGR1+l$erR2Q|Fj)P6?`Se_IMxlK zxR^fk=Z~sF?_2vL5?RWJ7aSbq5}#jj9EsVw9l&a#+8+ZZWIbLFnf2v()oLmA9q z4)BS*R>k2r+p*d}&Yl>7h~d608YC&U_bIRxdsdt%0zHFh+7e7qX{^(DzW-1alxF3^ z6!^uh4kaVhlJP0)~e`o{dQYl_W{=*^De8xuG?{rmo5SEWjr_8MmYQA#84fbW6RUJ< z`5hU+C2uIFxq}vHM_?J}?)m&H3QTO~GEiW?l6153ZjBMZtAk7hzBW*8wvM_#s$Il+ zG@=IEf8!^ibO+5du{Ej_zLN-2viG*kI&R|K2sYMjwQj&0vnmkoFttW9Ata`g-!hJW z6sA%e2$eER9<@>R6TIp|ncqg>sqw0@M@)88#`fMyG6t1JudIS!#^CB?!yh+5N^X*5 z#l@%{j{xa`6j;s>eDTI9EXv{PqzODaLGcJ)x4hL`xpZhxfwY1#>U%ZPc>zfW7!`#F z4_C0P|LP4aIzVMR<-TMM8Q}qrg*j`)m5n}8Q(H=7sBr502Qge|Yzm09Mukg%`QS!u z2`S}&o@FJv!N)r{@osT$(j8dvq+(x^XiDw`i?z5a?Z$g0?zwmqDZ5YNyi5p29azRm zys;sUn~z~5@wQ{%dfYvYy8_j^a8?r{*)8bsQ-v1W>6`< zG}WZD9@@!r7v4GBwPm8daXh4sn;RNDLSQ4lBv@qke*#jL4RR*32LT4%t%!zF-pSJ$ z`Q5cAo!#PaJwBk}gsOArY)7Knhd8FVP&7P58fIA;T}&c4B3%WsY;0)y9RhEgUOXgq zsY__$L=mH!ik#o$ixkVBw>E0KD}I9ksb#8*tDQ^fDNai-Y^I>3A}5I|gM2GHvLPZg z--hrE3vJ@l8C8fYiC&_t#x*V)Q`4w(bDT)hJ*!X55hP?p|yodsnm0UUw$SAyRuMPSw=Dr4|VvxamVz8@)u1L#X zSS}R_Z2eYfu1%c3j}wN%tcmxNN!6i^mSsBW>yq6`Gd}YO@@~xq%YW7}=#&$-gaV^m zZZ#QgWp1kcgJ&L*nlXTz=2s0@{c0MgqxY&2_ogv309NRMU69fV29jK4h~-keUfM7R z6s7(xh^e46^ooIwf~(-}6=jB!Tju(zvL&DO}yBaNTai3)tZq z5ZxnzRW+s1pc0C>yI@l*MEMIB?bK8l-*zaYxGInZ7ZF~QCvR+A?F3}a26M3nhohkz zk0Uk4_z;*~2&9GtZ4x0J>!DN^gq<5c3E<8Z72TbtY(;q&S7@v^@&d*h)GhdzCC(UC7@vEXv<51e zXBxLiZj@D02bQT^#{qwYiX0WRB^h@wZ2*}ICU(SFwFw{0;db?mly}%9`Wc1m75TG| zz|0Ja61a%itXKMO+^O;}Pu=tZ-_62MdlzaX#uK3=5{7n;FE3#t6Yb~VZbM+3#So$e zxW+)HGvCMnuzDKjZIGlp-F3~qOW264IJ&d$D(11~fJWrtKQfIuccrmsz)O6dN{X7>%t#z!{n6OR~=zVdS|30p+=*+=xooD$VvspO}Z&JAB2lm^prvIo9#P3{ufA1~h#vv@}4=km0(WG#lr1xH@p7~lN9o@NorO|iy}|Aew37Y{AvkW;9bI+3sInK!s}4Xam?ZpW zDGSTnf0Kn_zzaKk!x5TX$%RU|`bdTEAy+=djA%NP^`cUqKaO=Aigr5mYMiVr;jZIt z0~TI+SEyT+c<__P||>IYR@MVPa&A z>^60=cnI?2K&1kg{&7%>cgA`K_HwP2U!=l8ULjc6_zdc&j28ozRWoj#`Vv1Z^kB&Z z*7ob0!H-#*)oA#{9b;YsA4eJrpMo} zZg4ZOFJe#9lKy(PTz*cY8!k+$oh7v?Du&i*cU80Tsk71ohcn93uu|Ji-=m~A3#5Z+ zB8Dc$G&A+?Y3nmiis~90FNK7 zsB`Hs1a5?MJeGD=*Ov*MN$g`>(_uzc&& zRzgT=zu^`Xo_4q~nX5E%BXe%u2dfUgy8*2j6!l!HbCS&RHWcOBNtsjmc^C7+S-dqr z<1CWet|igzwz0vo=R(TST*}*beF{m<83!~H7ixEdAG73=9Pqlvi3f1g)7%AYnK{wG zVPH$w3W_VTw=c_#7H;=6`WSi#*Z^$IY85V^peJQfyW>+@FHPL~b|Yryr`a#@bss{A zXkedJHe9=7)3%=~rm@do8|PSb@5X%3A#6C&;$Q(~&1hRv&C<@&E}bs>E%kuZb<^8u zlQBVRyPOU-+QN#ivNce_9{+J)%h_i?*n z%;->p7$nz?4%fTrf{%IgFPHanXFQ{1?_FSGL-8xgM!XbvA;Io)$9g=Yzu&2mc(4vz zH2C<84q9q5o}1e#6|vxU=I?;T*Veu3GdwXoxK*;~T$U1wzfzB3{T^;`bCP=;n<8~@ z)wm4dqZKDKC?r_oT$0`60NXf;kKX?{ zMwq}rS#M;AKeS_O4#nh(Ln}-g-tL(fby{#|7Y^7IMFP)V=1x%LB44aaLIU<`ZKvt^!ufP9|`*-18a=J0vyTez8QD zQhqFJZ~=IwCAwUn?I4%_bc=0K1Rv}S>63tO(3r6aiD(bO_j&-;%n6)PXNG0%03 z*rpqW-+Qn2Ycmt9>}6=TH5gc6_Onl8P%ILpTFQ@eW`lP>%O6jal-nJ}CB z!AVe*Zm;s+96^! zi9p)v{vs~_esuqLgaYZz7{y1CsOj)$IB>XnpT>}Xz7fWAXhD*Dx%;{a?IMtF@kB|* zXz=)FRtnt4ODq(H=QnW3S5GL6N_MSdDG;=o8MCiKTHj%BKxsXTN-6x<*i||B8f{7i z4#2_~;z$Psv~mqUEz#@58yh3!*WERZh=k!_6i8PX8o#4(AQbba!wo2lUR(c!t|>mE zodsF5l<8nb-s;6&+T;9cH5j^A2KS z*rLb94wR&L)*=J8e5}jHJk@gPmNTOLXkFvYuR0D$TOh3u_B%7Nw}UC2YJB&;wlw`N zIir&IH;u+!>>Q^v+#XC0FJvieUqK^M^Y)>;WiO|Zm!nQB$I4<2iIan(%@+a6$LD?q z_brW)yNw-jOy9wqv6V44d+P+*hc%;nOl}Tc_5-FjY1xqm{Qg4zSPxQaf~9**sjUI_hOPQiiXM69KB#c`mPZGwa+>~+X6#rzTVg}e zc5UyYpJ?(|O_vQ-Ws^6eE)>&OV}I!{JF=95ifu{o6j}R%_!Wky?^cBoR~o}37wz_& z33LNMz_G1~va*kcUt;BglqGXOvK+aHWrfx>Z9xvui67@(xJKm{W5)cv22*q{RTM9D zPZUwVcuLLxfx@{6+FOuveGa>=T-(Fih-CX23P&j$bAhbBXIACgG0KY4Dr9aS_n25sG0(4GD3aIAooX+cVr?Q>w)3sQ*5QXF!wz=#ZSUUgnV_jKXk z9Ko|^@NXL|m=4}hw6-(G3sPRk18Ho|CSkLcE_oQ_RP;|+NYGhVbN-VqzgBpQK8|Mp zjHvsqTo2d~Qh184A4b{un-!LquG<@a!@+IDRtMMaj~+n%$XT%E2}5%v2Qsd0qZIkE z$kRgcnu4%7!Q-7!{8-caz$6vMXV5(ei?m;h7$go+GsNmUt7-V?e zO8^p+AJiz$^5ZGSzotpkhS?{o!_>V|ZS;NEaajAFO<>Zoc;&$ z!?3-LnLQLCxNYQpO2RKcvV|6pUsf&AnOJK)i1(H)P96%-uX}NpV~UL>KfkXaN@wiB z;*ZVmomR74bg>hUDrvR|Z+|&%1dxQjSIED4s4LF2_(P@N% z;HOylA6^Stqw)D8qBRr25{#uE{3dSOs>i73^k_}dQLvks+#pa9i;aoHh&$)& zJE0r}H)Iu5PKDzPjmn5EtCZ%^r#ifcr2Z+i8lpnHwIRCma1z6W_s=aFDHded@~1~3 zCB^V5{X+cG&=EB+qUe4=!fbjZQkI={CFZ+0|GLKkgT`=f>qI`gn>3_SA(5LET7D%Pu5*~^b_7+hA$lFkZl`Fz*1USjsiLC2!R4r zj0vbpjpy!7TG+rCg6-x4%*delk;!xR{|9VtTuPb~+hgtKq2kwp`a0w(IQ%4=C5r;3 zV2N*$(s5gPy=XW8O%E7>!FHdRs~)J<%r{7Svf9n)FBgM|rU08CEGB?O1}OK*qxQc8 z_LpyiFE}drFE@0}H2W&8wnzN&4vf@=EBJm;F3+Xa zUnTL%LiWC9phj4^tQ3egKf4=C?KeQADV0mca*q9&p~uh6{{}jo6LGwzHt~a+HSe|M zK8@rHBXBdDA28x@!CWR9t%zlc(O(1Y$LfRH-3j^J+HaCl_Hul91z@h zui+>+y&_UHFn(D3HHAZedGl8%iFly|DEEnDjQ>vo*cn4)L-C!RTL&Oh%>l@R{O#4R zhv`N8P|ej26n_);`g)Mvw%@N|l9tX9`|BxMv4Q3tX-81r!3X?~=^_$dt$u`)2=3#q%2d*QhM3%VhvSEUhpz;?&Ob0 zz4`zSZY~J0y!XSKQ;_^H`GFFX*1F@Sxf(X@pbzod=t8HaLqA34*EtazXWD)ry{bLD z>&9SN?UtEk?yhDCX`Nk!=wL3{x~5AjA<`1q&l>|cx!m!0matQyGU`kjDG-ZL$_(Ym z{2_5s&n;z~N$ZWOiUhVT*(fcx z(SAOTFWpOrY|pUA)_h1jfvtAnqQpLpZQlh)a383PxjzH{4gM&Jvjl@p`J3yr^EFL$ zi=xkj37k>Ew4pvd65N0}gb{@X4u&0yd#Yg<)c!~V za}LqaB2BXE_p7;q2}-o22}9zPLdqa-dr4@@j~^DJn#1%+hrKI-ETi1NuiBDjkbLhE zL@Afh?Ah{bcBpd#+Z8jShGVXs_YKA6UbN`ZmKujN)zlbpfMxu!#uo1GgNX~J#%E~*!w?!F%wc?xAv7@K#@_WR`(YWbbLX9lOytQ=bKRE6%MPF;U6XZu0Hl2Mz(JI7 zJ<-2&Y7R2iHv0Ku#^C7v^}?O(F^d@JqH z=RK8;W6zn6CZqsqI7S}w6J1=n{$$l~eDBk<(YakMMC z7)DnpQ+i?3Xk5tGyv@PR1^MR`&We=v)bZYkmuGK(Jq5H_5y~ex09DS?+9gB8fApH0 z9Zh#WbI7rYx{v*%aEAx?g$^i6MV6KEU)X@=E&h_c zN#U+m=1#BA_c}N8E90<9Dc@*}!gk}jwO+gorH|TZAzSw02|!rt)R^WRUpR3}(VWG2 zs$rMnH{rS~X|R0j>CcwvJgRS(wVv!i4{q24Iy z8q=hiasihE%lX!T%Nh&C@uQlYbFy@thiB6JJdV>TkW>=VlsY`B9`xP(blwk1dm&j& znMFx_6{Ki=*V{}nyy~vk6X_b45F@gcxo8=xu#w3ha?;fe8N4M8E`h^OP?=(u8Ava5U`xXZ=~j$< zxt_C0V~N6&k2&sIS%$(TahK&$u4RxLj^S09@MYCy)j`VL&;|djJbT?04!L))6PV1$ z4+ed8&O9aDupu-&T-DrISPr!+<2n<8J-T|+I;$98@u}JuT1Pmh@cKrw;z^H2^nC59 zyO7QKaoL=Oq$&}17juoTE8$p=P(eP$Wk`AZ%rv?SJo8U^JAQlr7aaNHIf!-`o({|s z?+i0;)ImQTC=Sxqp-FKn64P_>+G24+hLf*ygp}uz7{8MytZZp#qPgE!&3Q`sS5Hij1_MSNO|ybWr8K;u|I0_ z!Vi>*Nc6>si|+fLV>{zD0%{O~0Z3`@jdAkX2yP@vyExJQKn(ewG2hn3Jxv}SSd&-C z-)@N*vd4&&_ccc;PtFFGX@k zIbPa2c620)wt5>a0g&8qFjR=@#tH~4Y2c@Bg*xMw2WDelm(9~DMo5j(cli1RQl=;z zCG(A++Ps{F67PZ`^=o=7Pbem3ySmeRq8tgA5-OKATc$(Kfp$7EM;PXb3GaI2DA@>r znK5bHVT;ndb~Q?&97y6}Q`;qL?nK4~!^z>d)?1B-XI+T-d<{Y3tapXhi!P7y9h zOwNruQf&SF0mHIIxX&*k0BW*sEj8e0-Ts`$r1t<0r4>Hf4=9QIK>o}Cokr=SiF%Ht zK=VtuY4r%P8Qh4WvpOEl(&4t`PkHE2V%oXL^$+dfj|X`6z(+$?Y6<<^z`ipoR2i@i zkvcHwqj?yMm$!9V=AaC=V0knUt_$>!Qw+bb%!BknjCknN`xV+4jrdg8fgw>-OjnLS-{lY<^R0cm=)y140WUNS;f z*`S58N)Jnj2#O0gTw)WglDXI7O`A)JUGQg#Fn+so2*ltK*-P53zz@3|`~{OOsgr)` zU(g&DVDMlxs zK$Ic-dd&qF1YP-7!hfTf1KB-$4LU572bK1LM3 z6gxMgCVvTYO|HiBh973dIdEFaUB~h5T>lr*5(W)9NXd>NxV5a*o?noRSK2EXkF~4waU^_TW}jlK zV4Ia#4G9m`I1n6LRu|9fI1g9p=6`4}z7W1RYUH2lhNvuwZY%AB^-Q`jRDqvN;cvno zJ<3G})qbpSsM$V@B?`9Oc}KjyM^+*DIl!y)FvHM9dz1N4+zx@n?Y1zGguA+|8DZtAyq%Q zC4~eR5pA%9dC-0WVIbm%#497w;>|avHAg^F`^3BH^AW5Dq91GnyRu-`gP6kNknm=x$`a4BJv+Og5Vazvtqki@Rt<(c?$8aA7B8v;_aPSH$* z)5&QIoVLJ!mIW5#xO_Sc{AZ2%X>Cti;42nrBTnxJzG9No#nTq}&$Gbk{lI_Tn4i}8 zv<1Fmfj08=e&8!6IbA$$f&V-UoZb)o=Z*PkjZa(PD;8*DoZb(7#U!VTr!DZGXMxlE zf&aWQKdtd;3w*@_MO%I>{9nO+xyXO@z4fCGuEFnS-ETL_=6iHpJ_Fe=$_HC$%2kQ0 zr%t(i#++-XCZ^mt2mep=Uq(&4?#eGCZk#c98a}DH@#bsiOuZcGoY`JFy)`%c`YWf- znd)`**9PTN>GpxHdn*yrR=WQO`Vw)+ diff --git a/src/firmware/config.c b/src/firmware/config.c index 06baee27..dc2fe1a3 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -38,7 +38,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0612; +static const uint16_t FIRMWARE_VERSION = 0x0613; // 1 flash row static const uint8_t DEFAULT_CONFIG[128] = diff --git a/src/firmware/disk.c b/src/firmware/disk.c index e7c097fc..5b114009 100755 --- a/src/firmware/disk.c +++ b/src/firmware/disk.c @@ -718,8 +718,11 @@ void scsiDiskPoll() process_MessageIn(); // Will go to BUS_FREE state // Try and prevent anyone else using the SCSI bus while we're not ready. - *SCSI_CTRL_BSY = 1; - clearBSY = 1; + if (*SCSI_CTRL_BSY == 0) // Could be busy for a linked command + { + *SCSI_CTRL_BSY = 1; + clearBSY = 1; + } } diff --git a/src/firmware/scsi.c b/src/firmware/scsi.c index e5528bfc..81af617f 100755 --- a/src/firmware/scsi.c +++ b/src/firmware/scsi.c @@ -815,13 +815,14 @@ static void process_MessageOut() // After 80 we start to run out of bits in the fpga timing // register. (transferPeriod == 0) || + (offset == 0) || ((scsiDev.boardCfg.scsiSpeed != S2S_CFG_SPEED_NoLimit) && (scsiDev.boardCfg.scsiSpeed <= S2S_CFG_SPEED_ASYNC_50))) { scsiDev.target->syncOffset = 0; scsiDev.target->syncPeriod = 0; } else { - scsiDev.target->syncOffset = offset < 63 ? offset : 63; + scsiDev.target->syncOffset = offset <= 15 ? offset : 15; // FAST20 / 50ns / 20MHz is disabled for now due to // data corruption while reading data. We can count the // ACK's correctly, but can't save the data to a register diff --git a/src/firmware/scsiPhy.c b/src/firmware/scsiPhy.c index fadddcb3..b2bb258f 100755 --- a/src/firmware/scsiPhy.c +++ b/src/firmware/scsiPhy.c @@ -31,7 +31,7 @@ static uint8_t asyncTimings[][4] = { /* Speed, Assert, Deskew, Hold, Glitch */ -{/*1.5MB/s*/ 28, 18, 13, 13}, +{/*1.5MB/s*/ 28, 18, 13, 15}, {/*3.3MB/s*/ 13, 6, 6, 13}, {/*5MB/s*/ 9, 6, 6, 6}, // 80ns {/*safe*/ 3, 6, 6, 6}, // Probably safe @@ -58,7 +58,13 @@ static uint8_t asyncTimings[][4] = #define SCSI_FAST10_DESKEW 2 // 25ns #define SCSI_FAST10_HOLD 3 // 33ns -#define SCSI_FAST10_ASSERT 3 // 30ns +#define SCSI_FAST10_WRITE_ASSERT 3 // 30ns. Overall clocks only works if fpga overhead is 3. + +// Slow down the cycle to be valid. 2x assert period is TOO FAST when +// reading data. It's ok when writing due to the deskew. +// 50ns. ie. 100ns / 2. Rounded down because there's likely a few extra cycles +// here and there. +#define SCSI_FAST10_READ_ASSERT 5 // Fastest possible timing, probably not 20MB/s #define SCSI_FAST20_DESKEW 1 @@ -74,12 +80,17 @@ static uint8_t asyncTimings[][4] = : SCSI_FAST5_HOLD) +// Number of overhead cycles per period. +#define FPGA_OVERHEAD 2 +#define FPGA_CYCLES_PER_NS 9 +#define SCSI_PERIOD_CLKS(period) ((((int)period * 4) + (FPGA_CYCLES_PER_NS/2)) / FPGA_CYCLES_PER_NS) + // 3.125MB/s (80 period) to < 10MB/s sync // Assumes a 108MHz fpga clock. (9 ns) -// (((period * 4) / 2) * 0.8) / 9 -// Done using 3 fixed point math. // 3:0 Assertion count, variable -#define syncAssertion(period) ((((((int)period) * 177) + 750)/1000) & 0xF) +#define syncAssertionWrite(period,deskew) ((SCSI_PERIOD_CLKS(period) - deskew - FPGA_OVERHEAD + 1) / 2) +#define syncAssertionRead(period) syncAssertionWrite(period,0) + // Time until we consider ourselves selected // 400ns at 108MHz @@ -481,13 +492,12 @@ scsiSetDefaultTiming() asyncTiming[3]); } -void scsiEnterPhase(int phase) +void scsiEnterPhase(int newPhase) { // ANSI INCITS 362-2002 SPI-3 10.7.1: // Phase changes are not allowed while REQ or ACK is asserted. while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {} - int newPhase = phase > 0 ? phase : 0; int oldPhase = *SCSI_CTRL_PHASE; if (!scsiDev.resetFlag && (!scsiPhyFifoEmpty() || !scsiPhyFifoAltEmpty())) { @@ -505,7 +515,14 @@ void scsiEnterPhase(int phase) } else if (scsiDev.target->syncPeriod <= 25) { - scsiSetTiming(SCSI_FAST10_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1); + if (newPhase == DATA_IN) + { + scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1); + } + else + { + scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1); + } } else { @@ -514,26 +531,26 @@ void scsiEnterPhase(int phase) int glitch = scsiDev.target->syncPeriod < 35 ? 1 : (scsiDev.target->syncPeriod < 45 ? 2 : 5); + int deskew = syncDeskew(scsiDev.target->syncPeriod); + int assertion; + if (newPhase == DATA_IN) + { + assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew); + } + else + { + assertion = syncAssertionRead(scsiDev.target->syncPeriod); + } scsiSetTiming( - syncAssertion(scsiDev.target->syncPeriod), - syncDeskew(scsiDev.target->syncPeriod), + assertion, + deskew, syncHold(scsiDev.target->syncPeriod), glitch); } - // See note 26 in SCSI 2 standard: SCSI 1 implementations may assume - // "leading edge of the first REQ pulse beyond the REQ/ACK offset - // agreement would not occur until after the trailing edge of the - // last ACK pulse within the agreement." - // We simply subtract 1 from the offset to meet this requirement. - if (scsiDev.target->syncOffset >= 2) - { - *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset - 1; - } else { - *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset; - } + *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset; } - else + else if (newPhase >= 0) { *SCSI_CTRL_SYNC_OFFSET = 0; @@ -564,14 +581,20 @@ void scsiEnterPhase(int phase) asyncTiming[3]); } - *SCSI_CTRL_PHASE = newPhase; - busSettleDelay(); + if (newPhase >= 0) + { + *SCSI_CTRL_PHASE = newPhase; + busSettleDelay(); - if (scsiDev.compatMode < COMPAT_SCSI2) + if (scsiDev.compatMode < COMPAT_SCSI2) + { + s2s_delay_us(100); + } + } + else { - s2s_delay_us(100); + *SCSI_CTRL_PHASE = 0; } - } } @@ -587,10 +610,10 @@ void scsiPhyReset() dmaInProgress = 0; } - *SCSI_CTRL_PHASE = 0x00; - *SCSI_CTRL_BSY = 0x00; s2s_fpgaReset(); // Clears fifos etc. + *SCSI_CTRL_PHASE = 0x00; + *SCSI_CTRL_BSY = 0x00; scsiPhyFifoSel = 0; *SCSI_FIFO_SEL = 0; *SCSI_CTRL_DBX = 0; -- 2.38.5