📄 200.asm
字号:
$MOD51
;$TITLE(KEY BOARD FOR IBM AT)
;$DATE(DEC-17-98)
;$NOPAGING
;---------------
; new key layout
;---------------
;---constant definitions---
KeyMask EQU 07H ; used to force head, tail pointers in range
; Stack 60H to 7FH
STACK EQU 5FH ; one less than actual stack
; Keycode table offset
; AT codes are first, then the bit table for the key
TableCol EQU 2 ; number of bytes per key in table
BitByteOffset EQU 1 ; in table
ShiftKeyOffset EQU 03H ;sea 2003. 64 ; shift key matrix code offset
;---internal variable declarations---
; 00-07 RO-..-R7 using register bank0
LastDown DATA 08H ; stores last key down matrix address
WatchCtr DATA 09H ; watchdog counter
DebncPtr DATA 0AH ; pointer to debounce queue
CHANGES DATA 0BH ; holds keys in given column
ChgMask DATA 0CH ; bit mask used to find key that changed
KEY_OFFSET DATA 0DH
RepeatRate DATA 0EH ; keyboard repeat rate
RptCtr DATA 0FH ; autorepeat counter
BuzzerCounter DATA 10H
; 11H-12H not used
WchDogByte DATA 13H ; watchdog memory byte
TxCtr DATA 14H ; bit counter for sending data to IBM
TenMsCtr DATA 15H ; ten millisecond count
RepeatDelay DATA 16H ; of keyboard
TEMP DATA 17H ; save received byte from AT
LastSent DATA 18H ; last byte sent to host
RESEND_BYTE DATA 19H ; save byte that is to be resent to AT
; 1AH -1FH not used
DIAGNOSIS DATA 20H ; keyboard diagnostic byte
;--------
ShiftPushed BIT DIAGNOSIS.4 ; shift key flag
HostReset BIT DIAGNOSIS.5
FLAGS DATA 21H ; flags byte
;----
REPEATING BIT FLAGS.0 ; last key down is repeating
SCANNING BIT FLAGS.1 ; scan in progress
DelayFlag BIT FLAGS.2 ; scan routine pushed a value onto
; debounce delay que so skip next update
ReceivingCommand BIT FLAGS.3 ; from IBM
RESPONDING BIT FLAGS.4 ; sending command response to IBM AT
Cmd2ndByte BIT FLAGS.5 ; receiving 2nd data byte from IBM AT
UpLoading BIT FLAGS.6 ; sending data(keyinfo,message) to IBM AT
FLAGS2 DATA 22H
;-----
BadParity BIT FLAGS2.1 ; Parity bit bad in reception
DoAAH BIT FLAGS2.2 ; Tells warm start to send AAH power up code
WarmStart BIT FLAGS2.3 ; warm start - electro static discharge hit
KbIsAble BIT FLAGS2.4 ; matrix
NUM_LOCK BIT FLAGS2.5 ; num lock status
SCROLL_LOCK BIT FLAGS2.6 ; scroll lock status
CAPS_LOCK BIT FLAGS2.7 ; caps lock status
; 23H,24H not used
; Keyboard fifo pointer addresses
TailPntr DATA 25H ; fifo tail pointer
HeadPntr DATA 26H ; fifo head pointer
FifoFul BIT 26H.7 ; hi bit of headpntr - to show fifo is full
; 27H - 3FH not used
SHIFT_KEY DATA 28H ;sea 12.9
shift_sign BIT SHIFT_KEY.0 ;sea 12.9
shift_ok BIT SHIFT_KEY.1 ;sea 12.9
; Image of matrix 40H TO 47H, column0 to 7
; 48H TO 4FH reserved for matrix expansion
ImgLow DATA 40H ; status ram low address
ImgHigh DATA 47H ; status ram high address
; buffer 50H TO 57H
BufrLow DATA 50H ; low address of fifo
BufrHi DATA 57H ; high address of fifo
; Debounce delay queue 58H TO 5FH
DebncBot DATA 58H ; delay_Queue limits for debouncing
DebncTop DATA 5FH
; SFR bits
DataOut BIT P3.0 ; host data drive line -RXD
ClockOut BIT P3.1 ; host clock drive line -TXD
ClkIn BIT P3.2 ; host clock sense line -INT0
DataIn BIT P3.3 ; host data sense line -INT1
;---external variable declaration---
Xmem XDATA 0000H
; timer 0 is used here as a 1 millisecond timer ISR
; configure timer 0 in mode 0 -> 13 bit timer
; will only set TH0 -> 8 most significant bits of 13 bit timer
;*************************************************************
; for 16 Mhz crystal,
; time per tick = 1 / (crystal/12) = 12 / crystal = 0.75 uSEC
; 1 mSEC = 1000 uSEC, no. of ticks = 1000 / .75 = 1333
; Timer 0 (13 bit counter = 2000H (8192) will overflow interrupt).
; counter = 8192 - 1333 = 6859
; 6859 / 32 = 214.3 (prescale 32)-->set TH0 = 214
; 214 * 32 = 6848 --> INT. tIME = (8192 - 6848)*.75 = 1.008 msec
;**************************************************************
; timer 1, serial port not used
; 2 interrupt sources are used : timer0 , int1
; lowest priority interrupts : timer0
;****************************
; Interrupt Vector Table
;****************************
ORG 0000
JMP BEGIN
ORG 000BH ; timer0 overflow
JMP TIMER0
ORG 0013H ; external interupt 1,IBM data line went low
JB UpLoading,IntClr ; if sending data, ignore this interrupt
CALL FromHost? ; else, read command from IBM-AT
IntClr:
RETI
;*************************
; Initialization
;*************************
ORG 0030H
BEGIN:
MOV R0,#7FH ;>>
ClearInternal:
MOV @R0,#0
DJNZ R0,ClearInternal
MAIN:
; MOV 8EH,#3H ; sea 12.9 cpu: 89E554RC
MOV A,#0 ; sea 12.9
MOV SHIFT_KEY,A ; sea 12.9
MOV IE,#0 ; disable all interrupts
MOV TCON,#0 ; stop timer0
MOV P1,#0EFH ;>> turn buzzer off
MOV P3,#0FFH
CALL IntClr
CALL IntClr
CALL IntClr
CLR A
MOV PSW,A ; BANK 0
INIT1:
CLR SCANNING
CLR ShiftPushed ; reset shift key flag
SETB ClockOut ; clock line high
SETB DataOut ; data line high
SETB ClkIn
SETB DataIn
JNB ClkIn,INIT1 ; wait for clock to go high
INIT2:
MOV SP,#STACK ; 5FH
CLR ReceivingCommand ; not receiving AT commands
MOV R0,#DebncTop ; 5FH
INIT3:
MOV @R0,#0FFH
DEC R0
CJNE R0,#DebncBot - 1,INIT3 ; 58H
MOV HeadPntr,#BufrLow ; FIFO_HEAD := 50H
MOV TailPntr,#BufrLow ; FIFO_TAIL := 50H
MOV DebncPtr,#DebncBot ; 58H
MOV WatchCtr,#100
; setup timer0
MOV TenMsCtr,#10
MOV TH0,#214 ;>> for 1 msec. interrupts
MOV RptCtr,#127 ; make watchdog happy
MOV IE,#86H ; enable EXT1,TIMER0 interrupts
MOV TCON,#14H ; start timer0-EXT1 edge triggered
SETB KbIsAble
INIT4:
; initilization signal:
; will turn shift key led on and then stays on until communication with host.
; then led will be turned off before really starting keyborad routine.
JNB WarmStart,ColdBoot
MOV FLAGS,#0
JB DoAAH,SendAA
JMP MainLoop
; set keyboard defaults-power up reset only
ColdBoot:
MOV RepeatRate,#10 ; default repeat rate, in 10's of msec
MOV RepeatDelay,#50 ; default repeat delay, in 10's of msec
SETB ClockOut
SETB DataOut
SETB ClkIn
SETB DataIn
MOV A,DIAGNOSIS ; get error flags
ANL A,#07H ; single out error bits
JZ SendAA ; jump if no errors
MOV A,#0FDH ; get failure code
CALL ToHost ; send to host
JMP ColdCont
SendAA:
MOV A,#0AAH ; load power-up reset successful code
CALL ToHost ; and send it to the host
CLR DoAAH
ColdCont:
SETB WarmStart ; show that a cold boot has been performed
; due to the speed of xtal we use (12 mhz), it is far too fast
; we need to slow down in order to sync with host, otherwise
; host will think that keyboard is going to send code to it
; then host will lock up. I believe that 100 msec should be long enough.
;***************
; main loop
;***************
MainLoop:
CALL FromHost? ; see if AT is trying to send to keyboard
CALL DecodeKey_SendToHost ; key offset to scan code and send
CALL WatchDog ; check to make sure timer0 is working
JMP MainLoop
;*****************************************
;1msec timer 0 Interrupt Service Routine
;*****************************************
; background
TIMER0:
using 0 ; sea 12.6 addition
PUSH PSW
PUSH ACC
PUSH AR0 ;sea 12.6
MOV A,BuzzerCounter ;>>
JZ RELOADING
DJNZ BuzzerCounter,RELOADING
CLR P1.4 ; turn buzzer off
RELOADING:
MOV TH0,#214 ; reload timer0
MOV WchDogByte,#0AAH ; tweek foreground watchdog memory
DJNZ TenMsCtr,TIM4 ; if 10 milliseconds have gone by
MOV TenMsCtr,#10 ; restart 10 msec timer
; test the repeat counter and watchdog
DEC RptCtr ; RptCtr used for autorepeat
MOV A,RptCtr ; timing and as a background watchdog
CJNE A,#80H,TIMER0_END ; it should always be less than 128
SETB WarmStart
CLR DoAAH
JMP MAIN
TIM4:
JB ReceivingCommand,TIMER0_END
MOV A,TenMsCtr
CJNE A,#4,TIM8 ; scanning is done on the 4msec
JMP SCAN_TIME ; count of the ten msec timer
TIM8:
CJNE A,#8,TIMER0_END ; scan also done on the 8 msec count
; Time to scan the keyboard
SCAN_TIME:
JB SCANNING,TIMER0_END ; if scan not in progress
JNB KbIsAble,TIMER0_END
SETB SCANNING ; show scanning is taking place
CALL IRET ; re-enable the timer0 interrupt
; Update the debounce que before jumping to the scan routine
; if this is the 8msec time
CJNE A,#8,TIM5 ; if time for debounce update
JBC DelayFlag,TIM5 ; and scan routine hasn't updated it
MOV KEY_OFFSET,#0FFH ; initial Key Offset to invalid code
INC DebncPtr ; and push it on the debounce que
MOV A,DebncPtr ; put pointer in range
ADD A,#-(DebncTop+1) ; CY=1 IF A>=DebncTop+1 OR A>DebncTop
JNC PntrOk ; if pointer overflows
MOV DebncPtr,#DebncBot ; set to bottom of que
PntrOk:
MOV R0,DebncPtr ; put value into indirect
MOV @R0,KEY_OFFSET ; push the byte onto the que
TIM5:
CALL SCAN_MATRIX
TIMER0_END:
POP AR0 ;sea 12.6
POP ACC
POP PSW
IRET:
RETI
;******************************
;(1) Scan Matrix Routine
;******************************
; background
SCAN_MATRIX:
using 0 ; sea 12.6 addition
PUSH AR1 ;sea 12.6
MOV R1,#ImgLow ; 40H
ScanLoop:
CALL ScanColumn
JZ NextColumn ; no change scan next column
JMP ValidityTest ; if any keys changed, go validate them
NextColumn:
INC R1 ; else, set up to test next col
CJNE R1,#ImgHigh + 1,ScanLoop ;>>
;---------------sea----------------------
; JNB P1.1,sea1
;sea3:
; JB shift_ok,ScanDone
; CLR shift_sign
; JMP ScanDone
;sea1:
; JB shift_sign,ScanDone
; call Clock20
; JNB P1.1,sea2
; JMP sea3
;sea2:
; call Clock20
; JNB P1.1,sea4
; JMP sea3
;sea4:
; SETB shift_sign
; SETB shift_ok
;---------------sea----------------------
ScanDone:
CLR SCANNING ; show we are done scanning
POP AR1 ;sea 12.6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -