Problem with comparison.
/Modules/HBRIDGE/HB2FET02A/CAM_DOC/O1.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Modules/HBRIDGE/HB2FET02A/CAM_DOC/O2.pdf
0,0 → 1,142
%PDF-1.3
%Ç쏢
5 0 obj
<</Length 6 0 R/Filter /FlateDecode>>
stream
xœMÎì:“œçwgŸÅrzÖÝKðÀp£k`xÐÛw1%fF„ê~h¼Àa<d*™¤TERÿ÷Ïõ”ÿ\ûßùÏÿúüõ?þmüùßÿï¯öç¿þJþåû÷ß¿ÿó—eûóoÿó¯<æõ§´ÚþÑǟÏ_y¦êÉÿüëßYp¾–ð[øsÀGYX~\í£à˃ð9æ€çò=൮‡§5<iç¥ ¿…Ï1<„åËÕØ>
Ρ<
Ÿc.øJík}«Ø¯ygYu‘b¹DÃ\=¿sÝÚ¬G®9ªØš5½Ž¨æ[¢}ÀzäÊ-­¶ƒÖ³'oÂá-]Ìáó˜C^çÄòµU¶ÂáT„ÏcyšãOîéôÁԋ'_ãðo3V¾Qù;ûÝÇòü“Û<ܒ½,æ`<“p¡°íçÊ…Í“ØGáð6+¿Î…þÕ,þ=Â)çÓy½Zÿ°=íIæ&<?þה.æ(8oSʟkȝì¥0„S9
n?®Aéêü’á _~Ç8
+m3íãÏs~íd]•ù#|y/9
+‡?æÀ~_h¿_™ù#œòÈQpû=úO)»ýæs~×2.OÞ„ÃG½˜?Âç1‡<¯†åsÏl…é<ŸÇñù½þô<ÎñÓðäíÎg~ Ÿcx®Ëçk±}œcy>Ç\ð”êîŸ5ŸþeÉk ¿NÿMk
+ÁyÍR~´ßÓ`þ§<qÜþô󣌺ùxê÷$Ë^žòe^™9
+ÎGâò#e´?âúLÂ)ç)ⓓÅÿ\îdªÂS=¼Oá 8¯SʟëÿìYŽÿ§<qÜþ„{Hû}jç÷óNÂ=
+ûÐNgà(8oCʧŽöÛÌÌá”GŽ‚ÛOpa׏ëü¾ÞIø}Eaóԅƒàüj\¾÷Šö{IÂKÂòÄApÞ½ýk»¾7<¹ß·:ª'£pxŠß>9äß¾„å¿‘dû(NåAø<æý~}o8ü~õ}Kޘ?Âþý¨sOôûµíÃï×7™¯ÂüNyä(¸ýŽñ³g ¯ÿµ<ù´Ïzó5„¯áíә×ï&”¯Wbû(8Çò |Ž¹ày+Îß՛'oÂáýJÌáó˜C>ׅågl…é<ŸÇò²¾?hµûýχë' ŸÇòÒ2–/i²}§ò |sÀG»Î³ÚӄcVR,—h˜+®•ª}À:亖ØꣿŽ¨æ
+[ª}ÀzäjcÞZ¾ž0ôï *fK4Ì÷Óª}Àzäjßßs¶Õ®ú:¢j˜ l‰öë𜒭ûœ'Ùâ:‘Ëxó÷q{ð¢|¸eÇò÷y0½|¥g~6ßÝîÃI8¼•Å¼ß±Û\ƒç(>;ÈKMxü2/ö…é<ŸÇð<ò÷:S§ß'XîFéo¿“_ac ç–Ë·Ý W÷òœOùB|߶· îc@8¼ÂX
+Ç~-Û„Ïãò¹xâøs,ö…é<ŸÇðQžÑ ‘Îæ(=îöÆ÷wæïrÅoÊ(ÏÈÕ8ÝÍË¡­~l•yl]¤Ü¶.͕ëQ¼w«¹züV«Gì½¼ŽøhŸðrÍ:į9ûË{Õ ÚíÖ!W.vž'¹' =x?ú¾xoP~ŸáùeÇòÍ.÷ÃËO>å ñ$¿Ô(ÞÊ`Þ
+Ùop§‹Âçqy­¿îþ¡p8•áó˜^¯ò}’XÉGšvrÎÆ|ž‘¾zÍ)„ÃWŒ$>öÙ_«_…Ê#Áyƒ'ñ¾¾Çoþ$nI©a?É}ÃMç/û‹ì/©á”GŽ‚Û‡'…²‡†F;#e?i>ɛƒpøŒ'->9äyU,ŸûÅöQ8œÊƒðyÌ_ÏÝ×÷aíŒó»÷ªí!Á²( Îã¢&†T;†pì?Ðð•{ììܓ”oړÆQ8|äÎü>9乑ýœÛGáp*Âç1‡|–Ìùœ$Žýû™]8ÎalÈÊÇØНıŸÂc?³ Á9´Ï¾æqî)RÙ¯
+FÜspx¯ù#|sÄ×ÀòßÛ¶ÂáX…ÏcŽìŸmalëNÂØ
+…Ï1¼Öö=~>ç÷,Mx9קZ­<rœGÿ"Áí#áð
+wL(ìw«6…Ãs\¿Høpuïø»=×_Kæ2™çâçGÊÂApsPpûÈA8¼À3=
+»ÿŽÉ…ÃŒI ðáêÚ-\zÆÒʹ %ZIµïÓãj¯\ªA®£DªÁ!—j˜+Î~Õ>õž^¹Tƒ\ÆEû¼bs_öËÍÔÏ»KfxWƒÂæi Á9\ÏQpûÈA8¼àï{.ÆlÌQ8<Á<
+®î}>¥}¿\Ïf*Ó7Áù(‡ϕèI8ÎÑ~çãÛý2rð.…ÏSâ |¸º÷浟ðâ Õ~ïa®
+,ŸVbû(NåAø<æ€çl#8ó´OÞB碁pø„ßk>9äÉFp¼¼]nÐ>
+‡Sy>¹‰ýcíßã×ÇäÉçú˜^<×Â<û»X3‡üÚ/M¢üµ<Ñ>
+‡Sy>9àÍÇ‘Ï a(1Ž§Ú÷·^¯\ªa®õ>â(zÄï¶T[K5Ìïò÷™ì›Åç[Z’æ‡`ó9sœão¬•Ïí÷•˜?Â)·ŸcLÃNúrF‰Ó5.OGÁyŒR“ð9性ڰ|²[P°‚s,Â瘃Qô=î‘lˆï¡P8<ÅñIø<æï5(oïAÑ>
+‡Sy>9äcÚ þó4¦MF‚ñ=ý!ÆäH0¾_jÀ39
+›Ûôä ÏbãêßbÿîäPîõÛc6-Ã{F‚wåìØ
+£ºæ;ªkj a®üÊuý8â¥GL?¼O/ï½ÇA$R:-tâuýhÇëՎ×x÷Ñ0ׂñÏ%Gœk¾Ž¨Œ’ÂUÃ\qÄGÇýNé{ϱ“øö*ã{¡[†ÑLŒïmp¦£`|)_ÄmÆÚÁ¸úWÙ¿=ڈ+ÃP0¾Ý…;-‚Oå“ì×$ök"ÿjÿ*ׯv©_íŸ:$>uP|‰7æUìƒàí‹þöϺÖ/[ûzý³Æ?süó%í ‚sô?ejŸ;9•ûñ“uW˜y‚qí?‰ûÏ^9@þ`\ûïÅý÷Òþqÿ¿Šø‚q­ßÅõ³$̈DÁícÿÁýƒ·;(X|ŠÆ?+Ÿ˜Û|"_y˜m¡Ìø%Áøž 3ÏQ0n+ëàN„àMycûCíò¯«=ü»”_Äm!çÀ;¥ž;á‰øœ&û oÊó"õÁx–ø€<+ÏlÿRûù×Ô¿h_«NÃÑÐ]m¿Ã]5þuQûRÿ
+Áýñmµ$® ÁÛGâ@ž”ǝ´Úob¿*¯Ìc¡+ô?¿sÂAðøgæþQ´ýÊEñÃúƒ\ûOilªýð¯*¯Ì-œ8ZlKÏۄ+ÛBl˜
+ã]ìƒ`|*ŸÄ÷äªƳÄç_Ü>¶î_Vÿ¢};ïlsO77Iw¸‹Æ¿Tj_|~ÁýGnå÷¯¦ý«qÿj—Øoñº„×Eö«ö¯ßh|D‚q¾#ÁâW…ƒàñGû xûUí•ã‡õô|t'1> ¸}˜ýŒ‚û×´DûØãñƼ*¯Ì“òD܉þàç/Öç¢ýº¶_'ÿ¨}µ´o-¶œÈw†*÷êØÙ„gÅï7É+Š`¼ÐìtŒwåùTû“í/õo‘íòêÜãÛÝëÕ@>”²ã$¸£ˆ£Pýâ÷‹ÏèŸÑ)¾Ä ó¤öÛ¿Ô¿‹ü»W—AýJ‚c¾Ií…ûGÒ¾ 8GÿmõO÷ø¥Øˆåæ ß³ ;”Áx•öÁxSޘµ?ØþRÿù—/¯ÎSÿ‹êgIØ1·ñMÜ¿Í<?@ðúaüAðø¯Ì³ÚÏl_Û?qûCsþlß;ùjÿNöGû#‘Ø¿AðúaÿÁ¸ž_‰Ï¯¤çgâó3Éù§­ÇöÇlâ ì삂ñEoâH°õª¶»gô/žõ¬Â+ó&öA0®þ-öoM¯ÎÃ'Õo-ځ„„àKù"û1“Š„ã_O•ýë‰ê;‘pâÓãþ“„_æñÝd„Ó¾äßdÿ¬;`ýÇo'ag@Œ[sÀÎw ïÒ¾£SûŽ&ýãYyf~©ý‹ì÷%þ`\ë×¹~}Ò~$ûÔ¿:÷¯a˜`|B0¾¤}A0ûƒx²é×í¬þú&m8V€`Üîÿaç;ŒïçÓ_&!xVžÙ~Rû‰üËê_ÿìùGëwÆ׿I{ÜEÿCØ<7á Ÿb[-‘Ä?Œ©Æ«Ä„àMycûCíò¯¨Ѿ÷pö%ñ«¿æɇ7æ…îßIðö%ž™ÛëFlÿ‚Wå•ìÃø
+åƒø²ÛIðã]yg¾Ä>¶š51Gá¬vÅú¡`¼q|PpñEÁíCû àþUõ/ÚתïWïøµhßîɇwæEî¿@ðöÅû¼àýÎû%¼_d¿'±ßù‡«•Aðúu­_úM哸u'´‚ñ"þàí ïŸQpÞµöï@ðú"õ…â7ªÄoTŠ?ޟ€|)_d^b^äîì‚×ojýf¦ö!Nï—ïæ@û xû ÿ xü‡žƒÛ/~¿òl~ÿ¿ÉJã$·Û-Ø„Ͻ‘0í΃Bð¡|°ý©ö'ù7Ô¿þñÎò$l~׃ÿ /Ê ñ{|ìƒ`|ˆ oR?ŒW‰Á‹òÂö³ÚÏä_Wÿ¢}ï×IKâçó#g+ž|xan·›Ø>!xûïÌmó lÿ‚7åì×"ök!ÿjÿj¦úU­_ú%剸u§ªý+ìW;\‚·oËÒ¾-§ãïú>ÿ²žþþývæ¿£¼)÷øVµ_Å~Wޙóîp$|ÎîjÄ/âE_øøÖÝa~
+¿¬çWæó 毢àö‹ž_ûÐ
+ñΜ¿<“ëþÔÆ8;6çvÙf€ðþ„gþ|øå'žùó¸»! Á›òÆö‡ÚäÎásª+íP0n»GÂÎñ l>—pŒw±‚ñÂþ¡`<qýP0~q|Pž•g¶©ý‹ü»–øw-ªß5%~¾’²®E»G’ð¹×?|ŸŸ°ÿ„pÚ·ãú)Nÿ€ç7‚å…í'µŸØ¿¤þ%¬~¹ãCù`ÞØ>
+ÆípÐ~ xûb|A8¼ãî‰Vÿsj_Fûrì!8ïÿ¤¼¼ß·õ;Ù¿,dËaòD‚ñ½Ù엌‚qÛý­aï·_×!GÁxgû(ÿP0^¼:/X¿;ã7$ÏÊ3ñ¸¿"Áýë]üë\?˜€‚ǧ‰O/ß^$¾Û‡¾,“Ñþݜ½Kûºww€úµT±}šm^ƒí Âæû_¬ü%ãÛ݁öCðãÃûwŒWn?œÃ—_Ppû]ëñÉI⠂ÕIûÐnsßdWޙW±‚qsê‚qknø}µ•ê¾HÛû±'šÿÂ3?V¢7^‰¾§3~“p}Á9þ~ƒàöñ÷÷/©qÿp/¼¯R?˜Ÿšx¥>
+ƇòA|¿Î&û /âƛÔã²Ó
+Îiþk§øš9šÿÚ¨}̝¬þEûZu`§˜»}b}î~ݞ
+Æ'ç4”Ë›»®¿6!ùõ϶ïOp}aó™h'Œó—II0ޕwæCí¶¯þMöïÞø¯ïÕo™» xÎsžÙÏSìçIþ•Kü+\¿R¤~¥P|J•ø”Jñ%ž™'µŸÈþPÿûgÝë×/jŸ>¥ý@0¾Íeä!Dù¥å=þݺ?ãUye®íÛ¹}›¹ƒ»ë†¼)ȯr¿?±pa|A0ž¥}@ðúaû‚`|(̗Ú_Üþò=Œ[wûÓU*Ä¹ð>Ï“
+ÆåË](ln_$B‚ñ"öA0®þUöïN.å^¿½q®_@!øT>É><ÿ£¼*çúáîÇ x|ʐø”AñE‚·î® ö‹úWØ¿";}-ûÞLÄ÷þ´›çKÚãYyf.;…¡`œ¯$ßîf´Bð¥|‘}ŒOîŸû^]ü‹øZu°}@0®í›¹}ïˆu‰oØOCüKƒüK®O$8Çúƒàösû¹“_¼~x~àñ!ž™Wm¿Êö»ø¯ö-{þiì?Ql—lˆ
+Œowaý<
+Îa|·ã×(¸uˆuPý`}
+½_×ÛûõŠDŒª†Q]åÕU´… —hØÚpDÑ°ç€÷¢} ÇA$jÒÖ®õÝÚ¢í\íÝÚ¢Q®ö#W{qþ8âi¡šß}B´ýEÁ÷Nsªí\ý(QGÑ>ñEx+®ÚÎå})ÎmÑ(×ú‘kéWzq%õú„h;×{ß7Õ>ÐþK4l!8¢hØÚà}}yï
+[¼íóê%×sʏ>Q^}âX;+ÕÐ{è÷¢a$àê¯3­¯¹–æù}DÑ°µãL{ÊùºÛ; ûj)ßËqÝ.
+ýa^"
+ø+×YŠ¿z”Þ³†¹ú?³åG„_îÏYô$c„çÅm¡Wœ…$ß ­â, ÁøE+[Iøòl Á"º$oÊÛjuŠ•ë#$x|ˆãÊçLjß÷–™ý¿hå0 ›ÛÊ1ˆ/
+ÎÑþ öÙæ\~pù±¸þ(xyˆ
+à!oÊó©ö'Û_ÊñûúõCÁ9Äçá‰â÷òßwFš—m4ÇÁã‹;KàößåW§øÇ1 niû—„'™”'²sÆHðö›Zÿ9(þSã?#þU8ƗØÁâ“Ä?<~P?‚gå™ìÇΪ$¸«‹Ñ>÷FVè^â•yRû‰Û‰ øùõ!xRž¸ý¦¶ß$ÿ¨}µ´o²Ë‡ïLu'cåû›OO>|o‰žHž”'癞RHޕw²£d$/ʹ~9Kýr¦øÄÍŒ_¿Èÿžè)‹ãU⠂s´o;Ê·d7n¿o±3™Ýnµ¿çwvnEÁ8yŒãSù$>/ÙY ãEya._†BÁxWޙ©Î1>·°(~/ÿcç­Á_.!Áã ;Ë¢àö_ÜGñîpןPðãÃ(!
+V¿,ãòe)<þ°s+
+ÿqIüÇv˼3ÙÞ(œvCaó%;Ÿ¢`¼)ȯØÁøäÏPðöú¡àFYQpû_Ü¿®þEû¬øÔÏw–»ÃA<ŸÚ?¦ô¡í;Þí ;ï¢àýw>ÁûÆïŸCûg´ÏÐþ1¸Øé0ôú4øüz}‹þ §Ûæ¶T)Ç[²e…À[Låw2+÷•‡™w¶%Á¸=®âʹŒå…yRžˆßåáYYÆþð¬Lãú¥Nõ»“Ky¡ø½ý÷•o¶QjÅø„àñ…· (¸}äv+C͝¬þÁʺ]¾ìŠ‚qN•q ¯Ê+Ûïj¿“eŠ%üßÕ)KêWµ?r<¾hr²“nZy9¨~w²(/l?©ýDþemhŸhÎßí[•Wâv»öA0ÞÄ?¼aý@ޔ7¶?Ô¾¯,½µOÙ[u—qç‡;÷Ç/¾ê=ɛƒ`<íd‚q3W‡ðå×^è7®xþ@!øR¾È~¼E'ÁýKYüK\¿T¤~©P|ˆ7ä·;¿kYý§ó¤õK\?‰
+—H|`çºN_!á´ílBð¬<³ý¤öûw©ÕojýæÂöc~oSìƒ`¼Š Dü¡<‡ÃøÏñ/êgÝè_¿1$~c}àÓ¾ éñŸûý|™èÅw²Çõ…ãÛþ…åC0¾ÃqáñC0¾Ý…óãKù"¾7z$û ÏâƋÔ„Ã)>7Ï?öo÷Ô©~©KýÇ'i|Ò ø/Ìwu`gœãή ¸}ܹ÷w¦Á뗵~¹Sû_Ä­¹Ð>ÆípxؙçYúwܟÝɪý;v6wbüˆ„àY¹Çwªý)ö‹òÂ\w^ÁøR¾ˆ/=þâãÛF¸s3?¬?Îáù·_šØø¯¢¼0OüüÑïY~§ÿ÷Ô=ù“ßÉKùñ¿Û¤:˜¥‹‚ñ=© ž/Q0ޕwæEyaž”'æ—úw‘yIý@>”'Šÿ{~Í2¨~eHý
+LJød¾WºÄן/ïæxµ¯?_>ɤ<‘}x¾CÁýƒçC¼~Ä;ó¢¼0OÊñláÀö Áãç
+γöo¿ÿëûqyÂõç×ߗ7ûz_®¸?ßÉðÿÅ÷¤÷¿¯$/;9‡`ÜÌÁóÆ¿#ý!xQ^È~ü>àþÅï+ ^¿4¥~iR|ˆâæƯq|öFs%Ãó›·$\Ê[v¾ky þeʶ7*ðåJÎζ%Þ_“pvÎ-°Â…³ón‰ûg‚åƒìëÎÉvNÞîLõv^ÞՉY¸$|N8ïÏ
+úü¢©F¹Ú\íuÄùãˆîý‰ÍïYÛ¹Ê+×~ˆßWb¿S».OÞ„=’c'6ü’ `¼ò/
+Æ퇧!xVžÙþ¥ö/ò¯«¾žó®üR ð9á@n‚ƒ§ß[úÝ4Îa/)W'®ôßK~ÃõI
+Á»r/o_¢¯`ÜFŠ.à!¯Ê+ó¤öÛWÿû·'ÞRý@pßH-Q|ڋ/âÝ>™/wz(ß/îc½ Æ«òÊ<«ýÌö͝<„Í«…#îôPðò¿Æýõ4~ÿV¤ý@0Þ¤ýA0>•Oân´‚qsê‚qø…õpûK3¾hIüF6±ÞÖÁë9/à!øz=üÆ7¾^xf^Å>±ž×ë±÷òM¨Îñ‰ûMÃì~ü=0?ñÔ OZ>Q|ïåÀA0>Ä>Æwsà7²A0^}yéÃCpŽßØÁícü@pÿ0þ Äzá%õ‹öëÚþÛ¿g±Âç4ú‚qí¿ûïÊÙÇoŒ‚àþa|Aðúáz^b½®®>´ý·_ÿ@øѾû%՟ø듄'EŒ_4‹„Í퓚pÿ‚q›x¿Ï ¯Ê+ó¬ö3ÛWÿ&ûwOƒúàöBêvýŒøô)þٛ2à•¯W²ý$ÎõõÚ[ÆÃJ‘·d×òþ›+MÞË
+ã‹öÓ ÁÖóÇö7ϸÄ7Y•Wæ]ìƒ`\öÚBÁø”úàãsóBñ{ùï÷׸oŒ“àñ]$IpûÁm&J^>Òp'ãMś/O>|·í%`¤ã{ûX ƒ‚ñ½=Fô/‚gå™ìÃH
+î¬DCÁë+ÅPðøÄÍŒ_¶úûLž;Y•{ý²Æ's|îäPîÇß#áÔ> Êó¥öÙß/fÈ?Œký
+×ïNfå™ìcû`þííO*Æ'ã—Æ??>òÊñ©Ú+÷ßzIý@0ûKúÁ›òFöa%+
+î_éâ_ñú×ú«~Qÿڔ7æSíO¶¿Ô¿EþµKêBð©|’}Šï¢øš;Ô>“Û§IÿáÃÍm¿oÙ6Xð‘Ä;3í_Ü&¶ÀH$
+Æ-{Âæ¶=ìW„Bð¦¼1ŸÊ'q?@ÁýëIüë\¿ž¥~>úñJ܇ñ+VÿáüÒú]\¿KãsQ|lû
+ö'GïEƒýÉ1¢a.ˆjä*{¬ã£3Ã#8®öŠê£A ÁºÕ(Wú‘+i;®õnÇóþ*Zcw ­¡QQpÕ`vʵ4×(ï#Š¶sµ·÷¢Aì1¢Q®ü#W–#b ‰ޏ˜¥ÚÎuöƒ½ Ž¬A¼0—h°K>Q4h!ô^48‡0¢Q®ô#Wzõ‰õ£O,ñ[[´ß='çý¥Ò1ã.¾xò'·$̗AÁø^>4°|Æ÷ò˜/ƒ‚ñ¬<3¿”_ÄÛ‚ñ.þ`¼Iý@pŽñ¹y¥ø‘Û~ãøâ] ñxJ‚ì›'[UÏ|Ä; ïÝ_üž½oP0¾h&
+æ]¹÷¯Ô´}L*¹›ëÕ~À¯%öA>”Gÿ˜R?‚åܾ—öˆï¥ísqûmßÂíÛµtîSúÁ‹òÂ\ûGôï;9•Ol?¼þ pÚxÞ£l0KæNÂ,åûr‹³lP0>y¾&
+›t~ŸždRîåGãùŽ(/4_”ãYy&ޗØÁ¸ÖãQ‡sýîdSÞØþRû‹üÃþ‚×ûâ…yû Dû,mŸÅ¼þóömZ¾qyÅB!ÚÿÒö¿¨~Ô¿B0ž”'ân´Bp_ÿó_ÕñíÔÕ÷TLëžjXaÛEÕ"W.ý•ëhŸÛ4f!áÇÞü_ÿúÿϱàendstream
+endobj
+6 0 obj
+11801
+endobj
+4 0 obj
+<</Type/Page/MediaBox [0 0 595.22 842]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF]
+/ExtGState 8 0 R
+>>
+/Contents 5 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+4 0 R
+] /Count 1
+/Rotate 0>>
+endobj
+1 0 obj
+<</Type /Catalog /Pages 3 0 R
+>>
+endobj
+7 0 obj
+<</Type/ExtGState
+/OPM 1>>endobj
+8 0 obj
+<</R7
+7 0 R>>
+endobj
+2 0 obj
+<</Producer(GPL Ghostscript 8.15)
+/CreationDate(D:20070905000454)
+/ModDate(D:20070905000454)
+/Title(CAM output)
+/Creator(PScript5.dll Version 5.2)
+/Author(Jakub)>>endobj
+xref
+0 9
+0000000000 65535 f
+0000012118 00000 n
+0000012236 00000 n
+0000012050 00000 n
+0000011907 00000 n
+0000000015 00000 n
+0000011886 00000 n
+0000012166 00000 n
+0000012207 00000 n
+trailer
+<< /Size 9 /Root 1 0 R /Info 2 0 R
+/ID [( DbÜnî%ûZ{k¢)( DbÜnî%ûZ{k¢)]
+>>
+startxref
+12414
+%%EOF
/Modules/HBRIDGE/HB2FET02A/CAM_DOC/V2.pdf
0,0 → 1,566
%PDF-1.3
%Ç쏢
5 0 obj
<</Length 6 0 R/Filter /FlateDecode>>
stream
xœÜ½I®]K²%Öç(ØVãËëb ¨™9B™!!nC)à&böÚVç\^†züx —-7wóâ˜ۋÿçgùÚ~øOþñëãÇÿþ_÷Ïÿñÿþ@ñÏÿù?~ԟÿ׏¶OûÙçlÿ±ÎÏ6þãÞUöCÿÿŸÿçÿþ„ú_ϟÿãùó³êý/ VYmÿlëç(ø¿=ò:~Ý¢¿ÕleþìetÔìï4[âќNswÓ|›fÛÍ4-Í[7„úÙW_*ߺ\  Æý^ÿŒó•~›½üìcýÆòÙ.‡ˆšcµo4HÞhÖþhÌs@sÒÛkÖ¾9Äþùܸ^sôý&†š£¬þÄØÑÚÁš­:Í'DãûçxþÙ½æ*5h¶M Ašƒ4kÙõ5M¯ù„(!Í ù»4Ió5M(´'ÆÒ¾Ô|BlñNó)Õo4!DÐ|J»<¸ Ô\\+×P_—C<šˆ5çÓ*GkXÏejžçÖ&¨K¿ž€ó:n\§…€b„€©Ù³[A1€€˜šph‡h9ýøïÿÛßhõ?ÐU`sÿ9ê:_ÖÔ¡šç@¡²vÙLÝF9WÉã8A²îbLF¬ÓþõcíC¬cÌi<*ÙCìh ¦ÁøÑ+XbvS 9X§ÿy3÷ü…‚ß\÷k_ý„Ø"øêñȾÑlë¼×|Úf_}üFó ‘4ëþN³®wšµNð¸ué埅C/Ϛg~íqIóÌäýúžó±a|­ù„âæ3ùFCÄþ¡5°¶}í埅C¼Ó¼õë"Í[S µ½¡¬çýRó ±8ÄÍyÓ³ &†ˆ}ÒxâhЦ¿Ô||‡x£¹úùFCÄÞlÀp´•õuë0òıÝΧ…ü^ûÍ'ëÏø±–¯G'OˆÆ!bْæþz¤Àš;Æxjå—ßäó©
ó9ÊýN³œwšívyýË~B45Ϛ¦ùvl~Ö0M76ïwÂ(t­ÙïàIó1@5ßZÛÛ4M³vÏ&î¯ iÏêýuFÔg¶tªo–ÏCýHoµ~™þÜ×
+Þ½º@Aßfo¿Ñ·Ùۋ>µ¿I^î½åò<ÉËyÍ9ú­æõ­féàåû¢aCžLôº‹f™¥l¿~Ô{‹Âz÷Q-#DØ
+±BB¨•CÊMZÿÓf.T]/9w½ÅÜõs×{Ν„Û%Å%ç®Ý˜»¶cî»ÜI±RbHùˆU÷Ÿ.sXuë™aöÓ.g 7°õ̐úáÅ3VW©µê8pª‚¦Vš
+¡Ö¾Çbd€öOÇ¡¢ål¤:ùû¬¶Â7˜=«3{6gölÁlåpt_Ù£˜ýL¡Ì챜Ùc³•C³Ž3[cÔÂþ«¬†Âî ûLùxá J_0\ž›F”ë™P øõ£ÃŒM¹g,oZƑ€{#µêu1V¶†Sí`-o#ö_hµv™Í›]¨¢(¢rª%Â@ÌM-³y³ ¹OÖ"ßÉ1³•C;XËÛè
+û¯²Ú
+{ôâÍc™ÙcºâýÈáÐ4Ñ"@1ŠÙ£3{W ÄlåÐÖò6ºÂþ«¬¶Â®;˜]3»^gv½ÁláÐ4Ñ"°ƒÙu:³ëpf3³•C;¦3[cÔÂþ«¬¦Â¾àïéKîáõ´í—=ž›C쟧=x5wîkšõæÜÇ4»jŽºúOXŽ šaÍ£®Æ!H³zÍNk²oÓ$ÍNmץً Ì7."wþˆÚgXŒ».Гë'ƒ[ÖþD¿©oé×?I¿~þïôû—úšþ˜þ˜_¦ÿ[ýþ¥¾¦ßï¤ßï—éÿV¿©?y,þÛf¹
+5j©àcè›v-ÅÀ¯÷nŽ’$׼Šx/ÑÉâ;Å Ln¬œ¸p̓ɴÒú×gW¹{¿¯Ç'D[‰;Í?A·ExÉ?Åå¿Â–%ã`‡—j!ó²é¤Å™¢5Ԛph‡h9©Öþ>«ÿ_Ø°ÿ¢Ýo« ·rÊî
+WMíà€>)à iCD;°ÃDvcžià|wó|½V-}j@€M¸«VpŒ²XÌ© ‡vˆ–³‘¾ý}VcÿõŒS¾™Â@Wùn
+Swýf
+pæ…r2ýß4}Óiý§üAú§|™¾éÿ&}ÓMýIúëëôן¤¿¾L¿uð­¿mÛý þ®m£æoÛ6j¾ù=òmš÷}š¨ùû4ïi®ïÒó‹4×wi¢æ›ßð…~ ûBó ±9Ä;Íþ­fÕÜߦ¹¿Hs›æ~›f+ý›4ŸoÓdÍߤɚ¯ù\àÍùÛۇ@ÚN[ג³$ÆQð ÿWŽkÃi!{ éGZ<¾¥uìK©)‡vˆ–³‘¦AŸÕÿо%˜}›3–&4b¶r`šj!(ÁìsÙç8³ˆÙÊQî̾%ö_e5ŽX˨ÌyúŠ<oÞ#OšO°o41DÜ#_a7úùݹ­º'‡x£ywn 5ï˹-:ÁK _Ð°Õ–xBã|£ÙÖ~§y/¯ ­úõA]÷Y5Ÿ%0ýóõÖ~Ó?ywÿ3Q{öýÒò'ÄâÁòÞÚýN³·š§ã:åoNk<+ózZ5{Z5ߜÖè0}Ãõ쯸öf+Þþ<Kׅñ/6aÓ2hN§Y×7'DzoOˆæïNˆæë ‘3ð„Èúú,ÂÁÞ¹Rš¤É'Bߟ@M>êÒì¾Æö˖P`¬·G>íÛ œký½f;ï4Û8ðK,_·¡'ÄäéTÊÁM§¿;Ïš«¿œg¹0Gœg}]B·Vk5œxŸ&j.ú&N„âXoüFsâXo¼×ÄÅÃ/ϳ€&//†ú„mT}|}æâ q8DªÏR¿Ó|ÆËï4'•m¥®‘áåÇ!4šg+øõ㉩;³Ý­CŽ‰¯ÑPŒ `OC©Æ‘¬åm¤Ï6ŸÕÿо5˜}›3ûvgöíÁlåÀ4Ñ"PƒÙç:³Ïqf3³…›´ãÌÖµ°ÿ*«q¨:þ¯c4ˆåÊqe‚´[쟴äx‚ž_‘_™ï‘ï™/‘/‰o;ð=?"?2_#_ßñ6ßèì¨Åïø‘ùùx̐ñ=ß#ß3¿"¿2#j<Aã±èýð÷]†4×AþœÀôüŒüÌ|‹|Kü¾'èùù•ùùžùùòŽ¯²¡•a=1~Ç÷̯ȯÌßÈßÄcOÐó3ò3ó'ò'ñX¡Æ4–bp½‹Çz&WK鬗PëM¨þª¿ U^B•×P{çP*ñ¡ÆK¨ñ&T} U_C­“C©ä]¨vN
+zOÐó3ò3ó-ò-ñ0Ir<AϯȯÌ÷È÷̗ȗw|×ó•v­[üŽï™_‘_™¿‘¿‰Ç1ž çgägæOäOâ±B'h<ö}¦Ú\>°wW¡ñ»ž¡ã{ä{æWä—ñ…¶-wç¼ò=ò=ó%ò%ñ–?º›ÇòW˱©ÌǏZ«íoqüˆüÈ||Mü:gˆ|ƒåqãŸ
+q‘g£üÂíÓÎ €Ë{î5n¬U´ؑH‚ô$­Á˜`ŒCO[bj‘Y¬åm¤õ`˜ü}–ãòð¶â)W0™D杓1Í
+?{ݯo©yB,5+l‰Í·×úTü0v_.§©° \ïúúƒYÁ!ö])ÍQ`£Úï5{y§9¯ÜÕ³¾^ûŸ·¹@¡nT÷¯+VõwùðPa“ÓþMâOˆÉ!Þh®û›k¿PsÝ|íW-pÜ­÷¯[ÅbsˆøÙ«Žmšo?{Õ±LÓ]Ù×özsùk…ͧ|;^¼üu™æ—¿NÓtíIŠýêA%|£™ô¦¼ãh¬ðãèF !wI Š·h¨„¿¦q ýŽæÓüË.j%ǐòAþó?mæþá«nœ;¸šÑå®ó„OS^;åNCèuO+æŽÓp¹“3HC¹cìr'!ÔÊs§iøªûO—9º陆Û5 iüqHG¯"¨°ÉÞ®)¨Ç]a€×™ÙXÍ°ó­Eî*ŽQ®)àԄC;DËÙÈ7#ýuV[aë5 é EÄWP"zM ˜¦ZtA:†ÇZtÇ(×pj¡¢ålt…ýWYm…­×0ËÌæ«(½¦€ PLS-r©Ã:Ìl¾Š€cԍv”šph‡h9]aÿUV[aë5 3›¯" Dôš2@90Mµì`6_8ÀZÙ­×pjÙ­ZÎFWØ•Õ8ûß8
+—&ñe/øíèE0{\ÇÁú¹já.Ø+Ç ÒR=im¾zcd!5åÐ,Ñr6Ò´þﳚ
+»E³›7»z³K0{göÚÎlf6A6µÔ´Í®ÞìæÍn/…ý×YM׆¬`6B5`:³×ˆf7ovõf×hvõf7g6ÆhfÓu`Â-g¶·‘ïhù묦Ž&j6ÂÊ´¾ŠMk­)xix/ sðIµ5› €Z…MËš©)‡f‰–³‘
+ûï³ »—`6B5ûz³O4{9³Ûtf#0³ Š˛}¢ÙיMf±–·‘
+ûﳚ
+{E³—3»OgvÁlØ?l\uf#0³ Š͙1šÙ˜šr˛½^
+wjWœÙÔlÞ9M –˜†1šÙ˜šrәímäÑÈ_g5.DÁ6ˆ"Èá
+˜Îì3¢ÙݛݼÙ-šÝ¼Ùݙ1šÙ˜šr˙ímä/5Õt##\¦ƒ(†zñ`ՁRíã¸AT}F6Žƒ×©T  yÒpˆ´x D1ê ŠRSí-g#ß«ø×YM£‘Ì&x¥vfã³zÎìëÍ>ÞìÍ>ÞìëÌÆÍlLM¹îÌö6òh䯳š
+ûF³¯7ûx³W0{LgöÎlj6A1`z³W4ûx³¯7û¾ö_g5uàYJ—í.éèÄÓ ¸Ã‹$Ï:¼3P8ðpª… Ëv‚ŸgC-þÖO1ÊÕœšph‡h9¹ƒü묦Â.ÑìâÌ>י}N0ûlgöYÎlj6A6€´dcÅ fSjbvñf——Âþ묦ÑÈfº7»E³«7»x³K4»x³«7»E³»3›ì­‘ ûï³Ú®1èx#ªÜÆ;pÿ7C<†åpL®é\tã3ðp­çSüx!Ó¤ïŽ1¶ÚÓ1ÆÙôf§‚½ŽxÈ5¼=Æ®Ð==|̀Kß$ö-:N`< ð¶ý©—.ïŸ~"¤m„ìð5
+¡ÌÎ £~IúŽwNjߞ7væ8}9ÏLM8ûƒù“ùø”ÿ\~øחßÅkÙº8²ÒñÁVk¤^ ü‰?âè|q½‰¿ßnyoܵ3k°/4ˆwŽÜ ÞÔ_§Ç@ä5Á‹h‘÷‚wéŸçG„W¥·#—ÎÀØ
+ñ—Úø1Û"¿´c~i'òî öۓÙøò°çSüÝÍ)äŽDÑ|&ƒàÉD-‘¿˜HԝîvQZFa ü4©% 4—âpÊڑ÷ãOä§T)óÖ·ÄKAÕ¯
+ñ;Þ ”·±Ãã¢!Á>Búî
+ /xgŸÐâÏùߚÿ5ïRÉሿhCt|—´‘ x1û¸#ú^<üZNӟô3,‚Èÿä[ÃËÊïpbm腖ÿ¤Cn&¯Hs|Šaq».mÞéh«íøCóà'º$k¿³ØS:xÅÆTÈWpÌÀËoŽëd×Lü’—,&ܳº]—õË
+ú¬¡_f
+\†p[ڂàáé²4÷­Ç ˜‡eœÀ‹—æà¦g?.-¼âN¯ZGx­êƒß1ëO$֋óæT˜ Û¥‹Åù]¼N‹Ð8^q‹¸^ ü<N?ŏC0svAðö1:'P>uÅ!U1ÂïôÞ¦Û·}z Üæ;ñJ{q®)DÞ ”wkU^ð&þk¯êj=Á40ä·øŽúÀé÷´;ò%òô– ê#œuG~Ên“—ôÙïʇôKH¿gÞ „ßVœ÷Œ_¸8Æ:y/PÞUžL³øžÌKkò?ãwú/ùÃEÇ ~©µ¹&O+Ã[†;¯¸woŽK ɯjßZÒøLëv5áÀÃpiۘ+>x]Úó´ä݊k—}m‚^!_nÖ „w‰àâŽßµi¿yžžX°®7dEÐó~åY¢·}¡‚¾äØÌ?˜Bó«ø½¹6Ä÷K|²âç÷²zfïý·í÷ð±Uïø
+C3å ^g¤àBûÍ),ÏÉjÝt3V/ÞìŽwå·[uK²"9Ãs&ÀW3w·ôìÊï8°FËC¥mÈoZ
++Îïe3ò6p˜6ÞšC¼™Ûçô ì§[ßðáÝ” à›vü¨ ތxAFí§‡º]þ¼øSÂÏ9ðœæŠü€Ÿëԅ0€£º%[/Àõ°Ï¯ß8¼Húäú$p húµ8·&ôŽ÷u&âèÃW¡?ÝÒ·`±?ôË?&PÞ§ï±Ä°Þ²B<'ñG>½áÆƧ+qSu'`Þ;Þé&à2w»Ûƒ#/|Ü|Þ „wí âÒ}Šß͒Oç‘øÞ6‘Þ
+5ý*Hô@Þ'¹9S’}¼Ôìû¸äU<ïß² ¯ˆ}±+Ë>^òJU–“¼–½ÎB`s"I¬}e™ å~´Vá—aø4§_•¡é`•B¿{*DÞ ÞèÓÇw? €ìãÕgÓÕ¯|Е á·‡³CØð%Ò†Õ6ÜξZ´4åä=oFøàšÁh$f…@~„óƒsG]õrYМOw½|ÌÃ\¤€Ó㧵|”Ä/c‘æÊ1¤HIÏ¿ó…Ù§Á
+bÞV‹„~·%¿©w›0ï~÷Ì÷È÷ė¨_²¾úEæ[䗜³ ž¡çkäkâe7óge>꟬¿Cù®=3_"Ÿêg­P¾ ?CýøÅqæ£~î×Öå»ÆÉ||ªŸÕcùö\¾½E>×O‹ú-ë·X¾-—oõSsýÔX¾5—o‰õSrý”¨_’¾Nˆwó4æO¨w^WøùT¾ú­ˆù}2õwÖ_¡|Ýjƒð-ò©~æ å;çÊ||ªŸ9¢þÈúÑ?ÍìŸfôO3û§ýÓÌþiFÿ4³š5ê׬ýÓÌþiFÿ4³šÑ?ÍìŸFôO#û§q[ä³~ôO#û§ýÓÈþiDÿ4²Ñ?ìŸÆŠú¹ÿÑ?ìŸFôO#û§ýÓÈþiDÿ4²=ê÷¬ýÓÈþiDÿ4²Ñ?ìŸFôO#û'Ýå.|֏þidÿ4¢Ù?õèŸzöO=ú§žý“îE>ëGÿÔ³êÑ?õìŸzôO=û§ýSÏþ©Ï¨?³~ôO=û§ýSÏþ©GÿÔ³êÑ?õìŸìóY?ú§žýSþ©gÿÔ£êÙ?õèŸzöO½Dý’ô[ôO-û§ýSËþ©EÿÔ²jÑ?µìŸÚŽú;ëGÿÔ²jÑ?µìŸZôO-û§ýSËþI·2?²~ôO-û§ýSËþ©EÿÔ²jÑ?µìŸZ‹ú-ëGÿÔ²jÑ?µìŸZôO-û§ýSËþ©Þ _oÒ¯Ñ?ÕìŸjôO5û§ýSÍþ©FÿT³ÒãÁ̯¬ýSÍþ©FÿT³ªÑ?ÕìŸjôO5û§:¢þÈúÑ?ÕìŸjôO5û§ýSÍþ©FÿT³Òu á³~ôO5û§ýSÍþ©DÿT²*Ñ?•ìŸÊ‰ú'ëGÿT²*Ñ?•ìŸJôO%û§ýSÉþ©¬¨oëN²(åËˌy]RÇÇÄ»ñ1óQ¿e}»±y7g¾G¾'^>?1_væ[äÓºç½^_ çkäkâµÿ!Þõ?̗ȗÄëø˜x7>f>ê﬿Fà×Hü¼Ÿ7ó=ò=ñã~œÌGý‘õ{,ߞ˷·Èçúi±|[.ßë§åú©Q¿fýË·æò-±~JªŸsCùž{3?"ŸêG·º0²þé‘Oå{v¨Ÿ³Oæ[äóºÿ
+å{îÌ|‰|ªŸs¢þÉú;”ïÙ7ó#ò©~Î
+Ï_ÏHüˆüH¼¶/âÝ5Ì÷È÷ď¨?²¾¶/æ³ýº>E¼­O _#_¯í‹x¿¿Šø¨ß²¾¶/âÝõ™Ì—È—Ä—X¾%•o½¡~꽙‘Ïú'”o='ó=ò©~êå[÷Î|‹|ª=MÇüÊú«F>•o¡~ê\™/‘Oå«W×0Ÿ÷ÇÕõGÖï±|{.ßë§åúi±|[.ßë§æú©Q¿fýË·äò-±~JªÝN¼Ûö-||ªŸr¢þÉú§D>•oÙ¡~ÊNõS¢*Ù?•èŸJöOeFý™õ£*Ù?•èŸJöO%ú§’ýS‰þ©dÿd—Â2Ÿõ£*Ù?•èŸJöO%ú§’ýS‰þ©dÿTJÔ/Qÿéï|ù
+ôüˆüH|ðO=ß#ß¿£þÎúi_yòOýÿ$Ðó5ò5ñÁ? ô|ԟY?ø'ž/‘/‰ï±|{.ßë§åúiQßÖÏy#»|Ÿæmòö}Zøù¼ï^¯J'Þ¾O _#_ߣ~Ïúò}Zø’x™ß2oó[æõ†)âÝM¦ÌÈçò)Q¿d}ù> ||•ù-ñÕ]Ê|‹|*ßzBýÔ³3õOÖß¡|ë^™¯‘OõSW(ߺfæKäSýÔõgÖ¡|븙‘OõS{,ߞ˷÷ÈçúiQ¿eýË·åò­±~j®ŸË·æò-±~J®ŸõKÒ·c]È»3[—ȧú)'”o9©|ËõSöÍ|ÔßY…ò-ëd¾G>ÕO‰þ©dÿT¢*Ù?éV̏¬ýSÉþ©DÿT²*Ñ?•ìŸJôO%û§Ò¢~ËúÑ?•ìŸJôO%û§ýSIþɾ_ò1¨äŸìû¥ðY?ø'ÿýRøù–øàŸúMþɾ_
+_¿¢þÊúéÜWòOöý’ùäŸìû%óÉ?Ù÷KáGâ{ÔïY¿Çòí¹|[¬Ÿ–ë§Åòm¹|k¬Ÿšë§F}ÿ^WǃfRþ|Œ­&^ûâ]ÿÏ|ÔYßÞCÞ¿F|‰|>w'ãæÝø†xíÿ‰wý?óQ?Ÿ»ÓóGÌ»7™ï‘ï‘×óGÄ»óG·ȧò_'꟬jäSù®êgí•ùùT¾k…úYkf>êçs‘zþˆù™ÊW_&d~ÜÌ÷Èçòí¡~V?™ú=ë·X¾-—o‹õÓrýÔX¾5—oõSsý”¨_²~‰å[RùÎêgÞT?zþˆùs3?"ŸêG¯|`~gýÝ#ŸÊ×Þ«#~Ì·È§ò3ÔϜ;óQfýèŸföO3ú§™ýӌþifÿ4£šÙ?Íõ[֏þifÿ4£šÙ?ÍèŸföO3ú§™ýÓ¸AܓùùT¾#ú§‘ýӈþidÿ4¢Ù?é5!ÂgýèŸFöO#ú§‘ýӈþidÿ4¢Ù?õG֏þidÿ4¢Ù?èŸFöO#ú§‘ý“ÞöÆ|ÍúÑ?ìŸFôO#û§ýÓÈþ©GÿÔ³ê·D>ëGÿÔ³êÑ?õìŸzôO=û§ýSÏþ©¯¨¿²~ôO=û§ýSÏþ©GÿÔ³êÑ?õìŸzú=ëGÿÔ³êÑ?õìŸzôO=û§ýSÏþ©—¨_²~ôO=û§ýSËþ©EÿÔ²jÑ?µìŸÚ‰ú'ëGÿÔ²jÑ?µìŸZôO-û§ýÓ˽mFý™õ£jÙ?µèŸZöO-ú§–ýS‹þ©eÿÔZÔoY?ú§–ýS‹þ©eÿÔ¢jÙ?µèŸZöO­Dý’ôkôO5û§ýSÍþ©FÿT³ªÑ?ÕìŸêŽú;ëGÿT³ªÑ?ÕìŸjôO5û§ýSÍþÉÞ2 ~dýèŸjöO5ú§šýSþ©fÿT£ªÙ?éõOÂÇ{KzÕ÷rù”y}΋x÷“ð=ò=ñò}ƒyû¾!|‹|K¼|eÞ¾¿
+õwÖ×õâݽ)Ì×È×Ä«!Þ½Í|‰|*ß2¢þÈú=–oÏåÛGäsý´X¾-—o‹õÓrýÔ¨_³~å[sù–X?%×O‰å[bù¶{}ýô||Ö?3ðgf¾D>ÝÛs÷ü‰_7ðëf>꯬?OàçÉ||Oü؁;ó-ò-ñ=ê÷¬ßcùö\¾-ÖOËõÓbù¶\¾5ÖOÍõS£~Íú%–oòOv~‰¯iJþéôȧò=Á? ô|Ô?Y?ø'žo‘Oõs‚èùùT?z~I®©Š÷B¹õm¾fªÞ­oã5Sn}[øù¬¯ãGâmü(|‹|K¼Ž‰ß+ó5ò5ñ+êç{±l}›ù’xóïÈ;ÿN¼Ž‰÷o@?"?ߣ~Ïú=–oÏåÛbý´\?-–oËå[cýÔ\?5ê׬_bù–\¾%ÖOIõ£çsˆwçs„/‘OõsNÔ?Y‡ò=ûf~D>ՏžÏa~Ì÷ȧú93êϬ?[äSùžêǝϾF>—oõãÎçõ{Öo±|[.ßë§åú©±|k.ßë§äú)Q¿$ýýÓÎþiGÿ´³ÚÑ?íìŸvôO;û§½£þÎúÑ?íìŸvôO;û§ýÓÎþiGÿ´³Ú3êϬýÓÎþiGÿ´³ÚÑ?íìŸvôO;û§Ý¢~ËúÑ?íìŸvôO;û§ýÓÎþiGÿ´³Z7è»ó9—ȧò]Ñ?­ìŸVôO+û§ýÓÊþi­¨¿²~ôO+û§ýÓÊþiEÿ´²ZÑ?­ìŸÖˆú#ëGÿ´²ZÑ?­ìŸVôO+û§ýÓÊþiÕ¨_³~ôO+û§ýÓÊþiFÿ4³šÑ?ÍìŸæ‰ú'ëGÿ4³šÑ?ÍìŸfôO3û§ýÓÌþi®¨¿²~ôO3û§ýÓÌþiFÿ4³šÑ?ÍìŸfú=ëGÿ4³šÑ?ÍìŸfôO3û§ýÓÌþi–¨_²~ôO3û§ýÓÈþiDÿ4²Ñ?ìŸÆ‰ú'ëGÿ4²Ñ?ìŸFôO#û§ýÓÈþį?³~ôO#û§ýÓÈþiDÿ4²Ñ?ìŸF‹ú-ëGÿ4²Ñ?ìŸFôO#û§ýÓÈþ©ß ïÎçß#ŸÊ·GÿÔ³êÑ?õìŸzôO=û§¾£~>?1e}ÅÝ.œ¶¸OiB$ŸÂ™ÒŠ\´Ñ}Ž—Xò^÷)mÉÉæÊr‹É;ÞõÑ$mZ×÷‰,HÞ÷>ÛK,y뻾‚dAòî÷)«/.HÚ?ËKä3:Cژù˜Î¸9–‘Oꌓ+`äÃ:úî“ ’ªqì\#ÙÑWu\Tc½Ä’+`ä³;cæjùøŽ>¬é‚¤
+#WãȇxÆx‰%Ÿãý¥òQ}¸Ý‚äÓ<£½T@>Ð3êK5æ3=£¾Ä’õŒòRùdÏ(/՘÷ô›+ çó=ýæjìùˆO?/±äS>ýä
+èù Oß¹{>ëÓW®€žûôwس;ìó%–|觿¸ÃžÝaq‡Ý»ÃvA 0›qÐøj±evñÞÎxÕ¤«Çä÷EÂAÀiÑM¹‡Þ]= #¶,±ÅŸ$ª:’‡2üû„üDPë2^ÉXî@~hè­ÝY’ñ'¼‹žBH¼äõFk~a:+¥óŒ»ªBÌӆWJôieü€¢àiÍÕAÉ6Ç\@Ð]Ê1 ,`QÌðI±b4ZnKÊ»½©ƒë@$¾Ô›”¶,õ!ø׏,ɍíòj—ìîPɵ°CÞ=Ó5\=zIƟðbm
+yú‹1TΎ!äÑìKÞYøy'^à†ta/É´“*¯ù‚×Pö4ueK-–ýÒK”âÇ×T­Aø
+>bÑÒ|IÏzøÙ½á.=â%ôÛý†:Q‚¡øA«GÆu,ɉäÊÓ?•¼¬áµÅî[DGüa–düù㖑BtÁ'a—ÎJéT|²Ó¿§tÛ5ñ-O§‚lÔÞ×q§‚xJàé{‡‘h µ,I4M¢,xÂûP“˜U¸"Íqݑbæ«Ë\àõ%'wêøÊÃ#.T ’+ýT¥½ÌWº¶ZÕÇ:™4÷Jñ> ;¬*oI÷g¡ôÅûmÝà¼õ%T”düùS!ÄIlj«3r2q
+*±¥“Í—P)­.Ö¨„\”YGlöK…gIƟX.RVâʗ¸XwÖ¶½{Mpb1.xøÃ[g˜ìÿõ#K2þD7xCY}8‰Ô5êâýŸ…‚ÿØêÜ.ØðÀ²þŸJ±í ôc*ºœø¯¿Úyô¸ýÄùlÚóK¯
+À1\ƒu´ÉýWO¼ãÏ_üÑñ´òT§ùÀâ9¾K¢y{º·t„\À´ÆÍ®Gí렂¨–ÄÂsyâ¤rà…ÆÖ¼
+ Š¨øXµ?šÝŸ$hCWŽ¬_² í:Ð5UàTíPþ‡ì1pk`mÌÈ àö/xf…~  ŠU te
+;}õö؊ɑñž %þ8-…wèS|1¥ŸùÕȲðݒ]¹þ¨³ì µ¥+¡eþ-qnjðõ’]Š¦AYÆmg/qÔ´;ãÏ'ĉ!¶ºª“0§“%FK–X2‚m[žNT\¦üäÇmw}ÎÑåPQ’ñ“ë–R׎›>Úî]­1™ÔQÕ§JuP¢ÏÐêk[j]yøÖV¯–t’ký{¡N %-̅Š’Œ?ÀÎBÚ
+£-T”dì§Bódb¶?L%ôŒ¯IÌÇ8Ù~ ÓÒRušœjnžX·hÍ-"“‰I('z&K³X$%Ù7¨÷ô“åÉK²Ö§ AGTçU?Ñ ËÓÛÛVpLväW/±ØF-'k/¡:ù†´tmfVçaä·­S^•XÛÊ2ʝt²þŠ-ŠZŸ>D!¨¼¶ßƒ>­®Ï6KNYâ´f¼°¡eÅñfL>Nc•n#H0×­ekþ(Ô´çÔ5ÔT_-k“SFiüArjӖŠÉkd‚Ÿéµ¬Èiˆˆÿé$­C~5n«ÆÐgá品“Ð’µü¶øC¨4ýȒŒqÝö¬+¤#e3x]Zҙ¼T.¿¢©-yhyÊ*ã1Ë´ã¯ïBiïfkÄÖgŠEÖ¯òZ­XDu<dL;¥…=±ÈÈwÊÈNב—mHy·jýê™fŸCŸ= 0€Oàºçà³ýl°…§ç¦´‘†kvöÐZo–X‡*A0”Ÿªÿ€õ8U›9‹õfø/Jƒòo¡=]yØ+öp/Y¾-´,½˜€Aá5ŸøÄX»‹t/x>‚î~9´ˆ05°€ª© €Sú+bã¾;w6^t۔Ÿ
+TKÁ/¸=·½ÖQð‹’°h ‰¹«3&L¥õ;üð¯ãí.aä»zäTíÚ¬`æfY½*͊—»˜+TIј+^
+ÀÙ,À`€—Å\üv¯âuËvo»àáŸDµ}ÀÒ½e¨zÑÆLY™| î;³ƒŽ+^Jûñ¥?å!×lÝõöl`Õb>Öm|(,.æẁ“#Ãf¶<à\€|ºT·OÕ_܁
+e?^Ü=h
+ §«zÎåÚ¶ukNá@8¨¿à©ýfölÐÔ[¯wM¯vîrA°•ßzêöè}w½€öî~ÜYùQàåÎÊýæî-Ðv…ÀÈdäˆ]ïÛFˆ™  %›×¬
+pœW^bµÝ€¥A)‡<׍ÓHx 8ð)oIÄñûýø"ÀÈ¢pšPÿ涎—c1#?]dØ¥‘«‡'ôž*Áëýþ»vÿ|Óö?Øh溦où¿íöųàßãíœÜY©‹6¶BÁQð ^ǁÕ«€) à“’Ÿ1y´–Êï<`¿6°3P
+W{ÎÀ¿0V
+0€O—b)º_)èªÎ~ébæuèò̚˜!È|êz0
+?ü]]¿Ãê¶WKÈñ-}µ¢DvJ7ȕóälÕ^€~¤lÏ­Ð\¬7ÄÚf,%êX´ßð+ê_—…îJ
+&À…ö­?^ˆ7,Äó¥s´jÏ&~ÈO‚°Äïº:ZâWGþ/•êl‘×µ.ïOxü…ÚåÔ®<ï:6>kŽ[/7΅^û}î˜Ð‰Êj
+`Û.l§ÙÜT9@²—¶A|Íӎ
+M;1s¸!ÀíËnõ/C'ð ä&†•‚Ö¤ 1Å8eÿ¥¦Ü´í l£Œã\è›î”G·Õò…7È|W……œ² ÌõRžQs;3¡¾5û„Ìíóž3ߤwìÁó½
+¹QU@Þ
+ŽÚZ~â=eö]KÏæd_Ñæ PÇѦK¢uŸDS€ëKò¶S™£ÑÖƒw÷\¬‚ïùvn |ÃSo€HûÎ<øT®35À›]qæ<eY3À>)Eȑî½#¾q`˜ Ë.D2u`8|òS’Æ~ÒðUÍ­o>p(ÿÏ·<@»Û€MÔm¥ð)q+íêAqV­ëQèªB>`5U0l&Ð|ÒK€l¢ô0,î cÉ)_,.÷:!*èª9C­ø­RÇHæ¹ýV”]Om·O¹w•Î˜‘÷‘9¥8šãº-Ü>cµ¹çMK GŒîµÂ¾)d¾¨Â[·6ýA4LŸ[$þriˆñL·²Œ”姶oQHûÇ°¼äV·ïùƒ‰mÇCÕɚp€|Š®ràShø'@~ª ‹ãºì?k
+•\‹÷>éñôI0à}ÏÑ© ԔÏÜ0€‚çä̼ §‡ô9º<…‘Ígøø€ë€Ž¿æì½+z°ºcVÏ^S~$ »çÌgqÌ+FtœyzÌA¶NŸ©©ŸAÓÀm£+È šSå{ãlŽËøtO1
+åú è.ÖbÅߌ{ÎñÂ!ÅßòÛû$ÎYWß3”0/w0ÑÌR=-¥z,
+9‹.p»§¦R<3jÒ×
+|}­ÁIÃ.ËN@§3
+ÀyÀùGç±Ó]VŒnõtï
+黟ŸÊmæ,"< (€Ï
+Ž+.N³/Ü®£ðr<C»b>Îàý”< ìÅI’phbÝÈ~
+Âø´ñ·xtmr^E4o ·³*ÔÑA3mö9‘r“+r»pé§ÑÜÞüñ8Møa5®üÉ5ތƒ?ǦuZ+ŽëÄaâÖôàœà?ªÂ ŠÓÄ3ÇÆEðMÓÛ³¼¥;æ‹C8˜
+µÁIdÌ5´‹¬¸†Œ¼Ïò¿h‹¨ã ð̦|0,ËùgœÈ³ƒtàS¹é9>N΀ïm潨׽ÿðö|<krsa ž2ÍÀyÁh†¯„ⶩÀ)KÏ;À'W½rÐißQω@{°Þô84÷pǟ×Æ£õr^ÝËym2ð0îÅ®??ÞªAJµžÈ òZ‡å®ø ø(r§ëØ`‚¾ÃþüXñu7^‚o°w؏ô‡ôuW]GñwãìÉÓؙ·kñ^ùúÓ¿ÐN'xÞ`0ÃëÂÁ¶ ~ك®p¸ÝåwN|DøO­âŽ~`8¿ðèÚf<º˜B_¬Ý¸) 17®#<ÁÞä‡äùî <F¯1;À§r2^…$ª$ÑàÕÝsCÏé xI~Çä]EbÃÕmè å*’¦ÅI—›„ʨ¡2ð$¹¯ ¼>Åó€¾ü¸„
+5­ÂRm–*Ò§Ã醀bá“ ¼fÓjÂURƒ¼ŠZߧB0G‹í.W ‰—ÈsÒOÒÂQ¶á©hÈ;¦SÓUîÈQqÜ*NkÙAjÚ
+1gLO·Ð¢
+Ol¸[žiK„^ñL; ¦íü~á¡Œ¼ÅþÞ>·NåÈ?Ì¢ÛbÒwØúHpøÀÓGã·Ú.ʁvEÛ4w°iŠ[3‹© €Vw)šcõ;ÖZØ`JPJ¢{̼_ÑÚ>­~,V¬¿%;ìp+kb±÷¾¸-ý•à†Yw3%îüó¼Á •o—µröl^(©‚v`_;ò>檩:]ӃáRºác¶™÷7š@¿JŠFý Öü>êÝÊ¿Ãã•YÓRÃþ?¿M÷{~D?7Û6u‚K:HÜhÅ}n„ª6˜Yx¦Ž§< àS¹î¹æcm.Öbmv7C[ä³e÷GÚàKAµGð0°‡"nkO `I‡EpzÎ<.Ūwn'åÊNÆK¸}­›ß¢bÖMOߪ(Õ
+áãxؒ+¨@oQ_ $-fX9ÒWãJd׃£JboÏ-D€k°"ã“`kâÒ£v1?$øâ¡\…u
+u‡Yœ%|Ú/Úæa&êö
+OxÝ*Žsy ¯9=Ušþ¾>ïë}|4µ8:ü7
+ïC.‚£€cmšÌfԄµq;–Â.ï9þé†R85•žþ¶R8Օ©®phéKçV
+xìC2çl0©.ã ¤RÀ“6V
+0@ÇRعV,…í:Ú#y. ÀìÀÛQgŒðú½¤Ç¯£
+”„ºýô­(»R•<ÝgÍж øT®{ƞ8fÛ­ÒÍ‘=³y2..ÍËø1ã7güúŒÃÆ;Ž ½²ìê“yÏN×à#Â>•+Žã.…c½9Öb½~
+ê×<ö×úS Ø]Êwxàf±ÛúdÙ½$Ý°²K˸ñ^bÕ¹/ŒeÈ@å«G>Â@7#)wÝ wúÔ°ƒ- Š<¤}qÕ틛žKƒ"ÜØcƒ¢[Ü 7ˆ=¸‡Ïl½Í•n!¬ÅÙÁ ðzÎm\„Í/ú”3CÛYÂ
+r£!m\¬<ï½ðªHÝn·s•SŸdºr)~C›¶6ÕåÖ@°HtN¥·–+Ê¥m‹Y¹­z\Œ~æ;êҖµ©&@=‹qØÌpl;Êmoøʆ¯høò†¯høò†/oøʆ¯høò†OoøŒ†oøð†÷lx†wox†wox÷†÷lx†woxó†·hxõ†WoxɆ—hxñ†—hxñ†oxɆ—hxq†ïë ß7YƒÛ¶ øßè é#°#¬åd*dŠOojšvLuû€øe„cEódõ
+8“1ÎÀ¿t¶Òä.8„©×rJ໧Ã2b¢ˆÜ”½-oïªGO¢QÌ0§¶³aßñ÷GT[Ϙ¸ïÂñ€ƒ]¸ÙB8¨!>éÇØÝi6ˆuã6=.†;AŠ•GâñŸæ^LÂç†~Ëwù¦ð–Ø¿~Л>ÆÇaD5DÔK0´ÌË„Ï£¿ªj€_6Æ àt¯ã(¢éÎ¹$Ö£±³ÖƒŸwéÃUåx*÷¥r¬•úX›_?‚íFF´ÉxSÁ/8<@w1‰ã†tõ6oO÷–Ž‹»\/!i՘¼5ÅppòÐ$
+}"ÐÍÉ.ãŠÇ6ÊПIâ[©ô!]œßmàE<n°Ñ¤oxÈh£`/Ƈ
+8Þ²1<Tô¶j…ÿ|ÇÃMµ×߃àá+ìeï‰|…j©rü‡Â º‚_°y®¾óa/I@h’Ö*v¦ìÚqÃ2HÂÁ°ÀÈU«¤®¦2¶,f䯋 WFé<(9‰`”ꦍD+ntS?Ú¨S?‚|-šÐø°+mAtw&`šl…¦ì57`Åðüt‘9ðÉ%¬\kºGŽê¦¹íû; ]h¶Š{ù,ƒMÍ)üü6ÜhÛø¤\e ÛÆLÓ  ÉN«Yj²ÓzøøŽÛ¼,¥U\fóm ·»‡à0
+04¯z#ê4—j÷±Â˙1Վ›]uó@_ŸZ¸“v†Û*ªcg©?”~q³¡y€Ӕ¦“ÜsšÆGžû,ȕg ùD΀Ajç!Í(ó§…n7VÛkƒÅv ¨¼hÕ¼
+¦øž‰·£«f±Î†òÓLÏ™Ð3]—P½ÅuŽ\%³@怹ãý§òUݖ‡|
+­ÀŠ›ú-~ÓA¿Í™@/²q7–Â=ï9*…JaôT
+£‡RÕÌæԄ1R)ŒJa W
+à<p{.€T
+÷Gžp×¾r8ºí¤¤Ò< àÓ%¯Åƒ;íÐ4^9 ·<jñ€ì¡n
+å{ƒö5~û+܆|†_ÂH}îVt¼Áx­Ø8Š——)qG«]3ð!ƒ
+·Øq?¬­!~Ã78qîy|_Ôª‹!Y†/šJ•´}|uyÏ gŒ2!sօeÁKZ¸[vØϼáF×á׿’½}F~ºÈ€Ù060á¨Þ«n¥–â5ÚO¹áfW= B‹ñÛ#silO6ÏÆz÷½òª2]~q0*N°¸ä«Vbë
+äçˍ’Ë_²Ü(\V]
+uÙöC)¥ÄŸî®kÁõÎXQõ._òÒêŒ<ä‰G0xIÂásÔx ÂqëKøöñÑ>é8öŠi¼ç{ä›%†ïÚ(1eÏ~Ð
+³ìäð7}ඍо‚ƒ›ÀåÔl€ðêÿ¸P²]—?Y2–û>_'Ë´'IÆ°ž=R‰—¡aW3+¥3`o”@0eÀ³jCOM Ä(Cà›¨†>gƒšCsõAP²Í1œº”b2X{îø¤X1-·%åm=žÕÁŠu ’Œ?_êMJ[ –úüëG–dŒÆvŠ¥/}!J$לÜ7È2)«¾‚$ãÏ'ÄL!4ޖ°ú—ÿ ƈ֌Ùó+ZÏXÈc¨œCÜ&1`IÂUˆ„íUN¸{ŽdòC}æJW˜^C­1ƒB-µX®m€×–X‚9‡'œÂW°Î~–æKÎþžÉ¿”:Õ×>Adíß
+u¢C-2®c˜ßzÉå2<ô5lŸ nÅí)K2þ|BŒ¢ > »tVJ§Â:«@t­°*4ôkÈ÷ü~¼GµagíϨâˆkîë*”ÀÓö!"Ñ
+@kY’hšDH;Ç`öÕqۀYá“ÕÐ}äÌW—¹ÀÝFT\v??\ˆäeªɝÒ$è<ôRvþÖɤ¹WŠ·oû¹Ø ö-× üY¨)?^–àÏð֗PQ’ñçg¢Cˆ“ØÔVgädâTb£]'›/¡RZ2š5 ¹(³Ž*Øì—
+ϒŒ?±\¤¬Ä•/q±Ûœ0öšàÄb\ð`Ž·Î°ŒÔ³$ãOtƒ7”Õ‡“ØÔO]ãÿV¨»¹í{Öêž"²þŸ
+CúíÀ©È—Ú/yýÕ>ã²gÆÕí'Î÷ª=¿ôªÃ5øLwÐÑ
+û‡ R…@"øØfPæ‹ç<ø.‰æíéÞÒr‹ºÆMˆdrT¶›÷{+NŠ!^h\aÍ«’ ˆŠUÛy…MAbÀ‡@ºrdÍø¢Mhׁ®©:§ŠÑȖjØï S…m7À3‡I¥qíàˀØr¥¤ñ®ÖcÏ]<‚‚ªüTXñÒW,€—+ à“bÅhØA•»fâÈxυŠ’Œ?œ–Bˆ»?´|Šüôíþ£,ûø±v ú£Î²'Ԗ®„Ž™A˜ZãÞâôlAYÆmg/qÔ4eÍøó qbˆ­®ê$ÌédIƟђ%–Œ`Û^-á0å§æüô(Á²ëå%T”dü亥Եã¦uö âdRG"Yvõíæ9J_23ú³Pð¾I척%äZÿ^¨ÓƒCI s¡¢$ãÏkBÚÊ"gfxêpÊÉd8¥ûŠn2ùõeIƟ>¶æ
+!º/ºn–³/× ?7#²ÚÞqó…øĤå> ¿ãÃË©n–¢¦šÜ˜E¢«\ÐfÐ<¬ÿÿ‹ÕAØû˜M?ÆZKE"rÞ§!YÀ³™X¹Írã$Æ7ä!á/-R¯ñX¹”
+#‘ÆÁ„—ædZ®M·‡<ٙK±kqîÁÀ}1!L@$¢,"ÝéLztä_Ž8XT(Ï·Y}à`&n‡ß Rãïqð-ž0»+³²—Ìîª!Ã#¿ÁtðKÝ[maªí@uH"*‚½»ÅWñ º¿ø3!h·Ð¿‡ºiñ+G&gö¾ K¡ÉËÚ8ÝÕ0YSC‘ª8†"}±7ÔfÒ{·¡Jí¬,4ž9“†/k¢Yþ|D/iøwÇ:Kf ³ËÂišPäU©ø*®®çßÙ¸”í¤±þ :©÷µQÐIÿeèÅ8¿Ôq³ôˆeã·ÃrT¥,v“Õ&»ŽG˜À J]X*xN’ó‰ö ߟ‰õݾÉC05ˆoͦyôI0—ÓҬ˘ë€\íÖEê»6\™$˜ÀËh˞ÊÑ]†©l.º«ØXj¥€Pk¯ÎÁ˜Û?l}Óæ›AY弜6”vÜ6)å9x¯±uƒ® :ø%ůŠ?P„H“º0^À¥>æ]Max Ñ:µ¿¦“ŠîŒë¼N/òÃs¹Ñµ2¤y«;„NÍþ¶´—Ü-L_ëö‡½–ïnöjî´>r%ãÃ{qLŒ¼°>ہ¦Œ¦ývØ0rÇl`äØ»1g…&'è‘óv¨Åô†ÀG`/ÈÕKåžh:_úòQSPWÔW¼çû{P§•¿¦·°Í˟ï"½˜å«´B5Rü0Û
+ÍbN˜¨›Ín¯>ÁÔ|ÎãEüO´deÌ«G®BÉ
+«™ŸñËa™±ÇŽ-‚‚]sL@œH±þ¢=÷4x¢Ô&;¬’YkêBa_<—íñL ø±!{ø‹÷âIEk$>VöÒVòKƒ¸”-Û!!”ÊC¦s—˨²_˜-¶ ÄgŒÉyŒ4ã HÀô;ñe³§s´»ªÁà™f–Ô›¨Ù…Õxv·e ˜>#3Q4çN¬ç
+³ÑÕYsó˜@ÈUpɑ#ÂêËïÚ"g&JVLY°œ÷|äڀ?ô{\ceòrš\t¼Œ¦*‰˜˜Ý
+ß|k€Ý/ܹ|€cEìð‡e¹>ÿV§4ÑWê£Ò»Ô´m¹[Q±õnEÉ­(Xñ r+*V<ƒ»%·¢`+lœZ¡¢¶¤R¯TR„:ŒŠV̝Z¡WëRüR+æy0×çßŠà”©sC+Ôÿ„Ü
+Y{dê®OæèÄá>¼ 4p~Í0C 70}ÞtÞꝿ¥óf:´è„ÌêùóÖW¦F¯¼ÿÓ}?™L€3„  %=Îê
+(¥²¯ŽâüK ²ˆÜùu u~wãÚ jÎÝ5˜>âŒC‹ykÀ¤=’Íò\Ÿ8œy;'ÀˆÇ”à=Á0ŒI×¹‡"é8…o0=²çÔˆþ¦¯Öù‰Ba•Ômÿz}|;.ôÎiþ†Î°"})ÔÄÂ3^ÊGò½Ð£iê“ &ðršæJ¯{4£+×xA‰-•_˜$ðSèÓs¸­Ý´cæLD 2øœõpp×Tø«7—k
+_ýjø©áºê&ðrÚFÚÕp÷O©¥h¸Ë%|LzÃM®xB"y‹ˆ±S™2‰'|tƒâ ¼wdbéï€ú:§ŸN¶Ãç^¶ƒ÷.åð
+°þÌ$jœ• f?õoéd Í \šóÌ2G®¥OØŒfÖØ Œº4˜ÀKr9Wª„ܯ´Æ‡Lͮ⋽a¯ÀnÕ§C9#ã ô€ ¼Äk|ÐdŸpø
+Ê<¬ì'ÏΫ߸-û(²°Zùf\`’ò‚‹”’}:éé`¾úü-]>Õ8Ì~ùýJO“ìѓ6¾øm]a/
+~ý“`rÒÆÇÏïx¸Ãx¸0¾yœã(h?-ª ¬ô )ÌÖë‹0ZGž…´ù*äzR®uä^’…Å{ñúÌé4¡AOñR½ˆ0YGx‚z/nÙ,G/îu°÷ÆÌ1%= `{ºR™Ïo+ÃÐjûþ :Ñ'N?%ñü?ÒWw(ôõ'z÷Eæ·GV~ÖôÈ*hٞ$Á^’ëñjþÖëR¨µÜ™/³EkÐnn#rø ›ÿ’riäXM ¸‚ÀŠ´@8¸Ö
+‹¨8bù(>4•5Ÿ]$¼€Ãê÷8à°úOôºÏ“è•WÌá:k
+Eï ÁËiMi;üuóÎyرf‚ „»ÁáºwBW/Ó¼A7-DnàH`Çâ‡Á~ÛÃ;Fì;<´ÿ÷G:ûJ?@g÷õÕéxYÞN£ŒVAð@­fÎu;„¡pÿX,U(dŸtU_z0%J„ pw’%Ã#9à ¾¤8Ÿš+ôá oU}u‹lU±—ñ<• 9”öô‘é˜êEöØm´·ìà-ùß¼—¨ÞK,1Ö°ŸõA¯•þx‚éâ»Ü?ñ{®3’¿\5Å.VÑϖeûÔÈߚAÑãþjåoé› [@§¡s»ÓxYZ§OQÊ
+ìSUø­™þYuðKŠïX¼´¶CÇq¸·%v*;ÍË)oÕr•t)n–!qËT›·º`Èí¦óe«Ý"÷Ÿé-§ŸP3Þ|ªŠ¼ÌJï„ ãùî†ëäkèguEF἞Ùi1$¼[põHJÉ"•ÛS¨ŒïlËÁ¯,£†¹ú¦æýe?8~´>‡¯ tä €6ò & ¹²øè(Dêh¡s~FL#¢OÌl®˜Lý4Á¤Ô‰ê¹
+Aï_¸Þ¿Bå\uñ*Õ;¤Ò·¸*ÍóÌÒ@Ç̼ĩhÐXˆsÀ¥Æ;ՓGüØô``…·ÅoXV"՟‹à㇡EpÊ |þÌHÉ3;¼Þò¼?ðyò—ô™p>o´¶¡
+üQÆ£OåãQ_9€Õò¦×›þx†?ҙ˝ϳÌë.KaæL·ày…óy7U+Œ2dÍÚÉ Du#î
+eŒ~º‚(4·LìíK_Q±"wŘ`òj‚S†å_zåÓàÈ ×C-,²#}†ZÍ鎗¿n¥‘Ÿål¶…c>£úãSÚG¢°!-x–æ<sFªçό´Tׁ~5(Öi›s¡è¤ Ü„”ªvã,Nmw¢­ŠAsð˪p°-’‰Õ夆mìõø±ÏΗÐ.9¶k.÷þ  èÒÔ0¹ìLɌà²#%p| Ö¥dÔõ=Ç¢K5 ¬Àòԇiìaë±çlÝÁ¯L ^°ÅEúÆ<§¾ÍÝ%°³àf>Æyìl“ÂÃQ@Êä‘s©˜}'7t?z0C(Δ¼<­ÑèÙÖ].{Šs-]xlLöÜ<ª‰‡h§ð‡ÅÞª[ƒ†\ñƒ?¹âë
+r)Wþf:¬ðôHñ¥/äI]›À®ÙÔ\ëÁ©á‰†ü4A©»^¥îhÆo‡ÚDˆ\Ï.W/î‘SÊíŽD>8jç8 úL@^g<<ŒvýÔéP^“Ôá ˆ.nóäúáOO„@fw'Á¤TæxÖ÷
+ò&0çX
+#Ë.²ü—€ÞŽ¡É{@^Å\˪ŠÀZ<"ë¹î…rï‡àå´¥´Èˆßз‚=çʑHÙ&Ð:j!úzÊ0±Âß&ΰ}J݅$@õåM’ѸŠe!0}
+„ ˆÖËiÅÛR1£2!ey0×ÂÒ¾Ò
+‹ª<QØãn¬8½£·˜6¼oQ±«ðŽòé¤ä¨þÈt‡2áæÉ9ÿÎMÀGªìg:©þ‰Î¤ËÂn«]º¨Òeybí&ג—t) ½K—s'éò°2}Afށ̍¿pA¤“R%À>q®n+Ó13½šÈ>b3 Õó]C‚ ˆü.\ß5¬{× ¢Ÿ¿¤v¢ Js¥wð·NŽŽÜË»0:t
+“çÅ:|zL@ØÎ$¯ÊÃMÓ׉2‘«™|0¨ó"˧QA÷€?HÉþ¥uø“«ªŒÃŸcuErH4ñäl<ˆ ©Gïà,€¾xö­:±x %¿9Z(b`}&ÖtåVpwm³ëj-b3%X»†­®Ñ¤Ð"wzÝØgmµí/ëg-€ê`V¯Ào…Ïþ,;ӕAx9m MŸ“3P»Íª‹zÜk(çú8Ԕ:]8g§FkF h[wgjƒÞOùi8Ò&ðÒ¡wšøc……ò yÎ|k՟Cë
+•¼!¸éšҟL˜Ibü`Ýh¤¤ž=Ąx*#îK$Áÿš4–è\+]è;7AÛK—@'”ñÄ0Å1Å *L§œ«Ž¿`¯f;cú#yµÁÏè=g€ ¼œfò*Q¬ˆê€Mw4¤u§oà£ø•‹‡ä‰ëjè
+ÍI8¹ã&i0J ~IŽƒÁæS0ZË7ôÈÔzP©5JåçAÇYÙ ŒÂ7 nї
+Zz½—´d-À¯iN\>€…(ܘëþ·"
+?n"¨˜´•TvŒ<0T -ÊßÃD”Öi¬T§aÕXY¦J09ݕlfÎ5ÖjR0h=Ñ°
+Q½_¹¶ ¼b|"W¿iv¬Ãª)yŠ„¿/DÓ¿V˜˔¬ù‡ô€ Ð,_PÌråb_h66ãÁ¾¬Lǜ‹—
+ià:ž˜S¸ŽgnžäcÄ0&d3siT2yølÛreFsµ÷óûG:Ýp<0§i…=~s¼HGC! ~íÑ K06Õ¥Hžt FÖõ=`4v<™YÒÕþãsžv¢ +¬iCvâÈÍF¦Èl ãd­ Åº
+¶Ÿ*i©Û’~;´MÄù¶¾)˜ëøË"¦ŸW)°Ý¤€»KZê’}®.Ùgd:t‰뒭š–‹Ý°ïÇG,,¦&˜€r¶Çç“jdƒ®•_xoWç½¼gÆfNwñOíõ‰¼ïöødk±]ü@“Ší¡-ƒí@s­^Ìo•f¼
+sAåVî…õüLÓO7õÂ.W/ðëïè…] v^`Ñ{÷Ñ üìÇ€L
+A4üŒÜðs7ü`ÃIñN3c®lÚ@Ýy²êì4_~g˜ÀËiÐtIÑ\ϝë“r=¨cÄåßé¼^û§ °Aɧ#€]ìŠ5Ù´—lF`ZZAëà#Wßû’$h"ƒô¯?ùH‚+#9í€PĚ>%i°%¡¡èÅЋH»„"Vì ¡è< ±"ŒÕ‡uø¢®§B°
+¾ç²\·çº}ÏZ6_ïÊÅUQLžÂO@Æz©šk‘56ö×ÑÆfüÃÁ/ŠØ‘–@ƒˆ\Ä‘®œŠõiXӞZq&´ð°)§Æ
+¨¦
+-Í« °r }@f^ÚÃN«Õuädl*¨ï^0ü¼› Ѭ…uõ-Ÿ‚”ÞRúüVV´­úҌL“ÚX¤„š²#FV¦ìˆþw† ¼Œ¦s‰<Kù?£â\bu× 1Ø
+ºƒ_Q¼Ÿ)0¬pÀ9»Jj‚ põ
+šòÍ'iSFqèÑËðœ9#®‚6›Ÿ=[åY£ß^ ¼…‰4~”o©ú]מëÚ±®=×µc]û]מëÚ±®ë:r]'Öub]×]ו뺰®+×ua]×]וë*ªá9†]¼0â«j ð5¥:³qÀ½FVà­ÜðZRy+££~¹`Ø\ ¥íà‹òÑ°0ìóòOtr˜`é•ÝÝÊ
+Â^N[J›Á É낁_ÿ$˜ÀKJl¹ÄËB…ŦòÃ\™TÝS>±ØH[h›‰ô™ •é@Aå<°82€AÖÛ2ԅ÷¿N/ζ&ð2š-÷²ñ]Q½X%& =țtg¤Ü-(qpDžÄQԋïKe(
+X™àÁ*þÊa<&ÒÆÀ\7æÚdé Ñ°ñz¹}I(,¼ñò™õ’­´Èõ=|ǁ¬=ՋzÑÈ+Va1üûÈՀZ‡ƒ…Æ-U5;)‹§,q
+¸U¡4¨Ü“*^ù¼Piü$¢Ì
+ô\%ÀO=†:³øqÂùåi•lޖèDäÓ¤xVù}Dœ)óÃ;7ÖÈAó†ÕØñûˆ @üXÂ7XUNê¡a«dzÀ¨ar+¯4¹¾o6”*ÎåƶÒZ¦cfnàM 1o®‚ªÁHõL~N0áQÜp_·*?`çÊã²w#g™ñ´ztEl|ãÖâoöÝúÂhΗ†´ê»t)בr•·)Áåí¿¸Fh‘Ë“ó u®ÂæòÀŠÖˆ3>n?Ž…mxZó`½†æôx>ó”™Þ5:·~üöL32Z"R3t)~,wÊ_Ó¹"2÷úP½hîɤ2zx§ n€4ªO>ÚՋÆg@˜ ¨e4Q©’ê…x—3Ä!©qù;Ã^N³‚FÜ|6~zzà½(P¿~–©^(˜ëøË"zÜÿ
+ó3šŒ{'µ`\Sa|ʕ•]ý-ˆ@=,f?·ÛöÒ<ŸbŸÍãn4Ö{ÕSe~ü0éNX øâƒXÙT}tÜh­üeǍÀǪӡ»’>”Ó¹—ôêîÀ .gä*gâ@ ԣՑéÔ&•`ØHÂÖwÔlaÃùû>Þ¾F°“Ž^LSÀÏô–é5
+c¿6ž\2R‹
+ælš¦€0WVú`µ7½‚ÍJàöj6ÁôÀýÿ9tÖ<¼9
+Zfl_zXªÇ£Úã£åa7Æî0}üý¸DŠ#Çy§Iãt|øŸ‚k¿þ9»\12¦É;Õ»_õÂ[gÃ5þ÷Gȍ_C¥-²!‡Ò™*Cü®ïrãÖ¤Û1r”ŠLÍiX³X&É1Ìy ‹¤ê_ü°ûÇm«®ÅØ£ 6¹'äõm;7ÆM·5"œòÂožn’¦¹±ð¸™ÊçùöœËj ÿBN9L B–¤úW¬s
+BÆ£_åö(·¥\©\³à‰ÑÆñÑw²ön›«cÖ /3ÙWŒm3ÞW·Üã!êÁ”kc£=;ðϱ<¬[¬i!҃&©M9<¬Î9äÆ<þ6Ý6L„€\r…ý1Öùˆ¥½–ñ c¬+Ɗ:Z½íÈ›Ä9eÙÚ¶wUc.}½¿Bn,ë°õ¹¯÷²âM†¯ÖËN-B
+™Þ37rËõïô‘èt«JDE¬…wepbþ;j^øùl|ð%gHÀt֐RÖ9Ãâw!¯ fHZs¦€93ÖÉÆÇ]"(c»é7XnڀÍOÑ(Õc©èòíœ\…}Val\ÝzŠuÉjtÛ>OS·í}r·íÝƚzš3ߑoÍt u] ¬VÇ¡TXäuM˺E`,=¦^gY@·H€/¥|…¿`)%˄H˜À˾`
+lÚŒ{0Fîl-5 e:æÜ¢T‚Õ
+¢îk’ÚÑÛJQKt'Cˆò¦w'C-BRm,bCÕ+ÎÆÁ¬©d'Å,#ýÊå+9²¶ÕZ@õu3`ºnr€ò ñÃe;äÍ%R]öá’è²e]ÀñR&ð2©„,—ç\”zÑËEol€Ýå%†V€—ÓLö8XýÇ×øù™&5&õZ,‘a…{Gà¹
+þ×ó€ÎNŽDã¢ç™Š0:Ne›÷N+úQ®ý*õ¹J½è­_ôVÿ@çҍ×>¬¦Æ2ÖÒy´f¬@cº¬vVi!G÷ø–öè¹ ¶ÅΣ:w¬ÿþK¬úKτÈЎƊ9‰Ôó3kœzŽsÑ‹ÁçŒk§\©œ™[ª·ÞzG}õÎeÎöÎ¥=)„ÛTÏë
+¹ñëŸS¯Ò‹—^^±{‚°ëT”Ì4zm"lÄÊe-“í!DÆÀj·Dtöú/³r‡Ü˜ÇÀúj™<îý¹BãÒû}ٝŒå½<•œ+ÛØ®áG-1ìEÒrãw«}¦i ›‰ŸÊ©åäùzJùÇX–×yrKík՞ÙA>t§ 0Þ-ì!̒+q+=Â^@˜¾é£§º²½ðð+q¢üfLہ^g=9çså|Ñç]òäÜã:,ú5E~ƒvµy®œ’{ëhd­‚
+‹pCZÑíb.€Ü·Í$P<ô 
+¹¶§h¹–ðÈ#gŠêd§°‹D÷¸“`r¸Í¾JÌÃPá‡
+崒™e“7Ăæ*,öˆ#ίE ¾ìK®Sn:»ž ósï€êÃÌô£®À6¨
+˜€–J~*[I^F`tø :ó}¤?tRí®áßp94ðÄ2ª¯ÛxE®Q*¦×ÕêCò;Ã^º&¿÷Àp¹TàFZÁ²yYÇâbõ\nðQ}غ:—3]º©ýZ\úX¤ô”³È?Ñ 3ˆp+ôà×f[—zÃ7lc7=fù;Á„²‡ÇÙ$8ã‘RÅ珟Ž1T¡«0õ†‹«7;,Ԁé×Od®Òཿ€0—¨!6qVÇ7-œËun6Ë_Óyá»±¼‰™ÏßÓËM2=`/ÝÜ:E-½=yj÷A“VÓ.zĹû;°O.í?á:¯ðë,›.
+TDç•ÈLf¾áDÚÄTˁT²ùýÏêvÞV·Ó"ûüþ6–†œøZèÄ@ÖÅÊ!7~EiÃóös€¥:çPŽí«4„kcg2Ç®™–êhYÈÚ^ölùÆ[¨¥zGõ˜öå:%…ÜøÝ&۟yŒ ۞îčØ:-•MåŒ\»³Sí÷SþõÏrc֙zêÕwôÈñî;zW›ûŽÞ¤¦¼{î»Ý?ûÎtá£ïL‡ÞBnLzíÏãÂý³ïö¸ûδì½vãê»ùÑwWȍ¹ïæÝwçùì»óÜ}wž\ºŸ‘ٖ¸Fêc¶¸î‹þë´0;ôàè‘ÒON#DKvªi÷Ä{Ïc//ÜJ„è)sÆ/ŒQ®ŒYç8ÊꖯÕf¬Üòù\ø£¯fû)Fî«y÷Uy>ûª<w_;[WM_µÄæºÃ¥ø6’nÓ5Ìô’¯¿0ƾb¬«œõC9û.'V™ó4 ³‘»BnüÂZ_ÕÞ¬jH/Ãñ¶Ä4׫Ý\¸®/l†°[ïXC¯ ßzÇjnóÁŸzÇÕ41\kZC\ç¸v}‘bm éÉõ±kè^Ÿ+UƯÐ÷ûŠ‘ò5þe:ÇÖ+¦e«½àú©Þ+ÇÞOiˆÏïÚ/lZr®'¾Ï•RŽ}Ýqkå)Maÿ›&_—ÏßVžTÿf콅Ãz@Í!»Ž}‹s[ïËsÎrQë ƒŽ½¦¹qÒ±o&úü±ÚØë#«íühϸÚ3®öŒÚÓ?ÚÓ¯öôöŒ«=ã‡öôöô«=íjOûhO½ÚS¯öÔÚS>ÚS®ö”öÔ«=õ‡ö”ö”«=Ï՞çnÏ:¹=ëäö˜T‡í1ù0Ú³v®ÿC´47~q¾w{LRõڬܞµ>Ú3¯öÌ«=ó‡öŒöŒ«=ã£=ójÏü¡=ã£=ãjO¿ÚÓ?ÚÓ®ö´«=í‡öԏöÔ«=õ£=íjOû¡=õ£=õjO¹ÚS>Úó\íy®ö<Ÿí™çnÏ<¹þ7~·ç¹Úó|¶gž»=óäö̝Û3÷ݞi«¬Å°—£Êñ×°O aÖ¾š@ØùˆurÞ¦u!ëŠ1.ì›ã9|mÓÕ|Ú÷ !åØqŽ“ð»æ“cD9W/ؽÿ´ïPkrã׿ԬåT¶T‘›§}?Š¹}f‘¡šl=kM!ÜÛ夞û!<;¦q`ëËZ~·é
+¹1·©ìrLj9}šl]å¸nÚRÃô49¢Ú‘Þp‰+ܱ—±"V¹ñëŸa/-ÆôÒKÆ1ƒ L÷ ®Ë!¬|ĺò6Ó"û=¯]‘ë*¯±ë«;äÆ/î—caþ
+¤ž±‹0îà» ‰‘ÓoÝÇ6ìQÄ0£¸wȍß_±Ï4á3Qx`(§Þ崞B¸Mm¦œþ:V/i8VÏ»¡ßð¥i -©·­‡Å4áî'.PL{žµ9c!2ZW*çþ%.M}•(voj!hÕ ÂÊKƝ.©a¶õØYb¸´Xϲ0õ¬g:t¹®°ßòüHX9î;«'»² Xº:ë~÷¾üú'Áô…ú¦ðB>
+ðÀùû‹€Ùž5¾94iÒ«µ¯Â¶‘(l5ê|?\Úá["(U®¦½TžjK»ðì¸eóÃ#¬—þðõ§åÌp†À† §Û@˜À‹hiœÑD0 Ô–r­¥ÔÊ9Û½$¹Ö3XØBòÔ,¬§L€ç[žÞ‹48¤ÔÊ¿®Ç2#ý0}gÂÕ[ð⇰Œg—ΪÚÁŠ ~\þâR¡Ü´ü¼=«Ò¨ý‚È%‘ŽØ¦IÃ%e÷†W¹‹†/¿'묧o=Ì:v:1;?#3ÞCÝñ·AÐÆãÒOä0š>lzÚiÃU”-Wèn6gí¹.6ü'Ÿï€
+ˆ×ÏpŠa‘’ouµ/§ųÿ[®q9ü[ ð fƒþ *´RáQÁ9S€¿±80çâ<•éÕ¡ô„F6`Ë+Â^kŒÌ.~„÷waýÉ–§¬l»ƜN¦ŸÈ¬›R¿Á©´FÀæ­îØK°£T†:X6ÈÀÔ0£^?æJUØÐpk¬«úʽÐî^h¹öB˽Ь ÍÖbº*øõO‚ 舒eæU*ßH+¤U¾¾ÖD'ί°²±VÁ€ö`‚ °BVKw_
+Ñ­!'XA¼SßU8ÞÝo°|(Ķ)Ýê‡éKêr ÁËii þG2Z9£ãóLë£~×䆟óAƒ†ŸÔðÑ®†–®ßÔ»
+Ó¿¶7xüKT£®Ç¿Õß&ðrZGZÃ\۝kO¹î0ˉCçüÁ3ÙC¢…«QüD/À µ?ԀýÓB£²n¼r~©y_°È°çXÓ¿üïOtV".0ñe¡©Kgå<tc+>’¬œ¤f[Ö¤TlëQ‚ׇ%XŸy¢–N( ÷‰Â” ‡‘Ùí(.ìß4¥ ˜ÀËišQe™Zæy[5ðëŸPϳ¬Ýi½¤*¤af½°hïÈþD'ÏOu€K_QÑs;¢œù¨¹nV*4wY¼‚yÞú3Mízó^ÎJ¬RÛз¿3´Èf3wt¨Ä`U8­Þ€ª‹éhÙlb•æRÙT{|‹x­#-È5ì½C®¼ƒÄRyù#ýϕsé)åá~ôâ<¼ß¶^\$\ªñ?zÌA@8ì¢by€ ðرŒÛM_µÒrVH¥¾¶'ø¡EÖÌÚ!Í5§Í¨^ `9·i"?Ø<í| ªˆýµÛñ·tQe@A/¬„‚ü; Â9Bg3CùΏý‡Èço°üú'Á^œ++híäÎÏ —Újäü;C‹¬™½!Dî½zìYÉue)×j·”+·µA©ÜÖæ¥òw&Kêl_P;ù³Urž¼ÜzÎg<©”ÓnÓLàe´iñ+¢Gí~ £4`.ïEyÙ±£TÙ§?M_n)_é|^ç­÷C;7ŒÈwräh¶Ýµ§ ‚ï|@vbŸÿ ¯[v2þôîV.”NzT¦
+Và崂4×곜»gÄÞ³–·Ç\eÀ†LÀʎ
+{nx¨9´¶>®dø®{‡œÑp2\ôØus‚ ¼œ¶‘¶0×uçº1×RcÁíäPÓM)½!Y^jÚÝì·iÎìº6ôÐÞË~Ë<D×È<SßlÁ¿(€ ¼Œ¶ЖM÷âàWäºæ
+·gŽÔß,¬:=`/­qпú4Ÿ®¤ô¥ít‡œ
+§Õó×t¾bý™™®Ãà¥4½\흼öc^;<Só& cʎÌ\Nzï´rÆ3=Ñi
+ŸBéaþ¦fû[:9v«¸‘ ÇkÑ'µ"=CýFM[¸5cÃ7+T{6ÂùÀÚËvg¾-zÚwD4ûÙ.¦ïV:btZù¨ 2I›;2it×L˜ÀK$Õ ‰‰S©^¡®%Òè\Þ8Ê•í¿‡iÏ@tr™\u¢UþÕ„€PÈzÐ'k§9oX¼— ú2pZót>rµ±©Ìš¶ŠÚlÑÁrð‹"V µÃÏfk\¥w±é§¶âô¨â­"­zºÎö
+k\ív1SéÓµÖ Uà¯Ê*WrÅË@ZGP!"Á‹{Q(â'`®@éäw®ŒE‰qâºTÌJ$å‰í͜Siьí/é켬ÈòÎôç€Ù·ëcmÒ÷«’Tcï7Õôõ†|Fßo‡í:  ­ÇZG&Qõ®@¾|uB¤À¶ëMÞÜîÛ£ÓM«9õPÙx»‰ßßp³w­ôÙ Ô9ìT…‰u®~/KªF¶E®¼4ÁIµRwg«ôÐCd ?ùÃi…]
+ihöŽ²1͘bLqz/œ
+NvÃÖ@‘‹¦ó‘‹&¯InV9–ê¢â,ñ­#¨‘÷|¬þ‘S•dDum˨b®~®ÛÉ;vʕ¡ž„l®«ŠÏdÊx¤=(µ±EJ†Z €—Ó
+Òbw¥9_a줊A÷¾˜4,ŽxöXÚ¤'LÇà‚tð8øeýn4Éu"ˆSRÒIEŒ¨¯L
+úZ§/ËtßVÜŽȬ½¯~‹†fÉ%h_ÄhÔf]§3ùæó:É¿¬=û20%èËÀ”Y·ý>Óm?OUèþxðÿ•JögâF¨«©w‰JΪÞ#Mp:읏í”á!¤¦7ŸyË¡‰Àç³ÀO-׫ˆxýT||X ‹Gçsr§S©väÐ)3Ÿø |Û 0—MÜîÆûŽ ÝI ƌî$¸ì ‰&Պ³ªÆZ¤ç,Št¸.}t
+ú{F¨âÌû£žª/Mü »æÎÐÇ]"JÜ+…ýþ¹1)q×cx¾¢ö­”­¬R~…½ËQ¥dk9×æ
+<}i‡°a¹hH ýM›±fÊÛ§„HË­v:½ˆ½*îQ›iaÊ>¼/ZÜA˜ÕÙzµ™2½•%GS>.ʹª¼ÍxŠ7Rˆ<“·:»Ó—‘Ǩ}ý¶ç¬¢Oür9[ŸvtØBí+S9ï%öÀSY½Ãæÿ%ÖЧHÂýþ<W¬®æ,Ä\¾±0.upøÆ!YØc"k;‰f¦­š>Æ{Çâ^lV–ž#nǬ‹Ý!7—‘¦½è!Ü\FØùˆÅé¬vMyÕ¿0¸
+a¾õ3'Ga覻Ë_ßhüe, ÀSÂåÛ±¬^¦öã®.Õ!SwwYÊñí1Ȁis¢ò£=ìWùí¿?Æjö4a´ÑW˞¬
+JYO&˜sÉ*ö$mê³30MIâþ¦)ëOyf¬wmU˜a<”J˜€”ÊƦL¼¦a%Á2;i-³°š/Õ[ñ’Bào¥y`W:é 2À=|€&#w„FÞ×=ý¿”ûuO¯õýº§ÿº§ÿº§¿c}ÝÓÿo±üžæëžþëžþëžþëžþëž^h_÷ôÒÃ_÷ô_÷ô_÷ôWŒ~•Û£Ü¯{ú¯{ú¯{z§ÝÓÝÓk£¿îéÿùº§‡ê}ÝÓÝÓÝÓÛ$üº§ÿº§ÿº§ÿº§ÿçëžþëž~ù|øº§ÿº§ÿº§Ï1¾îé¿îé¿îéÝÓK®_÷ô‚¿îé¿îé¿îé¿îé¿îé=³¯{ú¯{ú¯{ú¯{ú¯{ú¿¤ÝÓÝÓÝÓK¬¯{ú¯{ú¨Ý×=½õÝ×=½Ôðëžþëž^B¾îé1Æ×=ý×=ý×=ý×=ý×==Ôöëžþëž^W“¯{ú¯{zÆ_÷ôÿùº§W¼/ å|ÝÓ_cúuO¿¾îéã2áëžþ÷×=ý¾îé¿îé¿îé%3ˆüuOÿuOÿuO/´¯{zîá¯{zȯ{zXd¾îéÿùº§ÿº§ÿÏ×=ý×=ý×=ý×=ý×=ý×=ý×=ý×=ý×=ýÂ\םëÆ\¿îéµÔ¯{ú¯{ú¯{z›I_÷ôJg¨ßÈ×=½I£óëžþëžþëžÞ‚¯{z/õëžþëž~º/ƒ¯{ú¯{úŸé_÷ô_÷ô_÷ô՗¦¯{ú¯{ú¯{úc}ÝÓÝÓÏÿ|ÝÓûØ}ÝÓþº§·X_÷ôR£¯{úèýsO_6iùåeÙ# Ì/¾¥wW›ýr€.`#ëRnßÆè墻!2¡ƒ¥ÒŸL.º¿jú7=§_wz7P*ô°¨t[°”¦ŒÞ2½]ýãÖþ„ÞÆ*+ÿœžÓ÷;}ËýÛîþm5ÓëE¯¹ëÝ¿5O½Ç§äôåN_rÿ–»Ÿ<>Ï5>û¤þUˆôžé=÷O8\ú>¹÷n™ý;YÏg¥ñÙÁ·Œ^3½^ô™ÆgǓ^£çôóN?RÿîsŒãs½œš¾Ïóôô}¾é¤@`çüþÄ öÏJég¿¾orJéםž|Q=ñ …Üä> +¬tëß³ݔìßôæP´\érõqoAgw‡ªKú+¿³‡C¥Ÿw@ë‰ÞúÞŸ¡Ð™Ñ»H¥{ÿ:Fz¢ÿ>èf}®>ä‡÷™wz›?•¬ÛºkŠ’í=ƒHw]ërÝæ%c•Nº^4éúÔþ§ñ±ï¯>ävñï¯ò„°ï·’ÅBƒB§+öý³ê¹A¦w¾‚Šþá+8èQz°þU:ôo§ ïöŒŽãìñl$:ŒoaWp=§‡ùÃ.—]Aé0ʃwýJ‡ùYX#™téEd':|è•äô¨‹Oººæ´Ðáû|øêÚõµ•^ÞáżÐKX&¯ì1Û5Œo ØÛÎéñÍ/Wé1:|ŸtÌ^JЋC¥Ó„)1~^½~³:Dº×ozóþ¡{Âë§Ò½I1 Àú+ôîé‰?•~§ï>¾Ü\Xÿ…>||éj¨€ü ýcòÇ{:=õû¢
+å7¡{ÿê_”ÿ ¤Þ¿B‡þÕôÍé%˗B_;ѯýÈ·J¯Ýç§Ð¯ýÈ×J¿Ûïò£Ð¯ý|J¿Óû÷%tø¾”þdúsÑýûz»û¿žD¯wÿ֜¾ÞéKîßr÷oÉãSîñy¢¯ýì?a|Ïûg?¿ ³/ùüBó¯@OûKMïõç)ýÞïƒtÜßKz—ϝ_áùˆÐO¦Ÿ›>Z¢»}¾¾júrÑ}ýúž7ýÉô碻ü%ô5nzN¿îô.ÿ }ö»}'·ï£ÿjî¿{|jn_½ÛWsÿÔ»JN_îô%·¯Üí{rÿ<Wÿì“Ú·/þçGF¿¿ŸHß~âo±íÚ¿
+ö?/è1ÿzÍò¿æ?ևY;î/„Žß?Èðý‰Ò/þû¡_ß쏔~§ùÑãmÒK¦_ó#ä³ù\ò™Ò­g-Y>›,ߺ|6ë%Ÿqÿ‡ü-o¿ñþÞùco×þšû7äÿÞF–ÿ¹}±à÷:°h|þûVñ„ý‡Ò}}W
+¾ïÇ¡ÎÊøCq¨ù'ù’¿O”Mȶÿi¾/ÚßµÌ?ðzÙÿNðäôÀi¶•ó‡õoˆNõItØÿ VìŽõOè謭øc ß²üœù/(†³ƒÖbýç'°þ/âOÓå³É—Ž Ÿ-~¡ìüc²}3à«£A(awhkc±ý4ç³ÔôÛM;1= Œïénè\ðÇÅ· .ŸÍPéۍ{0½g[‹ÍNxÿ(½\t—fÙJÊ<ìÉÇù;7øûb÷WÛógL¾öHë7֏µÐ§Ù›>jz6ù‡Lßüßå¯9Ôïüs²FØ_,¶Nåós²a”ϸýÓûŸ¯á~h±—¦³ùá𵵏[úÂý×Ïùïd3]¸¿âK—o&Ÿ¯¡|s”˜Žòõ/ì/•Þ/ºóg¡ÃþRé-ÓÛE_9ýºÓCûfÞ?
+²õv·¯÷·r¾ëÃÞÍ¡æ?q·wÏû»ó¤ûO¦ÃþÄڇtƒBŸ÷¼ý×ößB?Ðÿ$_ÅþTè£ÝéKN_.ºóo¡#ÿú“éÏEþËô5nzN¿ =_(fzðg2l„ûsmðߝîGµÿb|Ø;=øg#…BØ+=äSC¡Þé œ¢Aùì°¡Æ'÷ȟìp öDzùå<i¬tèºðOЧC˜-Ñ{»éPþrˆô–éí¢ÇúÁô}ß;§ßwúµ}Ýü%Ö¡ßüeÎD,F/™^.úÈéǝ~<™þ\ôX?˜Ž÷{Òÿ¹á½!ߟ’Ò¸:O^ß÷µ¾Ÿ|?´O¾"WÀn¾„éÍ¡¦'7Á‰Þa}ž$ߒ׍$ßòý݈ïK̪@ÿ‰•Œ¨ßq¨t¶’±2=Ɵå+÷Õ$ÕwNozØ ù­Ý/5RH.ßòû‹òíÃ2œ?*ä/¸Ýú±Ò7Èo¤¿7œ?*ä?z1Ìë“ÒÃëS#Rmøø
+}[é¤Ò!=í‡ßŸ =îÏD¾ô¦F¿äƒ˜_çÖ_<4à1¿N½î]Çü!vˆóÇäÏ¿þ´?
+ýh~.ƒúÑg§ûËCò9Þ_–Ÿc|i9oûç¿ÔE€îëËi5ÿ÷·‡Œºàý­Ðcþ´|ÿ¨ùûúÀôrï?C¿ä´¬_né£þ#é—(Ýå¡÷}Ók¦ßû¿è_¦·uÓsúv§¯3ÑëÝÿµd:|_l ËæW{xüÒ̯F^)ÒüzËú0?ÚÓvšJ·ù¡tüþÙÀ_÷ü¯ûy¥Ÿ’è‰?4¸'»±éþÝèO¦?}åôëNoߧґ? ¼_7z¿èÆ”Žü,­½]ôžÓ÷{}÷ñá÷ý¹Öçè~Žƒý¯ôâô“ûWèÞ¿Bßã¦?™~­ÏÑ¿B_wzï_¡ÏsÓ{¦£ü„ú ïO³åþ-õd9Æþ-ãùµ•šõûdý_j¿ú¿ãûÑÆî0P¾Õô‘ÿÉó»´ò/o‡Pþåö‡üû†%É¿²¿ŠïÅÑví_àû.ýú¾…õguŽzçõcu¬ß™p¾òþP÷o¡ðCtVgIû»PbúJúC>Fþµ^ù‹ùÊôü~¢Éƒ“›XŸ¸ÿixþ¼èº ϟ7oè_,ÚîÌþ‘~ η-ø _²vOú%š>ÎGw>?7ºŸïñq>Ž?<HgúJç÷œÄùÿ~Z:ÿ·§î.>;ݐ¬ˆ÷›‹ƒù5Zº¿Øœìÿ¥ý±ÿfw†°ÿfýž¸áóC¼Ù­£þ
+ï_ÚaŸ;åItø¾;áó…î7´ü8ߣæÀýi;ì4æïyòýÎaý´8¿u.I/ÞWbVÒýK?{ñ}±{Sü¾FºßÙ|?ß7»Ãý]¾?jê|¯fz½Ûíëé~Y‘Ä÷Ç^!áûWñ}¬ÿ÷ÿ| .Z¯ó«¸ÿf7“pÿÝø|&ô;búõ‡ýí‚tЏ{§?¨_(Ã~jØë]èç1ôóÞ¢R¸Žôô8?I!;ô•†wÅsÛY)0~§^ÐJ¦—»bÿšß*Ý×v¸¹ÛÝ¿>?OÉú F÷ô5¿TúˆýéJúFýI@•¿êoœ–í?´'ëÒ¿ý7=鏰Ï&ÐÑùí›?­ßqÌޛàþø~áú#nEû¸Óûüa{7p¾vʃú“BÇþC@NOv:ê'*¾Ï²P¿QèÐ?§vԟT:ôÉ¡Ÿ©õËúíÑÿ´µÌý_Xe¡|›ú¿´0bòíÆö%ûoùmäñ¯{ƒ|BFê³|RI`òö7vâí'Sî!ÿêý%ÿì
+ýköŠ0ÿ’í…ºÐ]>:®B2ý¹èÏHt<zNÿ\éÿªy%¼_bºÍo¥ÃüVzËôvѳ½&œŸ£NŸ&â"ð·õo;•Âñ¡0>ì
+ÆGևvX…ã3Øó;ƒñþõ-ÛÝRº·Ÿ]ôAû~œ¾Rÿõ'­Ýøaÿ¯>qüؑŒÑù­Í–õŸÞôò[cýt´¼[éûrù­MqýË
+Ó~ó¦gýÊÆ
+Ñ~eôô0ÈätØÿNú¾üþÏè~¸_S:Ȭûo¥ÇøŠþ¦ïO…ûSöûg¥Ç÷¹øÁeÉéáû\|?äߧÒãûZé}ÒÁWÉSãÂÈèpdôžé ÿÔP¨t:ίdŸÉè0?ÙeÛJãüU<øVzúFþ.ôø>;¤þ¬tH¿P¿Ré`‡²°À>J¦ £ý¥ÇúÚË ƒA‡ï‡–Ӈ|ó¦‡B¥ÓC>b/ !_½=*òe­¸?0zú‚ý‹ÒHÏ^öžÜ¿°¿â~?û¦¯|?+Zç/²¿‡õa×P8dúJûë7ÿZ)ý¾ø{uŽõ‰÷+ÍÿëËÿ°¾½ç'ž_}õ•Žü›ù£¯,ÿ§õ¡'ù€Å½´þpzç?,ÿâù…ø÷ùÍn>“|āÏY~o"úü?㒟Øû§ïÄU(ìú“쿽‡#Ûwœþ}wºNJß7Ï?—O{q¿Ÿò'õMò§ÌO—;]¢|ÜYÿÂÏz)5?È÷ííÃôýãùN'û9iþ1Ý×W¡ãúÊ߇ŸŸ)¾oÖ?ñó“7}¥ó“Nï7c|;û=ž7ÿ
+ËöBþÊt?ß:œo)ÝMñ
+‘Ÿ?t¾ŽÀó¥{û¯÷‹JwŸPEÞΛîéù}á¾ÓÇ÷;Ÿtþctï?~óWè1?ˆÃùcOß1ÿD?ø˨Èßj2º×¯ö‘ùËJ‰?óù3òw:ðˆþW:®O ùÃ#çÏç¦÷LïÝ¿ÿçz?û¦7œ?Jù‘,ø«Tøë3bAømͅõááÍ×)Ö¡ûúÃË5®?ÏÀórí‘×Ï÷ŽÌá³}&ƒJ/ÿé՜CTr>ePèeP€§ŸÍ¡Òrá†ö
+ÜŠ¸ë°úÞÏ9”ýñ9ìØé•N ÜK=ùø1¨ûë͞áŒ~‡J§
+›ÿ)¶ÿdPèKü¿)ÜéTz%laÿi:údmn_¡T‡J§ ]Š|Jup7I¶ØášÑku¨tjùÊ}Ó·C¡“óu„IôÖ*ýa·lN?…Þ:»C3z(ôJ ̹Ae·$õþ­TàãöÆp(ô÷‚N›£¿§³A¥7
+›è'|L+½áû®Îϙо »û„ìŽíWÐúïûGþĞq;ØGìéý•âû½QŸô~¯²Þx¿7øýڗ¦ ï÷½ß÷{tVŠï÷„üiÐúï÷”ý;h}‰÷{lßÞïÑY)¾ß$.Àû½7½áû=¶Ÿï÷–úà ˜?bˆÄªö|Äò±XÃò*yň.óÄçBqĊug©?ύ!VXêéÍd2òR¯§!&C¬±,¯ý‘WŒ÷ªV?bù¨­¢žì\pŽX1ö«4 +±|×£þí\ˆŽX1Öcy͏¼b6LóèèuĊ5kžja÷hƒd=Íû  ×+äkòX-aím²É¶†}äkÙ\6Bõc„bE›ÓF»~Œv¬ksØ•
+¾ÿྠéÓ¥¦„}p_÷#Ö÷©˜?ÏõÁ}AöËüñž;/ØxOÌî û€ˆõÁ}a7±î‚=AÄúྰ3€Xy­òúྰKæËt~p_Ø+ ã…óƒûŽa˜ÇÕùÁ}aß0Ì÷q\íy,ð!î±>¸/ì! Ö=Ú°“ˆXÜöëc´ƒûönòÄÇ×gs‘Wù(±üPbðè“Br,çÑêïw#Ëê5ž’bù¶¢»ÇáàÑËòš9Db™cçÑs¦‰eù;¶µöó±0çÑîA9xô|Ükð¹cžîmz~仏Y܋ó¾cöÆ·!}}zhöÕÊ7#}—Âükµ{æX,˜9³™?bçäá‘:¤4ûjýø¸Û·'ÈkÛÌô¼ÎL!Ë|š[íÍs;žfûêîÖá£Ý@R0ÿÄÖÆa­†±K¾ùr.û/—`| 6v™ÉfŽ­Ãý@ÇÚ1màÛ±˜—åùŒekGÌËX;<–oÍæ3RÈKgŽÏKØ£E,[;¦­r°SƒX–WÍ!Ë8¹ñÕ÷øƒ¯F,ã« ¤ÚˆÕ?bõÏXÆW#Jµ«}Äú¡öå#¯òC^Æ1!VýŒe3bTë±lµŠX°WX™‹R¬•B²lR=¯ó!çLÿŒûN[M€û‚œc}ß³LsÕÞFÛW…ñƒÌT½Ä’b¹44ûJ!Wí­'úN!ËÖ¡yÇy"êÕ<ÖI!W½Ú ä/ß±ºìy—‹çG‰?ô„^"ì¤íKvYbE‰Æ\–‹X!ËQkØG^!Ëù¾Öe¹ˆ;ië{ß+ÌÑRHG[·=¬ÛëØÚa Ó$¸]¶fúfŽB®íë°=,ÈÛW[‘ïÁ­¬¯¢+b}î­¢D“'<ÈÛFÈ/‰§Ÿ)ÅnnÙE¬“B¤Ä,‰üβɶ™s"VK!R¢çï±>÷¢Ûæª_‘O—
+ùÕÿt 痧´X&uÂÛi«LŸ—fŽ¥ŒX3…H^Ö;Æ}—ϸà¾ûñ”«¤Ž¥9Ô'ìkG
+:há”;b­"ymKi%ê,Am]íÉÖ´¹û·½Uf
+ý“UK
+ь6œC­jçDeOë[ý—ÎÔuь"ŠÕ(¢lýœB£féä@¥ËÈ£|ž²íe52՝Õv
+ŒLüY¶œÃ¡ÞÞÖ#&J-Ÿ!JYFÅÎø"ÊÞ6Fv¹|NÄy¤fäQl{G–ûX˜H³|B„H£E«QDÙÇÆȤ‹å"¤ ËÈ¢Ø&dÏc52=®åbÞ52‰aÙÎÎÏc=b+àò + eäQì‰(§ØÙÑõò GךQD±ï6¢œb=bëûò ±îO$¢X"Ê©6F&N,Ÿ»^EûD"Ê©V#Sê[>!ö]#pÖ±6œÓ¬GLðZ>!Îý‰DûD"Êé6Fv˱}Bœû£(Ÿ!GÅÖЇÜ6!@%R2:Å֝ˆrô'/·Mн´Œ<Š
+uwOµ5e§†ê¿§ÚúRy¸yç4['@ޑ(&ɜf+@»s1ätËd‰b¢ÅƵAú(&4œa+ÈEç˙¶ä/d3m›ÈÈp•?ËrU¾±fµ-ÎgÙÀúÝ+TÈyy*å=- ”Bﱈ¾h¾M7~dkĄ÷{¥~D©W”ò‘K¹s)å#J¹¢¸"·G‰)9ô´O77±âæE9[þè¤äŽe²ç8w^#>ë¡»Ó¡ìkÇ͋ž•õájÞ+ÍhÖ>bÅ=›®W}ø“Ÿ8ÄúÈkþ×¸ÇFC®X÷ àê«ß#¤!W¬{¨G,h«}äÕ~È«}ŒP{>cՏю?b•*ç‡X£]úg¬ç#¯ç‡¼žz>G¨Ÿ{´ûùí~îҐkߣÝ÷çh÷ý‘×þ!¯uP_Ÿ#Ô×=Ú}}ŽvŸ÷iÈëí>?G»¼Æyõ{„zÿ¡ÞïÑîýs´{û¡öÿñueY« t+o}çEõþ_€ Ôé¿J.Z‰DdøÁ¡â¹]ËnSè‹~ô„n¥
+r·æÜ¢·æ
+Ò·¦ÜN¡¯û*Aú–9T‚ô-+r»é[fäP Ò·ŒÈí2B_ãG_Aú–Ò·é[~Hߤoù!}K¾å‡ô-5ôUô¤oAéË÷‚ô-(}'ß éËjV Ò·€ô}Vüï^è‹`Ý澂ô- };ß Ò·¨ôå=>+•Ûxu§ }!š÷~­Tڏ=é ÑГßó܆˜hÞ?CX´P©ôåí:G+•Ú]ŸuB¤…JA6F@ ´R©Ózs‚‚ô…ˆi6µ@Ðt¶wÕ侂ô…èi6$AµP©bÏv+£V*8á`é ñÔl•ƒj¥Ò!Öú)H_ˆ­f›#„W+•öÅû
+ú·y÷‚ôÅm8¯V)H_ØÌÛ»¤/Ø*¯V®TÚ¯V)H_°†T’3$Ïm0«T^­R¾`Ÿù¾w/H_0ôT^­4`\© 犜ÿAä8¯V)H_ŒçÕ*é‹Qä,R¾K.'ÀËõe"ʕ*ª©¼ô5ÑåBå¥/š8ªª©zè«ÿèËK_´Þ*•—¾h*
+ç_J5C_óG_^úâéžRy鋇‰@å9g—Jå¥/•Uè«ÿèËK_<*Ïm8wV*/}ñ˜[©¼ôÅSu 
+½*úÑW¾ã‡ôAúŽÒwé;~Hߤïø!}50Ÿ©À¨<‡úéۃôí?¤oÒ·ÿ¾=HßþCújؾRýè+HßþCúö }ûéۃôí?¤oÒ·ÿ¾Ô/TõG_AúöÒ·éÛHߤoÿ!}{¾ý‡ôՐ¡Ê?ú
+}̍R©ô­wۂôÛ*÷‚ôÙÊÞÕ-H_Œõ/âýú‚ˆò17Jqÿd#l •F§s4s Òs(•ç6fªú*?ú
+Òª{mÕ }¡öðbÉTƒô…
+>Ÿlq5]((ŸO¹$.Ԥω°f(@/§bµP™2§‚•?DýGn5Ð e¡>eÞùû´>%¨—ÉN«%*•d@/§¬a®P¨2ïD„Z¨H*ÔªTp²z$žP±ò‘ÔÐKõ½i
+u'I¥P:2ÛÒ°@ èªG*‰
+ä`‹ÄgÁÐ@¦
+åʕª…¾Ú¾‚ …ÒßJd-ø*Ï!(ó­TAâB±o 
+}•}¹ …¿*p›~p;H_(rTÛù·Sè+žR¾P–¨<·ÓŠÜNAú¦9”‚ôM3r;Ð×øÑW¾iD¥ }SÜNAú¦9”‚ôM-r;µÐWûÑW¾©þàP¾©Fn§ }SùÁ¡ }ýà6…¾èG_Aú¦üƒCAú¦üƒÛAú¦ôƒCAú¦¸½S![*¾ã¨r 
+Úi‘=U”¾;9r 
+Ú)’=U”¾;Qr úї—¾XŒJ©¼ôŒs@UUàÖžSª(}µPýèËK_,ET¨~pÛK_,KTÛQúj}:¥Ê?úòÒ Õ)•—¾XNJ¨¦—¾X´¨<·g”¾Z½N©æ¾¼ôÅ2vJå¥/»*Ï¡¥/Tª(}¡ö¬RýèËK_,rTžÛ¥o~÷¼ôłwœhjòf{çRw¯„¾´x ;$A}`¡éû"‹¡Ê²R)·‰ïyé‹åðØé
+*f+¤B¬ï^
+}iévƒêãJ¥z¡ºPÜ©  &;©A%t¥R5î+H_(ÉÉÎsP•]©´¯çˆµÝ…
+¤ï‹}…
+ñJ¥Ü~‚Pg^¨@úNî+H_(¸ÅŽ‹Z³ ¨´¯Å÷‚ô…âmLªõрJ]KŸ»‹V S*•¾ì詵º€J]K3sÈý`Ñ.v@Õº]@¥®¥Ä
+Ò
+x±c¬Öð*H[À}é żØaW띕öõÜ© ª:SAa8€„ÚÕÙÞ¹T“ïyA‘;Žq„:ÔÙÞ¹T‹ïyÁ±G:BMj¡RéËÁŽP™Z©´¯çbõ©…J¥/‡<B•m¥Rn?WI
+÷féۃô…Âe¤µë•JƒÙŸ[/T°g*("Ç¡ŠŽÍ°”G+j59¥RéË‹ZS¨´/–¾-H_(.Ça‹Z_¨”Û,}ñš[,}[¾Pnn±ômAú6•¾‹¥o Ò·©ô]‹û
+Ï8;fô]·Ë“¨dÍki®>®’ïI©Ue*“x6V¨$HS8cÏƪ¢ô‘ø@J¾ƒ$žU…èG²G7HЪ4Ÿâ¹á܋ðÜkýGAvV(‘¸#s©úÈI¾ƒ$*5I™j=>’À(÷xHJ–*n>ßKY¾— &‹ŠIZá¬_2TÂYÿ
+甜 ¸¢‡tu}•ûêœ!\ú*5öU8ًœ]Î×g×5ø ø 6ŽËiyi67ä¦j˟Ø
+UÅ:É6ïã¦*æÎí‹OlùC©À;‘È™ºR©Y’ýÎõL¨tÚq’%9SW*ðæg~ș:PÁ1?SW*È5Ìy(äL¨ ×°œ–‡¾ ú³Ì6õÉ!ª¦žÊ©­ÄK¤ð,/õ„aC;û¾£—Hã#@‰úk$zq£Z9+Œjãì Â!Žæ@5Ç۝ ¶n7ù$K5çú•iTŽí:gǁc»þ~=¥pÜ}qöÆlûçt‘&¥R±¥}5ùÇeîª"-ùéyŽfô,ÜRò vsç8ü/G1ၯ$üªA‘*ÓV^ÄV*°•~$ ¥J>´)±’ ô²«Ó‹‰TIÀàÔcû¨’¨Ž˜ó\`ÕNUi±Œ* øä]øYÌ¢@½ìåUl¢JªaÞå§Å
+$ªSì
+Uã0Á
+$à°ë܋TIr÷$ÀéûG)°TÃó¸bþ0ޗÛ'wYi1|* ¨†§µX=Ù¸Àä©$cº^†gØ;¿g)`ìT’ŽlL`éH†s?a@珤»^š°}˽„²ýø _G<›AǼ$¼dÎÖÚ<‰KY‡fÒGÂ:&'£Cé#a“óˆé
+½TߋiÁ‚$58H¤Êt±+HRIñãzcûàe+wK…ÇG¯#‘‘R¦{NŠ€ä]mÇ\z—“Å‘PvO,ÑdBÑdL’‰c“Ä‘)Ivl’ 2%ñ‰Y%‚ H<›–ïÂǘĿt÷Ém%pLI¦g6G‰Ÿál
+9q4s˜-_6kŸ°‡^ƒ›ñVg± ÂÀ­N°È1ɏEŽUDÎ؉{ÿK’5ïç{¯¼º'Ɂ$;’z™¾—™‰{\ñ&Uئ_ÀJø‘Ô@RI ½4ß ¯£@R +5JR§'¡@âÀ’À6½lN‹×(`²Ó.£JbäCQ ñë¨>îE…òR!R˜¾ÉRá9ø››UH~è2yW?oÿ%»H%Íÿ%§é+gsÞKƘ³öã)ÙÝ Ë$çÓ݅ZÆ.F-.˜œÄ]0/‰øÑ
+IÆo²dp­ï®
+-ñ +³/9JÏû,’"·ñ³x½©dGrüÒÒ cãû#}\þ#\ÙÏK‹¬âšàüÍÔ&A!!T!ÎõìHR÷ Ðqa’0.:„¤:^U”W•KRIq$#ô2|/¼ª ù—á¥üХꇮ„—.þ¥) ù¡£Ð ù^rxéì_:‡¡Ë~èRxéä_:…¡ۆ|ùÓ½zÈä<+ùèÄ ÂAD§¥ÑYvT5OÖñcÖÕ8!%ñºŠD›Âù-ˆHW!ñ
+ZË¡—ì{Q¹iÒîãîÂö¤3\ؔD+) êM©A¨à Ïpà¡$~†“~ùñã¾QÕ/߆Ⱥù é¼ÉܱTòåÒ0wŒ&'*á*dî*¶Š/Ô*Óܹ#½=ÄjÕèõHdz±åµãôº$<FlSíhS=$"©÷’:í#q~ZlSç§iª6˜Å6UcƒÙ$bž0O~¢‚ÿ”€ÿÔGÒÀyJ‡œ§dÇ%:Ö°¦$C%¦P¡š’zÿŽ¿ áH·K"ÒmòamËàµØ~ÛýNMÎÙÙÏsªü³ÛwÁ?ëõÂâäòlO„­:o}x5ž[ܾÞͱæ âU·®_Ƨ뵂ï¯O¿¾¾Ëf¼½¾™6`]|øÃ)™CŸáý‡¼ßÖ:ëðï'¹ã‘±92.Ï—ø|pœTïÜ@Çwã3Œo“ÿßêwõʗu?|‹nNc€àøfY©qÛóÇüáÕØ ¿öÄӛQ0>ÇN*BîºC„»ï/KçÃÑóéâÅâ~–m¿Œ½ýý?¯»·ù>+gº¤žt>ÀîÃÉøÐñÿ+ÞLXý×¾ƒƒÝ•Gà]÷ړüÿÇnpÿÚËûïC8ô»{ío6ŸF—Â+xÝóô_„ÿ{¸ÌväôŸåùG¶¡ü¹6pl¼Ó¡áYõí_æǨÖãïõ¯x·yòñÂ2ÿ†^¾þ+x ~ø²î‚·ÿ$ø$›D —NžGÏL‡a¤x³¾†¯yþ9l‚ƒK‚œÙôߞBÛsޙL\ûÁE¾]äÛ·£èù6tþâl‘~8˜£ßb7ËðŸŽxÃÃÚ½‹”ÿŸ6ºÿâ3|&‡fpàïÅÙÎòp0²<¼Z¼:œ§//¯¶}õíÙRÁ¸W©Š¼U«}ÜñUþnׯÜ*›~x3g¦¯‘™¬êÂýěiêȇ«‹œïOt‘‡ã÷_("Œ‡'Û>ùöòý<܏_×ç_N«ÝŠÐÐñ;GeË+£²>Ý¿C¯†½ ßŞs{yþ3è8Qñðç9|íeý98®?·ý̦ýtϯúK.Ëé/°`2nö°`*îÚýþNÿ£y<Y<9\¿¿ƒwÿ~Í<ßhËã¶}óíõû»ïïÖO3[ùxq•³Yù÷py¿Ù­|º¸ŽÏÁ‡o¯òéàþäÓÅQXF>Ëam…äÓtòéû/#ŸV±ò‰Î‚¨ü[îÏÇú òk-+¿ŽeN×_Úú}óvp•ÿ7òÿáYðeק‹ËúG¹ÙõïáҞôòâ'}O–ç£n2º|Ë_ƒÃ‰o8³;™8²‰âí]7Ó¬æý»Ó?žO=?m9ës_Ásÿv‡ûŸë{.ß/Íe=ÿ¯ûºÈZÍœÿ—„\¶k Æ<¼ ÞmÃų¶_6
+âá̟²1ââÂÿ‹ÿNw¡ª¿]œ|{áÿóՏËÙÿ|¼óGæGéÕΏu*ßO9ú)|?ëÜùTf¶úÿ×àÝî..ßÿ'š¬þ}qù>Ëêöû|¸<ÿZnþ\֏zøëǜõƒƒ£~0÷éúÿð
+ûp½ÄöCðaüß^{‘ÿ5/8vðÚe}߯˗Жç£bü÷¸ś‰:»ý7®ÃþáC.±y>pG„þåûû60&dqùÿí—Køy¿oÁ—Ð^¾Ï
+²8ÚwÒÇ]rÇ}7d7y¸×_õü¸6ëÿÆäk‘KX?U?lz ýëú|ìÛÉÏ/ÏK.±ÿ¸)o~p=?¿Ã±üüVùÞõú×ýώŸôöU8¿¯}ØóûÓ?éú0’\bÿpL*÷ú×ù³3͐›?_‡òü£É¥¶ï*_¶9¯'ÿü:ÿNF7ÿ*éú4“\bÿŠg“üíõ¯ówÇW’›¿_‡2g—Kè?#Žiá¸ŧIëðú×õqe¹Äþe|·ýÐÛ÷5-ć“‚û—ñ]C.¡ÕÏ?3¼½ö"ŸZ"¹ÄöSðb’Èqû$øKh/ßKš¹Nqµï¶m? ö]Éyqqrúõvr¼È%þÿSé½öUñ)—ø|2>YÍÕÐmˆûó#͈rqòú½ÚÇÛÎ=EÞ~* îå?éÿïø~
+ã{*t~жÏâüØu0?¾õÀΏ²Œ|&8N»x3òçėãü8 ·àýû²ï¿×|ÿÑìûïçÇ÷6¾—õ~ÿ’¬ÿîÃe~îütFÿ¸¸ü9ë;þ1ßo9çŸÝ÷/ïWªÓ_..ùQv|¢Ñ_n|Šè'~
+”OS^
+W\æçÊցqiO6>òáM÷§ÃøO0®û½|ú×@ÿUlþ‡’¬ÿǪÅø”SPXýGVµù'ÞüÓ÷ë¿Öo=?^]Ë)¾öןµûzm¾½ÌŸ>Íùò7?´ Ÿà8>§½œß\Ïo2ÖGd¾ÏmßTÿƋÃø,Âú…ŒÃølý@ý3ßóYÿvÿ½µ´ãŸ+Áøý֌.š0„õۉïgò|ú[³ü§9A?)tÖ7”O[a’÷/Ô«}šôŸízïôŸ}`!ãûá~|B'ú5úÕÁE?¿8®OO—úæGûÈÅmûäڋü½8ÊߋK}ö‹Ãü~x±xq¸ðïâÀ¿FùS®ºò-¡ÿm9õ‡‘?;`øsêc}Ö³>(NýaäOËX¿õÃ-®ü×ço¥˜ç¸¼ÿöÿ7õO¾füj2ë_i{9Çñµ#ÿZsõ]iLý­ôbýŸ>¼€þVŽ:Ö¦ý}‰þVŽÿ8êoÇaZÎo>ÜúW–ã-çWŒÀ5!“à°ÿíûû’ó?Æ¡ýV˜ä|íá ÿ{Ý?\ù{ý7ezq؟ŽÔpÿüpý>Ç ¸Ì¶=|ŸãœÉ÷ùpý¾†‰¯{8ԏK¤FŒcýñ‡W‹ƒþCêP)8Î/“Ÿ‰q˜Ÿ¥¡|½8Ìï½áùüp|¢|¿8äoß )@>?Úô¯|8äÏë3žÇü ‡üàyiÂÅáû9
+x<¸³Oœ„;Z?ýœ? |¡¡Ó7^œýálˆ´~ú9Ž@ûÃÃåý]üâÃ¥~hn®~úÃ¥ý‰/œ¾½~¿¾~úÃeüN| ÌߋëüØâë'Òi óïúgƒ|i„òj²òíâò|T›•/ J·|>ög”ïÛà¡ãÿp\ŸʇtíÏËãÕâÕáòý'?ûáçÏÃAÜ Sùzäkjº üåׅõ!M֟ûw°þ\\֟³\ãú“Úê>î5ëgÙ¤þÔÉτõ§öYԏúðiêGí³"¨ÿDßËÔÚgQP¿éäwÂúMû,
+ê/Ñ·Ÿ3õ—v,<ÔOúp½|8Ö?úVƒfêû†Ö7:ùŸ°¾Ñ±_hý¢“ÿ ëí\P_ˆvýu¬/´s @ý “ß ëƒˆÖ§¡]ëÓì\P†výs¬?³s!@}úô S_fŸµAýÚõDZ~Ì>«ƒú0tê‡C}˜Ëê¿Ð®ÿŒõ_ÎùªÖ¡
+å`.~
+Õ±Ò4ý}¨yïé ú¾Ré Z›…ïn«ômãÍ{-ÿÍT°‘èAúÂ>@©‚ô…ÝPyÁž@©‚ô…P…¾Æ¾‚ô…]B“ïynÃ^¡±,ìAúŽ¡­Ä÷<·aß°UÔ{¯†¾j‹TAú¨<·a'¡TAúÂ~¨·¡ªge}"|`›Ó¾røÇüãUF/sÇR‰Œ®ÍÜqTü\-™;†J¶µ5sÇQq_ÝÞ¹To$š–ÐîæÎ¥âþEFóZ{žøž–3&sçRqÿZԘ̝C•ùY{èKw=¿¯£ic2wÌ
+#ې:š¹cV+ٌTþ^`?2Fñ3‡©`æôR¸%Ï ÖV`ï2ø«ÕòÈüíyLž™Ò×êæÎ¥Z|ï=}cn€5[VwÙ°6ávM¡ò½÷ŽßvÆ¢uÈæK¤ì¿Dƒ‘-X›öÎՙxæðÚÑø}`/Öy Û1—9E*^;t^êÚ!T²5멙;ŽêÍ™—°GS*^;:¯r°S*î‹ìKŒœåê·rU©X®*hµJUUT,W•
+µZ¡*êÇÓçÐWþÑKL ¢HÅS©@«*^­”
+ÃJÑM5Ì«›ôµ‚žÓå[`éÛy5é z}µ:{z涬
+í‡ÎDòöŽ¡m¨×a瑨ÓܹT¼uOú„>Wªeî¸ç*Ž
+ô/Ù±Šî«}”Óìጄ|ò°“æ/Yt9 Òd© ºœR©.·øÝ }©.'ûZÑå”
+vÒ<ö²W識;–¼n ¬ÛcñÚÁ 58¼fʦ·iî¸䯃÷° LYuxE¹§²²Š¥Š{+ýGÖ'„
+Þá¥ZæÎýG«‰üUɺÉ䙳”ª˜;÷¥¡Š{ÑÉsUŽÈ»húŽ{»|[
+痴d*Ö:a‡?ÙZ n]æ備Ã-•ª›;·/–¾CfœJߙ¤¥PesçP=‰¬îüµ£Å6´œ–S©†¹sûšÜ’ÿñÍô֘Ä$^ӆö.ßö|:“º…°DCϐ¼=óÕ042›é”d¾TýOesçu4Á5ˆíDJ2; ¯þãÍôuy) ?‘’Ì÷9©GÍx“j¸#!‰V¶9ø‰Øug”iî@G¬þ ^ÎÁ¨7'«RC¦…ªRܑ°OIæd±=rȜP{äëHHx{&˹xDX¥2!T¥y) ?‘’ÌÅ<bíbȄPí‚;bÞ$‚Av%~"öã2!º"Öï,Àþ»¯€C&„®€Ü‘ð'¢$+3Øt=dB¨éúu¤$üÝ*ÉÊ<"¼¾™Ã"JÂO¤$‹˜G¬N ™“\GJŸˆ’,â'b§¾!bú'bg,þhUÁY…G„¯!bùODIøQ’U™G|Ê1eB,ÿÑ*I<YOmUÈÉ\"oGKIxÝQ’õÎpÔñrò„ßKîHHXQP’õŽŒÔÃsò„'Ï×ïMEŠÃ©R>ŽçâG:y6€+éëEIxå’O±oÕÉSV¹&)¼æI9NƬ”OžàûzQ~ )Ç™íɓœo¹!«ZwÏÂþ½Sf@õÏÂzÿä] X7r9nÕ¬Oa¾!a HJC_å)¼oîû\JÂÚF$áyÞùšûD¬i‚>Ê$<7Y5ò‘°Æ7Y㽐I¸Vä@Ý{$¬ŸM±0M?¥Xíšb^Z01«ú}ož˜á¥YáZ¬pZöõRÁÙ\–ð7Ï¥LðW_‰¿£nÿHu¶•X¨¥ìIøY2‹«Ô «O+s/¨aôÝ]ÄkêNÝñúZÑ®p­úÎ*¼N€¾sIX“Y…W€â{adUît”KªÅj,µAû¸$¬4¬Æ+èä͗Õy5l(_*è«ó:×Qá*¿÷«|9žÕ¼8¯Á €õ»þQÞÅËÍ¿|Óþ%ïâßøuìùÖ%ù¯â÷ r$9ô’}/9’ìHđ[HtJ¶g­]ÒÍ)•ž¼<ÉV›d{çP±îٖï«égݞĮÛ(먦ž¼<[Ymâæ-T*hZ‘{%Pé9Û[¯j“¡ÒO¨B_ýG_ÍóæÝqTžÉM¥ºRUÏ¡wÇQyV7]Дª„¾Ê¾JàPI‘Š·uÅWª8”תÀí\#U
+}¥}¥À¡9T—çv]‘Ûuy½;–jzn×¹]gèkþèkxÕ9T‡çv‘Ûµ{½;ŽÊs»öÈíÚB_íG_Õs¨ÖÈ¡Z=·kÜ®%p¨üàPñÜ®å·)ôE?ú
+B·Ò¹[ónÑ[óé[Ón§ÐWŠ}• }ˊ*Aú–¹]‚ô-3r¨é[Fäv¡¯ñ£¯ }Ëé[‚ô-?¤o Ò·ü¾%HßòCú–úª?ú
+Ò· ôå{Aú”¾“ïôe5«é[@ú>+þw/ôE°ns_Aú¾ïé[Túò Ÿ•Jm¼ºS¾Í{?‚V*í‹Çž‚ô…hèIïynCL4ïŸ!,Z¨Túòv‚£•Jí®Ï:!ÒB¥Š # PZ©Ôƒi½9AAúBÄ4›Z h:Û;‡jr_AúBô4’ €Z¨T±g»„Q+œp0‡‚ô…xj¶ÊAHµRé‰ký¤/ÄV³Í«•Jûâ}é qփ¿4
+ W*í‹W«¤/XC*É’ç6˜U*¯V)H_°Ï|ßÀ»¤/z*¯V0®TsEÎÿ‡ rœW«¤/Əój•‚ôÅ(r–)H_Œ%—àåú2åJ•UŠT^úšèr¡òÒMœ@UUT=ôÕôå¥/Zo•ÊK_4*ŠT^ú¢í¨B_õG_^ú¢M¨r úÁm/}ñ¬¨·é·sè+ÿèËK_<²ªÀí¹=½ôÅ) ò܆ó/¥š¡¯ù£//}ñtO©¼ôÅÃD ò‚³K¥òҏJ*ôÕôå¥/•ç6œ;+•—¾xÌ­T^úâ©:P…¾Ê¾¼ôEŸ 
+ܦÜöÒ="€*p;ÿàv
+}¥}yé‹&B5‚ô?¤ïÒwü¾#HßñCújø¼Rýè+HßñCúŽ }Çé;‚ô?¤ïÒwü¾\¯T?ú
+Òwü¾#HßñCúŽ }Çé;‚ô?¤¯†Þ ýè+HßñCúŽ }Çé;‚ô?¤ïÒwü¾˜ÏTà‹
+}AÄ?ù˜¥‚¸²6†J£Ó9š¹é‹9”Ês3U }•}é‹Y„*H_Ì-@>¶¨R¤
+jÒçDX3H —S1ÈZ¨L™SÁʟ@¢þ#·h²PŸ2ïü}ZŸHÔËd§ÀÕ•J2 —SÖ0W(T™w"B-T $HjU* 8Y=ÏF¨XùHjè¥ú^‚4…º“$ˆR(™miX ô Õ#•D…hÞ ìµ€$h/¯(d`„r°E â³`h SñY0(ë}PÄ'ah Üó}т¾Þ’JA|ҏÐ@
+â“04©‚ø$ER*Ï^°r~ÇúÒäîi(ˆO‚°rÊ¡ >IÅ'PyA¹M¥
+âŠvUè«þè+ˆO‚°r¡
+â“T|UàJP¥
+B” `\©B_ùG_A”RúÁ¡ M)·ß½j†E¤ÉA¦f•©J5C_óG_A²f•¬J„kVáªTA¾B!t ò܆råJÕB_íG_AÐBéo¥
+²
+|•ç”ùVª q¡Ø7P…¾Ê¾‚Ü…Âß@¸M?¸¤/9ªÀíüƒÛ)ô•b_)H_(KTžÛiEn§ }ӌJAú¦¹Fèküè+Hß4"‡R¾©Gn§ }SJAú¦¹Zè«ýè+HßTp(HßT#·S¾©üàP¾‰~p›B_ô£¯ }SþÁ¡ }SþÁí }SúÁ¡ }S
+ÜÞ©-ßqT9Pí´Èž*Jߝ9Píɞ*Jߝ(9PýèËK_,F¥T^úbÉ9 **pHkÏ)U”¾Z¨~ôå¥/–¢*
+T?¸í¥/–¥ªÀí(}µ>Rå}y鋅ê”ÊK_,'%TÓK_,ZTžÛ3J_­^§TóG_^úb;¥òÒ‹]•çЌÒªÆ
+U”¾P{V©~ôå¥/¹*Ïí‰Ò7¿{^úbÁ;N´5y³½s©Æ»WB_Z¼…’ >°Pô}‘ÅPeY©”ÛÄ÷¼ôÅrxìt³•
+R!Öw/…¾´t;ƒAõq¥R½P]¨aÎTP“Ô ºR)‡÷¤/”ädç9¨Ê®TÚ×săÚîBÒ÷žB…x¥Rn?A¨3/T }'÷¤/ÜbÇE­YTÚ×â{AúBñ6&Õúh@¥®¥ÏÝE«„)•J_vôÔZ]@¥®¥™9äƒ~°h; jÝ. R×Rbé ¼Ø1Vkx¤-ྂô…b^ì°«õ΀JûzîTPU© 0@Bíêlï\ªÉ÷<‡ ÈÇ8Bêlï\ªÅ÷<‡à،#¡&µP©ôå`G¨L­TÚ×s±ƒúÔB¥Ò—C¡Ê¶R)·Ÿ«$…c3,WÅQP1\©’R1‡‚ô…ÒY•¨Õ½”J¥/&j/ R#0Kßpl†Å¾8<êÙ+•†{³ôíAúBá2R„ÚõJ¥ÁìÏ­*Ø3‘ãPE
+ÇfXJŽ£µšœR©ôå€E­)TÚKߤ/—ã°E­/TÊm–¾áØ Í-–¾-H_(7·Xú¶ }›JßÅÒ·éÛTú®Å}éÛ*ZýwŽ zzwään+`.Þu7[º —]É»‰ÛÀÐ{Š· n[F«?íìõe×𠂶%°×ï2t-Hٖ —]‰®[UÄ洋½Ö _ë«[û†gœŠ3ú®ÛåIT²æµ‹4WWÉw€$ÈÔª2•I<«
+ÔG¤)ƒ1‰gcUQúH| %ßAπªBô#Ù£$hU šOñÜpîExîµÆþ£ ;+”Hܑ¹T}ä$ßA’À•š$ˆÌ
+µI`”{<$%Ë7‰ï¥,ßK“EÅ$­pÖ/*ᬅsJÎ\ÑCºº¾J}uÎ.}•û*œìEή çk‡³ë|„
+|
+þÀ—£˜ðÀW~ Õ H•i+/b+‹ØJ?’ †R%ڊ”XIzÙÕéÅDª$àp걋}TITGÌy.0Ž‰j§ª´XF•|ò.ü,fQ ^öò*6Q%Õ0ïòÓbÕ)vOµ†*‰ñ˜`
+ðØuîŪ$¹{’Ààôý£Øªáy\1
+ ˜?ïK‹íH€»¬´>•TÃSŠZ¬ž@‚l\`òT’1]/Ã3ìß³0v*IG6&°t $ù‰0 óGÒ]/MHØ>‡å^ÂÙ~|¯#žÍ c^^²Gg kmžÄ¥¬C3é#a““Ñ¡ô‘°ŽÉyDt…—š?_ŠÀ†ÊiæІšw±\5 ŽÉFÜìù͚(§†Cëé"~QVF9ïZO—XuY°O±,Ãþ={ë)glCë)ç)Ó˜9ôÅÙÀr5w,O5ÎȆ6V â¾¨š;–Š÷,Éܹ{nVUX1•„¥èŒ§}ñ;{çÚX¨òöίƫþk¼xÁ˜5›;÷ÅyQú²wl_¼²p&6´ýr.LUÚfKæŽë‹Ÿ«esçôÅ wEMä´¦¨&ÎaÌMÕÍ3WÅÚ̹ÛÐÚ,ó^¬Í³“¹ó¶ÛLͳs×`jž=ãÇ÷\vå,ñ-š¼qߢœJƒ5¿,¬oÖ4Qle<@±’0_RäIùL‘w‡åÔä\—àÄ49m¥¸M)ÈÄûD¬^Ì
+yN4ÀÄÎ$hbç^˜_ü×°=ã'.Ž„|FYÙVN. ÛÊGš®’€§è#ɁÄå |%ñYòÄHüЍð¸>cŸ¸áùŒ} $pmirzÁ3O/¸æï˜ òá1 §ÁWíõ¿ÓÅ]IkžÄ§˜•¨•éâX€¤†^ªïE„´‹`A’H$ReºØ$)¤øq ½€±}𲕻¥Âã£×‘ÈH)Ó='E@ò®¶c.½ËÉâH(»'–h2!h2&IÄ±IâȔ$;6I™’øĬA$žMË÷ácLâ_ºûä¶8¦$Ó3›£Æ€ÄÏp6(‰O,_@âòuKÐßäèô·†œ8
+š¹̖/›µOØC¯ÁÍx«³ØaàV§Xä˜äÇ"Ç*"gìĽÿ%ɚ÷ó½W^ݓä@’É ½LßËLÄ=®x“* lÓ/ `%üHj ©Ž¤…^šï…×Q )Ž„•%©Ó“P ñ `FI`›^6§ÅkH0Ùi—Q%1ò!ƒ¿(øuT÷‡¢By€?©€?)Lßd©ðüÍÍ*$?t™¼«‹·ÿ’] ¤’æÿ’Óô•³¹ï%cÌYûñ”ìne’óéîB-c£LNbŽ.˜—Düh…$ã7Y28È áÖwW…–ø…•Ù—¥ç}I‘ÛøY¼ÞT²#@9~éaIбñý‘>.ÿ®ìç¥EVqM p þfj“ ªçzv$©{è¸0I BR ¯*J‚«Ê%)¤8’z¾^U€„üKðҁ~èRõCWÂKÿÒ†ŽüÐQè…|/9¼tö/ÃÐe?t)¼tò/ÂЁmC¾üé^
+=drž‚|tâá ¢SŠÒè,;*Žš'ëø1ëjœ’x]E¢MáüD¤«x­åÐKö½¨Ü´i÷qwa{Ò. lJ ¢•”õ¦Ô T Hp†g8ðP?ÃI¿üxŽqߨê—oCdÝ|tÞdîX*ùri˜;F“•p2wÛÅj•iîܑޞâµjt„z$2½ØòÚqz]#¶©v´©‘ԍ{Iö‘€8?-¶©‚óӉ4UÌb›ª±Ál1O
+ƋÓmŸ|{ù~îǯëó/§ÕnEhèø£²å•QYŸîß¡WÃ^†ÎïbOˆ¹½<ÿtœ¨xøáÓ¾ö²þןÛ~fÓ~ºçWý%—åôX07ûNX0wí‡~§ÿÑ<ž,ž®ßßÁ»¿fžo´åqÛ¾ùöúýÝ÷wë'ÈǙ­|¼¸Ê¿Ù¬ü{¸¼ßìV>]\Ççà÷Wùtp
+ĵÜ$‚-¨ß0 FËĈ֋´?!¤ÎúpL*:1–õ⺾mù£¬‡ù¹åF±^<Áû÷!¬×ö}UŒ}ã£ã?Rƀы«||ãßÉâ.ÆPCE/¡]Ï÷ó»ÚöÕ·¯Éâú~Éèt‚~Aÿ kߖxÌkOð}ýúût›ßM¢üiۜüé-#Û1—û–:?Úpó£oùªó«û(̯~ì?2?Û$;?ûù d~·9ìüîÇ %ß_[Å}G ‰ühËÚ··.ˆò­'U§q~pDÞÚãçÏ¿rÔu˜ŒsäÓÕï÷áûxÔM ||8G‰®©±Ø€³|ùðùC¾È÷ó©çÕ|?Œ7Á—™çùQÏù̏šïü錟zõØ¿d~Ô{þ¥ó£^û<Ϗú¢ç!ܱbP~½ò_çG½öÃ"íü«Ç 'ó£Þ yõ4y~ÔóýÀü¨Û`ªó£žóœùΟÅxÓˋïý‡¬¿õž¯th¿Ïˆeý®'JÖïšž/|¸]ÿ?<ƒþPÓÐゃÓ>ðw‹zì„á·­ƒßG¥m¿§ºå³ºX}ø4þU•Î†5I{ªÆ>Qéîo“àËØ7ê®,®þ'7ÿu|Éaüp™_T­ý…ñ.¸µß<¼Hû–ý‡ñ!x7ö£‡³}ê2ö)Æeüû0ö¯û}-}þQM@àÃåûºxî—ñÝü‡P@î_Ûۘć'ߙLœàŧòŸ/A ãÂÿ¥1ƒ€Oi¿lx ãÌÿ’4Zp–Ÿ>L` ã<þeï!*ðá,¿ëvP@Æ¥=øp^ÿ?|šH?ƙeï_§_ÿU>–#®<ÿ$Ào×n5Ñ}Œ'Á‡ í{xi/¾=ë¿'?þ¬3îù—§Á³ÿ\,îù—l{Ÿ,Büwã/ûËŸ&Bö‡Œ»ñ—ýáÃg÷¸m?}ûaÆö‡Œ'‹;þÈþðáݍ¯ìޖÇm{¯ŸÈþûá^¾ÈþqDZ¯<¼øñ-dqϲíÉ·';¾^¾lù㿱o1îÇ7Yþxù%öÆ]{±ï\¼{ù%ö·ö÷}ëûU«ÿr{ÿcÎñòMõŸR­~üÚ«ü;þ!^þ©~TšÕŸ¹½âÕ؏¸½ü³úõ[¿ZÏw^ÿ*_›µ?½þuþµeõ¯×žï^þª~VÎþÄÏï®òyãÝËç®òùâž?*»šO÷ó§Øö^þv•¿ÝÚ·¯÷ó/›÷ï^þv•¿ÝÚ·žl{/»ÊßníÛoüUþvkÿ`<[ܯÓð§yù«úëÃ}ûaÆ·yù«úóÃýþ¦›ñm^þªþ~q/Uÿ¸m¯ç£»¾¼9}¸þÿÐKÄåÿÇ2ç³×÷?çÃîý5x¡îóŒ\¨ûÀ À÷=§ ç¨e5ˆdy¸×_Åéûá ?Ö®1Y_´…8Yœ_Vuqˆ©ªuh•âN?ÏÓ¶wóK£©On|-^<.¾èGô׿ògûOeÏ9߯åÄåL‡gåÿš&H뵗÷¯Éúpû*x1\uèhÈä‡7/ÉýwÁ»ñÿzýË÷Q÷þ1»ïCýËê>*>ӗ†‡}¸^bû!ø0þo¯½Èÿš— ;xí²¾ï×åKè?ËóQ1þ{Ü¿âÍDÝþ×aÿð!—Ø¿<¸#Bÿòý}²Æ¸üÿv‡Ë%ü¿¼ß·¿àKh/ßg…ð6ijÅýü‘ýõÅýþZµ÷ÿŸl{§i(ÒœÛ?jãN>JÒÃçôx±¸›_~ôðáÛ²¸›xôp§ßh4ãn|ÅÿõâàÿúÚ7åŸ^‚üÔï·üø~¿I£ã?åæϬˆ¿K|>åÏ2þ½Ï> ósÛÇVñã#úÕÆ1ЏקxÐ/›Î¿ƒ»ù§á†ïÿüû5ΗðþCÞ¯¹Äñ•ù±‡ü÷+þÓÿi~¾8†>\Ö§
+î÷OšÙ÷á¾ýþýYí;éã.¹ã¾²›<Üë¯z~\›õãòµÈ%¬Ÿª6½„þu}>öíäçÈç%—Øܔ7?¸žŸßáX~~«|ïz ýëþgÇOzû*œß×>ìùýéŸt}I.±ÿ8&•{ýëüٙfÈ͟¯CyþÑäRÛw•/ۜד~'£‹›•t}šI.±ųIþöú×ù»ã+ÉÍ߯C™¿³Ë%ôŸÇ´pÜ¿âÓ¤uxýëú¸²\bÿ2¾Û~èíûšâÃ‹É ÁýËø®!—пêçŽÞ^{‘O-‘\bû)x1Iä¸}|È%´—ï¿%Í\§¸ÚwÛ¶û®ä¼¸89ýz;¹^äÿŽ©ô^ûªø”K|>Ÿ¬æjè¿6Äýù‘fD¹8yý^íãmçž"o?•„@÷òŸôÿw|?…ÿ¯Éâ¾½ò‡ÈÊç‹Ëþáâ~ÿ û¿‡»ï_í+ó;ÛöÞ> ç O~þW}~½þÀøé%´×ùAK.±½Œï¶ßv¯_’è­è%´×ù»íw=Ì_ý¾j’KlßǔˆÜ^æOmr íµ
+=ú 2øéϧ¶ÂôÿÌ`ùßzgLì41„*#c3 U0±\ˆÑÈJPrQ­ÉrÜx’"endstream
+endobj
+6 0 obj
+78825
+endobj
+4 0 obj
+<</Type/Page/MediaBox [0 0 595.22 842]
+/Rotate 0/Parent 3 0 R
+/Resources<</ProcSet[/PDF]
+/ExtGState 8 0 R
+>>
+/Contents 5 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+4 0 R
+] /Count 1
+/Rotate 0>>
+endobj
+1 0 obj
+<</Type /Catalog /Pages 3 0 R
+>>
+endobj
+7 0 obj
+<</Type/ExtGState
+/OPM 1>>endobj
+8 0 obj
+<</R7
+7 0 R>>
+endobj
+2 0 obj
+<</Producer(GPL Ghostscript 8.15)
+/CreationDate(D:20070905000653)
+/ModDate(D:20070905000653)
+/Title(CAM output)
+/Creator(PScript5.dll Version 5.2)
+/Author(Jakub)>>endobj
+xref
+0 9
+0000000000 65535 f
+0000079142 00000 n
+0000079260 00000 n
+0000079074 00000 n
+0000078931 00000 n
+0000000015 00000 n
+0000078910 00000 n
+0000079190 00000 n
+0000079231 00000 n
+trailer
+<< /Size 9 /Root 1 0 R /Info 2 0 R
+/ID [(E?åncž"O­êð>ǚ:)(E?åncž"O­êð>ǚ:)]
+>>
+startxref
+79438
+%%EOF
/Modules/HBRIDGE/HB2FET02A/PCB/HB2FET02A_blz.pcb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Modules/HBRIDGE/HB2FET02A/PCB/HB2FET02A.pcb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Modules/HBRIDGE/HB2FET02A/SW/h-bridge.cpp
0,0 → 1,1339
// Features:
// - Complete PID loop
// - Optional proportional feed-forward for open-loop control and wind-up minimization
// - Wind-up limiting under overload conditions
// - Torque throttling under overload
// - TWI interface with PnP support
// - Parameter storage in EEPROM including TWI address
// - Acceleration, deceleration limits
// - Speed integration to estimate travelled distance
// - Add 'go to distance' mode with trapezoid speed-profiles - Needs testing
// - Added 32-bit and 16-bit atomic reads and writes. Note: 8-bit atomic writes are NOT supported
// - Added support for duty cycle throttling (basically torque-throttling)
// - Added current reading and max current detection
// - Added per cycle over-current detection and early-termination of cycle
// - Added servo-type operation with pot-based position feedback
 
// TODO:
// - Add current integration for power usage estimation
// - Add serial interface
// - Add servo-type (PWM) interface
// - Add optical encoder support
// - When sampling for fast-collapse high-side and during the on-state: we only need two states - the high-side should be on already
// - Switching between high- and low-collapse modes to equalize catch-diode load - make this user-selectable
// - Detect continous-current mode and do something about it!
 
// TODO TEST:
// - Servo mode in all four modes
// - Freewheeling and back-EMF in all four modes
// - Braking
 
// BUGS:
// - back-EMF measurment is different in fast-collapse and low-collapse modes. This make control leading to different speeds in the two modes.
 
#define BOARD_umHBridge
#define H_BRIDGE
 
#include <avr/pgmspace.h>
+#include <avr/sleep.h>
+
+#include "common.h"
+#include "opled.h"
+#include "usart.h"
+#include "twi_aap.h"
+#include "eeprom.h"
+
+void DebugStat();
+
+// This is an 8-bit PWM
+namespace PWM1 {
+ enum eClkSrc {
+ ClkNone = 0,
+ Clk = (1 << CS10),
+ ClkDiv1 = (1 << CS10),
+ ClkDiv8 = (1 << CS11),
+ ClkDiv64 = (1 << CS11) | (1 << CS10),
+ ClkDiv256 = (1 << CS12),
+ ClkDiv1024 = (1 << CS12) | (1 << CS10),
+ ClkExtFall = (1 << CS12) | (1 << CS11),
+ ClkExtRise = (1 << CS12) | (1 << CS11) | (1 << CS10)
+ };
+
+ void inline Init(eClkSrc aClkSrc) {
+ SETBIT(DDRB,0x02|0x04); // Preprare PortB to output to handle disables
+ CLRBIT(PORTB,0x02|0x04); // Set port bits to 0 so that disable will work correctly
+ CLRBIT(PRR,PRTIM0);
+ TCCR1A = (1 << WGM10);
+ TCCR1B = aClkSrc | (1 << WGM12);
+ OCR1A = 0x0000;
+ OCR1B = 0x0000;
+ ICR1 = 0x0000;
+ TCNT1 = 0x0000;
+ }
+ void inline DisableChA() { CLRBIT(TCCR1A,(1 << COM1A1)); }
+ void inline DisableChB() { CLRBIT(TCCR1A,(1 << COM1B1)); }
+ void inline DisableChAB() { CLRBIT(TCCR1A,(1 << COM1A1) | (1 << COM1B1)); }
+ void inline EnableChA() { SETBIT(TCCR1A,(1 << COM1A1)); }
+ void inline EnableChB() { SETBIT(TCCR1A,(1 << COM1B1)); }
+ void inline EnableChAB() { SETBIT(TCCR1A,(1 << COM1A1) | (1 << COM1B1)); }
+ bool inline IsChAEnabled() { return TESTBIT(TCCR1A,(1 << COM1A1)) != 0; }
+ bool inline IsChBEnabled() { return TESTBIT(TCCR1A,(1 << COM1B1)) != 0; }
+ bool inline IsChAOrBEnabled() { return TESTBIT(TCCR1A,(1 << COM1A1) | (1 << COM1B1)) != 0; }
+ // We never set the high bits to anything but 0, so the high-byte in the TEMP register doesn't need to be set.
+ void inline SetChannelA(uint8_t aValue) { OCR1AL = aValue; }
+ uint8_t inline GetChannelA() { return OCR1AL; }
+ void inline SetChannelB(uint8_t aValue) { OCR1BL = aValue; }
+ uint8_t inline GetChannelB() { return OCR1BL; }
+ void inline EnableIRQ_A() { SETBIT(TIMSK1,(1 << OCIE1A)); }
+ void inline EnableIRQ_B() { SETBIT(TIMSK1,(1 << OCIE1B)); }
+ void inline EnableIRQ_AB() { SETBIT(TIMSK1,(1 << OCIE1A) | (1 << OCIE1B)); }
+ void inline EnableIRQ_Overflow() { SETBIT(TIMSK1,(1 << TOIE1)); }
+ void inline EnableOnlyIRQ_A() { TIMSK1 = (1 << OCIE1A); }
+ void inline EnableOnlyIRQ_B() { TIMSK1 = (1 << OCIE1B); }
+ void inline EnableOnlyIRQ_Overflow() { TIMSK1 = (1 << TOIE1); }
+ void inline DisableIRQ_A() { CLRBIT(TIMSK1,(1 << OCIE1A)); }
+ void inline DisableIRQ_B() { CLRBIT(TIMSK1,(1 << OCIE1B)); }
+ void inline DisableIRQ_Overflow() { CLRBIT(TIMSK1,(1 << TOIE1)); }
+ void inline DisableIRQ_All() { TIMSK1 = 0; }
+ bool inline IsPendingIRQ_A() { return (TESTBIT(TIFR1,(1 << OCF1A)) != 0); }
+ bool inline IsPendingIRQ_B() { return (TESTBIT(TIFR1,(1 << OCF1B)) != 0); }
+ bool inline IsPendingIRQ_Overflow() { return (TESTBIT(TIFR1,(1 << TOV1)) != 0); }
+ void inline ClearPendingIRQ_A() { TIFR1 = (1 << OCF1A); }
+ void inline ClearPendingIRQ_B() { TIFR1 = (1 << OCF1B); }
+ void inline ClearPendingIRQ_Overflow() { TIFR1 = (1 << TOV1); }
+ void inline ClearPendingIRQ_All() { TIFR1 = (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1); }
+}
+
+namespace ADConv {
+ enum eRef {
+ RefInt = (1 << REFS0) | (1 << REFS1),
+ RefVcc = (1 << REFS0),
+ RefExt = 0
+ };
+ enum eAdjust {
+ LeftAdjust = ADLAR,
+ RightAdjust = 0
+ };
+#if defined MEGA_BRIDGE
+ const uint8_t Ch_MotorA = 7;
+ const uint8_t Ch_MotorB = 2;
+ const uint8_t Ch_MotorCurrent = 6;
+ const uint8_t Ch_ServoPot = 3;
+ const uint8_t Ch_Battery = 1;
+
+ const eRef Ref_MotorA = RefVcc;
+ const eRef Ref_MotorB = RefVcc;
+ const eRef Ref_MotorCurrent = RefInt;
+ const eRef Ref_ServoPot = RefVcc;
+ const eRef Ref_Battery = RefVcc;
+#elif defined H_BRIDGE
+ const uint8_t Ch_MotorA = 7;
+ const uint8_t Ch_MotorB = 2;
+ const uint8_t Ch_MotorCurrent = 6;
+ const uint8_t Ch_ServoPot = 3;
+
+ const eRef Ref_MotorA = RefInt;
+ const eRef Ref_MotorB = RefInt;
+ const eRef Ref_MotorCurrent = RefInt;
+ const eRef Ref_ServoPot = RefVcc;
+ const eRef Ref_Battery = RefVcc;
+#elif defined SERVO_BRAIN
+ const uint8_t Ch_MotorA = 0;
+ const uint8_t Ch_MotorB = 2;
+ const uint8_t Ch_MotorCurrent = 6;
+ const uint8_t Ch_ServoPot = 3;
+
+ const eRef Ref_MotorA = RefVcc;
+ const eRef Ref_MotorB = RefVcc;
+ const eRef Ref_MotorCurrent = RefVcc;
+ const eRef Ref_ServoPot = RefVcc;
+ const eRef Ref_Battery = RefVcc;
+#else
+ #error HW version is not specified
+#endif
+
+ const uint8_t ADCSRA_BaseValue = (1 << ADEN) | (1 << ADATE) | (1 << ADPS2) | (1 << ADPS1);
+ static inline void Init() {
+ ADMUX = (1<< REFS0) | 15; // AVCC is the default reference
+ ADCSRA = ADCSRA_BaseValue;
+ ADCSRB = 0; // Free-running mode
+ DIDR0 = (1 << Ch_MotorA) | (1 << Ch_MotorB) | (1 << Ch_MotorCurrent);
+ }
+ static inline void SetChannel(uint8_t aChannel) {
+ ADMUX = (ADMUX & 0xf0) | (aChannel & 0x0f);
+ }
+ static inline void SetChannel(uint8_t aChannel,eRef aRef) {
+ ADMUX = (ADMUX & 0x20) | (aChannel & 0x0f) | aRef;
+ }
+ static inline void SetChannel(uint8_t aChannel,eRef aRef,eAdjust aAdjust) {
+ ADMUX = (aChannel & 0x0f) | aRef | aAdjust;
+ }
+ static inline void StartConversion(uint8_t aChannel) {
+ SetChannel(aChannel);
+ ADCSRA = ADCSRA_BaseValue | (1 << ADSC) | (1 << ADIE);
+ }
+ static inline void StartConversion(uint8_t aChannel,eRef aRef) {
+ SetChannel(aChannel,aRef);
+ ADCSRA = ADCSRA_BaseValue | (1 << ADSC) | (1 << ADIE);
+ }
+ static inline void StartConversion(uint8_t aChannel,eRef aRef, eAdjust aAdjust) {
+ SetChannel(aChannel,aRef,aAdjust);
+ ADCSRA = ADCSRA_BaseValue | (1 << ADSC) | (1 << ADIE);
+ }
+ static inline void StopConversion() {
+ CLRBIT(ADCSRA,(1 << ADEN)); // This might delete the pending IRQ request, but we don't really care
+ }
+ static inline uint8_t GetChannel() {
+ return ADMUX & 0x0f;
+ }
+ static uint16_t GetSample() {
+ while((ADCSRA & (1 << ADIF)) == 0); // Wait until conversion finishes
+ uint16_t RetVal = ADC;
+ SETBIT(ADCSRA,ADIF); // Clear the pending interrupt request (though we're polling)
+ return RetVal;
+ }
+ static inline uint16_t FastGetSample() {
+ return ADC;
+ }
+}
+
+namespace EEPROM_layout {
+ const uint16_t DataRecord_Ofs = 0x00; // size is sizeof(HBridge::DataRecord)
+ const uint16_t DataValid_Ofs = 0xfe;
+}
+
+template<typename T> inline T min(T aA,T aB) { return (aA>aB)?aB:aA; }
+template<typename T> inline T max(T aA,T aB) { return (aA>aB)?aA:aB; }
+
+#define SHOOT_THROUGH_DELAY for(int i=0;i<10000;++i);
+
+namespace HBridge {
+ enum eSampleStates {
+ SampleState_PreFastCollapse = 0,
+ SampleState_FastCollapse,
+ SampleState_PostFastCollapse,
+
+ SampleState_PreSampleBase,
+ SampleState_PreSampleBase2,
+ SampleState_SampleBase,
+ SampleState_PreSearchMax,
+ SampleState_PreSamplePot,
+ SampleState_SamplePot,
+ SampleState_SearchMax,
+ SampleState_SearchMin,
+ SampleState_PreCurrentSample,
+ SampleState_CurrentSample1,
+ SampleState_CurrentSample2,
+ SampleState_CurrentSample3,
+ // off-band battery sampling for fast-high-side collapse mode
+ SampleState_PreSampleBat,
+ SampleState_SampleBat
+ };
+ enum eOperatingModes {
+ OperatingMode_Speed = 0,
+ OperatingMode_Servo = 1
+ };
+
+ const int16_t RequestFreewheel = 0x4000;
+ const int16_t RequestBrake = 0x4001;
+
+ const uint8_t EEPROMDataValid = 0x01;
+
+ const uint8_t GuardTime = 255 - 47; // Maximum allowed duty cycle
+ const uint8_t ControlTime = 255 - 10;
+#if defined MEGA_BRIDGE
+ const uint8_t LoBMask = (0x01 << 2);
+ const uint8_t LoAMask = (0x01 << 1);
+ const uint8_t HiBMask = (0x01 << 5);
+ const uint8_t HiAMask = (0x01 << 6);
+ const eOperatingModes DefaultOperatingMode = OperatingMode_Speed;
+
+ const int16_t Def_IFactor = 0;
+ const int16_t Def_PFactor = 0;
+ const int16_t Def_DFactor = 0;
+ const int16_t Def_PFFactor = 0x0100;
+#elif defined H_BRIDGE
+ const uint8_t LoBMask = (0x01 << 2);
+ const uint8_t LoAMask = (0x01 << 1);
+ const uint8_t HiBMask = (0x01 << 5);
+ const uint8_t HiAMask = (0x01 << 6);
+ const eOperatingModes DefaultOperatingMode = OperatingMode_Speed;
+
+ const int16_t Def_IFactor = 0;
+ const int16_t Def_PFactor = 0;
+ const int16_t Def_DFactor = 0;
+ const int16_t Def_PFFactor = 0x0100;
+#elif defined SERVO_BRAIN
+ const uint8_t LoBMask = (0x01 << 2);
+ const uint8_t LoAMask = (0x01 << 1);
+ const uint8_t HiBMask = (0x01 << 6);
+ const uint8_t HiAMask = (0x01 << 5);
+ const eOperatingModes DefaultOperatingMode = OperatingMode_Servo;
+
+ const int16_t Def_IFactor = 0;
+ const int16_t Def_PFactor = 0x0200;
+ const int16_t Def_DFactor = 0;
+ const int16_t Def_PFFactor = 0;
+#else
+#error No HW version is specified!
+#endif
+
+ enum CollapseStates {
+ FastCollapseHighSide = 0,
+ FastCollapseLowSide,
+ SlowCollapseHighSide,
+ SlowCollapseLowSide,
+ CollapseStateMask = 0x0f,
+ CollapseStateAutoCycle = 0x10
+ };
+
+ uint8_t ADSampleIdx;
+ struct PublicData {
+ // The layout of this record IS important.
+ // This is the public interface that is accessible through the TWI interface
+
+ // Speed control request signal R/W (Scaled between -0x3fff and 0x3fff
+ // 0x4000 is freewheeling and 0x4001 is braking
+ int16_t RequestValue;
+
+ // PID control loop parameters R/W
+ int16_t IFactor;
+ int16_t PFactor;
+ int16_t DFactor;
+ int16_t PFFactor;
+ int16_t SampleOffset;
+
+ // Request change limits (acceleration limits) R/W
+ int16_t MaxPositiveChange;
+ int16_t MaxNegativeChange;
+
+ // Travel (distance counter) R/W
+ int32_t Distance;
+
+ // Travel cutoff R/W
+ int32_t FwDistanceLimit;
+ int32_t BwDistanceLimit;
+
+ // Current estimated distance required to stop (R/O)
+ int32_t DistanceToStop;
+
+ // Modified request (R/O)
+ int16_t CurrentRequest;
+
+ // Command given to the H-bridge R/O
+ int16_t Command;
+
+ // PID loop working set R/O
+ int16_t IValue;
+ int16_t LastError;
+ int16_t Error;
+
+ // Last Back-EMF sample R/O
+ int16_t VoltageSample;
+
+ // Back-EMF sampling code working set R/O
+ int16_t BaseValue;
+
+ int16_t SampleCnt_Snapshot;
+ int16_t MinValue_Snapshot;
+
+ // Private members: not part of the communication interface, but added to this structure for potential debugging
+ int16_t MinValue;
+ int16_t MaxValue;
+ int16_t SampleCnt;
+
+ int16_t OriginalRequestValue;
+
+ uint8_t SampleState;
+ uint8_t DutyCycleThrottle;
+ uint8_t NewData;
+ uint8_t IsForward;
+
+ uint16_t CurrentMax;
+ uint16_t CurrentDelta;
+ uint16_t CurrentTemp;
+ uint16_t CurrentMaxSearch;
+
+ uint8_t ADBufferEnable;
+ uint8_t ADBufferEnableHost;
+
+ uint16_t CurrentLimit;
+
+ uint8_t OperatingMode;
+ uint8_t CollapseState;
+
+ uint16_t ADBuffer[80];
+ } DataRecord;
+
+ inline uint8_t* GetDataRecord8(uint8_t aOfs) { return ((uint8_t *)&DataRecord)+aOfs; }
+ inline uint16_t* GetDataRecord16(uint8_t aOfs) { return (uint16_t *)(((uint8_t *)&DataRecord)+aOfs); }
+ inline uint32_t* GetDataRecord32(uint8_t aOfs) { return (uint32_t *)(((uint8_t *)&DataRecord)+aOfs); }
+ const inline size_t GetDataRecordSize() { return sizeof(DataRecord); }
+ uint8_t GetDataElementSize(uint8_t aOfs) {
+ #define FIELD_OFFSET(aField) ((uint8_t)((size_t)&(HBridge::DataRecord.aField)-(size_t)&HBridge::DataRecord))
+ #define OFFSET_ENTRY(aField) if (aOfs >= FIELD_OFFSET(aField)) return sizeof(DataRecord.aField); else
+ #define OFFSET_ENTRY_2(aField,aSize) if (aOfs >= FIELD_OFFSET(aField)) return (aSize); else
+ OFFSET_ENTRY_2(ADBuffer,sizeof(DataRecord.ADBuffer[0]))
+ OFFSET_ENTRY(CollapseState)
+ OFFSET_ENTRY(OperatingMode)
+ OFFSET_ENTRY(CurrentLimit)
+ OFFSET_ENTRY(ADBufferEnableHost)
+ OFFSET_ENTRY(ADBufferEnable)
+ OFFSET_ENTRY(CurrentMaxSearch)
+ OFFSET_ENTRY(CurrentTemp)
+ OFFSET_ENTRY(CurrentDelta)
+ OFFSET_ENTRY(CurrentMax)
+ OFFSET_ENTRY(IsForward)
+ OFFSET_ENTRY(NewData)
+ OFFSET_ENTRY(DutyCycleThrottle)
+ OFFSET_ENTRY(SampleState)
+ OFFSET_ENTRY(OriginalRequestValue)
+ OFFSET_ENTRY(SampleCnt)
+ OFFSET_ENTRY(MaxValue)
+ OFFSET_ENTRY(MinValue)
+ OFFSET_ENTRY(MinValue_Snapshot)
+ OFFSET_ENTRY(SampleCnt_Snapshot)
+ OFFSET_ENTRY(BaseValue)
+ OFFSET_ENTRY(VoltageSample)
+ OFFSET_ENTRY(Error)
+ OFFSET_ENTRY(LastError)
+ OFFSET_ENTRY(IValue)
+ OFFSET_ENTRY(Command)
+ OFFSET_ENTRY(CurrentRequest)
+ OFFSET_ENTRY(DistanceToStop)
+ OFFSET_ENTRY(BwDistanceLimit)
+ OFFSET_ENTRY(FwDistanceLimit)
+ OFFSET_ENTRY(Distance)
+ OFFSET_ENTRY(MaxNegativeChange)
+ OFFSET_ENTRY(MaxPositiveChange)
+ OFFSET_ENTRY(SampleOffset)
+ OFFSET_ENTRY(PFFactor)
+ OFFSET_ENTRY(DFactor)
+ OFFSET_ENTRY(PFactor)
+ OFFSET_ENTRY(IFactor)
+ OFFSET_ENTRY(RequestValue)
+ return 1;
+ #undef FIELD_OFFSET
+ #undef OFFSET_ENTRY
+ #undef OFFSET_ENTRY2
+ }
+
+ void FreeWheel();
+
+ inline void SaveSettings() {
+ uint8_t *Data = (uint8_t *)&DataRecord;
+ for(uint8_t i=EEPROM_layout::DataRecord_Ofs;i<EEPROM_layout::DataRecord_Ofs+sizeof(DataRecord);++i,++Data) {
+ EEPROM::SetByte(i,*Data);
+ }
+ EEPROM::SetByte(EEPROM_layout::DataValid_Ofs,EEPROMDataValid);
+ EEPROM::Wait();
+ }
+
+ inline void Init() {
+ // Init to all channels off - this is the free-wheeling state
+ PWM1::Init(PWM1::ClkDiv256); // Set clock to clkI/O / 256 -> full cycle is around 120Hz with an 8MHz clock
+ //PWM1::Init(PWM1::ClkDiv64); // Set clock to clkI/O / 64 -> full cycle is around 500Hz with an 8MHz clock
+ CLRBIT(PORTD,HiAMask);
+ CLRBIT(PORTD,HiBMask);
+ CLRBIT(PORTB,LoBMask);
+ CLRBIT(PORTB,LoBMask);
+ SETBIT(DDRB,LoBMask);
+ SETBIT(DDRB,LoAMask);
+ SETBIT(DDRD,HiBMask);
+ SETBIT(DDRD,HiAMask);
+
+ // No control loop - this is the default.
+ DataRecord.IFactor = Def_IFactor;
+ DataRecord.PFactor = Def_PFactor;
+ DataRecord.DFactor = Def_DFactor;
+ DataRecord.PFFactor = Def_PFFactor;
+ DataRecord.SampleOffset = 0;
+ DataRecord.CollapseState = FastCollapseHighSide;
+ DataRecord.OperatingMode = DefaultOperatingMode;
+ // No acceleration control - this is the default.
+ DataRecord.MaxPositiveChange = 0x7fff;
+ DataRecord.MaxNegativeChange = 0x7fff;
+
+ if (EEPROM::GetByte(EEPROM_layout::DataValid_Ofs) == EEPROMDataValid) {
+ uint8_t *Data = (uint8_t *)&DataRecord;
+ for(uint8_t i=EEPROM_layout::DataRecord_Ofs;i<EEPROM_layout::DataRecord_Ofs+sizeof(DataRecord);++i,++Data) {
+ *Data = EEPROM::GetByte(i);
+ }
+ }
+
+ DataRecord.IValue = 0;
+ DataRecord.Error = 0;
+ DataRecord.LastError = 0;
+ DataRecord.RequestValue = RequestFreewheel;
+ DataRecord.OriginalRequestValue = RequestFreewheel;
+ DataRecord.IsForward = true;
+ DataRecord.NewData = false;
+ DataRecord.Distance = 0;
+ DataRecord.FwDistanceLimit = 0x7fffffff;
+ DataRecord.BwDistanceLimit = 0x80000000;
+ DataRecord.DutyCycleThrottle = GuardTime;
+ DataRecord.CurrentLimit = 0xffff; // Anything over 0x3ff is OFF
+ for(uint8_t i = 0;i<sizeof(DataRecord.ADBuffer)/sizeof(DataRecord.ADBuffer[0]);++i) {
+ DataRecord.ADBuffer[i] = 0;
+ }
+ ADSampleIdx = 0;
+ DataRecord.ADBufferEnable = 0;
+ DataRecord.ADBufferEnableHost = true;
+
+ FreeWheel();
+ PWM1::EnableIRQ_AB();
+
+ DataRecord.SampleState = SampleState_CurrentSample3;
+ ADConv::StartConversion(ADConv::Ch_MotorCurrent);
+ }
+ // If made inline GCC generates invalid code
+ void Forward(uint8_t aSpeed) {
+ if (aSpeed > DataRecord.DutyCycleThrottle) aSpeed = DataRecord.DutyCycleThrottle;
+ if (aSpeed > GuardTime) aSpeed = GuardTime;
+ // Allways clear first, than set
+ CLRBIT(PORTB,LoBMask);
+ CLRBIT(PORTB,LoAMask);
+ CLRBIT(PORTD,HiBMask);
+ SETBIT(PORTD,HiAMask);
+ PWM1::SetChannelB(aSpeed);
+ PWM1::SetChannelA(ControlTime);
+ PWM1::DisableChAB();
+ if (aSpeed > 0) PWM1::EnableChB();
+ DataRecord.IsForward = true;
+ }
+ void Backward(uint8_t aSpeed) {
+ if (aSpeed > DataRecord.DutyCycleThrottle) aSpeed = DataRecord.DutyCycleThrottle;
+ if (aSpeed > GuardTime) aSpeed = GuardTime;
+ // Allways clear first, than set
+ CLRBIT(PORTB,LoBMask);
+ CLRBIT(PORTB,LoAMask);
+ CLRBIT(PORTD,HiAMask);
+ SETBIT(PORTD,HiBMask);
+ PWM1::SetChannelA(aSpeed);
+ PWM1::SetChannelB(ControlTime);
+ PWM1::DisableChAB();
+ if (aSpeed > 0) PWM1::EnableChA();
+ DataRecord.IsForward = false;
+ }
+ inline void FastFieldCollapseHighSide() {
+ if (PWM1::IsChAEnabled()) {
+ CLRBIT(PORTD,HiBMask);
+ CLRBIT(PORTD,HiAMask);
+ SETBIT(PORTD,HiAMask);
+ } else if (PWM1::IsChBEnabled()) {
+ CLRBIT(PORTD,HiAMask);
+ CLRBIT(PORTD,HiBMask);
+ SETBIT(PORTD,HiBMask);
+ }
+ }
+ inline void FastFieldCollapseLowSide() {
+ if (PWM1::IsChAEnabled()) {
+ CLRBIT(PORTD,HiAMask);
+ CLRBIT(PORTD,HiBMask);
+ SHOOT_THROUGH_DELAY;
+ CLRBIT(PORTB,LoAMask);
+ PWM1::DisableChAB();
+ SETBIT(PORTB,LoBMask);
+ } else if (PWM1::IsChBEnabled()) {
+ CLRBIT(PORTD,HiAMask);
+ CLRBIT(PORTD,HiBMask);
+ SHOOT_THROUGH_DELAY;
+ CLRBIT(PORTB,LoBMask);
+ PWM1::DisableChAB();
+ SETBIT(PORTB,LoAMask);
+ }
+ }
+ inline void SlowFieldCollapseHighSide() {
+ }
+ inline void SlowFieldCollapseLowSide() {
+ if (PWM1::IsChAEnabled()) {
+ CLRBIT(PORTD,HiAMask);
+ CLRBIT(PORTD,HiBMask);
+ SHOOT_THROUGH_DELAY;
+ CLRBIT(PORTB,LoBMask);
+ PWM1::DisableChAB();
+ SETBIT(PORTB,LoAMask);
+ } else if (PWM1::IsChBEnabled()) {
+ CLRBIT(PORTD,HiAMask);
+ CLRBIT(PORTD,HiBMask);
+ SHOOT_THROUGH_DELAY;
+ CLRBIT(PORTB,LoAMask);
+ PWM1::DisableChAB();
+ SETBIT(PORTB,LoBMask);
+ }
+ }
+ inline void ResetAfterFastCollapse() {
+ if (TESTBIT(PORTD,HiAMask) != 0) {
+ CLRBIT(PORTD,HiAMask);
+ SETBIT(PORTD,HiBMask);
+ } else if (TESTBIT(PORTD,HiBMask) != 0) {
+ CLRBIT(PORTD,HiBMask);
+ SETBIT(PORTD,HiAMask);
+ } else if (TESTBIT(PORTB,LoAMask) != 0) {
+ CLRBIT(PORTB,LoAMask);
+ SETBIT(PORTB,LoBMask);
+ } else if (TESTBIT(PORTB,LoBMask) != 0) {
+ CLRBIT(PORTB,LoBMask);
+ SETBIT(PORTB,LoAMask);
+ }
+ }
+
+ void CollapseField() {
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseHighSide:
+ FastFieldCollapseHighSide();
+ break;
+ case FastCollapseLowSide:
+ FastFieldCollapseLowSide();
+ break;
+ default:
+ case SlowCollapseHighSide:
+ SlowFieldCollapseHighSide();
+ break;
+ case SlowCollapseLowSide:
+ SlowFieldCollapseLowSide();
+ break;
+ }
+ }
+
+ inline void SwitchCollapseType() {
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseHighSide:
+ if (TESTBIT(DataRecord.CollapseState,CollapseStateAutoCycle) != 0) {
+ DataRecord.CollapseState = CollapseStateAutoCycle | FastCollapseLowSide;
+ }
+ break;
+ case FastCollapseLowSide:
+ if (TESTBIT(DataRecord.CollapseState,CollapseStateAutoCycle) != 0) {
+ DataRecord.CollapseState = CollapseStateAutoCycle | FastCollapseHighSide;
+ }
+ break;
+ default:
+ case SlowCollapseHighSide:
+ if (TESTBIT(DataRecord.CollapseState,CollapseStateAutoCycle) != 0) {
+ DataRecord.CollapseState = CollapseStateAutoCycle | SlowCollapseLowSide;
+ } else {
+ DataRecord.CollapseState = SlowCollapseHighSide;
+ }
+ break;
+ case SlowCollapseLowSide:
+ if (TESTBIT(DataRecord.CollapseState,CollapseStateAutoCycle) != 0) {
+ DataRecord.CollapseState = CollapseStateAutoCycle | SlowCollapseHighSide;
+ }
+ break;
+ }
+ }
+ inline void ResetHighSide() {
+ if (TESTBIT(PORTD,HiBMask)) {
+ CLRBIT(PORTD,HiBMask);
+ SETBIT(PORTD,HiBMask);
+ }
+ if (TESTBIT(PORTD,HiAMask)) {
+ CLRBIT(PORTD,HiAMask);
+ SETBIT(PORTD,HiAMask);
+ }
+ }
+ void FreeWheel() {
+ // Disable everything
+ CLRBIT(PORTB,LoBMask);
+ CLRBIT(PORTB,LoAMask);
+ CLRBIT(PORTD,HiBMask);
+ CLRBIT(PORTD,HiAMask);
+ PWM1::DisableChAB();
+ // Set up interrupts to some reasonable values
+ if (!DataRecord.IsForward) {
+ PWM1::SetChannelA(0x10);
+ PWM1::SetChannelB(ControlTime);
+ } else {
+ PWM1::SetChannelB(0x10);
+ PWM1::SetChannelA(ControlTime);
+ }
+ }
+ void Brake() {
+ // Allways clear first, than set
+ CLRBIT(PORTB,LoBMask);
+ CLRBIT(PORTB,LoAMask);
+ PWM1::DisableChAB();
+ PWM1::SetChannelB(0x10); // Set it to some reasonable value
+ PWM1::SetChannelA(ControlTime);
+ DataRecord.IsForward = true;
+ SETBIT(PORTD,HiAMask);
+ SETBIT(PORTD,HiBMask);
+ }
+ void HandleOverload() {
+ // Turn off both low-side FETs - this will remove the load for the rest of the cycle
+ CLRBIT(PORTB,LoBMask);
+ CLRBIT(PORTB,LoAMask);
+ PWM1::DisableChAB();
+ }
+
+
+ int16_t ScaledMult(int16_t aA, int16_t aB) {
+ return (((int32_t)aA * (int32_t)aB) >> 8);
+ }
+
+ static inline void DoControl() {
+ // Control acceleration
+ // Note: DoControl will not be called if RequestValue is Freewheel or Braking
+ int16_t SpeedDiff = DataRecord.RequestValue - DataRecord.CurrentRequest;
+ if (SpeedDiff > DataRecord.MaxPositiveChange) {
+ DataRecord.CurrentRequest += DataRecord.MaxPositiveChange;
+ } else if (SpeedDiff < -DataRecord.MaxNegativeChange) {
+ DataRecord.CurrentRequest -= DataRecord.MaxNegativeChange;
+ } else {
+ DataRecord.CurrentRequest = DataRecord.RequestValue;
+ }
+
+ // Limit motion to travel cutoff values. Note that we update RequestValue and not CurrentRequest
+ // so stop will be smooth. Since we estimage the time required to stop this also implements
+ // the go-to-distance functionality.
+ int16_t Change = (DataRecord.OriginalRequestValue > 0)?DataRecord.MaxNegativeChange:-DataRecord.MaxPositiveChange;
+ DataRecord.DistanceToStop = ((int32_t)DataRecord.VoltageSample * (int32_t)DataRecord.VoltageSample / (int32_t)Change) << 3;
+ int32_t StopPosition = DataRecord.Distance + DataRecord.DistanceToStop;
+ if (DataRecord.OriginalRequestValue > 0) {
+ if (StopPosition > DataRecord.FwDistanceLimit) {
+ DataRecord.RequestValue = DataRecord.CurrentRequest - min(DataRecord.MaxNegativeChange,DataRecord.CurrentRequest);
+ }
+ } else {
+ if (StopPosition < DataRecord.BwDistanceLimit) {
+ DataRecord.RequestValue = DataRecord.CurrentRequest + min(DataRecord.MaxPositiveChange,-DataRecord.CurrentRequest);
+ }
+ }
+
+ // Control loop
+ int16_t ScaledRequest = DataRecord.CurrentRequest >> 4;
+ DataRecord.LastError = DataRecord.Error;
+ DataRecord.Error = DataRecord.VoltageSample - ScaledRequest;
+ int16_t DValue = DataRecord.Error - DataRecord.LastError;
+ DataRecord.Command = ScaledMult(ScaledRequest,DataRecord.PFFactor) + ScaledMult(DataRecord.IValue,DataRecord.IFactor) + ScaledMult(DataRecord.Error,DataRecord.PFactor) + ScaledMult(DValue,DataRecord.DFactor);
+ // Limit command to valid range and limit IValue growth as well
+ if (DataRecord.Command >= 0x100) {
+ DataRecord.Command = 0xffL;
+ // In an overflow case allow integrator value updates if it works against the overflow (sign bits are differenet)
+ if (((DataRecord.IValue ^ DataRecord.Error) & 0x8000) != 0) DataRecord.IValue += DataRecord.Error;
+ } else if (DataRecord.Command <= -0x100) {
+ DataRecord.Command = -0xffL;
+ // In an overflow case allow integrator value updates if it works against the overflow (sign bits are differenet)
+ if (((DataRecord.IValue ^ DataRecord.Error) & 0x8000) != 0) DataRecord.IValue += DataRecord.Error;
+ } else {
+ // Use saturated arithmetics to avoid roll-over in the accumulator
+ int32_t TempIValue = (int32_t)DataRecord.IValue + (int32_t)DataRecord.Error;
+ if (TempIValue > 0x7fff) {
+ DataRecord.IValue = 0x7fffL;
+ } else if (TempIValue < -0x7fffL) {
+ DataRecord.IValue = -0x7fff;
+ } else {
+ DataRecord.IValue = TempIValue;
+ }
+ }
+ if (DataRecord.Command > 0) Forward(DataRecord.Command); else Backward((-DataRecord.Command));
+
+ DataRecord.NewData = true;
+ }
+
+ uint8_t SampleStateCnt = 0;
+
+ inline bool BatSampleWhileOn() {
+ uint8_t OnTime = (DataRecord.IsForward)?PWM1::GetChannelB():PWM1::GetChannelA();
+ return (OnTime > 128);
+ }
+
+ // Samples the positive pole of the motor WRT back-EMF
+ void SetADChannelMotorPositive() {
+ if (DataRecord.IsForward) {
+ ADConv::SetChannel(ADConv::Ch_MotorA,ADConv::Ref_MotorA,ADConv::RightAdjust);
+ } else {
+ ADConv::SetChannel(ADConv::Ch_MotorB,ADConv::Ref_MotorB,ADConv::RightAdjust);
+ }
+ }
+
+ // Samples the negative pole of the motor WRT back-EMF
+ void SetADChannelMotorNegative() {
+ if (DataRecord.IsForward) {
+ ADConv::SetChannel(ADConv::Ch_MotorB,ADConv::Ref_MotorB,ADConv::RightAdjust);
+ } else {
+ ADConv::SetChannel(ADConv::Ch_MotorA,ADConv::Ref_MotorA,ADConv::RightAdjust);
+ }
+ }
+
+ static void StartOffPhase(bool aWasChAOrBEnabled) {
+ // Start new measurements
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseLowSide:
+ SetADChannelMotorNegative();
+ if (aWasChAOrBEnabled) {
+ DataRecord.SampleState = SampleState_PreFastCollapse;
+ } else {
+ DataRecord.SampleState = SampleState_PostFastCollapse;
+ }
+ break;
+ case FastCollapseHighSide:
+ SetADChannelMotorPositive();
+ if (aWasChAOrBEnabled) {
+ DataRecord.SampleState = SampleState_PreFastCollapse;
+ } else {
+ DataRecord.SampleState = SampleState_PostFastCollapse;
+ }
+ break;
+ case SlowCollapseLowSide:
+ SetADChannelMotorNegative();
+ DataRecord.SampleState = SampleState_PreSampleBase;
+ break;
+ case SlowCollapseHighSide:
+ SetADChannelMotorPositive();
+ DataRecord.SampleState = SampleState_PreSampleBase;
+ break;
+ }
+ }
+
+ static inline void StartOnPhase() {
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseLowSide:
+ ADConv::SetChannel(ADConv::Ch_MotorCurrent,ADConv::Ref_MotorCurrent,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreCurrentSample;
+ break;
+ case FastCollapseHighSide:
+ if (BatSampleWhileOn()) {
+ SetADChannelMotorPositive();
+ DataRecord.SampleState = SampleState_PreSampleBat;
+ SampleStateCnt = 0;
+ } else {
+ ADConv::SetChannel(ADConv::Ch_MotorCurrent,ADConv::Ref_MotorCurrent,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreCurrentSample;
+ }
+ break;
+ case SlowCollapseLowSide:
+ ADConv::SetChannel(ADConv::Ch_MotorCurrent,ADConv::Ref_MotorCurrent,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreCurrentSample;
+ break;
+ case SlowCollapseHighSide:
+ ADConv::SetChannel(ADConv::Ch_MotorCurrent,ADConv::Ref_MotorCurrent,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreCurrentSample;
+ break;
+ }
+ bool InvertSample = !DataRecord.IsForward;
+ switch (DataRecord.OperatingMode) {
+ default:
+ case OperatingMode_Speed: {
+ int16_t LocalBaseValue = DataRecord.BaseValue;
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseHighSide:
+ case SlowCollapseHighSide:
+ break;
+ case FastCollapseLowSide:
+ case SlowCollapseLowSide:
+ InvertSample = !InvertSample;
+ LocalBaseValue = 0; // These are ground-based measurements...
+ break;
+ }
+ if (!InvertSample) {
+ DataRecord.VoltageSample = LocalBaseValue - DataRecord.MinValue;
+ } else {
+ DataRecord.VoltageSample = DataRecord.MinValue - LocalBaseValue;
+ }
+ }
+ break;
+ case OperatingMode_Servo:
+ DataRecord.VoltageSample = DataRecord.MaxValue;
+ break;
+ }
+
+ DataRecord.VoltageSample -= DataRecord.SampleOffset;
+ DataRecord.SampleCnt_Snapshot = DataRecord.SampleCnt;
+ DataRecord.MinValue_Snapshot = DataRecord.MinValue;
+ }
+
+ uint8_t BlinkCnt;
+ const uint8_t BlinkInterval = 50;
+
+ void HandleIRQ(bool IsIRQA) {
+ if (DataRecord.IsForward == IsIRQA) {
+ // Almost at the end: grab back-EMF data from sampling,
+ // do the control, and start sampling for current
+ StartOnPhase();
+
+ switch (DataRecord.RequestValue) {
+ case RequestFreewheel:
+ FreeWheel();
+ DataRecord.CurrentRequest = 0;
+ break;
+ case RequestBrake:
+ Brake();
+ DataRecord.CurrentRequest = 0;
+ break;
+ default:
+ // Update the travalled distance:
+ DataRecord.Distance += DataRecord.VoltageSample;
+ DoControl();
+ break;
+ }
+ SwitchCollapseType();
+ // Toggle user LED
+ ++BlinkCnt;
+ if (BlinkCnt > BlinkInterval) {
+ BlinkCnt = 0;
+ OpLed::Toggle();
+ }
+ } else {
+ // At the end of the on-part: reverse voltage across motor to fast-discharge it.
+ bool WasChAOrBEnabled = PWM1::IsChAOrBEnabled();
+ CollapseField();
+
+ ADSampleIdx = 0;
+
+ if (DataRecord.ADBufferEnable == 0) {
+ DataRecord.ADBufferEnable = 1;
+ }
+ if (DataRecord.ADBufferEnableHost) {
+ DataRecord.ADBufferEnableHost = false;
+ DataRecord.ADBufferEnable = 0;
+ }
+
+ // Start sampling for voltages and back-EMF
+ StartOffPhase(WasChAOrBEnabled);
+ ResetHighSide();
+ }
+ }
+
+ uint8_t CurrentSampleCnt;
+ const uint8_t CollapseSearchBlank = 1;
+ const uint16_t CollapseSearchLowLimit = 0x30;
+ const uint16_t CollapseSearchHighLimit = 0x90;
+
+ void Sample() {
+ int16_t CurData = ADConv::FastGetSample();
+
+ // Save off samples in the ADBuffer for host-side 'scope' display.
+ if (DataRecord.ADBufferEnable == 0) {
+ if (ADSampleIdx < sizeof(DataRecord.ADBuffer)/sizeof(DataRecord.ADBuffer[0])) {
+ int16_t ADSampleData = (int16_t)ADConv::GetChannel() << 10;
+ ADSampleData |= CurData;
+ DataRecord.ADBuffer[ADSampleIdx] = ADSampleData;
+ ++ADSampleIdx;
+ if (ADSampleIdx < sizeof(DataRecord.ADBuffer)/sizeof(DataRecord.ADBuffer[0])) {
+ DataRecord.ADBuffer[ADSampleIdx] = 0;
+ }
+ TOGGLEBIT(PORTD,0x10);
+ }
+ }
+
+ // State-machine for data-sampling.
+ switch (DataRecord.SampleState) {
+ case SampleState_PreFastCollapse:
+ DataRecord.SampleState = SampleState_FastCollapse;
+ // Update max current from the search field
+ DataRecord.CurrentMax = DataRecord.CurrentMaxSearch;
+ // TODO: If DataRecord.CurrentTemp isn't DataRecord.CurrentMaxSearch (more or less)
+ // than the over-current protection must have been activated.
+ SampleStateCnt = 0;
+ break;
+ case SampleState_FastCollapse:
+ // Wait in this state until turn-off transient is over
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseLowSide:
+ if (CurData < CollapseSearchLowLimit && SampleStateCnt > CollapseSearchBlank) {
+ ResetAfterFastCollapse();
+ DataRecord.SampleState = SampleState_PostFastCollapse;
+ } else if (CurData > CollapseSearchHighLimit) {
+ SampleStateCnt = CollapseSearchBlank;
+ }
+ ++SampleStateCnt;
+ break;
+ case FastCollapseHighSide:
+ if (CurData > CollapseSearchHighLimit && SampleStateCnt > CollapseSearchBlank) {
+ ResetAfterFastCollapse();
+ DataRecord.SampleState = SampleState_PostFastCollapse;
+ } else if (CurData < CollapseSearchLowLimit) {
+ SampleStateCnt = CollapseSearchBlank;
+ }
+ ++SampleStateCnt;
+ break;
+ }
+ break;
+ case SampleState_PostFastCollapse:
+ switch (DataRecord.OperatingMode) {
+ default:
+ case OperatingMode_Speed:
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseLowSide:
+ SetADChannelMotorPositive();
+ DataRecord.BaseValue = CurData;
+ DataRecord.SampleState = SampleState_PreSearchMax;
+ break;
+ case FastCollapseHighSide:
+ if (BatSampleWhileOn()) {
+ SetADChannelMotorNegative();
+ DataRecord.SampleState = SampleState_PreSearchMax;
+ } else {
+ SetADChannelMotorPositive();
+ DataRecord.SampleState = SampleState_PreSampleBat;
+ SampleStateCnt = 0;
+ }
+ break;
+ }
+ break;
+ case OperatingMode_Servo:
+ ADConv::SetChannel(ADConv::Ch_ServoPot,ADConv::Ref_ServoPot,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreSamplePot;
+ break;
+ }
+ break;
+ case SampleState_PreSampleBase:
+ // Throw away the data, but the next one is for real!
+ DataRecord.SampleState = SampleState_PreSampleBase2;
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case SlowCollapseLowSide:
+ SetADChannelMotorNegative();
+ break;
+ case SlowCollapseHighSide:
+ SetADChannelMotorPositive();
+ break;
+ }
+ // Update max current from the search field
+ DataRecord.CurrentMax = DataRecord.CurrentMaxSearch;
+ // TODO: If DataRecord.CurrentTemp isn't DataRecord.CurrentMaxSearch (more or less)
+ // than the over-current protection must have been activated.
+ SampleStateCnt = 0;
+ break;
+ case SampleState_PreSampleBase2:
+ // throw away this data, but the next one is for real!
+ DataRecord.SampleState = SampleState_SampleBase;
+ break;
+ case SampleState_SampleBase:
+ switch (DataRecord.OperatingMode) {
+ default:
+ case OperatingMode_Speed:
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case SlowCollapseLowSide:
+ SetADChannelMotorPositive();
+ DataRecord.BaseValue = CurData;
+ DataRecord.SampleState = SampleState_PreSearchMax;
+ break;
+ case SlowCollapseHighSide:
+ SetADChannelMotorNegative();
+ DataRecord.BaseValue = CurData;
+ DataRecord.SampleState = SampleState_PreSearchMax;
+ break;
+ }
+ break;
+ case OperatingMode_Servo:
+ ADConv::SetChannel(ADConv::Ch_ServoPot,ADConv::Ref_ServoPot,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreSamplePot;
+ break;
+ }
+ break;
+ case SampleState_PreSamplePot:
+ DataRecord.SampleState = SampleState_SamplePot;
+ break;
+ case SampleState_SamplePot:
+ DataRecord.MaxValue = CurData;
+ DataRecord.SampleCnt = 1;
+ break;
+ case SampleState_PreSearchMax:
+ DataRecord.SampleState = SampleState_SearchMax;
+ DataRecord.MaxValue = 0x0000;
+ DataRecord.SampleCnt = 0;
+ break;
+ case SampleState_SearchMax:
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseHighSide:
+ case SlowCollapseLowSide:
+ if (CurData <= DataRecord.MaxValue) {
+ DataRecord.MaxValue = CurData;
+ } else {
+ DataRecord.SampleState = SampleState_SearchMin;
+ DataRecord.MinValue = DataRecord.MaxValue;
+ }
+ break;
+ case FastCollapseLowSide:
+ case SlowCollapseHighSide:
+ if (CurData >= DataRecord.MaxValue) {
+ DataRecord.MaxValue = CurData;
+ } else {
+ DataRecord.SampleState = SampleState_SearchMin;
+ DataRecord.MinValue = DataRecord.MaxValue;
+ }
+ break;
+ }
+ break;
+ case SampleState_SearchMin:
+ switch (DataRecord.CollapseState & CollapseStateMask) {
+ case FastCollapseHighSide:
+ case SlowCollapseLowSide:
+ if (CurData > DataRecord.MinValue) {
+ DataRecord.MinValue = CurData;
+ }
+ DataRecord.SampleCnt++;
+ break;
+ case FastCollapseLowSide:
+ case SlowCollapseHighSide:
+ if (CurData < DataRecord.MinValue) {
+ DataRecord.MinValue = CurData;
+ }
+ DataRecord.SampleCnt++;
+ break;
+ }
+ break;
+ case SampleState_PreSampleBat:
+ if (SampleStateCnt > 4)
+ DataRecord.SampleState = SampleState_SampleBat;
+ ++SampleStateCnt;
+ break;
+ case SampleState_SampleBat:
+ DataRecord.BaseValue = CurData;
+ if (BatSampleWhileOn()) {
+ ADConv::SetChannel(ADConv::Ch_MotorCurrent,ADConv::Ref_MotorCurrent,ADConv::RightAdjust);
+ DataRecord.SampleState = SampleState_PreCurrentSample;
+ } else {
+ SetADChannelMotorNegative();
+ DataRecord.SampleState = SampleState_PreSearchMax;
+ }
+ break;
+ case SampleState_PreCurrentSample:
+ ADConv::SetChannel(ADConv::Ch_MotorCurrent,ADConv::Ref_MotorCurrent,ADConv::RightAdjust);
+ CurrentSampleCnt = 0;
+ DataRecord.SampleState = SampleState_CurrentSample1;
+ break;
+ case SampleState_CurrentSample1:
+ if (CurData > DataRecord.CurrentLimit) HandleOverload();
+ if (CurrentSampleCnt == 0) {
+ DataRecord.CurrentTemp = CurData;
+ DataRecord.CurrentMaxSearch = CurData;
+ }
+ ++CurrentSampleCnt;
+ if (CurData > DataRecord.CurrentMaxSearch) DataRecord.CurrentMaxSearch = CurData;
+ if (CurrentSampleCnt == 3) DataRecord.SampleState = SampleState_CurrentSample2;
+ break;
+ case SampleState_CurrentSample2:
+ if (CurData > DataRecord.CurrentLimit) HandleOverload();
+ // Sample delta-current. It is related to the back-EMF voltage, though
+ // this measurement is not precise enough to base control off of it
+ DataRecord.CurrentDelta = CurData - DataRecord.CurrentTemp;
+ DataRecord.CurrentTemp = CurData;
+ if (CurData > DataRecord.CurrentMaxSearch) DataRecord.CurrentMaxSearch = CurData;
+ DataRecord.SampleState = SampleState_CurrentSample3;
+ break;
+ case SampleState_CurrentSample3:
+ // We'll stay in this state until the on-phase ends...
+ if (CurData > DataRecord.CurrentLimit) HandleOverload();
+ DataRecord.CurrentTemp = CurData;
+ if (CurData > DataRecord.CurrentMaxSearch) DataRecord.CurrentMaxSearch = CurData;
+ break;
+ }
+ }
+}
+
+SIGNAL(SIG_OUTPUT_COMPARE1A) {HBridge::HandleIRQ(true);}
+SIGNAL(SIG_OUTPUT_COMPARE1B) {HBridge::HandleIRQ(false);}
+SIGNAL(SIG_ADC) {HBridge::Sample();}
+
+namespace TWI {
+ uint8_t Address;
+
+ extern const sConfigRecord ConfigRecord PROGMEM __attribute__ ((weak)) = {UniqueIDUnassigned,
+ DevClassHBridge,
+#if defined MEGA_BRIDGE
+ DevUmHBridge
+#elif defined H_BRIDGE
+ DevUmHBridge
+#elif defined SERVO_BRAIN
+ DevUmServoBrain
+#else
+#error No HW version is specified!
+#endif
+ };
+
+ enum UserStates {
+ US_ReceiveAddr = TWI::US_Base,
+ US_ReceiveData,
+ US_SendData
+ };
+
+ void HandleUserReceive() {
+ State = US_ReceiveAddr;
+ }
+
+ union {
+ uint8_t UInt8[4];
+ uint16_t UInt16[2];
+ uint32_t UInt32[1];
+ } TransmitBuffer;
+
+ void SendData() __attribute__ ((noinline));
+
+ void SendData() {
+ switch (HBridge::GetDataElementSize(Address)) {
+ default:
+ case 1:
+ TWIPrevData = *HBridge::GetDataRecord8(Address);
+ break;
+ case 2:
+ if ((Address & 1) == 0) {
+ TransmitBuffer.UInt16[0] = *HBridge::GetDataRecord16(Address);
+ }
+ TWIPrevData = TransmitBuffer.UInt8[Address & 1];
+ break;
+ case 4:
+ if ((Address & 3) == 0) {
+ TransmitBuffer.UInt32[0] = *HBridge::GetDataRecord32(Address);
+ }
+ TWIPrevData = TransmitBuffer.UInt8[Address & 3];
+ break;
+ }
+ TWDR = TWIPrevData;
+ ++Address;
+ if (Address >= HBridge::GetDataRecordSize()) Address = 0; // Wrap around
+ }
+
+ void GetData() {
+ switch (HBridge::GetDataElementSize(Address)) {
+ default:
+ case 1:
+ TransmitBuffer.UInt8[0] = TWIData;
+ *HBridge::GetDataRecord8(Address) = TransmitBuffer.UInt8[0];
+ break;
+ case 2:
+ TransmitBuffer.UInt8[Address & 1] = TWIData;
+ if ((Address & 1) != 0) {
+ // High-byte: store the whole word
+ *HBridge::GetDataRecord16(Address & (~0x01)) = TransmitBuffer.UInt16[0];
+ // Special-case request value, we have to save that in another spot as well...
+ if (Address == 1) {
+ HBridge::DataRecord.OriginalRequestValue = TransmitBuffer.UInt16[0];
+ }
+ }
+ break;
+ case 4:
+ TransmitBuffer.UInt8[Address & 3] = TWIData;
+ if ((Address & 3) != 0) {
+ // Highest byte: store the whole dword
+ *HBridge::GetDataRecord32(Address & (~0x03)) = TransmitBuffer.UInt32[0];
+ }
+ break;
+ }
+ ++Address;
+ if (Address >= HBridge::GetDataRecordSize()) Address = 0; // Wrap around
+ }
+
+ void HandleUserTransmit() {
+ SendData();
+ State = US_SendData;
+ }
+
+ void HandleUserState() {
+ switch (State) {
+ case US_ReceiveAddr:
+ switch (TWIStatus) {
+ case TW_SR_DATA_ACK:
+ // TODO: handle different command codes here -> check the data written to this address!
+ if (TWIData == 0xff) {
+ HBridge::SaveSettings();
+ ResetTWI();
+ } else {
+ //if ((TWIData & 0x7f) >= HBridge::GetDataRecordSize()) Address = HBridge::GetDataRecordSize() - 1; else Address = TWIData;
+ if (TWIData >= HBridge::GetDataRecordSize()) Address = HBridge::GetDataRecordSize() - 1; else Address = TWIData;
+ State = US_ReceiveData;
+ }
+ break;
+ default:
+ ResetTWI();
+ break;
+ }
+ break;
+ case US_ReceiveData:
+ switch (TWIStatus) {
+ case TW_SR_DATA_ACK:
+ GetData();
+ // We stay in this state for any optional additional data
+ break;
+ default:
+ ResetTWI();
+ break;
+ }
+ break;
+ case US_SendData:
+ switch (TWIStatus) {
+ case TW_ST_DATA_ACK:
+ SendData();
+ SETBIT(TWIControl,(1 << TWEA)); // require ACK
+ break;
+ default:
+ ResetTWI();
+ break;
+ }
+ break;
+ default:
+ // This really REALLY shouldn't happen...
+ ResetTWI();
+ break;
+ }
+ }
+}
+
+#ifdef USE_SERIAL_DEBUG
+// Debug interfaces
+namespace UsartComm {
+ inline void Init(uint16_t aBaudSetting) {
+ USART0::Init(aBaudSetting);
+ }
+ void HandleInput() {
+ uint8_t CurData = USART0::FastReceiveData();
+ OpLed::Toggle();
+ }
+}
+
+SIGNAL(SIG_USART_RECV) {UsartComm::HandleInput();}
+
+void DebugStat() {
+ cli();
+ int16_t VoltageSample = HBridge::DataRecord.VoltageSample;
+ uint16_t SampleCnt = HBridge::DataRecord.SampleCnt_Snapshot;
+ int16_t MinValue = HBridge::DataRecord.MinValue_Snapshot;
+ int16_t CurrentRequest = HBridge::DataRecord.CurrentRequest;
+ int16_t Error = HBridge::DataRecord.Error;
+ int16_t IValue = HBridge::DataRecord.IValue;
+ int16_t Command = HBridge::DataRecord.Command;
+ sei();
+
+ USART0::SendHexData(VoltageSample);
+ USART0::SendData(' '); USART0::SendData('S'); USART0::SendData(':'); USART0::SendHexData(SampleCnt);
+ USART0::SendData(' '); USART0::SendData('M'); USART0::SendData(':'); USART0::SendHexData(MinValue);
+ USART0::SendData(' '); USART0::SendData('R'); USART0::SendData(':'); USART0::SendHexData(CurrentRequest);
+ USART0::SendData(' '); USART0::SendData('E'); USART0::SendData(':'); USART0::SendHexData(Error);
+ USART0::SendData(' '); USART0::SendData('I'); USART0::SendData(':'); USART0::SendHexData(IValue);
+ USART0::SendData(' '); USART0::SendData('C'); USART0::SendData(':'); USART0::SendHexData(Command);
+ USART0::SendData('\r'); USART0::SendData('\n');
+}
+#endif // USE_SERIAL_DEBUG
+
+int main() {
+ cli();
+ EEPROM::Init();
+ OpLed::Init();
+ HBridge::BlinkCnt = 0;
+ #ifdef USE_SERIAL_DEBUG
+ UsartComm::Init(USART0::baud57600_8MHz);
+ #endif // USE_SERIAL_DEBUG
+ TCCR0A = 0;
+ TWI::Init();
+ ADConv::Init();
+ HBridge::Init();
+ SETBIT(DDRD,0x08|0x10);
+ sei();
+
+ // Everything happens in the interrupt routines. We have nothing else to do
+ // here but some optional debugging
+ while (true) {
+ #ifdef USE_SERIAL_DEBUG
+ cli();
+ if (HBridge::DataRecord.NewData) {
+ HBridge::DataRecord.NewData = false;
+ DebugStat();
+ } else {
+ sei();
+ }
+ #endif // USE_SERIAL_DEBUG
+ }
+ return 0;
+}
/Modules/HBRIDGE/HB2FET02A/SW/avr4.x
0,0 → 1,168
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:4)
MEMORY
{
text (rx) : ORIGIN = 0, LENGTH = 8K
data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
}
SECTIONS
{
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
/* Internal text space or external memory */
.text :
{
KEEP (*(.vectors))
__ctors_start = . ;
KEEP (*(.ctors))
__ctors_end = . ;
__dtors_start = . ;
KEEP (*(.dtors))
__dtors_end = . ;
*(.progmem.gcc*)
*(.progmem*)
. = ALIGN(2);
KEEP (*(.init0)) /* Start here after reset. */
KEEP (*(.init1))
KEEP (*(.init2)) /* Clear __zero_reg__, set up stack pointer. */
KEEP (*(.init3))
KEEP (*(.init4)) /* Initialize data and BSS. */
KEEP (*(.init5))
KEEP (*(.init6)) /* C++ constructors. */
KEEP (*(.init7))
KEEP (*(.init8))
KEEP (*(.init9)) /* Call main(). */
*(.text)
. = ALIGN(2);
*(.text.*)
. = ALIGN(2);
*(.fini9) /* _exit() starts here. */
*(.fini8)
*(.fini7)
*(.fini6) /* C++ destructors. */
*(.fini5)
*(.fini4)
*(.fini3)
*(.fini2)
*(.fini1)
*(.fini0) /* Infinite loop after program termination. */
_etext = . ;
} > text
.data : AT (ADDR (.text) + SIZEOF (.text))
{
PROVIDE (__data_start = .) ;
*(.data)
*(.gnu.linkonce.d*)
. = ALIGN(2);
_edata = . ;
PROVIDE (__data_end = .) ;
} > data
.bss SIZEOF(.data) + ADDR(.data) :
{
PROVIDE (__bss_start = .) ;
*(.bss)
*(COMMON)
PROVIDE (__bss_end = .) ;
} > data
__data_load_start = LOADADDR(.data);
__data_load_end = __data_load_start + SIZEOF(.data);
/* Global data not cleared after reset. */
.noinit SIZEOF(.bss) + ADDR(.bss) :
{
PROVIDE (__noinit_start = .) ;
*(.noinit*)
PROVIDE (__noinit_end = .) ;
_end = . ;
PROVIDE (__heap_start = .) ;
} > data
.eeprom :
{
*(.eeprom*)
__eeprom_end = . ;
} > eeprom
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
}
/Modules/HBRIDGE/HB2FET02A/SW/avr5.x
0,0 → 1,168
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:5)
MEMORY
{
text (rx) : ORIGIN = 0, LENGTH = 128K
data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
}
SECTIONS
{
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
/* Internal text space or external memory */
.text :
{
KEEP (*(.vectors))
__ctors_start = . ;
KEEP (*(.ctors))
__ctors_end = . ;
__dtors_start = . ;
KEEP (*(.dtors))
__dtors_end = . ;
*(.progmem.gcc*)
*(.progmem*)
. = ALIGN(2);
KEEP (*(.init0)) /* Start here after reset. */
KEEP (*(.init1))
KEEP (*(.init2)) /* Clear __zero_reg__, set up stack pointer. */
KEEP (*(.init3))
KEEP (*(.init4)) /* Initialize data and BSS. */
KEEP (*(.init5))
KEEP (*(.init6)) /* C++ constructors. */
KEEP (*(.init7))
KEEP (*(.init8))
KEEP (*(.init9)) /* Call main(). */
*(.text)
. = ALIGN(2);
*(.text.*)
. = ALIGN(2);
*(.fini9) /* _exit() starts here. */
*(.fini8)
*(.fini7)
*(.fini6) /* C++ destructors. */
*(.fini5)
*(.fini4)
*(.fini3)
*(.fini2)
*(.fini1)
*(.fini0) /* Infinite loop after program termination. */
_etext = . ;
} > text
.data : AT (ADDR (.text) + SIZEOF (.text))
{
PROVIDE (__data_start = .) ;
*(.data)
*(.gnu.linkonce.d*)
. = ALIGN(2);
_edata = . ;
PROVIDE (__data_end = .) ;
} > data
.bss SIZEOF(.data) + ADDR(.data) :
{
PROVIDE (__bss_start = .) ;
*(.bss)
*(COMMON)
PROVIDE (__bss_end = .) ;
} > data
__data_load_start = LOADADDR(.data);
__data_load_end = __data_load_start + SIZEOF(.data);
/* Global data not cleared after reset. */
.noinit SIZEOF(.bss) + ADDR(.bss) :
{
PROVIDE (__noinit_start = .) ;
*(.noinit*)
PROVIDE (__noinit_end = .) ;
_end = . ;
PROVIDE (__heap_start = .) ;
} > data
.eeprom :
{
*(.eeprom*)
__eeprom_end = . ;
} > eeprom
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
}
/Modules/HBRIDGE/HB2FET02A/SW/common.h
0,0 → 1,33
#ifndef __common_h__
#define __common_h__
 
#define CLRBIT(aReg,aBit) (aReg) &= ~(aBit)
#define SETBIT(aReg,aBit) (aReg) |= (aBit)
#define TOGGLEBIT(aReg,aBit) (aReg) ^= (aBit)
//#define TESTBIT(aValue,aConst) ((aValue & aConst) != 0)
#define TESTBIT(aValue,aConst) ({ \
uint8_t Temp = (uint8_t)(aValue); \
__asm__ ( \
"andi %0, %2" "\n\t" \
"breq L_%=" "\n\t" \
"ldi %0,1" "\n\t" \
"L_%=: " "\n\t" \
: "=r" (Temp) : "0" (Temp), "M" (aConst)\
); \
Temp; \
})
 
 
#if defined BOARD_rs232if
#define BOARD
#elif defined BOARD_umServo32
#define BOARD
#elif defined BOARD_umHBridge
#define BOARD
#elif defined BOARD_NA
#define BOARD
#else
#error BOARD_xxx must be defined
#endif
 
#endif // __common_h__
/Modules/HBRIDGE/HB2FET02A/SW/eeprom.cpp
0,0 → 1,43
#include <avr/pgmspace.h>
#include "eeprom.h"
#include "common.h"
 
void EEPROM::Wait() {
while(TESTBIT(EECR,(1<<EEPE)));
}
 
