(***************************************************************************** * SAMPLE1.PAS : INTERRUPT OPERATION * * * * This is a demonstration program to be used with the CTR-5 Counter * * timer board. The program will set up all five counters to count down * * from a different level, then use interrupts to read the count at a given * * interval. The results are then displayed on the screen. Note that this * * program uses segments, which should not be used by anything else. For * * instance, this program as is, cannot be run in the Turbo C desktop, or * * the program will lock up the system. * * * * The board should be set as follows: * * -- IRQ5 is used for interrupts * * -- On board clock set to 1 MHz * * -- An external jumper from pin 1 to pin 30. * * -- An external jumper from pin 11 to pin 2. * * * * LAST MODIFICATION: 2/5/98 * * * *****************************************************************************) program sample1; {$L ctr5drv} {$F+} USES crt; TYPE param_array = array[1..10] of integer; dat_array = array[1..100] of integer; (* These variable MUST be declared as global. They are the ones whose offsets are passed to the CTR5DRVC routine. If they are not global then the driver will not find their segment. *) VAR status,task :integer; params :param_array; buf :dat_array; procedure ctr5drv(t_off:word;p_off:word;st_off:word);external; 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 } (***************************************************************************** * PROCEDURE: call_driver -- local routine * * * * PURPOSE: Performs the call to the driver package. * * * * INPUT: None. * * * * CALLS: ctr5drv - entry point to driver package. * * * *****************************************************************************) procedure call_driver; var t_off,p_off,st_off :word; begin (* this section extracts the offset of the parameters that we will pass to the assembly driver *) t_off := ofs(task); (* offset of task number *) p_off := ofs(params[1]); (* offset of param list *) st_off := ofs(status); (* offset of status code *) status := 0; ctr5drv(t_off,p_off,st_off); (* call the driver *) (* this section checks for an error code *) if status > 0 then begin WriteLn('A status error code of ',status,' was detected.'); WriteLn('Program terminated.'); end; end; (* end call_driver *) (***************************************************************************** * PROCEDURE: setup -- local routine * * * * PURPOSE: Sets up the driver and counter board. * * * * INPUT: None. * * * * CALLS: call_driver - entry point to driver package. * * * *****************************************************************************) procedure setup(Address:word); var I :integer; begin (* initialize the board *) params[1] := Address; (* assign the Base Address *) params[2] := 1; (* FOUT divider ratio = 1 *) params[3] := 15; (* FOUT source = F5 *) params[4] := 0; (* counter 2 compare disabled *) params[5] := 0; (* counter 1 compare disabled *) params[6] := 0; (* disable time of day *) task := 0; call_driver; (* call driver *) if status > 0 then exit; (* if status > 0 then error *) for I := 1 to 5 do (* set up each counter *) begin params[1] := I; (* counter number *) params[2] := 0; (* no gating required *) params[3] := 0; (* positive edge counting *) params[4] := 11; (* count source = F1 *) params[5] := 0; (* disable special gate *) params[6] := 0; (* reload from load *) params[7] := 1; (* count repetitively *) params[8] := 0; (* count binary *) params[9] := 0; (* count down *) params[10]:= 2; (* terminal count toggle *) task := 1; call_driver; (* call driver *) if status > 0 then exit; (* if status > 0 then error *) task := 3; (* load counter *) params[1] := I; (* counter number *) params[2] := 1000 * I + 1000; (* number of counts to make *) call_driver; (* call the driver *) if status > 0 then exit; end; task := 2; (* load all counters *) params[1] := 2; params[2] := 1; params[3] := 1; params[4] := 1; params[5] := 1; params[6] := 1; call_driver; (* call the driver *) task := 2; (* arm the counters *) params[1] := 1; params[2] := 1; params[3] := 1; params[4] := 1; params[5] := 1; params[6] := 1; call_driver; (* call the driver *) end; (* setup *) (***************************************************************************** * PROCEDURE: get_readings -- local routine * * * * PURPOSE: Reads the 5 counters and displays them on the screen. * * * * INPUT: None. * * * * CALLS: call_driver - entry point to driver package. * * * *****************************************************************************) procedure get_readings; var index,i :integer; begin task := 7; (* install interrupts *) params[1] := 10; (* number of interrupts *) params[2] := $7000; (* these are the segments to *) params[3] := $7100; (* store the readings from *) params[4] := $7200; (* each counter *) params[5] := $7300; params[6] := $7400; params[7] := 0; (* start on IP0 disabled *) params[8] := 5; (* IRQ5 used for interrupts *) call_driver; (* call the driver *) if status > 0 then exit; (* wait for the interrupts to complete *) task := 8; repeat params[1] := 0; params[2] := 0; call_driver; (* call the driver *) until params[1] = 0; (* transfer the imformation in the segments for each counter into the data array. *) params[3] := $6f00; for i := 1 to 5 do (* for each counter *) begin index := (i - 1) * 20 + 1; task := 9; params[1] := 10; params[2] := 0; params[3] := params[3] + $100; params[4] := ofs(buf[index]); call_driver; (* call the driver *) if status > 0 then exit; end; (* display the counter values *) ClrScr; GotoXY(10,5); Write('PASS CTR 1 CTR 2 CTR 3 CTR 4 CTR 5'); GotoXY(10,6); Write('---- ----- ----- ----- ----- -----'); for i := 1 to 10 do begin GotoXY(10,6+i); Write(i:3,buf[i]:10,buf[i+20]:10,buf[i+40]:10,buf[i+60]:10,buf[i+80]:10); end; end; (* get_readings *) (***************************************************************************** * PROCEDURE: main -- local routine * * * * PURPOSE: Controls program flow, detects when user is ready to exit. * * * * INPUT: None. * * * * CALLS: setup - set up program and drivers. * * get_readings - perform the interrupts. * * * *****************************************************************************) var ch :char; Address :word; begin ClrScr; WriteLn(' SAMPLE1.PAS : INTERRUPT OPERATION '); WriteLn(' '); WriteLn(' This is a demonstration program to be used with the CTR-5 Counter '); WriteLn(' timer board. The program will set up all five counters to count down '); WriteLn(' from a different level, then use interrupts to read the count at a given '); WriteLn(' interval. The results are then displayed on the screen. Note that this '); WriteLn(' program uses segments, which should not be used by anything else. For '); WriteLn(' instance, this program as is, cannot be run in the Turbo C desktop, or '); WriteLn(' the program will lock up the system. '); WriteLn(' '); Address := AskForBaseAddress('350'); ClrScr; WriteLn; WriteLn; WriteLn; WriteLn(' Board Configuration:'); WriteLn; WriteLn(' -- The IRQ5 jumper should be installed (required)'); WriteLn(' -- On board clock should be set to 1 MHz (required)'); WriteLn(' -- An external jumper from pin 1 to pin 30 (required)'); WriteLn(' -- An external jumper from pin 11 to pin 2 (required)'); WriteLn(' -- All remaining jumper settings should not be altered.'); WriteLn; WriteLn; WriteLn; WriteLn(' Press Enter to continue'); readln; ClrScr; setup(Address); (* set up program and the driver *) if status <> 0 then exit; (* is status > 0 then board error *) repeat get_readings; (* perform the interrupts *) if status <> 0 then exit; (* if status > 0 then error *) (* check for program exit *) WriteLn;WriteLn; Write(' Press E to exit the program. Press any other key to rescan for data...'); while (not keypressed) do delay(1); (* wait for key press *) ch := readkey; (* read the char *) until (ch = 'E') or (ch = 'e'); ClrScr; end. (* main program *)