recipes/rc2014/ps2: add "resend" requests on parity check failures
This commit is contained in:
parent
0f82ebe02d
commit
2c6ab08d51
@ -75,7 +75,7 @@
|
||||
; - 2: awaiting parity bit
|
||||
; - 3: awaiting stop bit
|
||||
; it reaches 11, we know we're finished with the frame.
|
||||
; R19: Register used for parity computations
|
||||
; R19: Register used for parity computations and tmp value in some other places
|
||||
; R20: data being sent to the 595
|
||||
; Y: pointer to the memory location where the next scan code from ps/2 will be
|
||||
; written.
|
||||
@ -174,14 +174,13 @@ loop:
|
||||
|
||||
; Process the data bit received in INT0 handler.
|
||||
processbit:
|
||||
in r16, GPIOR0 ; backup GPIOR0 before we reset T
|
||||
andi r16, 0x1 ; only keep the first flag
|
||||
in r19, GPIOR0 ; backup GPIOR0 before we reset T
|
||||
andi r19, 0x1 ; only keep the first flag
|
||||
cbi GPIOR0, 0
|
||||
clt ; ready to receive another bit
|
||||
|
||||
; We've received a bit. reset timer
|
||||
ldi r19, TIMER_INITVAL
|
||||
out TCNT0, r19
|
||||
rcall resetTimer
|
||||
|
||||
; Which step are we at?
|
||||
tst r18
|
||||
@ -193,7 +192,7 @@ processbit:
|
||||
; step 3: stop bit
|
||||
clr r18 ; happens in all cases
|
||||
; DATA has to be set
|
||||
tst r16 ; Was DATA set?
|
||||
tst r19 ; Was DATA set?
|
||||
breq loop ; not set? error, don't push to buffer
|
||||
; push r17 to the buffer
|
||||
st Y+, r17
|
||||
@ -203,7 +202,7 @@ processbit:
|
||||
processbits0:
|
||||
; step 0 - start bit
|
||||
; DATA has to be cleared
|
||||
tst r16 ; Was DATA set?
|
||||
tst r19 ; Was DATA set?
|
||||
brne loop ; Set? error. no need to do anything. keep r18
|
||||
; as-is.
|
||||
; DATA is cleared. prepare r17 and r18 for step 1
|
||||
@ -216,7 +215,7 @@ processbits1:
|
||||
; We're about to rotate the carry flag into r17. Let's set it first
|
||||
; depending on whether DATA is set.
|
||||
clc
|
||||
sbrc r16, 0 ; skip if DATA cleared.
|
||||
sbrc r19, 0 ; skip if DATA cleared.
|
||||
sec
|
||||
; Carry flag is set
|
||||
ror r17
|
||||
@ -228,21 +227,23 @@ processbits1:
|
||||
rjmp loop
|
||||
processbits2:
|
||||
; step 2 - parity bit
|
||||
mov r1, r16
|
||||
mov r1, r19
|
||||
mov r19, r17
|
||||
rcall checkParity ; --> r16
|
||||
cp r1, r16
|
||||
; TODO: implement "resend requests" on parity check failure
|
||||
brne processbitReset ; r1 != r16? wrong parity
|
||||
brne processbitError ; r1 != r16? wrong parity
|
||||
inc r18
|
||||
rjmp loop
|
||||
|
||||
processbitError:
|
||||
clr r18
|
||||
ldi r19, 0xfe
|
||||
rcall sendToPS2
|
||||
rjmp loop
|
||||
|
||||
processbitReset:
|
||||
clr r18
|
||||
ldi r16, TIMER_INITVAL
|
||||
out TCNT0, r16
|
||||
ldi r16, (1<<TOV0)
|
||||
out TIFR, r16
|
||||
rcall resetTimer
|
||||
rjmp loop
|
||||
|
||||
; send next scan code in buffer to 595, MSB.
|
||||
@ -293,6 +294,105 @@ sendTo595Loop:
|
||||
|
||||
rjmp loop
|
||||
|
||||
resetTimer:
|
||||
ldi r16, TIMER_INITVAL
|
||||
out TCNT0, r16
|
||||
ldi r16, (1<<TOV0)
|
||||
out TIFR, r16
|
||||
ret
|
||||
|
||||
; Send the value of r19 to the PS/2 keyboard
|
||||
sendToPS2:
|
||||
; We don't use the general INT0 mechanism here. However, we still want
|
||||
; to listen to PCINT, so we don't disable interrupts entirely, just
|
||||
; INT0.
|
||||
ldi r16, (1<<PCIE)
|
||||
out GIMSK, r16
|
||||
|
||||
; First, indicate our request to send by holding both Clock low for
|
||||
; 100us, then pull Data low
|
||||
; lines low for 100us.
|
||||
cbi PORTB, CLK
|
||||
sbi DDRB, CLK
|
||||
rcall resetTimer
|
||||
|
||||
; Wait until the timer overflows
|
||||
in r16, TIFR
|
||||
sbrs r16, TOV0
|
||||
rjmp PC-2
|
||||
; Good, 100us passed.
|
||||
|
||||
; Pull Data low, that's our start bit.
|
||||
cbi PORTB, DATA
|
||||
sbi DDRB, DATA
|
||||
|
||||
; Now, let's release the clock. At the next raising edge, we'll be
|
||||
; expected to have set up our first bit (LSB). We set up when CLK is
|
||||
; low.
|
||||
cbi DDRB, CLK ; Should be starting high now.
|
||||
|
||||
; We will do the next loop 8 times
|
||||
ldi r16, 8
|
||||
; Let's remember initial r19 for parity
|
||||
mov r1, r19
|
||||
|
||||
sendToPS2Loop:
|
||||
; Wait for CLK to go low
|
||||
sbic PINB, CLK
|
||||
rjmp PC-1
|
||||
|
||||
; set up DATA
|
||||
cbi PORTB, DATA
|
||||
sbrc r19, 0 ; skip if LSB is clear
|
||||
sbi PORTB, DATA
|
||||
lsr r19
|
||||
|
||||
; Wait for CLK to go high
|
||||
sbis PINB, CLK
|
||||
rjmp PC-1
|
||||
|
||||
dec r16
|
||||
brne sendToPS2Loop ; not zero? loop
|
||||
|
||||
; Data was sent, CLK is high. Let's send parity
|
||||
mov r19, r1 ; recall saved value
|
||||
rcall checkParity ; --> r16
|
||||
|
||||
; Wait for CLK to go low
|
||||
sbic PINB, CLK
|
||||
rjmp PC-1
|
||||
|
||||
; set parity bit
|
||||
cbi PORTB, DATA
|
||||
sbrc r16, 0 ; parity bit in r16
|
||||
sbi PORTB, DATA
|
||||
|
||||
; Wait for CLK to go high
|
||||
sbis PINB, CLK
|
||||
rjmp PC-1
|
||||
|
||||
; Wait for CLK to go low
|
||||
sbic PINB, CLK
|
||||
rjmp PC-1
|
||||
|
||||
; We can now release the DATA line
|
||||
cbi DDRB, DATA
|
||||
|
||||
; Wait for DATA to go low. That's our ACK
|
||||
sbic PINB, DATA
|
||||
rjmp PC-1
|
||||
|
||||
; Wait for CLK to go low
|
||||
sbic PINB, CLK
|
||||
rjmp PC-1
|
||||
|
||||
; We're finished! Enable INT0, reset timer, everything back to normal!
|
||||
rcall resetTimer
|
||||
clt ; also, make sure T isn't mistakely set.
|
||||
ldi r16, (1<<INT0)|(1<<PCIE)
|
||||
out GIMSK, r16
|
||||
ret
|
||||
|
||||
; Check that Y is within bounds, reset to SRAM_START if not.
|
||||
checkBoundsY:
|
||||
tst YL
|
||||
|
Loading…
Reference in New Issue
Block a user