uint8_t EEPROM::GetByte(uint16_t aOfs) {
// Wait for any pending writes to finish
while(TESTBIT(EECR,(1<<EEPE)));
EEARL = aOfs & 0x00ff;
#ifdef EEARH
EEARH = 0;
#endif
SETBIT(EECR,(1 << EERE));
uint8_t RetVal = EEDR;
return RetVal;
}
 
void EEPROM::SetByte(uint16_t aOfs,uint8_t aData) {
// Wait for any pending writes to finish
while(TESTBIT(EECR,(1<<EEPE)));
EEARL = aOfs & 0x00ff;
#ifdef EEARH
EEARH = 0;
#endif
EEDR = aData;
SETBIT(EECR,(1<<EEMPE));
SETBIT(EECR,(1<<EEPE));
}
 
uint16_t EEPROM::GetWord(uint16_t aOfs) {
uint16_t RetVal;
((uint8_t *)(&RetVal))[0] = GetByte(aOfs+0);
((uint8_t *)(&RetVal))[1] = GetByte(aOfs+1);
return RetVal;
}
 
void EEPROM::SetWord(uint16_t aOfs,uint16_t aData) {
SetByte(aOfs+0,((uint8_t *)(&aData))[0]);
SetByte(aOfs+1,((uint8_t *)(&aData))[1]);
}
/Modules/HBRIDGE/HB2FET02A/SW/eeprom.h
0,0 → 1,18
#ifndef __EEPROM_H__
#define __EEPROM_H__
 
