Browse Source

Major rewrite for NKRO and CAPSLOCK mapping

Major revision to fix the following issues:
- simplified the code to simply use the Parse function for everything
- allows for NKRO up to keyboard hardware limitation
- allows CAPSLOCK to be remapped properly (backspace by default in
colemak)
- allows Shift-CAPSLOCK to retain the standard CAPS functionality
weigee 6 years ago
parent
commit
52a488c5c0
5 changed files with 86 additions and 182 deletions
  1. BIN
      HID1_11.pdf
  2. BIN
      Hut1_11.pdf
  3. BIN
      Hut1_12v2.pdf
  4. 86
    182
      keymapper.ino
  5. BIN
      word game list manager.xlsm

BIN
HID1_11.pdf View File


BIN
Hut1_11.pdf View File


BIN
Hut1_12v2.pdf View File


+ 86
- 182
keymapper.ino View File

@@ -6,7 +6,6 @@
6 6
 #include <usb_ch9.h>
7 7
 #include <Usb.h>
8 8
 #include <usbhub.h>
9
-#include <avr/pgmspace.h>
10 9
 #include <address.h>
11 10
 #include <hidboot.h>
12 11
 
@@ -24,7 +23,7 @@
24 23
 
25 24
 
26 25
 // function definitions
27
-bool HandleReservedKeystrokes(uint8_t mod, uint8_t key);
26
+bool HandleReservedKeystrokes(HID *hid, uint8_t *buf);
28 27
 void play_word_game(void);
29 28
 
30 29
 
@@ -42,15 +41,15 @@ typedef enum
42 41
     dvorak
43 42
 } KeyboardLayout;
44 43
 
45
-// keymap based on the scancodes from 4 to 57, refer to the HID usage table on the meaning of each element
44
+// Keymap based on the scancodes from 4 to 57, refer to the HID usage table on the meaning of each element
46 45
 PROGMEM prog_uint8_t qwertyKeymap[] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57};
47
-PROGMEM prog_uint8_t tarmak1Keymap[] = {4, 5, 6, 7, 13, 9, 10, 11, 12, 17, 8, 15, 16, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57};
48
-PROGMEM prog_uint8_t tarmak2Keymap[] = {4, 5, 6, 7, 9, 23, 13, 11, 12, 17, 8, 15, 16, 14, 18, 19, 20, 21, 22, 10, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57};
49
-PROGMEM prog_uint8_t tarmak3Keymap[] = {4, 5, 6, 7, 9, 23, 51, 11, 12, 17, 8, 15, 16, 14, 28, 19, 20, 21, 22, 10, 24, 25, 26, 27, 13, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 18, 52, 53, 54, 55, 56, 57};
50
-PROGMEM prog_uint8_t tarmak4Keymap[] = {4, 5, 6, 7, 9, 23, 51, 11, 24, 17, 8, 12, 16, 14, 28, 19, 20, 21, 22, 10, 15, 25, 26, 27, 13, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 18, 52, 53, 54, 55, 56, 57};
51
-PROGMEM prog_uint8_t colemakKeymap[] = {4, 5, 6, 22, 9, 23, 7, 11, 24, 17, 8, 12, 16, 14, 28, 51, 20, 19, 21, 10, 15, 25, 26, 27, 13, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 18, 52, 53, 54, 55, 56, 57};
46
+PROGMEM prog_uint8_t tarmak1Keymap[] = {4, 5, 6, 7, 13, 9, 10, 11, 12, 17, 8, 15, 16, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 42};
47
+PROGMEM prog_uint8_t tarmak2Keymap[] = {4, 5, 6, 7, 9, 23, 13, 11, 12, 17, 8, 15, 16, 14, 18, 19, 20, 21, 22, 10, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 42};
48
+PROGMEM prog_uint8_t tarmak3Keymap[] = {4, 5, 6, 7, 9, 23, 51, 11, 12, 17, 8, 15, 16, 14, 28, 19, 20, 21, 22, 10, 24, 25, 26, 27, 13, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 18, 52, 53, 54, 55, 56, 42};
49
+PROGMEM prog_uint8_t tarmak4Keymap[] = {4, 5, 6, 7, 9, 23, 51, 11, 24, 17, 8, 12, 16, 14, 28, 19, 20, 21, 22, 10, 15, 25, 26, 27, 13, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 18, 52, 53, 54, 55, 56, 42};
50
+PROGMEM prog_uint8_t colemakKeymap[] = {4, 5, 6, 22, 9, 23, 7, 11, 24, 17, 8, 12, 16, 14, 28, 51, 20, 19, 21, 10, 15, 25, 26, 27, 13, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 18, 52, 53, 54, 55, 56, 42};
52 51
 
