Compare commits

...

11 commits

Author SHA1 Message Date
Frank Adams
a8f211e6e5
Add files via upload 2023-10-12 12:44:08 -07:00
Frank Adams
ccbd9eebe2
Add files via upload 2023-09-04 10:51:16 -07:00
Frank Adams
89a9ff0243
Add files via upload 2023-09-03 10:56:07 -07:00
Frank Adams
4294250041
Add files via upload 2023-08-29 14:52:13 -07:00
Frank Adams
27be4d5a4d
Add files via upload 2023-08-29 14:48:23 -07:00
Frank Adams
d5f0d32860
Delete Lenovo_T41_Keyboard.ino 2023-08-29 14:47:23 -07:00
Frank Adams
7864c6a0e9
Add files via upload 2023-08-29 14:37:19 -07:00
Frank Adams
ec29edd1ba
Add files via upload 2023-02-10 17:15:13 -08:00
Frank Adams
e9a6f3ff66
Merge pull request #18 from NitemareReal/patch-1
Added missing keys and Num-Lock/Scroll-Lock status detection
2023-01-04 08:50:22 -08:00
Frank Adams
0c7d36a77e
Add files via upload 2022-12-26 12:44:08 -08:00
NitemareReal
f8e44fb1af
Added missing keys and Num-Lock/Scroll-Lock status detection
Added KEY_PAUSE, KEY_PRINTSCREEN and KEY_SCROLL_LOCK missing keys. Added support to switch on/off a (external) LED through pins 14 and 15 to show Num-Lock and Scroll-Lock status .
2022-11-29 14:13:49 +01:00
14 changed files with 13487 additions and 6 deletions

View file