namespace EEPROM {
inline void Init() {
EECR = 0; // Make sure we're erasing and writing at the same time
}
uint8_t GetByte(uint16_t aOfs);
void SetByte(uint16_t aOfs,uint8_t aData);
uint16_t GetWord(uint16_t aOfs);
void SetWord(uint16_t aOfs,uint16_t aData);
void Wait();
}
 
namespace EEPROM_layout {
}
 
#endif // __EEPROM_H__
/Modules/HBRIDGE/HB2FET02A/SW/gentwiuid.exe
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Modules/HBRIDGE/HB2FET02A/SW/guids.h
0,0 → 1,63
#ifndef __guids_h__
#define __guids_h__
 
#ifdef BOARD
// We're included for the target board. Define various structures
struct GUID {
uint32_t Part1;
uint16_t Part2;
uint16_t Part3;
uint8_t Part4[8];
};
#endif
 
// These are the only valid values for UniqueID items
const uint8_t num0 = 0x00;
const uint8_t num1 = 0x01;
const uint8_t num2 = 0x03;
const uint8_t num3 = 0x07;
const uint8_t num4 = 0x0f;
const uint8_t num5 = 0x1f;
const uint8_t num6 = 0x3f;
const uint8_t num7 = 0x7f;
const uint8_t num8 = 0xff; // this value is never used in any valid uniqueID, however it IS used in the unassigned ID
 
