Skip to content

Commit 96bef16

Browse files
committed
Belgian keyboard added
1 parent 111396f commit 96bef16

File tree

2 files changed

+409
-0
lines changed

2 files changed

+409
-0
lines changed
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/*
2+
* Based on Obdev's AVRUSB code and under the same license.
3+
*
4+
* TODO: Make a proper file header. :-)
5+
* Modified for Digispark by Digistump
6+
*/
7+
#ifndef __DigiKeyboard_h__
8+
#define __DigiKeyboard_h__
9+
10+
#include <Arduino.h>
11+
#include <avr/pgmspace.h>
12+
#include <avr/interrupt.h>
13+
#include <avr/delay.h>
14+
#include <string.h>
15+
16+
#include "usbdrv.h"
17+
#include "scancode-ascii-table-be.h"
18+
19+
// TODO: Work around Arduino 12 issues better.
20+
//#include <WConstants.h>
21+
//#undef int()
22+
23+
typedef uint8_t byte;
24+
25+
26+
#define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke
27+
28+
29+
static uchar idleRate; // in 4 ms units
30+
31+
32+
/* We use a simplifed keyboard report descriptor which does not support the
33+
* boot protocol. We don't allow setting status LEDs and but we do allow
34+
* simultaneous key presses.
35+
* The report descriptor has been created with usb.org's "HID Descriptor Tool"
36+
* which can be downloaded from http://www.usb.org/developers/hidpage/.
37+
* Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
38+
* for the second INPUT item.
39+
*/
40+
const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
41+
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
42+
0x09, 0x06, // USAGE (Keyboard)
43+
0xa1, 0x01, // COLLECTION (Application)
44+
0x05, 0x07, // USAGE_PAGE (Keyboard)
45+
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
46+
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
47+
0x15, 0x00, // LOGICAL_MINIMUM (0)
48+
0x25, 0x01, // LOGICAL_MAXIMUM (1)
49+
0x75, 0x01, // REPORT_SIZE (1)
50+
0x95, 0x08, // REPORT_COUNT (8)
51+
0x81, 0x02, // INPUT (Data,Var,Abs)
52+
0x95, 0x01, // REPORT_COUNT (simultaneous keystrokes)
53+
0x75, 0x08, // REPORT_SIZE (8)
54+
0x25, 0x65, // LOGICAL_MAXIMUM (101)
55+
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
56+
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
57+
0x81, 0x00, // INPUT (Data,Ary,Abs)
58+
0xc0 // END_COLLECTION
59+
};
60+
61+
62+
63+
/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
64+
* 10 Keyboard/Keypad Page for more codes.
65+
*/
66+
#define MOD_CONTROL_LEFT (1<<0)
67+
#define MOD_SHIFT_LEFT (1<<1)
68+
#define MOD_ALT_LEFT (1<<2)
69+
#define MOD_GUI_LEFT (1<<3)
70+
#define MOD_CONTROL_RIGHT (1<<4)
71+
#define MOD_SHIFT_RIGHT (1<<5)
72+
#define MOD_ALT_RIGHT (1<<6)
73+
#define MOD_GUI_RIGHT (1<<7)
74+
75+
#define KEY_A 20
76+
#define KEY_B 5
77+
#define KEY_C 6
78+
#define KEY_D 7
79+
#define KEY_E 8
80+
#define KEY_F 9
81+
#define KEY_G 10
82+
#define KEY_H 11
83+
#define KEY_I 12
84+
#define KEY_J 13
85+
#define KEY_K 14
86+
#define KEY_L 15
87+
#define KEY_M 51
88+
#define KEY_N 17
89+
#define KEY_O 18
90+
#define KEY_P 19
91+
#define KEY_Q 4
92+
#define KEY_R 21
93+
#define KEY_S 22
94+
#define KEY_T 23
95+
#define KEY_U 24
96+
#define KEY_V 25
97+
#define KEY_W 29
98+
#define KEY_X 27
99+
#define KEY_Y 28
100+
#define KEY_Z 26
101+
#define KEY_1 30
102+
#define KEY_2 31
103+
#define KEY_3 32
104+
#define KEY_4 33
105+
#define KEY_5 34
106+
#define KEY_6 35
107+
#define KEY_7 36
108+
#define KEY_8 37
109+
#define KEY_9 38
110+
#define KEY_0 39
111+
112+
#define KEY_ENTER 40
113+
114+
#define KEY_SPACE 44
115+
116+
#define KEY_F1 58
117+
#define KEY_F2 59
118+
#define KEY_F3 60
119+
#define KEY_F4 61
120+
#define KEY_F5 62
121+
#define KEY_F6 63
122+
#define KEY_F7 64
123+
#define KEY_F8 65
124+
#define KEY_F9 66
125+
#define KEY_F10 67
126+
#define KEY_F11 68
127+
#define KEY_F12 69
128+
129+
#define KEY_ARROW_LEFT 0x50
130+
131+
132+
class DigiKeyboardDevice : public Print {
133+
public:
134+
DigiKeyboardDevice () {
135+
cli();
136+
usbDeviceDisconnect();
137+
_delay_ms(250);
138+
usbDeviceConnect();
139+
140+
141+
usbInit();
142+
143+
sei();
144+
145+
// TODO: Remove the next two lines once we fix
146+
// missing first keystroke bug properly.
147+
memset(reportBuffer, 0, sizeof(reportBuffer));
148+
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
149+
}
150+
151+
void update() {
152+
usbPoll();
153+
}
154+
155+
// delay while updating until we are finished delaying
156+
void delay(long milli) {
157+
unsigned long last = millis();
158+
while (milli > 0) {
159+
unsigned long now = millis();
160+
milli -= now - last;
161+
last = now;
162+
update();
163+
}
164+
}
165+
166+
//sendKeyStroke: sends a key press AND release
167+
void sendKeyStroke(byte keyStroke) {
168+
sendKeyStroke(keyStroke, 0);
169+
}
170+
171+
//sendKeyStroke: sends a key press AND release with modifiers
172+
void sendKeyStroke(byte keyStroke, byte modifiers) {
173+
sendKeyPress(keyStroke, modifiers);
174+
// This stops endlessly repeating keystrokes:
175+
sendKeyPress(0,0);
176+
}
177+
178+
//sendKeyPress: sends a key press only - no release
179+
//to release the key, send again with keyPress=0
180+
void sendKeyPress(byte keyPress) {
181+
sendKeyPress(keyPress, 0);
182+
}
183+
184+
//sendKeyPress: sends a key press only, with modifiers - no release
185+
//to release the key, send again with keyPress=0
186+
void sendKeyPress(byte keyPress, byte modifiers) {
187+
while (!usbInterruptIsReady()) {
188+
// Note: We wait until we can send keyPress
189+
// so we know the previous keyPress was
190+
// sent.
191+
usbPoll();
192+
_delay_ms(5);
193+
}
194+
195+
memset(reportBuffer, 0, sizeof(reportBuffer));
196+
197+
reportBuffer[0] = modifiers;
198+
reportBuffer[1] = keyPress;
199+
200+
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
201+
}
202+
203+
size_t write(uint8_t chr) {
204+
if(chr == '<')
205+
sendKeyStroke(100);
206+
else if(chr == '>')
207+
sendKeyStroke(100, MOD_SHIFT_RIGHT);
208+
else if(chr == '\\')
209+
sendKeyStroke(100, MOD_ALT_RIGHT);
210+
211+
else
212+
{
213+
uint8_t data = pgm_read_byte_near(ascii_to_scan_code_table + (chr - 8));
214+
sendKeyStroke(data & 0b00111111, data >> 7 ? MOD_SHIFT_RIGHT : 0 | (data << 1) >> 7 ? MOD_ALT_RIGHT : 0);
215+
}
216+
//#define CONVERTDEADKEYS
217+
#ifdef CONVERTDEADKEYS
218+
/* To convert some dead keys to symbols */
219+
if(chr == '~' || chr == '`')
220+
{
221+
sendKeyStroke(0x2C); //Space
222+
}
223+
#endif
224+
225+
return 1;
226+
}
227+
228+
//private: TODO: Make friend?
229+
uchar reportBuffer[2]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
230+
using Print::write;
231+
};
232+
233+
DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice();
234+
235+
#ifdef __cplusplus
236+
extern "C"{
237+
#endif
238+
// USB_PUBLIC uchar usbFunctionSetup
239+
uchar usbFunctionSetup(uchar data[8]) {
240+
usbRequest_t *rq = (usbRequest_t *)((void *)data);
241+
242+
usbMsgPtr = DigiKeyboard.reportBuffer; //
243+
if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
244+
/* class request type */
245+
246+
if (rq->bRequest == USBRQ_HID_GET_REPORT) {
247+
/* wValue: ReportType (highbyte), ReportID (lowbyte) */
248+
249+
/* we only have one report type, so don't look at wValue */
250+
// TODO: Ensure it's okay not to return anything here?
251+
return 0;
252+
253+
} else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
254+
//usbMsgPtr = &idleRate;
255+
//return 1;
256+
return 0;
257+
258+
} else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
259+
idleRate = rq->wValue.bytes[1];
260+
261+
}
262+
} else {
263+
/* no vendor specific requests implemented */
264+
}
265+
266+
return 0;
267+
}
268+
#ifdef __cplusplus
269+
} // extern "C"
270+
#endif
271+
272+
273+
#endif // __DigiKeyboard_h__

0 commit comments

Comments
 (0)