program DIO_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: 2/5/98 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} 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} BASEADDR : Word; procedure initialize_board; {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[BASEADDR+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 0303 to 93 hex. This address is the control register for} {the IOD, assuming the base address is 300 hex. } end; {procedure initialize_board} procedure read_sensors(VAR ary:sensor_array);{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[BASEADDR]; {loads tempA & tempB with corresponding inputs} tempB := port[BASEADDR+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:integer; var temp:integer; begin {this sets status to the lower half} temp:=port[BASEADDR+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; var temp:longint; begin sound(2000); {this starts the computer's speaker } {which acts as a siren for the alarm} temp:=0; port[BASEADDR+2]:=$F; {this sets port C's lower nybble } repeat {bits to ON (1111 binary = F hex). } arming_stations:=get_status; {This activates four alarm outputs, } if arming_stations <> old_arming_stations then temp:=2000000000;{dis-armed} {and then toggles Port C Hi's} port[BASEADDR+2]:=port[BASEADDR+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} 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 } {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} begin clrscr; BASEADDR := AskForBaseAddress('0x300'); initialize_board; clrscr; gotoxy(5,5); writeln('This is the DIO 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(' 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('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; { <=-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); {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; {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); old_arming_stations := get_status; 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); {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; 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; delay(150); end; {else} end;{WHILE this end sends the program back to wait to be re-armed} end.