#include Reg9s12.h
;---------- START OF CONSTANTS -------------------
;---------- KEYPAD CONSTANTS ------------------
MAXLN: equ 8
DIGIT0: equ 8
DIGIT1: equ 4
DIGIT2: equ 2
DIGIT3: equ 1
;---------- LCD CONSTANTS ---------------------
ONE_MS: equ 4000 ; 4000 x 250ns = 1 ms at 24 MHz bus speed
FIVE_MS: equ 20000
TEN_MS: equ 40000
FIFTY_US: equ 200
DB0: equ 1
DB1: equ 2
REG_SEL: equ DB0 ; 0=reg, 1=data
NOT_REG_SEL:equ $FE
ENABLE: equ DB1
NOT_ENABLE: equ $FD
LCD: equ portk
LCD_RS: equ portk
LCD_EN: equ portk
REGBLK: equ $0
STACK: equ $2000
;---------- END CONSTANTS ---------------------
;----------------------------------------------------------------------------------------
;---------- Start Variables -------------------
org $1000
;------ Keypad Vars ----------
;-- Password --
passwd: rmb 4 ; Password will be stored in the last 4 bytes of EEPROM.
tmppasswd: rmb 4
pwchkvalid: rmb 1
spstr: fcc "Set New Password"
spsetstr: fcc "New Password Set"
epstr: fcc "Enter Password "
;-- Main Loop Vars --
incount rmb 1
strpt rmb 1
;-- Delay Variables.
R1: rmb 1
R2: rmb 1
R3: rmb 1
;-- keypad output store
KEY: rmb 1
TEMPKEY: rmb 1
KEYS: rmb 8
;------ LCD Vars -------------
pkimg: rmb 1
temp1: rmb 1
;str1: rmb 16 ;line 1 string variable
str1: fcc " " ;initialize as blank..
cnt1: rmb 1 ;line 1 length variable
;str2: rmb 16 ;line 2 string variable
str2: fcc " " ;initialize as blank..
cnt2: rmb 1 ;line 2 length variable
LCDimg: equ pkimg
LCD_RSimg: equ pkimg
LCD_ENimg: equ pkimg
;----------------------------------------------------------------------------------------
;---------- START OF PROGRAM ------------------
org $2000
lds #$2000 ; Initialize the stack.
ldaa #16 ; just for testing, replace with buttons
staa cnt1 ; ditto
staa cnt2 ; ditto
ldaa #0
staa strpt
staa incount
jsr SETPASSWD
jsr CHKPASSWD
lp1: jsr GETKEY
ldab KEY
ldx incount
stab str1,x
inx
stx incount
jsr LCDOUT
jmp lp1
end
;----------------------------------------------------------------------------------------
;----------------------------- SUBROUTINES! ---------------------------------------------
;----------------------------------------------------------------------------------------
;-------------------------------
;-- Set password subroutine. ---------------------------------------------
;-- Check 4-char string starting at address stored in index register x. --
;-------------------------------------------------------------------------
SETPASSWD: clr incount
ldx #0
SPSLOOP: ldaa spstr,x
staa str1,x
inx
cmpx #16
bne SPSLOOP
jsr LCDOUT
ldx #0
SPNEXTKEY: jsr GETKEY
ldaa KEY
staa passwd,x
ldaa #$2A
staa str2,x
inx
jsr LCDOUT
cmpx #4
bne SPNEXTKEY
jsr LCDOUT
ldx #0
pwsetlp: ldaa spsetstr,x
staa str1,x
inx
cmpx #16
bne pwsetlp
jsr LCDOUT
rts
;-------------------------------
;-- Check password subroutine --
;-------------------------------
CHKPASSWD: clr incount
ldx #0
CPSLOOP: ldaa epstr,x
staa str1,x
inx
cmpx #16
bne CPSLOOP
jsr LCDOUT
ldx #0
CPNEXTKEY: jsr GETKEY
ldaa KEY
staa tmppasswd,x
ldaa #$2A
staa str2,x
inx
jsr LCDOUT
cmpx #4
bne CPNEXTKEY
jsr LCDOUT
;-- At this point the passwd has been entered.
ldx #0
checkpwlp: ldaa passwd,x
ldaa tmppasswd,x
cba
bne cp_fail
inx
cmpx #4
bne checkpwlp
cmpx #4
beq cp_pass
cp_pass: ldaa #1
staa pwchkvalid
rts
cp_fail: ldaa #0
staa pwchkvalid
rts
;----------------------------------------------------------------------------------------
;----------------------------- Get key from keypad subroutine ---------------------------
;----------------------------------------------------------------------------------------
KEYRETURN: ldaa TEMPKEY
beq INITCHECK
staa KEY
puld
rts
GETKEY: clr KEY
clr TEMPKEY
pshd
ldaa #$F0
staa ddra
ldaa #$ff
staa ddrb,x
staa ddrj,x
bclr ptp,x,DIGIT0
bset ptp,x,DIGIT1
bset ptp,x,DIGIT2
bset ptp,x,DIGIT3
;--------- POLLING HERE! ----------------------
POLL:
ldaa KEY
ldab #0
cba
beq KEYRETURN
cba
bne SET_TK
SET_TK: staa TEMPKEY
INITCHECK: bclr porta,#%11110000 ; This disables all other bits.
bset porta,#%00010000 ; This is first row.
jsr DELAY
CHECKROW1: jsr DELAY
brset porta,#%00010001,D1
brset porta,#%00000010,D2
brset porta,#%00000100,D3
brset porta,#%00001000,D_A
jmp CHECKROW2;
;--------- DISPLAY FOR 7SEG DISP. --------------
;--------- DISPLAYS FOR FIRST ROW -------------
D1: ldaa #$31
staa KEY
jmp POLL
D2: ldaa #$32
staa KEY
jmp POLL
D3: ldaa #$33
staa KEY
jmp POLL
D_A: ldaa #$61
staa KEY
jmp POLL
;----------- Check row 2 ----------------------
CHECKROW2: asl porta
brset porta,#%00000001,D4
brset porta,#%00000010,D5
brset porta,#%00000100,D6
brset porta,#%00001000,D_B
jmp CHECKROW3
;----------- DISPLAYS FOR SECOND ROW ----------
D4: ldaa #$34
staa KEY
jmp POLL
D5: ldaa #$35
staa KEY
jmp POLL
D6: ldaa #$36
staa KEY
jmp POLL
D_B: ldaa #$62
staa KEY
jmp POLL
;------------- CHECK ROW 3 -----------------
CHECKROW3: asl porta
brset porta,#%00000001,D7
brset porta,#%00000010,D8
brset porta,#%00000100,D9
brset porta,#%00001000,D_C
jmp CHECKROW4
;------------- ROW 3 -----------------------
D7: ldaa #$37
staa KEY
jmp POLL
D8: ldaa #$38
staa KEY
jmp POLL
D9: ldaa #$39
staa KEY
jmp POLL
D_C: ldaa #$63
staa KEY
jmp POLL
;-------------- CHECK ROW 4 ----------------
CHECKROW4: asl porta
brset porta,#%00000001,DSTAR
brset porta,#%00000010,D0
brset porta,#%00000100,DPOUND
brset porta,#%00001000,D_D
ldaa #0
stab KEY
jmp POLL ;; Restart, nothing left to check.
;-------------- ROW 4 ----------------------
DSTAR: ldaa #$2A
staa KEY
jmp POLL
D0: ldaa #$30
staa KEY
jmp POLL
DPOUND: ldaa #$23
staa KEY
jmp POLL
D_D: ldaa #$64
staa KEY
jmp POLL
;----------DELAY
DELAY: PSHA ;Save Reg A on Stack
LDAA #100 ;
STAA R3 ;
;--1 msec delay. The D-Bug12 works at speed of 48MHz with XTAL=8MHz on Dragon12+ board
;Freq. for Instruction Clock Cycle is 24MHz (1/2 of 48Mhz).
;(1/24MHz) x 10 Clk x240x10=1 msec. Overheads are excluded in this calculation.
L3: LDAA #5
STAA R2
L2: LDAA #240
STAA R1
L1: NOP ;1 Intruction Clk Cycle
NOP ;1
NOP ;1
DEC R1 ;4
BNE L1 ;3
DEC R2 ;Total Instr.Clk=10
BNE L2
DEC R3
BNE L3
;--------------
PULA ;Restore Reg A
RTS
;----------------------------------------------------------------------------------------
;--------------------------- END OF GET_KEY SUBROUTINE ----------------------------------
;----------------------------------------------------------------------------------------
;----------------------------
;-- Clear LCD out strings. --
;----------------------------
clear_strs: pshx
psha
ldx #0
ldaa #0
clrloop: staa str1,x
staa str2,x
inx
cmpx #16
bne clrloop
ldaa #16
staa cnt1
staa cnt2
pula
pulx
rts
;----------------------------------------------------------------------------------------
;--------------------------- START OF LCD SUBROUTINE ------------------------------------
;----------------------------------------------------------------------------------------
lcd_ini: ldaa #$ff
staa ddrk ; port K = output
clra
staa pkimg
staa portk
ldx #inidsp ; point to init. codes.
pshb ; output instruction command.
jsr sel_inst
ldab 0,x
inx
onext: ldaa 0,x
jsr wrt_nibble ; initiate write pulse.
inx
jsr delay_5ms ; every nibble is delayed for 5ms
decb ; in reset sequence to simplify coding
bne onext
pulb
rts
inidsp: fcb 12 ; number of high nibbles
* ; use high nibbles only, low nibbles are ignored
fcb $30 ; 1st reset code, must delay 4.1ms after sending
fcb $30 ; 2nd reste code, must delay 100us after sending
; all following 10 nibbles must be delay 40us each after sending
fcb $30 ; 3rd reset code,
fcb $20 ; 4th reste code,
fcb $20 ; 4 bit mode, 2 line, 5X7 dot
fcb $80 ; 4 bit mode, 2 line, 5X7 dot
fcb $00 ; cursor increment, disable display shift
fcb $60 ; cursor increment, disable display shift
fcb $00 ; display on, cursor off, no blinking
fcb $C0 ; display on, cursor off, no blinking
fcb $00 ; clear display memory, set cursor to home pos
fcb $10 ; clear display memory, set cursor to home pos
*
sel_data: psha
; bset LCD_RSimg REG_SEL ; select instruction
ldaa LCD_RSimg
oraa #REG_SEL
bra sel_ins
sel_inst: psha
; bclr LCD_RSimg REG_SEL ; select instruction
ldaa LCD_RSimg
anda #NOT_REG_SEL
sel_ins: staa LCD_RSimg
staa LCD_RS
pula
rts
lcd_line1: jsr sel_inst ; select instruction
ldaa #$80 ; starting address for the line1
bra line3
lcd_line2: jsr sel_inst
ldaa #$C0 ; starting address for the line2
line3: jsr wrt_byte
jsr sel_data
jsr msg_out
rts
;
; at entry, x must point to the begining of the message,
; b = number of the character to be sent out
msg_out: ldaa 0,x
jsr wrt_byte
inx
decb
bne msg_out
rts
wrt_nibble: anda #$f0 ; mask out 4 low bits
lsra
lsra ; 4 MSB bits go to pk2-pk5
staa temp1 ; save high nibble
ldaa LCDimg ; get LCD port image
anda #$03 ; need low 2 bits
oraa temp1 ; add it with high nibble
staa LCDimg ; save it
staa LCD ; output data to LCD port
jsr enable_pulse
rts
*
; @ enter, a=data to output
;
wrt_byte:
pshx
psha ; save it tomporarily.
anda #$f0 ; mask out 4 low bits.
lsra
lsra ; 4 MSB bits go to pk2-pk5
staa temp1 ; save nibble value.
ldaa LCDimg ; get LCD port image.
anda #$03 ; need low 2 bits.
oraa temp1 ; add in low 4 bits.
staa LCDimg ; save it
staa LCD ; output data
bsr enable_pulse
pula
asla ; move low bits over.
asla
staa temp1 ; store temporarily.
ldaa LCDimg ; get LCD port image.
anda #$03 ; need low 2 bits.
oraa temp1 ; add in loiw 4 bits.
staa LCDimg ; save it
staa LCD ; output data
bsr enable_pulse
jsr delay_50us
pulx
rts
enable_pulse:
; bset LCD_ENimg ENABLE ; ENABLE=high
ldaa LCD_ENimg
oraa #ENABLE
staa LCD_ENimg
staa LCD_EN
; bclr LCD_ENimg ENABLE ; ENABLE=low
ldaa LCD_ENimg
anda #NOT_ENABLE
staa LCD_ENimg
staa LCD_EN
rts
delay_10ms: pshx
ldx #TEN_MS
bsr del1
pulx
rts
delay_5ms: pshx
ldx #FIVE_MS
bsr del1
pulx
rts
delay_50us: pshx
ldx #FIFTY_US
bsr del1
pulx
rts
;
; 250ns delay at 24MHz bus speed
;
del1: dex ; 1 cycle
inx ; 1 cycle
dex ; 1 cycle
bne del1 ; 3 cylce
rts
;;;;;;;;;;;FUNCTIONS TO CALL BY USER BELOW;;;;;;;;;;;;;;
LCDOUT:
pshx
pshy
pshd
jsr delay_10ms ; delay 20ms during power up
jsr delay_10ms
jsr lcd_ini ; initialize the LCD
jsr disp ;display blank to start
puld
puly
pulx
rts
disp:
ldx #str1 ; str1 for line1, x points to message 1
ldab cnt1 ; send out cnt1 characters
jsr lcd_line1
ldx #str2 ; str2 for line2, cnt2 points to message 2
ldab cnt2 ; send out cnt2 characters
jsr lcd_line2
jsr delay_10ms
jsr delay_10ms
; jmp disp loop on display to refresh
rts ;rts instead of auto-loop refresh
;----------------------------------------------------------------------------------------
;--------------------------- END OF LCD SUBROUTINE --------------------------------------
;----------------------------------------------------------------------------------------