53
-const uint8_t *keymap[] =
52
+const uint8_t *Keymap[] =
54 53
 {   
55 54
     qwertyKeymap,
56 55
     tarmak1Keymap,
@@ -60,205 +59,123 @@ const uint8_t *keymap[] =
60 59
     colemakKeymap
61 60
 };
62 61
 
63
-
64
-uint8_t keyBuffer[8] = {0,0,0,0,0,0,0,0};
62
+// global variables
65 63
 //uint32_t ledBlinkTime = millis();
66 64
 //uint16_t ledBlinkDelay = 500;
67 65
 //bool ledStatus = false;
68
-KeyboardLayout currentLayout = qwerty;
69
-
66
+KeyboardLayout CurrentLayout = qwerty;
67
+uint8_t KeyBuffer[8] = {0,0,0,0,0,0,0,0};
70 68
 
71 69
 class KbdRptParser : public KeyboardReportParser
72 70
 {
73
-    void PrintKey(uint8_t mod, uint8_t key);
74
-        
75 71
 protected:
76
-    virtual void OnKeyDown (uint8_t mod, uint8_t key);
77
-    virtual void OnKeyUp (uint8_t mod, uint8_t key);
78 72
     virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
79 73
 };
80 74
 
81
-void KbdRptParser::PrintKey(uint8_t m, uint8_t key)    
82
-{
83
-    
84
-    MODIFIERKEYS mod;
85
-    *((uint8_t*)&mod) = m;
86
-    
87
-    Serial.print((mod.bmLeftCtrl   == 1) ? "C" : " ");
88
-    Serial.print((mod.bmLeftShift  == 1) ? "S" : " ");
89
-    Serial.print((mod.bmLeftAlt    == 1) ? "A" : " ");
90
-    Serial.print((mod.bmLeftGUI    == 1) ? "G" : " ");
91
-    
92
-    Serial.print(" >");
93
-    Serial.print (key);
94
-    Serial.print (" : ");
95
-    PrintHex<uint8_t>(key);
96
-    Serial.print("< ");
97
-
98
-    Serial.print((mod.bmRightCtrl   == 1) ? "C" : " ");
99
-    Serial.print((mod.bmRightShift  == 1) ? "S" : " ");
100
-    Serial.print((mod.bmRightAlt    == 1) ? "A" : " ");
101
-    Serial.println((mod.bmRightGUI  == 1) ? "G" : " ");
102 75
 
103
-};
76
+// *******************************************************************************************
77
+// Parse
78
+// *******************************************************************************************
104 79
 
105
-void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)    
80
+void KbdRptParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
106 81
 {
107
-
108
-#ifdef DEBUG
109
-    Serial.print("DN ");
110
-    PrintKey(mod, key);
111
-#endif
82
+	// On error - return
83
+	if (buf[2] == 1)
84
+		return;
85
+
86
+    // for (uint8_t i=0; i<8; i++)
87
+    // {
88
+        // PrintHex(buf[i]);
89
+        // Serial.print(" ");
90
+    // }
91
+    // Serial.println("");
92
+
93
+    KeyBuffer[0] = buf[0];
112 94
     
113
-    if (!HandleReservedKeystrokes(mod, key))
95
+    if (!HandleReservedKeystrokes(hid, buf))
114 96
     {
115
-        // print the key based on the current layout
116
-        if (key-4 < 54)        // transpose of 4 becoz our array starts from 0 but A is 4
117
-                               // limit check to 57, which is the last mappable key (CAPSLOCK)
118
-            key = pgm_read_byte(keymap[currentLayout]+key-4);
119
-    
120
-        keyBuffer[0] = mod;
121
-        keyBuffer[2] = key;
97
+        // remap all keys according to the existing keymap
98
+        for (uint8_t i=2; i<8; i++)
99
+        {
100
+			// handle special case of Shift-CAPSLOCK to be ignored by the remapper
101
+			if (buf[i] == KEY_CAPS_LOCK && buf[0] & 0x22)
102
+				KeyBuffer[i] = buf[i];
103
+			else
104
+			{
105
+				// print the key based on the current layout
106
+				if (buf[i]>=4 && buf[i]-4 < 54)        	// transpose of 4 becoz our array starts from 0 but A is 4
107
+														// limit check to 57, which is the last mappable key (CAPSLOCK)
108
+					KeyBuffer[i] = pgm_read_byte(Keymap[CurrentLayout]+buf[i]-4);
109
+				else
110
+					KeyBuffer[i] = buf[i];
111
+			}
112
+			
113
+			// check locking keys
114
+			HandleLockingKeys(hid, KeyBuffer[i]);
115
+        }
116
+        
117
+        // send out key press
118
+        HID_SendReport(2,KeyBuffer,sizeof(KeyBuffer));
119
+
120
+        // for (uint8_t i=0; i<8; i++)
121
+        // {
122
+            // PrintHex(KeyBuffer[i]);
123
+            // Serial.print(" ");
124
+        // }
125
+        // Serial.println("");
126
+        // Serial.println("");
122 127
         
123
-        HID_SendReport(2,keyBuffer,sizeof(keyBuffer));    
124 128
     }
125
-}
126 129
 
