home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
c
/
caty16.zip
/
CATYCOMM.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-09-07
|
16KB
|
400 lines
UNIT CATYCOMM; (* Interrupt driven Serial Comm - D. J. Wilke 1/12/91 *)
INTERFACE
USES CRT, DOS, CATYGLO, CATYUTIL, CATYDISP;
PROCEDURE EnableInterrupts;
PROCEDURE CommExitProc;
PROCEDURE SetupSerialPort(Rate : WORD; ComPort : INTEGER;
ComVec : WORD; ComBase,IRQM : INTEGER; Fun : CHAR);
FUNCTION RInStat : Boolean;
FUNCTION TInStat : Boolean;
PROCEDURE FlushRBuffer;
PROCEDURE FlushTBuffer;
FUNCTION RInChar : Char;
FUNCTION TInChar : Char;
PROCEDURE OutChar(Ch : Char; ComBase : INTEGER);
PROCEDURE NoComm;
PROCEDURE BadEcho;
PROCEDURE SendTString(TStr : String86);
PROCEDURE SendRString(Inst : STRING5; SUS : INTEGER);
PROCEDURE WhatWasThat(Param : String5; Col,Row : INTEGER);
PROCEDURE CatSend(Param : String5; StatusUpdateSize : INTEGER);
PROCEDURE TurnCatOn;
PROCEDURE TurnCatOff;
IMPLEMENTATION
USES CATYINST;
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE EnableInterrupts;
BEGIN
INLINE($FB); (* Int Service Routine *)
END; (* EnableInterrupts *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE RIncoming(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : Word);
INTERRUPT;
VAR
RBR : INTEGER;
BEGIN
EnableInterrupts; (* Enable ints during ISR: *)
RBR := RComBase; (* 8250 Receive Buffer Reg *)
IF RLastSaved >= 1023 THEN (* Make 1K circ buffer *)
RLastSaved := 0
ELSE Inc(RLastSaved);
RBuffer[RLastSaved] := Char(Port[RBR]); (* Read incoming character *)
Port[OCW2] := $20; (* Send EOI byte to 8259 *)
END; (* RIncoming *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE TIncoming(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : Word);
INTERRUPT;
VAR
RBR : INTEGER;
BEGIN
EnableInterrupts; (* Enable ints during ISR: *)
RBR := TComBase; (* 8250 Receive Buffer Reg *)
IF TLastSaved >= 1023 THEN (* Make 1K circ buffer *)
TLastSaved := 0
ELSE Inc(TLastSaved);
TBuffer[TLastSaved] := Char(Port[RBR]); (* Read incoming character *)
Port[OCW2] := $20; (* Send EOI byte to 8259 *)
END; (* TIncoming *)
(*═══════════════════════════════════════════════════════════════════════*)
{$F+}
PROCEDURE CommExitProc;
VAR
ComBase : WORD;
RBR,IER,
IRQM,MCR : INTEGER;
BEGIN
ComBase := RComBase;
IRQM := RIRQM;
RBR := ComBase; (* 8250 Receive Buffer Reg *)
IER := ComBase + 1; (* 8250 Int Enable Reg *)
MCR := ComBase + 4; (* 8250 Modem Control Reg *)
Port[IER] := 0; (* Disable ints at 8250 *)
Port[OCW1] := Port[OCW1] OR IRQM; (* Disable IRQ_ at 8259 *)
Port[MCR] := 0; (* Bring the comm line down *)
ComBase := TComBase;
IRQM := TIRQM;
RBR := ComBase; (* 8250 Receive Buffer Reg *)
IER := ComBase + 1; (* 8250 Int Enable Reg *)
MCR := ComBase + 4; (* 8250 Modem Control Reg *)
Port[IER] := 0; (* Disable ints at 8250 *)
Port[OCW1] := Port[OCW1] OR IRQM; (* Disable IRQ_ at 8259 *)
Port[MCR] := 0; (* Bring the comm line down *)
SETINTVEC(RComVec,OldRComVec); (* Restore prev saved Rvect *)
IF TNC THEN
SETINTVEC(TComVec,OldTComVec); (* Restore prev saved Tvect *)
END; (* CommExitProc *)
{$F-}
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE SetupSerialPort(Rate : WORD;
ComPort : INTEGER;
ComVec : WORD;
ComBase,IRQM : INTEGER;
Fun : CHAR);
VAR
RBR,THR,DLL,DLM,
IER,IIR,LCR,MCR,
LSR,MSR : INTEGER;
Divisor : WORD;
BEGIN
RBR := ComBase; (* 8250 Receive Buffer Reg *)
THR := ComBase; (* 8250 Transm Holding Reg *)
DLL := ComBase; (* 8250 Divisor Latch LSB *)
DLM := ComBase +1; (* 8250 Divisor Latch MSB *)
IER := ComBase +1; (* 8250 Int Enable Reg *)
IIR := ComBase +2; (* 8250 Int Ident Reg *)
LCR := ComBase +3; (* 8250 Line Control Reg *)
MCR := ComBase +4; (* 8250 Modem Control Reg *)
LSR := ComBase +5; (* 8250 Line Status Reg *)
MSR := ComBase +6; (* 8250 Modem Status Reg *)
Divisor := Rate; (* Baud rate *)
RLastRead := 0; (* Init circ buf pointers *)
TLastRead := 0;
RLastSaved := 0;
TLastSaved := 0;
Port[IER] := 0; (* Disable ints during setup *)
IF Fun = 'R' THEN
GETINTVEC(RComVec,OldRComVec); (* Save old radio IRQ vector *)
IF Fun = 'T' THEN
GETINTVEC(TComVec,OldTComVec); (* Save old TNC IRQ vector *)
ExitProc := @CommExitProc; (* Hook exit proc into chain *)
IF Fun = 'R' THEN
SETINTVEC(RComVec,@RIncoming); (* Radio ISR addr in vec tbl *)
IF Fun = 'T' THEN
SETINTVEC(TComVec,@TIncoming); (* TNC ISR addr in vec tbl *)
Port[LCR] := Port[LCR] OR DLAB; (* Set up 8250 for baud rate *)
Port[DLL] := Lo(Divisor); (* Set baud rate divisor *)
Port[DLM] := Hi(Divisor);
IF Fun = 'R' THEN
Port[LCR] := RDataBits OR RStopBits; (* Set Radio word len/stop *)
IF Fun = 'T' THEN
Port[LCR] := TDataBits OR TStopBits; (* Set TNC word len/stop *)
Port[LCR] := Port[LCR] OR RParity; (* Set Radio parity *)
IF TNC THEN
Port[LCR] := Port[LCR] OR TParity; (* Set TNC parity *)
Port[MCR] := DTR OR RTS OR OUT2; (* Enable DTR/RTS/adapter *)
Port[OCW1] := Port[OCW1] AND (NOT IRQM); (* Turn on 8259 IRQ_ ints *)
Clearit := Port[RBR]; (* Clear garbage from RBR *)
Clearit := Port[LSR]; (* Clear garbage from LSR *)
Port[IER] := $01; (* Enable int on rcd char *)
END; (* SetupSerialPort *)
(*═══════════════════════════════════════════════════════════════════════*)
FUNCTION RInStat : Boolean;
BEGIN
IF RLastSaved <> RLastRead THEN (* Radio buffer status flag *)
RInStat := True
ELSE RInStat := False;
END; (* FUNCTION RInStat *)
(*═══════════════════════════════════════════════════════════════════════*)
FUNCTION TInStat : Boolean;
BEGIN
IF TLastSaved <> TLastRead THEN (* TNC buffer status flag *)
TInStat := True
ELSE TInStat := False;
END; (* FUNCTION TInStat *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE FlushRBuffer;
VAR
RBR : INTEGER;
BEGIN
RBR := RComBase; (* 8250 Receive Buffer Reg *)
RLastRead := 0;
RLastSaved := 0;
Clearit := Port[RBR]; (* Clear garbage from RBR *)
FILLCHAR(RBuffer,SIZEOF(RBuffer),0);
END; (* FlushRBuffer *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE FlushTBuffer;
VAR
RBR : INTEGER;
BEGIN
RBR := TComBase; (* 8250 Receive Buffer Reg *)
TLastRead := 0;
TLastSaved := 0;
Clearit := Port[RBR]; (* Clear garbage from RBR *)
FILLCHAR(TBuffer,SIZEOF(TBuffer),0);
END; (* FlushTBuffer *)
(*═══════════════════════════════════════════════════════════════════════*)
FUNCTION RInChar : Char; (* Nxt chr fr radio buf *)
BEGIN
IF RLastRead >= 1023 THEN (* End of buffer? *)
RLastRead := 0 (* Yes, wrap it *)
ELSE RLastRead := Succ(RLastRead); (* No, bump pointer *)
RInChar := RBuffer[RLastRead]; (* Return w/char *)
END; (* RInChar *)
(*═══════════════════════════════════════════════════════════════════════*)
FUNCTION TInChar : Char; (* Nxt chr fr TNC buf *)
BEGIN
IF TLastRead >= 1023 THEN (* End of buffer? *)
TLastRead := 0 (* Yes, wrap it *)
ELSE TLastRead := Succ(TLastRead); (* No, bump pointer *)
TInChar := TBuffer[TLastRead]; (* Return w/char *)
END; (* TInChar *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE OutChar(Ch : Char; ComBase : INTEGER);(* Send chr to comm port *)
VAR
THR : INTEGER;
BEGIN
THR := ComBase; (* 8250 xmit Hld Reg *)
Port[THR] := Byte(Ch) (* Put char into THR *)
END; (* OutChar *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE NoComm;
(* 'UUUUU' means input buffer did not receive data from radio *)
BEGIN;
WINDOW(2,6,79,23);
ErrorAlarm(ComErr,0,7); (* Issue com port error *)
Warble(3000,2400);
FlushRBuffer; (* Clear buffer of trash *)
PromptLine('M'); (* Put up Main Menu msg *)
WINDOW(2,6,79,23);
CLRSCR;
PromptLine('K'); (* Put up FK line *)
ClockFlag := TRUE; (* Reinstate RTC *)
MainMenu;
END; (* NoComm *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE BadEcho;
(* Got invalid or no Echo from 767, show command error *)
BEGIN;
WINDOW(2,6,79,23);
ErrorAlarm(CmdErr,0,7); (* Issue command error *)
Warble(3000,2400);
GOTOXY(31,9); WRITE('Inst:');
GOTOXY(31,10); WRITE('Echo:');
WhatWasThat(Inst,38,9);
WhatWasThat(Echo,38,10);
FlushRBuffer; (* Clear buffer of trash *)
PromptLine('M'); (* Put up Main Menu msg *)
WINDOW(2,6,79,23);
CLRSCR;
PromptLine('K'); (* Put up FK line *)
ClockFlag := TRUE; (* Reinstate RTC *)
MainMenu;
END; (* BadEcho *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE SendTString(TStr : String86);
(* Send command to TNC w/intercharacter delay *)
BEGIN
FOR Index := 1 to LENGTH(TStr) DO BEGIN
OutChar(TStr[Index],TComBase);
DELAY(TICD); (* Intercharacter delay *)
END;
OutChar(CHR(13),TComBase);
Peep(1000);
END; (* SendTString *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE SendRString(Inst : STRING5; SUS : INTEGER);
(* Send command to RADIO w/intercharacter and end-of-string delays *)
VAR
RESD : INTEGER;
BEGIN
RESD := SUS * 15;
ScreenWrite('Inst'+CHR(16)+' ',69,4,31); (* Show Inst activity *)
FOR Index := 1 to LENGTH(Inst) DO BEGIN
OutChar(Inst[Index],RComBase);
DELAY(RICD); (* Intercharacter delay *)
END;
ScreenWrite(' ',69,4,31);
DELAY(RESD); (* Yaesu takes 5 to 20 ms *)
END; (* SendRString *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE WhatWasThat(Param : String5; Col,Row : INTEGER);
(* Display Instruction/Echo as sent from computer/FT-767 *)
VAR
MSN,Result : INTEGER;
BEGIN (* WhatWasThat *)
TEXTCOLOR(SFG); TEXTBACKGROUND(DBG); (* Returned status colors *)
GOTOXY(Col,Row);
FOR Index := 1 TO LENGTH(Param) DO BEGIN
VAL(Param[Index],MSN,Result);
WriteHex(ORD(Param[Index]));
WRITE(' '); (* Disp as BCD Hex values *)
END;
END; (* WhatWasThat *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE CatSend(Param : String5; StatusUpdateSize : INTEGER);
(* Send Instruction string to 767, get Echo & send ACKnowledge *)
VAR
Temp : STRING[86];
Ch : STRING;
Try : INTEGER;
BEGIN (* CatSend *)
FlushRBuffer;
Inst := Param; (* Inform Global variable *)
Echo := 'UUUUU'; (* Flush last echo *)
ClockFlag := FALSE; (* No clock during Comm *)
EchoValid := FALSE;
Ch := ' ';
Try := 0;
IF Main THEN
ScreenWrite(' ',71,3,31); (* Show clock suspense *)
IF Test OR OneWay THEN BEGIN
FOR Index := 1 TO 5 DO (* All are 5 bytes long *)
Echo[Index] := Inst[Index]; (* Simulate 767 echo *)
EchoValid := TRUE;
END (* IF Test *)
ELSE REPEAT
Echo := 'UUUUU'; (* Flush last echo *)
SendRString(Param,15); (* Send Instruction to 767 *)
FOR Index := 1 TO 5 DO (* Get 5 char echo fr 767 *)
IF RInStat THEN Echo[Index] := RInChar; (* The REAL echo *)
ScreenWrite(' ',74,4,31); (* To clean up *)
IF Echo = Inst THEN BEGIN
ScreenWrite(CHR(17)+'Echo',74,4,31); (* Show Echo activity *)
DELAY(25); (* To see activity *)
EchoValid := TRUE; (* Everything OK *)
END (* IF Echo *)
ELSE BEGIN (* Everything's not OK *)
Try := Try +1; (* Bump attempt counter *)
STR(Try:2,Ch);
ScreenWrite('Try'+Ch,74,4,31); (* Show Try # *)
FlushRBuffer;
DELAY(25); (* To see activity *)
END; (* ELSE *)
UNTIL (EchoValid) OR (Try >= 3); (* Try three times... *)
IF NOT EchoValid THEN
IF Echo = 'UUUUU' THEN NoComm (* Check comm port *)
ELSE BadEcho; (* Echo is corrupted *)
(* If Test was TRUE, UPDATE.DAT had provided a simulated Update *)
IF NOT Test THEN BEGIN
(* Echo was a match, send ACK string *)
SendRString(AckString,StatusUpdateSize); (* 767 executes the cmd *)
FOR Index := 1 TO StatusUpdateSize DO
Lifo[Index] := RInChar; (* Get real Update fr 767 *)
(* Update stream from 767 is sent last byte first *)
Temp := Fifo(Lifo); (* Convert LIFO to FIFO *)
Update := Temp;
END; (* IF NOT Test *)
ClockFlag := TRUE; (* Reinstate RTC *)
END; (* CatSend *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE TurnCatOn; (* Activate Computer Aided Tuning system *)
BEGIN (* TurnCatOn *)
CatSend(CatOn,86); (* Turn on the CAT *)
ScreenWrite('CAT: ',65,4,30); (* Update status panel *)
END; (* TurnCatOn *)
(*═══════════════════════════════════════════════════════════════════════*)
PROCEDURE TurnCatOff; (* Deactivate Computer Aided Tuning system *)
BEGIN (* TurnCatOff *)
CatSend(CatOff,86); (* Put out the CAT *)
ScreenWrite('CAT: ',65,4,30); (* Update status panel *)
ScreenWrite(' Inactive ',69,4,31); (* Update status panel *)
END; (* TurnCatOff *)
END. (* UNIT CATYCOMM *)