// Unique IDs
#define UniqueIDUnassigned { \
num0,num1,num2,num3, \
num4,num5,num6,num7, \
num8,num7,num6,num5, \
num4,num3,num2,num1, \
num0,num1,num2,num3, \
num4,num5,num6,num7, \
num8,num7,num6,num5, \
num4,num3,num2,num1, \
num0,num1,num2,num3, \
num4,num5,num6,num7, \
num8,num7,num6,num5, \
num4,num3,num2,num1 \
}
 
// Device Class GUIDs
// {00000000-0000-0000-0000-000000000000}
#define DevClassReserved { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
// {D8745C7D-71A5-4977-A989-2E1EF853CCB8}
#define DevClassUnassigned { 0xd8745c7d, 0x71a5, 0x4977, { 0xa9, 0x89, 0x2e, 0x1e, 0xf8, 0x53, 0xcc, 0xb8 } }
// {15D37F46-A4F2-416d-8157-FAB7D1A66BE8}
#define DevClassServoController { 0x15d37f46, 0xa4f2, 0x416d, { 0x81, 0x57, 0xfa, 0xb7, 0xd1, 0xa6, 0x6b, 0xe8 } }
// {D3C8787E-DCE8-445b-B1C7-86C2BF85D144}
#define DevClassHBridge { 0xd3c8787e, 0xdce8, 0x445b, { 0xb1, 0xc7, 0x86, 0xc2, 0xbf, 0x85, 0xd1, 0x44 } }
 
