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

This is page designed, maintained and
(C)opyright 1999 by Geoff Knagge