6522 as a PS2 keyboard controller?

For discussing the 65xx hardware itself or electronics projects.
nerdy1
Posts: 14
Joined: 24 Jan 2018

6522 as a PS2 keyboard controller?

Post by nerdy1 »

Hello all,

I was wondering if any of you had ever heard of, or had experience with, using a 6522 as a keyboard controller for a PS/2 keyboard? I don't wish to use a microcontroller in my design, but I also don't wish to design and build my own keyboard!
The PS2 keyboard protocol is kind of funky with an 11-bit packet and no common BAUD rate (it just pulses the clock "whenever it feels like it?" -- I see rates reported from 10kHz to 30kHz.) I can't wrestle that protocol with a typical UART. I'm not even sure it could be done with a 6522 but I thought I would ask.

My fall-back position is to maybe connect the keyboard data line to a single data line on a regular peripheral interface adapter (or some other kind of latch?). I need the keyboard clock falling low to signal an interrupt on the CPU, but it can't be tied directly -- it needs to just pulse, so the IRQ line can return to high. Keyboard data line is valid while the clock line is low, so I could in theory then try to bit-bang the keyboard's serial data directly from the CPU. I am all still new to the hardware side of this stuff so I expect there are obvious things that I am missing.

Your thoughts and comments are much appreciated!
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: 6522 as a PS2 keyboard controller?

Post by DerTrueForce »

I don't know anything about implementing PS2, but if you're willing to code scanning and decoding the keyboard, you could use one of these.
Last edited by DerTrueForce on Wed Jan 24, 2018 5:33 am, edited 1 time in total.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by BigEd »

Hi nerdy1, and welcome.

I had a look around, and I think I've found a couple of references to previous work (most people these days have used a microcontroller, but not everyone.) Hope you'll find it useful - but it would be great if you can succeed and publish your work too.

Daryl's SBC project has this:
http://sbc.rictor.org/io/pckb6522.html
(see also this thread)

And the late Lee Davison had this, using a GAL:
http://retro.hansotten.nl/lee-davison-w ... interface/
(also here, but with the pictures missing)

And Dieter managed something too, using some TTL shift registers to assist:
http://www.6502.org/users/dieter/drc2/drc2.htm

It seems the AT keyboard and PS/2 keyboard use the same protocol, just a different connector - if that's not so, please correct me! And, at least at one point, most USB keyboards also can use the PS/2 protocol and just need a trivial electrical adapter.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by GARTHWILSON »

http://www.computer-engineering.org/ps2protocol/ looks helpful. You can do it with a 65(c)22. There's not a baud rate in the sense that a UART uses it, because it's synchronous, not asynchronous. Instead it's similar to I²C but with a minimum clock-low and clock-high time of 30µs and maximum of 50µs, and with a parity bit at the end instead of an ACK bit.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
nerdy1
Posts: 14
Joined: 24 Jan 2018

Re: 6522 as a PS2 keyboard controller?

Post by nerdy1 »

Thank you everyone for those links -- that is very helpful!
I am thrilled that it not only looks possible to do with a VIA, but there is even source code for me to "borrow"! (I think I will want an interrupt-based version of Daryl's code, but hopefully that will just be a software-only modification.)
New 65C22 is on the way...and I have some studying to do!
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by GARTHWILSON »

The VIA's CA1, CA2, CB1, and CB2 pins can be used as interrupt-on-change pins, suitable for an externally sourced clock signal. You can of course have a line connected to both that and one of the port pins at the same time, and then use the port pin to emulate an open-drain I/O by writing a 0 to its bit in the port's output register and then making the bit an output when you want to pull the line down, or an input when you want to read it or let it float up. Use an external pull-up resistor of course.

It isn't I²C, but very similar. I have an I²C-with-VIA part of the "circuit potpourri" page of the 6502 primer, at http://wilsonminesco.com/6502primer/pot ... ITBANG_I2C, and accompanying sample I²C bit-bang code that might give you some ideas, at http://wilsonminesco.com/6502primer/GENRLI2C.ASM .
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by cbmeeks »

This is very useful information. In my current "big board" SBC, I am using a VIA for a PS/2 keyboard, AY-3-8912 sound chip and a NES controller.

I'd love to learn more about those CA/CB pins. They are still a mystery to me. I'm planning on just bit-banging the VIA's for the moment. I will actually have two VIA's. One that I just mentioned and one for external ports.
Cat; the other white meat.
whartung
Posts: 1004
Joined: 13 Dec 2003

Re: 6522 as a PS2 keyboard controller?

Post by whartung »

The question is how much CPU bandwidth on the 6502 is necessary to decode the PS/2 protocol. 30KHz is kind of busy for a 1Mhz CPU. You'd have to be polling for bits pretty regularly, and I don't think you'd want the PS/2 clock to be hammering an interrupt.

In constrast to a keyboard scanner/decoder. You're dealing more with human terms and response rates, and can probably be a little more sloppy vs syncing up to a synchronous clock running at a random rate.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by cbmeeks »

Hmm. You got me thinking. It might be worth it to me to use a micro-controller tied to a 6522 now that I think about it. The micro-controller could handle the PS/2 and NES signals and just latch an 8 bit value on one of the VIA's ports.
Cat; the other white meat.
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: 6522 as a PS2 keyboard controller?

Post by DerTrueForce »

Garth did suggest using CA1/2 or CB1/2 as change interrupt pins. If you did that, you wouldn't need to poll them until an IRQ hits.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by GARTHWILSON »

If you don't want interrupts, putting the clock line on bit 6 or 7 of one of the ports lets you test it with BIT and then branch on the N or V flag, without regard to what's in A. Put it in a loop. The VIA does have several capabilities that do not initially meet the eye though. When you don't want the keyboard interrupting, and you don't want to miss any keyboard events, just pull its clock line low to make it wait until you're ready.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
nerdy1
Posts: 14
Joined: 24 Jan 2018

Re: 6522 as a PS2 keyboard controller?

Post by nerdy1 »

Thanks again Garth. It's important to me that my keyboard should be interrupt driven. I don't mind if it takes me a while to nail down the software.
Just so I am clear though, we are not talking about using the VIA's shift registers at all correct? We are just talking about using it to take control of the two keyboard lines, so I can drive them (or not) as needed?
Just out of curiosity, how crazy would it be to try to squeeze a 16-bit shift register into the middle there?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by GARTHWILSON »

The odd frame size would make it a bit of a challenge to handle it with the VIA's SR, but there might be a way to do it anyway, possibly using the SR to get the first 8 bits and then finishing it up in bit-banging as we were talking about above. In addition to going to the CB1 input, the clock line could still go to a CA line to generate an interrupt when a frame starts, then you have plenty of time to get into the ISR and start polling the SR-full bit (bit 2 of the interrupt flag register, or IFR) for when the first 8 bits are completed, and take the rest of the bits in manually, then reset the SR and other things needed to start the process again for the next frame. I have not sharpened my pencil to figure out anything further than what I just wrote. It's just out-loud thinking. There's usually a way to do these things. Be sure to address the VIA SR bug in mode 011 though (the only bug in the VIA, and it's in all brands) which I tell about in tip #8 of the Tip of the Day column, at viewtopic.php?p=2310#p2310 .
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Waveguide
Posts: 6
Joined: 20 Jul 2013
Contact:

Re: 6522 as a PS2 keyboard controller?

Post by Waveguide »

This topic got me doing some archeology among old Eagle files from many years ago when I was toying around with the thought of a dedicated PS/2 keyboard interface. The idea I had was to use two shift registers to capture an entire byte from the keyboard including start, stop and parity bits. When all bits are captured the PS/2 clock line is pulled low to prevent further transfer (the keyboard will buffer) and the CPU can pull one byte from the data register without any stress. The interface have one RO data register and one RW control register. Sending data to the keyboard is bit banged but data in that direction is relatively rare (mainly updating the keyboard LEDs).

This circuit was hastily put together, have not been tested and may not work at all but maybe it will spark some ideas :)
Attachments
ps2-interface.png
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: 6522 as a PS2 keyboard controller?

Post by gfoot »

As it came up recently in a similar thread, but without the use of VIAs, I thought about how I'd do this with a VIA. This is untested but I think it should work.

I searched around, and other VIA-based methods I've seen mostly revolve around bitbanging - but I think it should be possible and quite comfortable to use the shift register as Garth suggested higher in this thread, to minimise CPU overheads, maybe requiring only one interrupt per character received from the keyboard.

This circuit is quite appealing as it only requires a few small external components:
VIA-based PS/2 circuit - with SR bug
VIA-based PS/2 circuit - with SR bug
However, it suffers from the shift register bug, so we do actually need to add another IC, following Garth's advice to work around that:
VIA-based PS/2 circuit with workaround
VIA-based PS/2 circuit with workaround
This should allow bidirectional communication with the PS/2 device. The general principle is to use PB6 pulse counting via Timer 2 to get interrupts after certain bits are transmitted. You could also use CB1 interrupts or the SR interrupt, but using PB6 pulse counting alone means that for the common case of reading data we only need to spend one interrupt per frame, exactly when the data is available.

