USES Crt,Dos; {**** Last Modified: 8/24/98 ****} VAR test:byte; OLDISR : procedure; IRQnumber : integer; temp : byte; flag : WORD; ADDRESS : WORD; { The Base address of the watchdog board. } procedure CtrMode(cntr,mode:byte); var ctrl:byte; begin ctrl := (cntr shl 6) or $30 or (mode shl 1); port[ADDRESS+3] := ctrl; end; procedure LoadCtr(c,val:integer); begin port[ADDRESS+c] := lo(val); port[ADDRESS+c] := hi(val); end; procedure sendEOI; var error : integer; begin if (IRQnumber <= 7) then port[$20] := $20 else begin port[$20] := $20; port[$A0] := $20; end; end; procedure setflag;interrupt; {interrupt handler} begin flag := 1; test := port[ADDRESS+4]; sendEOI; (* clear the board's interrupt bit *) end; function initirq : integer; var intmask : integer; oldmask : integer; error : integer; begin if (IRQnumber <= 7) then begin getintvec(IRQnumber + 8, @oldisr); setintvec(IRQnumber + 8, addr(setflag)); oldmask := port[$21]; intmask := oldmask AND (NOT(1 SHL IRQnumber)); port[$21] := intmask; end else begin getintvec(IRQnumber + $70 - 8, @oldisr); setintvec(IRQnumber + $70 - 8, addr(setflag)); oldmask := port[$A1]; intmask := oldmask AND (NOT(1 SHL (IRQnumber - 8))); port[$A1] := intmask; end; initirq := oldmask; end; procedure resetirq; var intmask : integer; error : integer; begin if (IRQnumber <= 7) then begin intmask := port[$21]; intmask := intmask OR (1 SHL IRQnumber); port[$21] := intmask; setintvec(IRQnumber + 8, @oldisr); end else begin intmask := port[$A1]; intmask := intmask OR (1 SHL (IRQnumber - 8)); port[$A1] := intmask; setintvec(IRQnumber + $70 - 8, @oldisr); end; end; function AskForBaseAddress(OldOne : String) : Word; const Msg : string[4] = '0'; var NewOne, Success, Dummy, Error : Word; AddrInputPosX, AddrInputPosY : Word; begin if (OldOne = 'OLD') then OldOne := Msg; WriteLn('Please enter the Base Address (0000-FFFF) for your card (in hex)'); WriteLn('or press ENTER for ', OldOne, '. '); Write('>'); AddrInputPosX := WhereX; AddrInputPosY := WhereY; repeat GotoXY(AddrInputPosX, AddrInputPosY); ClrEol; Readln(Msg); Val('$' + Msg, NewOne, Error); if (error=0) then begin Success := 1; Dummy := NewOne; end else if (Msg = '') then begin GotoXY(AddrInputPosX, AddrInputPosY); WriteLn(OldOne); Msg := OldOne; Success := 1; Val('$' + Msg, Dummy, Error); end; until (Success = 1); AskForBaseAddress := Dummy; end; { end of AskForBaseAddress } function AskForBaseIRQ(OldOne : String) : Word; const Msg : string[4] = '0'; var NewOne, Success, Dummy, Error : Word; AddrInputPosX, AddrInputPosY : Word; begin if (OldOne = 'OLD') then OldOne := Msg; WriteLn('Please enter the IRQ for your card (in hex)'); WriteLn('or press ENTER for ', OldOne, '. '); Write('>'); AddrInputPosX := WhereX; AddrInputPosY := WhereY; repeat GotoXY(AddrInputPosX, AddrInputPosY); ClrEol; Readln(Msg); Val('$' + Msg, NewOne, Error); if (error=0) then begin Success := 1; Dummy := NewOne; end else if (Msg = '') then begin GotoXY(AddrInputPosX, AddrInputPosY); WriteLn(OldOne); Msg := OldOne; Success := 1; Val('$' + Msg, Dummy, Error); end; until (Success = 1); AskForBaseIRQ := Dummy; end; { end of AskForBaseIRQ } { ****************************************************************************** PROCEDURE set_counter Parameters: None Returns: None Purpose: This procedure performs the setup operations on the 82C54 counter/ timer chip. Calls: None Uses: ADDRESS Constant defined at top of program. ****************************************************************************** } PROCEDURE set_counter; VAR control_word : BYTE; BEGIN temp:=port[ADDRESS+7]; { disable counter functions} CtrMode(2,0); { set counter 2 to mode 0} port[ADDRESS+7]:=0; { enable counters} temp:=port[ADDRESS+7]; { disable counters} port[ADDRESS+6]:=0; { enable buzzer} port[ADDRESS+$0C]:=0; { select low clock rate} temp:=port[ADDRESS+$0D];{ disable opto reset} temp:=port[ADDRESS+$0E];{ disable opto reset} temp:=port[ADDRESS+$0F];{ disable program outputs} CtrMode(0,3); { program counter 0 for mode 3} LoadCtr(0,-1); { -1 is full load value, long reset and high granular} CtrMode(1,2); { program counter 1 for mode 2} LoadCtr(1,$10); { load counter 1 with 10 hex} CtrMode(2,1); { set counter 2 to mode 1} {LoadCtr(2,-1);} {Note: Not loading counter 2 creates an infinite reset duration} {Set the reset duration by loading a value in counter 2 and changing} {counter 2 to mode 2} END; { End set_counter } VAR read_back : BYTE; loop : WORD; ch : CHAR; aborted : boolean; BEGIN clrscr; flag := 0; test := $FF; ADDRESS := AskForBaseAddress('FCA0'); IRQNumber := AskForBaseIRQ('A'); clrscr; writeln('Pascal Sample #1: Use Of Counter/Timer Chip with Watchdog'); writeln('This program demonstrates how to program the 82C54 counter/timer'); writeln('chip on the Watchdog Timer board. A keystroke will stop the program.'); writeln; writeln('Press any key to start.'); ch := readkey; { Grab keystroke. } set_counter; { programs counters } temp:=port[ADDRESS+4]; {clear any potentially pending IRQs} initirq; {initialize the irq} port[ADDRESS+7] := 0; { Starts counters counting } for loop := 1 to 1000 do begin CtrMode(1,2); LoadCtr(1,$10); {prompt counter 1--don't need to prompt 0} GotoXY(1, 8); Writeln('Updating counter 1. Loop number : ', loop); end; writeln; writeln('Waiting for timeout . . .'); aborted := false; repeat aborted := KeyPressed; until ((aborted) OR ((test AND 0) = 0));{ OR (flag)); { check for bit 0 } resetirq; writeln; if (aborted) then writeln('Timeout aborted!') else writeln('Watchdog timed out successfully.'); temp:=port[ADDRESS+7]; {disable counters} port[ADDRESS+5]:=0; {turn off buzzer} END.