Password Modules
Password handling is done in two modules. The input module is what handles the input from the keypad and output to the LCD, but does not do any validity checking. The module initialisation procedure is passed a pointer to a table of the following form, the address of which is stored in PW_table by the module.
1 byte: Mode to switch to when enter pressed
1 byte: Mode to switch to when cancelled
1 byte: Mode to switch to when timeout occurs
1 byte: Amount of seconds before a timeout
1 byte: screen line #1 to be displayed
1 byte: screen line #2 to be displayed
The checking module is what is called by the program when we seek a password. Passwords are stored in an array, so we only need to tell the module which one we're asking for, what prompts to display on the top half of the screen, and which modes to change to under various circumstances. This is done by passing the setup procedure a pointer to a table of the following form :
1 byte : password number that we're aiming for
2 bytes: lines 1,2 of display
1 byte : mode to change to if password accepted
1 byte : mode to change to if cancelled
1 byte : mode to change to if timed out
1 byte : mode to change to if wrong 3 times
1 byte : timeout in seconds
Download:
; ///////////////////////////////////////////////////////////
; // Password Handling module
; // (c) 1999 Geoff Knagge, Andrew Carr, Mark Lynn
; // last modified : 22/10/1999
; //
; ///////////////////////////////////////////////////////////
Pa_Array: ; array of passwords
.byte 4,4,4,0A,7,0,0,0,0,0,0 ; 00: Master Code - 2290
.byte 01,0,0,0,0,0,0,0,0,0,0 ; 01: Zone 1 Arming
.byte 01,4,0,0,0,0,0,0,0,0,0 ; 02: Zone 2 Arming
.byte 01,8,0,0,0,0,0,0,0,0,0 ; 03: Zone 3 Arming
.byte 01,1,0,0,0,0,0,0,0,0,0 ; 04: Zone 4 Arming
.byte 01,5,0,0,0,0,0,0,0,0,0 ; 05: Zone 5 Arming
.byte 01,9,0,0,0,0,0,0,0,0,0 ; 06: Zone 6 Arming
.byte 01,2,0,0,0,0,0,0,0,0,0 ; 07: Zone 7 Arming
.byte 01,6,0,0,0,0,0,0,0,0,0 ; 08: Zone 8 Arming
.byte 01,0,0,0,0,0,0,0,0,0,0 ; 09: Zone 1 Disarming
.byte 01,4,0,0,0,0,0,0,0,0,0 ; 0A: Zone 2 Disarming
.byte 01,8,0,0,0,0,0,0,0,0,0 ; 0B: Zone 3 Disarming
.byte 01,1,0,0,0,0,0,0,0,0,0 ; 0C: Zone 4 Disarming
.byte 01,5,0,0,0,0,0,0,0,0,0 ; 0D: Zone 5 Disarming
.byte 01,9,0,0,0,0,0,0,0,0,0 ; 0E: Zone 6 Disarming
.byte 01,2,0,0,0,0,0,0,0,0,0 ; 0F: Zone 7 Disarming
.byte 01,6,0,0,0,0,0,0,0,0,0 ; 10: Zone 8 Disarming
.byte 0,0,0,0,0,0,0,0,0,0,0 ; 11: Tempory storage used
; when changing passwords
.byte 1,0,0,0,0,0,0,0,0,0,0 ; 12: Smoke disable password
.byte 1,0,0,0,0,0,0,0,0,0,0 ; 13: panic disable password
.byte 0,0,0,0,0,0,0,0,0,0,0 ; 14: temp password storage used
; when jumping to an alarm
;//////////////////////////////////////
Pa_init:
lxi HL,Pa_Array ; point HL to the array of passwords
mvi a,0B ; A = length of each password entry
mvi b,0 ; BC = password number
Pa_l1: ; HL = HL + BC * 0BH
dad BC ; HL = HL + BC
dcr A ; decrement counter
cpi 0 ; is it zero?
jnz pa_l1 ; if not keep adding...
; HL now points to the right password
mov b,h
mov c,l ; so does BC...
lxi DE,Pw_Entry ; and DE points to the input bufffer
mov a,m ; get number of characters
lxi hl,pa_cnt ; point to counter
mov m,a ; reset counter to number of characters
ret
;//////////////////////////////////////
Pa_cnt: .byte 0
;//////////////////////////////////////
Pa_size: ; in: a = password number
push bc
push de
push hl
mov c,a
call pa_init
pop hl
pop de
pop bc
ret
;//////////////////////////////////////
Pa_set: ; sets a password with whats in the password input
; buffer. Input : C=password to set
push af
push bc
push de
push hl
call Pa_init ; A=password leng, BC = points to password,
; HL=points to counter, DE=input
mvi a,0A ; counter = 10
mov m,a ; save it
Pa_l2:
mov h,d
mov l,e ; point HL to the input buffer (DE)
mov a,m ; get a character
mov h,b
mov l,c ; point HL to the password storage (BC)
mov m,a ; save the character
inx bc ; next character of output
inx de ; next character of input
lxi hl,pa_cnt ; point to counter
dcr m ; decrement it
mvi a,0FF
cmp m ; did it overflow?
jnz pa_l2 ; if not, copy another one
pop hl
pop de
pop bc
pop af
ret
;//////////////////////////////////////
Pa_C2: call pa_compare ; compare with password C
cpi 00 ; 0 = matched
jz pajc2 ; if matched, finished
push bc
mvi c,0 ; C = master password
call pa_compare ; compare with master
pop bc
pajc2: ret
Pa_compare: ; compare a password with the password input buffer.
; Input : C=password to check, Out: A=00 if matched
push bc
push de
push hl
call Pa_init ; A=password leng, BC = points to password,
; HL=points to counter, DE=input
Pa_l3: mov h,d
mov l,e ; point HL to the input buffer (DE)
mov a,m ; get a character
mov h,b
mov l,c ; point HL to the password storage (BC)
cmp m ; compare the character
jnz pa_j1 ; if not equal, whinge about it
inx bc ; next character of output
inx de ; next character of input
lxi hl,pa_cnt ; point to counter
dcr m ; decrement it
mvi a,0FF
cmp m ; did it overflow?
jnz pa_l3 ; no, compare the next
mvi a,0 ; load the "no error" code
jmp pa_j2 ; get out of here...
pa_j1: ; there was a mismatched character
mvi a,0FF ; load the error code
pa_j2:
pop hl
pop de
pop bc
ret
;////////////////////////////////////
; 1 byte : password number that we're aiming for
; 2 bytes: lines 1,2 of display
; 1 byte : mode to change to if password accepted
; 1 byte : mode to change to if cancelled
; 1 byte : mode to change to if timed out
; 1 byte : mode to change to if wrong 3 times
; 1 byte : timeout in seconds
;/////////////////////////// setup password checker
pa_table: .byte st_pac,10,10,0FF,0C,10
pa_data: .word 0
pa_tcnt: .byte 0 ; count of number of attempts...
pa_stable: ; sets up pa_table
push af
push hl
push de
push bc
lhld pa_data ; point HL to the data table
inx hl ; point to entry for line 1
mov a,m ; a = line 1
inx hl ; point to entry for line 2
mov b,m ; b = line 2
inx hl ; point to password ok mode
inx hl ; point to cancel mode
mov c,m ; c = cancel mode
inx hl ; point to time out mode
mov d,m ; d = timeout mode
inx hl ; point to wrong 3 times mode
inx hl ; point to timeout time mode
mov e,m ; e = timeout time
lxi hl,pa_table ; point to the input table
inx hl ; point to cancel mode
mov m,c ; cancel mode = C
inx hl ; point to timeout mode
mov m,d ; timeout mode = D
inx hl ; point to timeout time
mov m,e ; timeout time = E
inx hl ; point to line 1 code
mov m,a ; line 1 code = A
inx hl ; point to line 2 code
mov m,b ; line 2 code = B
pop bc
pop de
pop hl
pop af
ret
;///////////////////////////////////////
pa_retry:
push bc
push de
push af
push hl
lxi hl,pw_showchars ; point to the show characters flag
mov a,m ; restore the indicator flag
lxi hl,pa_table ; point to the input table
call pw_init ; reinitialise input module
pop hl
pop af
pop de
pop bc
ret
;//////////////////////////////////////
pa_setup: ; input : A = show indicator, HL=data
push bc
push de
push af
push hl
push af
shld pa_data ; point HL to table
call pa_stable ; setup the input table
mov a,m ; password we're aiming for
call pa_size ; how long is the password
cpi 0 ; zero?
jz pa_j5 ; if so, don't ask for one
mvi a,0
lxi hl, pa_tcnt ; point to number of attempts
mov m,a ; set number of tries to 0
pop af ; restore the indicator flag
lxi hl,pa_table ; point to input table
call pw_init
call pw_rst ; reset the timer
jmp pa_j6 ; finished
pa_j5: lhld pa_data ; called if no password needed
pop af ; clear stack
inx hl ; point to line 1
inx hl ; point to line 2
inx hl ; point to accept mode
mov c,m ; C = OK mode
call setmode ; set it
pa_j6: pop hl
pop af
pop de
pop bc
ret
;/////////////////////////////////////////
pa_chk: ; password has been entered, now check it
lhld pa_data ; point to data table
mov c,m ; get the password number
call pa_c2 ; compare it with the input
cpi 0 ; 00 = match
jz pa_cj1
; uh oh, no match.
lda a3times ; check "alarm if wrong 3 times" flag
cpi 0 ; is it set?
jz pacn3t ; no, don't trigger the alarm
lxi hl, pa_tcnt ; point to attempt counter
mov a,m ; read it
cpi 02 ; 3 tries?
jz pa_3tries ; yes, complain loudly
pacn3t: inr a ; otherwise increment the counter
mov m,a ; and save it
mvi c,sc_wpw ; show a message complaining
call LCD_setmsg
mvi c,st_wpw
call setmode ; wait for a keypress to continue
ret
pa_3tries:
lhld pa_data ; point to input table
inx hl ; point to line 1
inx hl ; point to line 2
inx hl ; point to accept mode
inx hl ; point to cancel mode
inx hl ; point timeout mode
inx hl ; point to wrong 3 times mode
mov c,m ; C = wrong 3 times mode
call setmode
ret
pa_cj1: inx hl ; password was matched, point to line 1
inx hl ; point to line 2
inx hl ; point to accept mode
mov c,m ; load it
call setmode ; and set it
ret
;////////////////////////////
Pa_wait: ; wait for a keypress
call keyget ; check keys
cpi KS_none ; was one pressed?
jz PawEnd; ; if not, do nothing
mvi C,ST_pRetry ; otherwise change mode to try again
call setmode ; store the new mode
Pawend:
ret;
; ///////////////////////////////////////////////////////////
; // Password input module
; // (c) 1999 Geoff Knagge, Andrew Carr, Mark Lynn
; // last modified : 22/10/1999
; //
; ///////////////////////////////////////////////////////////
PW_Table : .word 00 ; points to a table of the form:
; 1 byte: Mode to switch to when enter pressed
; 1 byte: Mode to switch to when cancelled
; 1 byte: Mode to switch to when timeout occurs
; 1 byte: Amount of seconds before a timeout
; 1 byte: screen line #1 to be displayed
; 1 byte: screen line #2 to be displayed
PW_entry : .byte 0,0,0,0,0,0,0,0,0,0,0
; password entered. one byte length
; followed by up to 10 scan codes
PW_timer : .byte 0 ; used for detecting time outs
PW_showchars: .byte 0
;PWL1: .byte 0
;PWL2: .byte 0
;PWL3: .byte 0
;PWL4: .byte 0
;/////////////////////////////////
PW_rst: ; reset timer - must be called externally to module
push af
push hl
lhld pw_table ; point HL to the pw table
inx hl ; point to cancel mode
inx hl ; point to timeout mode
inx hl ; point to timeout time
mov a,m ; A = timeout time
lxi hl,pw_timer ; point HL to the timer
mov m,a ; timer = A
pop hl
pop af
;/////////////////////////////////
PW_handle:
call PW_keys ; handle key presses
call PW_uL3 ; update line 3 of the display
call PW_ul4 ; update line 4 of the display
lxi hl, pw_timer ; point HL to the timer
mov a,m ; A = timer count
cpi 0 ; is it down to 0?
jnz pw_j15 ; if not, we're finished
lhld pw_table ; is so, point HL to the table
inx hl ; point to cancel mode
inx hl ; point to timeout mode
mov c,m ; c = timeout mode
call setmode ; change to that mode
pw_j15: ret
;/////////////////////////////////
PW_keys:
push af
push bc
push de
push hl
lhld pw_table ; point HL to the table, OK mode
call keyget ; check for a keypress
cpi KS_none ; was a key pressed?
jz pw_j9 ; if not, do nothing
cpi KS_invalid ; was the key valid?
jz pw_j9 ; if not, do nothing
cpi KS_Star ; was it the star
jz pw_j10 ; if so, handle it
inx hl ; move HL to "cancel" entry of table
cpi KS_Hash ; was it the hash?
jz pw_j11 ; if so, handle that
; 0-9 was pressed
mov e,a ; e = scan code of key that was pressed
lxi hl,pw_entry ; point HL to input buffer
mov a,m ; load first byte from buffer - character count
cpi 0A ; do we already have 10 characters?
jz pw_j13 ; if so, don't add it
inr a ; increment counter
mov m,a ; update character count
mov c,a ; C = char counter
mvi b,0 ; BC = char counter
dad bc ; point hl to the right character
mov m,e ; store the scancode of what was pressed
jmp pw_j9 ; finished
pw_j13: ; 0-9 pressed, but buffer full
jmp pw_j9 ; finished
PW_j10: ; key pressed was the *
mov c,m ; C = OK mode
call setmode ; change to that mode
jmp pw_j9 ; finished
PW_J11: ; key pressed was the #
mov c,m ; C = cancel mode
lxi hl,pw_entry ; point HL to the start of the buffer - char cnt
mov a,m ; A = number of characters
cpi 0 ; is it 0?
jz pw_j12 ; if so, cancel
; Otherwise, Backspace
dcr a ; decrement counter
mov m,a ; save it
jmp pw_j9 ; finished
pw_j12: call setmode ; Cancel pressed
jmp pw_j9 ; finished
PW_j9: pop hl
pop de
pop bc
pop af
ret
;/////////////////////////////////
PW_init : ; input HL=table to use, A=00 if hidechars
push hl
push af
push de
push bc
shld PW_table ; save pointer to the data table
lxi hl,Pw_showchars
mov m,A ; save the showchars flag
lhld PW_table ; point HL to the data table
inx hl ; point to cancel mode
inx hl ; point to timeout mode
inx hl ; point to timeout time
inx hl ; point to line 1 number
mov d,m ; D = code for line 1 of display
inx hl ; point to line 2 number
mov e,m ; E = code for line 2 of display
lxi hl,pwl1 ; point hl to where line 1 code is stored
mov m,d ; save line 1 in PWL1
inx hl ; line 2 code follows
mov m,e ; save line 2 in PWL 2
mvi a,0 ; character count = 0
lxi hl,Pw_entry ; point to start of buffer (char count)
mov m,a ; reset the character count
call PW_uL4 ; update the fourth line
call PW_uL3 ; update the third line
mvi c,sc_pwin ; set screen code for getting passwords
call LCD_SetMsg ; tell the LCD which message
mvi c,ST_PwIn ; mode = password entry
call setmode
pop bc
pop de
pop af
pop hl
ret
PWL_cancel = 99
PWL_backspace = 98
PW_uL3: push af
push hl
lxi hl,PW_showchars ; point HL to the showchars flag
mov a,m ; read the flag
cpi 00 ; 00 means show number of chars entered
jz pw_j7 ; if don't show, skip the next bit
lxi hl,pw_entry ; point HL to the input buffer
mov a,m ; load the character count
adi 12 ; add the base message code (line 12)
jmp pw_j8 ; miss the next line
pw_j7: mvi a,67 ; set the line code to "chars hidden"
pw_j8: lxi hl,pwl3 ; point HL to line 3 of the display
mov m,a ; Save the line code
pop hl
pop af
;///////////////////////////////////////
PW_uL4:
push af
push bc
push de
push hl
lxi hl,PW_entry ; point HL to the input buffer
mov a,m ; load byte 1 - the character count
cpi 0 ; is the character count 0?
jz PW_j1 ; yes, # mode is cancel
mvi c,PWL_backspace ; no, prompt #=backspace
jmp PW_j2
PW_j1: mvi c,PWL_cancel; yes, prompt #=cancel
PW_j2: lxi hl,PWL4 ; point HL to line 4 of the display
mov m,c ; save the line code in PWL4
lxi hl, pw_timer; point HL to the timeout counter
mov a,m ; load the timer value
sui 0A ; subtract 10
jc pw_j5 ; it overflowed... it was less than 10
mvi a,20 ; otherwise set the char to a space
jmp pw_j6
pw_j5: adi 3A ; set char to the appropriate digit
pw_j6: ; now store A in first char of PWL4...
;///////////////// This section determines the address
;///////////////// of character 1 of PWL4
LXI HL, MessageBank ; point HL to first message in array
LXI DE, MsgLength ; DE = the length of array messages
pw_j3:
DCR c ; c acts as a counter to find the message
JZ pw_j4 ; does HL point to the right message?
DAD DE ; no, point it to the next one
JMP pw_j3
;/////////////////
pw_j4: mov m,a ; Save A in the first char of PWL4
pop hl
pop de
pop bc
pop af
ret
|