Interface keyboard via USART

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

I want to interface an AVR with an old 83 key IBM XT keyboard. It uses a 2 wire (clock/data) protocol that is a bit simpler than the one used by modern PS/2 keyboards. It is a one way protocol (keyboard >> AVR)that uses 1 start bit, 8 data bits, 0 parity bits, 0 stop bits.

Is there any chance that this could be made to work with the AVR's hardware UART/USART?

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

I thought that all older PC keyboards used the PS/2 protocol i/f.

If you really have an asynchronous UART i/f, your life is easy. Does it use TTL levels ? Do some Googling.

Alternatively just find an old PS/2 keyboard and there is plenty of PS/2 code for an AVR.

David.

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

I thought the XT keyboard contained an 8042 which is a synchronous clock master so a "listener" has to bit-bang it (probably with the help of an external int). Each time the keyboard controller "waggles the clock" you take a sample of the data line and build the byte. I think it operates at 20kHz or was it 50kHz so you need to be fairly responsive.

Of course my memory of XT keyboards is jaded because the keyboard was the one part of the XT that IBM actually patented so for our PCs we designed a completely different keyboard interface then never heard the end of it from people moaning that "why cannot I just plug an XT keyboard into an Amstrad PC1512/1640?". In later PCs we followed the herd and just did the same interface as everyone else as there were no signs (curiously!) of IBM chasing patent infringement. If they'd wanted to kill the clone market this would have been the way they could have done it!

EDIT: this page looks very useful:

http://www.kbdbabel.org/signalin...

Shows signalling for both our keyboard and the IBM XT. Those 95us pulses for the IBM seem to show it is about 10kHz in fact.

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

I was hopping that I could use a USART instead of bit banging for better performance. According to: http://www.cs.cmu.edu/afs/cs/usr/jmcm/www/info/key2.txt the data rate is around 2000 bit/s.

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

Quote:

I was hopping that I could use a USART instead of bit banging for better performance.

Define "better performance". The fact is that with the falling edge interrupt you just go an sample "data" each time it occurs and shift that state into a byte that's being built. It's not like you have to sit in a loop polling the clock line or something.

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

clawson wrote:
Quote:

I was hopping that I could use a USART instead of bit banging for better performance.

Define "better performance". The fact is that with the falling edge interrupt you just go an sample "data" each time it occurs and shift that state into a byte that's being built. It's not like you have to sit in a loop polling the clock line or something.

That's true. I guess I had it in my head that it would be more reliable if I was using a dedicated hardware receiver. My plan is to create a XT to USB HID converter using a ATmega32U4 breakout board.

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

Sounds like fun.

My experience of XT keyboard protocol stems mainly from the design of this:

http://www.ebay.co.uk/itm/Amstra...

See the little pull out keyboard? That's really a PC XT keyboard containing a Holtek keyboard controller but done on a very small scale. As it's transmit only (unlike an AT keyboard) and it is the clock master it meant our device (the phone) had to be responsive to its clock pulses. That was easy to achieve on this first (and the second) model where we basically "owned" the CPU and putting in an external interrupt ISR was easy with guaranteed fast response time. But when we made the third model in the series:

http://www.ebay.co.uk/itm/AMSTRA...

To implement the video telephone we had to move the whole thing to using Linux (on an ARM9) and trying to persuade Linux to give us real-time response to our keyboard interrupt handler so that no clock pulse was ever missed was a thankless task. I guess that's what they call progress!

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

Looking at the XT protocol diagram, it looks as if there is in fact an implicit stop bit "0". I have never used UART before, but doesn't this mean I could use a UART in synchronous mode, set for 1 start bit, 8 data bits, 0 parity bits and 1 stop bit?

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

Yes you can use the USART to interface to your keyboard. Both XT and AT keyboards can be interfaced to the USART for RX. To TX [to an AT keyboard] you need to bit-bang, but can then switch back to the USART for RX.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

I'd debug this on something with 2 uarts like a mega324 or a mega162. Get one of them talking to teraterm at 115200, then write something that will clock in from the keyboard and display the scan code in hex on the real serial line. Should be able to use sync mode to the keyboard. That's how it works.

Imagecraft compiler user

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

OK, I'm bumping this because I finally received my AVR breakout and am ready to implement this. I'm looking at the pin descriptions now and I see that PD2 is the USART RX pin, and PD5 is XCK1, the synchronous external clock for the USART.

My question is how to set this up. My intention is that when they keyboard controller sends a key code, the AVR will be interrupted and read the byte in an ISR. Does the AVR support hardware interrupt when XCK1 transitions from high to low?

link

Going back to the signal diagram you can see that CLK in normally high and transitions low just before a transmission. Bits are clocked in on the low to high edge. Is this all compatible with the AVR USART, and if so how should I set it up for this?

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

Read about synchronous mode in the USART chapter... clk comes in on XCK1

Imagecraft compiler user

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

Well, looking at the data sheet I see that pins PD0 - PD3 correspond to INT0 - INT3, but it doesn't say anything about PD5/XCK1 being an interrupt, which is why I'm not certain if it supports XCK1 as an interrupt.

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

Both the following examples use an interrupt pin for the clock and a normal port pin for the data. Looking at your picture it seems the start bit is too long for normal uart comms. At the low data rate, I wouldn't be too worried about efficiency.

http://extremeelectronics.co.in/...

http://www.atmel.com/Images/doc1...

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

Kartman wrote:
Looking at your picture it seems the start bit is too long for normal uart comms

I'm unfamiliar with USARTs, but why would it matter if it's being clocked externally?

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

Good point. Have you found an example where the usart has been used? It seems the common method does not use a usart. There is probably a good reason for this.

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

I'd just bit-bang it in an INTn_vect ISR. The only thing the UART electronics would be providing otherwise is a shift register and this is easy to implement in software anyway.

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

Well, unless I'm mistaken it seems like I should be able to use the USART for this. The XT keyboard is clock master with a protocol that seems to be USART friendly. It seems all I would have to do it set the USART to synchronous slave mode, set the polarity to input on the rising edge, and then set up an ISR for USART_RXC_vect.

Correct me if I'm wrong, but that seems like it would be better than bit banging.

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

You might want to watch this. Note the comments about baud rate.

http://www.youtube.com/watch?v=y...

If you get yours working, let us know.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

I'm not using a UART, I'm using a USART, in synchronous slave mode. The keyboard is the clock master and the keyboard only ever talks to to microcontroller, never the other way around, so baud rate should be irrelevant.

Here's a question though. Once the USART has received a scan code and enters the ISR, is it possible to set XCK low from there? Lowering the clock line would prevent the keyboard from sending any more data for the duration of the ISR.

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

Chris, if you're so hell bent on using the usart, then give it a go and tell us if it worked. Not having used the sync mode of the usart before, I did a quick read of the mega128 datasheet and it has a chance of working, but there maybe other issues I haven't considered. The time you've spent querying this forum could've been better spent testing your theory. Personally, I'd just go with the interrupt and port bit since there's worked examples and I'd normally use the usart for other comms.

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

Well, I would if I could.

I'm trying to upload a test program with avrdude and all I'm getting is:

Quote:

avrdude: ser_open(): can't open device "/dev/ttyACM0"Input/output error
Eavrdude: butterfly_recv(): programmer in not responding

Breakout board: http://www.sparkfun.com/products/11117
Command line: sudo avrdude -p m32u4 -P /dev/ttyACM0 -c avr109 hello-avr.out
dmesg output: cdc_acm 5-2:1.0: ttyACM0: USB ACM device
OS: Linux Mint 13.0

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

OK I managed to get avrdude working though I had to switch to Windows XP.

I'm just trying to verify this thing is working but so far I've gotten nowhere.

Here is my test code.

#define F_CPU 16000000
#include 
#include 

int main (void)
{
	DDRB = 0xFF;
	while(1)
	{
		PORTB = 0xFF;
		_delay_ms(1000);
		PORTB = 0x00; 
		_delay_ms(1000);
	}
}

compiled with:

avr-gcc -mmcu=atmega32u4 -Os -Wall hello-avr.c -o hello-avr.o

avr-objcopy -j .text -j .data -O ihex hello-avr.o hello-avr.hex

avrdude -p m32u4 -P COM3 -c avr109 -U flash:w:hello-avr.hex

I used my volt meter to test the pins of PORTB but it can't seem to lock on to anything as if it's fluctuating all over the place.

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

Chris_F wrote:

Here's a question though. Once the USART has received a scan code and enters the ISR, is it possible to set XCK low from there? Lowering the clock line would prevent the keyboard from sending any more data for the duration of the ISR.

Reading a whole byte from UART and storing it for later use is so much faster process than the keyboard can transmit a single bit. I cannot imagine how this can be a problem.

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

Chris_F wrote:

link

Going back to the signal diagram you can see that CLK in normally high and transitions low just before a transmission. Bits are clocked in on the low to high edge. Is this all compatible with the AVR USART, and if so how should I set it up for this?

No I think that it is not compatible because in that picture the start bit is a logic 1 and stop bit is a logic 0. Based on that picture the data line also idles low, but my memory serves it should idle high and the picture is wrong.

The AVR USART must have a start bit of 0 and stop bit of 1. And the data line must idle high when there is no transmission, although then there is no clock either so that may not be necessary.

Also some sources say the XT protocol has two start bits. I vaguely remember that being true with my experiments, but that was over 10 years ago.

In fact I connected both AT and XT keyboards to PC parallel port as it had interrupt capability. Then I wrote a simple game for two players using two keyboards. Later I only used AT keyboards with AVRs, just by using the clock as interrupt.

Ah here is the document I have also read back then, from 1996: http://ilkerf.tripod.com/c64tower/F_Keyboard_FAQ.html

So in short: If you insist making it with USART, please invert the signal first. If there really are two start bits, then you must configure the USART to receive ninth data bit.

If you receive bits in an interrupt, you can keep your bit receiving routine syncronized with the known high/low start/stop bits or if no clock pulses have been there for long enough time then the first pulse must be a start bit.

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

Quote:

I used my volt meter to test the pins of PORTB but it can't seem to lock on to anything as if it's fluctuating all over the place.

That suggests the B pins are floating inputs which further suggests the code was not actually programmed into the AVR (and in the absence of any code setting DDRB and PORTB the deafult state is floating inputs).

I see you are using an AVR109 bootloader. Did avrdude run to completion without showing any errors? If you now ask it rto read back the code from the AVR does what you get match what you think you sent.

By the way I notice in the earlier avrdude command you were trying to send a .out command - that's not going to work though your later set of Windows commands looks like it should.

By the way rather than typing complex invocations of avr-gcc and avr-objcopy each time would you not consider using a Makefile (so you only have to get it right once). What's more for both Windows and Linux you can use Mfile (it even comes with WinAVR on Windows) and that will write you a very complete Makefile where you do little more than give the CPu target, the filenames and a few other options.

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

The watchdog may also be resetting the AVR periodically. Or the multimeter really slow to stabilize with a new reading (big RC filter inside).