@ -0,0 +1,397 @@
/* Copyright 2019 Frank Adams
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This software implements a GRID 1550 Laptop Keyboard Controller using a Teensy LC
// for use with a Windows PC.
//
// Revision History
// Initial Release Dec 12, 2019 - Created from Linux version, uses alt codes for \ and | which are not
// compatible with Linux
//
#define MODIFIERKEY_FN 0x8f // give Fn key a fake HID code
#define CAPS_LED 13 // Teensy LED on IO#13 shows Caps-Lock. Add another LED (anode) on IO#13 with its own dropping resistor to ground.
#define NUM_LED 26 // Teensy IO#26 shows Num-Lock (wire to anode of new LED)then to a dropping resistor to ground.
//
const byte rows_max = 11; // sets the number of rows in the matrix
const byte cols_max = 13; // 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] = {
{0,0,0,0,0,KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,0,KEY_F9,0},
{KEY_SPACE,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,KEY_ESC,KEY_1,0,KEY_F6,KEY_F7,KEY_F8,KEY_F10,0},
{0,0,0,0,0,KEY_TAB,KEY_Q,KEY_W,KEY_2,KEY_3,0,KEY_6,0},
{0,0,0,0,0,KEY_CAPS_LOCK,KEY_A,KEY_S,KEY_E,KEY_4,KEY_5,KEY_7,0},
{0,0,0,0,KEY_LEFT,0,KEY_SPACE,KEY_Z,KEY_F,KEY_D,KEY_8,KEY_9,0},
{0,0,0,0,KEY_NUM_LOCK,KEY_SCROLL_LOCK,KEY_V,KEY_B,KEY_H,KEY_Y,KEY_U,KEY_MINUS,0},
{0,0,0,0,KEY_DOWN,0,KEY_X,KEY_C,KEY_G,KEY_R,KEY_T,KEY_0,0},
{0,0,0,0,KEY_TILDE,KEY_UP,KEY_N,KEY_M,KEY_J,KEY_K,KEY_I,KEY_INSERT,0},
{0,0,0,0,KEY_BACKSLASH,KEY_RIGHT_BRACE,KEY_COMMA,KEY_BACKSPACE,KEY_L,KEY_DELETE,KEY_O,KEY_EQUAL,0},
{0,0,0,0,KEY_RIGHT,KEY_ENTER,KEY_SLASH,KEY_PERIOD,KEY_QUOTE,KEY_SEMICOLON,KEY_LEFT_BRACE,KEY_P,0}
};
// Load the numlock key matrix with key names at the correct row-column location.
// This matrix is the same as the normal matrix except for the number pad keys
// A zero indicates no numlock key at that location.
int numlock[rows_max][cols_max] = {
{0,0,0,0,0,KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,0,KEY_F9,0},
{KEY_SPACE,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,KEY_ESC,KEY_1,0,KEY_F6,KEY_F7,KEY_F8,KEY_F10,0},
{0,0,0,0,0,KEY_TAB,KEY_Q,KEY_W,KEY_2,KEY_3,0,KEY_6,0},
{0,0,0,0,0,KEY_CAPS_LOCK,KEY_A,KEY_S,KEY_E,KEY_4,KEY_5,KEYPAD_7,0},
{0,0,0,0,KEY_LEFT,0,KEY_SPACE,KEY_Z,KEY_F,KEY_D,KEYPAD_8,KEYPAD_9,0},
{0,0,0,0,KEY_NUM_LOCK,KEY_SCROLL_LOCK,KEY_V,KEY_B,KEY_H,KEY_Y,KEYPAD_4,KEY_MINUS,0},
{0,0,0,0,KEY_DOWN,0,KEY_X,KEY_C,KEY_G,KEY_R,KEY_T,KEYPAD_ASTERIX,0},
{0,0,0,0,KEY_TILDE,KEY_UP,KEY_N,KEY_M,KEYPAD_1,KEYPAD_2,KEYPAD_5,KEY_INSERT,0},
{0,0,0,0,KEY_BACKSLASH,KEY_RIGHT_BRACE,KEYPAD_0,KEY_BACKSPACE,KEYPAD_3,KEY_DELETE,KEYPAD_6,KEY_EQUAL,0},
{0,0,0,0,KEY_RIGHT,KEY_ENTER,KEYPAD_SLASH,KEYPAD_PERIOD,KEY_QUOTE,KEYPAD_PLUS,KEY_LEFT_BRACE,KEYPAD_MINUS,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,MODIFIERKEY_RIGHT_SHIFT,MODIFIERKEY_LEFT_SHIFT,MODIFIERKEY_FN,0,0,0,0,0,0,0,0,MODIFIERKEY_LEFT_ALT},
{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_LEFT_CTRL,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}
};
// Load the media key matrix with Fn 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,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,KEY_MEDIA_VOLUME_DEC,KEY_MEDIA_VOLUME_INC,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_HOME,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_PAGE_DOWN,KEY_PRINTSCREEN,0,0,0,0,0,0,0},
{0,0,0,0,0,KEY_PAGE_UP,0,0,0,0,0,KEY_F11,0},
{0,0,0,0,0,0,0,0,0,KEY_F12,0,0,0},
{0,0,0,0,KEY_END,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,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1}
};
//
// Define the Teensy LC I/O numbers (translated from the FPC pin #)
// Row FPC pin # 23,21,19,17,15,13,11,07,03,01,05 (These are the FPC pins if a connector board is used)
// Teensy I/O # 14,15,16,17,18,19,20,21,22,23,24
int Row_IO[rows_max] = {14,15,16,17,18,19,20,21,22,23,24}; // Teensy LC I/O numbers for rows
//
// Column FPC pin # 02,04,06,08,10,12,14,16,18,20,22,24,26 (These are the FPC pins if a connector board is used)
// Teensy I/O # 00,01,02,03,04,05,06,07,08,09,10,11,12
int Col_IO[cols_max] = {0,1,2,3,4,5,6,7,8,9,10,11,12}; // Teensy LC I/O numbers for columns
// Declare variables that will be used by functions
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;
//
// 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;
}
if (!slot1 || !slot2 || !slot3 || !slot4 || !slot5 || !slot6) {
slots_full = LOW; // slots are not full
}
else {
slots_full = HIGH; // slots are full
}
}
//
// 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();
}
//
// 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() {
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
}
}
//
boolean Fn_pressed = HIGH; // Initialize Fn key to HIGH = "not pressed"
extern volatile uint8_t keyboard_leds; // 8 bits sent from Pi to Teensy that give keyboard LED status. Caps lock is bit D1.
//
//---------------------------------Main Loop---------------------------------------------
//
void loop() {
// 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 including the Fn special case
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
if (modifier[x][y] != MODIFIERKEY_FN) { // Exclude Fn modifier key
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 { // Fn is pressed
Fn_pressed = LOW; // Fn status variable is active low
old_key[x][y] = LOW; // old_key state is "pressed" (active low)
}
}
else if (digitalRead(Col_IO[y]) && (!old_key[x][y])) { //check if key is not pressed and was previously pressed
if (modifier[x][y] != MODIFIERKEY_FN) { // Exclude Fn modifier key
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"
}
else { // Fn is released
Fn_pressed = HIGH; // Fn is no longer active
old_key[x][y] = HIGH; // old_key state is "not pressed"
}
}
}
// ***********end of modifier section
//
// ***********Normal keys and media keys in this section
else if ((normal[x][y] != 0) || (media[x][y] != 0)) { // check if normal or media key exists at this location in the array
if (!digitalRead(Col_IO[y]) && (old_key[x][y]) && (!slots_full)) { // check if key pressed and not previously pressed and slots not full
old_key[x][y] = LOW; // Save state of key as "pressed"
if (Fn_pressed) { // Fn_pressed is active low so it is not pressed and normal key needs to be sent
if (keyboard_leds & 1) { // test if Num Lock is turned on
load_slot(numlock[x][y]); //update first available slot with key name from numlock matrix
send_normals(); // send all slots over USB including the key that just got pressed
}
else {
load_slot(normal[x][y]); //update first available slot with key name from normal matrix
send_normals(); // send all slots over USB including the key that just got pressed
}
}
else if (media[x][y] != 0) { // Fn is pressed so send media if a key exists in the matrix
Keyboard.press(media[x][y]); // media key is sent using keyboard press function per PJRC
delay(5); // delay 5 milliseconds before releasing to make sure it gets sent over USB
Keyboard.release(media[x][y]); // send media key release
}
}
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 (Fn_pressed) { // Fn is not pressed
if (keyboard_leds & 1) { // test if Num Lock is turned on
clear_slot(numlock[x][y]); //clear slot with key name from numlock matrix
send_normals(); // send all slots over USB including the key that just got released
}
else {
clear_slot(normal[x][y]); //clear slot with key name from normal matrix
send_normals(); // send all slots over USB including the key that just got released
}
}
}
}
// **************end of normal and media key section
//
}
go_z(Row_IO[x]); // De-activate Row (send it to hi-z)
}
//
// **********keyboard scan complete
//
// Turn on the LED on the Teensy for Caps Lock based on bit 1 in the keyboard_leds variable controlled by the USB host computer
//
if (keyboard_leds & 1<<1) { // mask off all bits but D1 and test if set
go_1(CAPS_LED); // turn on the LED
}
else {
go_0(CAPS_LED); // turn off the LED
}
//
// Turn on the LED on the Teensy for Num Lock based on bit 0 in 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
}
//
delay(25); // The overall keyboard scanning rate is about 30ms
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,338 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// this software will determine how a laptop keyboard matrix is wired using a Teensy 4.0 on an T41 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 - Aug 10, 2023 - 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 33,32,08,10,31,30,07,11,29,28,06,12,27,26,05,24,25,04,20,03,21,02,22,01
// Load an array with the Teensy 4.0 I/O numbers that correspond to the FPC pins
int io_pin[] = {33,32,8,10,31,30,7,11,29,28,6,12,27,26,5,24,25,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 connected Teensy IO's
go_z(io_pin[k]); // set each I/O pin as an input with a pullup
}
delay(15000); // Wait for the host to connect to the Teensy as a keyboard. If 2 I/O pins are shorted,
// you want the host to be ready to receive the numbers.
}
//
// -------------------------------------------Main Loop--------------------------------------
//
void loop() {
//
//
for (int i=0; i<23; i++) { // outer loop index
go_0(io_pin[i]); // make the outer loop I/O pin an output and send it low
for (int j=i+1; j<24; j++) { // inner loop index
delayMicroseconds(10); // give time to let the signals settle out
if (!digitalRead(io_pin[j])) { // check for connection between inner and outer I/O pins
usb_num(io_pin[i]); // send outer loop I/O number over usb
usb_num(io_pin[j]); // send inner loop I/O number over usb
down_arrow(); // send a down arrow over usb
while(!digitalRead(io_pin[j])) { // wait until key is released
; // if 2 I/O pins are shorted, the code will hang here
}
}
}
go_z(io_pin[i]); // return the outer loop I/O pin to float with pullup
}
//
//
delay(25); // overall keyboard scan rate is about 30 milliseconds
//
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,745 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">
<eagle version="9.6.2">
<drawing>
<settings>
<setting alwaysvectorfont="yes"/>
<setting verticaltext="up"/>
</settings>
<grid distance="0.1" unitdist="mm" unit="mm" style="lines" multiple="1" display="no" altdistance="5" altunitdist="mil" altunit="mil"/>
<layers>
<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>
<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>
<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>
<layer number="18" name="Vias" color="2" fill="1" visible="yes" active="yes"/>
<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>
<layer number="20" name="Dimension" color="24" fill="1" visible="yes" active="yes"/>
<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="25" name="tNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="26" name="bNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="27" name="tValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="28" name="bValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>
<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>
<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>
<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>
<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>
<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>
<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>
<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>
<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="39" name="tKeepout" color="4" fill="11" visible="yes" active="yes"/>
<layer number="40" name="bKeepout" color="1" fill="11" visible="yes" active="yes"/>
<layer number="41" name="tRestrict" color="4" fill="10" visible="yes" active="yes"/>
<layer number="42" name="bRestrict" color="1" fill="10" visible="yes" active="yes"/>
<layer number="43" name="vRestrict" color="2" fill="10" visible="yes" active="yes"/>
<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>
<layer number="45" name="Holes" color="7" fill="1" visible="yes" active="yes"/>
<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>
<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>
<layer number="48" name="Document" color="7" fill="1" visible="yes" active="yes"/>
<layer number="49" name="Reference" color="7" fill="1" visible="yes" active="yes"/>
<layer number="50" name="dxf" color="7" fill="1" visible="no" active="no"/>
<layer number="51" name="tDocu" color="7" fill="1" visible="yes" active="yes"/>
<layer number="52" name="bDocu" color="7" fill="1" visible="yes" active="yes"/>
<layer number="53" name="tGND_GNDA" color="7" fill="9" visible="no" active="no"/>
<layer number="54" name="bGND_GNDA" color="1" fill="9" visible="no" active="no"/>
<layer number="56" name="wert" color="7" fill="1" visible="no" active="no"/>
<layer number="57" name="tCAD" color="7" fill="1" visible="no" active="no"/>
<layer number="59" name="tCarbon" color="7" fill="1" visible="no" active="no"/>
<layer number="60" name="bCarbon" color="7" fill="1" visible="no" active="no"/>
<layer number="88" name="SimResults" color="9" fill="1" visible="no" active="no"/>
<layer number="89" name="SimProbes" color="9" fill="1" visible="no" active="no"/>
<layer number="90" name="Modules" color="5" fill="1" visible="no" active="no"/>
<layer number="91" name="Nets" color="2" fill="1" visible="no" active="no"/>
<layer number="92" name="Busses" color="1" fill="1" visible="no" active="no"/>
<layer number="93" name="Pins" color="2" fill="1" visible="no" active="no"/>
<layer number="94" name="Symbols" color="4" fill="1" visible="no" active="no"/>
<layer number="95" name="Names" color="7" fill="1" visible="no" active="no"/>
<layer number="96" name="Values" color="7" fill="1" visible="no" active="no"/>
<layer number="97" name="Info" color="7" fill="1" visible="no" active="no"/>
<layer number="98" name="Guide" color="6" fill="1" visible="no" active="no"/>
<layer number="99" name="SpiceOrder" color="7" fill="1" visible="no" active="no"/>
<layer number="100" name="Muster" color="7" fill="1" visible="no" active="no"/>
<layer number="101" name="Patch_Top" color="12" fill="4" visible="yes" active="yes"/>
<layer number="102" name="Vscore" color="7" fill="1" visible="yes" active="yes"/>
<layer number="103" name="tMap" color="7" fill="1" visible="yes" active="yes"/>
<layer number="104" name="Name" color="16" fill="1" visible="yes" active="yes"/>
<layer number="105" name="tPlate" color="7" fill="1" visible="yes" active="yes"/>
<layer number="106" name="bPlate" color="7" fill="1" visible="yes" active="yes"/>
<layer number="107" name="Crop" color="7" fill="1" visible="yes" active="yes"/>
<layer number="108" name="tplace-old" color="10" fill="1" visible="yes" active="yes"/>
<layer number="109" name="ref-old" color="11" fill="1" visible="yes" active="yes"/>
<layer number="110" name="fp0" color="7" fill="1" visible="yes" active="yes"/>
<layer number="111" name="LPC17xx" color="7" fill="1" visible="yes" active="yes"/>
<layer number="112" name="tSilk" color="7" fill="1" visible="yes" active="yes"/>
<layer number="113" name="IDFDebug" color="4" fill="1" visible="yes" active="yes"/>
<layer number="114" name="Badge_Outline" color="7" fill="1" visible="yes" active="yes"/>
<layer number="115" name="ReferenceISLANDS" color="7" fill="1" visible="yes" active="yes"/>
<layer number="116" name="Patch_BOT" color="9" fill="4" visible="yes" active="yes"/>
<layer number="118" name="Rect_Pads" color="7" fill="1" visible="yes" active="yes"/>
<layer number="121" name="_tsilk" color="7" fill="1" visible="yes" active="yes"/>
<layer number="122" name="_bsilk" color="7" fill="1" visible="yes" active="yes"/>
<layer number="123" name="tTestmark" color="7" fill="1" visible="yes" active="yes"/>
<layer number="124" name="bTestmark" color="7" fill="1" visible="yes" active="yes"/>
<layer number="125" name="_tNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="126" name="_bNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="127" name="_tValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="128" name="_bValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="129" name="Mask" color="7" fill="1" visible="yes" active="yes"/>
<layer number="131" name="tAdjust" color="7" fill="1" visible="yes" active="yes"/>
<layer number="132" name="bAdjust" color="7" fill="1" visible="yes" active="yes"/>
<layer number="144" name="Drill_legend" color="7" fill="1" visible="yes" active="yes"/>
<layer number="150" name="Notes" color="7" fill="1" visible="yes" active="yes"/>
<layer number="151" name="HeatSink" color="7" fill="1" visible="yes" active="yes"/>
<layer number="152" name="_bDocu" color="7" fill="1" visible="yes" active="yes"/>
<layer number="153" name="FabDoc1" color="7" fill="1" visible="yes" active="yes"/>
<layer number="154" name="FabDoc2" color="7" fill="1" visible="yes" active="yes"/>
<layer number="155" name="FabDoc3" color="7" fill="1" visible="yes" active="yes"/>
<layer number="199" name="Contour" color="7" fill="1" visible="yes" active="yes"/>
<layer number="200" name="200bmp" color="1" fill="10" visible="yes" active="yes"/>
<layer number="201" name="201bmp" color="2" fill="10" visible="yes" active="yes"/>
<layer number="202" name="202bmp" color="3" fill="10" visible="yes" active="yes"/>
<layer number="203" name="203bmp" color="4" fill="10" visible="yes" active="yes"/>
<layer number="204" name="204bmp" color="5" fill="10" visible="yes" active="yes"/>
<layer number="205" name="205bmp" color="6" fill="10" visible="yes" active="yes"/>
<layer number="206" name="206bmp" color="7" fill="10" visible="yes" active="yes"/>
<layer number="207" name="207bmp" color="8" fill="10" visible="yes" active="yes"/>
<layer number="208" name="208bmp" color="9" fill="10" visible="yes" active="yes"/>
<layer number="209" name="209bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="210" name="210bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="211" name="211bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="212" name="212bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="213" name="213bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="214" name="214bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="215" name="215bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="216" name="216bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="217" name="217bmp" color="18" fill="1" visible="no" active="no"/>
<layer number="218" name="218bmp" color="19" fill="1" visible="no" active="no"/>
<layer number="219" name="219bmp" color="20" fill="1" visible="no" active="no"/>
<layer number="220" name="220bmp" color="21" fill="1" visible="no" active="no"/>
<layer number="221" name="221bmp" color="22" fill="1" visible="no" active="no"/>
<layer number="222" name="222bmp" color="23" fill="1" visible="no" active="no"/>
<layer number="223" name="223bmp" color="24" fill="1" visible="no" active="no"/>
<layer number="224" name="224bmp" color="25" fill="1" visible="no" active="no"/>
<layer number="225" name="225bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="226" name="226bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="227" name="227bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="228" name="228bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="229" name="229bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="230" name="230bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="231" name="231bmp" color="7" fill="1" visible="yes" active="yes"/>
<layer number="232" name="Eagle3D_PG2" color="7" fill="1" visible="yes" active="yes"/>
<layer number="233" name="Eagle3D_PG3" color="7" fill="1" visible="yes" active="yes"/>
<layer number="248" name="Housing" color="7" fill="1" visible="yes" active="yes"/>
<layer number="249" name="Edge" color="7" fill="1" visible="yes" active="yes"/>
<layer number="250" name="Descript" color="3" fill="1" visible="no" active="no"/>
<layer number="251" name="SMDround" color="12" fill="11" visible="no" active="no"/>
<layer number="254" name="cooling" color="7" fill="1" visible="yes" active="yes"/>
<layer number="255" name="routoute" color="7" fill="1" visible="yes" active="yes"/>
</layers>
<board>
<plain>
<wire x1="0" y1="0" x2="17.5" y2="0" width="0" layer="20"/>
<wire x1="17.5" y1="0" x2="17.5" y2="19" width="0" layer="20"/>
<wire x1="17.5" y1="19" x2="0" y2="19" width="0" layer="20"/>
<wire x1="0" y1="19" x2="0" y2="0" width="0" layer="20"/>
<hole x="2" y="2" drill="2.4"/>
<hole x="15.5" y="17" drill="2.4"/>
<text x="6.5" y="12" size="0.6096" layer="21">1</text>
<text x="6.4" y="5.7" size="0.6096" layer="21">2</text>
<text x="10.9" y="12" size="0.6096" layer="21">19</text>
<text x="11" y="5.7" size="0.6096" layer="21">20</text>
<text x="0.8" y="13.1" size="0.6096" layer="21">1</text>
<text x="0.8" y="15.8" size="0.6096" layer="21">3</text>
<text x="3.2" y="13.2" size="0.6096" layer="21">5</text>
<text x="3.2" y="15.8" size="0.6096" layer="21">7</text>
<text x="5.8" y="13.3" size="0.6096" layer="21">9</text>
<text x="5.5" y="15.8" size="0.6096" layer="21">11</text>
<text x="7.9" y="13.2" size="0.6096" layer="21">13</text>
<text x="8" y="15.9" size="0.6096" layer="21">15</text>
<text x="10.4" y="13.3" size="0.6096" layer="21">17</text>
<text x="10.5" y="15.8" size="0.6096" layer="21">19</text>
<text x="4.1" y="5" size="0.6096" layer="21">2</text>
<text x="4.1" y="2.7" size="0.6096" layer="21">4</text>
<text x="6.6" y="5" size="0.6096" layer="21">6</text>
<text x="6.6" y="2.6" size="0.6096" layer="21">8</text>
<text x="8.8" y="5.1" size="0.6096" layer="21">10</text>
<text x="8.8" y="2.6" size="0.6096" layer="21">12</text>
<text x="11.3" y="5" size="0.6096" layer="21">14</text>
<text x="11.3" y="2.7" size="0.6096" layer="21">16</text>
<text x="13.8" y="5" size="0.6096" layer="21">18</text>
<text x="13.9" y="2.8" size="0.6096" layer="21">20</text>
<text x="14.9" y="10.7" size="0.6096" layer="21">Tab</text>
<text x="1.3" y="7.6" size="0.6096" layer="21">Tab</text>
<text x="0.8" y="11.6" size="0.6096" layer="21">DF12-20DP</text>
<text x="11.7" y="8.1" size="0.6096" layer="22" rot="MR0">DF12-20DP
T41 Touchpad
Connector Breakout</text>
</plain>
<libraries>
<library name="DF12-20DP">
<packages>
<package name="DF12-20DP">
<smd name="2" x="0" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="1" x="0" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="4" x="0.5" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="3" x="0.5" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="6" x="1" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="5" x="1" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="8" x="1.5" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="7" x="1.5" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="10" x="2" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="9" x="2" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="12" x="2.5" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="11" x="2.5" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="14" x="3" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="13" x="3" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="16" x="3.5" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="15" x="3.5" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="18" x="4" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="17" x="4" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="20" x="4.5" y="-1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="19" x="4.5" y="1.8" dx="1.6" dy="0.3" layer="1" rot="R90"/>
<smd name="TAB1" x="-1.75" y="0" dx="0.8" dy="1.7" layer="1"/>
<smd name="TAB2" x="6.25" y="0" dx="0.8" dy="1.7" layer="1"/>
<text x="-6.6" y="4.6" size="1.27" layer="25">&gt;Name</text>
<text x="-6.6" y="3.2" size="1.27" layer="27">&gt;Value</text>
<hole x="-1.05" y="1.5" drill="0.6"/>
<hole x="5.55" y="1.5" drill="0.6"/>
</package>
</packages>
</library>
<library name="SparkFun-Connectors" urn="urn:adsk.eagle:library:513">
<description>&lt;h3&gt;SparkFun Connectors&lt;/h3&gt;
This library contains electrically-functional connectors.
&lt;br&gt;
&lt;br&gt;
We've spent an enormous amount of time creating and checking these footprints and parts, but it is &lt;b&gt; the end user's responsibility&lt;/b&gt; to ensure correctness and suitablity for a given componet or application.
&lt;br&gt;
&lt;br&gt;If you enjoy using this library, please buy one of our products at &lt;a href=" www.sparkfun.com"&gt;SparkFun.com&lt;/a&gt;.
&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Licensing:&lt;/b&gt; Creative Commons ShareAlike 4.0 International - https://creativecommons.org/licenses/by-sa/4.0/
&lt;br&gt;
&lt;br&gt;
You are welcome to use this library for commercial purposes. For attribution, we ask that when you begin to sell your device using our footprint, you email us with a link to the product being sold. We want bragging rights that we helped (in a very small part) to create your 8th world wonder. We would like the opportunity to feature your device on our homepage.</description>
<packages>
<package name="2X5_NOSILK" urn="urn:adsk.eagle:footprint:37735/1" library_version="1">
<description>&lt;h3&gt;Plated Through Hole - 2x5 No Silk Outline&lt;/h3&gt;
&lt;p&gt;Specifications:
&lt;ul&gt;&lt;li&gt;Pin count:10&lt;/li&gt;
&lt;li&gt;Pin pitch:0.1"&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;Example device(s):
&lt;ul&gt;&lt;li&gt;CONN_05x2&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;</description>
<pad name="1" x="0" y="0" drill="1.016" diameter="1.8796"/>
<pad name="2" x="0" y="2.54" drill="1.016" diameter="1.8796"/>
<pad name="3" x="2.54" y="0" drill="1.016" diameter="1.8796"/>
<pad name="4" x="2.54" y="2.54" drill="1.016" diameter="1.8796"/>
<pad name="5" x="5.08" y="0" drill="1.016" diameter="1.8796"/>
<pad name="6" x="5.08" y="2.54" drill="1.016" diameter="1.8796"/>
<pad name="7" x="7.62" y="0" drill="1.016" diameter="1.8796"/>
<pad name="8" x="7.62" y="2.54" drill="1.016" diameter="1.8796"/>
<pad name="9" x="10.16" y="0" drill="1.016" diameter="1.8796"/>
<pad name="10" x="10.16" y="2.54" drill="1.016" diameter="1.8796"/>
<rectangle x1="-0.254" y1="-0.254" x2="0.254" y2="0.254" layer="51" rot="R90"/>
<rectangle x1="-0.254" y1="2.286" x2="0.254" y2="2.794" layer="51" rot="R90"/>
<rectangle x1="2.286" y1="2.286" x2="2.794" y2="2.794" layer="51" rot="R90"/>
<rectangle x1="2.286" y1="-0.254" x2="2.794" y2="0.254" layer="51" rot="R90"/>
<rectangle x1="4.826" y1="-0.254" x2="5.334" y2="0.254" layer="51" rot="R90"/>
<rectangle x1="9.906" y1="2.286" x2="10.414" y2="2.794" layer="51" rot="R90"/>
<rectangle x1="9.906" y1="-0.254" x2="10.414" y2="0.254" layer="51" rot="R90"/>
<rectangle x1="7.366" y1="-0.254" x2="7.874" y2="0.254" layer="51" rot="R90"/>
<rectangle x1="7.366" y1="2.286" x2="7.874" y2="2.794" layer="51" rot="R90"/>
<rectangle x1="4.826" y1="2.286" x2="5.334" y2="2.794" layer="51" rot="R90"/>
<wire x1="0.635" y1="-1.27" x2="-0.635" y2="-1.27" width="0.2032" layer="51"/>
<text x="-0.889" y="3.81" size="0.6096" layer="25" font="vector" ratio="20">&gt;NAME</text>
<text x="-0.762" y="-2.159" size="0.6096" layer="27" font="vector" ratio="20">&gt;VALUE</text>
</package>
<package name="1X01" urn="urn:adsk.eagle:footprint:37642/1" library_version="1">
<description>&lt;h3&gt;Plated Through Hole&lt;/h3&gt;
&lt;p&gt;Specifications:
&lt;ul&gt;&lt;li&gt;Pin count:1&lt;/li&gt;
&lt;li&gt;Pin pitch:0.1"&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;Example device(s):
&lt;ul&gt;&lt;li&gt;CONN_01&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;</description>
<wire x1="1.27" y1="0.635" x2="0.635" y2="1.27" width="0.2032" layer="21"/>
<wire x1="0.635" y1="1.27" x2="-0.635" y2="1.27" width="0.2032" layer="21"/>
<wire x1="-0.635" y1="1.27" x2="-1.27" y2="0.635" width="0.2032" layer="21"/>
<wire x1="-1.27" y1="0.635" x2="-1.27" y2="-0.635" width="0.2032" layer="21"/>
<wire x1="-1.27" y1="-0.635" x2="-0.635" y2="-1.27" width="0.2032" layer="21"/>
<wire x1="-0.635" y1="-1.27" x2="0.635" y2="-1.27" width="0.2032" layer="21"/>
<wire x1="0.635" y1="-1.27" x2="1.27" y2="-0.635" width="0.2032" layer="21"/>
<wire x1="1.27" y1="-0.635" x2="1.27" y2="0.635" width="0.2032" layer="21"/>
<pad name="1" x="0" y="0" drill="1.016" diameter="1.8796" rot="R90"/>
<text x="-1.27" y="1.397" size="0.6096" layer="25" font="vector" ratio="20">&gt;NAME</text>
<text x="-1.27" y="-1.524" size="0.6096" layer="27" font="vector" ratio="20" align="top-left">&gt;VALUE</text>
<rectangle x1="-0.254" y1="-0.254" x2="0.254" y2="0.254" layer="51"/>
</package>
</packages>
<packages3d>
<package3d name="2X5_NOSILK" urn="urn:adsk.eagle:package:38114/1" type="box" library_version="1">
<description>Plated Through Hole - 2x5 No Silk Outline
Specifications:
Pin count:10
Pin pitch:0.1"
Example device(s):
CONN_05x2
</description>
<packageinstances>
<packageinstance name="2X5_NOSILK"/>
</packageinstances>
</package3d>
<package3d name="1X01" urn="urn:adsk.eagle:package:38028/1" type="box" library_version="1">
<description>Plated Through Hole
Specifications:
Pin count:1
Pin pitch:0.1"
Example device(s):
CONN_01
</description>
<packageinstances>
<packageinstance name="1X01"/>
</packageinstances>
</package3d>
</packages3d>
</library>
</libraries>
<attributes>
</attributes>
<variantdefs>
</variantdefs>
<classes>
<class number="0" name="default" width="0" drill="0">
</class>
</classes>
<designrules name="oshpark-2layer">
<description language="en">&lt;b&gt;OSH Park Design Rules&lt;/b&gt;
&lt;p&gt;
Please make sure your boards conform to these design rules.
&lt;/p&gt;
&lt;p&gt;
Note, that not all DRC settings must be set by the manufacturer. Several can be adjusted for the design, including those listed on our docs page here.
&lt;a href=&quot;http://docs.oshpark.com/design-tools/eagle/design-rules-files/&quot;&gt;Adjustable Settings&lt;/a&gt;
&lt;/p&gt;</description>
<param name="layerSetup" value="(1*16)"/>
<param name="mtCopper" value="0.035559375mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.0356mm 0.035559375mm"/>
<param name="mtIsolate" value="1.6mm 0.1499mm 0.2007mm 0.1499mm 0.2007mm 0.1499mm 0.2007mm 0.1499mm 0.2007mm 0.1499mm 0.2007mm 0.1499mm 0.2007mm 0.1499mm 0.2007mm"/>
<param name="mdWireWire" value="6mil"/>
<param name="mdWirePad" value="6mil"/>
<param name="mdWireVia" value="6mil"/>
<param name="mdPadPad" value="6mil"/>
<param name="mdPadVia" value="6mil"/>
<param name="mdViaVia" value="6mil"/>
<param name="mdSmdPad" value="6mil"/>
<param name="mdSmdVia" value="6mil"/>
<param name="mdSmdSmd" value="6mil"/>
<param name="mdViaViaSameLayer" value="8mil"/>
<param name="mnLayersViaInSmd" value="2"/>
<param name="mdCopperDimension" value="15mil"/>
<param name="mdDrill" value="6mil"/>
<param name="mdSmdStop" value="0mil"/>
<param name="msWidth" value="6mil"/>
<param name="msDrill" value="10mil"/>
<param name="msMicroVia" value="10mil"/>
<param name="msBlindViaRatio" value="0.5"/>
<param name="rvPadTop" value="0.25"/>
<param name="rvPadInner" value="0.25"/>
<param name="rvPadBottom" value="0.25"/>
<param name="rvViaOuter" value="0.25"/>
<param name="rvViaInner" value="0.25"/>
<param name="rvMicroViaOuter" value="0.25"/>
<param name="rvMicroViaInner" value="0.25"/>
<param name="rlMinPadTop" value="5mil"/>
<param name="rlMaxPadTop" value="20mil"/>
<param name="rlMinPadInner" value="5mil"/>
<param name="rlMaxPadInner" value="20mil"/>
<param name="rlMinPadBottom" value="5mil"/>
<param name="rlMaxPadBottom" value="20mil"/>
<param name="rlMinViaOuter" value="5mil"/>
<param name="rlMaxViaOuter" value="20mil"/>
<param name="rlMinViaInner" value="5mil"/>
<param name="rlMaxViaInner" value="20mil"/>
<param name="rlMinMicroViaOuter" value="5mil"/>
<param name="rlMaxMicroViaOuter" value="20mil"/>
<param name="rlMinMicroViaInner" value="5mil"/>
<param name="rlMaxMicroViaInner" value="20mil"/>
<param name="psTop" value="-1"/>
<param name="psBottom" value="-1"/>
<param name="psFirst" value="-1"/>
<param name="psElongationLong" value="100"/>
<param name="psElongationOffset" value="100"/>
<param name="mvStopFrame" value="1"/>
<param name="mvCreamFrame" value="0"/>
<param name="mlMinStopFrame" value="2.5mil"/>
<param name="mlMaxStopFrame" value="2.5mil"/>
<param name="mlMinCreamFrame" value="0mil"/>
<param name="mlMaxCreamFrame" value="0mil"/>
<param name="mlViaStopLimit" value="0mil"/>
<param name="srRoundness" value="0"/>
<param name="srMinRoundness" value="0mil"/>
<param name="srMaxRoundness" value="0mil"/>
<param name="slThermalIsolate" value="10mil"/>
<param name="slThermalsForVias" value="0"/>
<param name="dpMaxLengthDifference" value="10mm"/>
<param name="dpGapFactor" value="2.5"/>
<param name="checkAngle" value="0"/>
<param name="checkFont" value="1"/>
<param name="checkRestrict" value="1"/>
<param name="checkStop" value="0"/>
<param name="checkValues" value="0"/>
<param name="checkNames" value="1"/>
<param name="checkWireStubs" value="1"/>
<param name="checkPolygonWidth" value="0"/>
<param name="useDiameter" value="13"/>
<param name="maxErrors" value="50"/>
</designrules>
<autorouter>
<pass name="Default">
<param name="RoutingGrid" value="50mil"/>
<param name="AutoGrid" value="1"/>
<param name="Efforts" value="0"/>
<param name="TopRouterVariant" value="1"/>
<param name="tpViaShape" value="round"/>
<param name="PrefDir.1" value="a"/>
<param name="PrefDir.2" value="0"/>
<param name="PrefDir.3" value="0"/>
<param name="PrefDir.4" value="0"/>
<param name="PrefDir.5" value="0"/>
<param name="PrefDir.6" value="0"/>
<param name="PrefDir.7" value="0"/>
<param name="PrefDir.8" value="0"/>
<param name="PrefDir.9" value="0"/>
<param name="PrefDir.10" value="0"/>
<param name="PrefDir.11" value="0"/>
<param name="PrefDir.12" value="0"/>
<param name="PrefDir.13" value="0"/>
<param name="PrefDir.14" value="0"/>
<param name="PrefDir.15" value="0"/>
<param name="PrefDir.16" value="a"/>
<param name="cfVia" value="8"/>
<param name="cfNonPref" value="5"/>
<param name="cfChangeDir" value="2"/>
<param name="cfOrthStep" value="2"/>
<param name="cfDiagStep" value="3"/>
<param name="cfExtdStep" value="0"/>
<param name="cfBonusStep" value="1"/>
<param name="cfMalusStep" value="1"/>
<param name="cfPadImpact" value="4"/>
<param name="cfSmdImpact" value="4"/>
<param name="cfBusImpact" value="0"/>
<param name="cfHugging" value="3"/>
<param name="cfAvoid" value="4"/>
<param name="cfPolygon" value="10"/>
<param name="cfBase.1" value="0"/>
<param name="cfBase.2" value="1"/>
<param name="cfBase.3" value="1"/>
<param name="cfBase.4" value="1"/>
<param name="cfBase.5" value="1"/>
<param name="cfBase.6" value="1"/>
<param name="cfBase.7" value="1"/>
<param name="cfBase.8" value="1"/>
<param name="cfBase.9" value="1"/>
<param name="cfBase.10" value="1"/>
<param name="cfBase.11" value="1"/>
<param name="cfBase.12" value="1"/>
<param name="cfBase.13" value="1"/>
<param name="cfBase.14" value="1"/>
<param name="cfBase.15" value="1"/>
<param name="cfBase.16" value="0"/>
<param name="mnVias" value="20"/>
<param name="mnSegments" value="9999"/>
<param name="mnExtdSteps" value="9999"/>
<param name="mnRipupLevel" value="10"/>
<param name="mnRipupSteps" value="100"/>
<param name="mnRipupTotal" value="100"/>
</pass>
<pass name="Follow-me" refer="Default" active="yes">
</pass>
<pass name="Busses" refer="Default" active="yes">
<param name="cfNonPref" value="4"/>
<param name="cfBusImpact" value="4"/>
<param name="cfHugging" value="0"/>
<param name="mnVias" value="0"/>
</pass>
<pass name="Route" refer="Default" active="yes">
</pass>
<pass name="Optimize1" refer="Default" active="yes">
<param name="cfVia" value="99"/>
<param name="cfExtdStep" value="10"/>
<param name="cfHugging" value="1"/>
<param name="mnExtdSteps" value="1"/>
<param name="mnRipupLevel" value="0"/>
</pass>
<pass name="Optimize2" refer="Optimize1" active="yes">
<param name="cfNonPref" value="0"/>
<param name="cfChangeDir" value="6"/>
<param name="cfExtdStep" value="0"/>
<param name="cfBonusStep" value="2"/>
<param name="cfMalusStep" value="2"/>
<param name="cfPadImpact" value="2"/>
<param name="cfSmdImpact" value="2"/>
<param name="cfHugging" value="0"/>
</pass>
<pass name="Optimize3" refer="Optimize2" active="yes">
<param name="cfChangeDir" value="8"/>
<param name="cfPadImpact" value="0"/>
<param name="cfSmdImpact" value="0"/>
</pass>
<pass name="Optimize4" refer="Optimize3" active="yes">
<param name="cfChangeDir" value="25"/>
</pass>
</autorouter>
<elements>
<element name="J1" library="DF12-20DP" package="DF12-20DP" value="" x="6.62" y="9.12" smashed="yes">
<attribute name="NAME" x="0.02" y="13.72" size="1.27" layer="25" display="off"/>
<attribute name="VALUE" x="0.02" y="12.32" size="1.27" layer="27"/>
</element>
<element name="J2" library="SparkFun-Connectors" library_urn="urn:adsk.eagle:library:513" package="2X5_NOSILK" package3d_urn="urn:adsk.eagle:package:38114/1" value="" x="5.35" y="1.9" smashed="yes">
<attribute name="NAME" x="4.461" y="5.71" size="0.6096" layer="25" font="vector" ratio="20" display="off"/>
<attribute name="VALUE" x="4.588" y="-0.259" size="0.6096" layer="27" font="vector" ratio="20"/>
</element>
<element name="J3" library="SparkFun-Connectors" library_urn="urn:adsk.eagle:library:513" package="2X5_NOSILK" package3d_urn="urn:adsk.eagle:package:38114/1" value="" x="2" y="14.5" smashed="yes">
<attribute name="NAME" x="1.111" y="18.31" size="0.6096" layer="25" font="vector" ratio="20" display="off"/>
<attribute name="VALUE" x="1.238" y="12.341" size="0.6096" layer="27" font="vector" ratio="20"/>
</element>
<element name="J4" library="SparkFun-Connectors" library_urn="urn:adsk.eagle:library:513" package="1X01" package3d_urn="urn:adsk.eagle:package:38028/1" value="" x="1.9" y="6.1" smashed="yes">
<attribute name="NAME" x="0.63" y="7.497" size="0.6096" layer="25" font="vector" ratio="20" display="off"/>
<attribute name="VALUE" x="0.63" y="4.576" size="0.6096" layer="27" font="vector" ratio="20" align="top-left"/>
</element>
<element name="J5" library="SparkFun-Connectors" library_urn="urn:adsk.eagle:library:513" package="1X01" package3d_urn="urn:adsk.eagle:package:38028/1" value="" x="15.5" y="12.9" smashed="yes">
<attribute name="NAME" x="14.23" y="14.297" size="0.6096" layer="25" font="vector" ratio="20" display="off"/>
<attribute name="VALUE" x="14.23" y="11.376" size="0.6096" layer="27" font="vector" ratio="20" align="top-left"/>
</element>
</elements>
<signals>
<signal name="N$21">
<contactref element="J1" pad="TAB1"/>
<contactref element="J4" pad="1"/>
<wire x1="4.87" y1="9.12" x2="4.85" y2="9.1" width="0.1524" layer="1"/>
<wire x1="4.85" y1="9.1" x2="2.5" y2="9.1" width="0.1524" layer="1"/>
<wire x1="2.5" y1="9.1" x2="1.9" y2="8.5" width="0.1524" layer="1"/>
<wire x1="1.9" y1="8.5" x2="1.9" y2="6.1" width="0.1524" layer="1"/>
</signal>
<signal name="N$22">
<contactref element="J1" pad="TAB2"/>
<contactref element="J5" pad="1"/>
<wire x1="15.5" y1="12.9" x2="15.2934875" y2="12.97250625" width="0.1524" layer="1"/>
<wire x1="15.2934875" y1="12.97250625" x2="12.87" y2="9.12" width="0.1524" layer="1"/>
</signal>
<signal name="N$2">
<contactref element="J1" pad="3"/>
<contactref element="J3" pad="2"/>
<wire x1="7.12" y1="10.92" x2="7.12" y2="11.78" width="0.1524" layer="1"/>
<wire x1="6.3" y1="12.6" x2="3.8" y2="12.6" width="0.1524" layer="1"/>
<wire x1="3.8" y1="12.6" x2="3.3" y2="13.1" width="0.1524" layer="1"/>
<wire x1="3.3" y1="15.74" x2="2" y2="17.04" width="0.1524" layer="1"/>
<wire x1="7.12" y1="11.78" x2="6.3" y2="12.6" width="0.1524" layer="1"/>
<wire x1="3.3" y1="13.1" x2="3.3" y2="15.74" width="0.1524" layer="1"/>
</signal>
<signal name="N$3">
<contactref element="J1" pad="1"/>
<contactref element="J3" pad="1"/>
<wire x1="6.62" y1="10.92" x2="6.62" y2="11.28" width="0.1524" layer="1"/>
<wire x1="5.7" y1="12.2" x2="2.1" y2="12.2" width="0.1524" layer="1"/>
<wire x1="2.1" y1="12.2" x2="2" y2="12.3" width="0.1524" layer="1"/>
<wire x1="2" y1="12.3" x2="2" y2="14.5" width="0.1524" layer="1"/>
<wire x1="6.62" y1="11.28" x2="5.7" y2="12.2" width="0.1524" layer="1"/>
</signal>
<signal name="N$4">
<contactref element="J1" pad="5"/>
<contactref element="J3" pad="3"/>
<wire x1="7.62" y1="10.92" x2="7.62" y2="11.78" width="0.1524" layer="1"/>
<wire x1="7.62" y1="11.78" x2="6.4" y2="13" width="0.1524" layer="1"/>
<wire x1="6.4" y1="13" x2="5" y2="13" width="0.1524" layer="1"/>
<wire x1="5" y1="13" x2="4.54" y2="13.46" width="0.1524" layer="1"/>
<wire x1="4.54" y1="13.46" x2="4.54" y2="14.5" width="0.1524" layer="1"/>
</signal>
<signal name="N$5">
<contactref element="J1" pad="7"/>
<contactref element="J3" pad="4"/>
<wire x1="8.12" y1="10.92" x2="8.12" y2="11.78" width="0.1524" layer="1"/>
<wire x1="6.5952" y1="13.3048" x2="6.1" y2="13.3048" width="0.1524" layer="1"/>
<wire x1="6.1" y1="13.3048" x2="5.8" y2="13.6048" width="0.1524" layer="1"/>
<wire x1="5.8" y1="15.78" x2="4.54" y2="17.04" width="0.1524" layer="1"/>
<wire x1="8.12" y1="11.78" x2="6.5952" y2="13.3048" width="0.1524" layer="1"/>
<wire x1="5.8" y1="13.6048" x2="5.8" y2="15.78" width="0.1524" layer="1"/>
</signal>
<signal name="N$6">
<contactref element="J1" pad="9"/>
<contactref element="J3" pad="5"/>
<wire x1="8.62" y1="10.92" x2="8.62" y2="11.88" width="0.1524" layer="1"/>
<wire x1="7.08" y1="13.42" x2="7.08" y2="14.5" width="0.1524" layer="1"/>
<wire x1="8.62" y1="11.88" x2="7.08" y2="13.42" width="0.1524" layer="1"/>
</signal>
<signal name="N$7">
<contactref element="J1" pad="11"/>
<contactref element="J3" pad="6"/>
<wire x1="9.12" y1="10.92" x2="9.12" y2="12.08" width="0.1524" layer="1"/>
<wire x1="8.3" y1="15.82" x2="7.08" y2="17.04" width="0.1524" layer="1"/>
<wire x1="9.12" y1="12.08" x2="8.3" y2="12.9" width="0.1524" layer="1"/>
<wire x1="8.3" y1="12.9" x2="8.3" y2="15.82" width="0.1524" layer="1"/>
</signal>
<signal name="N$8">
<contactref element="J1" pad="13"/>
<contactref element="J3" pad="7"/>
<wire x1="9.62" y1="10.92" x2="9.62" y2="14.5" width="0.1524" layer="1"/>
</signal>
<signal name="N$9">
<contactref element="J1" pad="15"/>
<contactref element="J3" pad="8"/>
<wire x1="10.12" y1="10.92" x2="10.12" y2="13.02" width="0.1524" layer="1"/>
<wire x1="10.12" y1="13.02" x2="10.9" y2="13.8" width="0.1524" layer="1"/>
<wire x1="10.9" y1="13.8" x2="10.9" y2="15.4" width="0.1524" layer="1"/>
<wire x1="9.62" y1="16.68" x2="9.62" y2="17.04" width="0.1524" layer="1"/>
<wire x1="10.9" y1="15.4" x2="9.62" y2="16.68" width="0.1524" layer="1"/>
</signal>
<signal name="N$10">
<contactref element="J1" pad="17"/>
<contactref element="J3" pad="9"/>
<wire x1="10.62" y1="10.92" x2="10.62" y2="12.52" width="0.1524" layer="1"/>
<wire x1="12.16" y1="14.06" x2="12.16" y2="14.5" width="0.1524" layer="1"/>
<wire x1="10.62" y1="12.52" x2="12.16" y2="14.06" width="0.1524" layer="1"/>
</signal>
<signal name="N$1">
<contactref element="J1" pad="19"/>
<contactref element="J3" pad="10"/>
<wire x1="11.12" y1="10.92" x2="11.12" y2="12.02" width="0.1524" layer="1"/>
<wire x1="12" y1="12.9" x2="13.2" y2="12.9" width="0.1524" layer="1"/>
<wire x1="13.2" y1="12.9" x2="13.4" y2="13.1" width="0.1524" layer="1"/>
<wire x1="13.4" y1="15.8" x2="12.16" y2="17.04" width="0.1524" layer="1"/>
<wire x1="11.12" y1="12.02" x2="12" y2="12.9" width="0.1524" layer="1"/>
<wire x1="13.4" y1="13.1" x2="13.4" y2="15.8" width="0.1524" layer="1"/>
</signal>
<signal name="N$11">
<contactref element="J1" pad="2"/>
<contactref element="J2" pad="2"/>
<wire x1="6.62" y1="7.32" x2="6.62" y2="6.72" width="0.1524" layer="1"/>
<wire x1="6.62" y1="6.72" x2="5.3" y2="5.4" width="0.1524" layer="1"/>
<wire x1="5.3" y1="5.4" x2="5.3" y2="4.59" width="0.1524" layer="1"/>
<wire x1="5.3" y1="4.59" x2="5.35" y2="4.44" width="0.1524" layer="1"/>
</signal>
<signal name="N$12">
<contactref element="J1" pad="4"/>
<contactref element="J2" pad="1"/>
<wire x1="5.35" y1="1.9" x2="5.35" y2="2.65" width="0.1524" layer="1"/>
<wire x1="7.12" y1="6.42" x2="7.12" y2="7.32" width="0.1524" layer="1"/>
<wire x1="5.35" y1="2.65" x2="6.7" y2="4" width="0.1524" layer="1"/>
<wire x1="6.7" y1="4" x2="6.7" y2="6" width="0.1524" layer="1"/>
<wire x1="6.7" y1="6" x2="7.12" y2="6.42" width="0.1524" layer="1"/>
</signal>
<signal name="N$13">
<contactref element="J1" pad="6"/>
<contactref element="J2" pad="4"/>
<wire x1="7.89" y1="4.44" x2="7.89" y2="5.41" width="0.1524" layer="1"/>
<wire x1="7.62" y1="5.68" x2="7.62" y2="7.32" width="0.1524" layer="1"/>
<wire x1="7.89" y1="5.41" x2="7.62" y2="5.68" width="0.1524" layer="1"/>
</signal>
<signal name="N$14">
<contactref element="J1" pad="8"/>
<contactref element="J2" pad="3"/>
<wire x1="7.89" y1="1.9" x2="9.2" y2="3.31" width="0.1524" layer="1"/>
<wire x1="9.2" y1="3.31" x2="9.2" y2="5" width="0.1524" layer="1"/>
<wire x1="8.12" y1="6.08" x2="8.12" y2="7.32" width="0.1524" layer="1"/>
<wire x1="9.2" y1="5" x2="8.12" y2="6.08" width="0.1524" layer="1"/>
</signal>
<signal name="N$15">
<contactref element="J1" pad="10"/>
<contactref element="J2" pad="6"/>
<wire x1="10.43" y1="4.44" x2="8.62" y2="6.35" width="0.1524" layer="1"/>
<wire x1="8.62" y1="6.35" x2="8.62" y2="7.32" width="0.1524" layer="1"/>
</signal>
<signal name="N$16">
<contactref element="J1" pad="12"/>
<contactref element="J2" pad="5"/>
<wire x1="10.43" y1="1.9" x2="10.43" y2="2.63" width="0.1524" layer="1"/>
<wire x1="10.43" y1="2.63" x2="11.8" y2="4" width="0.1524" layer="1"/>
<wire x1="11.8" y1="4" x2="11.8" y2="4.82236875" width="0.1524" layer="1"/>
<wire x1="11.8" y1="4.82236875" x2="11.01396875" y2="5.6084" width="0.1524" layer="1"/>
<wire x1="9.12" y1="6.28105625" x2="9.12" y2="7.32" width="0.1524" layer="1"/>
<wire x1="11.01396875" y1="5.6084" x2="9.79265625" y2="5.6084" width="0.1524" layer="1"/>
<wire x1="9.79265625" y1="5.6084" x2="9.12" y2="6.28105625" width="0.1524" layer="1"/>
</signal>
<signal name="N$17">
<contactref element="J1" pad="14"/>
<contactref element="J2" pad="8"/>
<wire x1="9.62" y1="7.32" x2="9.62" y2="6.2932" width="0.1524" layer="1"/>
<wire x1="9.62" y1="6.2932" x2="10" y2="5.9132" width="0.1524" layer="1"/>
<wire x1="10" y1="5.9132" x2="11.140225" y2="5.9132" width="0.1524" layer="1"/>
<wire x1="12.513425" y1="4.54" x2="12.97" y2="4.44" width="0.1524" layer="1"/>
<wire x1="11.140225" y1="5.9132" x2="12.513425" y2="4.54" width="0.1524" layer="1"/>
</signal>
<signal name="N$18">
<contactref element="J1" pad="16"/>
<contactref element="J2" pad="7"/>
<wire x1="10.12" y1="7.32" x2="10.12" y2="6.38" width="0.1524" layer="1"/>
<wire x1="10.282" y1="6.218" x2="13.782" y2="6.218" width="0.1524" layer="1"/>
<wire x1="13.782" y1="6.218" x2="14.2" y2="5.8" width="0.1524" layer="1"/>
<wire x1="14.2" y1="3.13" x2="12.97" y2="1.9" width="0.1524" layer="1"/>
<wire x1="10.12" y1="6.38" x2="10.282" y2="6.218" width="0.1524" layer="1"/>
<wire x1="14.2" y1="5.8" x2="14.2" y2="3.13" width="0.1524" layer="1"/>
</signal>
<signal name="N$19">
<contactref element="J1" pad="18"/>
<contactref element="J2" pad="10"/>
<wire x1="10.62" y1="7.32" x2="10.62" y2="8.62" width="0.1524" layer="1"/>
<wire x1="10.8" y1="8.8" x2="11.6" y2="8.8" width="0.1524" layer="1"/>
<wire x1="11.6" y1="8.8" x2="11.9" y2="8.5" width="0.1524" layer="1"/>
<wire x1="11.9" y1="8.5" x2="11.9" y2="8" width="0.1524" layer="1"/>
<wire x1="11.9" y1="8" x2="12" y2="7.9" width="0.1524" layer="1"/>
<wire x1="12" y1="7.9" x2="14.8" y2="7.9" width="0.1524" layer="1"/>
<via x="14.8" y="7.9" extent="1-16" drill="0.35"/>
<wire x1="14.8" y1="7.9" x2="15.51" y2="7.19" width="0.1524" layer="16"/>
<wire x1="15.51" y1="7.19" x2="15.51" y2="4.44" width="0.1524" layer="16"/>
<wire x1="10.62" y1="8.62" x2="10.8" y2="8.8" width="0.1524" layer="1"/>
</signal>
<signal name="N$20">
<contactref element="J1" pad="20"/>
<contactref element="J2" pad="9"/>
<wire x1="15.51" y1="1.9" x2="16.8" y2="3.276578125" width="0.1524" layer="1"/>
<wire x1="16.8" y1="3.276578125" x2="16.8" y2="7" width="0.1524" layer="1"/>
<wire x1="16.8" y1="7" x2="16.48" y2="7.32" width="0.1524" layer="1"/>
<wire x1="16.48" y1="7.32" x2="11.12" y2="7.32" width="0.1524" layer="1"/>
</signal>
</signals>
<mfgpreviewcolors>
<mfgpreviewcolor name="soldermaskcolor" color="0xC8008000"/>
<mfgpreviewcolor name="silkscreencolor" color="0xFFFEFEFE"/>
<mfgpreviewcolor name="backgroundcolor" color="0xFF282828"/>
<mfgpreviewcolor name="coppercolor" color="0xFFFFBF00"/>
<mfgpreviewcolor name="substratecolor" color="0xFF786E46"/>
</mfgpreviewcolors>
</board>
</drawing>
<compatibility>
<note version="6.3" minversion="6.2.2" severity="warning">
Since Version 6.2.2 text objects can contain more than one line,
which will not be processed correctly with this version.
</note>
<note version="8.2" severity="warning">
Since Version 8.2, EAGLE supports online libraries. The ids
of those online libraries will not be understood (or retained)
with this version.
</note>
<note version="8.3" severity="warning">
Since Version 8.3, EAGLE supports URNs for individual library
assets (packages, symbols, and devices). The URNs of those assets
will not be understood (or retained) with this version.
</note>
<note version="8.3" severity="warning">
Since Version 8.3, EAGLE supports the association of 3D packages
with devices in libraries, schematics, and board files. Those 3D
packages will not be understood (or retained) with this version.
</note>
</compatibility>
</eagle>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,94 @@
cntrl-l 10 22
cntrl-r 26 22
shift-l 30 21
shift-r 26 21
alt-l 32 1
alt-r 24 1
gui
fn
a 28 20
b 29 24
c 27 26
d 28 27
e 11 27
f 29 28
g 32 29
h 33 32
i 8 11
j 33 28
k 8 28
l 7 28
m 33 26
n 33 24
o 7 11
p 11 6
q 11 20
r 11 29
s 28 25
t 30 29
u 33 11
v 29 26
w 11 25
x 26 25
y 33 30
z 26 20
` 10 20
1 12 20
2 12 25
3 12 27
4 29 12
5 10 29
6 33 10
7 33 12
8 8 12
9 7 12
0 6 12
- 10 6
= 8 10
bckspace 31 30
esc 32 20
f1 10 25
f2 10 27
f3 30 27
f4 32 27
f5 32 31
f6 32 8
f7 30 7
f8 10 7
f9 10 31
f10 31 12
f11 12 5
f12 12 4
insert 10 4
delete 10 5
home 10 2
pg-up 10 3
pg-dn 12 3
end 12 2
arrow-r 24 4
arrow-l 24 2
arrow-u 32 2
arrow-d 5 24
menu
/ 6 24
period 7 26
comma 8 26
; 28 6
' 32 6
enter 31 26
[ 30 6
] 8 30
\ 31 28
caps-lck 30 25
tab 30 20
space 31 24
prt-sc 12 1
screen-lk 11 1
pause 26 2
access IBM 32 5
vol down 30 5
vol up 11 5
mute 28 5
page left 26 3
page right 24 3

View file

@ -21,10 +21,15 @@
// Initial Release Aug 2, 2022 // Initial Release Aug 2, 2022
// //
#define MODIFIERKEY_FN 0x8f // give Fn key a HID code #define MODIFIERKEY_FN 0x8f // give Fn key a HID code
#define CAPS_LED 13 // Teensy LED shows Caps-Lock #define CAPS_LED 13 // Teensy LED shows Caps-Lock
#define NUM_LOCK_LED 14 // Teensy pin 14 for Num-Lock
#define SCROLL_LOCK_LED 15 // Teensy pin 15 for Scroll-Lock
#define USB_CAPS_LOCK 1
#define USB_NUM_LOCK 0
#define USB_SCROLL_LOCK 2
const byte rows_max = 16; // sets the number of rows in the matrix 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 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 // 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. // A zero indicates no normal key at that location.
@ -38,12 +43,12 @@ int normal[rows_max][cols_max] = {
{KEY_T,KEY_B,KEY_V,KEY_F,KEY_4,KEY_R,KEY_5,KEY_G}, {KEY_T,KEY_B,KEY_V,KEY_F,KEY_4,KEY_R,KEY_5,KEY_G},
{KEY_LEFT_BRACE,KEY_SLASH,KEY_BACKSLASH,KEY_SEMICOLON,KEY_0,KEY_P,KEY_MINUS,KEY_QUOTE}, {KEY_LEFT_BRACE,KEY_SLASH,KEY_BACKSLASH,KEY_SEMICOLON,KEY_0,KEY_P,KEY_MINUS,KEY_QUOTE},
{0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0},
{KEYPAD_5,0,KEYPAD_9,KEYPAD_7,0,0,KEYPAD_4,0}, {KEYPAD_5,0,KEYPAD_9,KEYPAD_7,KEY_PRINTSCREEN,0,KEYPAD_4,0},
{KEYPAD_2,KEY_RIGHT,KEYPAD_6,KEYPAD_1,KEY_F12,KEYPAD_3,KEY_INSERT,KEYPAD_PLUS}, {KEYPAD_2,KEY_RIGHT,KEYPAD_6,KEYPAD_1,KEY_F12,KEYPAD_3,KEY_INSERT,KEYPAD_PLUS},
{0,KEY_DOWN,KEYPAD_ASTERIX,0,KEY_F11,0,KEY_DELETE,0}, {0,KEY_DOWN,KEYPAD_ASTERIX,0,KEY_F11,0,KEY_DELETE,0},
{KEYPAD_8,0,0,KEY_MENU,KEY_PAGE_DOWN,0,KEY_PAGE_UP,KEYPAD_SLASH}, {KEYPAD_8,0,0,KEY_MENU,KEY_PAGE_DOWN,0,KEY_PAGE_UP,KEYPAD_SLASH},
{KEY_BACKSPACE,KEY_SPACE,KEY_ENTER,0,KEY_F10,0,KEY_F9,KEY_F5}, {KEY_BACKSPACE,KEY_SPACE,KEY_ENTER,0,KEY_F10,0,KEY_F9,KEY_F5},
{KEYPAD_0,KEY_LEFT,0,0,0,KEYPAD_ENTER,0,KEY_UP}, {KEYPAD_0,KEY_LEFT,KEY_PAUSE,0,0,KEYPAD_ENTER,0,KEY_UP},
{KEY_RIGHT_BRACE,0,KEY_COMMA,KEY_K,KEY_8,KEY_I,KEY_EQUAL,KEY_F6}, {KEY_RIGHT_BRACE,0,KEY_COMMA,KEY_K,KEY_8,KEY_I,KEY_EQUAL,KEY_F6},
{KEY_F7,0,KEY_PERIOD,KEY_L,KEY_9,KEY_O,KEY_F8,0} {KEY_F7,0,KEY_PERIOD,KEY_L,KEY_9,KEY_O,KEY_F8,0}
}; };
@ -80,7 +85,7 @@ 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,KEY_MEDIA_VOLUME_INC,0,0,KEY_MEDIA_FAST_FORWARD,0,0,0}, {0,KEY_MEDIA_VOLUME_INC,0,0,KEY_MEDIA_FAST_FORWARD,0,0,0},
{0,0,0,0,KEY_MEDIA_REWIND,0,0,0}, {0,0,0,0,KEY_MEDIA_REWIND,0,KEY_SCROLL_LOCK,0},
{0,0,0,0,KEY_END,0,KEY_HOME,0}, {0,0,0,0,KEY_END,0,KEY_HOME,0},
{0,0,0,0,KEY_MEDIA_STOP,0,KEY_MEDIA_PLAY_PAUSE,0}, {0,0,0,0,KEY_MEDIA_STOP,0,KEY_MEDIA_PLAY_PAUSE,0},
{0,KEY_MEDIA_VOLUME_DEC,0,0,0,0,0,0}, {0,KEY_MEDIA_VOLUME_DEC,0,0,0,0,0,0},
@ -372,12 +377,22 @@ void loop() {
// //
// Turn on the LED on the Teensy for Caps Lock based on bit 1 in the keyboard_leds variable controlled by the USB host computer // Turn on the LED on the Teensy for Caps Lock based on bit 1 in the keyboard_leds variable controlled by the USB host computer
// //
if (keyboard_leds & 1<<1) { // mask off all bits but D1 and test if set if (keyboard_leds & 1<<USB_CAPS_LOCK) { // mask off all bits but D1 and test if set
go_1(CAPS_LED); // turn on the LED go_1(CAPS_LED); // turn on the LED
} }
else { else {
go_0(CAPS_LED); // turn off the LED go_0(CAPS_LED); // turn off the LED
} }
if(keyboard_leds & 1<<USB_NUM_LOCK) { // mask off all bits but D0 and test if set
go_1(NUM_LOCK_LED);
}else{
go_0(NUM_LOCK_LED);
}
if(keyboard_leds & 1<<USB_SCROLL_LOCK) { // mask off all bits but D2 and test if set
go_1(SCROLL_LOCK_LED);
}else {
go_0(SCROLL_LOCK_LED);
}
// //
delay(25); // The overall keyboard scanning rate is about 30ms delay(25); // The overall keyboard scanning rate is about 30ms
} }

View file

@ -0,0 +1,960 @@
/* Copyright 2022 Frank Adams
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This software creates a USB keyboard and touchpad.
// The touchpad is PS/2 and the code uses "stream mode" instead of "remote mode".
//
// define the pins on the Teensy used for the touchpad ps2 bus
#define TP_DATA 11 // Touchpad ps/2 data connected to Teensy I/O pin
#define TP_CLK 12 // Touchpad ps/2 clock connected to Teensy I/O pin
#define CAPS_LOCK_N 8 // driven low to turn on the CAPS LED
#define NUM_LOCK_N 13 // driven low to turn on the NUM LED (Note the LED on the Teensy 3.2 is also connected to this I/O and has opposite polarity)
//
#define MODIFIERKEY_FN 0x8f // give the Fn key a HID code so it can be handled like any other key
//
const byte rows_max = 15; // sets the number of rows in the keyboard matrix
const byte cols_max = 8; // sets the number of columns in the keyboard 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_END,KEY_RIGHT,0,KEY_PRINTSCREEN,KEY_DELETE,KEY_HOME,KEY_PAGE_UP,KEY_PAGE_DOWN},
{KEY_QUOTE,KEY_ENTER,KEY_PAUSE,0,KEY_EQUAL,KEY_BACKSPACE,KEY_RIGHT_BRACE,KEY_BACKSLASH},
{KEY_SLASH,KEY_UP,KEY_MINUS,KEY_F12,KEY_0,KEY_P,KEY_LEFT_BRACE,KEY_SEMICOLON},
{0,0,0,0,0,0,0,0},
{0,0,KEY_F8,KEY_F9,0,0,KEY_MENU,KEY_LEFT},
{KEY_COMMA,KEY_INSERT,KEY_F7,KEY_F6,KEY_F5,KEY_8,KEY_I,KEY_K},
{0,0,0,0,0,0,0,0},
{KEY_PERIOD,KEY_DOWN,0,KEY_F11,KEY_F10,KEY_9,KEY_O,KEY_L},
{KEY_M,KEY_N,KEY_H,KEY_Y,KEY_6,KEY_7,KEY_U,KEY_J},
{KEY_V,KEY_B,KEY_G,KEY_T,KEY_5,KEY_4,KEY_R,KEY_F},
{KEY_X,KEY_Z,KEY_F2,KEY_F1,KEY_ESC,KEY_2,KEY_W,KEY_S},
{KEY_C,KEY_SPACE,KEY_F3,KEY_F4,KEY_CAPS_LOCK,KEY_3,KEY_E,KEY_D},
{0,0,0,0,0,0,0,0},
{0,0,0,KEY_TAB,KEY_TILDE,KEY_1,KEY_Q,KEY_A},
{0,0,0,0,0,0,0,0}
};
// Load the numlock key matrix with key names at the correct row-column location.
// This matrix is the same as the normal matrix except for the number pad keys
// A zero indicates no numlock key at that location.
int numlock[rows_max][cols_max] = {
{KEY_END,KEY_RIGHT,0,KEY_PRINTSCREEN,KEY_DELETE,KEY_HOME,KEY_PAGE_UP,KEY_PAGE_DOWN},
{KEY_QUOTE,KEY_ENTER,KEY_PAUSE,0,KEY_EQUAL,KEY_BACKSPACE,KEY_RIGHT_BRACE,KEY_BACKSLASH},
{KEYPAD_SLASH,KEY_UP,KEY_MINUS,KEY_F12,KEYPAD_ASTERIX,KEYPAD_MINUS,KEY_LEFT_BRACE,KEYPAD_PLUS},
{0,0,0,0,0,0,0,0},
{0,0,KEY_F8,KEY_F9,0,0,KEY_MENU,KEY_LEFT},
{KEY_COMMA,KEY_INSERT,KEY_F7,KEY_F6,KEY_F5,KEYPAD_8,KEYPAD_5,KEYPAD_2},
{0,0,0,0,0,0,0,0},
{KEYPAD_PERIOD,KEY_DOWN,0,KEY_F11,KEY_F10,KEYPAD_9,KEYPAD_6,KEYPAD_3},
{KEYPAD_0,KEY_N,KEY_H,KEY_Y,KEY_6,KEYPAD_7,KEYPAD_4,KEYPAD_1},
{KEY_V,KEY_B,KEY_G,KEY_T,KEY_5,KEY_4,KEY_R,KEY_F},
{KEY_X,KEY_Z,KEY_F2,KEY_F1,KEY_ESC,KEY_2,KEY_W,KEY_S},
{KEY_C,KEY_SPACE,KEY_F3,KEY_F4,KEY_CAPS_LOCK,KEY_3,KEY_E,KEY_D},
{0,0,0,0,0,0,0,0},
{0,0,0,KEY_TAB,KEY_TILDE,KEY_1,KEY_Q,KEY_A},
{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,MODIFIERKEY_LEFT_CTRL,0,0,MODIFIERKEY_RIGHT_CTRL,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{MODIFIERKEY_RIGHT_SHIFT,MODIFIERKEY_LEFT_SHIFT,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_RIGHT_ALT,MODIFIERKEY_LEFT_ALT,0,0,0,0,0,0},
{0,0,MODIFIERKEY_FN,0,0,0,0,0},
{0,MODIFIERKEY_GUI,0,0,0,0,0,0}
};
// Load the media key matrix with Fn 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,KEY_SCROLL_LOCK,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_NUM_LOCK,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,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,KEY_MEDIA_VOLUME_DEC,KEY_MEDIA_VOLUME_INC,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 (no keys pressed).
// 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}
};
//
// Define the Teensy 3.2 I/O numbers that are connected to the keyboard FPC connector pins
// Row FPC pin # 09,10,11,12,13,14,15,16,17,18,19,20,21,22,23
// Teensy I/O # 18,33,19,20,21,22,23,24,25,26,27,28,07,06,05
int Row_IO[rows_max] = {18,33,19,20,21,22,23,24,25,26,27,28,7,6,5}; // Teensy 3.2 I/O numbers for rows 0 thru 14
//
// Column FPC pin # 01,02,03,04,05,06,07,08
// Teensy I/O # 14,29,15,30,16,31,17,32
int Col_IO[cols_max] = {14,29,15,30,16,31,17,32}; // Teensy 3.2 I/O numbers for columns 0 thru 7
//
// Declare global variables that will be used by functions
//
boolean slots_full = LOW; // Goes high when USB slots 1 thru 6 contain normal keys
boolean touchpad_error = LOW; // set high if the touchpad fails to give the correct power-up response
char mstat; // touchpad status 8 bit register = Y overflow, X overflow, Y sign bit, X sign bit, Always 1, Middle Btn, Right Btn, Left Btn
char mx; // touchpad 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 touchpad gives a positive value.
char my; // touchpad y movement also 8 bits plus sign bit in status reg. Touchpad movement away from the user gives a positive value.
//
// 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;
//
// ********************Common Functions**********************************************
//
// 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);
}
//
// ********************Functions for keyboard scanning*******************************
//
// Function to load the key name into the first available slot
void load_slot(int key) {
if (!slot1) { // check if slot 1 is empty
slot1 = key; // and load it with the key name
}
else if (!slot2) { // otherwise go thru all the other slots looking for an empty to load
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) { // are any slots empty?
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) { // check if slot 1 contains the key that needs to be cleared
slot1 = 0; // and clear it
}
else if (slot2 == key) { // otherwise keep checking the other slots for a match
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;
}
if (!slot1 || !slot2 || !slot3 || !slot4 || !slot5 || !slot6) { // are any slots empty?
slots_full = LOW; // slots are not full
}
else {
slots_full = HIGH; // slots are full
}
}
//
// Function to load the modifier key name into the appropriate mod variable
void load_mod(int m_key) {
if (m_key == MODIFIERKEY_LEFT_SHIFT) { // Figure out which modifier key was pushed
mod_shift_l = m_key; // and load it into 1 of 7 possible variables
}
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) { // Figure out which modifier key was released
mod_shift_l = 0; // and clear the matching variable
}
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(); // sends all modifier values including the one that just changed (and all normal slots)
}
//
// Function to send the normal keys in the 6 slots over usb
void send_normals() {
Keyboard.set_key1(slot1); // load each slot into the cooresponding key number
Keyboard.set_key2(slot2);
Keyboard.set_key3(slot3);
Keyboard.set_key4(slot4);
Keyboard.set_key5(slot5);
Keyboard.set_key6(slot6);
Keyboard.send_now(); // sends all slots including the one that just changed (and all modifier values)
}
//
// *****************Functions for Touchpad***************************
//
// Function to send the touchpad a byte of data (command)
//
void tp_write(char send_data)
{
unsigned int timeout = 200; // break out of loop if watchdog over this value in msec
elapsedMillis watchdog; // zero the watchdog timer clock
char odd_parity = 0; // clear parity bit count
// Enable the PS/2 bus by floating the clock and data
go_pu(TP_CLK); //
go_pu(TP_DATA); //
delayMicroseconds(250); // wait before requesting the bus
go_0(TP_CLK); // Send the Clock line low to request to transmit data
delayMicroseconds(100); // wait for 100 microseconds per bus spec
go_0(TP_DATA); // Send the Data line low (the start bit)
delayMicroseconds(1); //
go_pu(TP_CLK); // Release the Clock line so it is pulled high
delayMicroseconds(1); // give some time to let the clock line go high
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop because tp did not respond
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
// send the 8 bits of send_data
for (int j=0; j<8; j++) {
if (send_data & 1) { //check if lsb is set
go_pu(TP_DATA); // send a 1 to TP
odd_parity = odd_parity + 1; // keep running total of 1's sent
}
else {
go_0(TP_DATA); // send a 0 to TP
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
send_data = send_data >> 1; // shift data right by 1 to prepare for next loop
}
// send the parity bit
if (odd_parity & 1) { //check if lsb of parity is set
go_0(TP_DATA); // already odd so send a 0 to TP
}
else {
go_pu(TP_DATA); // send a 1 to TP to make parity odd
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
go_pu(TP_DATA); // Release the Data line so it goes high as the stop bit
delayMicroseconds(80); // testing shows delay at least 40us
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
delayMicroseconds(1); // wait to let the data settle
if (digitalRead(TP_DATA)) { // Ack bit s/b low if good transfer
}
while ((digitalRead(TP_CLK) == LOW) || (digitalRead(TP_DATA) == LOW)) { // loop if clock or data are low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
// Inhibit the bus so the tp only talks when the Teensy is listening
go_0(TP_CLK);
}
//
// Function to get a byte of data from the touchpad
//
char tp_read(void)
{
unsigned int timeout = 200; // break out of loop if over this value in msec
elapsedMillis watchdog; // zero the watchdog timer clock
char rcv_data = 0; // initialize to zero
char mask = 1; // shift a 1 across the 8 bits to select where to load the data
char rcv_parity = 0; // count the ones received
go_pu(TP_CLK); // release the clock
go_pu(TP_DATA); // release the data
delayMicroseconds(5); // delay to let clock go high
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
if (digitalRead(TP_DATA)) { // Start bit s/b low from tp
// start bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
for (int k=0; k<8; k++) {
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
if (digitalRead(TP_DATA)) { // check if data is high
rcv_data = rcv_data | mask; // set the appropriate bit in the rcv data
rcv_parity++; // increment the parity bit counter
}
mask = mask << 1;
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
}
// receive parity
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
if (digitalRead(TP_DATA)) { // check if received parity is high
rcv_parity++; // increment the parity bit counter
}
rcv_parity = rcv_parity & 1; // mask off all bits except the lsb
if (rcv_parity == 0) { // check for bad (even) parity
touchpad_error = HIGH;
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
// stop bit
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
if (digitalRead(TP_DATA) == LOW) { // check if stop bit is bad (low)
// send bad stop bit to future error handler
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
if (watchdog >= timeout) { //check for infinite loop
touchpad_error = HIGH;
break; // break out of infinite loop
}
}
// Inhibit the bus so the tp only talks when the Teensy is listening
go_0(TP_CLK);
return rcv_data; // pass the received data back
}
//
// Function to decode 3 bytes of data from the touchpad = status, X Delta, Y Delta
//
char tp_packet(void)
{
// ******************************Receive Byte 0 = Status***********************
char rcv_data = 0; // initialize to zero
char mask = 1; // shift a 1 across the 8 bits to select where to load the data
char rcv_parity = 0; // count the ones received
//
unsigned int time_leftover = 24; // breakout of tp loop if timer is over this value in msec
elapsedMillis tp_timer; // zero the tp timer clock
//
go_pu(TP_CLK); // release the clock
go_pu(TP_DATA); // release the data
delayMicroseconds(5); // delay to let clock go high
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
if (tp_timer >= time_leftover) { //check if ready for next keyboard scan due to no tp activity
go_0(TP_CLK); // Inhibit the bus so the tp won't try to send data
return 1; // go back to main routine with a 1 signifying no tp data was received
}
}
if (digitalRead(TP_DATA)) { // Start bit s/b low from tp
// start bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
for (int k=0; k<8; k++) {
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // check if data is high
rcv_data = rcv_data | mask; // set the appropriate bit in the rcv data
rcv_parity++; // increment the parity bit counter
}
mask = mask << 1;
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
}
// receive parity
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // check if received parity is high
rcv_parity++; // increment the parity bit counter
}
rcv_parity = rcv_parity & 1; // mask off all bits except the lsb
if (rcv_parity == 0) { // check for bad (even) parity
// parity bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
// stop bit
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA) == LOW) { // check if stop bit is bad (low)
// stop bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
mstat = rcv_data; // save data result in status byte
// ******************************Receive Byte 1 = Delta X**************************
rcv_data = 0; // initialize to zero
mask = 1; // shift a 1 across the 8 bits to select where to load the data
rcv_parity = 0; // count the ones received
delayMicroseconds(5); // delay to let the clock stop ringing
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // Start bit s/b low from tp
// start bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
for (int k=0; k<8; k++) {
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // check if data is high
rcv_data = rcv_data | mask; // set the appropriate bit in the rcv data
rcv_parity++; // increment the parity bit counter
}
mask = mask << 1;
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
}
// receive parity
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // check if received parity is high
rcv_parity++; // increment the parity bit counter
}
rcv_parity = rcv_parity & 1; // mask off all bits except the lsb
if (rcv_parity == 0) { // check for bad (even) parity
// parity bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
// stop bit
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA) == LOW) { // check if stop bit is bad (low)
// stop bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
mx = rcv_data; // save data result in delta x byte
// Receive Byte 1 = Delta Y
// ******************************Receive Byte 2 = Delta Y**************************
rcv_data = 0; // initialize to zero
mask = 1; // shift a 1 across the 8 bits to select where to load the data
rcv_parity = 0; // count the ones received
delayMicroseconds(5); // delay to let the clock stop ringing
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // Start bit s/b low from tp
// start bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
for (int k=0; k<8; k++) {
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // check if data is high
rcv_data = rcv_data | mask; // set the appropriate bit in the rcv data
rcv_parity++; // increment the parity bit counter
}
mask = mask << 1;
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
}
// receive parity
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA)) { // check if received parity is high
rcv_parity++; // increment the parity bit counter
}
rcv_parity = rcv_parity & 1; // mask off all bits except the lsb
if (rcv_parity == 0) { // check for bad (even) parity
// parity bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
// stop bit
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == HIGH) { // loop until the clock goes low
}
if (digitalRead(TP_DATA) == LOW) { // check if stop bit is bad (low)
// stop bit not correct - put error handler here if desired
}
delayMicroseconds(1); // delay to let the clock settle out
while (digitalRead(TP_CLK) == LOW) { // loop until the clock goes high
}
my = rcv_data; // save data result in delta y byte
//
// Inhibit the bus so the tp only talks when we're listening
go_0(TP_CLK);
return 0;
}
//
void touchpad_init()
{
touchpad_error = LOW; // start with no error
go_pu(TP_CLK); // float the clock and data to touchpad
go_pu(TP_DATA);
// Sending reset command to touchpad
tp_write(0xff);
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
delay(1000); // wait 1 second so tp can run its self diagnostic
// verify proper response from tp
if (tp_read() != 0xaa) { // verify basic assurance test passed
touchpad_error = HIGH;
}
if (tp_read() != 0x00) { // verify basic assurance test passed
touchpad_error = HIGH;
}
// Send touchpad disable code so that the mode byte can be loaded next
tp_write(0xf5); // tp disable
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// Load Mode Byte with 00 using the following special sequence from page 38 of Synaptics Interfaceing Guide.
// Send set resolution to 0 four times followed by a set sample rate to 0x14
// The resolution and sample rate are not actually changed but instead it loads the mode byte.
// #1 set resolution
tp_write(0xe8); // set resolution (actually part of setting mode byte)
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x00); // to zero
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// #2 set resolution (actually part of setting mode byte)
tp_write(0xe8); // set resolution
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x00); // to zero
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// #3 set resolution
tp_write(0xe8); // set resolution
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x00); // to zero
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// #4 set resolution (actually part of setting mode byte)
tp_write(0xe8); // set resolution
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x00); // to zero
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// Set sample rate (actually part of setting mode byte)
tp_write(0xf3); // set sample rate
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x14); // to 14 hex
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// This completes the mode byte load
// set the resolution for real
tp_write(0xe8); // Sending resolution command
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x03); // value of 0x03 = 8 counts/mm resolution (default is 4 counts/mm)
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// set the sample rate for real
tp_write(0xf3); // Sending sample rate command
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
tp_write(0x28); // 0x28 = 40 samples per second, the default value used for Synaptics TP
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// Load stream mode command so tp will send data whenever it's available
tp_write(0xea); // stream mode
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
// Send touchpad enable code
tp_write(0xf4); // tp enable
if (tp_read() != 0xfa) { // verify correct ack byte
touchpad_error = HIGH;
}
}
//
//----------------------------------Setup before main loop-------------------------------------------
//
void setup() {
for (int a = 0; a < cols_max; a++) { // loop thru all keyboard 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 keyboard row pins
go_z(Row_IO[b]); // set each row pin as a floating output
}
touchpad_init(); // reset tp and check that self diagnostic passed. Put tp in stream mode and enable it
//
}
//
boolean Fn_pressed = HIGH; // Active low, shows when the Fn key is pressed
extern volatile uint8_t keyboard_leds; // 8 bits sent from Host to Teensy that give keyboard LED status.
// declare and initialize touchpad variables
boolean over_flow; // Active high, set if x or y movement values are bad due to overflow
boolean left_button = 0; // Active high, on/off variable for left button is set if bit 0 of mstat is set
boolean right_button = 0; // Active high, on/off variable for right button is set if bit 1 of mstat is set
boolean old_left_button = 0; // Active high, on/off variable for left button status from the previous polling cycle
boolean old_right_button = 0; // Active high, on/off variable for right button status from the previous polling cycle
boolean button_change = 0; // Active high, shows when a touchpad left or right button has changed since the last polling cycle
//
//---------------------------------Main Loop---------------------------------------------
//
void loop() {
// 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 including the Fn special case
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
if (modifier[x][y] != MODIFIERKEY_FN) { // Exclude Fn modifier key because Fn is not sent to USB host
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 { // keep track of Fn key being pressed
Fn_pressed = LOW; // Fn status variable is active low
old_key[x][y] = LOW; // old_key state is "pressed" (active low)
}
}
else if (digitalRead(Col_IO[y]) && (!old_key[x][y])) { //check if key is not pressed and was previously pressed
if (modifier[x][y] != MODIFIERKEY_FN) { // Exclude Fn modifier key
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 was just released
old_key[x][y] = HIGH; // Save state of key as "not pressed"
}
else { // keep track of Fn key being released
Fn_pressed = HIGH; // Fn is no longer active
old_key[x][y] = HIGH; // old_key state is "not pressed"
}
}
}
// ***********end of modifier section
//
// ***********Normal keys, num lock, and media keys in this section
else if ((normal[x][y] != 0) || (media[x][y] != 0)) { // check if normal or media key exists at this location in the array
if (!digitalRead(Col_IO[y]) && (old_key[x][y]) && (!slots_full)) { // check if key pressed and not previously pressed and slots not full
old_key[x][y] = LOW; // Save state of key as "pressed"
if (Fn_pressed) { // Fn is not pressed and normal or num lock key needs to be sent
if (keyboard_leds & 1) { // test if Num Lock is turned on
load_slot(numlock[x][y]); //update first available slot with key name from numlock matrix
send_normals(); // send all slots over USB including the key that just got pressed
}
else { // Num Lock is not turned on so send normal key
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 (media[x][y] != 0) { // Fn is pressed so send media if a key exists in the matrix
Keyboard.press(media[x][y]); // media key is sent using keyboard.press function per PJRC instructions
delay(5); // delay 5 milliseconds before releasing to make sure it gets sent over USB
Keyboard.release(media[x][y]); // send media key release
}
}
// Key release
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 (Fn_pressed) { // only clear the slot if the Fn key is not pressed
if (keyboard_leds & 1) { // test if Num Lock is turned on
clear_slot(numlock[x][y]); //clear slot with key name from numlock matrix
send_normals(); // send all slots over USB including the key that just got released
}
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, media, and backlight section
//
} // end of column loop
go_z(Row_IO[x]); // De-activate the current Row (send it to hi-z) so the next row can be activated
} // end of row loop
//
// **********Keyboard scan complete
//
// ***********Touchpad Section
//
if (touchpad_error == LOW) { // Only proceed if the touchpad was initialized correctly and passed its self test
//
if (tp_packet() == 0x00) { // tp_packet returned zero so data was received in mstat, mx, and my variables
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 & 0x7f; // mask off 8th bit
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 & 0x7f; // mask off 8th bit
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 is set
if (over_flow) {
mx = 0x00; // data is bad due to the overflow 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);
}
//
// read the left and right button bits in the PS/2 status byte from the touchpad
if ((0x01 & mstat) == 0x01) { // if left button is set in the status byte
left_button = 1; // set the left button variable
}
else { // otherwise clear the left button variable
left_button = 0;
}
if ((0x02 & mstat) == 0x02) { // if right button is set in the status byte
right_button = 1; // set the right button variable
}
else { // otherwise clear right button variable
right_button = 0;
}
// Determine if the left or right touchpad buttons have changed since last polling cycle using xor
button_change = (left_button ^ old_left_button) | (right_button ^ old_right_button);
// Don't send button status if there's no change since last time.
if (button_change){
Mouse.set_buttons(left_button, 0, right_button); // send left, middle, and right button status
}
old_left_button = left_button; // remember button status for next polling cycle
old_right_button = right_button;
}
}
//
// End of touchpad routine
//
// Turn on or off the LEDs for Num Lock and Caps Lock based on bits 0 and 1 from the
// keyboard_leds variable returned by the host computer over USB. Sending the I/O pin low turns on the
// LED.
//
if (keyboard_leds & 1) { // mask off all bits but D0 and test if set
go_0(NUM_LOCK_N); // turn on the Num Lock LED
}
else {
go_1(NUM_LOCK_N); // turn off the Num Lock LED
}
//
//
if (keyboard_leds & 1<<1) { // mask off all bits but D1 and test if set
go_0(CAPS_LOCK_N); // turn on the Caps Lock LED
}
else {
go_1(CAPS_LOCK_N); // turn off the Caps Lock LED
}
//
// repeat loop at 30msec scan rate
}