program IOD_24_board_demo; uses crt,dos; {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- This program is a demonstration of the Digital Input/Output circuits. The program is a rendition of a security system, that allows you to monitor the status of 16 security sensors, and to automatically trigger four alarms that can be used to turn on the lights, activate a siren, or send a triggering pulse to a silent alarm. The alarm system in this demonstration has four arming stations, which toggle the alarm on or off. LAST MODIFIED ON: August 21, 1995 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} CONST ON = 1; {create some useful constants} CONST OFF = 0; {...} TYPE sensor_array = array[0..15] of integer; {this creates a type of variable used for sensor data} VAR sensors_at_arm : sensor_array; {bit by bit status of sensors when alarm } {is activated, used to notify user of open} {windows, etc. } sensors_now : sensor_array; {bit by bit status of sensors at current } {time. When compared against } {sensors_at_arm, indicates break-in if } {there is a change. } arming_stations : integer; {a variable representing all four arming } old_arming_stations:integer; {stations. If value changes, toggle alarm} {ON / OFF. } hour,min,sec,hun:word; {variables used to retrieve time} key : char; {useful temporary variable} i : integer; {useful temporary variable used in loops} j : integer; {useful temporary variable used in loops} function AskForBaseAddress(OldOne : String) : Word; const Msg : string[3] = '0'; var NewOne, Success, Dummy, Error : Word; AddrInputPosX, AddrInputPosY : Word; begin if (OldOne = 'OLD') then OldOne := Msg; WriteLn('Please enter the Base Address (100-3F8) 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 ((NewOne <= $3F8) AND (NewOne >= $100)) 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; procedure initialize_board(Address : word); {this procedure sets MODE 0 as active, } {and sets Port A, B, and C Lo as as input, with} begin {Port C Hi being output. } port[Address+3] := $93; {the bit pattern required to set the desired } {port[x] is pascal's } {mode and port designations is 10010011 = 93 hex} {method of accessing } {Refer to the User Manual for a description of } {the port memory. The} {what each bit does. } {above code sets the } {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} {port memory at Address+3 to 93 hex. This address is the control register for} {the IOD. } end; {procedure initialize_board} procedure read_sensors(VAR ary:sensor_array;Address:word);{this procedure fetches data from} VAR tempA : byte; {Ports A and B, and returns a binary} VAR tempB : byte; {representation of each sensor. } begin tempA := port[Address]; {loads tempA & tempB with corresponding inputs} tempB := port[Address+1]; {from board.} for i := 0 to 7 do begin if ((tempA shr i) AND ON) > 0 then {this tests to see if bit # i is ON} ary[i]:=ON {i.e. TRUE ^^^ } {and sets the corresponding array } else {element to ON if it is ... else the} ary[i]:=OFF; {array element is set to OFF. } end; for i:=0 to 7 do begin if ((tempB shr i) AND ON) > 0 then ary[i+8]:=ON {in order to get Port B into array } else {elements 8 through 15, we add 8 to} ary[i+8]:=OFF; {the bit numbers in the assignment.} end; end; {procedure read_sensors} function get_status(Address:word):integer; var temp:integer; begin {this sets status to the lower half} temp:=port[Address+2]; {(lower nybble) of Port C, the half} get_status:=temp AND $0F; {defined in Initialize to be input,} end; {function get_arming_status} {for four (4) arming switches. } procedure ALARM(Address:word); var temp:longint; begin sound(2000); {this starts the computer's speaker } {which acts as a siren for the alarm} temp:=0; port[Address+2]:=$F; {this sets port C's lower nybble } repeat {bits to ON (1111 binary = F hex). } arming_stations:=get_status(Address); {This activates four alarm outputs, } if arming_stations <> old_arming_stations then temp:=2000000000;{dis-armed} {and then toggles Port C Hi's} port[Address+2]:=port[Address+2] XOR $10; temp:=temp+1; until temp>=200000000; {LSB, which might be used with an } nosound; {external speaker to produce a siren} end; {procedure ALARM} {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} { MAIN PROGRAM } var Address : word; begin initialize_board(Address); ClrScr; gotoxy(1,3); WriteLn(' EVENT-P.PAS : IOD-24'); WriteLn; WriteLn('This is the IOD demonstration program. This program will simulate'); WriteLn('an alarm system program, containing sixteen sensors and four arming'); WriteLn('stations, along with four separate alarm outputs, which could be routed'); WriteLn('to a siren, lights, silent alarm, etc.'); WriteLn; WriteLn; WriteLn; Address:=AskForBaseAddress('354'); ClrScr; GotoXY(1,2); WriteLn('Board Configuration:'); WriteLn; WriteLn(' -- Jumper IN5 should be installed (required)'); WriteLn(' -- Jumper IP should be installed (required)'); WriteLn(' -- All remaining jumper settings are irrelevant'); WriteLn; WriteLn(' To arm the system, ground one of the arming stations (pins 9,11,13'); WriteLn(' or 15), when prompted to arm. To trigger an alarm, ground any odd'); WriteLn(' pin between 17 and 47, inclusive. To stop the alarm, either wait,'); WriteLn(' or ground an arming station again. To exit without triggering an '); WriteLn(' alarm, ground an arming station. Then press a key when the promp'); WriteLn(' appears.'); WriteLn; WriteLn('THIS PROGRAM IS INTENDED ONLY FOR DEMONSTRATION PURPOSES, AND IS NOT'); WriteLn('MEANT TO BE USED AS AN ACTUAL ALARM SYSTEM.'); WriteLn;WriteLn; WriteLn('Press any key to begin program.'); key:=readkey; ClrScr; WriteLn; WriteLn('The program will now check for ''open'' sensors. If any of the'); WriteLn('digital input lines is grounded, it will read as an open sensor.'); WriteLn('Make desired connections and press RETURN to continue.'); old_arming_stations:=get_status(Address); { <=-this loads the status of the arming} repeat {switches at the time the program is} {first activated. A change in status} {would indicate arming.} read_sensors(sensors_now,Address); {this reads the current status of the} for i:=0 to 15 do begin {sensors, which is then displayed, to} if sensors_now[i]=OFF then {to indicate open windows, etc.} WriteLn('Sensor #',i,' is open'); end; WriteLn; WriteLn('Press ESC to re-scan, RETURN to begin alarm scanning.'); key:=readkey; ClrScr; until key=#13; {the repeat..until loop gives the user an opportunity to} {shut open windows or doors, then re-scan the sensors } WHILE TRUE do begin {this WHILE is used to form an infinite loop} WriteLn('Waiting to be armed, or press any key to halt program.'); repeat {this repeat..until loop continues until } arming_stations:=get_status(Address); {arming station status changes, indicating} if keypressed then begin key := readkey; { Strip keystroke from buffer. } halt(1); {arming, or a key is pressed, indicating } end; until arming_stations <> old_arming_stations; {program termination. } sound(900); {short tone indicating the alarm has been armed} delay(300); {..} nosound; {..} WriteLn('Alarm system will activate in 15 seconds'); read_sensors(sensors_at_arm,Address); old_arming_stations := get_status(Address); gettime(hour,min,sec,hun); {this code reads the system clock for the} i:=sec+15; {current time, which is used to delay for} if i > 60 then i := i-60; {15 seconds.} repeat {..} gettime(hour,min,sec,hun); {..} until sec = i; {end of delay loop} WriteLn; WriteLn('ALARM SYSTEM ACTIVE AND ARMED'); sound(900); {short tone indicating alarm is fully activated} delay(300); {..} nosound; {..} j:=0; repeat {this code compares current } read_sensors(sensors_now,Address); {status of sensors against } for i:= 1 to 16 do begin {their status at time of arm} if sensors_now[i-1] <> sensors_at_arm[i-1] then j:=1; {to determine if break-in} {has occurred...any change } end; {for} {indicates break-in.} arming_stations := get_status(Address); if arming_stations <> old_arming_stations then j := -1; {flag used to signal alarm is de-activated} until j <> 0; if j = -1 then begin {if j was set to -1 in the above loop, then} gettime(hour,min,sec,hun); {alarm is de-activated} WriteLn('Alarm deactivated at ',hour,':',min,'.',sec); sound(900); {chirps the speaker to indicate disarming} delay(100); {..} nosound; {..} delay(50); {..} sound(900); {..} delay(100); {..} nosound; {..} end {end of disarming routine} else {if alarm} begin WriteLn('Sensor #',j,' has been activated!!'); gettime(hour,min,sec,hun); WriteLn('The time of alarm is ',hour,':',min,'.',sec); ALARM(Address); delay(150); end; {else} end;{WHILE this end sends the program back to wait to be re-armed} end.