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

📄 kbdisr.asm

📁 mcs51,2051,x86系列MCU
💻 ASM
字号:
TITLE "KBDISR.ASM"
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;   File:        kbdisr.asm
;   Author:      Steve Roberts    8/2/96
;   Description: Converts legacy PS/2 keyboard signals to USB format.
;                This code is vectored to via the INT1 interrupt. The
;                keyboard sends 11 clock pulses for data output and
;                for receiving data from the system.  Each of these
;                pulses is a separate call to this ISR.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include  donconst.inc
include  externs.inc
include  82930.inc

extern   SEND_KBD_REPORT_EP2

define KBDISR_VECTOR,SPACE=CODE, ORG=004013H  ; For DEBUGGER
segment KBDISR_VECTOR
        ejmp  KBD_ISR

;define KBDISR_VECTOR,SPACE=CODE, ORG=FF0013H   ; For burning FLASH
;segment KBDISR_VECTOR
;       ejmp  KBD_ISR


define KBDISR,SPACE=CODE
segment KBDISR

KBD_ISR: 
    push  PSW1
    push  PSW
    push  R0
    push  R1
    push  R2
    push  R3
    push  WR16
    push  ACC
     
    mov   A, KBD_MODE                ; Checks to see if it is a send
    jz    SEND                       ; to the kbd, or a reception
    lcall RCV_FROM_KBD               ; 0=send, 1=receive
    jmp   EXIT_KBD_ISR

SEND:
    lcall SEND_TO_KBD
      
EXIT_KBD_ISR:
    pop   ACC   
    pop   WR16
    pop   R3
    pop   R2
    pop   R1
    pop   R0
    pop   PSW
    pop   PSW1 
    reti   


;--------------------------------------------------------------
;   Function:    RCV_FROM_KBD
;   Description: Handles data bits from the keyboard and coverts
;                them to bytes that are stored in the keyboard
;                data buffer.  Bytes are stored in the buffer as
;                USB usage index codes - not keyboard make/break
;                codes.
;   Called from: Within kbdisr.asm
;---------------------------------------------------------------
RCV_FROM_KBD:                            
            
    dec   BIT_COUNT          
    mov   A, BIT_COUNT
    jz    RPARITY
    mov   R1, #0FFh    
    cmp   R1, BIT_COUNT        ; BIT_COUNT=FF at stop bit
    je    STOP_BIT     

    mov   A, P3                ; Handle d0-d7
    anl   A, #010h
    rl    A
    rl    A
    rl    A
    mov   R1, A
    mov   R0, DATA_FROM_KBD
    orl   R0, R1
    mov   DATA_FROM_KBD, R0
    mov   R1, #01h
    cmp   R1, BIT_COUNT        ; Branch to shift if start-d6
    jsl   START_D6
    ret                        ; When at d7, skip 
                                        
START_D6:
    mov   R0, DATA_FROM_KBD
    srl   R0
    mov   DATA_FROM_KBD, R0
    ljmp  EXIT_RCV_FROM_KBD

RPARITY:
    mov   A, DATA_FROM_KBD     ; From kbd receive parity 
    mov   R1, PSW
    anl   R1, #01h             ; If data has odd# bits=1 then r1=1
    mov   A, R1
    rl    A
    rl    A
    rl    A
    rl    A
    anl   A, P3                ; All ok if A=0
    jnz   RPARITY_ERROR
    ljmp  EXIT_RCV_FROM_KBD

RPARITY_ERROR:
    mov   KBD_MODE, #0         ; Set keybd to rcv mode
    mov   DATA_TO_KBD, #KBD_RESEND
    mov   BIT_COUNT, #0Ah
    clr   P3.4                 ; RTS to kbd - 
                               ; Kbd will send clk pulses  
    ljmp  EXIT_RCV_FROM_KBD

STOP_BIT:
    jnb   P3.4, RPARITY_ERROR  ; Issue resend if no stop bit
    mov   BIT_COUNT, #0Ah
    mov   R0, DATA_FROM_KBD
                
    cmp   R0, #0FAh            ; Different handling for kbd
    je    RCV_INIT_ACKS        ; Initialization bytes
    cmp   R0, #0AAh
    je    RCV_INIT_ACKS
    cmp   R0, #0FEh
    je    RCV_INIT_ACKS
    cmp   R0, #0FCh
    je    RCV_INIT_ACKS
    cmp   R0, #0EEh
    je    RCV_INIT_ACKS
    
    cmp   R0, #0F0h            ; KBD sends F0 before break code
    je    BREAK_CODE_COMING

    mov   DPTR, #KEY_CODE_TABLE  ; Converts keycodes to USB usage
    mov   KEY_CODE_INDEX, #0     ; index codes
    lcall KEY_CODE_LOOP       
    mov   DATA_FROM_KBD, KEY_CODE_INDEX
    mov   R0, DATA_FROM_KBD
    mov   P1, DATA_FROM_KBD
    mov   R1, BREAK_CODE_MODE
    cmp   R1, #1
    je    REMOVE

    lcall ADD_A_KEY
    sjmp  EXIT_RCV_FROM_KBD

REMOVE:
    lcall REMOVE_A_KEY
    sjmp  EXIT_RCV_FROM_KBD

BREAK_CODE_COMING:
    mov   BREAK_CODE_MODE, #1
    sjmp  EXIT_RCV_FROM_KBD

RCV_INIT_ACKS:  
    mov   KBD_COMMAND, R0
    sjmp  EXIT_RCV_FROM_KBD  
             
;-------------------------------------------------------------------
;     Function    : KEY_CODE_LOOP    
;     Description : Converts keycodes to USB Usage Index Codes 
;     Called from : Within kbdisr.asm by function "RCV_FROM_KBD"
;-------------------------------------------------------------------
KEY_CODE_LOOP:
    mov   A, KEY_CODE_INDEX      ; Does scan set 3 keycode
    movc  A, @A+DPTR             ; conversion to USB Usage
    mov   R1, A                  ; Index code
    cmp   R0, R1
    je    EXIT_KEY_CODE_LOOP
    inc   KEY_CODE_INDEX
    mov   R1, #0E8h              ; Watch for overrun of key code table
    cmp   R1, KEY_CODE_INDEX
    je    RESET_INDEX
    ljmp  KEY_CODE_LOOP

RESET_INDEX:
    mov   KEY_CODE_INDEX, #0     ; Start from the top again
    ljmp  KEY_CODE_LOOP          ; No real good way to handle this
                                 ; but it SHOULD never happen
EXIT_KEY_CODE_LOOP:
    ret
;-------------------------------------------------------------------

EXIT_RCV_FROM_KBD:
    ret                
;-------------------------------------------------------------------




;-------------------------------------------------------------------
;    Function:    ADD_A_KEY
;    Description: Adds new keycodes to buffer
;    Called from: Within kbdisr.asm by function "RCV_FROM_KBD"
;-------------------------------------------------------------------
ADD_A_KEY:      
    mov   WR16, #KBD_BUFFER_START
    ;mov   A, USB_PROTOCOL        ; USB Boot protocol has different
    ;jz    ADD_TO_BOOT_FORMAT     ; report format than Item Protocol

ADD_TO_ITEM_FORMAT:
    inc   WR16, #1               ; To get past ID byte
    cmp   R0, #0E1h              ; E1h is the left SHIFT key
    je    ADD_LEFT_SHIFT
    cmp   R0, #0E5h              ; E5h is the right SHIFT key
    je    ADD_RIGHT_SHIFT
    cmp   R0, #0E0h              ; E0h is the left CTRL key
    je    ADD_LEFT_CTRL
    cmp   R0, #0E4h              ; E4h is the right CTRL key
    je    ADD_RIGHT_CTRL
    cmp   R0, #0E2h              ; E2h is the left ALT key
    je    ADD_LEFT_ALT
    cmp   R0, #0E6h              ; E6h is the right ALT key
    je    ADD_RIGHT_ALT
                
    ;inc   WR16, #1
    add   WR16, #02h           ; To get past mod & reserved bytes
ADD_LOOP:
    mov   R1, #0
    cmp   R1, @WR16
    je    WRITE_KEYCODE          ; Find first empty location in buffer
    inc   WR16, #1
    cmp   WR16, #KBD_BUFFER_END
    jg    SEND_ERROR_ROLLOVER_STATE ; Too many keys hit - send all 01's
    jmp   ADD_LOOP              

WRITE_KEYCODE: 
    mov   @WR16, R0
    sjmp  EXIT_ADD_A_KEY

ADD_LEFT_SHIFT:
    mov   R0, @WR16            ; Modifier key bit-map (HID Spec 1.0):
    orl   R0, #002h            ; d0= Left Ctrl
    mov   @WR16, R0            ; d1= Left Shift
    sjmp  EXIT_ADD_A_KEY       ; d2= left Alt
                               ; d3= Left GUI (not supported)
