⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 200.asm

📁 用8051实现的PS2协议的PC键盘
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	RET
; 1.check validity of R1
; 2.key debounce
; 3.matrix image update
; 4.combine (key offset) & (F0: key pushed or released)->pushed into FIFO
ValidityTest:
	MOV CHANGES,A          ; save XOR result
	MOV A,TL0              ; additional software watchdog tests
	NOP                    ; make sure timer is still running
	NOP                    ; delay to allow timer to increment
	XRL A,TL0              ; see if timer value changed
	JZ InitVect            ; no change abort
	MOV A,R1               ; now check range of image pointer
	ADD A,#-(ImgHigh+1)    ; CY=1 if A>ImgHigh
	JC InitVect            ; reboot if R1>ImgHigh
	MOV A,R1
	ADD A,#-ImgLow         ; CY=1 if A>=ImgLow
	JC ValidImage          ; reboot if R1<ImgLow
InitVect:
	SETB WarmStart
	CLR DoAAH
	JMP MAIN
ValidImage:
	MOV R0,#90             ; delay before validity check
	DJNZ R0,$
        PUSH DPH
        PUSH DPL
        PUSH ACC
        MOV DPTR,#Xmem
        MOV A,#0FFH
        MOVX @DPTR,A
        POP ACC
        POP DPL
        POP DPH
	CALL ScanColumn        ; test the current col. again
	ANL A,CHANGES          ; compare old changes with new
	JNZ NewKeys            ; if nothing changed,
	JMP NextColumn         ; go test next col
NewKeys:
	MOV CHANGES,A          ; else, save the valid changes
	MOV ChgMask,#1         ; set up a mask for testing keys that changed
	MOV A,R1               ; calculate key offset
	ADD A,#-(ImgLow)       ; based on column# in image
 	SWAP A                 ; column# = R1 - ImgLow 
	RR A                   ; offset row0 key of column =  column# * 8
	MOV KEY_OFFSET,A       ; low 3 bits will later become row number
	MOV A,ChgMask          ; get key change mask
TstKeys:
	ANL A,CHANGES          ; if key in this row changed
	JNZ KeyChg             ; go process
TestMore:
	MOV A,CHANGES          ; else, test if no more changed
	JZ NextColumn          ; go scan next col
	MOV A,ChgMask          ; else, rotate mask and try next row
	CLR C
	RLC A
	MOV ChgMask,A
	JNC DoMore             ; if last row in col
	JMP NextColumn         ; go try next column
DoMore:  ; above code is designed for 8 keys per column
	INC KEY_OFFSET         ; else, adjust offset for next row
	JMP TstKeys            ; do all 8 rows
KeyChg:   ; mask has identified a changed key
	JNB FifoFul,KEYC       ; if the fifo is full, quit the scan
	JMP ScanDone
KEYC:
        MOV A,ChgMask          ; else
	CPL A
	ANL A,CHANGES
	MOV CHANGES,A          ; clear out the detected bit in CHANGES
	MOV A,ChgMask
	ANL A,@R1              ; find out if key was up or down before
	JNZ KeyUp1             ; if key was up, then it went down
KeyDown:
	MOV A,ChgMask          ; process the down key
	ORL A,@R1              ; make the image RAM status for this key
	MOV @R1,A              ; match the current state
	SETB DelayFlag ; flag timer0 that a key went on the Delay_Que
	INC DebncPtr           ; push the key offset value onto the delay que
	MOV A,DebncPtr         ; test pointer for overflow
	ADD A,#-(DebncTop+1)   ; CY=1 if A>DebncTop
	JNC DebncOk            ; if overflow
	MOV DebncPtr,#DebncBot ; set to bottom of que
DebncOk:
	MOV R0,DebncPtr        ; put pointer in index
	MOV @R0,KEY_OFFSET     ; store the key offset in the que
	MOV A,KEY_OFFSET       ; now push the key offset onto the FIFO
	CLR F0                 ; flag as a down code
	CALL PushKey           ; call the push routine
        SETB P1.4;>> buzzer on for 50msec
        MOV BuzzerCounter,#50
	JMP TestMore           ; then go back and test some more keys
KeyUp1:
	MOV R0,#DebncBot       ; if the key is in the que
STKTST:
        MOV A,KEY_OFFSET       ; don't let it go up yet
	XRL A,@R0              ; search the que
	JZ TestMore            ; if found in que, go test more
        INC R0                 ; inc and test R0
	MOV A,R0
	ADD A,#-(DebncTop+1)   ; C=1 if ACC > DebncTop
	JNC STKTST             ; loop until R0 > DebncTop
; key not found in delay que, okay to send up
	MOV A,ChgMask          ; clear the key's bit in image RAM
	XRL A,@R1
	MOV @R1,A
	MOV A,KEY_OFFSET       ; then push the key offset value
	SETB F0                ; marked as an up code
	CALL PushKey           ; onto the FIFO
	JMP TestMore
;*****************************
;(2)    Push Key onto FIFO
;*****************************
; background
PushKey:
	MOV R0,A               ; save byte-key offset
	MOV A,HeadPntr
	JB FifoFul,POK         ; if fifo full, dump byte
	ADD A,#-(BufrLow-1)
        ANL A,#KeyMask         ; 7
	ADD A,#BufrLow         ; inc and adjust headpntr
	XCH A,R0
	MOV C,F0               ; put up/down flag in msbit of offset
        MOV ACC.7,C
	MOV @R0,A              ; store byte in FIFO
	MOV A,R0
	CJNE A,TailPntr,POK    ; is FIFO full
        ORL A,#80H             ; set full flag
POK:
        MOV HeadPntr,A
	RET
;******************************
;(3)    Keycode Buffer Pop
;******************************
PopKey:
	MOV A,TailPntr         ; compare tail pointer with head
	CJNE A,HeadPntr,NotEmpty ; to see if FIFO is empty
	SETB C                 ; if empty, set carry bit and exit
	RET
NotEmpty:
        ADD A,#-(BufrLow-1)    ; else
	ANL A,#KeyMask         ; force tail pointer to be in
	ADD A,#BufrLow         ; range (software watch), then increment
	MOV R0,A               ; and store value in R0
	MOV A,@R0              ; retrieve key-offset from FIFO
	MOV C,ACC.7            ; retrieve Up/Down flag from the msb
	MOV F0,C               ; of data, and store in flag 0
	CLR ACC.7              ; clear flag out of data
	MOV TailPntr,R0        ; save new tail pointer
	CLR FifoFul            ; clear FIFO full flag, if it was set
	CLR C                  ; clear carry to show pop was successful
	RET
;******************************************
;>>(4)   Process Key Information Routine
;******************************************
DecodeKey_SendToHost:
        JB KbIsAble,DoIt
        JMP TestDone
; get key offset
DoIt:
;------------sea-----------
;	JNB shift_ok,sea80
;	CLR shift_ok
;	MOV A,#64
;	JMP SUCCESS
;sea80:
;------------sea----------
	CALL PopKey            ; pop key offset from FIFO
        JNC SUCCESS            ; c = 0 means PopKey was successful
        JMP TestRepeating      ; if FIFO is empty, go test for repeating key
SUCCESS:
; check key offset for "shift" key and set led
	CJNE A,#ShiftKeyOffset,NotShiftKey ; 33  
;sea01:
        JB F0,ShiftUp_DoNothing		
        CPL P1.0
        CPL ShiftPushed
ShiftUp_DoNothing:
        JMP TestDone
; now we want DPTR to point to key code in table. there are 2 bytes per key
; in the key scan code table, so offset must be multiplied by 2 to get the no.
; of bytes from start of table.this is then added to the table base address.
NotShiftKey:
        MOV R1,A               ; save the offset for later use
	MOV B,#TableCol        ; 2 - number of bytes per key in table
	MUL AB
	JNB ShiftPushed,NonShft1
 	ADD A,#LOW (ShiftKeyBase) ; if shift key depressed
        JMP NonShft2
NonShft1:
        ADD A,#LOW (KeyBase)   ; if shift key not depressed
NonShft2:
	MOV DPL,A
	MOV A,B
	JNB ShiftPushed,NonShft3
	ADDC A,#HIGH (ShiftKeyBase) ; add carry into high byte of address
        CLR ShiftPushed
        SETB P1.0
	JMP NonShft4
NonShft3:
	ADDC A,#HIGH (KeyBase)
NonShft4:
	MOV DPH,A              ; DPTR = Base + 2(key offset)
; if key code is 0 e.g. DEAD POSITION exit
	CLR A
        MOVC A,@A+DPTR         ; get key scan code from the table
        MOV R7,A ; save key code temporarily
	JNZ SendPrefixes
	JMP DecodeRet
; else send prefixes first depending on key (low,high,special)
SendPrefixes:
	MOV A,#BitByteOffset   ; 1
	MOVC A,@A+DPTR         ; read bit byte for this key
        JNB ACC.0,SpecialOrHigh
        MOV A,#0F0H
        CALL ToHost
	MOV A,#59H             ; right shift key is up(low)
	CALL ToHost
        JMP WentUpOrDown?