// Device GUIDs
// {00000000-0000-0000-0000-000000000000}
#define DevReserved { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
// {E59F78CE-6328-4316-B1DE-F0AA5E45F34F}
#define DevUnassigned { 0xe59f78ce, 0x6328, 0x4316, { 0xb1, 0xde, 0xf0, 0xaa, 0x5e, 0x45, 0xf3, 0x4f } }
// {E3470D73-9110-4d61-915E-916FF8A89BA6}
#define DevUmServo32 { 0xe3470d73, 0x9110, 0x4d61, { 0x91, 0x5e, 0x91, 0x6f, 0xf8, 0xa8, 0x9b, 0xa6 } }
// {CF232A58-497F-4bba-9E13-D9AB7938B418}
#define DevUmHBridge { 0xcf232a58, 0x497f, 0x4bba, { 0x9e, 0x13, 0xd9, 0xab, 0x79, 0x38, 0xb4, 0x18 } }
// {518FC22C-B5A1-40b3-8D7C-C75EC729F25C}
#define DevUmServoBrain { 0x518fc22c, 0xb5a1, 0x40b3, { 0x8d, 0x7c, 0xc7, 0x5e, 0xc7, 0x29, 0xf2, 0x5c } }
 
#endif // __guids_h__
/Modules/HBRIDGE/HB2FET02A/SW/opled.h
0,0 → 1,34
#ifndef __opled_h__
#define __opled_h__
 