127
-void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)    
128
-{
129
-#ifdef DEBUG
130
-    Serial.print("UP ");
131
-    PrintKey(mod, key);
132
-#endif
133
-    
134
-    keyBuffer[0] = 0;
135
-    keyBuffer[2] = 0;
136
-       
137
-    HID_SendReport(2,keyBuffer,sizeof(keyBuffer));
130
+};
138 131
 
139
-}
140 132
 
141
-// Copy and pasted over from Oleg's library in preparation for next major revision
142
-
143
-// void KbdRptParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
144
-// {
145
-// Serial.println ("This is my own parse function!");
146
-
147
-	// // On error - return
148
-	// if (buf[2] == 1)
149
-		// return;
150
-		
151
-	// KBDINFO	*pki = (KBDINFO*)buf;
152
-
153
-	// for (uint8_t i=2; i<8; i++)
154
-	// {
155
-		// bool down = true;
156
-		// bool up	  = true;
157
-
158
-		// for (uint8_t j=2; j<8; j++)
159
-		// {
160
-			// if (buf[i] == prevState.bInfo[j] && buf[i] != 1)	// if at least one of the keys are the same
161
-				// down = false;									// as the previous state, then it could not 
162
-																// // have been pressed again
163
-			// if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)	// if any of the keys in the previous
164
-				// up = false;													// is found now, then it has not been
165
-		// }																	// released
166
-			
167
-		// if (down)
168
-		// {
169
-			// HandleLockingKeys(hid, buf[i]);
170
-			// OnKeyDown(*buf, buf[i]);
171
-			// }
172
-		// if (up)
173
-		// {
174
-			// OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]);
175
-		// }
176
-	// }
177
-
178
-	// // handle modifier keys
179
-	// if ( (buf[0] & 0x01) > (prevState.bInfo[0] & 0x01))		// left CTRL was pressed
180
-		// OnKeyDown (*buf, 0xe0);
181
-	// if ( (buf[0] & 0x01) < (prevState.bInfo[0] & 0x01))		// left CTRL was release
182
-		// OnKeyUp (prevState.bInfo[0], 0xe0);
183
-
184
-	// if ( (buf[0] & 0x02) > (prevState.bInfo[0] & 0x02))		// left SHIFT was pressed
185
-		// OnKeyDown (*buf, 0xe1);
186
-	// if ( (buf[0] & 0x02) < (prevState.bInfo[0] & 0x02))		// left SHIFT was release
187
-		// OnKeyUp (prevState.bInfo[0], 0xe1);
188
-		
189
-	// if ( (buf[0] & 0x04) > (prevState.bInfo[0] & 0x04))		// left ALT was pressed
190
-		// OnKeyDown (*buf, 0xe2);
191
-	// if ( (buf[0] & 0x04) < (prevState.bInfo[0] & 0x04))		// left ALT was release
192
-		// OnKeyUp (prevState.bInfo[0], 0xe2);
193
-		
194
-	// if ( (buf[0] & 0x08) > (prevState.bInfo[0] & 0x08))		// left GUI was pressed
195
-		// OnKeyDown (*buf, 0xe3);
196
-	// if ( (buf[0] & 0x08) < (prevState.bInfo[0] & 0x08))		// left GUI was release
197
-		// OnKeyUp (prevState.bInfo[0], 0xe3);
198
-
199
-	// if ( (buf[0] & 0x10) > (prevState.bInfo[0] & 0x10))		// right CTRL was pressed
200
-		// OnKeyDown (*buf, 0xe4);
201
-	// if ( (buf[0] & 0x10) < (prevState.bInfo[0] & 0x10))		// right CTRL was release
202
-		// OnKeyUp (prevState.bInfo[0], 0xe4);
203
-
204
-	// if ( (buf[0] & 0x20) > (prevState.bInfo[0] & 0x20))		// right SHIFT was pressed
205
-		// OnKeyDown (*buf, 0xe5);
206
-	// if ( (buf[0] & 0x20) < (prevState.bInfo[0] & 0x20))		// right SHIFT was release
207
-		// OnKeyUp (prevState.bInfo[0], 0xe5);
208
-		
209
-	// if ( (buf[0] & 0x40) > (prevState.bInfo[0] & 0x40))		// right ALT was pressed
210
-		// OnKeyDown (*buf, 0xe6);
211
-	// if ( (buf[0] & 0x40) < (prevState.bInfo[0] & 0x40))		// right ALT was release
212
-		// OnKeyUp (prevState.bInfo[0], 0xe6);
213
-		
214
-	// if ( (buf[0] & 0x80) > (prevState.bInfo[0] & 0x80))		// right GUI was pressed
215
-		// OnKeyDown (*buf, 0xe7);
216
-	// if ( (buf[0] & 0x80) < (prevState.bInfo[0] & 0x80))		// right GUI was release
217
-		// OnKeyUp (prevState.bInfo[0], 0xe7);
218
-
219
-
220
-
221
-
222
-	// /*
223
-	// for (uint8_t i=0; i<8; i++)
224
-		// prevState.bInfo[i] = buf[i];
225
-	// */
226
-	// memcpy(prevState.bInfo, buf, 8);		// potentially faster than the loop? code seems to compile smaller also
227
-// };
228
-
229
-
230
-bool HandleReservedKeystrokes(uint8_t mod, uint8_t key) // return true if it is a reserved keystroke
133
+bool HandleReservedKeystrokes(HID *hid, uint8_t *buf) // return true if it is a reserved keystroke
231 134
 {
135
+    uint8_t mod = buf[0];       // read the modifier byte
136
+    
137
+    uint8_t numKeysPressed = 0;
138
+    uint8_t keyPosition = 0;
139
+    
140
+    // check that there is only 1 single key that is pressed
141
+    for (uint8_t i=2; i<8; i++) if (buf[i] > 0) {
142
+        numKeysPressed++;
143
+        keyPosition = i;
144
+    }
145
+	
146
+    if (numKeysPressed != 1) return false;	// only allow single keypress for reserved keystrokes (besides modifiers)
147
+    
148
+    
232 149
     // check if we are changing layouts
233 150
     if ((mod & 0x22) && (mod & 0x11))  {        // Shift-Alt keystrokes
234
-        switch (key) {
151
+        switch (buf[keyPosition]) {
235 152
             case 0x27:    // 0
236
-                currentLayout = qwerty;
153
+                CurrentLayout = qwerty;
237 154
                 digitalWrite(modeLED, LOW);
238 155
                 return true;
239 156
 
240 157
             case 0x1e:    // 1
241
-                currentLayout = tarmak1;
158
+                CurrentLayout = tarmak1;
242 159
                 digitalWrite(modeLED, HIGH);
243 160
                 return true;
244 161
 
245 162
             case 0x1f:    // 2
246
-                currentLayout = tarmak2;
163
+                CurrentLayout = tarmak2;
247 164
                 digitalWrite(modeLED, HIGH);
248 165
                 return true;
249 166
 
250 167
             case 0x20:    // 3
251
-                currentLayout = tarmak3;
168
+                CurrentLayout = tarmak3;
252 169
                 digitalWrite(modeLED, HIGH);
253 170
                 return true;
254 171
 
255 172
             case 0x21:    // 4
256
-                currentLayout = tarmak4;
173
+                CurrentLayout = tarmak4;
257 174
                 digitalWrite(modeLED, HIGH);
258 175
                 return true;
259 176
 
260 177
             case 0x22:    // 5
261
-                currentLayout = colemak;
178
+                CurrentLayout = colemak;
262 179
                 digitalWrite(modeLED, HIGH);
263 180
                 return true;
264 181
 
@@ -267,26 +184,15 @@ bool HandleReservedKeystrokes(uint8_t mod, uint8_t key) // return true if it is
267 184
                 return true;
268 185
         }
269 186
     }
270
-
271
-// note that in the current implementation of HandleReservedKeystrokes, this
272
-// part of the code will never get called even if DEBUG is defined
273
-#ifdef DEBUG
274
-    Serial.print("Current layout: ");
275
-    Serial.println(currentLayout);
276
-    
277
-    for (uint8_t i=0; i<54; i++)
278
-        Serial.println(pgm_read_byte(keymap[currentLayout]+i));
279
-#endif
280
-
187
+	
281 188
     return false;
282 189
 
283
-
284 190
 }
285 191
 
286 192
 
287
-// *******************************
288
-// ****     WORD GAME!!!       ***
289
-// *******************************
193
+// *******************************************************************************************
194
+// WORD GAME!!!
195
+// *******************************************************************************************
290 196
 
291 197
 void play_word_game(void)
292 198
 {
@@ -296,7 +202,7 @@ void play_word_game(void)
296 202
 
297 203
     uint16_t randNum;
298 204
 
299
-    switch (currentLayout) {
205
+    switch (CurrentLayout) {
300 206
         case tarmak1:
301 207
             strcpy (priorityAlphabets, "nek");
302 208
             break;
@@ -364,8 +270,6 @@ void setup()
364 270
     // initialize the digital pin as an output.
365 271
     pinMode(modeLED, OUTPUT);  
366 272
 
367
-
368
-
369 273
     Keyboard.begin();
370 274
 
371 275
 #ifdef DEBUG

BIN
word game list manager.xlsm View File


Loading…
Cancel
Save