.EQU KEY_ESC =$76
.EQU KEY_ENTER =$5A
.EQU KEY_UP =$75
.EQU KEY_DOWN =$72
.EQU KEY_LEFT =$6B
.EQU KEY_RIGHT =$74
.EQU KEY_PAGEUP =$7D
.EQU KEY_PAGEDOWN =$7A
.EQU KEY_HOME =$6C
.EQU KEY_END =$69
.EQU KEY_SPACE =$29
.EQU KEY_F1 =$05
.EQU KEY_NUMLOCK =$77
.EQU KEY_CAPSLOCK =$58
.EQU KEY_SCROLLLOCK =$7E
.EQU KEY_Y =$35
.EQU PS2K_BIT_PARITY =0
.EQU PS2K_BIT_EXTKEY =1 ; расш.код
.EQU PS2K_BIT_RELEASE=2 ; отпускание
.EQU PS2K_BIT_ACKBIT =3 ; окончание передачи
.EQU PS2K_BIT_TX =7 ; передача
.EQU PS2K_BIT_READY =7
.MACRO PS2K_DATALINE_UP
CBI DDRD,6
SBI PORTD,6
.ENDMACRO
.MACRO PS2K_DATALINE_DOWN
CBI PORTD,6
SBI DDRD,6
.ENDMACRO
.MACRO PS2K_CLOCKLINE_UP
CBI DDRE,4
SBI PORTE,4
.ENDMACRO
.MACRO PS2K_CLOCKLINE_DOWN
CBI PORTE,4
SBI DDRE,4
.ENDMACRO
;
;--------------------------------------
;
.DSEG
PS2K_BIT_COUNT: .BYTE 1
PS2K_DATA: .BYTE 1
PS2K_RAW_READY: .BYTE 1
PS2K_RAW_CODE: .BYTE 1
PS2K_SKIP: .BYTE 1
PS2K_FLAGS: .BYTE 1
PS2K_KEY_FLAGS: .BYTE 1
PS2K_KEY_CODE: .BYTE 1
PS2K_TIMEOUT: .BYTE 2
.CSEG
;
;--------------------------------------
;
PS2K_INIT:
IN TEMP,EICRB
ORI TEMP,(1<<ISC41)|(0<<ISC40)
OUT EICRB,TEMP
IN TEMP,EIMSK
ORI TEMP,(1<<INT4)
OUT EIMSK,TEMP
LDI TEMP,(0<<CS02)|(1<<CS01)|(0<<CS00) ; clk/8
OUT TCCR0,TEMP
STS PS2K_FLAGS,NULL
STS PS2K_BIT_COUNT,NULL
STS PS2K_SKIP,NULL
STS PS2K_KEY_FLAGS,NULL
RET
;
;--------------------------------------
;
TIM0_OVF:
PS2K_DATALINE_UP
PUSH TEMP
IN TEMP,SREG
PUSH TEMP
IN TEMP,TIMSK
CBR TEMP,(1<<TOIE0)
OUT TIMSK,TEMP
POP TEMP
OUT SREG,TEMP
POP TEMP
PS2K_CLOCKLINE_UP
RETI
;
;--------------------------------------
;
EXT_INT4:
PUSH TEMP
IN TEMP,SREG
PUSH TEMP
PUSH COUNT
PUSH DATA
LDS DATA,PS2K_DATA
LDS COUNT,PS2K_BIT_COUNT
LDS TEMP,PS2K_FLAGS
SBRC TEMP,PS2K_BIT_TX
RJMP INT4TX_0
CPI COUNT,9
BREQ INT4RX9
CPI COUNT,10
BRCC INT4RXS
TST COUNT
BRNE INT4RX1
;start bit
SBIC PIND,6 ; data line
RJMP INT4RX_CLR_D
CBR TEMP,(1<<PS2K_BIT_PARITY)
INC COUNT
RJMP INT4_EXIT
;data bits
INT4RX1:LSR DATA
SBIS PIND,6 ; data line
RJMP INT4RX2
ORI DATA,0B10000000
EOR TEMP,ONE
INT4RX2:INC COUNT
RJMP INT4_EXIT
;parity bit
INT4RX9:SBIC PIND,6 ; data line
EOR TEMP,ONE
SBRS TEMP,PS2K_BIT_PARITY
RJMP INT4RX_CLR_D
INC COUNT
RJMP INT4_EXIT
;stop bit
INT4RXS:SBIS PIND,6 ; data line
RJMP INT4RX_CLR_D
STS PS2K_RAW_READY,COUNT
STS PS2K_RAW_CODE,DATA
PS2K_CLOCKLINE_DOWN
LDI COUNT,$80
OUT TCNT0,COUNT ;Tclk*8*128=~92us
LDI COUNT,(1<<TOV0)
OUT TIFR,COUNT
IN COUNT,TIMSK
ORI COUNT,(1<<TOIE0)
OUT TIMSK,COUNT
LDS COUNT,PS2K_SKIP
TST COUNT
BRNE INT4RX_SKIP
CPI DATA,$E1
BREQ INT4RX_E1
CPI DATA,$AA
BREQ INT4RX_CLR_F
CPI DATA,$AB
BREQ INT4RX_AB
CPI DATA,$EE
BREQ INT4RX_CLR_F
CPI DATA,$FA
BREQ INT4RX_CLR_F
CPI DATA,$FE
BREQ INT4RX_CLR_F
CPI DATA,$E0
BREQ INT4RX_E0
CPI DATA,$F0
BREQ INT4RX_F0
SBR TEMP,(1<<PS2K_BIT_READY)
STS PS2K_KEY_FLAGS,TEMP
STS PS2K_KEY_CODE,DATA
RJMP INT4RX_CLR_F
INT4RX_E0:
SBR TEMP,(1<<PS2K_BIT_EXTKEY)
RJMP INT4RX_CLR_D
INT4RX_F0:
SBR TEMP,(1<<PS2K_BIT_RELEASE)
RJMP INT4RX_CLR_D
INT4RX_SKIP:
DEC COUNT
STS PS2K_SKIP,COUNT
BRNE INT4RX_CLR_D
LDS DATA,PS2K_KEY_CODE
CPI DATA,$7E
BRNE INT4RX_CLR_D
LDI TEMP,(1<<PS2K_BIT_READY)|(1<<PS2K_BIT_RELEASE)|(1<<PS2K_BIT_EXTKEY)
STS PS2K_KEY_FLAGS,TEMP
RJMP INT4RX_CLR_F
INT4RX_AB:
STS PS2K_KEY_CODE,NULL
LDI COUNT,1
STS PS2K_SKIP,COUNT
RJMP INT4RX_CLR_F
INT4RX_E1:
LDI TEMP,(1<<PS2K_BIT_READY)|(1<<PS2K_BIT_EXTKEY)
STS PS2K_KEY_FLAGS,TEMP
LDI DATA,$7E
STS PS2K_KEY_CODE,DATA
LDI COUNT,7
STS PS2K_SKIP,COUNT
INT4RX_CLR_F:
CLR TEMP
INT4RX_CLR_D:
CLR DATA
CLR COUNT
RJMP INT4_EXIT
;-------
INT4TX_0:
CPI COUNT,9
BREQ INT4TX9
CPI COUNT,10
BREQ INT4TXS
CPI COUNT,11
BRCC INT4TXA
TST COUNT
BRNE INT4TX1
;start bit
SBR TEMP,(1<<PS2K_BIT_PARITY)
INC COUNT
RJMP INT4_EXIT
;data bits
INT4TX1:ROR DATA
BRCC INT4TX2
PS2K_DATALINE_UP
EOR TEMP,ONE
INC COUNT
RJMP INT4_EXIT
INT4TX2:PS2K_DATALINE_DOWN
INC COUNT
RJMP INT4_EXIT
;parity bit
INT4TX9:SBRC TEMP,PS2K_BIT_PARITY
RJMP INT4TXP
PS2K_DATALINE_DOWN
INC COUNT
RJMP INT4_EXIT
INT4TXP:PS2K_DATALINE_UP
INC COUNT
RJMP INT4_EXIT
;stop bit
INT4TXS:PS2K_DATALINE_UP
INC COUNT
RJMP INT4_EXIT
;здесь раньше проверялся ack-bit, но CHRV знает ;)
; где есть такие клавиатуры, которые не выдают этот бит.
INT4TXA:;CLR TEMP
;SBIS PIND,6 ; data line
LDI TEMP,(1<<PS2K_BIT_ACKBIT)
CLR DATA
CLR COUNT
INT4_EXIT:
STS PS2K_BIT_COUNT,COUNT
STS PS2K_DATA,DATA
STS PS2K_FLAGS,TEMP
POP DATA
POP COUNT
POP TEMP
OUT SREG,TEMP
POP TEMP
RETI
;
;--------------------------------------
;out: DATA == скан-код клавиши
; TEMP.PS2K_BIT_EXTKEY == расш.код
WAITKEY:CALL RANDOM
LDS TEMP,PS2K_KEY_FLAGS
SBRS TEMP,PS2K_BIT_READY
RJMP WAITKEY
STS PS2K_KEY_FLAGS,NULL
SBRC TEMP,PS2K_BIT_RELEASE
RJMP WAITKEY
LDS DATA,PS2K_KEY_CODE
RET
;
;--------------------------------------
;out: sreg.Z == clr - было нажатие (автоповтор)
; DATA == скан-код клавиши
; TEMP.PS2K_BIT_EXTKEY == расш.код
INKEY: CALL RANDOM
LDS TEMP,PS2K_KEY_FLAGS
SBRS TEMP,PS2K_BIT_READY
RJMP INKEY9
STS PS2K_KEY_FLAGS,NULL
SBRC TEMP,PS2K_BIT_RELEASE
RJMP INKEY9
LDS DATA,PS2K_KEY_CODE
CLZ
RET
INKEY9: SEZ
RET
;
;--------------------------------------
;in: DATA
;out: sreg.Z - CLR == ok; SET == timeout
PS2K_SEND_BYTE:
PS2K_DATALINE_UP
IN TEMP,TIMSK
CBR TEMP,(1<<TOIE0)
OUT TIMSK,TEMP
PS2K_CLOCKLINE_UP
CLR TEMP
PS2K_SEND0:
SBIS PINE,4 ; clock line
RJMP PS2K_SEND_BYTE
DEC TEMP
BRNE PS2K_SEND0
CLI
PS2K_CLOCKLINE_DOWN
PS2K_DATALINE_DOWN
STS PS2K_DATA,DATA
LDI TEMP,(1<<PS2K_BIT_TX)
STS PS2K_FLAGS,TEMP
STS PS2K_BIT_COUNT,NULL
STS PS2K_SKIP,NULL
STS PS2K_KEY_FLAGS,NULL
STS PS2K_RAW_READY,NULL
SEI
DELAY_US 100
PS2K_DATALINE_DOWN
DELAY_US 500
LDIZ PS2K_TIMEOUT
LDIW 15
CALL SET_TIMEOUT_MS
PS2K_CLOCKLINE_UP
PS2K_SEND1:
LDS TEMP,PS2K_FLAGS
ANDI TEMP,(1<<PS2K_BIT_ACKBIT)
BRNE PS2K_SEND2
LDIZ PS2K_TIMEOUT
CALL CHECK_TIMEOUT_MS
BRCC PS2K_SEND1
PS2K_DATALINE_UP
SEZ
PS2K_SEND2:
RET
;
;--------------------------------------
;out: sreg.Z - CLR == ok; SET == timeout
; DATA == byte
PS2K_RECEIVE_BYTE:
STS PS2K_RAW_READY,NULL
LDIZ PS2K_TIMEOUT
LDIW 20
CALL SET_TIMEOUT_MS
PS2K_RXBYTE1:
LDS TEMP,PS2K_RAW_READY
TST TEMP
BRNE PS2K_RXBYTE2
LDIZ PS2K_TIMEOUT
CALL CHECK_TIMEOUT_MS
BRCC PS2K_RXBYTE1
CLR DATA
SEZ
RET
PS2K_RXBYTE2:
LDS DATA,PS2K_RAW_CODE
RET
;
;--------------------------------------
;
.EQU PS2K_DETECT_TEMP=0
;
PS2K_DETECT_KBD:
GETMEM 1
PS2K_CLOCKLINE_UP
LDIZ MLMSG_KBD_DETECT*2
RCALL PRINTMLSTR
STS PS2K_RAW_READY,NULL
LDIZ PS2K_TIMEOUT
LDIW 500
CALL SET_TIMEOUT_MS
PS2K_DETECT_K1:
LDS TEMP,PS2K_RAW_READY
TST TEMP
BRNE PS2K_DETECT_K2
LDIZ PS2K_TIMEOUT
CALL CHECK_TIMEOUT_MS
BRCC PS2K_DETECT_K1
RJMP PS2K_DETECT_K3
PS2K_DETECT_K2:
LDS DATA,PS2K_RAW_CODE
RCALL HEXBYTE_FOR_DUMP
PS2K_DETECT_K3:
LDI DATA,$FF
RCALL PS2K_DETECT_SEND
; BRNE PS2K_DETECT_K6
STS PS2K_RAW_READY,NULL
LDIZ PS2K_TIMEOUT
LDIW 1000
CALL SET_TIMEOUT_MS
PS2K_DETECT_K4:
LDS TEMP,PS2K_RAW_READY
TST TEMP
BRNE PS2K_DETECT_K5
LDIZ PS2K_TIMEOUT
CALL CHECK_TIMEOUT_MS
BRCC PS2K_DETECT_K4
RCALL PS2K_DETECT_NORESPONSE
RJMP PS2K_DETECT_K6
PS2K_DETECT_K5:
LDS DATA,PS2K_RAW_CODE
RCALL HEXBYTE_FOR_DUMP
CPI DATA,$AA
BREQ PS2K_DETECT_K6
RCALL PS2K_DETECT_UNWANTED
PS2K_DETECT_K6:
LDI DATA,$F2
RCALL PS2K_DETECT_SEND
BRNE PS2K_DETECT_K7
LDI DATA,$AB
RCALL PS2K_DETECT_RECEIVE
BRNE PS2K_DETECT_K7
LDI DATA,$83
RCALL PS2K_DETECT_RECEIVE
PS2K_DETECT_K7:
LDI DATA,$F0
RCALL PS2K_DETECT_SEND
BRNE PS2K_DETECT_K8
LDI DATA,$02
RCALL PS2K_DETECT_SEND
PS2K_DETECT_K8:
LDI DATA,$F3
RCALL PS2K_DETECT_SEND
BRNE PS2K_DETECT_K9
LDI DATA,$00
RCALL PS2K_DETECT_SEND
LDIZ MSG_READY*2+3
CALL PRINTSTRZ
PS2K_DETECT_K9:
FREEMEM 1
RET
;
PS2K_DETECT_SEND:
RCALL HEXBYTE_FOR_DUMP
RCALL PS2K_SEND_BYTE
BREQ PS2K_DETECT_TXFAIL
RCALL PS2K_RECEIVE_BYTE
BREQ PS2K_DETECT_NORESPONSE
RCALL HEXBYTE_FOR_DUMP
CPI DATA,$FA
BRNE PS2K_DETECT_UNWANTED
RET
;
PS2K_DETECT_RECEIVE:
STH PS2K_DETECT_TEMP,DATA
RCALL PS2K_RECEIVE_BYTE
BREQ PS2K_DETECT_NORESPONSE
RCALL HEXBYTE_FOR_DUMP
LDH TEMP,PS2K_DETECT_TEMP
CP DATA,TEMP
BRNE PS2K_DETECT_UNWANTED
RET
;
PS2K_DETECT_TXFAIL:
LDIZ MLMSG_TXFAIL*2
RJMP PS2K_DETECT_XXFAIL
PS2K_DETECT_UNWANTED:
LDIZ MLMSG_UNWANTED*2
RJMP PS2K_DETECT_XXFAIL
PS2K_DETECT_NORESPONSE:
LDIZ MLMSG_NORESPONSE*2
PS2K_DETECT_XXFAIL:
CALL PRINTMLSTR
CLZ
RET
;
;--------------------------------------
;