Skip to content

Instantly share code, notes, and snippets.

@wjes
Last active April 13, 2023 03:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wjes/ed98ffea3f15ff1631a7fb25019d3f14 to your computer and use it in GitHub Desktop.
Save wjes/ed98ffea3f15ff1631a7fb25019d3f14 to your computer and use it in GitHub Desktop.
Teensy-LC code for a dell inspiron 1420 latam spanish keyboard
/* Copyright 2018 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 Dell Inspiron 1420 Laptop Keyboard Controller using a Teensy LC on
// a daughterboard with a 25 pin FPC connector. The keyboard part number is ONK769.
// This routine uses the Teensyduino "Press / Release" to send Normal, Modifier and Media
// keys over USB. The layout implemented is Latam Spanish.
// Description of Teensyduino keyboard functions is at www.pjrc.com/teensy/td_keyboard.html
//
// Revision History
// Initial Release June 11, 2019
//
//
#define MODIFIERKEY_FN 0x8f // give Fn key a HID code
#define CAPS_LED 13 // Teensy LED shows Caps-Lock
//
const byte rows_max = 17; // sets the number of rows in the matrix
const byte cols_max = 8; // sets the number of columns in the matrix
//
// Load the normal key matrix with the Teensyduino key names described at www.pjrc.com/teensy/td_keyboard.html
// A zero indicates no normal key at that location.
//
int normal[rows_max][cols_max] = {
{0,KEY_INSERT,0,KEY_F12,0,0,0,KEY_RIGHT},
{0,KEY_DELETE,0,KEY_F11,0,0,0,KEY_DOWN},
{KEY_UP,KEY_HOME,KEY_MENU,KEY_END,0,0,0,KEY_LEFT},
{0,KEY_F8,KEY_F7,'9','o','l','.',0},
{'{','\'',KEY_LEFT_BRACE,'0','p','ñ','}','-'},
{KEY_F6,'¿','+','8','i','k',',',0},
{'h','6','y','7','u','j','m','n'},
{KEY_F5,KEY_F9,KEY_BACKSPACE,KEY_F10,0,0,KEY_ENTER,KEY_SPACE},
{'g','5','t','4','r','f','v','b'},
{KEY_F4,KEY_F2,KEY_F3,'3','e','d','c',0},
{'<',KEY_F1,KEY_CAPS_LOCK,'2','w','s','x',0},
{KEY_ESC,'|',KEY_TAB,'1','q','a','z',0},
{0,0,0,KEY_PRINTSCREEN,KEY_NUM_LOCK,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_UP,KEY_PAGE_DOWN,0,0},
{0,0,0,0,0,0,0,0}
};
// Load the modifier key matrix with key names at the correct row-column location.
// A zero indicates no modifier key at that location.
int modifier[rows_max][cols_max] = {
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{MODIFIERKEY_LEFT_ALT,0,0,0,0,0,0,MODIFIERKEY_RIGHT_ALT},
{0,0,MODIFIERKEY_LEFT_SHIFT,0,0,0,MODIFIERKEY_RIGHT_SHIFT,0},
{0,MODIFIERKEY_LEFT_CTRL,0,0,0,0,MODIFIERKEY_RIGHT_CTRL,0},
{0,0,0,MODIFIERKEY_GUI,0,0,0,0},
{0,0,0,0,0,MODIFIERKEY_FN,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,KEY_PAUSE,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,'9','6','3','.',0},
{0,0,0,'/','*','-',0,'+'},
{0,0,0,'8','5','2',0,0},
{0,0,0,'7','4','1','0',0},
{0,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_SYSTEM_SLEEP,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,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.
// HIGH = key not pressed, LOW = key is pressed
boolean old_normal_key[rows_max][cols_max];
boolean old_media_key[rows_max][cols_max];
boolean old_modifier_key[rows_max][cols_max];
//
// Define the Teensy LC I/O numbers (translated from the FPC pin #)
// Row FPC pin # 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17
// Teensy I/O # 23,00,22,01,24,02,21,03,25,04,20,05,19,06,18,07,17
int Row_IO[rows_max] = {23,0,22,1,24,2,21,3,25,4,20,5,19,6,18,7,17}; // Teensy LC I/O numbers for rows
//
// Column FPC pin # 18,19,20,21,22,23,24,25
// Teensy I/O # 08,16,09,15,10,14,11,26
int Col_IO[cols_max] = {8,16,9,15,10,14,11,26}; // Teensy LC I/O numbers for columns
//
// 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++)
go_pu(Col_IO[a]); // set each column pin as an input with a pullup
for (int b = 0; b < rows_max; b++)
go_z(Row_IO[b]); // set each row pin as a floating output
for (int r = 0; r < rows_max; r++)
for (int c = 0; c < cols_max; c++)
old_normal_key[r][c] = old_media_key[r][c] = old_modifier_key[r][c] = HIGH;
}
//
boolean fn = HIGH; // Initialize Fn key to HIGH = "not pressed"
//uint16_t mod = 0; // Initialize the modifier keys (bitwise OR between all the modifier keys)
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 r = 0; r < rows_max; r++) {
go_0(Row_IO[r]); // Activate Row (send it low)
delayMicroseconds(10); // give the row time to go low and settle out
for (int c = 0; c < cols_max; c++) {
// Modifier keys
if (modifier[r][c]) {
if (!digitalRead(Col_IO[c]) && old_modifier_key[r][c] == HIGH) { // Key first press
if (modifier[r][c] != MODIFIERKEY_FN) {
Keyboard.press(modifier[r][c]);
//mod |= modifier[r][c];
//Keyboard.set_modifier(mod);
//Keyboard.send_now();
}
else fn = LOW;
old_modifier_key[r][c] = LOW;
}
else if (digitalRead(Col_IO[c]) && old_modifier_key[r][c] == LOW) { // Key release
if (modifier[r][c] != MODIFIERKEY_FN) {
Keyboard.release(modifier[r][c]);
//mod &= ~modifier[r][c] | 0xE000;
//Keyboard.set_modifier(mod);
//Keyboard.send_now();
}
else fn = HIGH;
old_modifier_key[r][c] = HIGH;
}
}
else {
// Normal keys
if (normal[r][c]) {
if (!digitalRead(Col_IO[c]) && old_normal_key[r][c] == HIGH) { // Key first press
if (fn == HIGH) Keyboard.press(normal[r][c]);
old_normal_key[r][c] = LOW;
}
else if (digitalRead(Col_IO[c]) && old_normal_key[r][c] == LOW) { // Key release
Keyboard.release(normal[r][c]);
old_normal_key[r][c] = HIGH;
}
}
// Media keys
if (media[r][c]) {
if (!digitalRead(Col_IO[c]) && old_media_key[r][c] == HIGH) { // Key first press
if (fn == LOW) Keyboard.press(media[r][c]);
old_media_key[r][c] = LOW;
}
else if (digitalRead(Col_IO[c]) && old_media_key[r][c] == LOW) { // Key release
Keyboard.release(media[r][c]);
old_media_key[r][c] = HIGH;
}
}
}
}
go_z(Row_IO[r]); // De-activate Row (send it to hi-z)
}
// Turn on the LED on the Teensy for Caps Lock
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
delay(5); // The overall keyboard scanning rate is about 30ms
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment