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
|
; - 2: awaiting parity bit
|
||||||
; - 3: awaiting stop bit
|
; - 3: awaiting stop bit
|
||||||
; it reaches 11, we know we're finished with the frame.
|
; 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
|
; R20: data being sent to the 595
|
||||||
; Y: pointer to the memory location where the next scan code from ps/2 will be
|
; Y: pointer to the memory location where the next scan code from ps/2 will be
|
||||||
; written.
|
; written.
|
||||||
@ -174,14 +174,13 @@ loop:
|
|||||||
|
|
||||||
; Process the data bit received in INT0 handler.
|
; Process the data bit received in INT0 handler.
|
||||||
processbit:
|
processbit:
|
||||||
in r16, GPIOR0 ; backup GPIOR0 before we reset T
|
in r19, GPIOR0 ; backup GPIOR0 before we reset T
|
||||||
andi r16, 0x1 ; only keep the first flag
|
andi r19, 0x1 ; only keep the first flag
|
||||||
cbi GPIOR0, 0
|
cbi GPIOR0, 0
|
||||||
clt ; ready to receive another bit
|
clt ; ready to receive another bit
|
||||||
|
|
||||||
; We've received a bit. reset timer
|
; We've received a bit. reset timer
|
||||||
ldi r19, TIMER_INITVAL
|
rcall resetTimer
|
||||||
out TCNT0, r19
|
|
||||||
|
|
||||||
; Which step are we at?
|
; Which step are we at?
|
||||||
tst r18
|
tst r18
|
||||||
@ -193,7 +192,7 @@ processbit:
|
|||||||
; step 3: stop bit
|
; step 3: stop bit
|
||||||
clr r18 ; happens in all cases
|
clr r18 ; happens in all cases
|
||||||
; DATA has to be set
|
; 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
|
breq loop ; not set? error, don't push to buffer
|
||||||
; push r17 to the buffer
|
; push r17 to the buffer
|
||||||
st Y+, r17
|
st Y+, r17
|
||||||
@ -203,7 +202,7 @@ processbit:
|
|||||||
processbits0:
|
processbits0:
|
||||||
; step 0 - start bit
|
; step 0 - start bit
|
||||||
; DATA has to be cleared
|
; 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
|
brne loop ; Set? error. no need to do anything. keep r18
|
||||||
; as-is.
|
; as-is.
|
||||||
; DATA is cleared. prepare r17 and r18 for step 1
|
; 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
|
; We're about to rotate the carry flag into r17. Let's set it first
|
||||||
; depending on whether DATA is set.
|
; depending on whether DATA is set.
|
||||||
clc
|
clc
|
||||||
sbrc r16, 0 ; skip if DATA cleared.
|
sbrc r19, 0 ; skip if DATA cleared.
|
||||||
sec
|
sec
|
||||||
; Carry flag is set
|
; Carry flag is set
|
||||||
ror r17
|
ror r17
|
||||||
@ -228,21 +227,23 @@ processbits1:
|
|||||||
rjmp loop
|
rjmp loop
|
||||||
processbits2:
|
processbits2:
|
||||||
; step 2 - parity bit
|
; step 2 - parity bit
|
||||||
mov r1, r16
|
mov r1, r19
|
||||||
mov r19, r17
|
mov r19, r17
|
||||||
rcall checkParity ; --> r16
|
rcall checkParity ; --> r16
|
||||||
cp r1, r16
|
cp r1, r16
|
||||||
; TODO: implement "resend requests" on parity check failure
|
brne processbitError ; r1 != r16? wrong parity
|
||||||
brne processbitReset ; r1 != r16? wrong parity
|
|
||||||
inc r18
|
inc r18
|
||||||
rjmp loop
|
rjmp loop
|
||||||
|
|
||||||
|
processbitError:
|
||||||
|
clr r18
|
||||||
|
ldi r19, 0xfe
|
||||||
|
rcall sendToPS2
|
||||||
|
rjmp loop
|
||||||
|
|
||||||
processbitReset:
|
processbitReset:
|
||||||
clr r18
|
clr r18
|
||||||
ldi r16, TIMER_INITVAL
|
rcall resetTimer
|
||||||
out TCNT0, r16
|
|
||||||
ldi r16, (1<<TOV0)
|
|
||||||
out TIFR, r16
|
|
||||||
rjmp loop
|
rjmp loop
|
||||||
|
|
||||||
; send next scan code in buffer to 595, MSB.
|
; send next scan code in buffer to 595, MSB.
|
||||||
@ -293,6 +294,105 @@ sendTo595Loop:
|
|||||||
|
|
||||||
rjmp loop
|
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.
|
; Check that Y is within bounds, reset to SRAM_START if not.
|
||||||
checkBoundsY:
|
checkBoundsY:
|
||||||
tst YL
|
tst YL
|
||||||
|
Loading…
Reference in New Issue
Block a user