#include "common.h"
 
namespace OpLed {
#if defined BOARD_rs232if
const int OpLedMask=(0x01 << 4);
#elif defined BOARD_umServo32
const int OpLedMask=(0x01 << 4);
#elif defined BOARD_umHBridge
const int OpLedMask=(0x01 << 2);
#else
#error Unknown board specification
#endif
 
void inline Init() {
SETBIT(DDRD,OpLedMask);
}
 
void inline On() {
SETBIT(PORTD,OpLedMask);
}
 
void inline Off() {
CLRBIT(PORTD,OpLedMask);
}
 
void inline Toggle() {
TOGGLEBIT(PORTD,OpLedMask);
}
}
 
#endif // __opled_h__
/Modules/HBRIDGE/HB2FET02A/SW/twi_aap.cpp
0,0 → 1,375
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/sleep.h>
 
#include "common.h"
#include "usart.h"
#include "twi_aap.h"
#include "eeprom.h"
 
/*********
switch (TWOStatus) {
case TW_SR_SLA_ACK: //0x60
break;
case TW_SR_ARB_LOST_SLA_ACK: //0x68
break;
case TW_SR_GCALL_ACK: //0x70
break;
case TW_SR_ARB_LOST_GCALL_ACK: //0x78
break;
case TW_SR_DATA_ACK: //0x80
break;
case TW_SR_DATA_NACK: //0x88
break;
case TW_SR_GCALL_DATA_ACK: //0x90
break;
case TW_SR_GCALL_DATA_NACK: //0x98
break;
case TW_ST_LAST_DATA: //0xC8
case TW_SR_STOP: //0xA0
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
break;
default: // All non-handled states will basically terminate any processing
State = MS_Idle;
CLRBIT(TWIControl,(1 << TWEA)); // will return NACK, i.e. will pretend to be unaddressed
break;
}
 
switch (TWOStatus) {
case TW_ST_SLA_ACK: //0xA8
break;
case TW_ST_ARB_LOST_SLA_ACK: //0xB0
break;
case TW_ST_DATA_ACK: //0xB8
break;
case TW_ST_DATA_NACK: //0xC0
break;
case TW_ST_ARB_LOST: //0x38 - let's hope it works
break;
case TW_ST_LAST_DATA: //0xC8
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
break;
default: // All non-handled states will basically terminate any processing
State = MS_Idle;
CLRBIT(TWIControl,(1 << TWEA)); // will return NACK, i.e. will pretend to be unaddressed
break;
}
**********/
 
