The Security Module
The module that calculates which doors and windows should be considered secured and/or locked, and handles zone locking and settings. The conditions for things becoming secure is described in the alarms module. A summary of the routine inputs/outputs for this module are found here or downloaded in Lotus Wordpro 97 format here (50KB)
The recalculate procedure initially tries to secure all zones, doors, and windows. Any unlocked door which connects to the outside is not able to be secured. The procedure then checks all doors, and if a door is in its insecure state, and one of zones on either side of it is secure, then that zone becomes insecure. Consequently, all unlocked doors and windows in that zone also become insecure. This is repeated until all doors are checked without any changes being made.
Download:
; /////////////////////////////////////////////////////////////
; // Security Module
; // (c) 1999 Geoff Knagge, Andrew Carr, Mark Lynn
; // last modified : 22/10/1999
; //
; /////////////////////////////////////////////////////////////
ZoneData:
; +--------- bit 7= secure
; |+-------- bit 6= indicator for codes
; ||+------- bit 5= max window security
; ||| +-- bit 0= locked
; ||| |
.byte 01100000# ; Zone 1
.byte 01100000# ; Zone 2
.byte 01100000# ; Zone 3
.byte 01100000# ; Zone 4
.byte 01100000# ; Zone 5
.byte 01100000# ; Zone 6
.byte 01100000# ; Zone 7
.byte 01100000# ; Zone 8
.byte 01100000# ; Zone 9 - outside
.byte 01100000# ; Zone 10- outside
SZ_unsecure: ; input A = zone
cpi outZone
jz SZ_uj3
push hl
push af
push de
push bc
mov e,A
;///////// For all doors,
; if (not locked)
; and (connected to zone)
; unsecure door
mvi b,0
mvi c,0
SZuL1: call SDgLock
cpi 0
jz SZuJ1 ; zero means locked
call SDgCtZone
cmp e
jz SZuJ2 ; this is the controlling zone
call SDgCnZone
cmp e
jnz SZuJ1 ; not connected to zone
SZuJ2: ; we get here if the door is in the zone
call SD_unsecure
SZuJ1:
inx bc ; next door
mvi a,8 ; too many doors?
cmp c
jnz SZuL1 ; no, go and check it.
;/////////// End of "For all Doors" loop
lxi hl,ZoneData ; point to zone status array
mov c,e
dad bc ; move to right cell
mov a,m ; load status bit
ani 7F ; clear secure bit
mov m,a ; save status bit
pop bc
pop de
pop af
pop hl
SZ_uj3: ret
SZ_lock: ; input A = zone
push hl
push af
push de
push bc
mov e,a
;///////// For all doors,
; if controlled by zone
; lock door
mvi b,0
mvi c,0
SZaL1: call SDgCtZone
cmp e ; is the door controlled by this zone
jnz SZaJ1 ; no
call SD_relock ; yes, lock it... lock it good!
SZaJ1:
inx bc ; next door
mvi a,8 ; too many doors?
cmp c
jnz SZaL1 ; no, go and check it.
;/////////// End of "For all Doors" loop
lxi hl,ZoneData ; point to zone status array
mov c,e
dad bc ; move to right cell
mov a,m ; load status byte
ori 01 ; set Locked bit
mov m,a ; save status byte
pop bc
pop de
pop af
pop hl
ret
SZglock: ; input A = zone; output A=status
push hl
push bc
lxi hl,ZoneData ; point to zone status array
mov c,a
dad bc ; move to right cell
mov a,m ; load status byte
ani 01
pop bc
pop hl
ret
SZgMaxSecure: ; input A = zone; output A=status
push hl
push bc
lxi hl,ZoneData ; point to zone status array
mov c,a
dad bc ; move to right cell
mov a,m ; load status byte
ani 20
pop bc
pop hl
ret
SZ_MaxSecure: ; input A = zone;
push hl
push bc
push af
lxi hl,ZoneData ; point to zone status array
mov c,a
dad bc ; move to right cell
mov a,m ; load status byte
ori 20 ; set bit 5
mov m,a
pop af
pop bc
pop hl
ret
SZ_MinSecure: ; input A = zone;
push hl
push bc
push af
lxi hl,ZoneData ; point to zone status array
mov c,a
dad bc ; move to right cell
mov a,m ; load status byte
ani 0DF ; clear bit 5
mov m,a
pop af
pop bc
pop hl
ret
SZgindicator: ; input A = zone; output A=status
push hl
push bc
lxi hl,ZoneData ; point to zone status array
mov c,a
dad bc ; move to right cell
mov a,m ; load status byte
ani 40
pop bc
pop hl
ret
SZ_unlock: ; input A = zone
push hl
push af
push de
push bc
mov e,a
;///////// For all doors,
; if controlled by zone
; unlock door
mvi b,0
mvi c,0
SZbL1: call SDgCtZone
cmp e ; is the door controlled by this zone
jnz SZbJ1 ; no
call SD_unlock ; yes, lock it... lock it good!
SZbJ1:
inx bc ; next door
mvi a,8 ; too many doors?
cmp c
jnz SZbL1 ; no, go and check it.
;/////////// End of "For all Doors" loop
lxi hl,ZoneData ; point to zone status array
mov c,e
dad bc ; move to right cell
mov a,m ; load status byte
ani 0FE ; clear Locked bit
mov m,a ; save status byte
pop bc
pop de
pop af
call sz_unsecure
pop hl
ret
SZ_secure: ; secures a zone. input C=zone
push bc
push hl
push af
mvi b,0
lxi hl,ZoneData ;point to zone status aray
dad bc ;point to right zone
mov a,m ;load zone stat byte
ori 80 ;set secure bit
mov m,a ;save zone status
pop af
pop hl
pop bc
ret
SZgsecure: ; gets a zones secure status. input A=zone
; output A=stat
push bc
push hl
mov c,a
mvi b,0
lxi hl,ZoneData ;point to zone status aray
dad bc ;point to right zone
mov a,m ;load zone stat byte
ani 80
pop hl
pop bc
ret
recalculate:
call SD_read ; get hardware stati
call SW_read ; get hardware stati
;////////////// Try to secure all zones, doors, windows
mvi c,0
mvi b,0
rc_L1:
call SZ_secure ; secure zone C
call SDglock ; is door locked
cpi 0
jz rccl5 ; yes, automatically try to secure it
call SDgCtZone ; get door's controlling zone
cpi outzone ; an unlocked door connecting
jz rccl4 ; to the outside is always unsecure
call SDgCnZone ; get door's connecting zone
cpi outzone ; an unlocked door connecting
jz rccl4 ; to the outside is always unsecure
rccl5: call SD_T2Secure; try to secure door C. we get here if
; the door is either unlocked or internal
rccl4: call SW_T2Secure; try to secure window C
inx bc ; next zone, door and window
mvi a,8 ; have we counted too high?
cmp c
jnz rc_L1 ; no go back and do the next
rc_L2:
mvi e,0 ; clear "changed" flag
;//////////////////// Start of loop
mvi c,0 ; for doors = 0 to 7
rc_L3:
call SDgSecure ; is door secure?
cpi 0
jnz rc_J1 ; yes, it won't change much...
mvi d,0 ; D counts connected, secure zones
call SDgCtZone ; get controlling zone in A
call SZgSecure ; is this zone secure?
cpi 0
jz rc_J2 ; no
inr d ; yes, increment counter
rc_j2:
call SDgCnZone ; get connecting zone in A
call SZgSecure ; is it secure?
cpi 0
jz rc_J3 ; no
inr d ; yes, increment counter
rc_j3:
mov a,d ; a = counter
cpi 1 ; is it exactly 1?
jnz rc_j1 ; no, don't unsecure anything
call SDgCnZone ; no, unsecure both zones
CALL SZ_unsecure; (input: A = zone)
call SDgCtZone
call SZ_unsecure
mvi e,0FF ; set changed flag
rc_J1:
inx bc ; increment loop counter
mvi a,8
cmp c ; have we counter too high
jnz rc_L3 ; no, another pass needed...
;//////////////////// End of loop
mvi a,0FF
cmp e ; is changed flag set?
jz rc_L2 ; yes, we need another pass
;////////////// Now go and unsecure eligible windows
mvi c,0 ; for windows = 0 to 7
rc_L4:
call SWgCtZone ; get Window's controlling zone
mov e,a ; E = controlling zone
call SZgSecure ; is zone secure?
cpi 0
jnz rc_J4 ; yes, window shall stay secure...
mov a,e
call SZgLock ; is zone locked?
cpi 0
jz rc_J5 ; no, so the window shan't be secured
mov a,e
call SZgMaxSecure; is maxsecure bit set?
cpi 0
jnz rc_J4 ; yes, window stays as it is
rc_J5: ; // we get here if (the zone is insecure) and
; ((zone is unlocked) or (!maxsecure))
call SW_unsecure; Window is hereby unsecured...
rc_J4:
inx bc ; increment loop counter
mvi a,8
cmp c ; have we counter too high
jnz rc_L4 ; no, another pass needed...
ret
;/////////////////////////////////////
ala_on:
push hl
push af
mvi a,0
lxi hl,alar_stat
mov m,a
pop af
pop hl
ret
ala_off:
push hl
push af
mvi a,1
lxi hl,alar_stat
mov m,a
pop af
pop hl
ret
;/////////////////////////////////////
.imprt "doors.asm"
.imprt "windows.asm"
|