So initially we set PB6 as an input, enable shift register input with an external clock source (mode 011), and enable Timer 2's pulse counting mode. The PS/2 clock falling causes CB1 to rise on the next PHI2 leading edge, shifting data into the shift register. First we count 9 pulses, to cover the start bit and eight data bits:

Code: Select all

       start D0  D1  D2  D3  D4  D5  D6  D7
CA2 """\___/"""V"""\___/"""\___/"""V"""V""
PB6 """"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_
 T2  9   8   7   6   5   4   3   2   1   0
                               T2 IRQ ---^
When the interrupt arrives, we read data out of the shift register and reset Timer 2 to count another 11 pulses - that covers the parity bit, stop bit, next start bit, and 8 data bits - so this will give another interrupt after the next character arrives:

Code: Select all

       start D0  D1  D2  D3  D4  D5  D6  D7 par stop       start D0  D1  D2  D3  D4  D5  D6  D7 par stop
CA2 """\___/"""V"""\___/"""\___/"""V"""V"""V"""V"""""""""""\___/"""V"""\___/"""\___/"""V"""V"""V"""V""""
PB6 """"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"""""""""\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"
 T2  9   8   7   6   5   4   3   2   1   0 B A   9           8   7   6   5   4   3   2   1   0 B A   9
                               T2 IRQ ---^                                         T2 IRQ ---^
This is not doing any checking of start/parity/stop bits, so could be vulnerable to going out of sync. It may be desirable to accept two interrupts per frame, reading the first 8 bits from the shift register in the first one and the last three bits in the second one, so we can check the start/stop/parity bits are correct and resynchronise if not:

Code: Select all

       start D0  D1  D2  D3  D4  D5  D6  D7 par stop       start D0  D1  D2  D3  D4  D5  D6  D7 par stop
CA2 """\___/"""V"""\___/"""\___/"""V"""V"""V"""V"""""""""""\___/"""V"""\___/"""\___/"""V"""V"""V"""V""""
PB6 """"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"""""""""\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"\_/"
 T2  8   7   6   5   4   3   2   1   0 3 2   1   0 8         7   6   5   4   3   2   1   0 3 2   1   0 8
                           T2 IRQ ---^-----------^                             T2 IRQ ---^-----------^
If we need to pause data transmission or interrupt a character, we can briefly set PB6 as a low output to pull the PS/2 clock line low. This interrupts the device and we can set T2 to its initial value again, get an interrupt where we want it during the next character. This could be an appropriate response to detecting a framing error.

To send a character to the device, we need to pull the PS/2 clock (PB6) low as above, and then pull the PS/2 data line low by setting CB2 as a low output, then let the clock float again (by setting PB6 as an input). There are some timing constraints here. Then we need to send data in sync with the clock coming from the device. That can be done either by bitbanging CB2 based on CB1 rising-edge interrupts, or using the shift register, but note that we have more than 8 bits to send, so if we are using the shift register then we need to catch the interrupt on shift register completion (or use PB6 pulse counting again) and send a second byte at that point, in order to fill out the full frame. The second byte won't complete (the device won't send enough clock pulses) so we also then need to count the pulses and, after the frame is over, turn off the shift register output so that we're ready to receive data again.

It's also possible to poll timer 2 to determine progress during a transmit or receive, or to determine whether we are between frames - I'm not sure if that's useful for anything though.

Overall this should allow receiving data with only one interrupt per character, or two if you want to be a bit safer and check for framing errors, and allows for interrupting the device, and sending data to the device - so I think it should cover all the bases. Sending may be less efficient (requiring maybe two interrupts to manage the sending operation) but as that's rare, I don't see that as a big problem. It seems quite flexible, and while it's a shame it requires an extra IC in addition to the VIA, that's not bad overall!

Edit: I've built this now (the one with the 74HCT74 to guard against the shift register bug), and it works pretty well. The shift register is an awkward little thing to get working properly though - it doesn't act exactly how any of the datasheets say (comparing the WDC ones to the Rockwell ones, and to the old typewritten MOS one). The upshot is, we do need to use two interrupts per input character - but it's not wasted, as it allows doing all the framing and parity checks. I've attached the code for reference in case it's useful to anyone - this uses interrupts for reads, but bit-banging for writes (as they are much more rare) - though it should be possible, with care, to use the shift register for writes as well.

Edit 2 - I looked into using the shift register for writes as well as reads, but it's not a good fit because it changes the data on the wrong clock edge. To make that work you'd need some external circuit to uninvert the clock during writes, which is not really practical. The shift register would also drive CB2 high as well as low, when it's meant to be an open-collector signal, so it's not a great fit really.
Attachments
ps2test.s
Sample code for reading and writing the PS/2 keyboard
(6.94 KiB) Downloaded 74 times
Post Reply