📄 kbd9.asm
字号:
;************************************************************************************
;| |
;| PROGARM : ps2kbd.asm |
;| |
;| FUNCTION: USB to PS2 Keyboard bridge implemented with PDIUSBD11 + MCU |
;| |
;| COMPILER: ASM51 Macro Assebbler V1.2 ( SW I2C version) |
;| |
;| USED IN : 80C51 SERIES |
;| |
;| AUTHORS : David Wang |
;| |
;| Modified: JUL-11-2000 |
;| |
;| VERSION : Rev 0.8 |
;| |
;| UPDATES : Rev 0.8a 13/07/00 |
;| Fix update keyboard LED status(timing problem with PS/2 interface)| |
;| Rev 0.8b 18/07/00 |
;| Add kbd_set_scan/kbd_get_scan/kbd_get_id |
;| Rev 0.8c 26/07/00 |
;| Add support BOOT protocol/legacy mode |
;| Before execute set_address, firmware should wait until next IN |
;| token with default address arrives |
;| |
;************************************************************************************
;| |
;|The sample code is provided on an "as is" basis, and Philips Semiconductors |
;|expressly disclaims any or all warranties expressed or implied, including |
;|without limitation warranties of fitness for a particular purpose. In no |
;|event shall Philips Semiconductors be liable for any direct, indirect, |
;|incidental consequential damages of any kind whatsover with respect to the |
;|use of the code. |
;| |
;|Philips Semiconductors reserves the right, in its sole discretion and |
;|without any obligation, to make improvements to, or correct any error in any |
;|portion of the code. |
;| |
;************************************************************************************
; |
;This sample code is used to implement a converter between PS/2 keyboard and USB. |
;With this converter, a PS/2 keyboard can be used as a USB HID keyboard. |
;The demo board uses Philips PDIUSBD11 and a 8051 compatible MCU. |
; |
;************************************************************************************
$TITLE(d11 USB-PS/2 KEYBOARD)
$PAGEWIDTH(132)
$DATE(12/7/2000)
$DEBUG
$OBJECT
$MOD51
;----------------
FLAG DATA 20H ;general flag
I2C_FAIL BIT FLAG.0 ;I2C FAIL FLAG.
VALIDATE_FLAG BIT FLAG.1 ;WRITE BUFFER FLAG
;PS2_DATA_OK BIT FLAG.2 ;indicate one bar data stream is ready
;DATA_DONE BIT FLAG.3 ;data send done
PAUSE_FLAG BIT FLAG.4 ;KEY <PAUSE> PRESSED
E0_FLAG BIT FLAG.5 ;AN EXTRA PS/2 KEYCODE DETECTED
PS2_BUFFER_CHANGED BIT FLAG.6
PS2_ERROR_ROLLOVER BIT FLAG.7
;----------------
EMB_STATUS DATA 21H ;FLAG AND STATUS
EMB_SELF_POWER BIT EMB_STATUS.0 ;EMB FUNCTION SELF POWERED FLAG
EMB_REMOTE_WAKE BIT EMB_STATUS.1 ;EMB FUNCTION REMOTE WAKEUP FLAG
EMB_EPT0_OUT_STALL BIT EMB_STATUS.2 ;EMB FUNCTION EPT0 OUT STALL FLAG
EMB_EPT0_IN_STALL BIT EMB_STATUS.3 ;EMB FUNCTION EPT0 IN STALL FLAG
EMB_EPT1_IN_STALL BIT EMB_STATUS.4 ;EMB FUNCTION EPT1 IN STALL FLAG
EMB_CONFIG BIT EMB_STATUS.5 ;EMB CONFIGURED
;----------------
KBD_MODIFIER DATA 22H
KBD_L_CTRL BIT KBD_MODIFIER.0
KBD_L_SHIFT BIT KBD_MODIFIER.1
KBD_L_ALT BIT KBD_MODIFIER.2
KBD_L_GUI BIT KBD_MODIFIER.3
KBD_R_CTRL BIT KBD_MODIFIER.4
KBD_R_SHIFT BIT KBD_MODIFIER.5
KBD_R_ALT BIT KBD_MODIFIER.6
KBD_R_GUI BIT KBD_MODIFIER.7
;----------------
LED_STATUS DATA 23H
LED_SCROLL BIT LED_STATUS.0
LED_NUM BIT LED_STATUS.1
LED_CAPS BIT LED_STATUS.2
;----------------
KBD_STATUS DATA 24H
KBD_INIT_NOK BIT KBD_STATUS.0
KBD_ID_OK BIT KBD_STATUS.1
KBD_SELECT_SCANSET_1 BIT KBD_STATUS.2
KBD_SELECT_SCANSET_2 BIT KBD_STATUS.3
KBD_SELECT_SCANSET_3 BIT KBD_STATUS.4
;----------------
RW_COUNTER DATA 30H
EMB_ADDR DATA 31H ;ADDRESS OF THE EMBEDDED FUNCTION
EMB_LAST_COM DATA 32H ;CONTAINS THE LAST RECEIVED REQUEST
EMB_BYTE_TO_SEND DATA 33H
EMB_MSG_DPH DATA 34H
EMB_MSG_DPL DATA 35H
PROTOCOL DATA 36H
PS2_LAST_KEY DATA 37H ;POINT TO LAST VALID HID KEY IN PS2_BUFFER
PS2_BUFFER DATA 38H ;FROM 38H-3DH ARE USED FOR HID KEYCODE BUFFER
;-------------------------------------------------
; S/W I2C CONTROL REGISTERS
;-------------------------------------------------
BITCNT DATA 50H ;I2C BIT COUNTER.
BYTE_CNT DATA 51H ;BYTES TO BE PROCESSED BY I2C TX/RX
CNT_BYTE DATA 52H ;NUMBER OF BYTES TO BE TRANSMITTED
SLV_ADR DATA 53H ;I2C ADDRESS OF ACTIVE SLAVE.
;-----------
I2C_BUFFER DATA 54H ;I2C TRANSMIT/RECEIVE DATA BUFFER
;54H-5fH 10 BYTES
;-----------
STACK_BUF DATA 60H
;
;*******************************************
; d11 commands
;*******************************************
;
; Initialization Commands
;
SET_HUB_ADDRESS_EN EQU 0D0h
SET_EMB_ADDRESS_EN EQU 0D1h
SET_EPOINT_EN EQU 0D8h
;
; Data Flow Commands
;
SEL_EPT_EMBF_OUT EQU 002h
SEL_EPT_EMBF_IN EQU 003h
SEL_EPT_EMBF_INT EQU 004h
;---
READ_LAST_EMBF_OUT_ST EQU 042h
READ_LAST_EMBF_IN_ST EQU 043H
READ_LAST_EMBF_INT_ST EQU 044H
;---
READ_EMBF_OUT_ST EQU 082h
READ_EMBF_IN_ST EQU 083H
READ_EMBF_INT_ST EQU 084H
;---
SET_EMBF_OUT_ST EQU 042h
SET_EMBF_IN_ST EQU 043H
SET_EMBF_INT_ST EQU 044H
;---
READ_BUFFER EQU 0F0h
WRITE_BUFFER EQU 0F0h
ACK_SETUP EQU 0F1h
CLEAR_BUF EQU 0F2h
READ_INT EQU 0F4h
VALIDATE_BUF EQU 0FAh
;
; General Commands
;
SEND_RESUME EQU 0F6h
;READ_CURR_FRAME_NUM EQU 0F5h
SET_MODE EQU 0F3H
;
;*******************************************
; USB Request descriptor
;*******************************************
;
OFFSET_bmReqTyp EQU 02h
OFFSET_bmReq EQU 03h
OFFSET_wValue EQU 04h
OFFSET_wIndex EQU 06h
OFFSET_wLength EQU 08h
;
REQ_SET_ADDRESS EQU 05H
;
REQ_GET_REPORT EQU 01H
REQ_GET_IDLE EQU 02H
REQ_GET_PROTOCOL EQU 03H
REQ_SET_REPORT EQU 09H
REQ_SET_IDLE EQU 0AH
REQ_SET_PROTOCOL EQU 0BH
;
REQ_GET_FEATURE EQU 0EH
REQ_SET_FEATURE EQU 0FH
;
;*******************************************
; IO port definition
;*******************************************
;
SCLPIN BIT P0.0 ;S/W I2C CLOCK PIN
SDAPIN BIT P0.1 ;S/W I2C DATA PIN
PS2_DATA BIT P0.4 ;P0.2 ;ps2 data
PS2_CLK BIT P3.3 ;P3.2 ;ps2 clock
d11_INT_PORT BIT P1.5 ;d11 INTERRUPT PIN
SUSPEND_PORT BIT P1.2 ;d11 SUSPEND PIN
;
;*******************************************
; INTERRUPT VECTOR TABLE
;*******************************************
;
CSEG AT 0000H
ORG 0000H
LJMP START ;PROGRAM START
ORG 0003H
AJMP INT0_ISR ;INT0 SERVICE ROUTINE
ORG 000BH
AJMP TMR0_ISR ;TIMER0 SERVICE ROUTINE
ORG 0013H
LJMP PS2_INF ;INT1 SERVICE ROUTINE
ORG 001BH
AJMP TMR1_ISR ;TIMER1 SERVICE ROUTINE
ORG 0023H
AJMP UART_ISR ;UART SERVICE ROUTINE
ORG 002BH
AJMP I2C_ISR ;I2C SERVICE ROUTINE
;
INT0_ISR: ;INT0 SERVICE ROUTINE
TMR0_ISR: ;TIMER0 SERVICE ROUTINE
;INT1_ISR: ;INT1 SERVICE ROUTINE
TMR1_ISR: ;TIMER1 SERVICE ROUTINE
UART_ISR: ;UART SERVICE ROUTINE
I2C_ISR: ;I2C SERVICE ROUTINE
RETI
;
;***************************************
; PROGRAM START
;***************************************
;
ORG 0030H
START:
MOV IE,#00H ;ALL INTERRUPT DISABLE
MOV IP,#00H ;INT PRIORITY DISABLE
;-----------------------------
; INITIAL I/O PORT
;-----------------------------
MOV P0,#11111111B
MOV P1,#11111111B
MOV P2,#11111111B
MOV P3,#11111111B
;-----------------------------
;CLEAR DATA MEMORY
;-----------------------------
MOV R0,#0H
CLR_DATA:
MOV @R0,#0
INC R0
CJNE R0,#080H,CLR_DATA
;
MOV SP,#STACK_BUF ;SET STACK POINTER
;----
MOV I2C_BUFFER,#SET_MODE
MOV I2C_BUFFER+1,#10000110B ;SWITCH TO d11 COMPATIBILE MODE
MOV I2C_BUFFER+2,#00000011B ;SWITCH TO 12 MHZ OUTPUT
ACALL WRITE_TWO_BYTE ;REMOTE WAKEUP DISABLE
;----
ACALL DELAY_100MS
;
MOV PS2_LAST_KEY,#PS2_BUFFER-1
clr ea ;disable all interrupt
setb ex1 ;enable external interrupt INT1
mov TCON,#00000100B ;enable interrupt 1 triggerred with the falling edge
;----
ACALL INITIAL
;----
MAIN:
ACALL USB_SUBROUTINE
jnb EMB_CONFIG,main ;stop_ps2
setb ea ;enable interrupt INT1 only after configuration
SJMP MAIN
;--------------------
; INITIAL SETTING
;--------------------
INITIAL:
;INITIALIZE D11
MOV EMB_STATUS,#01H
MOV EMB_ADDR,#00H
MOV I2C_BUFFER,#SET_MODE ;RECONNECT SOFTCONNECT
MOV I2C_BUFFER+1,#10111100B ;INITIALIZE d11 as debug mode for interrupt pipe work
ACALL WRITE_ONE_BYTE
;INITIALIZE PS/2 KEYBOARD
LCALL KBD_GET_ID
JNB KBD_ID_OK,INITIAL_FAIL
LCALL KBD_SET_SCAN
JNC INITIAL_FAIL
LCALL KBD_GET_SCAN
JNB KBD_SELECT_SCANSET_3,END_INITIAL
LCALL KBD_PS3_SAK_MB
AJMP END_INITIAL
INITIAL_FAIL:
SETB KBD_INIT_NOK
MOV PROTOCOL,#01H ;DEFAULT IS REPORT PROTOCOL, NOT BOOT PROTOCOL(00H)
END_INITIAL:
RET
;=========================================================================
USB_SUBROUTINE:
JB d11_INT_PORT,d11_RET ;IF d11 INT PORT HI THEN RETURN
;------
MOV I2C_BUFFER,#READ_INT ;READ INTERRUPT REGISTER
ACALL READ_TWO_BYTE ;READ DATA FROM d11
;------
MOV A,I2C_BUFFER
JB ACC.2,EMB_ED0_OUTPUT
JB ACC.3,EMB_ED0_INPUT
JB ACC.4,EMB_ED1_INPUT_P
;-----
MOV A,I2C_BUFFER+1
JB ACC.6,RESTART_d11
RET
;--------------------
RESTART_d11:
;----
MOV I2C_BUFFER,#SET_HUB_ADDRESS_EN ;SET HUB ADDRESS : 0
MOV I2C_BUFFER+1,#00H ;ENABLE HUB
ACALL WRITE_ONE_BYTE
;----
MOV I2C_BUFFER,#SET_EMB_ADDRESS_EN ;ENABLE EMBED ADDRESS
MOV I2C_BUFFER+1,#080H
ACALL WRITE_ONE_BYTE
;----
MOV I2C_BUFFER,#SET_EPOINT_EN ;ENABLE INTERRUPT ENDPOINT
MOV I2C_BUFFER+1,#02H
ACALL WRITE_ONE_BYTE
;----
ACALL INITIAL
;----
d11_RET:
DATA_ERROR:
RET
;========================
EMB_ED1_INPUT_P:
LJMP EMB_ED1_INPUT
;========================
EMB_ED0_INPUT:
MOV I2C_BUFFER,#READ_LAST_EMBF_IN_ST ;clear int reg and signaling at int pin
ACALL READ_ONE_BYTE
;------
MOV I2C_BUFFER,#SEL_EPT_EMBF_IN ;SELECT EMB EPT0 IN
ACALL READ_ONE_BYTE
MOV A,I2C_BUFFER
ANL A,#00000001B ;IS BUFFER EMPTY?
JNZ d11_RET
;------
EMB_MORE_MESSAGE:
MOV R0,#EMB_BYTE_TO_SEND
MOV A,@R0
JZ EMB_END_IN
MOV DPH,EMB_MSG_DPH
MOV DPL,EMB_MSG_DPL
ACALL SEND_TO_HOST
EMB_END_IN:
RET
;*******************************************
CHK_LAST_COMM:
MOV A,EMB_LAST_COM
MOV EMB_LAST_COM,#0
CJNE A,#REQ_SET_REPORT,WRONG_REQ_COMMAND ;LAST COM IS SET_REPORT?
;----
MOV I2C_BUFFER,#SEL_EPT_EMBF_OUT ;select ctrl_out
ACALL WRITE_COMMAND
;-----
MOV I2C_BUFFER,#READ_BUFFER ;read out the content from fifo
ACALL READ_TEN_BYTE
;------
MOV I2C_BUFFER,#CLEAR_BUF ;release fifo
ACALL WRITE_COMMAND
;-----
; MOV A,I2C_BUFFER+1 ;READ TOTAL HOW MANY BYTES
; CJNE A,#1,EMB_DATA_ERROR ;NOT CORRECT COMMAND FROM HOST
;-----
MOV A,I2C_BUFFER+2 ;Actual data byte from SET_REPORT request
MOV C,ACC.0
MOV LED_NUM,C
MOV C,ACC.1
MOV LED_CAPS,C
MOV C,ACC.2
MOV LED_SCROLL,C
ACALL KBD_SET_LED ;Update keyboard LED status
ACALL SEND_ZERO_PACKET
RET
;------
WRONG_REQ_COMMAND:
MOV I2C_BUFFER,#CLEAR_BUF ;RELEASE BUFFER
ACALL WRITE_COMMAND
EMB_DATA_ERROR:
RET
;********************************************************************
EMB_ED0_OUTPUT:
MOV I2C_BUFFER,#READ_LAST_EMBF_OUT_ST ;clr int reg and signaling at int pin
ACALL READ_ONE_BYTE ;
;----
MOV I2C_BUFFER,#READ_EMBF_OUT_ST ;SETUP PACKET STATUS
ACALL READ_ONE_BYTE
MOV A,I2C_BUFFER
ANL A,#00000100B
JNZ EMB_READ_SETUP_DATA ;SETUP PACKET IS NOT ACK
MOV A,I2C_BUFFER
ANL A,#00100000B
JNZ CHK_LAST_COMM ;OUT TOKEN COMING, BUFFER FULL
AJMP EMB_DATA_ERROR ;NO TOKEN COMING
;--------------------------- ;MAYBE OUT TOKEN
EMB_READ_SETUP_DATA:
MOV I2C_BUFFER,#SEL_EPT_EMBF_IN ;select ctrl_in
ACALL WRITE_COMMAND
;-----
MOV I2C_BUFFER,#ACK_SETUP ;to ack it
ACALL WRITE_COMMAND
;---------------------------
MOV I2C_BUFFER,#SEL_EPT_EMBF_OUT ;select ctrl_out
ACALL WRITE_COMMAND
;-----
MOV I2C_BUFFER,#ACK_SETUP ;to ack it
ACALL WRITE_COMMAND
;---------------------------
MOV I2C_BUFFER,#READ_BUFFER ;read fifo first
ACALL READ_TEN_BYTE
;------
MOV I2C_BUFFER,#CLEAR_BUF ;then release it
ACALL WRITE_COMMAND
;-----
MOV A,I2C_BUFFER+1 ;READ TOTAL HOW MANY BYTES
CJNE A,#8,EMB_DATA_ERROR ;NOT CORRECT COMMAND FROM HOST
;-----------------------------------------------------------------
; DECODE HUB ENDPOINT 0 STANDARD REQUEST COMMAND
;-----------------------------------------------------------------
EMB_DECODE_REQUEST:
MOV R2,I2C_BUFFER+OFFSET_bmReqTyp
MOV R3,I2C_BUFFER+OFFSET_bmReq
MOV R4,I2C_BUFFER+OFFSET_wValue
MOV R5,I2C_BUFFER+OFFSET_wIndex
MOV R6,I2C_BUFFER+OFFSET_wLength
MOV A,R2 ;GetbmReqTyp
ANL A,#01100000B
JZ EMB_STANDARD_REQUEST
AJMP EMB_CLASS_REQUEST
;*******************************************************************************
;
;---------------------------------------
EMB_STANDARD_REQUEST:
MOV A,R3 ;Get bmReq
CLR C
SUBB A,#0CH
JC CONTU_EMB_STD_RQST
;
NO_SUPPORT_REQ:
MOV I2C_BUFFER,#SET_EMBF_IN_ST ;STALL ctrl IN
MOV I2C_BUFFER+1,#01H
ACALL WRITE_ONE_BYTE
MOV I2C_BUFFER,#SET_EMBF_OUT_ST ;STALL ctrl OUT
MOV I2C_BUFFER+1,#01H
ACALL WRITE_ONE_BYTE
RET
;
CONTU_EMB_STD_RQST:
MOV DPTR,#EMB_STD_RQST_TBL
MOV A,R3
RL A
JMP @A+DPTR
EMB_STD_RQST_TBL:
AJMP EMB_GET_STATUS
AJMP EMB_CLEAR_FEATURE
AJMP NO_SUPPORT_REQ
AJMP EMB_SET_FEATURE
AJMP NO_SUPPORT_REQ
AJMP EMB_SET_ADDRESS
AJMP EMB_GET_DESCRIPTOR
AJMP NO_SUPPORT_REQ
AJMP EMB_GET_CONFIG
AJMP EMB_SET_CONFIG
AJMP EMB_GET_INTERFACE
AJMP NO_SUPPORT_REQ
AJMP NO_SUPPORT_REQ
;=================================================================
; Setup an alternate interface for current interface
;=================================================================
EMB_SET_INTERFACE:
ACALL SEND_ZERO_PACKET
RET
;=================================================================
; Get the alternate interface number for currect interface
;=================================================================
EMB_GET_INTERFACE:
MOV I2C_BUFFER,#WRITE_BUFFER ;WRITE BUFFER COMMAND
MOV I2C_BUFFER+1,#0
MOV I2C_BUFFER+2,#1
MOV I2C_BUFFER+3,#0
ACALL WRITE_THREE_BYTE
RET
;=================================================================
; Set device address
;=================================================================
EMB_SET_ADDRESS:
MOV A,R4
ORL A,#080H
MOV EMB_ADDR,A ;I2C_BUFFER+OFFSET_wValue
;---
ACALL SEND_ZERO_PACKET
;----
SET_ADDRESS_LOOP:
MOV I2C_BUFFER,#READ_INT
LCALL READ_ONE_BYTE
MOV A,I2C_BUFFER
JNB ACC.3,SET_ADDRESS_LOOP
; JB d11_INT_PORT,SET_ADDRESS_LOOP ;IF d11 INT PORT HI THEN RETURN
;---
SET_EMB_ADDR:
MOV I2C_BUFFER,#SET_EMB_ADDRESS_EN ;WRITE NEW ADDRESS TO HUB
MOV I2C_BUFFER+1,EMB_ADDR
ACALL WRITE_ONE_BYTE
;----
MOV I2C_BUFFER,#READ_LAST_EMBF_IN_ST ;clr int reg and signaling at int pin
ACALL READ_ONE_BYTE ;either read one byte or not
RET
;===============================================================
; Get current configuration number
;===============================================================
EMB_GET_CONFIG: ;8
;---
MOV I2C_BUFFER,#WRITE_BUFFER ;WRITE BUFFER COMMAND
MOV I2C_BUFFER+1,#0
MOV I2C_BUFFER+2,#1
MOV I2C_BUFFER+3,#0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -