Add files via upload
This commit is contained in:
parent
8aad4880df
commit
9bc72a5bb1
18 changed files with 2159 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Example_Keyboards/How to modify the Teensyduino 3p2 code.pdf
Normal file
BIN
Example_Keyboards/How to modify the Teensyduino 3p2 code.pdf
Normal file
Binary file not shown.
BIN
Example_Keyboards/How to modify the Teensyduino LC code.pdf
Normal file
BIN
Example_Keyboards/How to modify the Teensyduino LC code.pdf
Normal file
Binary file not shown.
Binary file not shown.
1019
Example_Keyboards/Lenovo_ThinkPad_T61/Lenovo_Scanner.brd
Normal file
1019
Example_Keyboards/Lenovo_ThinkPad_T61/Lenovo_Scanner.brd
Normal file
File diff suppressed because it is too large
Load diff
719
Example_Keyboards/Lenovo_ThinkPad_T61/Lenovo_T61_KBandTP.ino
Normal file
719
Example_Keyboards/Lenovo_ThinkPad_T61/Lenovo_T61_KBandTP.ino
Normal file
|
@ -0,0 +1,719 @@
|
||||||
|
// This software is in the public domain
|
||||||
|
// It controls a Lenovo ThinkPad T61 Laptop Keyboard and PS/2 Trackpoint using a Teensy 3.2 on
|
||||||
|
// a daughterboard with a 44 pin FPC connector. The keyboard part number is 42T3177.
|
||||||
|
// This routine uses the Teensyduino "Micro-Manager Method" to send Normal and Modifier
|
||||||
|
// keys over USB. Only the volume control multi-media keys are supported by this routine.
|
||||||
|
// Description of Teensyduino keyboard functions is at www.pjrc.com/teensy/td_keyboard.html
|
||||||
|
// The PS/2 code for the Trackpoint was originally from https://playground.arduino.cc/uploads/ComponentLib/mouse.txt
|
||||||
|
// but the interface to the host was changed from RS232 serial to USB using the PJRC Mouse functions.
|
||||||
|
// A watchdog timer was also added to the "while loops" so the code can't hang if a clock edge is missed.
|
||||||
|
//
|
||||||
|
// Revision History
|
||||||
|
// Initial Release Oct 27, 2018
|
||||||
|
//
|
||||||
|
// Trackpoint signals
|
||||||
|
#define MDATA 18 // ps/2 data to trackpoint
|
||||||
|
#define MCLK 19 // ps/2 clock to trackpoint
|
||||||
|
#define MRESET 0 // active high trackpoint reset at power up
|
||||||
|
// Keyboard LEDs
|
||||||
|
#define CAPS_LED 28 // Wire these 3 I/O's to the anode side of LED's
|
||||||
|
#define NUM_LED 29 // Wire the cathode side thru a dropping resistor
|
||||||
|
#define SCRL_LED 30 // to ground.
|
||||||
|
#define BLINK_LED 13 // The LED on the Teensy is programmed to blink
|
||||||
|
// Keyboard Fn key (aka HOTKEY)
|
||||||
|
#define HOTKEY 14 // Fn key plus side
|
||||||
|
#define HOTKEY_RTN 23 // Fn key minus side (always driven low in this routine)
|
||||||
|
// sync signal for measuring scan frequency
|
||||||
|
#define SYNC 27
|
||||||
|
// Set the keyboard row & column size
|
||||||
|
const byte rows_max = 16; // sets the number of rows in the matrix
|
||||||
|
const byte cols_max = 8; // sets the number of columns in the matrix
|
||||||
|
//
|
||||||
|
// Load the normal key matrix with the Teensyduino key names described at www.pjrc.com/teensy/td_keyboard.html
|
||||||
|
// A zero indicates no normal key at that location.
|
||||||
|
//
|
||||||
|
int normal[rows_max][cols_max] = {
|
||||||
|
{KEY_TILDE,KEY_1,KEY_Q,KEY_TAB,KEY_A,KEY_ESC,KEY_Z,0},
|
||||||
|
{KEY_F1,KEY_2,KEY_W,KEY_CAPS_LOCK,KEY_S,0,KEY_X,0},
|
||||||
|
{KEY_F2,KEY_3,KEY_E,KEY_F3,KEY_D,KEY_F4,KEY_C,0},
|
||||||
|
{KEY_5,KEY_4,KEY_R,KEY_T,KEY_F,KEY_G,KEY_V,KEY_B},
|
||||||
|
{KEY_6,KEY_7,KEY_U,KEY_Y,KEY_J,KEY_H,KEY_M,KEY_N},
|
||||||
|
{KEY_EQUAL,KEY_8,KEY_I,KEY_RIGHT_BRACE,KEY_K,KEY_F6,KEY_COMMA,0},
|
||||||
|
{KEY_F8,KEY_9,KEY_O,KEY_F7,KEY_L,0,KEY_PERIOD,0},
|
||||||
|
{KEY_MINUS,KEY_0,KEY_P,KEY_LEFT_BRACE,KEY_SEMICOLON,KEY_QUOTE,0,KEY_SLASH},
|
||||||
|
{KEY_F9,KEY_F10,0,KEY_BACKSPACE,KEY_BACKSLASH,KEY_F5,KEY_ENTER,KEY_SPACE},
|
||||||
|
{KEY_INSERT,KEY_F12,0,0,0,0,0,KEY_RIGHT},
|
||||||
|
{KEY_DELETE,KEY_F11,0,0,0,0,0,KEY_DOWN},
|
||||||
|
{KEY_PAGE_UP,KEY_PAGE_DOWN,0,0,KEY_MENU,0,0,0},
|
||||||
|
{KEY_HOME,KEY_END,0,0,0,KEY_UP,KEY_PAUSE,KEY_LEFT},
|
||||||
|
{0,KEY_PRINTSCREEN,KEY_SCROLL_LOCK,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0}
|
||||||
|
};
|
||||||
|
// Load the modifier key matrix with key names at the correct row-column location.
|
||||||
|
// A zero indicates no modifier key at that location.
|
||||||
|
int modifier[rows_max][cols_max] = {
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,MODIFIERKEY_GUI,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,MODIFIERKEY_LEFT_ALT,0,MODIFIERKEY_RIGHT_ALT},
|
||||||
|
{0,0,0,MODIFIERKEY_LEFT_SHIFT,0,0,MODIFIERKEY_RIGHT_SHIFT,0},
|
||||||
|
{MODIFIERKEY_LEFT_CTRL,0,0,0,0,0,MODIFIERKEY_RIGHT_CTRL,0}
|
||||||
|
};
|
||||||
|
// Load the media key matrix with key names at the correct row-column location.
|
||||||
|
// A zero indicates no media key at that location.
|
||||||
|
int media[rows_max][cols_max] = {
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,KEY_MEDIA_VOLUME_INC,KEY_MEDIA_VOLUME_DEC,KEY_MEDIA_MUTE,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0}
|
||||||
|
};
|
||||||
|
// Initialize the old_key matrix with one's.
|
||||||
|
// 1 = key not pressed, 0 = key is pressed
|
||||||
|
boolean old_key[rows_max][cols_max] = {
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1},
|
||||||
|
{1,1,1,1,1,1,1,1}
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// Define the Teensy 3.2 I/O numbers
|
||||||
|
//
|
||||||
|
// Row FPC pin # 22,18,14,10,02,04,08,12,06,20,16,24,28,32,26,30
|
||||||
|
// Teensy I/O # 20,33,24,25,31,32,07,06,26,04,05,03,02,01,21,22
|
||||||
|
int Row_IO[rows_max] = {20,33,24,25,31,32,7,6,26,4,5,3,2,1,21,22}; // Teensy 3.2 I/O numbers for rows
|
||||||
|
//
|
||||||
|
// Column FPC pin # 05,13,09,07,11,03,15,17
|
||||||
|
// Teensy I/O # 16,10,12,17,11,15,09,08
|
||||||
|
int Col_IO[cols_max] = {16,10,12,17,11,15,9,8}; // Teensy 3.2 I/O numbers for columns
|
||||||
|
//
|
||||||
|
// Declare variables that will be used by functions
|
||||||
|
boolean trackpoint_error = LOW; // sent high when touch pad routine times out
|
||||||
|
boolean slots_full = LOW; // Goes high when slots 1 thru 6 contain normal keys
|
||||||
|
// slot 1 thru slot 6 hold the normal key values to be sent over USB.
|
||||||
|
int slot1 = 0; //value of 0 means the slot is empty and can be used.
|
||||||
|
int slot2 = 0;
|
||||||
|
int slot3 = 0;
|
||||||
|
int slot4 = 0;
|
||||||
|
int slot5 = 0;
|
||||||
|
int slot6 = 0;
|
||||||
|
//
|
||||||
|
int mod_shift_l = 0; // These variables are sent over USB as modifier keys.
|
||||||
|
int mod_shift_r = 0; // Each is either set to 0 or MODIFIER_ ...
|
||||||
|
int mod_ctrl_l = 0;
|
||||||
|
int mod_ctrl_r = 0;
|
||||||
|
int mod_alt_l = 0;
|
||||||
|
int mod_alt_r = 0;
|
||||||
|
int mod_gui = 0;
|
||||||
|
//
|
||||||
|
// *****************Functions for Trackpoint***************************
|
||||||
|
// Function to send the trackpoint a command
|
||||||
|
void trackpoint_write(char data)
|
||||||
|
{
|
||||||
|
char i;
|
||||||
|
char parity = 1;
|
||||||
|
// put pins in output mode
|
||||||
|
go_z(MDATA);
|
||||||
|
go_z(MCLK);
|
||||||
|
elapsedMillis watchdog; // set watchdog to zero
|
||||||
|
delayMicroseconds(300);
|
||||||
|
go_0(MCLK);
|
||||||
|
delayMicroseconds(300);
|
||||||
|
go_0(MDATA);
|
||||||
|
delayMicroseconds(10);
|
||||||
|
// start bit
|
||||||
|
go_z(MCLK);
|
||||||
|
// wait for trackpoint to take control of clock)
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clock is low, and we are clear to send data
|
||||||
|
for (i=0; i < 8; i++) {
|
||||||
|
if (data & 0x01) {
|
||||||
|
go_z(MDATA);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
go_0(MDATA);
|
||||||
|
}
|
||||||
|
// wait for clock cycle
|
||||||
|
while (digitalRead(MCLK) == LOW) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parity = parity ^ (data & 0x01);
|
||||||
|
data = data >> 1;
|
||||||
|
}
|
||||||
|
// parity
|
||||||
|
if (parity) {
|
||||||
|
go_z(MDATA);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
go_0(MDATA);
|
||||||
|
}
|
||||||
|
// wait for clock cycle
|
||||||
|
while (digitalRead(MCLK) == LOW) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// stop bit
|
||||||
|
go_z(MDATA);
|
||||||
|
delayMicroseconds(50);
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// wait for trackpoint to switch modes
|
||||||
|
while ((digitalRead(MCLK) == LOW) || (digitalRead(MDATA) == LOW)) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// put a hold on the incoming data.
|
||||||
|
go_0(MCLK);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Function to get a byte of data from the trackpoint
|
||||||
|
//
|
||||||
|
char trackpoint_read(void)
|
||||||
|
{
|
||||||
|
char data = 0x00;
|
||||||
|
int i;
|
||||||
|
char bity = 0x01;
|
||||||
|
// start the clock
|
||||||
|
elapsedMillis watchdog; // set watchdog to zero
|
||||||
|
go_z(MCLK);
|
||||||
|
go_z(MDATA);
|
||||||
|
delayMicroseconds(50);
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delayMicroseconds(5); // wait for clock ring to settle
|
||||||
|
while (digitalRead(MCLK) == LOW) { // eat start bit
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=0; i < 8; i++) {
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (digitalRead(MDATA) == HIGH) {
|
||||||
|
data = data | bity;
|
||||||
|
}
|
||||||
|
while (digitalRead(MCLK) == LOW) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bity = bity << 1;
|
||||||
|
}
|
||||||
|
// ignore parity bit
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (digitalRead(MCLK) == LOW) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eat stop bit
|
||||||
|
while (digitalRead(MCLK) == HIGH) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (digitalRead(MCLK) == LOW) {
|
||||||
|
if (watchdog >= 200) { //check for infinite loop
|
||||||
|
trackpoint_error = HIGH; // set error flag
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// put a hold on the incoming data.
|
||||||
|
go_0(MCLK);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void trackpoint_init()
|
||||||
|
{
|
||||||
|
trackpoint_error = LOW; // start with no error
|
||||||
|
go_z(MCLK); // float the clock and data to trackpoint
|
||||||
|
go_z(MDATA);
|
||||||
|
// Trackpoint Reset signal is active high. Start it off low to let power stabilize
|
||||||
|
go_0(MRESET); // drive low
|
||||||
|
delay(1000); // wait 1 second
|
||||||
|
go_1(MRESET); // drive High to activate Reset signal to trackpoint
|
||||||
|
delay(1000); // wait 1 second to give it a good long reset
|
||||||
|
go_0(MRESET); // drive Reset back to the inactive (low) state
|
||||||
|
delay(1000); // wait 1 second before proceeding so trackpoint is ready
|
||||||
|
// Sending reset command to trackpoint
|
||||||
|
trackpoint_write(0xff);
|
||||||
|
trackpoint_read(); // ack byte
|
||||||
|
// Read ack byte
|
||||||
|
trackpoint_read(); // blank
|
||||||
|
trackpoint_read(); // blank
|
||||||
|
// Sending remote mode code so the trackpoint will send data only when polled
|
||||||
|
trackpoint_write(0xf0); // remote mode
|
||||||
|
trackpoint_read(); // Read ack byte
|
||||||
|
delayMicroseconds(100);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// *****************Functions for Keyboard*****************************
|
||||||
|
// Function to load the key name into the first available slot
|
||||||
|
void load_slot(int key) {
|
||||||
|
if (!slot1) {
|
||||||
|
slot1 = key;
|
||||||
|
}
|
||||||
|
else if (!slot2) {
|
||||||
|
slot2 = key;
|
||||||
|
}
|
||||||
|
else if (!slot3) {
|
||||||
|
slot3 = key;
|
||||||
|
}
|
||||||
|
else if (!slot4) {
|
||||||
|
slot4 = key;
|
||||||
|
}
|
||||||
|
else if (!slot5) {
|
||||||
|
slot5 = key;
|
||||||
|
}
|
||||||
|
else if (!slot6) {
|
||||||
|
slot6 = key;
|
||||||
|
}
|
||||||
|
if (!slot1 || !slot2 || !slot3 || !slot4 || !slot5 || !slot6) {
|
||||||
|
slots_full = LOW; // slots are not full
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
slots_full = HIGH; // slots are full
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to clear the slot that contains the key name
|
||||||
|
void clear_slot(int key) {
|
||||||
|
if (slot1 == key) {
|
||||||
|
slot1 = 0;
|
||||||
|
}
|
||||||
|
else if (slot2 == key) {
|
||||||
|
slot2 = 0;
|
||||||
|
}
|
||||||
|
else if (slot3 == key) {
|
||||||
|
slot3 = 0;
|
||||||
|
}
|
||||||
|
else if (slot4 == key) {
|
||||||
|
slot4 = 0;
|
||||||
|
}
|
||||||
|
else if (slot5 == key) {
|
||||||
|
slot5 = 0;
|
||||||
|
}
|
||||||
|
else if (slot6 == key) {
|
||||||
|
slot6 = 0;
|
||||||
|
}
|
||||||
|
slots_full = LOW;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to load the modifier key name into the appropriate mod variable
|
||||||
|
void load_mod(int m_key) {
|
||||||
|
if (m_key == MODIFIERKEY_LEFT_SHIFT) {
|
||||||
|
mod_shift_l = m_key;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_RIGHT_SHIFT) {
|
||||||
|
mod_shift_r = m_key;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_LEFT_CTRL) {
|
||||||
|
mod_ctrl_l = m_key;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_RIGHT_CTRL) {
|
||||||
|
mod_ctrl_r = m_key;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_LEFT_ALT) {
|
||||||
|
mod_alt_l = m_key;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_RIGHT_ALT) {
|
||||||
|
mod_alt_r = m_key;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_GUI) {
|
||||||
|
mod_gui = m_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to load 0 into the appropriate mod variable
|
||||||
|
void clear_mod(int m_key) {
|
||||||
|
if (m_key == MODIFIERKEY_LEFT_SHIFT) {
|
||||||
|
mod_shift_l = 0;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_RIGHT_SHIFT) {
|
||||||
|
mod_shift_r = 0;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_LEFT_CTRL) {
|
||||||
|
mod_ctrl_l = 0;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_RIGHT_CTRL) {
|
||||||
|
mod_ctrl_r = 0;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_LEFT_ALT) {
|
||||||
|
mod_alt_l = 0;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_RIGHT_ALT) {
|
||||||
|
mod_alt_r = 0;
|
||||||
|
}
|
||||||
|
else if (m_key == MODIFIERKEY_GUI) {
|
||||||
|
mod_gui = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to send the modifier keys over usb
|
||||||
|
void send_mod() {
|
||||||
|
Keyboard.set_modifier(mod_shift_l | mod_shift_r | mod_ctrl_l | mod_ctrl_r | mod_alt_l | mod_alt_r | mod_gui);
|
||||||
|
Keyboard.send_now();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to send the normal keys in the 6 slots over usb
|
||||||
|
void send_normals() {
|
||||||
|
Keyboard.set_key1(slot1);
|
||||||
|
Keyboard.set_key2(slot2);
|
||||||
|
Keyboard.set_key3(slot3);
|
||||||
|
Keyboard.set_key4(slot4);
|
||||||
|
Keyboard.set_key5(slot5);
|
||||||
|
Keyboard.set_key6(slot6);
|
||||||
|
Keyboard.send_now();
|
||||||
|
}
|
||||||
|
// **************Functions common to keyboard and trackpoint**************************
|
||||||
|
//
|
||||||
|
// Function to set a pin to high impedance (acts like open drain output)
|
||||||
|
void go_z(int pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, INPUT);
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to set a pin as an input with a pullup
|
||||||
|
void go_pu(int pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, INPUT_PULLUP);
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to send a pin to a logic low
|
||||||
|
void go_0(int pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Function to send a pin to a logic high
|
||||||
|
void go_1(int pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//************************************Setup*******************************************
|
||||||
|
void setup() {
|
||||||
|
// ************trackpoint setup
|
||||||
|
trackpoint_init(); // reset trackpoint, then set it's resolution and put it in remote mode
|
||||||
|
if (trackpoint_error) {
|
||||||
|
trackpoint_init(); // try one more time to initialize the trackpoint
|
||||||
|
}
|
||||||
|
// ************keyboard setup
|
||||||
|
for (int a = 0; a < cols_max; a++) { // loop thru all column pins
|
||||||
|
go_pu(Col_IO[a]); // set each column pin as an input with a pullup
|
||||||
|
}
|
||||||
|
//
|
||||||
|
for (int b = 0; b < rows_max; b++) { // loop thru all row pins
|
||||||
|
go_z(Row_IO[b]); // set each row pin as a floating output
|
||||||
|
}
|
||||||
|
//
|
||||||
|
go_0(HOTKEY_RTN); // Always drive the Hotkey return side low
|
||||||
|
go_pu(HOTKEY); // Pull up the Hotkey plus side for reading
|
||||||
|
//
|
||||||
|
pinMode(BLINK_LED, OUTPUT); // I/O 13 drives the LED on the Teensy
|
||||||
|
pinMode(SYNC, OUTPUT); // I/O 27 drives a scope for frequency measurement
|
||||||
|
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// *******declare and initialize trackpoint variables
|
||||||
|
char mstat; // trackpoint status reg = Y overflow, X overflow, Y sign bit, X sign bit, Always 1, Middle Btn, Right Btn, Left Btn
|
||||||
|
char mx; // trackpoint x movement = 8 data bits. The sign bit is in the status register to
|
||||||
|
// make a 9 bit 2's complement value. Left to right on the trackpoint gives a positive value.
|
||||||
|
char my; // trackpoint y movement also 8 bits plus sign. trackpoint movement away from the user gives a positive value.
|
||||||
|
boolean over_flow; // set if x or y movement values are bad due to overflow
|
||||||
|
boolean left_button = 0; // on/off variable for left button = bit 0 of mstat
|
||||||
|
boolean right_button = 0; // on/off variable for right button = bit 1 of mstat
|
||||||
|
boolean middle_button = 0; // on/off variable for middle button = bit 2 of mstat
|
||||||
|
boolean old_left_button = 0; // on/off variable for left button status the previous polling cycle
|
||||||
|
boolean old_right_button = 0; // on/off variable for right button status the previous polling cycle
|
||||||
|
boolean old_middle_button = 0; // on/off variable for middle button status the previous polling cycle
|
||||||
|
boolean button_change = 0; // Active high, shows when any trackpoint button has changed since last polling cycle
|
||||||
|
// **********declare and initialize keyboard variables
|
||||||
|
boolean Fn_pressed = HIGH; // Initialize Fn key to HIGH = "not pressed"
|
||||||
|
extern volatile uint8_t keyboard_leds; // 8 bits sent from Host to Teensy that give keyboard LED status.
|
||||||
|
char blink_count = 0; // Blink loop counter
|
||||||
|
boolean blinky = LOW; // Blink LED state
|
||||||
|
boolean sync_sig = LOW; // sync pulse to measure scan frequency
|
||||||
|
//
|
||||||
|
//*********************************Main Loop*******************************************
|
||||||
|
//
|
||||||
|
void loop() {
|
||||||
|
// *************Keyboard Main**************
|
||||||
|
// Read the Fn key (aka Hotkey) which is not part of the key matrix
|
||||||
|
if (!digitalRead(HOTKEY)) {
|
||||||
|
Fn_pressed = LOW; // Fn key is pressed (active low)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Fn_pressed = HIGH; // Fn key is not pressed
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Scan keyboard matrix with an outer loop that drives each row low and an inner loop that reads every column (with pull ups).
|
||||||
|
// The routine looks at each key's present state (by reading the column input pin) and also the previous state from the last scan
|
||||||
|
// that was 30msec ago. The status of a key that was just pressed or just released is sent over USB and the state is saved in the old_key matrix.
|
||||||
|
// The keyboard keys will read as logic low if they are pressed (negative logic).
|
||||||
|
// The old_key matrix also uses negative logic (low=pressed).
|
||||||
|
//
|
||||||
|
for (int x = 0; x < rows_max; x++) { // loop thru the rows
|
||||||
|
go_0(Row_IO[x]); // Activate Row (send it low)
|
||||||
|
delayMicroseconds(10); // give the row time to go low and settle out
|
||||||
|
for (int y = 0; y < cols_max; y++) { // loop thru the columns
|
||||||
|
// **********Modifier keys
|
||||||
|
if (modifier[x][y] != 0) { // check if modifier key exists at this location in the array (a non-zero value)
|
||||||
|
if (!digitalRead(Col_IO[y]) && (old_key[x][y])) { // Read column to see if key is low (pressed) and was previously not pressed
|
||||||
|
load_mod(modifier[x][y]); // function reads which modifier key is pressed and loads it into the appropriate mod_... variable
|
||||||
|
send_mod(); // function sends the state of all modifier keys over usb including the one that just got pressed
|
||||||
|
old_key[x][y] = LOW; // Save state of key as "pressed"
|
||||||
|
}
|
||||||
|
else if (digitalRead(Col_IO[y]) && (!old_key[x][y])) { //check if key is not pressed and was previously pressed
|
||||||
|
clear_mod(modifier[x][y]); // function reads which modifier key was released and loads 0 into the appropriate mod_... variable
|
||||||
|
send_mod(); // function sends all mod's over usb including the one that just released
|
||||||
|
old_key[x][y] = HIGH; // Save state of key as "not pressed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ***********end of modifier section
|
||||||
|
//
|
||||||
|
// ***********Normal keys section
|
||||||
|
else if (normal[x][y] != 0) { // check if normal key exists at this location in the array (a non-zero value)
|
||||||
|
if (!digitalRead(Col_IO[y]) && (old_key[x][y])) { // check if key is pressed and was not previously pressed
|
||||||
|
old_key[x][y] = LOW; // Save state of key as "pressed"
|
||||||
|
if ((normal[x][y] == KEY_SCROLL_LOCK) && (!Fn_pressed)) { // check for special case of Num Lock Key
|
||||||
|
load_slot(KEY_NUM_LOCK); // update first available slot with Num Lock instead of Scroll Lock
|
||||||
|
send_normals(); // send all slots over USB including the Num Lock Key that just got pressed
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
load_slot(normal[x][y]); //update first available slot with normal key name
|
||||||
|
send_normals(); // send all slots over USB including the key that just got pressed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (digitalRead(Col_IO[y]) && (!old_key[x][y])) { //check if key is not pressed, but was previously pressed
|
||||||
|
old_key[x][y] = HIGH; // Save state of key as "not pressed"
|
||||||
|
if ((normal[x][y] == KEY_SCROLL_LOCK) && (!Fn_pressed)) { // check for special case of Num Lock Key
|
||||||
|
clear_slot(KEY_NUM_LOCK); // clear the slot that contains Num Lock
|
||||||
|
send_normals(); // send all slots over USB including the Num Lock key
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clear_slot(normal[x][y]); //clear the slot that contains the normal key name
|
||||||
|
send_normals(); // send all slots over USB including the key that was just released
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// **************end of normal section
|
||||||
|
//
|
||||||
|
// *************Volume key section. Note PJRC states that volume up, down, & mute should be sent with Keyboard.press function.
|
||||||
|
else if (media[x][y] != 0) { // check if any volume control key exists at this location in the array (a non-zero value)
|
||||||
|
if (!digitalRead(Col_IO[y]) && (old_key[x][y])) { // check if key is pressed and was not previously pressed
|
||||||
|
old_key[x][y] = LOW; // Save state of key as "pressed"
|
||||||
|
Keyboard.press(media[x][y]); // send volume key press
|
||||||
|
}
|
||||||
|
else if (digitalRead(Col_IO[y]) && (!old_key[x][y])) { //check if key is not pressed, but was previously pressed
|
||||||
|
old_key[x][y] = HIGH; // Save state of key as "not pressed"
|
||||||
|
Keyboard.release(media[x][y]); // send volume key release
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ***************end of volume section
|
||||||
|
}
|
||||||
|
go_z(Row_IO[x]); // De-activate Row (send it to hi-z)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// **********keyboard scan complete
|
||||||
|
//
|
||||||
|
// ****************************Trackpoint Routine*********************************
|
||||||
|
//
|
||||||
|
// poll the trackpoint for new movement data
|
||||||
|
over_flow = 0; // assume no overflow until status is received
|
||||||
|
trackpoint_error = LOW; // start with no error
|
||||||
|
trackpoint_write(0xeb); // request data
|
||||||
|
trackpoint_read(); // ignore ack
|
||||||
|
mstat = trackpoint_read(); // save into status variable
|
||||||
|
mx = trackpoint_read(); // save into x variable
|
||||||
|
my = trackpoint_read(); // save into y variable
|
||||||
|
if (((0x80 & mstat) == 0x80) || ((0x40 & mstat) == 0x40)) { // x or y overflow bits set?
|
||||||
|
over_flow = 1; // set the overflow flag
|
||||||
|
}
|
||||||
|
// change the x data from 9 bit to 8 bit 2's complement
|
||||||
|
mx = mx >> 1; // convert to 7 bits of data by dividing by 2
|
||||||
|
mx = mx & 0x7f; // don't allow sign extension
|
||||||
|
if ((0x10 & mstat) == 0x10) { // move the sign into
|
||||||
|
mx = 0x80 | mx; // the 8th bit position
|
||||||
|
}
|
||||||
|
// change the y data from 9 bit to 8 bit 2's complement and then take the 2's complement
|
||||||
|
// because y movement on ps/2 format is opposite of touchpad.move function
|
||||||
|
my = my >> 1; // convert to 7 bits of data by dividing by 2
|
||||||
|
my = my & 0x7f; // don't allow sign extension
|
||||||
|
if ((0x20 & mstat) == 0x20) { // move the sign into
|
||||||
|
my = 0x80 | my; // the 8th bit position
|
||||||
|
}
|
||||||
|
my = (~my + 0x01); // change the sign of y data by taking the 2's complement (invert and add 1)
|
||||||
|
// zero out mx and my if over_flow or trackpoint_error is set
|
||||||
|
if ((over_flow) || (trackpoint_error)) {
|
||||||
|
mx = 0x00; // data is garbage so zero it out
|
||||||
|
my = 0x00;
|
||||||
|
}
|
||||||
|
// send the x and y data back via usb if either one is non-zero
|
||||||
|
if ((mx != 0x00) || (my != 0x00)) {
|
||||||
|
Mouse.move(mx,my);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// send the trackpoint left and right button status over usb if no error
|
||||||
|
if (!trackpoint_error) {
|
||||||
|
if ((0x01 & mstat) == 0x01) { // if left button set
|
||||||
|
left_button = 1;
|
||||||
|
}
|
||||||
|
else { // clear left button
|
||||||
|
left_button = 0;
|
||||||
|
}
|
||||||
|
if ((0x02 & mstat) == 0x02) { // if right button set
|
||||||
|
right_button = 1;
|
||||||
|
}
|
||||||
|
else { // clear right button
|
||||||
|
right_button = 0;
|
||||||
|
}
|
||||||
|
if ((0x04 & mstat) == 0x04) { // if middle button set
|
||||||
|
middle_button = 1;
|
||||||
|
}
|
||||||
|
else { // clear middle button
|
||||||
|
middle_button = 0;
|
||||||
|
}
|
||||||
|
// Determine if any buttons have changed since last polling cycle
|
||||||
|
button_change = ((left_button ^ old_left_button) | (right_button ^ old_right_button) | (middle_button ^ old_middle_button));
|
||||||
|
// Don't send button status if there's no change since last time.
|
||||||
|
if (button_change) {
|
||||||
|
Mouse.set_buttons(left_button, middle_button, right_button); // send button status
|
||||||
|
}
|
||||||
|
old_left_button = left_button; // remember new button status for next polling cycle
|
||||||
|
old_right_button = right_button;
|
||||||
|
old_middle_button = middle_button;
|
||||||
|
}
|
||||||
|
// **************************************End of trackpoint routine***********************************
|
||||||
|
//
|
||||||
|
// *******keyboard LEDs
|
||||||
|
// Turn on or off the LEDs for Num Lock, Caps Lock, and Scroll Lock based on bit 0, 1, and 2 from the keyboard_leds
|
||||||
|
// variable controlled by the USB host computer
|
||||||
|
//
|
||||||
|
if (keyboard_leds & 1) { // mask off all bits but D0 and test if set
|
||||||
|
go_1(NUM_LED); // turn on the Num Lock LED
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
go_0(NUM_LED); // turn off the Num Lock LED
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
if (keyboard_leds & 1<<1) { // mask off all bits but D1 and test if set
|
||||||
|
go_1(CAPS_LED); // turn on the Caps Lock LED
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
go_0(CAPS_LED); // turn off the Caps Lock LED
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
if (keyboard_leds & 1<<2) { // mask off all bits but D2 and test if set
|
||||||
|
go_1(SCRL_LED); // turn on the Scroll Lock LED
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
go_0(SCRL_LED); // turn off the Scroll Lock LED
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Blink LED on Teensy to show a heart beat
|
||||||
|
//
|
||||||
|
if (blink_count == 0x17) {
|
||||||
|
digitalWrite(BLINK_LED, blinky);
|
||||||
|
blinky = !blinky;
|
||||||
|
blink_count = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
blink_count = blink_count + 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Provide a sync pulse to measure the scan frequency
|
||||||
|
//
|
||||||
|
sync_sig = !sync_sig; // toggle the sync signal
|
||||||
|
digitalWrite(SYNC, sync_sig);
|
||||||
|
//
|
||||||
|
// ****************End of main loop
|
||||||
|
//
|
||||||
|
delay(24); // The overall keyboard/trackpoint scanning rate was measured at 30ms
|
||||||
|
}
|
92
Example_Keyboards/Lenovo_ThinkPad_T61/Lenovo_T61_io_list.txt
Normal file
92
Example_Keyboards/Lenovo_ThinkPad_T61/Lenovo_T61_io_list.txt
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
cntrl-l 16 22
|
||||||
|
cntrl-r 9 22
|
||||||
|
shift-l 17 21
|
||||||
|
shift-r 9 21
|
||||||
|
alt-l 15 1
|
||||||
|
alt-r 8 1
|
||||||
|
gui 12 3
|
||||||
|
a 11 20
|
||||||
|
b 25 8
|
||||||
|
c 24 9
|
||||||
|
d 11 24
|
||||||
|
e 12 24
|
||||||
|
f 25 11
|
||||||
|
g 15 25
|
||||||
|
h 31 15
|
||||||
|
i 32 12
|
||||||
|
j 31 11
|
||||||
|
k 32 11
|
||||||
|
l 7 11
|
||||||
|
m 31 9
|
||||||
|
n 31 8
|
||||||
|
o 7 12
|
||||||
|
p 12 6
|
||||||
|
q 12 20
|
||||||
|
r 12 25
|
||||||
|
s 11 33
|
||||||
|
t 17 25
|
||||||
|
u 31 12
|
||||||
|
v 25 9
|
||||||
|
w 12 33
|
||||||
|
x 9 33
|
||||||
|
y 31 17
|
||||||
|
z 9 20
|
||||||
|
` 16 20
|
||||||
|
1 10 20
|
||||||
|
2 10 33
|
||||||
|
3 10 24
|
||||||
|
4 25 10
|
||||||
|
5 16 25
|
||||||
|
6 31 16
|
||||||
|
7 31 10
|
||||||
|
8 32 10
|
||||||
|
9 7 10
|
||||||
|
0 6 10
|
||||||
|
- 16 6
|
||||||
|
= 32 16
|
||||||
|
bckspace 26 17
|
||||||
|
esc 15 20
|
||||||
|
f1 16 33
|
||||||
|
f2 16 24
|
||||||
|
f3 17 24
|
||||||
|
f4 15 24
|
||||||
|
f5 15 26
|
||||||
|
f6 15 32
|
||||||
|
f7 17 7
|
||||||
|
f8 16 7
|
||||||
|
f9 16 26
|
||||||
|
f10 26 10
|
||||||
|
f11 10 5
|
||||||
|
f12 10 4
|
||||||
|
insert 16 4
|
||||||
|
delete 16 5
|
||||||
|
home 16 2
|
||||||
|
pg-up 16 3
|
||||||
|
pg-dn 10 3
|
||||||
|
end 10 2
|
||||||
|
arrow-r 8 4
|
||||||
|
arrow-l 8 2
|
||||||
|
arrow-u 15 2
|
||||||
|
arrow-d 5 8
|
||||||
|
menu 11 3
|
||||||
|
/ 6 8
|
||||||
|
period 7 9
|
||||||
|
comma 32 9
|
||||||
|
; 11 6
|
||||||
|
' 15 6
|
||||||
|
enter 26 9
|
||||||
|
[ 17 6
|
||||||
|
] 32 17
|
||||||
|
\ 26 11
|
||||||
|
caps-lck 17 33
|
||||||
|
tab 17 20
|
||||||
|
space 26 8
|
||||||
|
prt-sc 10 1
|
||||||
|
scr-lk 12 1
|
||||||
|
pause 9 2
|
||||||
|
page left 9 3
|
||||||
|
page right 8 3
|
||||||
|
mute 11 5
|
||||||
|
volume down 17 5
|
||||||
|
volume up 12 5
|
||||||
|
ThinkVantage 15 5
|
329
Example_Keyboards/Lenovo_ThinkPad_T61/Matrix_Decoder_T61.ino
Normal file
329
Example_Keyboards/Lenovo_ThinkPad_T61/Matrix_Decoder_T61.ino
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
//
|
||||||
|
// This software is in the public domain.
|
||||||
|
// It will determine how a laptop keyboard matrix is wired using a Teensy 3.2 on an FPC T61 daughterboard.
|
||||||
|
// Open an editor on a computer and load or create a file that lists every key
|
||||||
|
// on the laptop keyboard that will be tested. Connect the FPC cable of the test keyboard
|
||||||
|
// to the Teensy/FPC board. Connect a USB cable from the Teensy to the computer.
|
||||||
|
// Wait a few seconds for the computer to see the Teensy as a keyboard. If numbers are reported on the screen
|
||||||
|
// before any keys are pressed, these I/O numbers are shorted together and must be fixed.
|
||||||
|
// Press each key one by one on the test keyboard as listed on the editor screen. When a key
|
||||||
|
// is pressed on the test keyboard, the program detects which Teensy I/O's
|
||||||
|
// were connected. Those two I/O's are sent over USB (separated by a TAB) and displayed
|
||||||
|
// on the editor. After sending the numbers, a DOWN ARROW is sent over USB to prepare for
|
||||||
|
// the next key. Once all keys on the test keyboard have been pressed, the file in
|
||||||
|
// the editor can be saved to create a row-column matrix.
|
||||||
|
//
|
||||||
|
// Revision History
|
||||||
|
// Rev 1.00 - Oct 21, 2018 - Original Release
|
||||||
|
//
|
||||||
|
// FPC 02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32
|
||||||
|
// I/O 31,15,32,16,26,17,07,12,25,11,06,10,24,09,05,08,33,04,20,03,21,02,22,01
|
||||||
|
// Load an array with the Teensy 3.2 I/O numbers that correspond to the FPC pins
|
||||||
|
int con_pin[] = {31,15,32,16,26,17,7,12,25,11,6,10,24,9,5,8,33,4,20,3,21,2,22,1};
|
||||||
|
//
|
||||||
|
// load the key codes used in sending usb numbers, tab, and down arrow
|
||||||
|
int key_1 = KEY_1;
|
||||||
|
int key_2 = KEY_2;
|
||||||
|
int key_3 = KEY_3;
|
||||||
|
int key_4 = KEY_4;
|
||||||
|
int key_5 = KEY_5;
|
||||||
|
int key_6 = KEY_6;
|
||||||
|
int key_7 = KEY_7;
|
||||||
|
int key_8 = KEY_8;
|
||||||
|
int key_9 = KEY_9;
|
||||||
|
int key_0 = KEY_0;
|
||||||
|
int key_tab = KEY_TAB;
|
||||||
|
int key_down = KEY_DOWN;
|
||||||
|
//
|
||||||
|
// Function to set a pin as an input with a pullup so it's high unless grounded by a key press
|
||||||
|
void go_z(int pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, INPUT_PULLUP);
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set a pin as an output and drive it to a logic low (0 volts)
|
||||||
|
void go_0(int pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to send numbers over USB for display on an editor
|
||||||
|
void usb_num(int num) // the numbers 0 thru 33 are sent over usb as 0 thru 33
|
||||||
|
{
|
||||||
|
switch (num) {
|
||||||
|
case 0:
|
||||||
|
Keyboard.set_key1(key_0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Keyboard.set_key1(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
Keyboard.set_key1(key_4);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
Keyboard.set_key1(key_5);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Keyboard.set_key1(key_6);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
Keyboard.set_key1(key_7);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
Keyboard.set_key1(key_8);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
Keyboard.set_key1(key_9);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(50);
|
||||||
|
Keyboard.set_key1(0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(50);
|
||||||
|
Keyboard.set_key2(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_4);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_5);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_6);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_7);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_8);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
Keyboard.set_key1(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_9);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(50);
|
||||||
|
Keyboard.set_key1(0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(50);
|
||||||
|
Keyboard.set_key2(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_4);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 25:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_5);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 26:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_6);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_7);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_8);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 29:
|
||||||
|
Keyboard.set_key1(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_9);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
Keyboard.set_key1(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 31:
|
||||||
|
Keyboard.set_key1(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_1);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
Keyboard.set_key1(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key2(key_2);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
case 33:
|
||||||
|
Keyboard.set_key1(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(50);
|
||||||
|
Keyboard.set_key1(0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(50);
|
||||||
|
Keyboard.set_key2(key_3);
|
||||||
|
Keyboard.send_now();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key1(0); // clear out the key slots
|
||||||
|
Keyboard.set_key2(0);
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key1(key_tab); // Tab over to position for next number
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key1(0); // clear out the tab from the slot
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to send a down arrow over usb to position for the next key
|
||||||
|
void down_arrow(void) {
|
||||||
|
Keyboard.set_key1(key_down); // send a down arrow
|
||||||
|
Keyboard.send_now();
|
||||||
|
delay(20);
|
||||||
|
Keyboard.set_key1(0); // release the down arrow
|
||||||
|
Keyboard.send_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------Setup-----------------------------------
|
||||||
|
void setup() {
|
||||||
|
for (int k = 0; k < 24; k++) { // loop thru all connector pins
|
||||||
|
go_z(con_pin[k]); // set each pin as an input with a pullup
|
||||||
|
}
|
||||||
|
delay(15000); // Wait for the host to connect to the Teensy as a keyboard. If 2 pins are shorted,
|
||||||
|
// you want the host to be ready to receive the pin numbers.
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// -------------------------------------------Main Loop--------------------------------------
|
||||||
|
//
|
||||||
|
void loop() {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
for (int i=0; i<23; i++) { // outer loop index
|
||||||
|
go_0(con_pin[i]); // make the outer loop pin an output and send this pin low
|
||||||
|
for (int j=i+1; j<24; j++) { // inner loop index
|
||||||
|
delayMicroseconds(10); // give time to let the signals settle out
|
||||||
|
if (!digitalRead(con_pin[j])) { // check for connection between inner and outer pins
|
||||||
|
usb_num(con_pin[i]); // send outer loop I/O number over usb
|
||||||
|
usb_num(con_pin[j]); // send inner loop I/O number over usb
|
||||||
|
down_arrow(); // send a down arrow over usb
|
||||||
|
while(!digitalRead(con_pin[j])) { // wait until key is released
|
||||||
|
; // if 2 pins are shorted, the code will hang here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go_z(con_pin[i]); // return the outer loop pin to float with pullup
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
delay(25); // overall keyboard scan rate is about 30 milliseconds
|
||||||
|
//
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue