USART for PS/2. Why does loop-back mess with RX data?

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hi freaks,

So I wanted to use USART to interface a ps2 keyboard on a AVR128DB28. With the code I've written to test received data, I read scan codes successfully. However, once I enable loop-back (without any further modifications to the code). I start getting regular parity/frame errors (the data itself is also corrupted). Anyone has a clue why?

 

The code:

	.dseg
ps2ptr:	.byte	2

	.cseg

ps2init:
	push	r16

	; setup usart module
	ldi	r16, 0b1000_1_000			; RX Complete ISR and Loop-back Mode
	sts	USART0_CTRLA, r16
	ldi	r16, 0b1000_1_000			; RX enable and open drain
	sts	USART0_CTRLB, r16
	ldi	r16, 0b01_11_0_011		; SYNC, ODD parity, 1 Sp, 8bit
	sts	USART0_CTRLC, r16
	ldi	r16, 0b00_00_00_01		; usart to pins: P4-P7
	sts	PORTMUX_USARTROUTEA, r16

	; setup clock pin
	ldi	r16, 0b0_0_00_1_000		; ~invert and enable pullup
	sts	PORTA_PIN6CTRL, r16
	ldi	r16, 0b01000000			; set xck as input
	sts	PORTA_DIRCLR, r16
	; setup data pin
	ldi	r16, 0b0_0_00_1_000		; enable pullup
	sts	PORTA_PIN5CTRL, r16

	; setup test pointer
	ldi	r16, LOW(vgafb)    ; initializes ps2ptr with start of sram for testing purposes (vgafb is defined on another file)
	sts	ps2ptr, r16
	ldi	r16, HIGH(vgafb)
	sts	ps2ptr+1, r16

	pop	r16
	ret

; Receive Complete (RXC) Interrupt
ips2rx:
	push	r16
	push	ZL
	push	ZH

	lds	r16, USART0_RXDATAH             ; load flags
	ldi	ZL, LOW(vgafb)
	ldi	ZH, HIGH(vgafb)
	st	Z, r16                          ; save flags to start of ram
	andi	r16, 0x7F
	brne	_ips2rxend                      ; if error flags are set, end procedure

	lds	ZL, ps2ptr
	lds	ZH, ps2ptr+1
	lds	r16, USART0_RXDATAL
	st	Z+, r16                         ; read received data, and store it in ram sequentially

	cpi	ZL, 0x80
	brne	_ips2rxend
	cpi	ZH, 0x65
	brne	_ips2rxend
	ldi	r16, LOW(vgafb)
	sts	ps2ptr, r16
	ldi	r16, HIGH(vgafb)
	sts	ps2ptr+1, r16                   ; don't store outside of vgafb (for testing purposes)

_ips2rxend:
	sts	ps2ptr, ZL
	sts	ps2ptr+1, ZH	

	lds	r16, USART0_RXDATAL             ; ensure RXDATA is emptied
	pop	ZH
	pop	ZL
	pop	r16
	reti

 

-Miguel

 

Edit: Added some comments to the code for readability

This topic has a solution.
Last Edited: Fri. Apr 9, 2021 - 05:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't think that usual USARTs would support PS/2 communications.

In particular:

ldi	r16, 0b01_11_0_011		; SYNC, ODD parity, 1 Sp, 8bit

I thought "synchronous" and "start/stop bits" did not not work at the same time.  But the datasheet is a bit skimpy on the operation of sync mode (excepting "master SPI")

Are you working from some sort of App Note that implies it is possible?

 

I did find:

https://www.microchip.com/forums...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Does the open drain need a pullup?

 

Bit 3 – LBME Loop-back Mode Enable
Writing a ‘1’ to this bit enables an internal connection between the TXD pin and the USART receiver and disables
input from the RXD pin to the USART receiver.

 

if its not connected, it might not have one... just a guess

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


westfw wrote:
I thought "synchronous" and "start/stop bits" did not not work at the same time

So did I, but Wikipedia suggests this is correct:

https://en.wikipedia.org/wiki/PS/2_port

 

This used to be a very common project back in the days when PS/2 was a thing, so there ought to be plenty of historic references - plenty of hits for "AVR PS/2" on google:

 

https://www.google.com/search?q=AVR+PS%2F2

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Plexd wrote:
Bit 3 – LBME Loop-back Mode Enable
Writing a ‘1’ to this bit enables an internal connection between the TXD pin and the USART receiver

Apart from any implication to the AVR and its code, PS/2 has only a single data line; so a simple hardware loopback like this cannot possibly work - surely ?

 

PS/2 can only be transferring data in one direction at any one time.

 

So, if you really want a loop-back, you're going to have to do it in software: receive first, then turn the bus around, then transmit.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I'ts working!

@Plexd answer was an eye opener. My mistake was that I thought loop-back mode used pin RX for bi-directional comms instead of TX... It uses TX.

And yeah, I've enabled pullups on both the data line (TX) and the clock line. I've only tested receiving data though, I'll update when I get transmitting

 

westfw wrote:

