📄 kbd9.asm
字号:
;----------------------------------------
;OUT_PHILIPS:
; MOV I2C_BUFFER,#WRITE_BUFFER
; MOV I2C_BUFFER+1,#0
; MOV I2C_BUFFER+2,#8
; MOV I2C_BUFFER+3,#0FDH
; MOV I2C_BUFFER+4,#50H ;'P'
; MOV I2C_BUFFER+5,#68H ;'h'
; MOV I2C_BUFFER+6,#69H ;'i'
; MOV I2C_BUFFER+7,#6CH ;'l'
; MOV I2C_BUFFER+8,#69H ;'i'
; MOV I2C_BUFFER+9,#70H ;'p'
; MOV I2C_BUFFER+10,#73H ;'s'
; MOV RW_COUNTER,#10
; LCALL WRITE_N_BYTE
; RET
;----------------------------------------
;=================================
READ_FROM_d11:
MOV SLV_ADR,#036H ;WRITE COMMAND
MOV CNT_BYTE,#1 ;NUMBER OF BYTES TO BE SENT
LCALL WRITE_d11_POINT ;READ 1 BYTES
;-----
MOV SLV_ADR,#035H ;READ DATA
MOV CNT_BYTE,RW_COUNTER
ACALL READ_d11
RET
;---------------------------------------
; WRITE DATA INTO ENDPOINT 0 INPUT
;---------------------------------------
WRITE_TO_d11:
;-----------
CLR VALIDATE_FLAG ;IS WRITE BUFFER COMMAND?
MOV A,I2C_BUFFER
XRL A,#WRITE_BUFFER
JNZ WRITE_TO_d11_1
SETB VALIDATE_FLAG
;
MOV I2C_BUFFER,#SEL_EPT_EMBF_IN ;SELECT EMBED IN BUFFER
AJMP SEL_EPT_COMMAND
SEL_EPT_COMMAND:
LCALL WRITE_COMMAND
MOV I2C_BUFFER,#WRITE_BUFFER
;-----------
WRITE_TO_d11_1:
MOV SLV_ADR,#036H ;WRITE COMMAND
MOV CNT_BYTE,#1 ;NUMBER OF BYTES TO BE SENT
ACALL WRITE_d11_POINT ;READ 1 BYTES
;----------
MOV SLV_ADR,#034H ;WRITE DATA
MOV CNT_BYTE,RW_COUNTER
ACALL WRITE_d11
;-----
JNB VALIDATE_FLAG,WRITE_RET ;ONLY WRITE BUFFER NEED VALIDATE BUFFER
MOV I2C_BUFFER,#VALIDATE_BUF ;READY DATA TO SEND
LCALL WRITE_COMMAND
;----
WRITE_RET:
RET
;----------------------------------------
;***************************************************************
;* Function = Read_d11
;* Input = SlvAdr (d11 slave address);
;* CNT_Byte (Number of Bytes to be sent);
;*
;* Return = I2C_BUFFER Buffer
;* Change = R0,R3
;****************************************************************
READ_d11:
MOV BYTE_CNT,CNT_BYTE
;----
ACALL GOMASTER ;ACQUIRE BUS AND SEND SLAVE ADDRESS.
JB I2C_FAIL,READ_NOK ;CHECK FOR SLAVE NOT RESPONDING.
;---
MOV R0,#I2C_BUFFER ;SET FIRST RECEIVE DATA BUFFER ADDRESS
READ_DATA_LOOP:
ACALL RCV_BYTE ;RECEIVE DATA BYTE
MOV @R0,A ;PUT RECEIVED DATA TO BUFFER
INC R0 ;PREPARE NEXT BYTE
DJNZ BYTE_CNT,READ_DATA_LOOP ;REPEAT UNTIL ALL BYTES RECEIVED
READ_NOK:
READ_OK:
ACALL SEND_STOP ;DONE, SEND AN I2C STOP.
RET
;========================================
RCV_BYTE:
MOV BITCNT,#8 ;SET BIT COUNT.
RCV_LOOP:
ACALL SCLHIGH ;READ ONE DATA BIT.
ACALL BITDLY
MOV C,SDAPIN ;GET DATA BIT FROM PIN.
RLC A ;ROTATE BIT INTO RESULT BYTE.
CLR SCLPIN
ACALL BITDLY
DJNZ BITCNT,RCV_LOOP ;REPEAT UNTIL ALL BITS RECEIVED.
;---
PUSH ACC ;SAVE ACCUMULATOR
MOV A,BYTE_CNT
CJNE A,#1,SRBACK ;CHECK FOR LAST BYTE OF FRAME.
SETB SDAPIN ;SEND NO ACKNOWLEDGE ON LAST BYTE.
SJMP SRBACLK ;NO ACK WHEN IT'S LAST BYTE
;----
SRBACK:
CLR SDAPIN ;SEND ACKNOWLEDGE BIT.
SRBACLK:
ACALL SCLHIGH ;SEND ACKNOWLEDGE CLOCK.
POP ACC ;RESTORE ACCUMULATOR
ACALL BITDLY
CLR SCLPIN
SETB SDAPIN ;CLEAR ACKNOWLEDGE BIT.
ACALL BITDLY
RET
;****************************************************************************
;* Function = WRITE_d11
;* Input = SLV_ADR (d11 SLAVE ADDRESS)
;* SUB_ADR (d11 COMMAND);
;* CNT_Byte (Number of Bytes to be sent);
;* @I2C_BUFFER (Output Buffer, Data to be sent, starts from RAM
;* location sI2C_BUFFER)
;* Return = None
;* Change = R0,R3
;*****************************************************************************
WRITE_d11_POINT:
MOV R0,#I2C_BUFFER ;SET FIRST RECEIVE DATA BUFFER ADDRESS
WRITE_d11:
MOV BYTE_CNT,CNT_BYTE
;----
ACALL GOMASTER ;ACQUIRE BUS AND SEND SLAVE ADDRESS.
JB I2C_FAIL,WRITE_NOK ;CHECK FOR SLAVE NOT RESPONDING.
;-----
;;; MOV R0,#I2C_BUFFER ;SET FIRST RECEIVE DATA BUFFER ADDRESS
WRITE_DATA_LOOP:
MOV A,@R0 ;GET DATA BYTE FROM BUFFER.
ACALL SEND_BYTE ;SEND NEXT DATA BYTE.
INC R0 ;ADVANCE BUFFER POINTER.
JB I2C_FAIL,WRITE_NOK ;CHECK FOR SLAVE NOT RESPONDING.
DJNZ BYTE_CNT,WRITE_DATA_LOOP ;ALL BYTES SENT?
WRITE_NOK:
WRITE_OK:
ACALL SEND_STOP ;DONE, SEND AN I2C STOP.
RET
;========================================
; SEND SLAVE ADDRESS TO d11
;----------------------------------------
GOMASTER:
CLR I2C_FAIL ;CLEAR ERROR STATUS FLAGS.
;---
JNB SCLPIN,FAULT ;CHECK FOR BUS CLEAR.
JNB SDAPIN,FAULT
CLR SDAPIN ;BEGIN I2C START.
ACALL BITDLY
CLR SCLPIN
ACALL BITDLY ;COMPLETE I2C START.
MOV A,SLV_ADR ;GET SLAVE ADDRESS.
ACALL SEND_BYTE ;SEND SLAVE ADDRESS.
RET
;-------------
FAULT:
SETB I2C_FAIL ;SET FAULT STATUS
RET ;AND EXIT.
;-------------
BITDLY:
RET ;NOPS TO DELAY 5 MICROSECONDS (MINUS 4
;========================================
SEND_BYTE:
MOV BITCNT,#8 ;SET BIT COUNT.
SBLOOP:
RLC A ;SEND ONE DATA BIT.
MOV SDAPIN,C ;PUT DATA BIT ON PIN.
ACALL SCLHIGH ;SEND CLOCK.
ACALL BITDLY
CLR SCLPIN
ACALL BITDLY
DJNZ BITCNT,SBLOOP ;REPEAT UNTIL ALL BITS SENT.
SETB SDAPIN ;RELEASE DATA LINE FOR ACKNOWLEDGE.
ACALL SCLHIGH ;SEND CLOCK FOR ACKNOWLEDGE.
ACALL BITDLY
JNB SDAPIN,SBEX ;CHECK FOR VALID ACKNOWLEDGE BIT.
SETB I2C_FAIL ;SET STATUS FOR NO ACKNOWLEDGE.
SBEX:
CLR SCLPIN ;FINISH ACKNOWLEDGE BIT.
ACALL BITDLY
RET
;=======================================
SCLHIGH:
SETB SCLPIN ;Set SCL from our end.
JNB SCLPIN,$ ;Wait for pin to actually go high.
RET
;-----------------------------------
SEND_STOP:
CLR SDAPIN ;Get SDA ready for stop.
ACALL SCLHIGH ;SET CLOCK FOR STOP.
ACALL BITDLY
SETB SDAPIN ;SEND I2C STOP.
ACALL BITDLY
RET ;BUS SHOULD NOW BE RELEASED.
;---
DELAY_20MS:
PUSH ACC
MOV R7,#20
AJMP DELAY_1MS
;========================================
DELAY_100MS:
PUSH ACC
MOV R7,#100
;----
DELAY_1MS:
MOV A,#200 ;200*5us=1ms
DY:
NOP
NOP
NOP
DEC A
JNZ DY
DJNZ R7,DELAY_1MS
;DY_RET:
POP ACC
RET
;;
;==============================
; For Interrupt Pipe
;==============================
EMB_ED1_INPUT:
; JNB PS2_BUFFER_CHANGED,INT_RET ;NO CHANGE, NO NEED TO RESEND
; CLR PS2_BUFFER_CHANGED
MOV I2C_BUFFER,#READ_LAST_EMBF_INT_ST ;CLEAR INTERUPT BIT AND LINE
LCALL READ_ONE_BYTE
;------
MOV I2C_BUFFER,#SEL_EPT_EMBF_INT ;SELECT EMB EPT0 IN
LCALL READ_ONE_BYTE
MOV A,I2C_BUFFER
ANL A,#00000001B ;IS BUFFER EMPTY?
JNZ INT_RET ;not empty, return
head_fill:
MOV RW_COUNTER,#10 ;TOTAL BYTES TO SEND = data length plus 2
MOV R0,#I2C_BUFFER
MOV @R0,#WRITE_BUFFER ;COMMAND
INC R0
MOV @R0,#0 ;FIRST BYTE SHOULD BE ZERO
INC R0
MOV @R0,#8 ;DATA LENGTH 8 BYTES
JNB PS2_ERROR_ROLLOVER,NORMAL_DATA_FILL
CLR PS2_ERROR_ROLLOVER
;REPORT PHANTOM STATE
INC R0
MOV @R0,KBD_MODIFIER ;SET MODIFIER BYTE
INC R0
MOV @R0,#0 ;SET RESERVED BYTE
MOV R7,#6
ERROR_data_fill:
INC R0
MOV @R0,#01H
DJNZ R7,ERROR_data_fill
AJMP INT_WRITE_N_BYTE
NORMAL_DATA_FILL:
MOV I2C_BUFFER+3,KBD_MODIFIER ;SET MODIFIER BYTE
MOV I2C_BUFFER+4,#0 ;SET RESERVED BYTE
MOV I2C_BUFFER+5,PS2_BUFFER ;SET HID KEYCODE #1
MOV I2C_BUFFER+6,PS2_BUFFER+1 ;SET HID KEYCODE #2
MOV I2C_BUFFER+7,PS2_BUFFER+2 ;SET HID KEYCODE #3
MOV I2C_BUFFER+8,PS2_BUFFER+3 ;SET HID KEYCODE #4
MOV I2C_BUFFER+9,PS2_BUFFER+4 ;SET HID KEYCODE #5
MOV I2C_BUFFER+10,PS2_BUFFER+5 ;SET HID KEYCODE #6
INT_WRITE_N_BYTE: ;INTERRUPT PIPE TO HOST
MOV I2C_BUFFER,#SEL_EPT_EMBF_INT
LCALL WRITE_COMMAND
MOV I2C_BUFFER,#WRITE_BUFFER
INT_WRITE_TO_d11_1:
MOV SLV_ADR,#036H ;WRITE COMMAND
MOV CNT_BYTE,#1 ;NUMBER OF BYTES TO BE SENT
LCALL WRITE_d11_POINT ;READ 1 BYTES
MOV SLV_ADR,#034H ;WRITE DATA
MOV CNT_BYTE,RW_COUNTER
LCALL WRITE_d11
MOV I2C_BUFFER,#VALIDATE_BUF ;READY DATA TO SEND
LCALL WRITE_COMMAND
JNB PAUSE_FLAG,INT_RET
CLR PAUSE_FLAG ;REMOVE <PAUSE> KEY FROM BUFFER AFTER SENT
MOV A,#48H
ACALL BREAK_KEY
INT_RET:
RET ;END OF EMD_ED1_INPUT
;;
;;====================================================================================
;; MCU begins to receive ps2 data byte through external interrupt pin INT1(pin 12).
;; PS2 clk signal was connected to INT1 pin(pin 12). For the very first time, INT1
;; interrupt was enabled and falling-edge active. Then uP read one complete byte
;; (10 bits) with polling. During this time, interrupt was disabled until the whole
;; byte(or several bytes for extra keycodes) was completely received.
;;
;; According to PS2 specification, the data must have existed on the PS2-SDA before
;; PS2_CLK become low. So uP doesn't read the SDA until SCL goes low.
;;
;; Before return, interrupt was enabled again.
;;======================================================================================
;;
PS2_INF:
push acc
push psw
SETB RS0
clr ex1 ;disable external interrupt INT1
GET_ONE_KEY:
CLR E0_FLAG
LCALL READ_PS2_BYTE ;READ IN ONE PS/2 BYTE
CJNE A,#0CCH,EXTRA_KEYCODE ;'CC', NO MORE CODE IN
AJMP END_PS2_INF
;-------------------------------------------------------------------------------
; EXTRA KEYCODES
;-------------------------------------------------------------------------------
EXTRA_KEYCODE:
; CJNE A,#84H,E1_KEYCODE
; MOV A,#46H ;'84', <ALT> + <PRINT SCREEN> DOWNCODE
; SETB E0_FLAG
; AJMP EXIT_MAKE_KEY
;E1_KEYCODE:
CJNE A,#0E1H,E0_KEYCODE
SETB E0_FLAG
LCALL READ_PS2_BYTE ;CODE STREAM BEGINS WITH 'E1'
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
MOV A,#77H ;'E1 14 77 E1 F0 14 F0 77', <PAUSE> DOWNCODE
SETB PAUSE_FLAG
AJMP EXIT_MAKE_KEY
BASIC_KEYCODE_1:
AJMP BASIC_KEYCODE
E0_KEYCODE:
CJNE A,#0E0H,BASIC_KEYCODE_1
SETB E0_FLAG
LCALL READ_PS2_BYTE ;CODE STREAM BEGINS WITH 'E0'
CJNE A,#0F0H,E0_11
;E0_F0_KEYCODE:
LCALL READ_PS2_BYTE ;CODE STREAM BEGINS WITH 'E0 F0'
E0_F0_11:
CJNE A,#11H,E0_F0_14
CLR KBD_R_ALT ;'E0 F0 11', RIGHT ALT UPCODE
AJMP EXIT
E0_F0_14:
CJNE A,#14H,E0_F0_27
CLR KBD_R_CTRL ;'E0 F0 14', RIGHT CTRL UPCODE
AJMP EXIT
E0_F0_27:
CJNE A,#27H,E0_F0_1F
CLR KBD_R_GUI ;'E0 F0 27', RIGHT GUI UPCODE
AJMP EXIT
E0_F0_1F:
CJNE A,#1FH,E0_F0_2F
CLR KBD_L_GUI ;'E0 F0 1F', LEFT GUI UPCODE
AJMP EXIT
E0_F0_2F:
CJNE A,#2FH,E0_F0_12
CLR E0_FLAG ;'E0 F0 2F', RIGHT APP UPCODE
AJMP EXIT_BREAK_KEY
E0_F0_12:
CJNE A,#12H,E0_F0_59
AJMP END_PS2_INF
E0_F0_59:
CJNE A,#59H,E0_F0_XX
AJMP END_PS2_INF
E0_F0_XX:
AJMP EXIT_BREAK_KEY
;-------------------------------------------------------------------------------
; RIGHT KEYBOARD KEYCODES(UPCODE) AND SOME SPECIAL KEYCODES
;-------------------------------------------------------------------------------
E0_11:
CJNE A,#11H,E0_14
SETB KBD_R_ALT ;'E0 11', RIGHT ALT DOWNCODE
AJMP EXIT
E0_14:
CJNE A,#14H,E0_27
SETB KBD_R_CTRL ;'E0 14', RIGHT CTRL DOWNCODE
AJMP EXIT
E0_27:
CJNE A,#27H,E0_1F
SETB KBD_R_GUI ;'E0 27', RIGHT GUI DOWNCODE
AJMP EXIT
E0_1F:
CJNE A,#1FH,E0_2F
SETB KBD_L_GUI ;'E0 1F', LEFT GUI DOWNCODE
AJMP EXIT
E0_2F:
CJNE A,#2FH,E0_84
CLR E0_FLAG ;'E0 2F', <APPLICATION> DOWNCODE
AJMP EXIT_MAKE_KEY
E0_84:
CJNE A,#84H,E0_12
CLR E0_FLAG ;'E0 84', <ALT> + <PRINT SCREEN> UPCODE
AJMP EXIT_BREAK_KEY
E0_12:
CJNE A,#12H,E0_59
AJMP END_PS2_INF
E0_59:
CJNE A,#59H,E0_7E
AJMP END_PS2_INF
E0_7E:
CJNE A,#7EH,E0_XX
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
LCALL READ_PS2_BYTE
SETB PAUSE_FLAG
AJMP EXIT_MAKE_KEY
E0_XX:
AJMP EXIT_MAKE_KEY
;-------------------------------------------------------------------------------
; LEFT KEYBOARD AND KEYPAD KEYCODES
;-------------------------------------------------------------------------------
BASIC_KEYCODE:
CJNE A,#0F0H,DOWNCODE ;'F0 ##', BASIC UPCODE
LCALL READ_PS2_BYTE
UP_LEFT_CTRL:
CJNE A,#14H,UP_LEFT_SHIFT
CLR KBD_L_CTRL ;'F0 14', <LEFT CTRL> UPCODE
AJMP EXIT
UP_LEFT_SHIFT:
CJNE A,#12H,UP_LEFT_ALT
CLR KBD_L_SHIFT ;'F0 12', <LEFT SHIFT> UPCODE
AJMP EXIT
UP_LEFT_ALT:
CJNE A,#11H,UP_RIGHT_SHIFT
CLR KBD_L_ALT ;'F0 11', <LEFT ALT> UPCODE
AJMP EXIT
UP_RIGHT_SHIFT:
CJNE A,#59H,UP_OTHERS
CLR KBD_R_SHIFT ;'F0 59', <RIGHT SHIFT> UPCODE
AJMP EXIT
UP_OTHERS:
; MOV @R0,#0 ;CLEAR KEYCODE IN PS2_BUFFER(KEY RELEASED)
AJMP EXIT_BREAK_KEY
DOWNCODE:
CJNE A,#14H,DN_LEFT_SHIFT ;'##', (## != 'E0' OR 'F0') BASIC DOWNCODE
SETB KBD_L_CTRL ;'14', LEFT CTRL DOWNCODE'
AJMP EXIT
DN_LEFT_SHIFT:
CJNE A,#12H,DN_LEFT_ALT
SETB KBD_L_SHIFT ;'12', LEFT SHIFT DOWNCODE
AJMP EXIT
DN_LEFT_ALT:
CJNE A,#11H,DN_RIGHT_SHIFT
SETB KBD_L_ALT ;'11', LEFT ALT DOWNCODE
AJMP EXIT
DN_RIGHT_SHIFT:
CJNE A,#59H,DN_OTHERS
SETB KBD_R_SHIFT ;'59', RIGHT SHIFT DOWNCODE
AJMP EXIT
DN_OTHERS:
AJMP EXIT_MAKE_KEY
EXIT_MAKE_KEY:
ACALL FIND_HID_KEYCODE
JZ EXIT
ACALL MAKE_KEY
SJMP END_PS2_INF
EXIT_BREAK_KEY:
ACALL FIND_HID_KEYCODE
JZ EXIT
ACALL BREAK_KEY
SJMP END_PS2_INF
EXIT:
SETB PS2_BUFFER_CHANGED
; INC R0
; AJMP GET_ONE_KEY
END_PS2_INF:
; CLR IT1
CLR RS0
pop psw
pop acc
SETB EX1
reti
;*******************************************************************************
;ROUTINE :
;FUNCTION:
;INPUTS :
;OUTPUTS :
;CHANGED :
;---------------------------------------
FIND_HID_KEYCODE:
JB E0_FLAG,E0_KEYS
JB KBD_SELECT_SCANSET_3,PS3_KEYS
MOV DPTR,#TBL_PS2_TO_HID ;BASIC KEYCODE TABLE
SJMP LOOK_UP
PS3_KEYS:
MOV DPTR,#TBL_PS3_TO_HID
SJMP LOOK_UP
E0_KEYS:
MOV DPTR,#TBL_PS2EXTRA_TO_HID ;EXTRA KEYCODE TABLE
CLR C
SUBB A,#4AH
CLR E0_FLAG
LOOK_UP:
MOVC A,@A+DPTR
END_FIND_HID_KEY:
RET
;*******************************************************************************
;ROUTINE :
;FUNCTION:
;INPUTS :
;OUTPUTS :
;CHANGED :
;---------------------------------------
MAKE_KEY:
MOV R2,A
DEC A
JZ ROLLOVER ;'01', ERROR ROLLOVER CONDITION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -