ࡱ; L<  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry  !#$%&'()*+,-./23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`bcdefghijklmnopqrstuvwxy{|}~ ®`VTextStarWriter 5.0TASK,0,1.2,0,100,1,10665;649110;100;0;0;16200;10575;0;0SW5HDR.0/1!Numbering Symbols Internet linkBullet Symbols 301955031 311943031 333717031 350007031 200405041 331862041 370936041 420643081 425857121 425952121Outline0 # R-n#)QR-n#)QR-n#.QR-n#)QR-n#)QR-n#)R- n#)QR- n#)QR   n+.starbats n+.starbats6 n+.starbatsQ n+.starbatsl n+.starbats n+.starbats n+.starbats n+.starbats n+.starbats n+.starbats R   n+.starbats n+.starbats6 n+.starbatsQ n+.starbatsl n+.starbats n+.starbats n+.starbats n+.starbats n+.starbats n+.starbats ZSBX sb Z Standard StarBASICSBX ARSBX AR SBX AR2c%bqqp3 ObjEFFFD685@ޅ)䰱np3 ObjEFFFD686@ޅ)䰱I Vp3 ObjEFFFD687@ޅ)䰱 p3 ObjEFFFD688@ޅ)䰱/ H?O) SfxDocumentInfo  Tim Hurman .1tU Tim Hurman /1 Tim Hurman /1 Info 0 Info 1 Info 2 Info 3 .1`Flqc<44Standard LIBIMBEDDED LIBIMBEDDEDlSWG, A<  #$%&'()*./0123456789:;<=>?@ABCDGHK  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFQRSTUX0i!'@yX'9@ starbats helveticaXX!iXOutdevItemPool 1   )     &'()*+,-./06789:;UVWXYZ[\]c !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstt      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefde0x5g'(@w3XXX'^@W  3Ultrafine DashedXX,'^@;D7+mdH:XXXX&X.X6X>'@yBlackGray 30%Blue 7WhiteXX X7XQXi'c@ZkArrow}}XXQ'@SArrow}}#Arrow XXQX_' @ Iek %  W # XXXX&X.X6X>XFXNXVX^Xf' v@ t)ek@ HS0W FXXXX&X.X6X>XFXN'@O!X'@n!X@X @ @ @ @ @ @'@8nXX'@w""White?Gray 30%Gray 20%XX X2XIXc'6@ 22ddX'(@K  X'&(@%I1 BMvv(@@SD@x^SI 0 s\ z 46ZBn8x)1̔.<觔B+̄ ޢ40:prf |q]~+H~|WFMbP@aoCē[ȡz6~U{߃XRXf Xz!X"X#X$X%X&@1X@2X@82X@X2X@z2X@2X @2 @2@2X@3X  @'3X  @F3X   @`3   @v3   @3 @3 @3 @3@3X@ 4X @$4 @:4 @P4 @f4;(+@4X,, @4X--@4X..@4X//@5X00 @+511 @A522 @W533 @m544 @555 @566 @5II@5XJJ ^@6P}L?XXXX&X.X6X>KK@V6X(L@v6XMM@6XNN@6XOO@6XPP@6XQQ@$72XXRR@J7XSS^@7     XXXX&X.X6X>TT@7XUU@7XVV@82XXWW@?8XXX@_8XYY@~8XZZ@8X[[@8X\\@8X]]@8X__ @9`` @-9aa @C9bb @Y9cc @o9dd @9ee @9gg@9MXXhh@9\Xii@:\Xjj@':\Xkk@I:\Xll@k:\Xmm@:\Xnn@:MXXoo"@:ZXXpp@;\Xqq@);\Xrr @C;ss @Y;tt @o;uu @;vv @;ww @;xx @;yy @;@;*XX"@-<*y*XX"@[<*XX @y< @< @< @<- @-F''''~'''' ''''''''''''''''c '''''''''' '''''''''' '''''''''' '''''''''' ''''''''''  ''''''''''  ''''''''''  ''''''''''  ''''''''''  '''''''''' '''''''''' '''''''''''''''''' '''''''''' '''''''''' '''''''''' '''''''''' '''''''''' ''''''' ' '' '''''''' '''''''''' '''''''''' '''''''''' ''''''' ''' '''''''''' ''''''''''  ''''''' ' ''! ''''''''''" ''''''''''# ''''''''''$ ''''''' ' ''%''''&'''''(')*'+,'XX2XVXXXX^XXX6X~XXXVXXX.XRXvXXXNXXX&XnXXXXFXXXXfXXX> X X X X X X X X * @)T'''''    '''''    ''''''''''    '''''     '''''    '''''"     '''''"     '''''#     '''''      '''''      ''''' '''''''     '''''     '''''''#    '''''$     '''''    '''''    '''''    '''''    '''''$    '''''''!    '''''!    '''''    ''''''''''!     '''''    !'''''    "'''''    #'''''    $'''''    %'''''    &'''(''XXzXXXX|XXTXX,XXXpXXXXXXXXnXXFXXXXX Xt X X Xp Xv X XN X X& X X X X **2@}UdXXXX 77P@Ud+;(,,--..//XX2X8X>HH2 @_g*g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g* (@'A'1'+'!'''''''''g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' g*6'<( (@'A'1'+''!''' ?(''''''%'S'"'' g*6'<( (@'A'1'+''!''' ?(''''''%'S'"''+g*6'<( (@'A'1'+''!'''?(''''''%'S'"''g*6'<( (@'A'1'+''!''' ?(''''''%'S'"''g*6'<( (@'A'1'+''!'''?(''''''%'S'"''+'+'+'XXXXRXXTXXX(XX`XXX4XXlX X X X X X X ff@eQQVV&IIQQVVIIJJKKL(MMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]IIJJKKL(MMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]IIJJKKL(MMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]IIJJKKL(MMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]II IIJJKKL(MMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]] IIJJKKL(MMNNOOPPQQRRSS TTUUVVWWXXYYZZ[[\\]] IIJJKKL(MMNNOOPPQQRRSS TTUUVVWWXXYYZZ[[\\]] IIJJKKL(MMNNOOPPQQRRSS TTUUVVWWXXYYZZ[[\\]] IIJJKKL(MMNNOOPPQQRRSS TTUUVVWWXXYYZZ[[\\]]IIJJKKL(MMNNOOPPQQRRSS TTUUVVWWXXYYZZ[[\\]]QQVVQQVVQQVVXX X&X>XXFXXNXZX`XXhXXpXXxXXXXzz@f gghhiijjkkllmmnnooppqq gghhiijjkkllmmnnooppqqXXVB@-gXX&B!q1Qg}..../=/_/u///// 0050K0a0w0000001%1D1p1111122,2B2X2n222393[3}3333 4w44445"5A5`55555566.6D6Z66666 7.7P7z777788.8D8Z8p88888"989N9d9z9:DRLRR\bc P#iEditEngineItemPool i6f* 0vg*,@+n ",StarBatsN-",StarBatsN-",StarBatsN-"` ` ,StarBatsN-" ,StarBatsN-",StarBatsN-"hh,StarBatsN-",StarBatsN-",StarBatsN-"pp,StarBatsN-X6'@Jn X@jn X!@n dddX<(@n X (T@ruStarBats!"-StarBats!"-StarBats!"-StarBats!"-StarBats!"-StarBats!"-StarBats!"-StarBats!"-oStarBats!"- StarBats!"- 1StarBats!"- StarBats!"- StarBats!"- StarBats!"-UStarBats!"-StarBats!"-StarBats!"-StarBats!"-XXGXXXX+XdXXXXHXXXX,XeXX@'!@Ds dddXA'@js ddX1'@s dX+'@stXX' @ 8tEn. n. n. n. n. rn. 1n. Tn. XXXX+X7XCXOX[Xg!'@~t X'2@t timesCtimesXX' z@&u@d o2d bd  hd 0d d d :d XXX"X,X6X@XJXT?(@du dX'@u XX'@u 5XX'@u X'@u X'@v X'@0v X%'@Qv dXS'@pv X"'@v X'@v XFe2 _ s ]  , K l Pj|g* ",StarBatsN-",StarBatsN-",StarBatsN-"` ` ,StarBatsN-" ,StarBatsN-",StarBatsN-"hh,StarBatsN-",StarBatsN-",StarBatsN-"pp,StarBatsN-6'ddd<( (StarBats!"-@'dddA'dd1'd+''!''times'd ?(d''''''%'dS'"''.5=RZ &-4=DLDrMdNNJoeMn0.1Ű/10/1  DrLyHellDrLyHeavenDrLyControlsDrPg/NMJoeM. DrML DrObSVDr&8 %M @ > UDrObSVDr&8 M @ > (0; *dD iD iV@ V@ DrCn#DrCn$;PFZDrObSVDr& D H @ > n`DDrObkSVDr& D H @ > " D H DrObSVDr&U ]E G @ > # U ]E G }xV4B1f8051g*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  Simulatorg*6'<( (@'A'1'+''!''' ?(''''''%'S'"'' DrXXDrObSVDr&? :@ @ > ^oDrOb SVDr&? :@ @ > oDrObqSVDr&? :@ @ > "? :@ DrObkSVDr&? @ @ > "? @ DrObqSVDr&? @ @ > "? @ DrObkSVDr&? @ @ > "? @ DrXXDrOb:SVDr&? &@ @ > #? &@ xV4B1 UNIX Pipeg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&> A @ >  (4; W@ 3W@ DrObkSVDr&> CB @ > $> CB DrObkSVDr&> s? @ > $> s? DrObSVDr&vd> ? @ > !n< o< D> s? DrObSVDr&? @ @ > "(n0= F@ ~ @ DrObSVDr&@ A @ > "(n= F@ ~ @ DrObSVDr&@ A @ > "(nP> F#A ~ #A DrObSVDr&4A 2B @ > "(n> FA ~ A DrObkSVDr&TC> ? @ > #%T ? k? DrObSVDr&%:= i kC @ > $(0; :V@ TO@ DrCn#DrCn#;DrOb5SVDr&!? "AA @ > %# !? "AA xV4B1Fileg*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  DrObqSVDr&BE mG @ > &"IE fG DrOb<SVDr&!F %QG @ > %# !F %QG xV4B1 Serial portg*6'<( (@'A'1'+''!''' ?(''''''%'S'"'' DrObSVDr&C ^"I @ > $(0; IF F DrCn$DrCn$;PFDrObSVDr&%A= ^"I @ > $(0; :V@ IF DrCn$DrCn$;PFDrXXDrOb SVDr& %d@  aDrObkSVDr&Zl@  ZlDrOb@SVDr&s%@ !s%xV4B1Stream of bytesg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb:SVDr& s@ ! sxV4B1 Sent datag*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb@SVDr&."@ !."xV4B1Data to be sentg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&@ h][DrObSVDr&@ h]lblDrObSVDr&e@ kDrObSVDr&e @ kDrObSVDr&6@ hxxDrObSVDr&&-@ !&-xV4B1mWindowg*6'<( (@'A'1'+''!'''?(''''''%'S'"''(16 bytes max)g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& @ hDrOb@SVDr&Ud@ !UdxV4B1Window movementg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrOb$SVDr&h V&S@ #3DrObSVDr&h S@ stDrObSVDr&V&S@ stDrOb7SVDr&z&@  z&xV4B1Clientg*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  DrOb7SVDr&o@  oxV4B1Serverg*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  DrObSVDr&t V&=@ stDrObSVDr&t +V&@ {DrObSVDr&t V&@ >?0KDrObSVDr&t @ stDrObSVDr&@ 3DrObSVDr&[@ stDrObSVDr&@@ stM5DrObSVDr&@ st(5NDrObSVDr&B[@ st5DrObSVDr&@ stN5jDrObSVDr&]w@ st5DrObSVDr&B@ st55DrXXDrObSVDr&7!w@ st5yDrObSVDr&E";@ stDrObSVDr&t %V&@ uDrObSVDr&t V&@ -.6]DrObSVDr&t V&;@ -.ɻDrObSVDr&t )V&@ -.yDrOb6SVDr&<A8@  ?A2bxV4B1SYN Ag*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb?SVDr&'@  'xV4B1SYN B, ACK A+1g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb8SVDr&@  xV4B1SYN B+1g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb5SVDr&U@  UxV4B1Datag*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb4SVDr&@  xV4B1ACKg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb6SVDr& @   xV4B1FIN Hg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb8SVDr&i@  ixV4B1ACK H+1g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb6SVDr&&iZ@  &iZxV4B1FIN Ig*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb8SVDr&@  xV4B1ACK I+1g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb9SVDr& P@  PxV4B1SYN_SENTg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb9SVDr&e`U#o@ e`U#oxV4B1SYN_RCVDg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb<SVDr&X'$6@ X'$6xV4B1 ESTABLISHEDg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb:SVDr&j V@ j VxV4B1 FIN_WAIT1g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb:SVDr&j NV]@ j NV]xV4B1 FIN_WAIT2g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb:SVDr&# &`5@ # &`5xV4B1 TIME_WAITg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb;SVDr&pZ$@ pZ$xV4B1 CLOSE_WAITg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb9SVDr&eW#t@ eW#txV4B1LAST_ACKg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb7SVDr&p*"9@ p*"9xV4B1CLOSEDg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb7SVDr&e!(@ e!(xV4B1LISTENg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrOb:SVDr& i&@ 6j95?DrObkSVDr& Kj#΀@ 6j  Kj#΀DrObSVDr& u$v@ 6j!wk u#uDrObSVDr&gou@ 6jwkxkQoWvuDrObGSVDr&vww@ 6j vwwxV4B132 bit Sequence numberg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& K @ 6j ukvk ʀ kDrObSVDr& $@ 6j!uk k#kDrObSVDr&#g$@ 6j kk##kDrOb5SVDr&@ 6j xV4B1Datag*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrObJSVDr&s?t@ 6j s?txV4B116 bit Source port numberg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrObOSVDr&sw"t@ 6j sw"txV4B116 bit Destination port numberg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& >r$r<%DrObSVDr&%@ 89K$DrOb5SVDr&!#3@  !#3xV4B1Timeg*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  DrObSVDr& !F@   !FzxV4B1cSerialg*6'<( (@'A'1'+''!''' ?(''''''%'S'"'' Datag*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  DrOb4SVDr& M@   MxV4B1RENg*6'<( (@'A'1'+''!''' ?(''''''%'S'"''  DrXXDrOb SVDr&V {'$0@ 'k QDrObkSVDr& '\$-@ ' '\$-DrObSVDr&W B*$@+@ 'Di4  *\$*DrObSVDr&{'@+@ '4 5 z'z*DrObSVDr&{'.@ '4 5 '-DrObFSVDr&|+@,@ ' |+@,xV4B116 bit Identificationg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObGSVDr&(")@ ' (")xV4B116 bit Header Checksumg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&V $-$0@ 'DrObSVDr&V $-U0@ ' 45 - m0DrObSVDr&c /$0@ 'DiA u0i$u0DrObSVDr&#*-$0@ ' \$-^$t0DrOb5SVDr&d./@ ' d./xV4B1Datag*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrOb:SVDr&(V)@ ' (V)xV4B1 ICMP Typeg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb:SVDr&()@ ' ()xV4B1 ICMP Codeg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb@SVDr&+C!,@ ' +C!,xV4B1Sequence Numberg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr& %g@ ,!DrObkSVDr&8$H@ ,8$HDrObSVDr&Oo@ , Oo|xV4B1e4 bitg*6'<( (@'A'1'+''!'''?(''''''%'S'"''versiong*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& %~@ ,qja&$DrObSVDr&US~@ ,a&b'8DrObSVDr&Y-E@ , JY-E+xV4B14 bitg*6'<( (@'A'1'+''!'''?(''''''%'S'"''headerg*6'<( (@'A'1'+''!'''?(''''''%'S'"''lengthg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&(&~@ ,a&b'8DrObSVDr&#@ ,a&b'484DrObSVDr&Bn@ , BnxV4B1s 8 bit Type Ofg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' Service (TOS)g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&!@ , !xV4B1v16 bit Total Lengthg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' (in bytes)g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& S%Q@ ,qja&Ҹ$ҸDrObFSVDr&lڷ@ , lڷxV4B116 bit Identificationg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&lyZ@ , lyZzxV4B1c3 bitg*6'<( (@'A'1'+''!'''?(''''''%'S'"''Flagsg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&Q@ ,a&b'vvҸDrObGSVDr&޶.#Ϸ@ , ޶.#ϷxV4B113 bit Fragment offsetg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& %%#@ ,qja&$DrObSVDr&(S&#@ ,a&b'ҸDrObSVDr&W8@ , W8xV4B1p 8 bit Time Tog*6'<( (@'A'1'+''!'''?(''''''%'S'"'' Live (TTL)g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb?SVDr&cƹU@ , cƹUxV4B18 bit Protocolg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObGSVDr&?ƹa"@ , ?ƹa"xV4B116 bit Header Checksumg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& %@ ,qja&$DrObISVDr&@ , xV4B132 bit Source IP addressg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObNSVDr&!kU\@ , !kU\xV4B132 bit destination IP addressg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr& a@ , a&b'HDrObSVDr&$%g@ , +,$N$DrObSVDr& c%a@ ,qja&$DrObSVDr& %@ ,qjqS$DrObDSVDr&_P@ , _PxV4B1IP options (If any)g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb5SVDr&l@ , lxV4B1Datag*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&I"1b@ HDrObSVDr&|LQP@ HWuIAMPDrCn$DrCn$;xi(#DrObSVDr&N"1b@ H WuEDY(VDrCn$DrCn#;(#DrObSVDr&_ P R@ H/DrObkSVDr&_ P R@ H _ P RDrOb3SVDr&yPYQ@ H yPYQxV4B1 Input FIFOg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&PR@ HDrObkSVDr&PR@ H PRDrOb4SVDr&jPQQ@ H jPQQxV4B1 Output FIFOg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&Yz]@ HCDrObkSVDr&Yz]@ H Yz]DrOb2SVDr&T[c\@ H T[c\xV4B1 8051 UARTg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&OA;W@ H Wu/H0*U. RDrCn#DrCn$;xiDrObSVDr&O;W@ H Wu/HR*UDrCn$DrCn#;xiDrObSVDr&dZ= ]@ H WuTK[[DrCn#DrCn#;DrObkSVDr&`IM@ H `IMDrObSVDr&LP@ H WuTK. PMDrCn$DrCn$;(#xiDrOb5SVDr&^iJxK@ H ^iJxKxV4B1 Main Programg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&cZ4]@ H cZ4]ixV4B1RSerialg*6'<( (@'A'1'+''!'''?(''''''%'S'"''I/Og*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&_+UV@ HDrObkSVDr&_+UV@ H _+UVDrOb8SVDr&uUV@ H uUVxV4B1SLIP Translatorg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&3T[@ H WuEVDYDrCn#DrCn$;(#DrXXDrObJSVDr&=+%3@ *gDrObkSVDr&,B!-@ *,B!-DrObkSVDr&=0%"2@ *=0%"2DrObSVDr&lF0j2@ *:';'(#!20DrOb+SVDr&{01@ *{01xV4B1C0g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&?,2@ *gDrObSVDr&?,=2@ *&&,2DrObSVDr&,/@ *&&q,q.DrObSVDr&F02@ *:';'q0q!2DrObSVDr&/2@ *&&60!2DrObSVDr&.0@ *&&Kq.60DrXXDrObSVDr&$,2@ *LDrObSVDr&$,"2@ *&&,2DrObSVDr&,/@ *&&V,V.DrObSVDr&E02@ *8'9'V0V 2DrObSVDr&/2@ *&&40 2DrObSVDr&.0@ *&&QV.40DrXXDrObSVDr&#F0$2@ *&&$0$"2DrOb+SVDr&W$0o%1@ *W$0o%1xV4B1C0g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&0B1@ *0B1xV4B1DBg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&01@ *01xV4B1DBg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&,#-@ *,#-xV4B1DBg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&01@ *01xV4B1DDg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&02@ *02xV4B1DCg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&,-@ *,-xV4B1C0g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&+!,@ *v&,B!,DrOb4SVDr&+\,@ *+\,xV4B1 IP Datagramg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb4SVDr&23@ *23xV4B1 SLIP Packetg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrOb SVDr&)Sg be@ ^YX zDrObqSVDr&:z[Rd@ ^YRz[j%dxiDrObqSVDr&]c@ ^Y] c|iDrObSVDr&&^n_@ ^Y)JrE?!_r^DrObSVDr& b>d@ ^Y)Jrb(cDrObSVDr&b1d@ ^Y)JrbwcDrObSVDr&--^_@ ^Y)Jr%_^DrObSVDr&)S" be@ ^Y)Jry[]DrOb4SVDr&[g \@ ^Y[g \xV4B1 Buffer Headg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb4SVDr&Z#![@ ^YZ#![xV4B1 Buffer Tailg*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&X[$w_@ ^YZN[N\^DrObSVDr&Y\^@ ^YZN[N[M\DrObySVDr&f\Jc@ ^Y^ by*DrOb+SVDr&`a@ ^Y`axV4B101g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&\]@ ^Y\]xV4B100g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&EcqTd@ ^YEcqTdxV4B102g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&`a@ ^Y`axV4B103g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrOb+SVDr&1q\#]@ ^Y1q\#]xV4B104g*6'<( (@'A'1'+''!'''?(''''''%'S'"'' DrXXDrObOSVDr& b$@ }EDrObSVDr&&@ u}EDrObqSVDr&&@ &DrObSVDr&T{@  T{~xV4B1gCircularg*6'<( ( @'A'1'+''!'''?(''''''%'S'"''Bufferg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrXXDrObSVDr&b#@ }EDrObkSVDr&b#@ b#DrOb=SVDr&4@  4xV4B1 Main programg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrXXDrObkSVDr&J#z@ J#zDrObJSVDr& @   xV4B1Interrupt Service Routineg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&(@ ejDrCn#DrCn#;DrObSVDr&<@ jeJDrCn#DrCn#;DrObSVDr&@ eezDrCn#DrCn$;xiDrObSVDr&#@ }EDrObkSVDr&#@ #DrOb>SVDr&@  xV4B1 Hardware UARTg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrXXDrObkSVDr&]$@ ,l$DrObSVDr&$@  $xV4B1i Serial I/Og*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' Moduleg*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrObSVDr&X1@ mDrCn#DrCn$ ;DrOb;SVDr& |@  |xV4B1 Serial I/Og*6'<( ( @'A'1'+''!'''?(''''''%'S'"'' DrXXDrObkSVDr&Gc$}@ 'Gc$}DrObkSVDr&8;wͱ@ '8;wͱDrObkSVDr&!@ '!DrObkSVDr& O a& @  ) O a& DrObkSVDr&ң0*@ +ң0*DrObkSVDr&!*S@ 1+!*SDrXX Controlsgg DrXXMD* !"#$%&'()*+,-./0123456789:;<='P@ d d Bs U d XXX"X,X6' @9X'@XX'@wX+'$@X'(!@:. u . X@'1!@rdrddrXA'2J@;rdrddxddxdxdxdXXX&X27S;"@qXX8S<4@XXX"9S=(@XX('@Q@FUXR'D@eX4y2R0pPn$' '(. . p. @ . . . . . P. . . !. $. `'. 0*. -. /. 2. p5. @8. ;. =. @. 6')^2P  Numbering SymbolsNumbering Symbols Internet link Internet link!''Bullet SymbolsBullet Symbols''Text BoxText Box1@'2A';7S<8S=9S>>@(' OLEOLE;7S<8S=9S>> FormulaFormula@1@'<8S>> GraphicGraphic@;7S<8S=9S>> StandardStandard@HeadingStandard Text body@''2A'DR'  Text bodyStandard Text body@2A' Heading 1Heading Text body@''  Heading 2Heading Text body@' ''  Heading 3Heading Text body@''  Heading 4Heading Text body@' '' Table Contents Text bodyTable Contents@ Table HeadingTable Contents Table Heading@ ''$+'Frame contents Text bodyFrame contents CaptionStandardCaption' '2A'HeaderStandardHeader@('FooterStandardFooter@(' Footer leftStandard Footer left(' Footer rightStandard Footer right('N8|< V%}>vGRF51F BM76(FSDx^WYrF!@@voJHOnʏ;) T.(b^!"Z^V V+y?x^yyQqq/xokz^iź RS5ؾkdi֮{>U0o;\g,R.)^SiQUOVj_vZZjRi6K)`((#mayUE'Z7\C)|`B;kӪ,h;dп|h*༡JRثuC q^:^!v<1yBBTG@ d<2Vj=ęt]z2DMV; \g_%;WlFE_,%nJ0Yz [j] :|цcsQ#MPFXCode@΁D 2=m߽G%8(y>?D >V rdo[1sM̖eƙi)]r,)0؝Zm{ts%kҕr qIuZ=~)q[|1 5d}<M!xg4¡jLǮ<6y85:3YS`)5@T)gg'p?>Vu 甛șp{p:O#6)hLkDH`gSjɔeȏ\oN0 ^4͖F Mܬp?3*ycۗG`2o3SG,5ǒ2V*iVwGYMJikKR ,E_+7%686w޴|Y}=@ ԃ##N U2n_]O*ybN3j8vb`Z/q E3+{}3w =%sp˯[_jjSq{{^M8( هIޡ }j=G;ݫ>@qũ>C У,eFv'x3_ҏ@ 1]nG˧Mn";v7#s n{(/#R:cjsGܱϭ.m5KmZ0CZۭfGʆ!'N83(Lmu% 2fX)ʺ^}_E4b %Oh+'0 h t 99@+M@D@3M@; Tim Hurman Tim Hurman @ޅ)䰱Formula StarMath 5.0SW5HDR.0/1!@ Frameformat ZeichenformatTextformatvorlageStandard Heading Text body  Heading 1  Heading 2  Heading 3  Heading 4Table Contents Table Heading Frame contentsCaptionHeaderFooter Footer left Footer rightNumbering Symbols Internet linkBullet Symbols Text Box OLE Formula GraphicRoot 26 Column 27 Column 28 Column 29 Column 30 Graphic1 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 Object1 49 Object2 50 Object3 51 Object4 52 53 54 55 Table1 56 Table2 57 58 59Standard  Illustration Table TextDrawingY <.Y =.Y >.Y ?.q2x GeneralGeneraldNC#,###.00#,###.00SystemNC #,##0.00 CCC#,##0.00 CCCNC$#,##0.--;[RED]-$#,##0.-- $#,##0.---$#,##0.--REDNC$ MM/DD/YYYYMM/DD/YYYY def/SystemNC%MM/DD/YYMM/DD/YY def/SystemNC&NNNNMMMM DD, YYYYNNNNMMMM  DD, YYYYSystemNC' MMM D, YYMMM D, YY def/SystemNC. [HH]:MM:SS.00 [HH ]:MM:SS .00NC3MM/DD/YYYY HH:MM:SS MM/DD/YYYY HH :MM:SS  NCK MMM D, YYYYMMM D, YYYY def/System     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~NCL MMMM D, YYYYMMMM  D, YYYY def/SystemNCM NN, MMM D, YYNN, MMM D, YY def/SystemNCNNN, MMMM D, YYYYNN, MMMM  D, YYYY def/SystemNCONNNNMMMM D, YYYYNNNNMMMM  D, YYYY def/SystemNCP D. MMM. YYYYD. MMM. YYYYDIN 5008 (EN 28601)NCQ D. MMMM YYYYD. MMMM  YYYYDIN 5008 (EN 28601)NCRMM-DDMM-DDDIN 5008 (EN 28601)NCSYY-MM-DDYY-MM-DDDIN 5008 (EN 28601)NCT YYYY-MM-DDYYYY-MM-DDDIN 5008 (EN 28601)NCUWWWWNC GeneralGeneraldNC #,##0.00#,##0.00SystemNC  #,##0.00 CCC#,##0.00 CCCNC #,##0.--;[RED]-#,##0.-- #,##0.---#,##0.--REDNC  DD/MM/YYYYDD/MM/YYYY def/SystemNC DD/MM/YYDD/MM/YY def/SystemNC  DD MMMM YYYYDD MMMM  YYYYSystemNC D MMM YYD MMM YY def/SystemNC  [HH]:MM:SS.00 [HH ]:MM:SS .00NC DD/MM/YYYY HH:MM:SS DD/MM/YYYY HH :MM:SS  NC  D MMM YYYYD MMM YYYY def/SystemNC  D MMMM YYYYD MMMM  YYYY def/SystemNC  NND MMM YYNND MMM YY def/SystemNC  NND MMMM YYYYNND MMMM  YYYY def/SystemNC NNNND MMMM YYYYNNNND MMMM  YYYY def/SystemNC  D. MMM. YYYYD. MMM. YYYYDIN 5008 (EN 28601)NC  D. MMMM YYYYD. MMMM  YYYYDIN 5008 (EN 28601)NC MM-DDMM-DDDIN 5008 (EN 28601)NC YY-MM-DDYY-MM-DDDIN 5008 (EN 28601)NC  YYYY-MM-DDYYYY-MM-DDDIN 5008 (EN 28601)NC WWWWNCBoeoePp ;;2$:: SAP.AAPdddAPddAPr  HeaderSAPddAPNTSA @l:=SAPAPPNGG> PicEFFFC642S(A `A`A  PA  PAPAPA PA Prz FooterShAPddASPNJTASAd A @A0AP!S\AP.AAPdddAPddAP!ZSW5HDR.0/1C(517e(Build:4163)(SV517)]DAddress bookaddress!@ Frameformat ZeichenformatTextformatvorlageStandard Heading Text body  Heading 1  Heading 2  Heading 3  Heading 4Table Contents Table Heading Frame contentsCaptionHeaderFooter Footer left Footer rightNumbering Symbols Internet linkBullet Symbols Text Box OLE Formula GraphicRoot 26 Column 27 Column 28 Column 29 Column 30 Graphic1 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 Object1 49 Object2 50 Object3 51 Object4 52 53 54 55 Table1 56 Table2 57 58 59Standard  Illustration Table TextDrawingd&1%1 4 5*j standard.dicY <.Y =.Y >.Y ?.6FNT3. DevelopmentT iTThe project was initially divided into eight stages. These stages were designed to create small steps between simple functionality and the complete TCP/IP stack. The steps were:T Tj%Tools acquisition and accustomisationS2APdddA @ 4258571213TbBasic serial input and outputS2APdddA @ 4259521213Te Link Layer (SLIP) implementationS2APdddA @ 4259521213Tf!Network layer (IP) implementationS2APdddA @ 4259521213TXICMP implementationS2APdddA @ 4259521213Ti$Transport Layer (UDP) implementationS2APdddA @ 4259521213Ti$Transport Layer (TCP) implementationS2APdddA @ 4259521213Te Application layer implementationS2APdddA @ 4259521213T iTcXThis report will follow through these stages to show how the TCP/IP stack was developed.T iT5*3.1. Tools acquisition and accustomisationT T The project's requirement to use a single chip microcontroller meant that the range of suitable products available was limited. The microcontroller needed to be relatively cheap, in order that the devices could be produced inexpensively. It was also necessary to have the appropriate development tools available for the operating system being utilised. A hardware simulator was not used due to the difficulty of debugging the software. In addition, a hardware simulator would require a serial port to communicate with the main computer; this would tie up a UART on the microcontroller. Since all standard microcontrollers have one UART, it would have been necessary to add another UART in hardware or simulate one by software, neither of which would have been desirable.T TThe operating system had to be chosen, for which there were two options - Microsoft Windows, or a UNIX variant. There are many more development tools available for Windows, however they lack the ability to control the serial port with precision. It is very difficult to manage the parameters used by the serial port, for instance whether hardware or software flow control is used. In addition, the Windows simulator software which was available did not have the ability to bind to the serial port. Fewer UNIX simulators were obtainable, however they did have several advantages; for example the software could simulate the serial port or bind to the device itself. UNIX allows the user to control the serial port to a much finer degree than Windows. T iTHaving decided to use UNIX for development, this eliminated the majority of the microcontrollers. There were three competitors left.T iT\Intel's 8051 seriesS2AP6dddQA @ 3019550313 T^Motorola's AVR seriesS2AP6dddQA @ 3019550313 TgArizona Microchip's PIC seriesS2AP6dddQA @ 3019550313 T iT0%Of these, Intel's 8051 series has the best support. The devices are available from many manufacturers with various configurations. To design software for these devices, there are a series of development tools for UNIX, all of which are available without cost. Assemblers, a simulator and several C compilers are available for 8051 development. However, it was decided to develop the stack in assembly language as a C compiler would introduce unnecessary bulk into the code. Due to the expected size of the final code, C was considered unacceptable. T iT}Following the decision to use UNIX, the variant had to be determined. There were two options available; Solaris and Linux. Solaris was the primary choice, but SLIP support had vanished in favour of the more popular PPP. Linux, however, contained support for the older SLIP protocol. The chosen development platform was a Dell Optiplex running Linux (Slackware 7.0 release). A null modem cable was installed between the two serial ports of the computer, in order that software could interface with one serial port and believe that is was talking to a real 8051. The 8051 simulator was attached to the second serial port of the computer.T iTTo acquire skills in using the simulator, several pieces of test code were run. It was here that the simulator was shown to be incorrect. Whilst testing the external interrupt sequences, it was found that they were responding to a logic 1 (+5v) instead of a logic 0 (0v). Having examined the code for both the simulator and interrupt sequence, it was decided that the simulator was faulty. Once this was reported to the main developer of the simulator, it was soon fixed, and a new version released. T iTDue to the failure observed in the external interrupt routines, it was decided that testing should be performed on all interrupts and input/output routines. No further failures were found.T iT T;"3.2. Basic serial input and outputSA PT T 3.2.1. DesignT TTo implement the basic serial input and output, there were two possible paths, which would lead to entirely different designs later in the project.T iT The first option was the polling Input/Output (I/O) model, in which the microcontroller performs busy-waiting on the serial register for each byte of data the device receives. However the serial register only provides single-byte buffering. This means that if the device was late to copy the data out of the serial port register, it might be overwritten by the next piece of data arriving at the device. This gives rise to the opportunity for data loss, a prospect that would have very extreme consequences. There is also cause for concern when the efficiency is considered. Due to the busy-waiting, the device may not perform any other operation, therefore wasting many thousands of instruction cycles per second. However this form of I/O is very simple to implement and debug.T iTC8The second form of I/O is interrupt-driven I/O. This involves a separate Interrupt Service Routine (ISR), that is called whenever a byte of data finishes being sent or received by the device. The interrupt suspends the code that is currently running. Interrupts also start to introduce the concept of a multitasking system, as different sections of code can interrupt each other. This system is much more complex as it requires a buffer. The buffer cannot be interrupted, and therefore needs to perform mutual exclusion. This effect can be produced by momentarily disabling interrupts, and forcing them to wait in a queue. When the interrupts are re-enabled, if any have been queued, they will be called in order of priority. There are five interrupts in the 8051 series. These are listed below descending order of priority.T iT]External interrupt 0S2AP6dddQA @ 3119430313 TYTimer 0 overflowS2AP6dddQA @ 3119430313 T]External interrupt 1S2AP6dddQA @ 3119430313 TYTimer 1 overflowS2AP6dddQA @ 3119430313 T>Serial register activity (the completion of a send or receive)S2AP6dddQA @ 3119430313 T iTWhen a serial register interrupt occurs, the microcontroller sets at least one of the two flags. These flags are called Transmit Interrupt (TI) and Receive Interrupt (RI) and denote a send or receive respectively.T iTXMWhen data is received via this method, it must be processed at a steady rate in order to avoid the buffer overflowing. The buffer can only be a limited size due to memory restrictions within the microcontroller. The 8051 series is only available with a maximum of 256 bytes of internal RAM, in addition to 8192 bytes of internal ROM.T Ti^The interrupt mechanism is more reliable than polled I/O and gives the opportunity to access many performance enhancements. The main program will be told when there is data available, therefore the device may continue executing if there is no dependency on the incoming data. However, this method is significantly more complex to implement and debug.T iT 3.2.2. ImplementationT T 3.2.2.1 OverviewT[PAfter assessing both possibilities, it was decided to implement interrupt driven I/O, since this would provide a firm communications base for the TCP/IP stack. This has the added advantage of removing all I/O dependencies from higher layers, providing a simpler development scheme and separating the distinct layers in the TCP/IP stack.T TThe basic serial I/O was grouped together, providing an Application Programming Interface (API) with which the main program could communicate (Figure. 3.2.1). The main program and the serial I/O module are viewed as threads of execution that are running in parallel. The main program is running constantly, but the Serial I/O modules may interrupt it when data has to be sent or received.A8 A8 TSA  TL(Figure 3.2.1. Interrupt Driven I/O modelSA  A @T@o5: S&A  PA  PA PT iT  T% 3.2.2.2. Interrupt HandlerT TWhen the 8051 finishes sending or receiving a byte of data, the TI or RI flags are set respectively. This, in turn, causes the microcontroller's Program Counter (PC) register to be immediately reloaded with the address of the ISR. In the case of the 8051, this address is 0x0023h. The microcontroller then starts executing instructions from this point onwards. At this point it is possible to check whether a transmit or receive has occurred by checking the status of the two flags. Depending upon which flag was set, it is possible to call the appropriate buffer access routine, described below, and move data between the main program and the serial UART.T TWhen receiving data, the microcontroller prompts the interrupt handler to place data into the receive buffer. However, when transmitting, the microcontroller needs a 'push' to start sending the data. To this end, an extra flag is used to signify when the software can push the transmit interrupt handler into sending data. This flag is called SENDOK, and is initially set to one. When data is placed into the transmit buffer, the buffer checks this flag; if it contains a logical one, the software may set the TI bit to indicate that a transmit interrupt should occur. Whenever a transmit interrupt occurs, there are two choices possible. Firstly, if there is data in the buffer, the ISR may send the next byte of data, returning SENDOK back to a logical zero. If there is no available data, SENDOK may be placed at a logical one, so that when a byte of data is next placed into the transmit buffer, the transmit interrupt may be pushed into sending data again.T iT! 3.2.2.3. Buffer designT Tf[The buffer design is circular, in order to contain the memory used by the buffer into a small area. Each buffer can be viewed as an individual First In First Out (FIFO) buffer. There are two buffers in total, one for data that is destined for transmission and the other containing data that has been received. Each buffer has two flags and two control bytes associated with it. The two flags maintain the extreme states of the buffer, when it is full and empty, by doing this only one flag will ever be active. The two control bytes maintain the current positions of the head and tail within the buffer.T iTIn this design, data is always placed onto the head of the queue and taken from the tail. The head pointer always points to a currently free location, which may be the tail of the queue, indicating that the buffer is full. The tail pointer always indicates the next piece of data to read; if this is the head of the queue, then the buffer is considered empty. Figure. 3.2.2 shows the buffer in this state.A8 huTR$Figure 3.2.2. Circular buffer designS#A PA  A @T@o5: S&A  PA  PA PT}rBoth buffers are five bytes long. When accounting for the control bytes, the amount of memory used for each buffer is 8 bytes. Additionally two one bit flags are also needed for each buffer, which indicate whether the buffer is either empty or full. Four constants are used to indicate the start and end of each buffer, however these do not require any execution memory.T iTThere are two access routines associated with each buffer, a buffer put and a buffer get method. In the main program listing these are called:T Tx!TxBPS (Transmit Buffer Put Start)S2AP6dddQA @ 333717031A8 !3 Tx!TxBGS (Transmit Buffer Get Start)S2AP6dddQA @ 333717031A8 3 Ti RxBPS (Receive Buffer Put Start)S2AP6dddQA @ 3337170313 Ti RxBGS (Receive Buffer Get Start)S2AP6dddQA @ 3337170313 T iT}The functions TxBGS and RxBPS, do not need to disable interrupts. This is because they can only be called from within an interrupt handler. Also, in addition, the 8051 is unable to preempt if the current instruction is in an interrupt handler of the same or greater priority. Therefore a transmit interrupt can never pre-empt a receive interrupt since they have the same priority. A8 }T iTC*The other two functions TxBPS and RxBGS, need to disable all interrupts during their execution. If not, and an interrupt occurred, the buffer would be in an undetermined state after the function call. All four functions take and return their arguments and results, respectively, in the accumulator.A8 *TSA  TSA  T{The two receive buffer routines also provide flow control for the microcontroller. A special function register within the microcontroller can enable and disable the serial receiver, this is called REN. However this will only work in the simulator which provides input buffering. In reality, the two external interrupts would need to function as a hardware flow control interface.SA  TSA  TSA  TqThe basic logic of the four functions are shown in Listing 3.2.1, these are shown in pseudo-C fragments for ease.SA  A8 3@TSA  TSA  TSA  TI%Listing 3.2.1. Buffer access routinesSA  A @TNSA  o5:!S&A  PA  PA PI Buffer AccesssR9SGA PA  PA/Pdu :;N1fTMTransmit sectionS2AtimesAd A  T5S*AcourierAd TG#define Start 0x00S*AcourierAd TE#define End 0x06S*AcourierAd TU unsigned char *Data_Head = 0x00;S*AcourierAd TU unsigned char *Data_Tail = 0x00;S*AcourierAd TNFlag TxB_FULL, TxB_EMPTY;S*AcourierAd T5S*AcourierAd T5S*AcourierAd TG/* Transmit PUT */S*AcourierAd TNvoid Put(unsigned char a)S*AcourierAd T6{S*AcourierAd TF while(TxB_FULL);S*AcourierAd T5S*AcourierAd TJ S*AcourierAd T6 S*AcourierAd TE *Data_Head = a;S*AcourierAd TB Data_Head++;S*AcourierAd T6 S*AcourierAd TJ if(Data_Head == End)S*AcourierAd TI Data_Head = Start;S*AcourierAd T5S*AcourierAd TP if(Data_Head == Data_Tail)S*AcourierAd TD TxB_FULL = 1;S*AcourierAd T5S*AcourierAd TE if(SENDOK == 1)S*AcourierAd T> TI = 1;S*AcourierAd T5S*AcourierAd TL S*AcourierAd T6}S*AcourierAd T5S*AcourierAd T5S*AcourierAd T5S*AcourierAd TG/* Transmit GET */S*AcourierAd TLunsigned char Get(void)S*AcourierAd T6{S*AcourierAd TF unsigned char a;S*AcourierAd T6 S*AcourierAd TI a = *Data_Tail;A8d A8courierTB Data_Tail++;S*AcourierAd T TJ if(Data_Tail == End)S*AcourierAd TI Data_Tail = Start;S*AcourierAd T TP if(Data_Head == Data_Tail)S*AcourierAd TE TxB_EMPTY = 1;S*AcourierAd T5S*AcourierAd T@ return(a);S*AcourierAd T6}S*AcourierAd T5S*AcourierAd T5S*AcourierAd TVReceive SectionS<A PAtimesAd A  T5S*AcourierAd TG#define Start 0x00S*AcourierAd TE#define End 0x06S*AcourierAd TU unsigned char *Data_Head = 0x00;S*AcourierAd TU unsigned char *Data_Tail = 0x00;S*AcourierAd TNFlag RxB_FULL, RxB_EMPTY;S*AcourierAd T5S*AcourierAd T5S*AcourierAd TF/* Receive Put */S*AcourierAd TNvoid Put(unsigned char a)S*AcourierAd T6{S*AcourierAd TG if(RxB_FULL == 1)S*AcourierAd T> return;S*AcourierAd T5S*AcourierAd TE *Data_Head = a;S*AcourierAd TB Data_Head++;S*AcourierAd T6 S*AcourierAd TJ if(Data_Head == End)S*AcourierAd TI Data_Head = Start;S*AcourierAd T5S*AcourierAd TQ if(Data_Head == Data_Tail){S*AcourierAd TD RxB_FULL = 1;S*AcourierAd TC REN = 0;A8 d A8 courierT7 }S*AcourierAd T6}S*AcourierAd T5S*AcourierAd T T5S*AcourierAd TF/* Receive GET */S*AcourierAd TLunsigned char Get(void)S*AcourierAd T6{S*AcourierAd TF unsigned char a;S*AcourierAd T6 S*AcourierAd TG while(RxB_EMPTY);S*AcourierAd T5S*AcourierAd TJ S*AcourierAd T: A8d A8courierTE a = *Data_Tail;S*AcourierAd TB Data_Tail++;S*AcourierAd T TJ if(Data_Tail == End)S*AcourierAd TI Data_Tail = Start;S*AcourierAd T5S*AcourierAd TP if(Data_Head == Data_Tail)S*AcourierAd TE TxB_EMPTY = 1;S*AcourierAd T5S*AcourierAd T> REN = 1;S*AcourierAd TL S*AcourierAd T@ return(a);S*AcourierAd T:}A8d A8courierT iT*3.2.3. DiscussionSA PT iTFor the purpose of testing the buffer, the main program consisted of a simple loop. This listened for incoming data and then immediately echoed it back down the serial line. On the UNIX side of the SLIP line, a small program was written, simulating the UNIX talk command interface. The source code for this application can be found in the appendix, under 'serialview'. This enabled typing at a sufficiently high rate to test the returned results. As predicated, the result was an exact match, thus proving that the buffer was indeed working as intended. The source code for serialview was donated to the open source community and has been integrated into the simulator.T iT{A small lag time was noticed between a character being sent and received. This can be attributed to one of several reasons.T iTThe line speed of the serial port was only 9600 baud. It is possible to notice a lag with such a slow rate, even when using PPP over a phone line.S2AP6dddQA @ 3500070313 T7The 8051 simulator is a non-real-time simulator, this means that the instructions are executed at a much slower rate then they would be in hardware. There would be some delay as the simulator does not respond properly to the serial input.S2AP6dddQA @ 3500070313 TThe Linux serial device drivers may not be responding to the input at the precise moment it is received. This is due to the large buffers contained within the computer's UART.S2AP6dddQA @ 3500070313 T iT0%3.3. Link Layer (SLIP) implementationT T 3.3.1. DesignT TThe link layer provides the translation between the network (IP) layer and the actual hardware used to transmit the data across the network. It provides the framing around the IP packet and possibly provides basic error detection/correction. In the case of SLIP, a very simple translation occurs to provide start and end of frame markers. Certain bytes with the packet will also be translated (Table 3.3.1), as they would otherwise match the frame delimiters. The SLIP protocol defines two special bytes, 0xC0, the SLIP END character, and 0xDB, the SLIP ESC character. The two characters 0xDC and 0xDD indicate which special character has been escaped. This can be show diagrammatically, as in Figure 3.3.1 belowA8 A8 T iTL(Table 3.3.1. SLIP translation charactersSA  A @E#fK7S@APAPdddAPLBfSA PtfxSoAPAPA9P7N0T' Original ByteSA @tfS~AP%APAHP7N2T)Translated ByteSA @Ldth@fKSBAPA*P7NT0xC0t|@fZSQAP%A9P7NT 0xDB,0xDCLLdtbNT0xDBt$bNT 0xDB,0xDDT T-S"APT Tp2Figure 3.3.1 IP datagram SLIP packet translationSA  A @A8 symbolT@o5:" S&A  PA  PA PT T5*Entire packets are separated by pairs of the SLIP end delimiter, 0xC0. This provides the receiver with error control. If one of the characters within the packet is corrupted to become 0xC0, the SLIP layer knows that the next byte to be received should be 0xC0; if not, there has been an error. The receiver can then discard the packet and wait for the next sequence of two consecutive 0xC0 characters to re-synchronise with the sender. The SLIP protocol provides no way to detect errors in the packet, as it does not contain a checksum or CRC for checks.T iTThe simplicity of the SLIP protocol makes it ideal for use in this project, as packaging the IP packet for transmission is not computationally intensive. SLIP also allows transmission without the entire IP packet being buffered in memory beforehand. T iT 3.3.2. ImplementationT T There are two potential methods by which to implement SLIP translation between the hardware and the IP layer. Firstly the SLIP interface could be integrated into the interrupt routines, providing the program side of the buffer with a purely IP interface. Alternatively, the SLIP translation could also occur in the program side buffer interface. In this way the buffers would contain the SLIP data needed for a direct send and receive. In addition no extra processing is required in the interrupt service routines.TRGIt was decided to place the SLIP translation code into the interrupt routines. This has the disadvantage of requiring extra processing time and complicating the interrupt service routines. However it does free up much needed space in the buffers. As the buffers are only five bytes in length, the minimum space a SLIP packet would need is two bytes more than the raw IP packet. However the buffer space required may be much more depending on the contents of the IP packet. This method has the added advantage of providing a transparent link layer, thus simplifying the network layer.T iT`UTo implement this several flags are needed to store the state between incoming bytes.T TPKTRECV. This indicates a logical one when an IP packet is being received, this includes all data between the two SLIP END characters.S2AP6dddQA @ 2004050413 TSLIPESC_R. This is set to a logical one when a SLIP ESC character is received and cleared when the next byte is received and interpreted.S2AP6dddQA @ 2004050413 TSLSEND1. This is the first flag which stores the state of an outgoing packet, so that the SLIP translation knows when to send the final 0xC0 character.S2AP6dddQA @ 2004050413 TESLSEND2. This is the other half of the outgoing packet state monitor.S2AP6dddQA @ 2004050413 T iTuNThe serial transmit interrupt handler is required to store complex state information. There are four states that indicate which action to take shown in Table 3.3.2. From Table 3.3.2 it can be seen that there continues to be an interaction between the network layer and the link layer. However without giving the link layer knowledge of IP, or extra memory, this is unavoidable. This mechanism also provides a synchronisation between the network and link layers, because before processing the next packet, the network layer is forced wait until the current packet has been fully transmitted.A8 A8 T T$SA  A @TY5Table 3.3.2. Serial transmit interrupt handler statesSA  A @E #fK8S@APt APdddAPLTBfSA PtfxSoAP APA9P7N9T0 SLSEND1 stateSA  A tfxSoAP APA9P7N9T0 SLSEND2 stateSA  A tfS~AP APAHP7N>T5 Transmission stateSA  A LdtfySpAP A*P7APA`A`N$T 0SA @tfySpAP A*P7APA`A`N$T 0SA @t@fZSQAP A9P7NBT9 .Nothing sent, send 0xC0, and move to state 1,0LdtfySpAP A*P7APA`A`?N$T 1SA @tfySpAP A*P7APA`A`N$T 0SA @tvbNoTf [Normal packet transmission, when the network layer finishes sending data, move to state 1,1LdtfySpAP A*P7APA`A`N$T 0SA @tfySpAP A*P7APA`A`?N$T 1SA @tWbNPTG <Packet send and final 0xC0 character sent, move to state 0,0LdtfySpAP A*P7APA`A`?N$T 1SA @tfySpAP A*P7APA`A`?N$T 1SA @tMbNFT= 2Packet over, send final 0xC0 and move to state 0,1T TRGThe link layer states may seem to have a strange ordering. They are organised to use the least number of instructions when moving between states, and performing checks on the correct state. Only two checks are needed to ascertain the current state. This can be seen in the assembler listing of the TCP/IP stack in the appendix.T iTnThe program code in Listing 3.3.1 shows the pseudo-C for the interrupt handler, with SLIP processing included.A8 !T TSA  TL(Listing 3.3.1. Serial interrupt handlersSA  A @TYSA  A @o5:#S&A  PA  PA PIInterrupt HandlerssR:SGA PA  PA/Pdu :;NgTT/* Receive interrupt handler */S*AcourierAd TGvoid Receive(void)S*AcourierAd T6{S*AcourierAd TF unsigned char a;S*AcourierAd T= RI = 0;S*AcourierAd T6 S*AcourierAd TT/* copy data from serial SFR */S*AcourierAd T@ a = *SBUF;S*AcourierAd T5S*AcourierAd TP /* receiving a packet ? */S*AcourierAd TH if(PKTRECV != 1) {S*AcourierAd TD if(a == 0xC0)S*AcourierAd TD PCKRECV = 1;S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd TT /* was the last char a ESC? */S*AcourierAd TJ if(SLIPESC_R == 1) {S*AcourierAd TD if(a == 0xDC)S*AcourierAd TA a = 0xC0;S*AcourierAd T< else S*AcourierAd TA a = 0xDB;S*AcourierAd T5S*AcourierAd TE SLIPESC_R = 0;S*AcourierAd T@ RxBPS(a);S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd TS /* receiving and ESC char? */S*AcourierAd TE if(a == 0xDB) {S*AcourierAd TE SLIPESC_R = 1;S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd TP /* was it an 0xC0 char? */S*AcourierAd TE if(a == 0xC0) {S*AcourierAd TG if(PKTRECV == 1)S*AcourierAd TD PKTRECV = 0;S*AcourierAd T; elseS*AcourierAd TD PKTRECV = 1;S*AcourierAd T5S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd T? RxBPS(a);S*AcourierAd T= return;S*AcourierAd T6}S*AcourierAd T5S*AcourierAd T5S*AcourierAd T_ /* Transmit interrupt handler */S4A PAcourierAd THvoid Transmit(void)S*AcourierAd T6{S*AcourierAd TF unsigned char a;S*AcourierAd T= TI = 0;S*AcourierAd T5S*AcourierAd TE /* state 0,0 */S*AcourierAd TT if((SLSEND1==0)&&(SLSEND2==0))S*AcourierAd T7 {S*AcourierAd TD *SBUF = 0xC0;S*AcourierAd TC SLSEND1 = 1;S*AcourierAd TC SLSEND2 = 0;S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd TE /* state 1,0 */S*AcourierAd TT if((SLSEND1==1)&&(SLSEND2==0))S*AcourierAd T7 {S*AcourierAd TI if(RxB_EMPTY == 1)S*AcourierAd T? return;S*AcourierAd T5S*AcourierAd TQ /* peek at the next byte */S*AcourierAd TM if(RxB_Tail == 0xC0) {S*AcourierAd TD SBUF = 0xDB;S*AcourierAd TH RxB_Tail = 0xDC;S*AcourierAd T? return;S*AcourierAd T8 }S*AcourierAd T7 S*AcourierAd TM if(RxB_Tail == 0xDB) {S*AcourierAd TH SBUF = 0xDB;A8d A8courierTH RxB_Tail = 0xDD;S*AcourierAd T? return;S*AcourierAd T8 }S*AcourierAd T8 S*AcourierAd TC a = TxBGS();S*AcourierAd TA *SBUF = a;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd TE /* state 0,1 */S*AcourierAd TT if((SLSEND1==0)&&(SLSEND2==1))S*AcourierAd T7 {S*AcourierAd TN SLSEND1 = SLSEND1 = 0;S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T5S*AcourierAd TE /* state 1,1 */S*AcourierAd TT if((SLSEND1==1)&&(SLSEND2==1))S*AcourierAd T7 {S*AcourierAd TD *SBUF = 0xC0;S*AcourierAd TC SLSEND1 = 0;S*AcourierAd TC SLSEND2 = 1;S*AcourierAd T> return;S*AcourierAd T7 }S*AcourierAd T8} S*AcourierAd T3.3.3. TestingT TIt was vital to ensure that the SLIP translation was working correctly. If it was not, the remainder of the TCP/IP stack would be affected. The receive translation was implemented first. This was then passed a dummy packet containing both normal data and escaped data. The main program used was the same as before (see section 3.2.3); this allowed the results of the SLIP de-translation to be viewed easily. A program was written to present the results in a readable form. This program took the packet and sent it byte-by-byte to the simulator. After sending each byte, it waited for half a second to see if any data was received. The packet sent consisted of (all values are show in hexadecimal):T TG<Packet sent: C0, 00, 01, DB, DC, 02, 03, DB, DD, 04, 05, C0T;0Expected results: 00, 01, C0, 02, 03, DB, 04, 05T1&Actual results: 00, 01, C0, 02, 04, 05T TThis initially led to a belief that either the SLIP translation or the serial transmission interrupt handler was not functioning correctly. Having fully debugged the SLIP translation and the transmit interrupt handler by interrupting the execution whenever a byte was received to sent, it was concluded that the program code was not at fault. This was proved by observing the offending characters were being sent to the serial port by the SLIP layer.T TPETwo options remained: firstly, the simulator was faulty, and secondly, the serial interface or software on the computer were faulty. To decipher between these, the simulator's serial input was left attached to the serial device on the computer, and the serial output connected to a file. Again, the expected results were seen in the file. This led to the conclusion that the serial communication program or computer hardware to be at fault. It is very unlikely for hardware to fail when used in the correct way, therefore it was decided that the software should be examined first.T TAfter much scrutiny, the problem was found. UNIX uses a POSIX interface to access the serial port. The default parameters of the serial port use software flow when transferring data. It was noted that character 0x03 mapped directly to the XOFF character which disables serial reception in the computer. However, the default settings also let any character be used as the XON command. This meant that the sequence 03, DB, firstly disabled the serial reception and then re-enabled it. To dispose of this problem, software flow control was disabled. The full range of POSIX settings was examined to avoid any other such communication hazards. T TAfter the fix was applied, the test procedure was repeated and a more noticeable lag observed. Due to the simplicity of the receiving SLIP translation, it was decided SLIP could not be the cause of the lag. The lag was even more noticeable at higher data rates, particularly when the time waiting for received serial data, in the test program, was dropped to zero. To examine the lag more closely, it was decided to trace an individual byte through the current design to view what might be delaying the data. By chance, when entering the serial transmit interrupt handler it was noted that both the transmit and receive interrupt flags were active, however the receive ISR had not yet been serviced. When examining the logic, the reason for this was clear. When entering the interrupt handler, the TI and RI flags were checked, however the TI took precedence. Once the transmit ISR had completed, program execution returned from the interrupt handler without servicing RI.T iTThis effect was able to occur as the 8051 microcontroller is a full duplex device. The microcontroller is therefore both send and receive data at the same time, thereby increasing the overall data rate to and from the device. To fix this required that both flags be checked when entering the interrupt handler, and if necessary, executing both send and receive ISRs. Once this was achieved, the lag was minimised.T TThe SLIP transmit translator was ready to be implemented. Once this was carried out, the above series of test were run again and the following results achieved:T TG<Packet sent: C0, 00, 01, DB, DC, 02, 03, DB, DD, 04, 05, C0T;0Expected results: 00, 01, C0, 02, 03, DB, 04, 05T9.Actual results: 00, 01, C0, 02, 03, DB, 04, 05T TThis confirmed that the SLIP translation was functioning correctly and the main program was ready to receive IP awareness. Figure 3.3.2 shows the program structure at this stage.A8 {T iTM)Figure. 4. SLIP translator with bufferingSA  A @T T@o5:$ S&A  PA  PA PT iTSA PT1&3.4. Network layer (IP) implementationT T 3.4.1. DesignT TThe network layer provides an unreliable end-to-end connection between two or more hosts. It is responsible for routing a packet through a network of hosts to its final destination. The IP provides no guarantees that a series of packets will arrive in the correct order, that each packet will take the same route across a network or even that the packets will arrive at the final destination at all. T iTDue to the size and complexity of the IP header, it was necessary to reduce some of the possible configurations and information within the header. A basic IP header is shown in Figure 3.4.1. A8 T iTNCThe diagram shows the twenty bytes which are necessary for the IP header. The IP layer for this microcontroller must store eighteen of these bytes and one bit flag. This allows the IP header to be reconstructed, which is needed when sending an Internet Control Message Protocol (ICMP) error. The two bytes that do not need storing are the Flags and Fragmentation offset fields. This is due to the restrictions placed upon the SLIP interface. Due to the Maximum Transfer Unit (MTU) of the interface, and assumptions made regarding the Transport layer packet, it can be assumed that fragmentation will not be required. However if the packet is fragmented, it is automatically defined the transport layer data as invalid since, as described later, the device only accepts single byte commands. The packet can therefore be safely dropped. T iT*To regenerate a fragmented packet within the device would require more memory than is available from the microcontroller. The IP layer is not required to store the IP checksum, however this is advantageous, as it reduces the amount of processing necessary to send an ICMP error message. T iTSA  TIFigure 3.4.1. The IP headerS#A PA  A @Tp Adapted from RFC 791 (1981)o5:% S&A  PA  PA PA8d T iTICMP has a large quantity of control over the routing and network layer and thus has a close linked relationship with IP. ICMP does not define a complete layer in the TCP/IP protocol stack, moreover it lies between the network and transport layers (see appendix . For simplification, some references (Internetworking with TCP/IP) even refer to ICMP as part of the IP layer, however this is not true.A8 -HT iTThe Type of Service (TOS) options are ignored on the incoming packet due to their meanings. The TOS bits contain options to enable a higher throughput, minimise latency and increase the reliability. Most current TCP/IP stacks ignore these options, however they are used by some applications. This IP layer will ignore the TOS bits, since only one packet can be processed at a time and thus the TOS bits are redundant.T iTodThe IP packet contains many associated options, which allow a number of advanced features of IP to be used. Such options include IP record route, where the specific path an IP packet takes across a network is recorded. There is also a source routing option, that defines the route an IP packet must take to reach its destination. These options are ignored by most TCP/IP stacks as they can cause both network and security problems, such as IP spoofing. This IP layer will ignore these options because they usually refer to machines with multiple interfaces and plenty of memory with which to process the packet.T iT 3.4.2. ImplementationT iT' 3.4.2.1. IP datagram receiveT TThe main testing program used in the previous two sections was removed and replaced by the IP implementation. The IP layer is set to perform busy-waiting on the PCKRECV bit whilst there is no packet being received.T iTOnce a packet starts to be received, the main program executes a completely serial IP interpretation. Initially, this was carried out without any checksum calculation; to avoid complexity during the receive operation.T iT To recognise the end of the header, the IP layer stores the number of 32 bit words in the header-length field. For every four bytes received, this value is decremented by one. This is allowed since the IP header is guaranteed to be an integer number of 32 bit words. T iTOnce all of the 20 required bytes have been read, the IP layer loops whilst reading the remainder of the IP header. This absorbs any options that were transmitted. However these values are discarded instantly and no use is made of them.T iT|The microcontroller was hard-coded with the IP address 10.0.0.2; this can only be changed by re-assembling the program code.T iTIt was more complex to generating the IP header for packets. Due to the arrangement of the IP header, the checksum has to be calculated before any addresses can be sent. This means pre-processing the checksum; and then sending the remaining parts of the header. This is because the IP packet was originally optimised for the Berkeley Software Distribution (BSD) 4.2 which was released in 1983. T iT  T5 3.4.2.2. Checksum generationSA PT iTg\Within the IP header is a 16-bit checksum. This can verify whether any data within the header has been modified in transit. The 8051 family of microcontrollers are only 8-bit orientated. This means that to calculate the checksum, two bytes are needed. The data is then applied alternately to each of these bytes, thus generating a 16-bit checksum.T TWith little information on the subject of computing the checksum, it was decided to produce some test code in C to confirm the algorithm before converting it into assembly language.T T9.The official definition of the IP checksum is:T T"The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header. For purposes of computing the checksum, the value of the checksum field is zero." - RFC 791, Internet Protocol specificationT THowever, no sources of information were found which elaborated on this definition, let alone provide any implementation notes. The first method that was tried was the exclusive-ORing of consecutive bytes. The IP header can be separated into a series of 16 bit values. The first byte of the initial 16-bit value was then EX-ORed with all the first bytes from each 16-bit item. The same method was then applied to the second byte of each 16-bit value. However, this method was proved incorrect. Soon after another RFC came to light: RFC 1071, Computing the Internet Checksum. This showed precise algorithms used in this procedure and provided many examples. This RFC showed that the one's compliment sum was in-fact simple addition, with end-around carry. In other words, when the value being calculated reaches the maximum number available in the number of bits used, the overflow would be added to the least significant byte of the checksum.T TDue to the microcontroller containing 8-bit registers, two overflows are needed to be checked. The following is a simple example of an 8-bit overflow wrap-around.T iT" Binary HexadecimalT 11110011 0xF3T: 00010000 0x10 +A8  A8  T$ 00000001 00000011 0x103T iTWLThe extra value generated by the overflow is then added to the initial byte:T T 00000011 0x01T: 00000001 0x03 +A8  A8  T 0x000100 0x04TAs before, in the 8051 microcontroller two bytes, were used. When one byte generated an overflow, the other byte was incremented by one, thus providing the 16-bit wrap-around.T TQFTwo functions were created to generate the checksum, each one being called alternately. The checksum generation functions were implemented in this way to reduce the number of instructions executed by each function. Checksumming can be achieved in this way because the number of bytes in the IP header is guaranteed to be even.T TThe functions can be used both to generate and calculate the IP header checksum. When calculating the checksum, the transmitted value is added to the checksum. After all the bytes in the IP header, including any options, have been processed in this way, the resultant value of the two bytes will be 0xff, 0xff, for a correct checksum and any other value otherwise. When an incorrect checksum is received, the packet is silently discarded.T TWhen generating the IP checksum, the bytes that should be transmitted as the checksum are omitted. This can be done because RFC 791 states that the values should initially be zero. Adding zero to both bytes of the checksum will have no effect and thus can safely be ignored. Once the checksum has been calculated for all the bytes in the IP header, the checksum is complemented, or inverted, and then sent as the checksum. Listing 3.4.1 shows the correct pseudo-C code.A8 T iTc'Listing 3.4.1. Checksum generation codeS1APdddA  A @TfS&APdddA  o5:&S&A  PA  PA PTv)/* checksum generation and calculation */SBAPEdddEAcourierAd Thunsigned char checkMSB = 0;SBAPEdddEAcourierAd Thunsigned char checkLSB = 0;SBAPEdddEAcourierAd Tdunsigned char wone = 0;SBAPEdddEAcourierAd T'SAPEdddETlvoid checksum(unsigned int val)SBAPEdddEAcourierAd TN{SBAPEdddEAcourierAd Th unsigned int a = 0;SBAPEdddEAcourierAd Td /* MSB first */SBAPEdddEAcourierAd Tb if(wone == 0)SBAPEdddEAcourierAd TV {SBAPEdddEAcourierAd Tf wone = 1;SBAPEdddEAcourierAd Tm checkMSB += val;SBAPEdddEAcourierAd Tw* a = checkMSB & 0xffffff00;SBAPEdddEAcourierAd Ti if(a != 0) {SBAPEdddEAcourierAd T|/ checkMSB &= 0x000000ff;SBAPEdddEAcourierAd Tt' checksum(0x01);SBAPEdddEAcourierAd Tv) wone = 1; /* A */SBAPEdddEAcourierAd Tf }SAPEdddEA8d A8courierT] } else {SBAPEdddEAcourierAd Tf wone = 0;SBAPEdddEAcourierAd Tm checkLSB += val;SBAPEdddEAcourierAd Tw* a = checkLSB & 0xffffff00;SBAPEdddEAcourierAd Ti if(a != 0) {SBAPEdddEAcourierAd T|/ checkLSB &= 0x000000ff;SBAPEdddEAcourierAd Tt' checksum(0x01);SBAPEdddEAcourierAd Tv) wone = 0; /* A */SBAPEdddEAcourierAd T^ }SBAPEdddEAcourierAd TV }SBAPEdddEAcourierAd TN}SBAPEdddEAcourierAd T TjQWhen the program shown in Listing 3.4.1 was initially run, errors were still being observed. Having taken the hexadecimal values and calculated the checksum by hand, it was confirmed that the code was in error. Debugging the code with gdb, the failure was noticed. When entering the function, a test is performed on the variable 'wone' to decide which byte the operation is applied to. The value of 'wone' is then complimented for the next time thus ensuring that the operation will be applied to the other byte on the next call. If an overflow occurs, the function is called recursively, adding one to the other byte. However, when this occurs the variable 'wone' is complemented again. Thus, the next time the the function is called, the operation is applied to the same byte. To correct this, the variable 'wone' is reset after an overflow, this is shown by the points marked /* A */. This could never happen in the assembler code because no recursion is allowed. The 8051 has a very small area for the stack. This could easily overwrite important data if unconstrained recursion was allowed to occur.A8 'T T3.4.3. ResultsT T^STo test this part of the project, a SLIP interface was set-up on the serial port of the computer. A piece of code (appendix 5: '      !"#$%&'()*+,-./0123456789:;>?@ABCDEFGHIJKMNOPQRSTUVWXserial_listen') was written to record all the input from the serial port into a file, thus recording an entire SLIP packet. Another piece of software was also written to send data out of the computer's serial port (appendix 8: 'steptest'). This program waits for the user to press enter before sending the next byte. The SLIP interface was configured with multicast and broadcast packets disabled. Therefore, no packets from router discovery or lan broadcasts would be forwarded to the microcontroller. The SLIP interface was given the address 10.0.0.1, and a subnet mask of 255.255.255.255. Thus the only packets that could be forwarded to the SLIP interface were those that were directly addressed to the microcontroller.T TThe packet that was chosen to be recorded was an ICMP echo request. This is due to the simplicity of the protocol and the intention to be implement ICMP next. The packet header had the following sequence of bytes:T TW10x45 0x00 0x00 0x54 0x00 0x49 0x00 0x00 0x40 0x01SAcourierTW10x66 0x5e 0x0a 0x00 0x00 0x01 0x0a 0x00 0x00 0x02SAcourierT T8-This packet is shown without the SLIP framing. Closely examining the above header prompted an enhancement to the checksum algorithm, an extra check was added to ascertain whenever the value was zero. This had the result of saving many instruction cycles since a vast proportion of the header was zero.T TWhen testing the IP header code, a common mistake kept recurring. Much of the IP header code works by comparisons, introducing the following errors. When executing a compare instruction, there are two very closely linked forms.T`CJNE A,0x00h,NextS2APdddA @ 3318620413TaCJNE A,#0x00h,NextS2APdddA @ 3318620413TB7Both of the above instructions execute a "compare and jump if not equal". However the first instruction compares the accumulator with the value in address 0x00h (R0), and the second compares the accumulator with the constant value 0x00h. This meant that unexpected branches occurred when they were not meant to.T TOnce these issues had been resolved, the IP header evaluation code was shown to be functioning correctly. This was tested by stepping through the program and checking that the IP header was evaluated correctly.T T#3.5. ICMP implementationT T 3.5.1. DesignT TICMP provides messages for the network and transport layers that need attention. These messages range from serious errors like an unreachable network, to simple information, such as an echo request or reply. Some ICMP messages may even move through to the application layer.T TMany ICMP messages are directed towards routers and the status of links. It was therefore decided to implement only those message types that were needed, as and when required. However, to ensure that the IP layer was functioning correctly and could detect different ICMP message types, it was decided to implement the ICMP echo reply code. This would also test the correct generation of IP headers for packets being sent.T TICMP echo reply packets are generated in response to an ICMP echo request in a 1:1 ratio. This is the protocol used by the UNIX 'ping' command to test the state of a host. The ICMP echo request and reply messages contain an 8-byte header. When replying to an echo request, the last four bytes of the header must be returned in addition to any data following the header. The format of an ICMP message can be seen in Figure 3.5.1.A8 A8 T TW3Figure 3.5.1. ICMP echo request/reply packet formatSA  A @Tp Adapted from RFC 792 (1981)o5:'S&A  PA  PA PA8d TThe type and code identify how the host should interpret the message. When replying to an ICMP echo request, the Identification and Sequence Number fields must be returned exactly.T T 3.5.2. ImplementationT TWhen calculating the ICMP checksum, the length of the packet is not guaranteed to be even. Therefore the checksum calculation functions were merged to look more like the pseudo-C code in Listing 3.4.1. To achieve this a single-bit flag was introduced to keep track of which byte of the checksum the operation occurred upon. This also meant that only one function call was needed for both bytes.A8 T TeZWhen implementing the ICMP echo reply, there was a large memory storage problem. Due to the data contained within the packet needing to be returned to the sender. Most UNIX variants use between 56 and 64 bytes, which accounts for one quarter of the 8051's memory. It was decided to use the indirect addressing area of the memory to buffer this data. This memory area covers 128 bytes from 0x0080 to 0x00ff. It is called indirect memory because to access it the user has to load a special register called the Data PoinTeR (DPTR) with the address, and then use one of the MOVX instructions. For example:T T MOVX a,@DPTRT TThis instruction would move the contents of the address contained within the DPTR register into the accumulator. This is a similar concept to a pointer dereference operation in C.T TWhen receiving the ICMP data, the DPTR is loaded with 0x00ff. After each receive, the byte is added to the checksum and placed into the indirect memory. The DPL register is then decremented, this has the effect of subtracting one from the lowest eight bits of the DPTR register. By doing this, the last four bytes of ICMP header and all of the data were stored in the indirect memory area. The last four bytes of the header are stored as they are not altered when sending the reply.T TOnce all the data had been received, the IP header could be sent followed by the ICMP header and data. To send the IP header, a function call was created. The length of data was passed in registers R2 and R3 and the protocol in R5. The amount of data pushed onto the stack was kept at a minimum because there was a further layer of function calls executed from within this function. This lead to the stack getting close to overflowing. However, by minimising the number of registers PUSHed and POPed, this scenario was avoided.T TTo send the ICMP header and data involved a simple piece of serial code which invoked the reverse procedure from placing data in the buffer, loading the DPTR with 0x00ff and decrementing the DPL until all data was sent.T%3.5.3. Testing and resultsT TLATo test this stage, the packet 'ICMP echo request', shown in the appendix 'Test Packets' was passed through the stepping test used earlier. When stepping through this packet, the results obtained were similar to those expected, although the packet was echoed back at such a speed that, it was impossible to check by hand.T T:/Thus, a new version of the steptest called packettest was written (appendix 4: packettest). This program was able to receive the incoming data and save it to a file for examination. Another program called 'analyser' was also created (appendix 3: analyser), to interpret the packet, confirm the checksums and examine the payload. This program is similar in operation to the UNIX snoop and tcpdump commands, when reading packets from a file. This program has the advantage of displaying the packet information, even if the packet is in error (checksum failure).T TZOUsing these new tools, the time between sending bytes was set at half a second and the packet returned was shown to be exactly correct. However, when the time between sends was dropped to zero, as on a live SLIP interface, the packets seemed to be shortened by one byte. When tested repeatedly, exactly the same results were produced.T T}rInitially, as discussed earlier, this was assumed to be an error in the serial port controls. However, the byte concerned had no significance to any flow control parameters. To investigate further, the simulator was instructed to cause a breakpoint at the moment when the ICMP data was starting to be received. When stepping through the program, the ICMP code functioned as when leaving gaps between sends, thus producing correct results. However when running at full speed the same result occurred, dropping the single byte. As a precaution, the serial access code for the simulator was examined, but no fault was discovered.T TThe exact number of bytes that would be sent before the offending byte was sent were counted and the simulator was instructed to stop on exactly that number of iterations of the serial receive interrupt handler. When the simulator stopped, the offending byte had indeed been received by the simulator. To see where this failed, the program was stepped through. The result was a programming error. The first few lines of the RxBPS code are listed below to show the cause.T@o5:(S&A  PA  PA PT^/* Receive Put */SBAP ddd AcourierAd Tfvoid Put(unsigned char a)SBAP ddd AcourierAd TN{SBAP ddd AcourierAd T_ if(RxB_FULL == 1)SBAP ddd AcourierAd TV return;SBAP ddd AcourierAd T'SAP@ ddd@ T T{As the program section shows, when the buffer is marked full, the incoming byte was discarded. Setting the simulator up to break on the second time that RxB_FULL was set to a logical one confirmed the theory. This only occurred once, explaining the lost byte. In addition, it only took place when a large amount of processing is required, delaying receiving data from the buffer.TThe next puzzle was why this was happening, as another part of the RxBPS function switched off serial reception when the buffer was full. With careful examination of the simulator code, it can be explained. Figure 3.5.2 shows a timing diagram for the serial input. If the first byte sets the RxB_FULL flag, the REN bit will go to a logical zero. However, if a byte is being received at that moment in time, it will be passed on to the running program. This problem seems only to exist in the simulator. However, it is also possible for the same sequence of events to occur in hardware, although much less likely. When taking the DTR line low, indicating there is no more buffer space, there could be a character in transit. However the hardware is significantly faster, so the DTR flag would be bought low almost instantly. This is not a guarantee that this failure will not occur in hardware, so a formal fix was needed.A8 T TM)Figure 3.5.2. Serial input timing diagramSA  A @T@o5:)S&A  PA  PA PT TTo allow for this, the buffer was signalled to be full one byte before it was actually full. This allowed space for one more byte to be received avoiding the problem. Listing 3.5.1 shows the updated RxBPS routine.A8 T TP,Listing 3.5.1. The RxBPS function version 2.SA  A @TjS*AcourierAd o5:*S&A  PA  PA PTh/* Receive Put version 2 */SBAP~ ddd~ AcourierAd Tfvoid Put(unsigned char a)SBAP~ ddd~ AcourierAd TN{SBAP~ ddd~ AcourierAd T^ unsigned char b;SBAP~ ddd~ AcourierAd TMSBAP~ ddd~ AcourierAd T_ if(RxB_FULL == 1)SBAP~ ddd~ AcourierAd TV return;SBAP~ ddd~ AcourierAd TMSBAP~ ddd~ AcourierAd T] *Data_Head = a;SBAP~ ddd~ AcourierAd TZ Data_Head++;SBAP~ ddd~ AcourierAd TN SBAP~ ddd~ AcourierAd Tb if(Data_Head == End)SBAP~ ddd~ AcourierAd Ta Data_Head = Start;SBAP~ ddd~ AcourierAd TMSBAP~ ddd~ AcourierAd TZ /* added */ SBAP~ ddd~ AcourierAd T\ b = Data_Head;SBAP~ ddd~ AcourierAd TZ if(b == End)SBAP~ ddd~ AcourierAd TY b = Start;SBAP~ ddd~ AcourierAd TMSBAP~ ddd~ AcourierAd Ta if(b == Data_Tail){SBAP~ ddd~ AcourierAd T\ RxB_FULL = 1;SBAP~ ddd~ AcourierAd T_ REN = 0;SAP~ ddd~ A8 d A8 courierTO }SBAP~ ddd~ AcourierAd TN}SBAP~ ddd~ AcourierAd T3S(AtimesAd TvWhen tested as before, the program worked correctly in a basic step mode. However, when in full speed mode data was still being lost but in a different pattern than that prior to the modifications. Data was being lost in groups of five bytes, exactly the same size as the buffer. Having monitored the buffer, it was clear that a buffer overflow was occurring (Figure 3.5.3).S2A PAtimesAd A8 htT=S2AtimesAd A  TeFigure 3.5.3. Buffer overflowS=AtimesAd A  A @ThS(AtimesAd o5:+S&A  PA  PA PT3S(AtimesAd T3S(AtimesAd T3S(AtimesAd TvFigure 3.5.3 shows how a buffer overflow can occur. Each stage shows the state after the previous action has occurred.S(AtimesAd A8  T This is the buffer in its normal position. When a byte of data is received, the head increments by one. Variable b then takes the value of the Head + 1, setting the TxB_FULL flag.SVAP6dddQAtimesAd A @ 3709360413 TCThe buffer receives another byte of data; this uses the last available byte in the buffer. The head pointer increments by one, and b assumes the value of the Head + 1. No flags are set as b does not equal the tail.SVAP6dddQAtimesAd A @ 3709360413 T}One byte of data is taken from the buffer, clearing the TxB_FULL flag, setting the REN bit and incrementing the tail pointer.SVAP6dddQAtimesAd A @ 3709360413 TTOne more byte of data is received, the data is placed into the buffer and the head increments. Again b takes the value of Head + 1, which is ahead of the Tail, and therefore no flags are set. The buffer has one space at this point.SVAP6dddQAtimesAd A @ 3709360413 TJAnother byte of data is received, the data is placed into the buffer and the head is incremented. The buffer is totally full at this point, however no flags are set because b is now two bytes in-front of the tail pointer.SVAP6dddQAtimesAd A @ 3709360413 TdA byte is taken from the buffer and the tail catches up with the head. This sets the RxB_EMPTY flag.SVAP6dddQAtimesAd A @ 3709360413 TXThe buffer sits at this stage waiting for the next byte, having lost five bytes of data.SVAP6dddQAtimesAd A @ 3709360413 TThe fix for this problem was remarkably simple. It required that both the Head pointer and variable b be checked to see if the buffer is full. This final version of the RxBPS function is shown in Listing 3.5.2.S(AtimesAd A8 T3S(AtimesAd T],Listing 3.5.2. The RxBPS function version 3.S&APpdddpA  TSBAPpdddpAcourierAd o5:,S&A  PA  PA PTh/* Receive Put version 3 */SBAP ddd AcourierAd Tfvoid Put(unsigned char a)SBAP ddd AcourierAd TN{SBAP ddd AcourierAd T^ unsigned char b;SBAP ddd AcourierAd TMSBAP ddd AcourierAd T_ if(RxB_FULL == 1)SBAP ddd AcourierAd TV return;SBAP ddd AcourierAd TMSBAP ddd AcourierAd T] *Data_Head = a;SBAP ddd AcourierAd TZ Data_Head++;SBAP ddd AcourierAd TN SBAP ddd AcourierAd Tb if(Data_Head == End)SBAP ddd AcourierAd Ta Data_Head = Start;SBAP ddd AcourierAd TMSBAP ddd AcourierAd Ti if(Data_Head == Data_Tail){SBAP ddd AcourierAd T\ RxB_FULL = 1;SBAP ddd AcourierAd T_ REN = 0;SAP ddd A8 d A8 courierTO }SBAP ddd AcourierAd TMSBAP ddd AcourierAd TZ /* added */ SBAP ddd AcourierAd T\ b = Data_Head;SBAP ddd AcourierAd TZ if(b == End)SBAP ddd AcourierAd TY b = Start;SBAP ddd AcourierAd TMSBAP ddd AcourierAd Ta if(b == Data_Tail){SBAP ddd AcourierAd T\ RxB_FULL = 1;SBAP ddd AcourierAd T_ REN = 0;SAP ddd A8 d A8 courierTO }SBAP ddd AcourierAd TN}SBAP ddd AcourierAd T3S(AtimesAd T3S(AtimesAd TWhen the modifications were applied, the ICMP layer functioned correctly. The results of this can be seen in the appendix under "Test Packets". The returned packet is called 'ICMP echo reply'. The device was proved to be functioning correctly with no delay between sending bytes. The SLIP interface was re-initialised and the simulator was connected to the other serial port. When the ping command was executed the following results were obtained.S(AtimesAd T3S(AtimesAd T3S(AtimesAd TZ'PING 10.0.0.2 (10.0.0.2): 56 data bytesS(AtimesAd Tl964 bytes from 10.0.0.2: icmp_seq=0 ttl=255 time=2019.8 msS(AtimesAd Tl964 bytes from 10.0.0.2: icmp_seq=1 ttl=255 time=2020.0 msS(AtimesAd Tl964 bytes from 10.0.0.2: icmp_seq=2 ttl=255 time=2000.0 msS(AtimesAd Tl964 bytes from 10.0.0.2: icmp_seq=3 ttl=255 time=2000.0 msS(AtimesAd T3S(AtimesAd TV#This shows that the simulator was generating an ICMP echo replies. However, the RTT (Round Trip Time) is very large. The results show indicate a two second RTT. This can be explained by the fact that the simulator being non-real-time and thus was having trouble executing the instructions at a fast enough rate. This would also account for the simulator using over 95% of the CPU when running. For comparison the 8051 is an eight-bit microcontroller being simulated at an equivalent rate of 11.059Mhz, running on a 32-bit 200MHz Pentium computer.S(AtimesAd TB)3.6. Transport Layer (UDP) implementationSA PT T 3.6.1. DesignT3S(AtimesAd TxEThe User Datagram Protocol (UDP) is a simple, connectionless datagram-based protocol. It does not provide any error correction or flow control but there is error detection included, in the form of a checksum. However, this will only discard the packet, and it is up to the application layer to realise the data inconsistency.S(AtimesAd T3S(AtimesAd TIn this stack, the UDP does not provide a great deal of benefit except as a basis for developing the TCP layer. However, it proves that the microcontroller is capable of supporting a complete protocol stack.S(AtimesAd T T@ In a large TCP/IP stack, the UDP layer would interface with a device known as a de-multiplexor to filter application layer data to a specific process. This is unnecessary in a small device such as this. The transport layer and application layer can almost be joined into one layer. This was not carried out because the application layer code could be used in both the UDP and TCP layers. Since the multiplexor was removed, the application layer was bound to a specific port at assembly time. The default is port number 4096.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T 3.6.2. ImplementationT3S(AtimesAd TFor the initial development of the UDP layer, packets destined for any port other than 4096 were simply ignored. Accepting this, meant that the UDP layer became a simple interpretation of the packet. When calculating the checksum for the UDP datagram, a twelve byte pseudo header is included in the checksum. The UDP checksum also covers all the data contained within the UDP datagram. This is shown in Figure 3.6.1.S3AtimesAd A @A8 T3S(AtimesAd TW$When using UDP, the checksum generation is optional. However, this implementation will discard any datagram that does not contain a valid checksum. The UDP layer is vastly simplified by not allowing fragmented packets. This removes the requirement to store state information between packets. S(AtimesAd T3S(AtimesAd TOnce the reception and transmission of UDP packets had been confirmed, ICMP type 3 messages were implemented. This enabled the microcontroller to signal another host to stop sending packets. This is useful when a host generates packets bound for a port other than 4096. The UDP layer consequently sends an ICMP "port unreachable" message, which forces the source host to close down the application sending the packets.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd Tk#Figure 3.6.1. The UDP header formatS=AtimesAd A  A @T Adapted from RFC 768, 1980S2AtimesAd A  o5:-S&A  PA  PA PA8 A8d T3S(AtimesAd T3S(AtimesAd T3.6.3. ResultsT3S(AtimesAd T3S(AtimesAd TTo test this section, the UDP layer was configured as an echo server. In this mode any data received by the server will be echoed back to the client.S(AtimesAd T3S(AtimesAd TTo test the UDP layer, a UDP packet called 'UDP test' was captured from the SLIP interface using the serial_listen program (appendix 9: Test packets). The packet only contains one byte of data, an 'A' character. By sending this packet, both sending and receiving UDP packets could be tested. Having corrected a few minor program errors, the UDP layer was shown to be functioning correctly. S(AtimesAd T3S(AtimesAd Th5Once the ICMP type 3 messages were implemented, the same test was repeated. However when the simulator attempted to check the destination port number, a breakpoint was induced in the simulator and the port number was altered to fail the test. In other words, the UDP layer was forced to return an ICMP error. S(AtimesAd T3S(AtimesAd TOnce these test were completed and the return packets checked for validity, the SLIP interface was one again set up and the test run in a live situation. An interface for accessing the device was built on the computer. This is called 'udp_cmd' and can be found in the appendices. This program accepts input from the command line, which is then passed to the microcontroller for evaluation. The following tcpdump output was obtained.S(AtimesAd T3S(AtimesAd Tb/When sending a datagram to the recognised port:S(AtimesAd Ti422:16:26.360730 10.0.0.1.5000 > 10.0.0.2.4096: udp 1S*AcourierAd Ti422:16:28.361101 10.0.0.2.4096 > 10.0.0.1.5000: udp 1S*AcourierAd T5S*AcourierAd TThe last section of both lines, 'udp 1', represents the UDP layer receiving and returning a single byte of data. The udp_cmd program binds itself to port 5000, and sends datagrams to the simulator on port 4096.T3S(AtimesAd T3S(AtimesAd T^+When sending a datagram to an invalid port:S(AtimesAd T5S*AcourierAd T5S*AcourierAd Ti422:23:11.325645 10.0.0.1.5000 > 10.0.0.2.4097: udp 1S*AcourierAd TM22:23:13.786554 10.0.0.2 > 10.0.0.1: icmp: 10.0.0.2 udp port 4097 unreachableS*AcourierAd T5S*AcourierAd T3S(AtimesAd TWhen the ICMP error is received by the Linux computer, the socket associated with port 5000 was closed. This prohibits any sends and receives by the program. The only way to defeat this is to shut down the socket and re-initialise.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T4)3.7. Transport Layer (TCP) implementationT3S(AtimesAd T 3.7.1. DesignT3S(AtimesAd TTCP is a protocol that provides a reliable and ordered stream of bytes between peer hosts. This enables TCP to be used for connections that require the reliability guarantees, which UDP cannot provide. Due to the size and complexity of the TCP protocol, it was decided that a full implementation would be far beyond the timescale of the project and physical attributes of the microcontroller. Thus to achieve this goal, the TCP specification was implemented as a basic set of characteristics, which could be incorporated into the Layer on an 'as needed' basis. This meant that any feature of TCP that was not needed would not be included. There were several items that were not essential. The first of these was the TCP multiplexor. In a large system, this device multiplexes the input and output of all applications wishing to use the TCP/IP stack. However, since only one TCP port is used in a small microcontroller application the multiplexor has no use, and can therefore be dropped.S(AtimesAd T3S(AtimesAd T@The TCP header (Figure 3.7.1.) contains a 32-bit sequence number and a 32-bit acknowledgement number. The sequence number is generated by a counter that increments by one, every 4 microseconds. This is impractical considering that the microcontroller's clock is 11.059Mhz and instructions take 12 clock cycles to complete, giving an instruction clock of 921.583 KHz. In other words, one instruction is completed every 1.08mSeconds, making the RFC specification almost impossible. A8id A8itimesA8 A8 symbolT iTlHowever, the BSD sources violate the RFC and provide a feasible implementation. BSD creates a clock that updates its counter by 64000 every half a second, which corresponds to updating by one every 8 mSeconds. This provides a way to implement the counter in 8051, without using all the available instruction time. This timer can also be used for the TCP re-transmission, keepalive and persist signals. However, it is unlikely that the 8051 will have enough processing power to keep track of all timers and so the majority will not be used.A8 symbolA8:d A8:timesT3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd Tk#Figure 3.7.1. The TCP header formatS=AtimesAd A  A @T Adapted from RFC 793.S(AtimesAd o5:.S&A  PA  PA PA8 A8d T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd TThere are not many differences between the TCP (Figure 3.7.1) and UDP (Figure 3.6.1) headers. However, there are several enhancements of the UDP header. The sequence numbers, described above, allow the server and client to keep track of the position of a packet within a stream of bytes. These also allows both ends to recognise whether a packet has been lost and needs to wait for it to be retransmitted.S(AtimesAd A8 0<A8 GST3S(AtimesAd TNThe most important differences between the TCP and UDP headers in regard to this project, are the six flags shown just before the window size field. These flags enable hosts to acknowledge packets, reset connections and many other functions. A brief description of the flags follows:S(AtimesAd T3S(AtimesAd T&URG. By setting this flag, the transmitting host indicates that urgent data has been placed into the data stream. The receiver then decides what to do with this data. The urgent pointer indicates the location of this data. However there are two different interpretations of this field. The BSD TCP implementation points to the the byte following the last byte of urgent data. The correct specification points to the last byte of urgent data.SVAP6dddQAtimesAd A @ 4206430813 TACK. This flag indicates that the acknowledgement field within the TCP header is valid and should be used to confirm the reception of a byte sequence.SVAP6dddQAtimesAd A @ 4206430813 TqPSH. When this flag is set, the TCP layer is ordered to transmit data as soon as it is ready to send. On the receiver, this will cause any bytes currently buffered to be flushed to the application layer, along with the data contained within the current packet.SVAP6dddQAtimesAd A @ 4206430813 T>RST. When a packet is sent with the reset flag active, it will abort the current connection. This is used for terminating connections that do not have any application layer program associated with them. For instance, when a host tries to connect to a port that is not 4096, the microcontroller will generate a reset packet, which will prevent the transmitting host from sending any more packets. This is the same as the UDP layer sending a "port unreachable" error.SVAP6dddQAtimesAd A @ 4206430813 TlSYN. When setting up a connection, SYN packets transfer the initial sequence numbers between the peer hosts.SVAP6dddQAtimesAd A @ 4206430813 T#FIN. Setting this flag indicates the the sender no longer wishes to send data. However the receiver of this flag may still send data, until it sends a packet with an active FIN flag.SVAP6dddQAtimesAd A @ 4206430813 T3S(AtimesAd T3S(AtimesAd T 3.7.2. ImplementationT T( 3.7.2.1. TCP state transitionT3S(AtimesAd TThe TCP layer is implemented through a series of states. The connection moves between each state as is required Figure 3.7.2 shows all the states for the TCP layer.S(AtimesAd A8 p|TEFigure 3.7.2. TCP state transitions (Adapted from TCP/IP illustrated)S=AtimesAd A  A @A8 #EA8$Ed ThS(AtimesAd o5:/S&A  PA  PA PT3S(AtimesAd TThis 8051 TCP layer is solely concerned with server states because it will never operate as a client. To move between these five states, three bit flags were used. TCPCNS1, TCPCNS2 and CLOSEW. Initially all there flags are set to zero. S(AtimesAd T3S(AtimesAd T3S(AtimesAd T\%To begin with, the server is in the LISTEN state, waiting for a synchronisation packet. When a packet with a valid SYN bit is received, the microcontroller is instructed to collect an Initial Sequence Number (ISN) from the counter. At this time, a packet with active SYN and ACK bits will also be sent. This is termed a passive open because the server did not initiate the synchronisation sequence. Following this, the stream setup information is copied for future reference. This includes the socket pair, local sequence number and remote sequence number. A socket is the combination of an IP number and a port number. It defines a socket pair as two sockets indicating the termination points at both ends of the stream. Once the synchronisation packet is sent, the microcontroller moves into the SYN_RCVD state, this is performed via setting the TCPCNS1 bit. When the acknowledgement is received for the synchronisation packet, the TCPSNS2 flag is set. This indicats that the host is in its ESTABLISHED state, during which time data is transferred normally.A8%d A8%timesTi6Finally the server will be sent a finish packet. This will move the state into the CLOSE_WAIT/LAST_ACK position. Theses two states can be combined because once the client has finished sending data, the server will have no further data to send to the client. This indicates that the client always initiates the close (active close) and that the server always responds to the close (passive close). When in this state the microcontroller sets the CLOSEW flag. The return finish packet is sent to the client along with an acknowledgement for the finish packet received.S(AtimesAd T3S(AtimesAd TIn the CLOSE_WAIT/LAST_ACK state, any data send to the host is ignored since it cannot be originating from the client. However, a delayed packet may arrive at the microcontroller, in which case it should be ignored anyway. The only packet that will alter the state is an acknowledgement indicator. When this is received, the microcontroller resets all variables and indicators associated with the stream and moves back to the LISTEN state.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T 3.7.2.2. TCP TimerT3S(AtimesAd TY"As described above, the BSD TCP timer provides a way to implement timing without destroying the microcontroller's ability to process the data. The 8051 has two timers, however only one is used for the baud rate generation. This leaves the remaining timer to be used in TCP timing. The timers can be configured in many different ways, but only one method has a possible use in TCP timing. The timer was configured as a 16 bit count-up timer. However, it was necessary to find a suitable value in order to generate half second rollover interrupts.A8d A8timesT TThe microcontroller clock runs at 11.059Mhz. The internal counter is only updated every instruction cycle. A single instruction cycle lasts for twelve clock cycles. From this, the effective counter frequency can be found, which is:TSA @TSA @Aq0lf:0SWAP A%PNO ObjEFFFD685APUA PT3S(AtimesAd T^+The counter value can then be generated by:S(AtimesAd T3S(AtimesAd TS3AtimesAd A @Aq0lf:1SWAPNtA%PNO ObjEFFFD686APA PT3S(AtimesAd T Unfortunately, this value cannot be stored in the counter because it can only accommodate 16 bits. The value indicated above would require a twenty bit counter. The maximum time interval that the counter can generate is calculated below.S(AtimesAd T3S(AtimesAd TS3AtimesAd A @Aq0lf:2SWAPA%PNO ObjEFFFD687APA PT3S(AtimesAd T To implement the timer it was decided to make the counter update twenty times a second, ten times faster than the BSD counter. To keep the sequence number in time, the value was updated by only one tenth each time.S(AtimesAd T3S(AtimesAd TThe correct timer value can be calculated to be 46079, which is equivalent to 0xB3FF. However as the timer counts up not down, the counter reload value is:S(AtimesAd T3S(AtimesAd TS3AtimesAd A @Aq0lf:3SWAPr 4A%PNO ObjEFFFD688APfA PT3S(AtimesAd TThe actual timer reload value was 0x4C08 because eight cycles are used to reload the timer, by adding this to the reload value, the timer is compensated for the time taken to commit the reload.S(AtimesAd T3S(AtimesAd T3S(AtimesAd TWhen the BSD timer rollover occurs, the ISN is incremented by 64000. Thus, after one second, the RFC compliant ISN will be incremented by 250000. However the BSD ISN will only be incremented by 128000. At this point there were two options available, to follow the BSD or RFC compliant timer. The BSD timer is far simpler since every twentieth of a second, the microcontroller's counter would increment by 6400 (0x1900). This provides easy addition in hexadecimal because only one byte needs to be dealt with. However, the RFC timer is more complex since every twentieth of a second the ISN needs to be updated by 12500 (0x30D4). This requires complex addition in an eight bit accumulator, which would consume more instruction cycles.S(AtimesAd T3S(AtimesAd T3S(AtimesAd TIt was decided to follow the RFC standard, but to add a small enhancement. Every twentieth of a second, the timer was to be updated by 12544 (0x3100) thus simplifying the addition. However, this does introduce an inaccuracy since after one second, the timer will contain 250880, giving a 0.35% error when compared to the RFC value os 250000. The counter does not need to provide a vitally accurate measurement and thus this is an acceptable error.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T= 23.7.2.3. TCP connection initiation and terminationT3S(AtimesAd T`-Once the timer was functioning correctly, the first major task was to achieve reliable connection synchronisation and termination sequences. Without this, none of the TCP protocol would be able to operate properly. To speed development, several functions were created that could be used by all parts of the TCP layer to check the validity of a packet. These functions perform the operations which add to the local or remote sequence numbers, comparing the socket pair information and the stored sequence numbers with those obtained from the received packet.S(AtimesAd T3S(AtimesAd T{HA function was also created to send the TCP header and data. This relies on the flags, options and data to be transmitted to be set up in the buffer area of memory. The send function then dispatches the TCP header, options and data, whilst calculating the checksum on the fly and reducing the amount of data processing required.S(AtimesAd T3S(AtimesAd Tf3Once the connection and disconnection sections were completed, they were tested (the results of which can be seen below). The TCP layer then had reset functionality added. This meant that when a packet was received, and it was not recognised as part of the current stream a reset packet would be sent to the originating host. This informs the destination host to abort the source socket and stop sending data. A packet can be identified as not being part of the current stream by having an incorrect port number. This can been seen working in the results section.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T: /3.7.2.4. TCP data, flow control and restrictionT3S(AtimesAd TaThis was by far the most complex part of the TCP layer to implement. The TCP layer needed to be configured to prevent the microcontroller being overloaded with data from the source host. To this end, a series of restricting parameters had to be defined, so as to allow TCP to function correctly and at the same time not swamp the destination with data. S(AtimesAd T3S(AtimesAd TDue to the small amount of memory within the 8051, incoming data packets must be kept small, thus avoiding problems with buffering and processing. To do this the Maximum Segment Size (MSS) of each TCP packet was set to 16. This option can only be set in the TCP synchronisation stage, where it is usually set to the Maximum Transmission Unit (MTU) of the host. By setting this value small enough, the TCP layer on the client side will be forced to send any data that is passed to it without waiting for more data. The smallest applicable size for the MSS is two bytes, however the microcontroller is able to cope with sixteen. This also has the advantage of not filling up the serial buffer on the Linux computer with lots of small packets.S(AtimesAd T3S(AtimesAd TTCP also defines a window size. This is the number of bytes that can be sent to a host before receiving an acknowledgement. In TCP, the window 'slides' along the data (Figure 3.7.3).S(AtimesAd A8 A8 T3S(AtimesAd Th Figure 3.7.3. TCP sliding windowS=AtimesAd A  A @ThS(AtimesAd o5:4S&A  PA  PA PT3S(AtimesAd T_In the TCP layer, the the window size is set to the MSS. This means that when a large segment of data is sent, it will completely fill the window and the sender will be forced to wait for an acknowledgement. Both the window size and MSS may be smaller than sixteen. However, this introduces the possibility of filling the buffer on the Linux end of the SLIP line, which would cause much more error control to be encountered than is necessary. The smallest the window size may become is two. If the window size is allowed to become 1, TCP invokes a series of window recovery packets, because it assumes the window size is the result of Silly Window Syndrome (SWS). SWS can cause unnecessary complications within the TCP layer. These involve, but are not limited to, holding data back to fill a larger segment, reversing the effect of the push flag described below.S(AtimesAd T3S(AtimesAd T3S(AtimesAd TTCP can be restricted further by the use of the push flag. This flag causes all TCP buffering to be eliminated and data to be sent as soon as the transport layer is able to. This flag is often set when the applications layer is involved in interactive communications rather than bulk data transfer, for example Telnet as opposed to the File Transfer Protocol (FTP). This flag will ensure that if any bytes enter the transport layer, they will be sent immediately. S(AtimesAd T=S2AtimesAd A  T3S(AtimesAd T3S(AtimesAd T3.7.3. TestingT3S(AtimesAd T|To test the initial connection protocols, an initial synchronisation packet was recorded from the SLIP line using the serial_listen program (appendix 5). Once the program was able to respond correctly to this packet and the returned synchronisation packet was checked to make sure it contained the correct values, development became a lot more complex. This is because, to generate the correct response packets would mean writing the TCP layer in C on the UNIX host as well as in assembler on the microcontroller, or testing the device on a live SLIP interface. The second method was chosen. This resulted in large periods of time spent waiting for connections to time out due to the retransmission properties of TCP. Initially the TCP layer was unable to respond to finish packets, therefore the packet would be re-transmitted fifteen times, in the space of half an hour. During this time, the SLIP interface could not be used because the retransmitted packets would interfere with the device. It was soon discovered that the variables that control the TCP re-transmission in Linux could easily be altered, reducing this time to only five minutes.S(AtimesAd T3S(AtimesAd T3S(AtimesAd TThis method of testing became even more complex when sending the finish packets, as a problem was encountered. The finish packets were being sent, but not recognised. In addition, they were being reported as having incorrect lengths by tcpdump. Due to the position of data within the stream, the packets were almost impossible to debug, because they were completely embedded within the TCP protocol.S(AtimesAd T:To enable packet analysis, the simulator was set up as in Figure 3.7.4. using various UNIX commands to achieve the data copying so that packets could be analysed. This arrangement allowed all outgoing packets to be replicated both to the serial port and to disk. Once this had been achieved the packets were split into separate files and analysed. The problem was soon discovered. The finish and acknowledgement packets needed to be sent at the same time, however the buffers had failed to be flushed in-between each packet and therefore the SLIP end characters were not being sent. This made the packet seem longer than the reported size. A small piece of code was inserted into the finish sequence to accommodate for this. When the test was re-run the expected results were seen, and the TCP connection closed down correctly. The final stage was to recognise the last acknowledgement packet sent and reset the internal state. This was completed with no malfunctions. The tcpdump output of this test are shown below.S(AtimesAd A8 :FT3S(AtimesAd T.Figure 3.7.4. Serial transmission interceptionSGAtimesAd A  A A @ThS(AtimesAd o5:5S&A  PA  PA PT5S*AcourierAd TCOpen connection:S(AtimesAd T10.0.0.1.1035 > 10.0.0.2.4096: S 2188408712:2188408712(0) win 32120 (DF) (ttl 64, id 58831)S*AcourierAd Tk10.0.0.2.4096 > 10.0.0.1.1035: S 25088:25088(0) ack 2188408713 win 16 (ttl 255, id 1)S*AcourierAd Tp10.0.0.1.1035 > 10.0.0.2.4096: . ack 25089 win 32120 (DF) (ttl 64, id 58832)S*AcourierAd T5S*AcourierAd T5S*AcourierAd TDClose connection:S(AtimesAd T10.0.0.1.1035 > 10.0.0.2.4096: F 2188408713:2188408713(0) ack 25089 win 32120 (DF) (ttl 64, id 58838)S*AcourierAd T{F10.0.0.2.4096 > 10.0.0.1.1035: . ack 2188408714 win 16 (ttl 255, id 2)S*AcourierAd TU10.0.0.2.4096 > 10.0.0.1.1035: F 25809:25809(0) ack 2188408714 win 16 (ttl 255, id 3)S*AcourierAd Tp10.0.0.1.1035 > 10.0.0.2.4096: . ack 25810 win 32120 (DF) (ttl 64, id 58839)S*AcourierAd T3S(AtimesAd TxEHaving proved that the microcontroller was initiating and terminating connections properly, the reset sequence was added. This was a minor addition of a conditional statement and setting up the outgoing packet. Having done this the simulator was re-run and the following results achieved when connecting to an incorrect port.S(AtimesAd T3S(AtimesAd T10.0.0.1.1037 > 10.0.0.2.4097: S 3223233328:3223233328(0) win 32512 (DF) (ttl 64, id 59604)S*AcourierAd TL10.0.0.2.4097 > 10.0.0.1.1037: R 0:0(0) ack 3223233329 win 0 (ttl 255, id 6)S*AcourierAd T3S(AtimesAd TIt was now necessary to test the main data transfer. This found that the packets contained much more data than was expected. When tracing the execution, it was found that when checking the remaining length of data to send, an overflow was occurring. This resulted in vast quantities of data being sent, approximately two hundred bytes. Once this had been repaired, the test was repeated and the following results were achieved for a single byte echo.S(AtimesAd T3S(AtimesAd T10.0.0.1.1038 > 10.0.0.2.4096: S 3805911386:3805911386(0) win 32512 (DF) (ttl 64, id 61399)S*AcourierAd To10.0.0.2.4096 > 10.0.0.1.1038: S 6685952:6685952(0) ack 3805911387 win 16 (ttl 255, id 7)S*AcourierAd TN10.0.0.1.1038 > 10.0.0.2.4096: . ack 6685953 win 32512 (DF) (ttl 64, id 61403)S*AcourierAd Tg10.0.0.1.1038 > 10.0.0.2.4096: P 3805911387:3805911388(1) ack 6685953 win 32752 (DF) (ttl 64, id 61424)S*AcourierAd TY10.0.0.2.4096 > 10.0.0.1.1038: P 6685953:6685955(2) ack 3805911388 win 16 (ttl 255, id 8)S*AcourierAd TN10.0.0.1.1038 > 10.0.0.2.4096: . ack 6685955 win 32750 (DF) (ttl 64, id 61428)S*AcourierAd Tg10.0.0.1.1038 > 10.0.0.2.4096: F 3805911388:3805911388(0) ack 6685955 win 32752 (DF) (ttl 64, id 61447)S*AcourierAd T{F10.0.0.2.4096 > 10.0.0.1.1038: . ack 3805911389 win 16 (ttl 255, id 9)S*AcourierAd TZ10.0.0.2.4096 > 10.0.0.1.1038: F 6685955:6685955(0) ack 3805911389 win 16 (ttl 255, id 10)S*AcourierAd TN10.0.0.1.1038 > 10.0.0.2.4096: . ack 6685956 win 32751 (DF) (ttl 64, id 61454)S*AcourierAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T!3.8. Application layerT3S(AtimesAd T 3.8.1. DesignT3S(AtimesAd T The application layer for this project is a very basic item. It examines the first byte of each received packet for a valid command. This is possible because TCP has been forced into interactive mode. There are three possible commands; ON, OFF and STATUS. The first two of these set and reset bit zero on port zero of the microcontroller and report OK back to the server. The third command checks the state of the bit and returns the state, ON or OFF. Any other commands will return an error.S(AtimesAd T3S(AtimesAd T3S(AtimesAd T 3.8.2. ImplementationT3S(AtimesAd TSDue to the simplicity of this program section, it only needs a single function call. This leaves the result in the buffer area of memory and places the length into register zero. The TCP or UDP layer then returns its headers and reads the data from memory, returning the result to the client. Listing 3.8.1, below, shows how this operates.S(AtimesAd A8 %2T3S(AtimesAd THS=AtimesAd A  A @Tr*Listing 3.8.1. Application layer interfaceS=AtimesAd A  A @TjS*AcourierAd o5:6S&A  PA  PA PT_#define LIGHT P0.0SBAPVdddVAcourierAd TMSBAPVdddVAcourierAd Tw*void ProcessCommand(unsigned char command)SBAPVdddVAcourierAd TN{SBAPVdddVAcourierAd T3 /* check to see if there was a command received */SBAPVdddVAcourierAd T_ if(length == 0) {SBAPVdddVAcourierAd T] Buffer("ERR");SBAPVdddVAcourierAd TV r0 = 3;SBAPVdddVAcourierAd TV return;SBAPVdddVAcourierAd TO }SBAPVdddVAcourierAd TMSBAPVdddVAcourierAd Tb if(command == '0') {SBAPVdddVAcourierAd TZ *LIGHT = 0;SBAPVdddVAcourierAd T\ Buffer("OK");SBAPVdddVAcourierAd TV r0 = 2;SBAPVdddVAcourierAd Tj } else if (command == '1') {SBAPVdddVAcourierAd TZ *LIGHT = 1;SBAPVdddVAcourierAd T\ Buffer("OK");SBAPVdddVAcourierAd TV r0 = 2;SBAPVdddVAcourierAd Ti } else if (command =='S') {SBAPVdddVAcourierAd T` if(*LIGHT == 1) {SBAPVdddVAcourierAd T^ Buffer ("ON");SBAPVdddVAcourierAd TW r0 = 2;SBAPVdddVAcourierAd TW } else {SBAPVdddVAcourierAd T^ Buffer("OFF");SBAPVdddVAcourierAd TW r0 = 3;SBAPVdddVAcourierAd TP }SBAPVdddVAcourierAd TV } else {SBAPVdddVAcourierAd T] Buffer("ERR");SBAPVdddVAcourierAd TV r0 = 3;SBAPVdddVAcourierAd TO }SBAPVdddVAcourierAd TN}SBAPVdddVAcourierAd TMSBAPdddAcourierAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3S(AtimesAd T3.8.3. ResultsT3S(AtimesAd T3S(AtimesAd TUTo test the application layer, two programs were written implementing the protocol described above. The two programs test the application layer in TCP and UDP and are called tcp_cmd and udp_cmd respectively (appendices 10 and 11). The result of this test can be seen below. The extra command 'Q' is a client only command to quit the program.S(AtimesAd T3S(AtimesAd T5S*AcourierAd TNEnter command (1|0|S|Q):SS*AcourierAd TB Received: OFFS*AcourierAd TNEnter command (1|0|S|Q):1S*AcourierAd TA Received: OKS*AcourierAd TNEnter command (1|0|S|Q):SS*AcourierAd TA Received: ONS*AcourierAd TNEnter command (1|0|S|Q):0S*AcourierAd TA Received: OKS*AcourierAd TNEnter command (1|0|S|Q):SS*AcourierAd TB Received: OFFS*AcourierAd TYEnter command (1|0|S|Q):QS5AcourierAd A @JColour DeskjetSGENPRT PostScriptDQtQtd,,lp -d colourcolourSGENPRT7 UwזwV88. ?&&3.AUu 6P;;,Uu (u H;-@u !Uu ]2?Bu {B{u xu Bu B u 'B4u BAu E BN u E B[ u E Bh u E  Bu u E  B u E  Bu E  Bu E  Bu Bu Bu Bu Bu Bu Bu ;u KB?u xu Bu  BF&u BS'u u  B0u -U%:u u F;@u *U%?$ ~3B.AUu 6p;;,Uu (u H;-@u Uu ]2?Bu B u Bu B4u BAu BNu E6? B[u E6?  Bhu E6? !Bu u "B u #B u [$Bu %@Bu &ABu h'IBlu (JByu )KBu N*QB%u +RB&u ,SB'u '-VB+u .WB",u /XB/-u ;u K0Y-U%:u u F;@u *U%J?$ 3%.AUu 6P;;,Uu (u H;-@u Uu ]2?Bu K1ZBKu xu 2[Bu ;u K3\B u xu 4]Bu xu 5_B" u 6`B/ u 7aB< u 8 kBu 9lBu :mBu ; wBZ"u <xBg#u =yBt$u E6? >zB%u E6? ?{B&u E6? @|B'u E6? A}B(u E6? B~B)u CB*u DB+u 'EB.u FB0u GB1u H-U%:u u F;@u +e%?$ 3%.AUu 6p;;,Uu (u H;-@u aUu ]2?Bu 4IB4u JBAu AKB u LB u MB u ;u KNBu xu OB\u u PBgu xu 4QBu RB u ASBau TBnu U-Bvu VB u WB!u X-U%:u u F;@u  +e%r?$ 3%x .AUu 6P;;,Uu (u H;-@u [Uu ]2?Bu YBu u ZB&u xu [Bu xu h\B u xu ]Bu  xu ^ B$u xu _Bu xu `B.u u aB9!u xu bB"u [cB*u dB&+u eB3,u Af-U%:u u F;@u +e%P?$ `3%VN.AUu 6p;;,Uu (u H;-@u ­Uu ]2?Bu g-Bu hB u AiBu jBu kBu lBu mB&u E6? nB3u E6? oB@u E6? pBMu E6? qBZu rBgu sBtu AtB#u uB$u vB%u 4wB*u xB+u yB,u Az-U%:u u F;@u  +e%.V?$  3%4.AUu 6P;;,Uu (u H;-@u H Uu ]2? Bu {Bu |Bu }B*u ~B2u B?u BLu -BTu \"\ u D$S96":D$&D$?"&D$?4b& b &b&bg&b&b&bn&b&b&bu&b"&b&b|&b) & b & b & b0 & b & b &b7 &b &b&b>&b&b&bE&b&b&bL&b&b&bS&b&b&bZ&b&b& ba&!b&"b&#bh&$b& %b"&&b&'b|& (b&)b6 &*b &+b!&,b="&-b"&.b#&/"E:;D$E'D$?@"E'D$?2b' 0b ' 1b'2b'3bt'4b!'5b'6b{'7b('8b'9b':b/';b'<b '=b6 '>b '?b '@b= 'Ab 'Bb 'CbD'Db'Eb'FbK'Gb'Hb'IbR'Jb'Kb'LbY'Mb'Nb'Ob`'Pb 'Qb'Rbg'Sb'Tb'Ubn'Vb' Wb('Xb'Yb'Zb/'[b'\b']b6 '^b '_b!'`b="'aB-u bB.u cB/u d-U%:u u F;@u  +e% ?$ Ъ3%.AUu 6p;;,Uu (u H;-@u Uu ]2?Bu KeBKu xu fBu gBu hoBE u pBR u qB_u sByu tBu uBu E6?wBu 4E6?4{Bu 'E6?'~Bu Bu B"u B/u ;u KBj!u xu B"u ;u KB*%u xu B&u u  B$0u B11u -U%:u u F;@u +e%?$ Д3%.AUu 6P;; ,Uu (u H;-@u Uu ]2?Bu ju uEu?7nE}?-}U88\ ?FU88\ /E&}U88 ?FU88 pU}|?-|U87\ ?FU87\ /E&|U87 ?FU87 pU|?-|U87\ ?FU87\ /E&|U87 ?FU87 B}u Bu Bu Bu =-B u Bcu Bpu [Bu  Bu !Bu 4"B#u #B&$u $B3%u %B@&u ;u K&B{(u xu 'B*u [(-U%:u u F;@u  +e%?$ ?3%Y.AUu 6p;; ,Uu (u H;-@u —Uu ]2?Bu [)B[u *Bhu +Bu u ,B u -B u E6?.B u E6?/Bu E6?0Bu E6? 1Bu 2Bu 3Bu h4Blu 5Byu 6Bu 7) u t ?8t }?- }U88b ?FU88b /E }U88b ?FU88b /E }U88b ?FU88b }t ?- U87b ?FU8b /E U87b ?FU8b /E U87b ?FU87b t ?- U87b A?FU8Qb /E U87b A?FU8Qb /E U87b A?FU87b A t ?- U87b '?FU8Db /E U87b '?FU8Db /E U87b '?FU87b 'L t ?- U87b ?FU8b /E U87b ?FU8b /E U87b ?FU87b B^0u g-U%:u u F;@u +e%a?$  3%.AUu 6P;; ,Uu (u H;-@u % Uu ]2? Bu 4hB4u iBAu jBNu kBhu lBu u mB} u n-B u op" u #S:":#&#?"&#?2b&qb&bZ&rb&sb&tba&ub&vb&wbh&xb&yb&zbo&{b&|b&}bv &~b# &b &b} &b* &b &b &b1&b&b&b8&b&b&b?&b&b&bF&b&b&bM&b&b&bT&b&b&b[&b&b&bb&b&b& bi& b& b& bp & b!&P"E:;#E'#?@4"E'#?5b'b'bZ'b'b'ba'b'b'bh'b'b'bo'b'b'bv 'b# 'b 'b} ' b* '!b '"b '#b1'$b'%b'&b8''b'(b')b?'*b'+b',bF'-b'.b'/bM'0b'1b'2bT'3b'4b'5b['6b'7b'8bb'9b':b';bi'<b'=b'>bp '?b!'@b!'Abw"'Bb$#'C-U%:u u F;@u  +e%?$ 3%.AUu 6p;; ,Uu (u H;-@u GUu ]2?Bu KDBKu xu EBu u NBE u OBR u PB_u QBlu RByu SBu NYBu ZBu [aB< u bBI!u hjB)u kB*u [r-U%:u u F;@u +e%b?$ ]3%h".AUu 6P;; ,Uu (u H;-@u ªUu ]2?Bu ATwBAu xBNu yB[u A~B u B u Bu Bu Bu Bu Bu Bu 'B+u B8u BEu BMu -BZu Bgu Btu Bu -U%:u u F;@u  +e%@*?$ >3%Fe.AUu 6p;;,Uu (u H;-@u –Uu ]2?Bu KBKu ;u KBu ;u KBu ;u KBu xu B u ABu Bu Bu 'Bu Bu Bu  B!u B"u B#u 4 B'u  B)u  B*u  -U%:u u F;@u +e%m?$ 3%$.AUu 6P;;,Uu (u H;-@u Uu ]2? Bu  -Bu B u Bu B&u B3u ABtu Bu B u AB%u B&u B'u hBQ0u -U%:u u F;@u  +e%?$ 3%.AUu 6p;;,Uu (u H;-@u =Uu ]2?Bu B u Bu ;u KBUu xu Bu Bu u Bu xu  Bw u '!B u "Bu #Bu '$Bu %Bu &Bu 4'B-u (B:u )BGu '*Bnu +B{u ,B u -B"u .B#u /B$u A0B)u 1B +u 2B,u u 3-U%:u u F;@u +e%?$ 3%-.AUu 6P;;,Uu (u H;-@u 5Uu ]2?Bu 4Bu xu 5Bu 6Bu A7Bu 8B u '9B" u :B/u ;B<u < BIu '= Bpu > B}u ? B!u @B&"u AB@$u BBM%u CBZ&u DBg'u E Bt(u F!B)u G"B*u H#B+u I$B,u J%B-u K&B.u L'B/u M(B0u N)-U%:u u F;@u +e%5?$ 3%p.AUu 6p;;,Uu (u H;-@u 6Uu ]2?*Bu 'O,B'u P-B4u AQ2Bu u R3B u NS9Bu T:Bu NU@B+u VAB8u WBBEu XC/BMu EYDBUu EE0ZEBu EE0[FBu EE0\GB\u EE0]HB u EE0 ^IB u EE0_JB u EE0`KBp!u EE0aLB"u EE0bMB"u EE0cNBw#u EE0dOB$$u EE0ePB$u EE0fQB~%u EE0gRB+&u EE0hSB&u EE0iTB'u EE0jUB2(u EE0kVB(u EE0lWB)u EE0mXB9*u EE0nYB*u EE0oZB+u EE0p[B@,u EE0q\B,u EE0r]B-u EE0s^BG.u EE0t_B.u EE0u`B/u EE0vaBN0u EE0wbB0u xc-U%:u u F;@u  +e%x?$ 3%.AUu 6P;;,Uu (u H;-@u nUu ]2?Bu yqBu zrBu ;u K{sBu xu |tBu } Bu ~B u 'BF#u BS$u B9%u B&u B,'u 4B`+u Bm,u 'B/u E B0u E -U%:u u F;@u +e%t?$ +3%z.AUu 6p;;,Uu (u H;-@u xUu ]2?Bu 4B4u BAu 'Bhu ;u KB u ;u KB u xu Bcu ;u KBu xu B#u 4BWu Bdu NBu Bu NB %u B&u -B"'u -U%:u u F;@u  +e%R?$ #3%X9.AUu 6P;;,Uu (u H;-@u {Uu ]2?Bu 'B'u ;u KBbu ;u KBu xu B" u ABcu Bpu hBu Bu Bu Bu 'B&u B3u NB%u B&u [B-u B.u '-U%:u u F;@u +e%0A?$ Љ3%6|.AUu 6p;;,Uu (u H;-@u Uu ]2?Bu KBKu xu Bu 4Bu Bu [Blu Byu ABu Bu hB/u B< u N-B&u B'u E BD(u E B(u E B)u E  BK*u E  B*u E@ 5  B,u  B-u A-U%:u u F;@u  +e%?$ &3%.AUu 6P;;,Uu (u H;-@u hUu ]2?"Bu B u B u -B u B3u  B@u '#Bgu $Btu %-B|u &B) u E~ 'B u E~ (B!u E~ )B0"u E~ *B"u E~ +B#u E~ ,B7$u E~ -B$u E~ .B%u E~ /B>&u E~ 0B&u E~ 1B'u E~ 2BE(u E~ 3B(u E~ 4B)u E~ 5BL*u E~ 6B*u E~ 7B+u E~ 8BS,u E~ 9B-u E~ :B-u E~ ;BZ.u E~ <B/u E~ =B/u E~ >Ba0u ?-U%:u u F;@u   +e%?$ %3%.AUu 6p;;,Uu (u H;-@u rUu ]2?Bu ADBAu EBIu F-BQu GB^u hHBu AIBu NJBUu LBou 'E6?'OB!u 'E6?'RB$u E6?TB&u 'E6?'WB)u 'E6?'ZB%-u E6?\B?/u E6?^-U%:u u F;@u  +e% ?$ %3%D.AUu 6P;;,Uu (u H;-@u rUu ]2?-Bu 'aB'u bB4u Epc/B<u EpdBu E eBu E fBCu E gBu E hBu E iBJ u E jB u E kB u E lBQ u E mB u E nB u E oBX u E pBu E qBu E rB_u E sB u E tBu E uBfu E vBu E wBu E xBmu E yBu E zBu E  {Btu E  |B!u E  }Bu E  ~B{u E  B(u E Bu E Bu Bu Bu NB!u B"u B$u B%u B&u B+'u B8(u BE)u BR*u [-U%:u u F;@u  +e%L?$ m3%.AUu 6p;;,Uu (u H;-@u Uu ]2?Bu KBKu ;u KBu ;u KBu xu BFu 4 Bz u !B u '"Bu #Bu [$Bu %B#u &B0u 'B=u ;u K(Bxu xu )Bu A*B>$u +BK%u 4,B)u -B*u N.B0u /-U%:u u F;@u +e%?$ 3%.AUu 6P;;,Uu (u H;-@u cUu ]2?Bu 0B u 1Bu 2-B"u 3Bu 4Bu 5Bu ;u K6Bu xu 7Bu 8Bu 9Bu :Bu A;B%u <B&u 4=BB*u >BO+u N?-U%:u u F;@u  +e%d?$ 3%j .AUu 6p;;,Uu (u H;-@u 6Uu ]2?Bu @B u ABu BBu CBtu DB!u 'EBHu FBUu GBb u HBo u IB u JB u KBv u ZLB u MB}u NBu 'OBu PBu QBu RBu ;u KSBu xu TBu ;u KUBu xu VBXu W B)u X B+u ~Y-U%:u u F;@u +e%B?$ 3%HP.AUu 6P;;,Uu (u H;-@u -Uu ]2?Bu ZB u [Bu \B u ]B u ^B u _B u `B u aBu b-Bu lcBZ-u d Bg.u e!Bt/u f"B0u g#-U%:u u F;@u  +e% X?$ T3%&.AUu 6p;;,Uu (u H;-@u ¬Uu ]2?Bu Ah(BAu i)BNu 4j-B u k.B u NE6?Nl4Bu 'E6?'m7Bu 4E6?4n;B8u [E6?[oBB u E6?pDB"u 'E6?'qGB%u rHB&u sIB'u ;u KtJB)*u xu uKB+u u vLB-u xu wMB>/u xO-U%:u u F;@u +e%?$ T3%.AUu 6P;;,Uu (u H;-@u ¡Uu ]2?Bu yP-B u RzQB_u {RBlu '|UB u }VB!u ~WB"u e-U%:u u F;@u  +e%?$ 3%.AUu 6p;; ,Uu (u H;-@u uUu ]2?Bu [lB[u mBhu NsBu tBu uBu vBu u wBu xu xBmu [Bu Bu 'B u O-B "u 8eD ?0UE  DB$u B%u B&u O-B'u t8eTJNt?1TK NtCB&*u B3+u 'BZ.u O-Bg/u 8e:IR?2:S 0C.U%:u u F;@u @+e% ?$ Щ3%[.AUu 6P;;!-Uu (u H;-@u AUu ]2?Bu B u 'B4u BAu B[u O-Bhu 48e(nr 4?3fn r 4B u B u 'B u Bu Bu Blu Byu Bu NB"u B#u B$u B%u u B(u xu B)u [B0u .U%:u u F;@u B+e%c?$ .3%.AUu 6p;;"-Uu (u H;-@u CyUu ]2?Bu 4B4u BAu [B u B u Bu u Bu xu BFu ABu Bu u B "u B#u 'B=&u BJ'u -BR(u B_)u Bl*u .U%:u u F;@u D +e%v?$ 3%|.AUu 6P;;#-Uu (u H;-@u E'Uu ]2? Bu  B u B u B u NBu Bu B u Bu ;u KBTu xu Bu  B)u  B*u  B+u N.U%:u u F;@u F+e%T?$ Ђ3%Z$ .AUu 6p;;$-Uu (u H;-@u GUu ]2?Bu B u !Bu "-Bu #BMu $B u %Bu Z'Btu Z)Bu Z+B(!u ,B!u -B"u .B#u Z0B$u 1B%u Z3B&u Z5BJ(u 6BW)u 4:B-u ;B.u Z=B/u Z?BL1u @.U%:u u F;@u H +e%2, ?$ 3%8g .AUu 6P;;%-Uu (u H;-@u IXUu ]2?Bu NFBNu GB[u ZIBu ZKB u ZMBi u ZOB u ZQBu ZSBwu ZUBu VB~u ZXBu ZZB2u [B?u \BLu ]BYu ;u K^Bu xu _Bu ;u K`BTu xu aBu [hB4&u iBA'u jBN(u ;u KkB*u xu lB,u 4pBB0u qB$1u r.U%:u u F;@u J+e%o ?$ 3% .AUu 6p;;&-Uu (u H;-@u KjUu ]2?8Bu s-Bu tBu EVuBbu EVvBu EVwBu EVxBiu EVyBu EVzBu EV{Bpu EV|Bu EV}Bu EV~Bwu EVB$ u EVB u EVB~ u EVB+ u EVB u EV B u EV B2 u EV B u EV Bu EV B9u EVBu EVBu EVB@u EVBu EVBu EVBGu EVBu EVBu EVBNu EVBu EVBu EVBUu EBu B"u B/u B<u BIu ;u KBu xu  B u !B!u A"BW&u #Bd'u $B(u %B(u &Bk)u 'B*u (B*u )Br+u *B,u +B,u ,By-u -B&.u .B.u /.U%:u u F;@u L +e% ?$ lZ/ SfxDocumentInfo  Tim Hurman .1ض Tim Hurman .1ض uK Info 0 Info 1 Info 2 Info 3 .1tU<Oh+'0 h t 1@@@{ҹ@{ҹ Tim Hurman Tim Hurman0304T0xFFFF - 0xB3FF = 0x4C00F ddd<dd<Times New RomanTimes New RomanTimes New RomanTimes New RomanTimes New Roman HelveticaCourier  2Sunknown @ޅ)䰱Formula StarMath 5.0 SfxDocumentInfo  Tim Hurman .1ض Tim Hurman .1ض uK Info 0 Info 1 Info 2 Info 3 .1w<Oh+'0 h t 1@@@{ҹ@{ҹ Tim Hurman Tim Hurman0304TL(Counter value) over (Counter Frequency) = 65535 over 921583 = 0.071 SecondsF ddd<dd<Times New RomanTimes New RomanTimes New RomanTimes New RomanTimes New Roman HelveticaCourier  2Sunknown @ޅ)䰱Formula StarMath 5.0I VSfxDocumentInfo  Tim Hurman .1ض Tim Hurman .1ض uK Info 0 Info 1 Info 2 Info 3 .1<Oh+'0 h t 1@@@{ҹ@{ҹ Tim Hurman Tim Hurman0304TaTime Delay times Counter frequency = 0.5 times 921583 newline ~~~~~~~~~~~~~Counter value = 460791F ddd<dd<Times New RomanTimes New RomanTimes New RomanTimes New RomanTimes New Roman HelveticaCourier  2Sunknown @ޅ)䰱Formula StarMath 5.0nSfxDocumentInfo  Tim Hurman .1ض Tim Hurman .1ض uK Info 0 Info 1 Info 2 Info 3 .1X<Oh+'0 h t 1@@@{ҹ@{ҹ Tim Hurman Tim Hurman0304T11.059Mhz over 12 = 921583HzF ddd<dd<Times New RomanTimes New RomanTimes New RomanTimes New RomanTimes New Roman HelveticaCourier  2SunknownRoot Entry ®`V=ObjEFFFD685*@ޅ)䰱CompObj<Ole StarBASICSfxWindows<SwNumRulesStandardjObjEFFFD686 #@ޅ)䰱ObjEFFFD687 @ޅ)䰱ObjEFFFD688 @ޅ)䰱persist elements" SfxDocumentInfo  "uBasicManager204DrawingLayer uSfxStyleSheets1 EmbeddedPictures"PicEFFFC642aSummaryInformation(z8SwPageStyleSheets$StarWriterDocument& ZCompObj=Ole persist elements"SfxDocumentInfo uSfxWindowsSummaryInformation(8StarMathDocument"FCompObj=Ole persist elements"!SfxDocumentInfo  uSfxWindowsSummaryInformation("8StarMathDocument"zCompObj$%=Ole persist elements"&(SfxDocumentInfo 'uSfxWindowsSummaryInformation()8StarMathDocument"CompObj+,=Ole persist elements"-/SfxDocumentInfo .uSfxWindowsSummaryInformation(08StarMathDocument"J