I thought "synchronous" and "start/stop bits" did not not work at the same time.  But the datasheet is a bit skimpy on the operation of sync mode (excepting "master SPI")

Are you working from some sort of App Note that implies it is possible?

 

I'm not using an App Note, in fact I found very little when it comes to hardware ps2 on an avr on the web.

However, the fact that it is working, would make me believe that it is possible. There's nothing on the datasheet that implies it's impossible either.

 

awneil wrote:

So, if you really want a loop-back, you're going to have to do it in software: receive first, then turn the bus around, then transmit.

 

I want to prove you wrong, I think you only need software to pull the data clock low before trasmitting (Maybe this could even be a timer event). Once that's done, the keyboard will stop sending data, load the command into the tx buffer and off you go.

Now this is in theory, I will be back when I have practical proof ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For the benefit of future readers who may come along with the same question, would you care to share the working code?

 

miguel_roldao wrote:
I want to prove you wrong, I think you only need software to pull the data clock low before trasmitting (Maybe this could even be a timer event). Once that's done, the keyboard will stop sending data, load the command into the tx buffer and off you go.

Isn't that exactly what I said?

 

  1. you need to complete the receive operation
  2. Turn the bus around - ie, pull the data clock low before trasmitting
  3. do the transmission

 

all of that needs software to control it, and to store the received data prior to re-transmitting it  - you can't just use a simple hardware loopback; ie, just connecting Tx to Rx.

 

But anyhow, it's working; so now you can mark the solution - see Tip #5 in my signature, below:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

awneil wrote:

For the benefit of future readers who may come along with the same question, would you care to share the working code?

 

Here goes:

ps2init:
	push	r16
	
	; setup usart module
	ldi	r16, 0b1000_1_000		; RX Complete ISR and Loop-back Mode
	sts	USART0_CTRLA, r16
	ldi	r16, 0b1000_1_000		; RX enable and open drain
	sts	USART0_CTRLB, r16
	ldi	r16, 0b01_11_0_011		; SYNC, ODD parity, 1 Sp, 8bit
	sts	USART0_CTRLC, r16
	ldi	r16, 0b00_00_00_01		; usart to pins: P4-P7 (route it wherever you want)
	sts	PORTMUX_USARTROUTEA, r16
	
	; setup clock pin
	ldi	r16, 0b0_0_00_1_000		; enable pullup
	sts	PORTA_PIN6CTRL, r16
	ldi	r16, 0b01000000			; set xck as input
	sts	PORTA_DIRCLR, r16
	; setup data pin
	ldi	r16, 0b0_0_00_1_000		; enable pullup
	sts	PORTA_PIN4CTRL, r16

	pop	r16
	ret

; Receive Complete (RXC) Interrupt
ips2rx:
	push	r16
	push	r17

	lds	r16, USART0_RXDATAH		; load flags
	lds	r17, USART0_RXDATAL             ; load data
	andi	r16, 0x7F
	brne	_ips2rxend			; if error flags are set, end procedure

        ; do whatever you want with your beautiful data here

_ips2rxend:
	pop	r17
	pop	r16
	reti 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now, if only I could find that old PS2 keyboard.......

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
I did find:
Thanks; in that thread are mentions of

  • glue logic
  • bit bang

glue logic - CCL can enhance USART

bit bang - PS/2 has a significant bit rate

 


Can USART synch act as a PS/2 port | Microchip

 

Advanced Examples | Getting Started with Configurable Custom Logic (CCL)

PS2Keyboard Library, Connect a keyboard for user input (PJRC)

Wayback Machine | Computer-Engineering.org | The PS/2 Mouse/Keyboard Protocol

[2/3 page]

The clock frequency must be in the range 10 - 16.7 kHz. 

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Huh.  Does that mean that 0 start bits and 0 stop bits is not possible when operating the USART in Synchronous mode?  I would have assumed that that was the default (like SPI.  But note that SPI Master Mode and Synchronous mode are not the same thing.)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:

Huh.  Does that mean that 0 start bits and 0 stop bits is not possible when operating the USART in Synchronous mode?  I would have assumed that that was the default (like SPI.  But note that SPI Master Mode and Synchronous mode are not the same thing.)

 

Yup, in synchronous mode USART, there's always start and stop bits. Unless its Master SPI mode, but this mode is locked to 8 data bits.

 

 

Now, I'm having trouble to find a way to implement transmitting data without using all software. I had some ideas:

  1. Use USART in synchronous mode. But because the start bit is sent while the clock line is low, I can't find a way to trigger the transmitter. If there was a way to trigger the transmitter by software, it would be a really neat way to implement ps/2 on USART.
  2. Use USART in SPI master mode, so I can send the start bit by software, and the other bits are handled by the transmitter. However because SPI master mode is limited to 8 bits, I would need to send 2 packets and somehow end the second one after 2 bits.

 

Last Edited: Fri. Apr 9, 2021 - 05:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

miguel_roldao wrote:
I'm having trouble to find a way to implement transmitting data without using all software.

It's been asked before:

https://www.google.com/search?q=implement+ps%2F2+on+USART

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...