Offline
Newbie
Karma: 0
Posts: 17
|
 |
« on: January 10, 2012, 04:05:34 pm » |
Hi all. I'm working on a project that includes wiring an old Apple IIc keyboard to a teensy board to act as a USB keyboard. Simplifying the multiplexing of keys, i've been using the keypad library from the playground ( http://arduino.cc/playground/Code/Keypad). After some fiddling with the keyboard itself and working around some dead pins, I have it working, mostly. It's a big matrix - 14 columns by 10 rows, which uses up almost all of the inputs on the teensy. My sketch works in detecting one key at a time, so I can type with it, but it's not very useful without modifier keys. I'm not sure if I'm running into a limitation of the keypad library (detecting multiple keys at a time isn't necessarily required on a 3x4 keypad) or if my implementation is lacking. So... is it possible to detect multiple, simultaneous keypresses in the keypad library? If so, can someone point me to an example sketch I can look at for guidance? If not, is there a better way to attempt what i'm doing - a matrix keyboard library I haven't found?
|
|
|
|
|
Logged
|
|
|
|
|
Phillipsburg, NJ
Offline
Full Member
Karma: 6
Posts: 124
Author: Matrix Keypad Library
|
 |
« Reply #1 on: January 10, 2012, 05:55:57 pm » |
My sketch works in detecting one key at a time, so I can type with it, but it's not very useful without modifier keys. I'm not sure if I'm running into a limitation of the keypad library or if my implementation is lacking. I can tell you with certainty that it's definitely the library. I was one of the people who wrote it.  In fact I made absolutely sure that it would only return one key press at a time. Give me a little time (no later than this weekend) to think about it and I'll see what I can do with the library. Can you tell me what kind of modifiers you'd like to have/use?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #2 on: January 10, 2012, 09:44:55 pm » |
modifiers? the usual - shift, control, apple key...
this is an old-school apple II keyboard i'm working on. it still has the apples on it - not the command squiggly. and no alt/option, though that would probably be necessary with a more modern counterpart. the apple keys should map to MODIFIER_GUI, right?
my thought while driving home tonight was that i could do it with two keypad objects, the second one only managing the pins for the modifier keys. luckily, they're separated from the alpha/num keys on the keyboard itself.
any thoughts?
|
|
|
|
|
Logged
|
|
|
|
|
Phillipsburg, NJ
Offline
Full Member
Karma: 6
Posts: 124
Author: Matrix Keypad Library
|
 |
« Reply #3 on: January 10, 2012, 11:03:41 pm » |
[thought] i could do it with two keypad objects, the second one only managing the pins for the modifier keys. luckily, they're separated from the alpha/num keys on the keyboard itself. I was thinking the same thing but I haven't been able to test it. I'm not sure just how well a micro can support separate C++ objects in memory. Even if it works there would still be the problem that you could only use one modifier at a time. Control+Shift+<Key> wouldn't be available. Still it would be interesting to see what happens. Are you willing to try?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #4 on: January 10, 2012, 11:32:18 pm » |
i'll give it a shot. i'm more interested in being able to type in mixed case and use symbols than anything else - this is a hack, not going to be my daily driver 
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #5 on: January 11, 2012, 11:01:39 am » |
using the second keypad object doesn't seem to work. i'm not sure what's happening, though, since even when i explicitly set a modifier key, it has no effect. here's my complete sketch (you can see the IIc matrix map commented at the top: #include <Keypad.h>
/*
31 24 22 8 14 10 6 1 4 2 26 16 34 28
12 ESC 1 2 3 4 5 6 7 8 9
3 \ = 0 -
33 TAB Q W E R T Y U I O
5 ` P [ ]
18 A D S H F J G K ; L
20 Z X C V B M N , . /
23 CMD CMD
21 CTL SHFT CAPS
9 DEL DN LA RA
7 RTN UP SPC '
14 columns 10 rows
24 input pins
*/
const byte ROWS = 8; // rows const byte COLS = 10; // columns char keys[ROWS][COLS] = {
{ KEY_ESC, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9} ,
{ 0, 0, 0, 0, 0, KEY_BACKSLASH, 0, KEY_EQUAL, KEY_0, KEY_MINUS} ,
{ KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O},
{ 0, 0, 0, 0, 0, KEY_TILDE, 0, KEY_P, KEY_LEFT_BRACE, KEY_RIGHT_BRACE},
{ KEY_A, KEY_D, KEY_S, KEY_H, KEY_F, KEY_J, KEY_G, KEY_K, KEY_SEMICOLON, KEY_L},
{ KEY_Z ,KEY_X, KEY_C, KEY_V ,KEY_B, KEY_M, KEY_N, KEY_COMMA, KEY_PERIOD, KEY_SLASH},
{ 0 , 0 ,0 ,0, 0, KEY_BACKSPACE, 0 ,KEY_DOWN, KEY_LEFT, KEY_RIGHT},
{ 0, 0, 0, 0, 0 ,KEY_ENTER, 0 ,KEY_UP, KEY_SPACE ,KEY_QUOTE}
};
byte rowPins[ROWS] = { 0 ,1,2,3,4,5,6,9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = { 10,11,12,13,14,15,16,17,18,19}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
const byte ROWS2 = 2; // rows const byte COLS2 = 4; // columns char keys2[ROWS2][COLS2] = { { 0 , 0 ,MODIFIERKEY_SHIFT ,KEY_CAPS_LOCK }, {MODIFIERKEY_GUI, MODIFIERKEY_GUI, 0 ,0 } }; byte rowPins2[ROWS2] = { 7,8}; //connect to the row pinouts of the keypad
byte colPins2[COLS2] = { 20,21,22,23}; //connect to the column pinouts of the keypad
Keypad keypad2 = Keypad( makeKeymap(keys2), rowPins2, colPins2, ROWS2, COLS2 );
void setup(){ }
void loop(){ char key = keypad.getKey(); char key2 = keypad2.getKey();
if (key){ Keyboard.set_key1(key); } else { Keyboard.set_key1(0); }
if (key2){ Keyboard.set_key2(key2); } else { Keyboard.set_key2(0); }
// Keyboard.set_key3(MODIFIERKEY_SHIFT);
Keyboard.send_now();
}
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #6 on: January 11, 2012, 11:09:56 am » |
i should probably mention that i'm using the Teensy with Teensyduino and sending the keys via the keyboard library - see here: http://www.pjrc.com/teensy/td_keyboard.html
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #7 on: January 11, 2012, 12:06:29 pm » |
oops... forgot the syntax for adding a modifier key. my loop is now thus: void loop(){ char key = keypad.getKey(); char key2 = keypad2.getKey();
if (key2){ Keyboard.set_modifier(key2); }
if (key){ Keyboard.set_key1(key); }
Keyboard.send_now(); Keyboard.set_modifier(0); Keyboard.set_key1(0); }
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #8 on: January 11, 2012, 12:20:57 pm » |
okay. i think i have an idea of what's going on.
initially, i thought the modifier keypad (keypad2) wasn't working, but it turns out that it was, only very intermittently.
so i swapped my order of the getKey() lines - now keypad2 is getting updated first. suddenly, my modifiers are working!
but the other keys are all only working intermittently... so i think it's a speed problem. the teensy's not able to update both matrices in one pass of the loop. maybe a delay?
|
|
|
|
|
Logged
|
|
|
|
|
Phillipsburg, NJ
Offline
Full Member
Karma: 6
Posts: 124
Author: Matrix Keypad Library
|
 |
« Reply #9 on: January 11, 2012, 12:25:22 pm » |
using the second keypad object doesn't seem to work. i'm not sure what's happening, though, since even when i explicitly set a modifier key, it has no effect. Thanks for the link to the teensy keyboard code. It was a big help and I can tell you that you are not using the functions to correctly send modifier keys. (Sorry if I sound a bit blunt but I'm racing to post this from work.) I can go into it more when I get home tonight but just a quick example: I see that you commented it out but you used Keyboard.set_key3(MODIFIERKEY_SHIFT); to send a modifier key when you should have used Keyboard.set_modifier(MODIFIERKEY_SHIFT); From the teensy link you also need to do: Keyboard.send_now() After you have set the normal and modifier keys, use Keyboard.send_now() to communicate that combination to the PC or Mac.
|
|
|
|
|
Logged
|
|
|
|
|
Phillipsburg, NJ
Offline
Full Member
Karma: 6
Posts: 124
Author: Matrix Keypad Library
|
 |
« Reply #10 on: January 11, 2012, 12:28:30 pm » |
so i swapped my order of the getKey() lines - now keypad2 is getting updated first. suddenly, my modifiers are working!
but the other keys are all only working intermittently... so i think it's a speed problem. the teensy's not able to update both matrices in one pass of the loop. maybe a delay? No, the keypad was built to work better without any delay()s in your code. I think there might be some interference between the keypad objects keypad and keypad2. I'll take a look and see if I can identify what it might be.
|
|
|
|
|
Logged
|
|
|
|
|
Central MN, USA
Offline
Faraday Member
Karma: 35
Posts: 5941
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
|
 |
« Reply #11 on: January 11, 2012, 12:31:28 pm » |
What is the keyboard object? Browsed through your code and didn't find a definition. Is it in keypad.h? Just trying to understand your code to see if I can offer any help.
BTW, do you know if the debounce time in the keypad library is static variable or not?
|
|
|
|
|
Logged
|
|
|
|
|
Phillipsburg, NJ
Offline
Full Member
Karma: 6
Posts: 124
Author: Matrix Keypad Library
|
 |
« Reply #12 on: January 11, 2012, 12:40:48 pm » |
What is the keyboard object? Browsed through your code and didn't find a definition. Is it in keypad.h? Just trying to understand your code to see if I can offer any help. Edit: I should have paid closer attention to your question. Sorry about the mis-answer. Yeah, sorry about that, I was using C++ jargon to describe when the 'object' was created in the users code. For example the keypad2 object is created when he called: Keypad keypad2 = Keypad( makeKeymap(keys2), rowPins2, colPins2, ROWS2, COLS2 ); BTW, do you know if the debounce time in the keypad library is static variable or not? Debounce time is variable and can be set by the user, for example: void setup() { Serial.begin(9600); keypad.addEventListener(keypadEvent); keypad.setDebounceTime(500); }
Although, I doubt you'll ever need a debounce time as high as 500 milliseconds. 
|
|
|
|
« Last Edit: January 11, 2012, 12:44:29 pm by mstanley »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #13 on: January 11, 2012, 12:42:29 pm » |
What is the keyboard object? Browsed through your code and didn't find a definition. Is it in keypad.h? Just trying to understand your code to see if I can offer any help.
the keyboard object comes from the teensyduino libraries. sorry, i didn't make that clear in the OP. see: http://www.pjrc.com/teensy/td_keyboard.html
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #14 on: January 11, 2012, 12:55:58 pm » |
my current and semi-working sketch: const byte ROWS = 8; // rows const byte COLS = 10; // columns char keys[ROWS][COLS] = {
{ KEY_ESC, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9} ,
{ 0, 0, 0, 0, 0, KEY_BACKSLASH, 0, KEY_EQUAL, KEY_0, KEY_MINUS} ,
{ KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O},
{ 0, 0, 0, 0, 0, KEY_TILDE, 0, KEY_P, KEY_LEFT_BRACE, KEY_RIGHT_BRACE},
{ KEY_A, KEY_D, KEY_S, KEY_H, KEY_F, KEY_J, KEY_G, KEY_K, KEY_SEMICOLON, KEY_L},
{ KEY_Z ,KEY_X, KEY_C, KEY_V ,KEY_B, KEY_M, KEY_N, KEY_COMMA, KEY_PERIOD, KEY_SLASH},
{ 0 , 0 ,0 ,0, 0, KEY_BACKSPACE, 0 ,KEY_DOWN, KEY_LEFT, KEY_RIGHT},
{ 0, 0, 0, 0, 0 ,KEY_ENTER, 0 ,KEY_UP, KEY_SPACE ,KEY_QUOTE}
};
byte rowPins[ROWS] = { 0 ,1,2,3,4,5,8,9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = { 10,11,12,13,14,15,16,17,18,19}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
const byte ROWS2 = 1; // rows const byte COLS2 = 4; // columns char keys2[ROWS2][COLS2] = { {MODIFIERKEY_SHIFT, MODIFIERKEY_SHIFT, 0 ,0 } //{ 0 , 0 ,MODIFIERKEY_SHIFT, MODIFIERKEY_SHIFT } }; byte rowPins2[ROWS2] = { 6}; //connect to the row pinouts of the keypad
byte colPins2[COLS2] = { 20,21,22,23}; //connect to the column pinouts of the keypad
Keypad keypad2 = Keypad( makeKeymap(keys2), rowPins2, colPins2, ROWS2, COLS2 );
void setup(){
}
void loop(){ char key = keypad.getKey(); char key2 = keypad2.getKey();
KeyState modifier = keypad2.getState();
if (key2){ Keyboard.set_modifier(key2); }
KeyState alpha = keypad.getState(); if (key){ Keyboard.set_key1(key); }
Keyboard.send_now(); if(modifier == RELEASED) { Keyboard.set_modifier(0); } if(alpha == RELEASED) { Keyboard.set_key1(0); }
} notice two getKey() lines. the first "alpha" keypad is responsive, and the second "modifier" works only occasionally. if i swap those lines, the opposite is true, which leads me to think that i'm asking too much of the teensy in each pass of the matrix scan. would it be more likely to work if i used waitForKey() instead, and only read the modifier keypad if there's an alpha key pressed to modify?
|
|
|
|
|
Logged
|
|
|
|
|
|