-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathThinkpadKeyboard.h
154 lines (145 loc) · 4.91 KB
/
ThinkpadKeyboard.h
1
2
3
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#ifndef KeyboardIncludes_h
#include "KeyboardIncludes.h"
#endif
#ifndef KeyboardClass
#define KeyboardClass
class ThinkpadKeyboard
{
public:
ThinkpadKeyboard();
void begin();
void getData();
static void sendData();
private:
void _press(uint8_t);
void _pressKeys();
uint16_t _i, _j; /*looping variables */
uint8_t _keysToSend, _keyPressCount;
const uint8_t _inputPins[TOTAL_INPUT_PINS] = { 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, LAST_PIN /* last needs a rewire */ };
const uint8_t _outputPins[TOTAL_OUTPUT_PINS] = { 22, 24, 26, 28, 30, 32, 34, 36, 38, 40 };
static KeyReport _keyData;
};
ThinkpadKeyboard::ThinkpadKeyboard() /* constructor - setup pins */
{
for(_i = 0; _i < TOTAL_OUTPUT_PINS; _i++) /* set all _outputPins as output and set HIGH */
{
pinMode(_outputPins[_i], OUTPUT);
digitalWrite(_outputPins[_i], HIGH);
}
for(_j = 0; _j < TOTAL_INPUT_PINS; _j++) /* set all _inputPins as INPUT_PULLUP */
{
pinMode(_inputPins[_j], INPUT_PULLUP);
}
attachInterrupt(_inputPins[0], pin0falling, FALLING); /* Interrupt is triggered when we put _outputPin low */
attachInterrupt(_inputPins[1], pin1falling, FALLING); /* For Due, Zero, MKR1000 and 101 boards the interrupt number = pin number. */
attachInterrupt(_inputPins[2], pin2falling, FALLING); /* https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/ */
attachInterrupt(_inputPins[3], pin3falling, FALLING);
attachInterrupt(_inputPins[4], pin4falling, FALLING);
attachInterrupt(_inputPins[5], pin5falling, FALLING);
attachInterrupt(_inputPins[6], pin6falling, FALLING);
attachInterrupt(_inputPins[7], pin7falling, FALLING);
attachInterrupt(_inputPins[8], pin8falling, FALLING);
attachInterrupt(_inputPins[9], pin9falling, FALLING);
attachInterrupt(_inputPins[10], pin10falling, FALLING);
attachInterrupt(_inputPins[11], pin11falling, FALLING);
attachInterrupt(_inputPins[12], pin12falling, FALLING);
attachInterrupt(_inputPins[13], pin13falling, FALLING);
attachInterrupt(_inputPins[14], pin14falling, FALLING);
attachInterrupt(_inputPins[15], pin15falling, FALLING);
attachInterrupt(_inputPins[16], pin16falling, FALLING);
static HIDSubDescriptor nodeKeyboard(keyboard_hidReportDescriptor, sizeof(keyboard_hidReportDescriptor));
HID().AppendDescriptor(&nodeKeyboard);
}
void ThinkpadKeyboard::begin() /* setup variables */
{
for(_i = 0; _i < MAX_KEY_PRESS; _i++)
{
keysCurrentlyPressed[_i] = 0;
_keyData.keys[_i] = 0;
}
_keyData.reserved = 0;
_keyData.modifiers = 0;
numKeysCurrentlyPressed = 0;
_keysToSend = 0;
_keyPressCount = 0;
}
void ThinkpadKeyboard::_press(uint8_t k)
{
switch(k)
{
/* do magic stuff for modifiers */ /*
case 0x100:
case 0x101:
*/
default: _keyData.keys[_keysToSend++] = k;
break;
}
}
void ThinkpadKeyboard::getData()
{
begin(); /* Clear data from last time */
for(outPin = 0; outPin < TOTAL_OUTPUT_PINS ; outPin++) /* Light up all pins */
{
digitalWrite(_outputPins[outPin], LOW); /* Interrupt triggered by _inputPins falling */
digitalWrite(_outputPins[outPin], HIGH); /* keysCurrentlyPressed[current] set to keyboardMatrixChar[outPin][ISR_call_#] in ISR */
}
_pressKeys();
}
void ThinkpadKeyboard::_pressKeys()
{
/* loop through keys in keysCurrentlyPressed and put them into the keyreport
* _keyPressCount cycles through keysCurrentlyPressed, _keysToSend cycles through open slots in keyreport.keys
* loop _keyPressCount up to numKeysCurrentlyPressed - put that many keys into
* loop _keysToSend up to MAX_KEY_PRESS - this many slots
*/
for(_keysToSend = 0, _keyPressCount = 0;
(_keysToSend < MAX_KEY_PRESS) && (_keyPressCount < numKeysCurrentlyPressed);
_keyPressCount++) /* TOFIX: NKRO */
{
switch(keysCurrentlyPressed[_keyPressCount])
{
case KEY_VOL_UP: _press(0xE0);
_press(0x32);
break;
case KEY_VOL_DOWN: _press(0xE0);
_press(0x02);
break;
case KEY_MUTE: _press(0xE0);
_press(0x23);
case KEY_BREAK: _press(0xE0);
_press(0x46);
break;
case KEY_PAUSE: _press(0xE1);
_press(0x1D);
_press(0x45);
_press(0xE1);
_press(0x9D);
_press(0xC5);
break;
// Above Not Working
case KEY_POWER: _press(KEY_LEFT_CTRL);
_press(KEY_LEFT_ALT);
_press(KEY_DELETE);
break;
case KEY_IBM: _press(KEY_LEFT_CTRL);
_press(KEY_LEFT_SHIFT);
_press(KEY_F10);
break;
case KEY_FN: _press(KEY_LEFT_GUI);
break;
case KEY_PAGE_LEFT: _press(KEY_LEFT_CTRL);
_press(KEY_LEFT_ARROW);
break;
case KEY_PAGE_RIGHT: _press(KEY_RIGHT_CTRL);
_press(KEY_RIGHT_ARROW);
break;
default: _press(keysCurrentlyPressed[_keyPressCount]);
break;
}
}
}
void ThinkpadKeyboard::sendData() /* send the keyReport over USB HID */
{
HID().SendReport(HID_PROTOCOL_KEYBOARD,&_keyData,sizeof(_keyData));
}
#endif