├── OrthoKey_12x4Key_3Layer ├── SetupPins.ino ├── Debug.ino ├── KeyHandlers.ino ├── OrthoKey_12x4Key_3Layer.ino ├── MatrixLoop.ino └── Keymap.ino └── README.md /OrthoKey_12x4Key_3Layer/SetupPins.ino: -------------------------------------------------------------------------------- 1 | void setupPins() { 2 | pinMode(delayLoopPin, INPUT_PULLUP); 3 | 4 | //Setup col pins 5 | for(int i=0; i 2 | 3 | ////Config variables 4 | //Matrix Setup 5 | const int LAYERS = 3; 6 | const int ROWS = 4; 7 | const int COLUMNS = 12; 8 | 9 | //Loop Delay 10 | int delayLoopPin = 21; 11 | 12 | //Input pins 13 | int ColPins[COLUMNS] = {21,20,19,18,17,22,5,4,3,2,1,0}; 14 | int RowPins[ROWS] = {12,13,9,10}; 15 | 16 | //Output debug info to serial monitor 17 | const bool EnableDebug = true; 18 | 19 | ////System Variables 20 | 21 | //Default Buttons 22 | const int NO_ACTION = 0; 23 | const int LAYER_RAISE = 1; 24 | const int LAYER_LOWER = 2; 25 | 26 | //Keymap 27 | bool switchStates[ROWS][COLUMNS]; 28 | int currentLayer = 1; //0 raised; 1 default; 2 lowered; 29 | 30 | 31 | void setup() 32 | { 33 | setupPins(); 34 | Serial.begin(9600); 35 | pinMode(11, OUTPUT); 36 | } 37 | 38 | void delayByPin() { 39 | //If delayPin becomes low (connected to ground) then delay loop 40 | //implemented to stop the chip from becoming stuck in a key spamming loop 41 | //Note: Can be removed if in need of the extra pin 42 | while (digitalRead(delayLoopPin) == LOW) 43 | { 44 | delay(8000); 45 | } 46 | } 47 | 48 | void loop() 49 | { 50 | delayByPin(); 51 | switchMatrixLoop(); 52 | delay(10); 53 | } 54 | -------------------------------------------------------------------------------- /OrthoKey_12x4Key_3Layer/MatrixLoop.ino: -------------------------------------------------------------------------------- 1 | void switchMatrixLoop() { 2 | //loop through columns, loop through rows and read outputs 3 | for(int row = 0; row < ROWS; row++) 4 | { 5 | digitalWrite(RowPins[row], LOW); //Power Low on column 6 | for(int column = 0; column < COLUMNS; column++) 7 | { 8 | //Pass inverted pin state of ColPin as row state because of INPUT_PULLUP 9 | //If the switch is pressed, this column should be pulled LOW by the column pin. 10 | //By inverting this a pressed key is 1 and a released key is 0. 11 | keyChangeCheck(!digitalRead(ColPins[column]), row, column); 12 | } 13 | digitalWrite(RowPins[row], HIGH); //Power back to High on Column 14 | } 15 | } 16 | 17 | void keyChangeCheck(bool currentState, int row, int column) 18 | { 19 | bool previousState = switchStates[row][column]; 20 | if(currentState == previousState) //Key is the same 21 | { 22 | //No change; 23 | } 24 | else if (currentState == HIGH) //Key is pressed 25 | { 26 | switchStates[row][column] = true; 27 | keyPressHandler(Keymap[currentLayer][row][column]); 28 | 29 | DebugPrintKeyState(); 30 | } 31 | else //Key is released 32 | { 33 | //Serial.println(String(Keymap[currentLayer][row][column]) + String(" Key released, Layer: ") + currentLayer + String(" Row: ") + row + String(" Column: ") + column); 34 | switchStates[row][column] = false; 35 | keyReleaseHandler(Keymap[currentLayer][row][column]); 36 | 37 | DebugPrintKeyState(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ArduinoKeyboardFirmware 2 | Arduino keyboard firmware to convert a key matrix into keyboard input with multiple switchable key layers. Initially made for use with an Arduino Pro Micro or Teensy 2.0. 3 | 4 | ## Confirmed working arduino boards: 5 | * Pro Micro (Tested on 5V 16MHz, but it should work on 3.3V 8MHz as well) 6 | * Teensy 2.0 7 | 8 | ## Ortho 12x4Key 3Layer 9 | The project for which I started this endeavour. Wanting to create my own Planck-like Grid Keyboard, with 48 keys (12x4). The amount of rows and columns can be easily adjusted at the top of the main .ino file, underneath `////Config variables` 10 | 11 | ### Files 12 | #### OrthoKey_12x4Key_2Layer.ino 13 | This is the main file, here you can edit the amount of rows and columns that you want to use, and map the pins for those rows and columns. 14 | It also hosts the main application loop. 15 | #### Keymap.ino 16 | This is where you configure your keymap. 17 | #### SetupPins.ino 18 | This sets the pinmode for the input and output pins according to the configured data. 19 | #### MatrixLoop.ino 20 | This script loops through the matrix to determine the state for each switch. Next it checks the new state to the previous state to check whether the switch has changed. If the state has changed it will result in a switch being pressed or released, which will trigger the KeyHandlers.ino's function. 21 | #### KeyHandlers.ino 22 | This script is called from the MatrixLoop. This is where the keypress or release will be converted into an character from the Keymap.ino. 23 | 24 | 25 | ## Usefull additional information: 26 | * For how to setup a key matrix and how/why it works I highly recommend the guide over at PCBHeaven: 27 | http://pcbheaven.com/wikipages/How_Key_Matrices_Works/ 28 | * For creating visual keyboard layouts and saving them as json: 29 | http://www.keyboard-layout-editor.com/ 30 | * For using the above json data to generate a Plate and Case cutout file: 31 | http://builder.swillkb.com/ 32 | * For ascii & arduino keyboard specific keycodes see: 33 | http://www.asciitable.com/ 34 | https://www.arduino.cc/en/Reference/KeyboardModifiers 35 | -------------------------------------------------------------------------------- /OrthoKey_12x4Key_3Layer/Keymap.ino: -------------------------------------------------------------------------------- 1 | //For ascii & arduino keyboard specific keycodes see: 2 | //http://www.asciitable.com/ 3 | //https://www.arduino.cc/en/Reference/KeyboardModifiers 4 | 5 | const unsigned int Keymap[LAYERS][ROWS][COLUMNS] = 6 | { 7 | {//0 Raised layer 8 | { 9 | '`', 10 | '1', 11 | '2', 12 | '3', 13 | '4', 14 | '5', 15 | '6', 16 | '7', 17 | '8', 18 | '9', 19 | '0', 20 | KEY_DELETE 21 | }, 22 | { 23 | NO_ACTION, 24 | NO_ACTION, 25 | NO_ACTION, 26 | NO_ACTION, 27 | NO_ACTION, 28 | NO_ACTION, 29 | NO_ACTION, 30 | KEY_PAGE_UP, 31 | KEY_HOME, 32 | KEY_UP, 33 | KEY_END, 34 | NO_ACTION 35 | }, 36 | { 37 | M(KEY_LEFT_SHIFT), 38 | NO_ACTION, 39 | NO_ACTION, 40 | NO_ACTION, 41 | NO_ACTION, 42 | NO_ACTION, 43 | NO_ACTION, 44 | KEY_PAGE_DOWN, 45 | KEY_LEFT, 46 | KEY_DOWN, 47 | KEY_RIGHT, 48 | NO_ACTION 49 | }, 50 | { 51 | KEY_LEFT_CTRL, 52 | NO_ACTION, 53 | KEY_LEFT_GUI, 54 | KEY_LEFT_ALT, 55 | NO_ACTION, 56 | ' ', 57 | ' ', 58 | LAYER_RAISE, 59 | NO_ACTION, 60 | NO_ACTION, 61 | NO_ACTION, 62 | NO_ACTION 63 | } 64 | }, 65 | {//1 Default layer 66 | { 67 | KEY_ESC, 68 | 'q', 69 | 'w', 70 | 'e', 71 | 'r', 72 | 't', 73 | 'y', 74 | 'u', 75 | 'i', 76 | 'o', 77 | 'p', 78 | KEY_BACKSPACE 79 | }, 80 | { 81 | KEY_TAB, 82 | 'a', 83 | 's', 84 | 'd', 85 | 'f', 86 | 'g', 87 | 'h', 88 | 'j', 89 | 'k', 90 | 'l', 91 | ';', 92 | KEY_ENTER 93 | }, 94 | { 95 | KEY_LEFT_SHIFT, 96 | 'z', 97 | 'x', 98 | 'c', 99 | 'v', 100 | 'b', 101 | 'n', 102 | 'm', 103 | ',', 104 | '.', 105 | '/', 106 | '\'' 107 | }, 108 | { 109 | KEY_LEFT_CTRL, 110 | NO_ACTION, 111 | KEY_LEFT_GUI, 112 | KEY_LEFT_ALT, 113 | LAYER_LOWER, 114 | ' ', 115 | ' ', 116 | LAYER_RAISE, 117 | NO_ACTION, 118 | NO_ACTION, 119 | NO_ACTION, 120 | NO_ACTION 121 | } 122 | }, 123 | {//2 Lowered layer 124 | { 125 | KEY_F1, 126 | KEY_F2, 127 | KEY_F3, 128 | KEY_F4, 129 | KEY_F5, 130 | KEY_F6, 131 | KEY_F7, 132 | KEY_F8, 133 | KEY_F9, 134 | KEY_F10, 135 | KEY_F11, 136 | KEY_F12 137 | }, 138 | { 139 | KEY_CAPS_LOCK, 140 | NO_ACTION, 141 | NO_ACTION, 142 | NO_ACTION, 143 | NO_ACTION, 144 | NO_ACTION, 145 | NO_ACTION, 146 | NO_ACTION, 147 | NO_ACTION, 148 | '[', 149 | ']', 150 | NO_ACTION 151 | }, 152 | { 153 | NO_ACTION, 154 | NO_ACTION, 155 | NO_ACTION, 156 | NO_ACTION, 157 | NO_ACTION, 158 | NO_ACTION, 159 | NO_ACTION, 160 | NO_ACTION, 161 | '-', 162 | '=', 163 | NO_ACTION, 164 | NO_ACTION 165 | }, 166 | { 167 | KEY_LEFT_CTRL, 168 | NO_ACTION, 169 | KEY_LEFT_GUI, 170 | KEY_LEFT_ALT, 171 | LAYER_LOWER, 172 | ' ', 173 | ' ', 174 | NO_ACTION, 175 | NO_ACTION, 176 | NO_ACTION, 177 | NO_ACTION, 178 | NO_ACTION 179 | } 180 | } 181 | }; 182 | --------------------------------------------------------------------------------