namespace TWI {
extern const sConfigRecord ConfigRecord PROGMEM __attribute__ ((weak)) = {UniqueIDUnassigned,DevClassUnassigned,DevUnassigned};
 
// void TWI::UserInit() __attribute__ ((weak));
void TWI::HandleUserReceive() __attribute__ ((weak));
void TWI::HandleUserTransmit() __attribute__ ((weak));
void TWI::HandleUserState() __attribute__ ((weak));
static inline void TWI::HandleState_MS_Idle();
static inline void TWI::HandleState_MS_Addressed();
static inline void TWI::StateMachine();
 
uint8_t ConfigCnt;
}
 
void TWI::ResetTWITransmit() {
// Same as above, but also returns the statemachine to the idle state
State = MS_Idle;
LastCmd = TWI_AAPCmd_Reserved;
// In slave-transmitter mode it's not possible to reset the TWI.
// But at least we can transmit all '1'-s so we won't interfere with the bus.
#ifdef SERIAL_DBG
USART0::SendData('*');
#endif
TWDR = 0xff;
SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO));
}
void TWI::ResetTWIReceive() {
// Same as above, but also returns the statemachine to the idle state
State = MS_Idle;
LastCmd = TWI_AAPCmd_Reserved;
// In slave-transmitter mode it's not possible to reset the TWI.
// But at least we can transmit all '1'-s so we won't interfere with the bus.
#ifdef SERIAL_DBG
USART0::SendData('#');
#endif
TWDR = 0xff;
SETBIT(TWIControl,(1 << TWSTO));
CLRBIT(TWIControl,(1 << TWEA));
}
void TWI::ResetTWI() {
switch (TWIStatus) {
case TW_ST_LAST_DATA: //0xC8
case TW_SR_STOP:
case TW_ST_DATA_NACK:
case TW_SR_DATA_NACK:
case TW_SR_GCALL_DATA_NACK:
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting
break;
case TW_BUS_ERROR:
// This is the point where we re-enable the address recognition
ResetTWITransmit();
break;
default:
ResetTWIReceive();
break;
}
}
 
/*void TWI::UserInit() {
}*/
 
void TWI::HandleUserReceive() {
#ifdef SERIAL_DBG
USART0::SendData('r');
#endif
ResetTWI();
}
 
void TWI::HandleUserTransmit() {
#ifdef SERIAL_DBG
USART0::SendData('t');
#endif
ResetTWI();
}
 
void TWI::HandleUserState() {
}
 
 
static inline void TWI::HandleState_MS_Idle() {
switch (TWIStatus) {
case TW_SR_SLA_ACK:
LastCmd = TWI_AAPCmd_Reserved;
HandleUserReceive();
break;
case TW_SR_GCALL_ACK:
State = MS_Addressed;
break;
case TW_ST_SLA_ACK:
if ((TWIData & 0xfe) == GeneralCallAddr) {
// TWI_AAP read command: things depend on what the last (write) command was:
if (LastCmd == TWI_AAPCmd_GetConfig) {
// This is the read part of the GetUDID command: Send the byte count and change state
TWIPrevData = sizeof(ConfigRecord);
TWDR = TWIPrevData;
State = AAP_CmdGetConfig_SendConfig;
ConfigCnt = 0;
//SETBIT(TWIControl,(1 << TWEA)); // require ACK
} else {
//Unknown read command: ignore
ResetTWITransmit();
}
} else {
HandleUserTransmit();
}
break;
case TW_ST_LAST_DATA:
case TW_SR_STOP:
#ifdef SERIAL_DBG
USART0::SendData('.');
#endif
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting
break;
case TW_ST_DATA_ACK:
case TW_SR_DATA_ACK:
case TW_SR_GCALL_DATA_ACK:
ResetTWIReceive();
break;
case TW_BUS_ERROR:
case TW_ST_DATA_NACK:
case TW_SR_DATA_NACK:
case TW_SR_GCALL_DATA_NACK:
// This is the point where we re-enable the address recognition
ResetTWITransmit();
break;
default:
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI
break;
}
}
 
static inline void TWI::HandleState_MS_Addressed() {
switch (TWIStatus) {
case TW_SR_GCALL_DATA_ACK:
switch(TWIData) {
case TWI_AAPCmd_ResetDevices:
LastCmd = TWIData;
State = MS_Idle;
SoftAddress = 0;
TWAR = SoftAddress | 1; // General call recognition and slave-receiver mode through address being 0
break;
case TWI_AAPCmd_ResetToPermAddress:
LastCmd = TWIData;
State = MS_Idle;
SoftAddress = EEPROM::GetByte(EEPROM_layout::TWI_SoftAddr_Ofs);
TWAR = SoftAddress | 1; // General call recognition and slave-receiver mode
if (SoftAddress != 0) {
// We have a valid address, do not respond to this command
LastCmd = TWI_AAPCmd_Reserved;
}
break;
case TWI_AAPCmd_GetConfig:
LastCmd = TWIData;
State = AAP_CmdGetConfig_GetAddress;
break;
case TWI_AAPCmd_AssignAddress:
LastCmd = TWIData;
ConfigCnt = 0;
State = AAP_CmdAssignAddress_GetUniqueID;
break;
default:
// unknown command - ignore the rest
ResetTWIReceive();
break;
}
break;
default:
ResetTWI();
break;
}
}
 
static inline void TWI::StateMachine() {
TWIStatus = TWSR & TW_STATUS_MASK;
TWIControl = TWCR;
if (TWIStatus != TW_SR_STOP) {
TWIData = TWDR;
} else {
// Fast short-circuit for stop-bit detection
// This condition cannot use clock-stretching so we might miss the next start if we don't hurry
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA)); // turn address recognition back on
CLRBIT(TWIControl,(1 << TWSTO)); // even if we did so, stop aborting
SETBIT(TWIControl,(1 << TWINT));
TWCR = TWIControl;
return;
}
 
#ifdef SERIAL_DBG
// DUMP state to serial port
USART0::SendData('s'); USART0::SendData(' '); USART0::SendHexData(TWIStatus); USART0::SendData(' ');
USART0::SendData('d'); USART0::SendData(' '); USART0::SendHexData(TWIData); USART0::SendData(' ');
USART0::SendData('S'); USART0::SendData(' '); USART0::SendHexData(State); USART0::SendData(' ');
USART0::SendData('L'); USART0::SendData(' '); USART0::SendHexData(LastCmd); USART0::SendData(' ');
USART0::SendData('A'); USART0::SendData(' '); USART0::SendHexData(SoftAddress); USART0::SendData('-');
#endif
switch (State) {
case MS_Idle:
HandleState_MS_Idle();
break;
case MS_Addressed:
HandleState_MS_Addressed();
break;
 
case AAP_CmdGetConfig_GetAddress:
switch (TWIStatus) {
case TW_SR_GCALL_DATA_ACK:
State = MS_Idle;
SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI
if (SoftAddress != TWIData) {
// We have a valid address, or was not addressed -> do not respond to this command
LastCmd = TWI_AAPCmd_Reserved;
}
break;
default:
ResetTWI();
break;
}
break;
 
case AAP_CmdAssignAddress_GetUniqueID:
switch (TWIStatus) {
case TW_SR_GCALL_DATA_ACK:
if (TWIData == pgm_read_byte(ConfigRecord.UniqueID+ConfigCnt)) {
++ConfigCnt;
if (ConfigCnt == UniqueID_Size) State = AAP_CmdAssignAddress_GetAddress;
} else {
// UDID is not ours, abort command
ResetTWIReceive();
}
break;
default:
ResetTWI();
break;
}
break;
case AAP_CmdAssignAddress_GetAddress:
switch (TWIStatus) {
case TW_SR_GCALL_DATA_ACK:
SoftAddress = TWIData & 0xfe;
if (TWIData & 0x01 == 1) {
EEPROM::SetByte(EEPROM_layout::TWI_SoftAddr_Ofs,SoftAddress);
}
State = MS_Idle;
TWAR = SoftAddress | 1; // General call recognition and normal operation
SETBIT(TWIControl,(1 << TWEA) | (1 << TWSTO)); // reset the TWI
LastCmd = TWI_AAPCmd_Reserved;
break;
default:
ResetTWI();
break;
}
break;
 
 
 
// Read-oriented commands
case AAP_CmdGetConfig_SendConfig:
switch (TWIStatus) {
case TW_ST_DATA_ACK:
if (TWIData != TWIPrevData) {
// We've lost the arbitration
ResetTWITransmit();
break;
}
TWIPrevData = pgm_read_byte(((uint8_t*)(&ConfigRecord))+ConfigCnt);
TWDR = TWIPrevData;
ConfigCnt++;
//At the last byte, we require NACK
if (ConfigCnt == sizeof(ConfigRecord)) {
State = MS_Idle;
CLRBIT(TWIControl,(1 << TWEA)); // require NACK
} else {
State = AAP_CmdGetConfig_SendConfig;
SETBIT(TWIControl,(1 << TWEA)); // require ACK
}
break;
 
default:
ResetTWI();
break;
}
break;
 
// User commands
default:
HandleUserState();
break;
}
// re-enable the TWI interrupts
SETBIT(TWIControl,1 << TWINT);
#ifdef SERIAL_DBG
USART0::SendData('S'); USART0::SendData(' '); USART0::SendHexData(State); USART0::SendData(' ');
USART0::SendData('L'); USART0::SendData(' '); USART0::SendHexData(LastCmd); USART0::SendData(' ');
USART0::SendData('A'); USART0::SendData(' '); USART0::SendHexData(SoftAddress); USART0::SendData(' ');
USART0::SendData('C'); USART0::SendData(' '); USART0::SendHexData(TWIControl); USART0::SendData(0x0d); USART0::SendData(0x0a);
#endif
TWCR = TWIControl;
}
 
SIGNAL(SIG_TWI) {TWI::StateMachine();}
 
uint8_t TWI::State;
uint8_t TWI::LastCmd;
uint8_t TWI::SoftAddress;
uint8_t TWI::TWIStatus;
uint8_t TWI::TWIData;
uint8_t TWI::TWIPrevData;
uint8_t TWI::TWIControl;
/Modules/HBRIDGE/HB2FET02A/SW/twi_aap.h
0,0 → 1,77
#ifndef __twi_aap_h__
#define __two_aap_h__
 
#include <compat/twi.h>
 
#include "common.h"
#include "usart.h"
#include "guids.h"
#include "eeprom.h"
//#define SERIAL_DBG
 
namespace EEPROM_layout {
const uint16_t TWI_SoftAddr_Ofs = 0xff;
}
 
namespace TWI {
const uint8_t GeneralCallAddr = 0;
const size_t UniqueID_Size = 16*3;
const size_t GUID_Size = sizeof(GUID);
 
struct sConfigRecord {
uint8_t UniqueID[UniqueID_Size];
GUID ClassID;
GUID DevID;
};
 
enum TWI_AAPCommands {
TWI_AAPCmd_Reserved = 0,
TWI_AAPCmd_Start = 0x20,
TWI_AAPCmd_End = 0x21,
TWI_AAPCmd_ResetDevices = 0x22,
TWI_AAPCmd_ResetToPermAddress = 0x23,
TWI_AAPCmd_GetConfig = 0x24,
TWI_AAPCmd_AssignAddress = 0x25
};
enum MainStates {
MS_Idle = 0,
MS_Addressed,
AAP_CmdGetConfig_GetAddress,
AAP_CmdGetConfig_SendConfig,
AAP_CmdAssignAddress_GetUniqueID,
AAP_CmdAssignAddress_GetAddress,
US_Base
};
 
extern uint8_t State;
extern uint8_t LastCmd;
extern uint8_t SoftAddress;
 
inline void Init() {
TWBR = 32; // 100kHz with an 8MHz crystal
// TWBR = 16; // 200kHz with an 8MHz crystal
TWSR = 0; // pre-scaler: 1
TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE) | (1 << TWINT);
if (TWSR == TW_BUS_ERROR) SETBIT(TWCR,(1 << TWSTO)); // reset TWI
TWAMR = 0; // all address bits matter
State = MS_Idle;
SoftAddress = EEPROM::GetByte(EEPROM_layout::TWI_SoftAddr_Ofs);
if (SoftAddress == 0xff) SoftAddress = 0;
SoftAddress &= 0xfe;
// TWAR = GeneralCallAddr | 1; // General call recognition and slave-receiver mode through address being 0
TWAR = SoftAddress | 1;
LastCmd = TWI_AAPCmd_Reserved;
}
 
// These used in all states, including user states, so make them available.
extern uint8_t TWIStatus;
extern uint8_t TWIData;
extern uint8_t TWIPrevData;
extern uint8_t TWIControl;
 
void ResetTWITransmit();
void ResetTWIReceive();
void ResetTWI();
}
 
#endif // __twi_aap_h__
/Modules/HBRIDGE/HB2FET02A/SW/usart.cpp
0,0 → 1,65
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
 
#include "common.h"
#include "usart.h"
 
 
void USART0::SendData(uint8_t aData) {
while(!TESTBIT(UCSR0A,(1 << UDRE0)));
UDR0 = aData;
}
 
uint8_t USART0::ReceiveData() {
while(!TESTBIT(UCSR0A,(1 << RXC0)));
return UDR0;
}
 
// a non-exported helper function
static char MakeHexDigit(uint8_t aDigit) {
if (aDigit > 9) return 'a'+aDigit-10; else return '0'+aDigit;
}
 
void USART0::SendHexData(uint8_t aData) {
SendData(MakeHexDigit(aData >> 4));
SendData(MakeHexDigit(aData & 0x0f));
}
 
void USART0::SendHexData(uint16_t aData) {
SendHexData((uint8_t)(aData >> 8));
SendHexData((uint8_t)(aData & 0xff));
}
 
void USART0::SendHexData(uint32_t aData) {
SendHexData((uint16_t)(aData >> 16));
SendHexData((uint16_t)(aData & 0xffff));
}
 
void USART0::SendHexData(int16_t aData) {
if (aData < 0) {
SendData('-');
aData = -aData;
} else {
SendData(' ');
}
SendHexData((uint16_t)aData);
}
 
void USART0::SendHexData(int32_t aData) {
if (aData < 0) {
SendData('-');
aData = -aData;
} else {
SendData(' ');
}
SendHexData((uint32_t)aData);
}
 
void USART0::SendString(const char *aString) {
while(aString != 0) SendData(*(aString++));
}
 
void USART0::SendPGString(const char *aString) {
while(aString != 0) SendData(pgm_read_byte(aString++));
}
/Modules/HBRIDGE/HB2FET02A/SW/usart.h
0,0 → 1,41
#ifndef __usart_h__
#define __usart_h__
 
#include "common.h"
 
namespace USART0 {
// setting = f_osc/16/BAUD - 1
const uint16_t baud9600_8MHz = 51;
const uint16_t baud19200_8MHz = 25;
const uint16_t baud57600_8MHz = 8;
const uint16_t baud19200_6_14MHz = 19;
const uint16_t baud38400_6_14MHz = 9;
const uint16_t baud19200_6_5MHz = 20;
const uint16_t baud38400_6_5MHz = 10;
const uint16_t baud57600_6_5MHz = 6;
inline uint8_t FastReceiveData();
inline void Init(uint16_t aBaudSetting) {
UBRR0 = aBaudSetting;
UCSR0A = 0;
FastReceiveData(); // Clear any possible pending input data (to avoid spurious IRQ
UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
void SendData(uint8_t aData);
uint8_t ReceiveData();
inline void FastSendData(uint8_t aData) {
UDR0 = aData;
}
inline uint8_t FastReceiveData() {
return UDR0;
}
void SendHexData(uint8_t aData);
void SendHexData(uint16_t aData);
void SendHexData(uint32_t aData);
void SendHexData(int16_t aData);
void SendHexData(int32_t aData);
void SendString(const char *aString);
void SendPGString(const char *aString);
}
 
#endif // __usart_h__
/Modules/HBRIDGE/HB2FET02A/SCH/HB2FET02A.DSN
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Modules/HBRIDGE/HB2FET02A/SCH/HB2FET02A.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property