SpecialOrHigh:
	JB ACC.5,SPECIAL
        MOV A,#59H             ; right shift key is down(high)
        CALL ToHost
        JMP WentUpOrDown?
SPECIAL:  ; cursors,insert,home,page up/dn,delete,end
	MOV A,#0E0H            ; cursor keys on the AT send this code first
	CALL ToHost            ; so that keys are not affected by numlock
WentUpOrDown?:
        JNB F0,JustKeyCode
	MOV A,#0F0H            ; up code
	CALL ToHost            ; send it
JustKeyCode:
        MOV A,R7 ; key code
        CALL ToHost            ; send key scan code
; check autoRepeating now
        MOV A,LastDown         ; see if this key should be autorepeating
	XRL A,R1               ; compare this to last key down offset
	JB F0,KEYUP            ; if key gone down and LastDown != new key
	JZ DecodeRet           ; then repeat this key
        MOV LastDown,R1        ; load matrix offset as last key down
	MOV RptCtr,RepeatDelay ; load repeat delay into counter
        SETB REPEATING         ; and start autorepeating
	JMP DecodeRet          ; timer0 int. controls repeat delay and rate
KEYUP:
        JNZ DecodeRet
	CLR REPEATING ; if LastDown == R1 and gone up stop repeating
	MOV LastDown,#0FFH
	JMP DecodeRet
TestRepeating:
; add here to prevent send last byte while host is initializing
        JB HostReset,TestDone
	JNB REPEATING,TestDone ; if a key is repeating
	MOV A,RptCtr           ; get repeat count
	JNB ACC.7,DecodeRet    ; test for delay complete
  	ADD A,RepeatRate       ; if delay complete
	MOV RptCtr,A           ; reload with repeat rate
	MOV A,LastDown         ; and send host the down code again
        CLR F0                 ; with down flag
	JMP SUCCESS            ; go send repeating key
TestDone:
	MOV RptCtr,RepeatDelay ; if not repeating, keep RptCtr near 0
DecodeRet:
	RET
;**********************************
;(5)    Upload to Host Routine
;**********************************
; send the command response byte in the acc
SendResponse:
	MOV RptCtr,RepeatDelay
        SETB RESPONDING     ; sending a command response
	JMP TOH1
; resend the data byte in the acc
; used after transmission was interrupted by a command request
RESEND:
        MOV A,RptCtr        ; adjust repeat counter
	JNB ACC.7,RES1      ; if necessary
	MOV RptCtr,#5
RES1:
        MOV A,RESEND_BYTE   ; get byte back and try to send it again
ToHost:                     ; synchronous data transfer to host
        CLR RESPONDING      ; show this is not a command response
	SETB UpLoading      ; show us sending to the host
; all send entry points end up here
TOH1:
        CLR EA              ; disable interrupts during this routine
	MOV C,P             ; get parity of byte from PSW bit P
	CPL C               ; convert 8051 even parity to odd for host
	MOV R0,A            ; save data
	MOV TEMP,A          ; preserve it for later
	MOV TxCtr,#9        ; initial transmit bit counter
	MOV A,#40           ; set up loop counter
TOH2:
        SETB ClkIn          ; assure transmit and receive
	SETB DataIn         ; clock and data bits are in proper
	SETB DataOut        ; drive and receive sense
	SETB ClockOut       ; software watch
	JB DataIn,TOH4      ; jump out if host wants to send
TOH3:
        JMP ToHAbort
TOH4:
        JB ClkIn,TOH5       ; wait 40 loops for host to get unbusy
        DJNZ ACC,TOH2
	JMP ToHAbort        ; if still busy, abort send
TOH5:
        CLR DataOut         ; set data line low for start bit
	CALL Clock20        ; delay for lines to settle (half clock cycle)
	CLR ClockOut        ; set clock line low
	CALL Clock40        ; delay for one clock period
	SETB ClockOut       ; set clock high
	CALL Clock20
	JNB ClkIn,ToHAbort  ; if clock stays low, host busy, abort TX
SendLp:
	MOV A,R0            ; get data byte we are transmitting
	RRC A               ; rotate current bit to transmit into carry
	MOV R0,A            ; save remainder and parity (that was in carry)
	MOV DataOut,C       ; move carry bit value to data output bit
	CALL Clock20        ; then delay a half clock cycle

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -