If you read my last post on dealing with the delightful Commodore C16 keyboard (You didn't? Shame on you; I don't write these posts for myself you know!... Actually that's not true - I write them almost exclusively for myself and am genuinely amazed at the four people who come to this blog and read this crap.) then you'll probably be thinking that an Arduino with a keyboard connection which uses up almost all of its digital pins is pretty useless.
And right you are.
I did explain that I'd first tried to use shift registers to reduce the pin count but had run into a few problems. Well... in this post, I'm putting the 74HC595 back into the circuit so that "Port A" only takes up three Arduino pins instead of the eight we used last time.
The 74HC595 is a dead simple serial to parallel IC. And here's a perfect example of why I hate schematics... they make everything look so complicated.
I've left out the data lines for "Port B" since at the moment, they're still directly wired into the Arduino as before. "Port A" is now the eight Q output lines from the chip; we're not using the RESET function so that's tied high; and GND goes to... ground!?
I'm going to be borrowing SPI terminology here. We need to control three lines to pass serial data from the Arduino to the 74HC595. We have a CLOCK pulse line, an enable line (OE - Output Enable) which is active low and tells the 74HC595 to load the data it has received onto the Q output pins; and a MOSI (master-output/slave-input or Arduino-output/595-input if you like).
If you look again at the schematic, in particular at the IC, you'll spot two clock lines. Yep, the 74HC595 uses two clock pulses but I'm tying them together to keep things slightly simpler. To cut a long story short, what this means is that I need to add an extra clock pulse after I've finished sending my data byte, otherwise the final bit is missed off. If you can't figure out why from reading the datasheet, feel free to ask.
Coding this is beautifully simple - declare your pins.
byte _OE = 9; byte _CLOCK = 2; byte _MOSI = 3;
Make sure you set them up in setup() and initialise their default values.
pinMode(_OE, OUTPUT); digitalWrite(_OE, HIGH); pinMode(_CLOCK, OUTPUT); digitalWrite(_CLOCK, LOW); pinMode(_MOSI, OUTPUT); digitalWrite(_MOSI, LOW);
Now when you're ready to send a byte to the C16 keyboard in order to select a row from the key matrix, you pull OE high so that the 595 doesn't display the output yet; use the shiftOut() function to send the data byte; pulse the clock one extra time; and then bring OE low so that the final byte value is sent to the keyboard connector pins.
void KBD_Write(byte data)
{
digitalWrite(_OE, HIGH);
shiftOut(_MOSI, _CLOCK, MSBFIRST, data);
digitalWrite(_CLOCK, HIGH); //need an extra clock since we've tied the two clock pins on the IC together
digitalWrite(_CLOCK, LOW);
digitalWrite(_OE, LOW);
}That's our new KBD_Write() function - replacing the shit from the last post with a much cleaner way of selecting those key rows.
One import thing to note: although this looks like SPI, it isn't. Or at least, it doesn't work with the SPI library available from the Arduino IDE. I'm staying away from the standard pins because even including the library in your sketch messes all of this up if you try to put your CLOCK and MOSI on the pins the library uses. And I need that library later...
Next... taking another crack at using a 74HC165 for handling the keyboard's input.





0 Comments