📄 ps2code.asm
字号:
;---------------------------------------------------------------------------------------------
; HEADER:
;---------------------------------------------------------------------------------------------
TITLE "PS/2 Keyboard Emulator"
SUBTITLE "Copyright 2001, Adam Chapweske"
LIST P=16F877
INCLUDE "p16f877.inc"
RADIX DEC
ERRORLEVEL -224, 1
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC
;---------------------------------------------------------------------------------------------
#DEFINE DATA PORTA, 2 ;May be assigned to any I/O pin
#DEFINE CLOCK PORTA, 3 ;May be assigned to any I/O pin
#DEFINE KEY PORTB, 0
#DEFINE PERIOD 20 ;Time between reading of inputs. Min=(osc frequency)/204800
;---------------------------------------------------------------------------------------------
; RAM ALLOCATION:
;---------------------------------------------------------------------------------------------
cblock 0x20
TEMP0 ,TEMP1
RECEIVE, PARITY, COUNTER ;Used in I/O routines
OLDKEYCODE,NEWKEYCODE
endc
;---------------------------------------------------------------------------------------------
cblock 0x30 ;Contains to-be-sent packet and last packet sent
LENGTH
SEND1
SEND2
SEND3
endc
;---------------------------------------------------------------------------------------------
; MACROS:
;---------------------------------------------------------------------------------------------
;Delay "Cycles" instruction cycles
Delay macro Time
if (Time==1)
nop
exitm
endif
if (Time==2)
goto $ + 1
exitm
endif
if (Time==3)
nop
goto $ + 1
exitm
endif
if (Time==4)
goto $ + 1
goto $ + 1
exitm
endif
if (Time==5)
goto $ + 1
goto $ + 1
nop
exitm
endif
if (Time==6)
goto $ + 1
goto $ + 1
goto $ + 1
exitm
endif
if (Time==7)
goto $ + 1
goto $ + 1
goto $ + 1
nop
exitm
endif
if (Time%4==0)
movlw (Time-4)/4
call Delay_us
exitm
endif
if (Time%4==1)
movlw (Time-5)/4
call Delay_us
nop
exitm
endif
if (Time%4==2)
movlw (Time-6)/4
call Delay_us
goto $ + 1
exitm
endif
if (Time%4==3)
movlw (Time-7)/4
call Delay_us
goto $ + 1
nop
exitm
endif
endm
;---------------------------------------------------------------------------------------------
; ORG 0x000:
;---------------------------------------------------------------------------------------------
org 0x000
goto Start
;---------------------------------------------------------------------------------------------
; EMULATE BAT:
;---------------------------------------------------------------------------------------------
BATdelay clrf TEMP0 ;Used for a 400 ms delay at power-on
clrf TEMP1
DelayLoop Delay 6
decfsz TEMP0, f
goto DelayLoop
decfsz TEMP1, f
goto DelayLoop
retlw 0x00
;---------------------------------------------------------------------------------------------
; HANDLE COMMAND:
;---------------------------------------------------------------------------------------------
if (high Table1End != 0)
ERROR "Command handler table must be in low memory page"
endif
Command movlw 0xED ;0xE6 is lowest code
subwf RECEIVE, w
bnc MainLoop
HandlerTable addwf PCL, f ;Add offset
goto MainLoop ;0xED
goto KeyBd_EE ;0xEE
goto MainLoop ;0xEF
goto MainLoop ;0xF0
goto MainLoop ;0xF1
goto MainLoop ;0xF2
goto MainLoop ;0xF3
goto KeyBd_F4 ;0xF4
goto MainLoop ;0xF5
goto MainLoop ;0xF6
goto MainLoop ;0xF7
goto MainLoop ;0xF8
goto MainLoop ;0xF9
goto MainLoop ;0xFA
goto MainLoop ;0xFB
goto MainLoop ;0xFC
goto MainLoop ;0xFD
goto PacketOut ;0xFE - Resend
Table1End goto Reset ;0xFF - Reset
;---------------------------------------------------------------------------------------------
; START:
;---------------------------------------------------------------------------------------------
Start clrf PORTA
clrf PORTB
bsf STATUS, RP0 ;(TRISA=TRISB=0xFF by default)
movlw 0x57 ;Timer mode, assign max. prescaler, enable pullups
movwf OPTION_REG
movlw 0x07
movwf ADCON1
clrf PORTC
bcf STATUS, RP0
goto Reset
;---------------------------------------------------------------------------------------------
; Reset Mode:
;---------------------------------------------------------------------------------------------
Reset clrf PORTC
movlw 0x00
movwf OLDKEYCODE
movwf NEWKEYCODE
movlw 0xAA
movwf SEND1 ;Load BAT completion code
movlw 0x01
movwf LENGTH
call BATdelay
bcf STATUS,RP0
goto PacketOut ;Output 2-byte "completion-code, device ID" packet
;---------------------------------------------------------------------------------------------
; Stream/Remote Mode:
;---------------------------------------------------------------------------------------------
MainLoop btfss DATA
goto PacketIn
bsf PORTC,2
call ReadInputs
movf OLDKEYCODE, w
xorwf NEWKEYCODE ,w
btfsc STATUS, Z
goto MainLoop
goto Report
;---------------------------------------------------------------------------------------------
; REPORT:
;---------------------------------------------------------------------------------------------
Report bsf PORTC,0
movf OLDKEYCODE,w
andlw 0xff
btfss STATUS,Z
goto KeyBreak
goto KeyMake
KeyBreak movlw 0xf0
movwf SEND1
movf OLDKEYCODE,w
call Label
movwf SEND2
movlw 0x02 ;Movement data report length
movwf LENGTH
movlw 0x00
movwf OLDKEYCODE
goto PacketOut
KeyMake movf NEWKEYCODE,w
andlw 0xff
btfsc STATUS,Z
goto MainLoop
movf NEWKEYCODE,w
call Label
movwf SEND1
movlw 0x01 ;Movement data report length
movwf LENGTH
movf NEWKEYCODE,w
movwf OLDKEYCODE
goto PacketOut
Label addwf PCL
retlw 0x45
retlw 0x46
;---------------------------------------------------------------------------------------------
; OUTPUT PACKET
;---------------------------------------------------------------------------------------------
PacketOut movlw SEND1 ;First byte of packet
movwf FSR
movf LENGTH, w ;Length of packet
movwf TEMP1
PacketOutLoop movf INDF, w ;Get data byte
call ByteOut ; Output that byte
xorlw 0xFF ;Test for RTS error
bz PacketIn
xorlw 0xFE ^ 0xFF ;Test for inhibit error
bz PacketOut
incf FSR, f ;Point to next byte
decfsz TEMP1, f
goto PacketOutLoop
goto MainLoop
;---------------------------------------------------------------------------------------------
; READ PACKET
;---------------------------------------------------------------------------------------------
PacketIn
call ByteIn
xorlw 0xFF ;Test for parity/framing error
bz KeyBd_ERR
xorlw 0xFE ^ 0xFF ;Test for inhibit error
bz MainLoop
movlw 0xFE ;Test for "Resend" command
xorwf RECEIVE, w
bz PacketOut
movlw 0xEE
xorwf RECEIVE,w
btfss STATUS,Z
goto Acknowledge
movlw 0xEE
call ByteOut
goto MainLoop
Acknowledge movlw 0xFA ;Acknowledge
call ByteOut
goto Command
;---------------------------------------------------------------------------------------------
; READ INPUTS:
;---------------------------------------------------------------------------------------------
ReadInputs movlw 0x00
btfsc KEY
movlw 0x01
movwf NEWKEYCODE
return
;---------------------------------------------------------------------------------------------
; HANDLE COMMANDS:
;---------------------------------------------------------------------------------------------
;Invalid command
KeyBd_ERR movlw 0xFE
call ByteOut
bsf PORTC,1
goto MainLoop
KeyBd_EE movlw 0xEE
call ByteOut
goto MainLoop
KeyBd_F2 movlw 0xAB
movwf SEND1
movlw 0x83
movwf SEND2
movlw 0x02
movwf LENGTH
goto PacketOut
KeyBd_F4 goto MainLoop
;---------------------------------------------------------------------------------------------
; OUTPUT ONE BYTE: - TIMING IS CRITICAL!!!
;---------------------------------------------------------------------------------------------
ByteOut movwf TEMP0
InhibitLoop btfss CLOCK ;Test for inhibit
goto InhibitLoop
Delay 100 ;(50 microsec = 58 clock cycles, min)
btfss CLOCK
goto InhibitLoop
btfss DATA ;Check for request-to-send
retlw 0xFF
clrf PARITY
movlw 0x08
movwf COUNTER
movlw 0x00
call BitOut ;Start bit (0)
btfss CLOCK ;Test for inhibit
goto ByteOutEnd
Delay 4
ByteOutLoop movf TEMP0, w
xorwf PARITY, f
call BitOut ;Data bits
btfss CLOCK ;Test for inhibit
goto ByteOutEnd
rrf TEMP0, f
decfsz COUNTER, f
goto ByteOutLoop
Delay 2
comf PARITY, w
call BitOut ;Parity bit
btfss CLOCK ;Test for inhibit
goto ByteOutEnd
Delay 5
movlw 0xFF
call BitOut ;Stop bit (1)
Delay 48
retlw 0x00
ByteOutEnd bsf STATUS, RP0
bsf DATA
bsf CLOCK
bcf STATUS, RP0
retlw 0xFE
BitOut bsf STATUS, RP0
andlw 0x01
btfss STATUS, Z
bsf DATA
btfsc STATUS, Z
bcf DATA
Delay 21
bcf CLOCK
Delay 45
bsf CLOCK
bcf STATUS, RP0
Delay 5
return
;---------------------------------------------------------------------------------------------
; READ ONE BYTE: (Takes about 1ms) - TIMING IS CRITICAL!!!
;---------------------------------------------------------------------------------------------
ByteIn btfss CLOCK ;Test for Request-to-send
retlw 0xFE
btfsc DATA
retlw 0xFE
movlw 0x08
movwf COUNTER
clrf PARITY
Delay 28
ByteInLoop call BitIn ;Data bits
btfss CLOCK ;Test for inhibit
retlw 0xFE
bcf STATUS, C
rrf RECEIVE, f
iorwf RECEIVE, f
xorwf PARITY,f
decfsz COUNTER, f
goto ByteInLoop
Delay 1
call BitIn ;Parity bit
btfss CLOCK ;Test for inhibit
retlw 0xFE
xorwf PARITY, f
Delay 5
ByteInLoop1 Delay 1
call BitIn ;Stop bit
btfss CLOCK ;Test for inhibit
retlw 0xFE
xorlw 0x00
btfsc STATUS, Z
clrf PARITY
btfsc STATUS, Z ;Stop bit = 1?
goto ByteInLoop1 ; No--keep clocking.
bsf STATUS, RP0 ;Acknowledge
bcf DATA
Delay 11
bcf CLOCK
Delay 45
bsf CLOCK
Delay 7
bsf DATA
bcf STATUS, RP0
btfss PARITY, 7 ;Parity correct?
retlw 0xFF ; No--return error
Delay 45
retlw 0x00
BitIn Delay 8
bsf STATUS, RP0
bcf CLOCK
Delay 45
bsf CLOCK
bcf STATUS, RP0
Delay 21
btfsc DATA
retlw 0x80
retlw 0x00
;---------------------------------------------------------------------------------------------
; DELAY:
;---------------------------------------------------------------------------------------------
;Delays 4w+4 cycles (including call,return, and movlw) (0=256)
Delay_us addlw -1 ;Precise delays used in I/O
btfss STATUS, Z
goto Delay_us
return
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -