home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
TPKERMIT
/
PACKET.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-03-25
|
13KB
|
288 lines
(* +FILE+ PACKET.PASMSCPM *)
(* =============================================================== *)
(* SENDPACKET -This procedure sends the SendData packet . *)
(* 1. The COUNT sent includes SEQ,PACKETTYPE,and CHECKSUM *)
(* i.e. it is 3 larger than the OutCount or *)
(* if CheckType = 2 or 3 then COUNT is 4 or 5 larger. *)
(* 2. The COUNT and SEQ and CHECKSUM values are offset by *)
(* 32 decimal (20hex) to make it a printable ASCII char.*)
(* 3. The CHECKSUM are calculated on the ASCII value of *)
(* the printable characters. *)
(* *)
(* Assumptions: *)
(* The following Global variables must be correctly set *)
(* before calling this procedure . *)
(* 1. OutDataCount - an integer-byte count of data characters.*)
(* 2. OUTSEQ - an integer-byte count of sequence number. *)
(* 3. OUTPACKETTYPE - an character of type . *)
(* 4. SendData - a character array of data to be sent. *)
(* =============================================================== *)
PROCEDURE SENDPACKET ;
VAR
I,SUM,Checkbytes : INTEGER ;
achar : byte ;
SOHecho : boolean ;
BEGIN (* SENDPACKET procedure *)
(* SOHecho := Not (LocalEcho or (Series1 and WaitXon)) ; *)
SOHecho := Not (LocalEcho or Series1) ;
achar := 0 ;
If WaitXon then
While achar <> XON do if Readchar(achar) then
else achar := xon ;
WaitXon := XonXoff ;
While RecvChar(achar) do ; (* throw away all previous incoming data *)
Delay(50);
SUM := 0 ;
CRC := 0 ;
Checkbytes := 1 ;
If (OutPacketType = ord('S')) or (OutPacketType = ord('I')) or
(InpacketType = ord('S')) or (InpacketType = ord('I')) or
(InpacketType = ord('R')) then (* leave Checkbytes := 1 *)
else
If Checktype = ord('2') then Checkbytes := 2 else
If Checktype = ord('3') then Checkbytes := 3 ;
SendChar(StartChar) ; (* SOH *)
If SOHecho then (* wait for SOH to be echoed back *)
While achar <> StartChar do
if Not Readchar(achar) then achar:=StartChar ;
OutCount := OutDataCount + 2 + Checkbytes ;
SendChar(OutCount + $20) ; (* COUNT *)
SUM := SUM + OutCount + $20 ;
CRCheck(OutCount+$20) ;
SendChar(OUTSEQ+$20) ; (* SEQ *)
SUM := SUM + OUTSEQ + $20;
CRCheck(OUTSEQ+$20);
SendChar(OUTPACKETTYPE) ; (* TYPE *)
SUM := SUM + ORD(OUTPACKETTYPE) ;
CRCheck(Ord(OutpacketType));
IF OutDataCount > 0 THEN
FOR I := 1 TO OutDataCount DO
BEGIN (* Send Data *)
SendChar(SendData[I]) ; (* DATA *)
SUM := SUM + SendData[I] ;
CRCheck(SendData[I]);
END ; (* Send Data *)
If Checkbytes = 1 then
Begin (* one Checksum *)
CHECKSUM := (SUM + (SUM AND $C0) DIV $40 ) AND $3F ;
SendChar(CHECKSUM+$20); (* CHECKSUM *)
End (* one Checksum *)
else
If Checkbytes = 2 then
Begin (* two Checksum *)
Checksum := (Sum div $40) and $3F ; (* Bit 11 - 6 *)
SendChar(Checksum+$20) ;
Checksum := Sum and $3F ; (* Bit 5 - 0 *)
SendChar(Checksum+$20) ;
End (* two Checksum *)
else
If Checkbytes = 3 then
Begin (* CRC *)
SendChar((CRC shr 12 ) and $0F + $20) ;
SendChar((CRC shr 6 ) and $3F + $20) ;
SendChar((CRC ) and $3F + $20) ;
End ; (* CRC *)
SendChar(EndChar); (* Cr *)
If NumPad > 0 then
For I := 1 to NumPad do SendChar(PadChar); (* Padding *)
END ; (* SENDPACKET procedure *)
(* =============================================================== *)
(* RECVPACKET -This Function returns TRUE if it successfully *)
(* recieved a packet and FALSE if it had an error. *)
(* Side Effects: *)
(* The following global variables will be set. *)
(* 1. InDataCount - an integer value of the msg char count. *)
(* 2. INSEQ - an integer value of the sequence count. *)
(* 3. TYPE - a character of message type (Y,N,D,F,etc) *)
(* 4. RecvData - an array of data bytes to be sent. *)
(* *)
(* =============================================================== *)
FUNCTION RECVPACKET : BOOLEAN ;
VAR
I,SUM,RESENDS : INTEGER ;
INCHAR,Checkbytes : Byte ;
dummy : Boolean ;
LABEL EXIT ;
BEGIN (* RECVPACKET procedure *)
RECVPACKET := false ; (* assume false until proven otherwise *)
If GotSOH then begin Inchar := StartChar; GotSOH := false; end
else Inchar := $20 ;
While Inchar <> StartChar Do
If Readchar(Inchar) then (* SOH *)
else goto exit ;
SUM := 0 ;
CRC := 0 ;
If not ReadChar (InCount) then goto exit ; (* COUNT *)
SUM := SUM + InCount ;
CRCheck(InCount) ;
InCount := InCount - $20 ; (* To absolute value *)
if not ReadChar (INSEQ) then goto exit ; (* SEQ *)
SUM := SUM + INSEQ ;
CRCheck(INSEQ) ;
INSEQ := INSEQ - $20 ;
If not ReadChar (INPACKETTYPE ) then goto exit ; (* TYPE *)
SUM := SUM + INPACKETTYPE ;
CRCheck(InPacketType);
Checkbytes := 1 ;
If (OutPacketType = ord('S')) or
(InpacketType = ord('S')) or
(InpacketType = ord('R')) then (* leave Checkbytes := 1 *)
else
If Checktype = ord('2') then Checkbytes := 2 else
If Checktype = ord('3') then Checkbytes := 3 ;
InDataCount := InCount - 2 - Checkbytes ;
IF InDataCount > 0 THEN
FOR I := 1 TO InDataCount DO
BEGIN (* Recv Data *)
If ReadChar (RecvData[I]) then (* DATA *)
Begin (* checksum and CRC *)
SUM := SUM + RecvData[I] ;
CRCheck(RecvData[I]);
End (* checksum and CRC *)
else
goto exit ;
END ; (* Revc Data *)
RECVPACKET := True ; (* Assume Ok until check fails *)
If Checkbytes = 1 then
Begin (* one char Checksum *)
CHECKSUM := (SUM + (SUM AND $C0) DIV $40 ) AND $3F ;
If ReadChar (INCHAR) then
IF INCHAR <> CHECKSUM+$20 THEN RECVPACKET := FALSE ;
End (* one char Checksum *)
else
If Checkbytes = 2 then
Begin (* two char Checksum *)
Checksum := (Sum div $40) and $3F ;
If ReadChar(Inchar) then
If Inchar <> Checksum+$20 then RECVPACKET := false ;
Checksum := Sum and $3F ;
If ReadChar(Inchar) then
If Inchar <> Checksum+$20 then RECVPACKET := false ;
End (* two char Checksum *)
else
If Checkbytes = 3 then
Begin (* CRC char Checksum *)
Checksum := (CRC shr 12) and $0F ;
If ReadChar(Inchar) then
(* If Inchar <> Checksum+$20 then
Writeln('CRC1 ',Inchar,' ',checksum+$20); *)
If Inchar <> Checksum+$20 then RECVPACKET := false ;
Checksum := (CRC shr 6 ) and $3F ;
If ReadChar(Inchar) then
(* If Inchar <> Checksum+$20 then
Writeln('CRC2 ',Inchar,' ',checksum+$20); *)
If Inchar <> Checksum+$20 then RECVPACKET := false ;
Checksum := (CRC ) and $3F ;
If ReadChar(Inchar) then
(* If Inchar <> Checksum+$20 then
Writeln('CRC3 ',Inchar,' ',checksum+$20); *)
If Inchar <> Checksum+$20 then RECVPACKET := false ;
End; (* CRC char Checksum *)
Exit:
END ; (* RECVPACKET procedure *)
(* =============================================================== *)
(* RESENDIT - This procedure RESENDS the packet if it gets a nak *)
(* It calls itself recursively upto the number of times *)
(* specified in the intial parameter list. *)
(* Side Effects - If it fails then the STATE in the message is set *)
(* to 'A' which means ABORT . *)
(* - Global variable RetryCount is incremented *)
(* =============================================================== *)
PROCEDURE RESENDIT ( RETRIES : INTEGER ) ;
BEGIN (* RESENDIT procedure *)
RetryCount := RetryCount + 1 ;
IF RETRIES > 0 THEN
BEGIN (* Try again *)
SENDPACKET ;
IF RECVPACKET THEN
IF INPACKETTYPE = ord('Y') THEN
ELSE
IF INPACKETTYPE = ord('N') THEN RESENDIT(RETRIES-1)
ELSE STATE := A
ELSE STATE := A ;
END (* Try again *)
ELSE STATE := A ; (* Retries failed - ABORT *)
END ; (* RESENDIT procedure *)
(* ------------------------------------------------------------ *)
(* SendPacketType - Procedure will send a packet of the *)
(* type specified in the Character parameter. *)
(* i.e. SendPacketType('Y') an ACK packet *)
(* SendPacketType('N') an NAK packet *)
(* ------------------------------------------------------------ *)
PROCEDURE SendPacketType (PacketType : char);
BEGIN (* SEND ACK or NAK or B or Z *)
OutDataCount := 0 ;
IF PacketType <> 'N' THEN OUTSEQ := OUTSEQ + 1 ;
IF OUTSEQ >= 64 THEN OUTSEQ := 0;
OUTPACKETTYPE := Ord(PacketType) ;
SENDPACKET ;
END ; (* SEND ACK or NAK or B or Z *)
(* ------------------------------------------------------------ *)
PROCEDURE PutInitPacket ;
Begin (* Put Parameters into Init Packet *)
OutDataCount := 9 ;
OUTSEQ := 0 ;
(* The values are tranformed by adding hex 20 to *)
(* the true value, making the value a printable char *)
SendData[1] := PacketSize+ $20 ; (* Buffsize *)
SendData[2] := Timeout + $20 ; (* Time out sec *)
SendData[3] := NumPad + $20 ; (* Num padchars *)
SendData[4] := PadChar + $20 ; (* Pad char *)
SendData[5] := EndChar + $20 ; (* EOL char *)
SendData[6] := CntrlQuote ; (* Quote character *)
SendData[7] := Bit8Quote ; (* Quote character *)
SendData[8] := CheckType ; (* Check Type *)
SendData[9] := RepChar ; (* Repeat Character *)
IF Bit8Quote = $00 then OutDataCount := 6 (* Don't send bit8_quote *)
else
If CheckType = $00 then OutDataCount := 7
else
If RepChar = $00 then OutDataCount := 8 ;
End ; (* Put Parameters into Init Packet *)
(* ------------------------------------------------------------ *)
PROCEDURE GetInitPacket ;
Begin (* Get init parameters *)
IF InDataCount >= 1 then PacketSize := RecvData[1]-$20 ;
IF InDataCount >= 2 then TimeOut := RecvData[2]-$20 ;
IF InDataCount >= 3 then NumPad := RecvData[3]-$20 ;
IF InDataCount >= 4 then PadChar := RecvData[4]-$20 ;
IF InDataCount >= 5 then EndChar := RecvData[5]-$20 ;
IF InDataCount >= 6 then CntrlQuote := RecvData[6] ;
IF InDataCount >= 7 then
Begin (* Validate bit8Quote *)
Bit8Quote := RecvData[7] ;
If RecvData[7] = ord('Y') then Bit8Quote := ord('&') ;
If Not (chr(Bit8Quote) in [']'..'?','`'..'~'])
then Bit8Quote := 0 ;
End (* Validate bit8Quote *)
else Bit8Quote := $00 ;
IF (InDataCount >= 8) and (chr(RecvData[8]) in ['1','2','3'] )
then CheckType := RecvData[8]
else CheckType := ord('1') ;
IF InDataCount >= 9 then
If chr(RecvData[9]) in [']'..'?','`'..'~']
then RepChar := RecvData[9]
else RepChar := $00
else RepChar := $00 ;
End ; (* Get init parameters *)
(* ------------------------------------------------------------ *)