ADD_RIGHT_SHIFT:               ; d4= Right Ctrl
    mov   R0, @WR16            ; d5= Right Shift
    orl   R0, #020h            ; d6= Right Alt
    mov   @WR16, R0            ; d7= Right GUI (not supported)
    sjmp  EXIT_ADD_A_KEY       

ADD_LEFT_CTRL:
    mov   R0, @WR16
    orl   R0, #001h
    mov   @WR16, R0
    sjmp  EXIT_ADD_A_KEY

ADD_RIGHT_CTRL:
    mov   R0, @WR16
    orl   R0, #010h
    mov   @WR16, R0
    sjmp  EXIT_ADD_A_KEY

ADD_LEFT_ALT:
    mov   R0, @WR16
    orl   R0, #004h
    mov   @WR16, R0
    sjmp  EXIT_ADD_A_KEY

ADD_RIGHT_ALT:
    mov   R0, @WR16
    orl   R0, #040h
    mov   @WR16, R0
    sjmp  EXIT_ADD_A_KEY

SEND_ERROR_ROLLOVER_STATE:
    mov   ERROR_ROLLOVER_STATE, #1  ; report_req_isr checks this var
    sjmp  EXIT_ADD_A_KEY
               
EXIT_ADD_A_KEY:
    mov   R0, IDLE_MODE             ; If in idle mode, must fill FIFO
    cmp   R0, #0                    ; with new key event info
    je    RETURN_ADD_A_KEY          

    cmp   R0, #1                    ; If in INDEF IDLE mode, leave timer alone
    je    CALL_SEND_KBD_REPORT_EP2

    clr   TCON.4                    ; Disables timer0 until report is written
                                    ; Only done when in TIMED IDLE mode
CALL_SEND_KBD_REPORT_EP2:
    lcall SEND_KBD_REPORT_EP2

RETURN_ADD_A_KEY:
    ret                  
;-------------------------------------------------------------------


;-------------------------------------------------------------------
;    Function:    REMOVE_A_KEY
;    Description: Deletes necessary keycodes from buffer
;    Called from: Within kbdisr.asm by function "RCV_FROM_KBD"                    
;-------------------------------------------------------------------
REMOVE_A_KEY:
    mov   WR16, #KBD_BUFFER_START
    inc   WR16, #1               ; To get past ID byte
    cmp   R0, #0E1h              ; E1h is the left SHIFT key
    je    REMOVE_LEFT_SHIFT
    cmp   R0, #0E5h              ; E5h is the right SHIFT key
    je    REMOVE_RIGHT_SHIFT
    cmp   R0, #0E0h              ; E0h is the left CTRL key
    je    REMOVE_LEFT_CTRL
    cmp   R0, #0E4h              ; E4h is the right CTRL key
    je    REMOVE_RIGHT_CTRL
    cmp   R0, #0E2h              ; E2h is the left ALT key
    je    REMOVE_LEFT_ALT
    cmp   R0, #0E6h              ; E6h is the right ALT key
    je    REMOVE_RIGHT_ALT
           
;    inc   WR16, #1               ; To get past modifier byte
    add   WR16, #02h             ; To get past mod & reserved bytes
REMOVAL_LOOP:
    cmp   R0, @WR16
    je    CLEAR_KEY_CODE
    inc   WR16, #1
    cmp   WR16, #KBD_BUFFER_END
    jg    KBD_BREAK_CODE_ERROR   ; Happens when key was not placed (ERROR ROLLOVER STATE)
    mov   ERROR_ROLLOVER_STATE, #0  ; Since key is being removed, clear ER State
    jmp   REMOVAL_LOOP

CLEAR_KEY_CODE: 
    mov   R0, #0
    mov   @WR16, R0
    sjmp  EXIT_REMOVE_A_KEY

REMOVE_LEFT_SHIFT:
    mov   R0, @WR16              ; Modifier key bit-map (HID Spec 1.0):
    anl   R0, #0FDh              ; d0= Left Ctrl
    mov   @WR16, R0              ; d1= Left Shift
    sjmp  EXIT_REMOVE_A_KEY      ; d2= Left Alt
                                 ; d3= Left GUI (not supported)
REMOVE_RIGHT_SHIFT:              ; d4= Right Ctrl
    mov   R0, @WR16              ; d5= Right Shift
    anl   R0, #0CFh              ; d6= Right Alt
    mov   @WR16, R0              ; d7= Left GUI (not supported)
    sjmp  EXIT_REMOVE_A_KEY

REMOVE_LEFT_CTRL:
    mov   R0, @WR16
    anl   R0, #0FEh
    mov   @WR16, R0
    sjmp  EXIT_REMOVE_A_KEY

REMOVE_RIGHT_CTRL:
    mov   R0, @WR16
    anl   R0, #0EFh
    mov   @WR16, R0
    sjmp  EXIT_REMOVE_A_KEY

REMOVE_LEFT_ALT:
    mov   R0, @WR16
    anl   R0, #0FBh
    mov   @WR16, R0
    sjmp  EXIT_REMOVE_A_KEY

REMOVE_RIGHT_ALT:
    mov   R0, @WR16
    anl   R0, #0BFh
    mov   @WR16, R0
    sjmp  EXIT_REMOVE_A_KEY

KBD_BREAK_CODE_ERROR:
    sjmp  EXIT_REMOVE_A_KEY         ; Should reset system here (??)

EXIT_REMOVE_A_KEY:
    mov   R0, IDLE_MODE             ; If in idle mode, must fill FIFO
    cmp   R0, #0                    ; with new key event info
    je    RETURN_REMOVE_A_KEY          

    cmp   R0, #1                    ; If in INDEF IDLE mode, leave timer alone
    je    CALL2_SEND_KBD_REPORT_EP2

    clr   TCON.4                    ; Disables timer0 until report is written
                                    ; Only done when in TIMED IDLE mode

CALL2_SEND_KBD_REPORT_EP2:
    lcall SEND_KBD_REPORT_EP2

RETURN_REMOVE_A_KEY:
    mov   BREAK_CODE_MODE, #0
    ret
;------------------------------------------------------------------



;------------------------------------------------------------------
;    Function:    SEND_TO_KBD
;    Description: Sends commands to keyboard bit-by-bit.  
;    Called from: Within kbdisr.asm
;------------------------------------------------------------------
SEND_TO_KBD:    
    mov   R1, #0Ah
    cmp   R1, BIT_COUNT
    jne   NOT_FIRST_PASS
    mov   MASK_BIT, #1

NOT_FIRST_PASS:
    dec   BIT_COUNT
    mov   R1, #0FFh
    cmp   R1, BIT_COUNT          ; BIT_COUNT=FF when finished
    jne   D0_STOP
              
ACK:
    jnb   P3.4, OKAY             ; To check for ACK (P3.4 low)
                                 ;**WHAT TO DO IF NO ACK? - RESEND?
    sjmp  EXIT_SEND_TO_KBD

OKAY:
    mov   BIT_COUNT, #0Ah        ; ACK checked - all is ok
                                 ; Reset BIT_COUNT
    mov   KBD_MODE, #1           ; Set to "rcv from kbd" mode
    setb  P3.4                   ; Tells kbd all is okay            
    setb  P3.3
    sjmp  EXIT_SEND_TO_KBD   

D0_STOP:         
    mov   R1, #1               
    cmp   R1, BIT_COUNT          ; move_data until BIT_COUNT=1
    jsl   MOVE_DATA        

SEND_PARITY:
    mov   R3, #0
    cmp   R3, BIT_COUNT
    je    SET_BIT                ; Send stop bit if BIT_COUNT=0
    mov   A, DATA_TO_KBD         ; For parity check
    mov   R2, PSW
    anl   R2, #1
    cmp   R1, R2                 ; NOTE- kbd=odd parity; 82930=even
    je    CLR_BIT                ; If equal, odd # of bits sent
    jmp   SET_BIT                ; If not, even # of bits sent
 
MOVE_DATA:
    mov   R1, DATA_TO_KBD        ; Move data out one bit at a time
    anl   R1, MASK_BIT
    mov   R0, MASK_BIT
    sll   R0
    mov   MASK_BIT, R0
    mov   A, R1 
    jz    CLR_BIT
    
SET_BIT:                         ; Writes a data bit of "1"
    setb  P3.4                   
    sjmp  EXIT_SEND_TO_KBD

CLR_BIT:                         ; Writes a data bit of "0"
    clr   P3.4                   
    sjmp  EXIT_SEND_TO_KBD

EXIT_SEND_TO_KBD:
    ret
;-------------------------------------------------------------------

⌨️ 快捷键说明

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