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

📄 kbd9.asm

📁 一个PS2键盘单片机, 使用Philips的接口+8051,写的不错,非常值得学习.
💻 ASM
📖 第 1 页 / 共 4 页
字号:
;************************************************************************************
;|														|
;|  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 + -