I'm using a pro micro board to adapt an old Atari 1200xl computer keyboard to a HID USB keyboard for my PC. The keyboard is an 8x8 matrix actively scanned through two 4051 multiplexers. A pair of signal lines, one for the modifier keys (SHIFT, CONTROL, and BREAK) and the other for all of the other keys indicate a key press by being pulled low at a given point in the scan. The connections between the Atari keyboard and the pro micro are set out in my sketch, posted below.
This is my first arduino project and I've managed to pound out some crude but effective code that works for everything except the modifiers. More specifically, the problem is that I can't figure out how to stop the modifiers from staying once a modifier key is pressed. For example, holding SHIFT switches all subsequent keys to upper case, but releasing it doesn't revert things back to lower case. Same is true for CONTROL (so everything typed after pressing Control causes much mischeif). I've tried inserting Keyboard.releaseAll() in various places in my functions and main loop, but it doesn't seem to have any effect.
I'm not looking for someone to code the solution for me, but I would appreciate any hints or suggestions as to what I'm missing. Here's my sketch. (Ignore the keyboard.writes for SHIFT, etc. I just stuck those in there to test if the keys were working).
// 1200xl to USB
// Hardware Connections to Pro Micro:
const int KR1=3; // 1200xl connector pin 3
const int KR2=2; // 1200xl connector pin 1
const int resetKey=15; //1200xl connector pin 10
const int startKey=14; // " pin 11
const int selectKey=16; // " pin 12
const int optionKey=10; // " pin 13
int resetKeyState;
int startKeyState;
int selectKeyState;
int optionKeyState;
int count = 0; // binary count to 4051 pins
int keyList[]= { // no modifiers yet
97,49,113,61,62,122,88,42,88,54, // i= 0-9 ascii: a,1,q,=,>,z,INV,not used,6
121,117,55,216,110,218,103,53,116,105, // 10-19 ascii: y,u,7,F3,n,F1,g,5,t,i
56,98,109,107,104,88,88,88,88,88, // 20-29 ascii: 8,b,m,k,h,25-28 not used, HELP
32,106,115,50,119,45,60,120,47,43, //30-39 ascii: 30 not used,j,s,2,w,-,<,x,/,+
100,51,101,112,48,99,46,59,193,177, //40-49 ascii: d,3,e,p,0,c, . , ; ,CAPS,ESC, (ascii lists 27 for ESC, but actually 177 per arduino reference)
9,10,8,215,88,217,102,52,114,111, //50-59 ascii: TAB,RETURN,BACKSPACE,F4, 54 not used, F2,f,4,r (ascii lists show 13 for carriage return/enter, but it's actually 10)
57,118,44,108}; //60-63 ascii: 9,v, , ,l
int KR1State = HIGH; //default high= nothing pressed
int KR2State = HIGH; // same for the modifier line
int modKey= 0; // which modifier key
int keyCode = 0; // variable for the physical key, not character -- only included for debugging
char keyChar; // variable for actual character to send
const char ctrlKey = KEY_LEFT_SHIFT;
const char shiftKey = KEY_LEFT_SHIFT;
const char brkKey = KEY_END;
// variables for debounce
unsigned long timeRead = 0;
unsigned long debounceTime = 106; // best rate without hardware debouncing
//____________________________________________________SETUP___________________________________________
void setup()
{
pinMode(4,OUTPUT); // Rows (U2)
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT); // Columns (U1)
pinMode(8,OUTPUT);
pinMode(9,OUTPUT);
pinMode(KR1,INPUT_PULLUP); // KR1 line (connector 3-- goes low when keypress grounds any 4051 line)
pinMode(KR2,INPUT_PULLUP); // separate column for SHIFT, CONTROL and BREAK
pinMode(resetKey,INPUT_PULLUP); //our four GTIA keys
pinMode(startKey,INPUT_PULLUP);
pinMode(selectKey,INPUT_PULLUP);
pinMode(optionKey,INPUT_PULLUP);
//Serial.begin(9600); // use serial port for testing
Keyboard.begin(); // don't use this until everything WORKS!
}
// _____________________________________ VOID LOOP___________________________________________________
void loop()
{
// Keyboard scan
for(count=0;count<64;count++) // count to 64
{
int a=count%2; // and convert each count to a 6-bit binary
int b=count/2%2;
int c=count/4%2;
int d=count/8%2;
int e=count/16%2;
int f=count/32%2;
digitalWrite(9,a); // c.;usend the high bits to A,B,C on U1
digitalWrite(8,b);
digitalWrite(7,c);
digitalWrite(6,d); // .;n7send the low bits to A,B,C on U2
digitalWrite(5,e);
digitalWrite(4,f);
keyCode=count; // each count identifies a key, e.g., 0="A", 32="S", etc.
keyPress(); // has a key been pressed?
modKeys(); // what modifier, if any, to apply?
if (KR1State==LOW) { //seems redundant with this in the function but needs to be here anyway
keyChar = (char) keyList[count]; // convert the Keycode into the corresponding ascii from the array
keySend(); // key has been debounced so go ahead and send it to USB
Keyboard.releaseAll();
}
GTIAkeys(); // check and send RESET,START,SELECT,OPTION
} // for-loop close
} // void loop close
// ____________________________________DEBOUNCE FUNCTION_____________________________________________
void debounceWait()
{
do { // nothing until debounceTime is reached
}
while (millis() - timeRead < debounceTime); //
}
// ______________________________________KEPRESS FUNCTION ___________________________________________
boolean keyPress()
{
KR1State = digitalRead(KR1); // check for keypress
if (KR1State == LOW){ // i.e., if a key is pressed
timeRead = millis(); // start time for the debounce function
debounceWait();
}
return(KR1State);
}
//_____________________________________MODIFIER KEYS ________________________________
char modKeys()
{
KR2State=digitalRead(KR2);
if (KR2State==LOW){
if(keyCode==13){ //SHIFT
modKey=shiftKey;
Keyboard.print("SHIFT");
}
else
if (keyCode==47) { //CONTROL
modKey=ctrlKey;
Keyboard.print("CONTROL");
}
else
if (keyCode==60) { //BREAK
modKey==brkKey;
Keyboard.print("BREAK");
}
}
return(modKey);
}
// _______________________________________KEYSEND FUNCTION___________________________________________
void keySend()
{
//Serial.print(keyChar); // change to keyboard after everything debugged
Keyboard.press(modKey); //apply modifier
Keyboard.write(keyChar);
}
//________________________________________GTIA KEYS__________________________________________________
void GTIAkeys()
{
//these four keys are not part of the matrix and are debounced in hardware
resetKeyState=digitalRead(resetKey);
startKeyState=digitalRead(startKey);
selectKeyState=digitalRead(selectKey);
optionKeyState=digitalRead(optionKey);
if (resetKeyState==LOW) {
resetSend();
}
if (startKeyState==LOW){
startSend();
}
if (selectKeyState==LOW) {
selectSend();
}
if (optionKeyState==LOW) {
optionSend();
}
}
//____________________________________RESET SEND___________________________________
void resetSend()
{
Keyboard.print("A");//---just send some letters for testing
}
//____________________________________SELECT SEND__________________________________
void startSend()
{
Keyboard.print("B");
}
//_____________________________________SELECT SEND_________________________________
void selectSend()
{
Keyboard.print("C");
}
//_____________________________________OPTION SEND__________________________________
void optionSend()
{
Keyboard.print("D");
}