Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1702 | - | 1 | /* MAX3421E USB Host controller LCD/keyboard demonstration */ |
2 | #include <Spi.h> |
||
3 | #include <Max3421e.h> |
||
4 | #include <Usb.h> |
||
5 | #include <Max_LCD.h> |
||
6 | |||
7 | /* keyboard data taken from configuration descriptor */ |
||
8 | #define KBD_ADDR 1 |
||
9 | #define KBD_EP 1 |
||
10 | #define KBD_IF 0 |
||
11 | #define EP_MAXPKTSIZE 8 |
||
12 | #define EP_POLL 0x0a |
||
13 | /**/ |
||
14 | //****************************************************************************** |
||
15 | // macros to identify special charaters(other than Digits and Alphabets) |
||
16 | //****************************************************************************** |
||
17 | #define BANG (0x1E) |
||
18 | #define AT (0x1F) |
||
19 | #define POUND (0x20) |
||
20 | #define DOLLAR (0x21) |
||
21 | #define PERCENT (0x22) |
||
22 | #define CAP (0x23) |
||
23 | #define AND (0x24) |
||
24 | #define STAR (0x25) |
||
25 | #define OPENBKT (0x26) |
||
26 | #define CLOSEBKT (0x27) |
||
27 | |||
28 | #define RETURN (0x28) |
||
29 | #define ESCAPE (0x29) |
||
30 | #define BACKSPACE (0x2A) |
||
31 | #define TAB (0x2B) |
||
32 | #define SPACE (0x2C) |
||
33 | #define HYPHEN (0x2D) |
||
34 | #define EQUAL (0x2E) |
||
35 | #define SQBKTOPEN (0x2F) |
||
36 | #define SQBKTCLOSE (0x30) |
||
37 | #define BACKSLASH (0x31) |
||
38 | #define SEMICOLON (0x33) |
||
39 | #define INVCOMMA (0x34) |
||
40 | #define TILDE (0x35) |
||
41 | #define COMMA (0x36) |
||
42 | #define PERIOD (0x37) |
||
43 | #define FRONTSLASH (0x38) |
||
44 | #define DELETE (0x4c) |
||
45 | /**/ |
||
46 | /* Modifier masks. One for both modifiers */ |
||
47 | #define SHIFT 0x22 |
||
48 | #define CTRL 0x11 |
||
49 | #define ALT 0x44 |
||
50 | #define GUI 0x88 |
||
51 | /**/ |
||
52 | /* "Sticky keys */ |
||
53 | #define CAPSLOCK (0x39) |
||
54 | #define NUMLOCK (0x53) |
||
55 | #define SCROLLLOCK (0x47) |
||
56 | /* Sticky keys output report bitmasks */ |
||
57 | #define bmNUMLOCK 0x01 |
||
58 | #define bmCAPSLOCK 0x02 |
||
59 | #define bmSCROLLLOCK 0x04 |
||
60 | /**/ |
||
61 | EP_RECORD ep_record[ 2 ]; //endpoint record structure for the keyboard |
||
62 | |||
63 | char buf[ 8 ] = { 0 }; //keyboard buffer |
||
64 | char old_buf[ 8 ] = { 0 }; //last poll |
||
65 | /* Sticky key state */ |
||
66 | bool numLock = false; |
||
67 | bool capsLock = false; |
||
68 | bool scrollLock = false; |
||
69 | bool line = false; |
||
70 | |||
71 | void setup(); |
||
72 | void loop(); |
||
73 | |||
74 | MAX3421E Max; |
||
75 | USB Usb; |
||
76 | Max_LCD LCD; |
||
77 | |||
78 | void setup() { |
||
79 | // set up the LCD's number of rows and columns: |
||
80 | LCD.begin(16, 2); |
||
81 | LCD.home(); |
||
82 | Serial.begin( 9600 ); |
||
83 | Serial.println("Start"); |
||
84 | Max.powerOn(); |
||
85 | delay( 200 ); |
||
86 | } |
||
87 | |||
88 | void loop() { |
||
89 | Max.Task(); |
||
90 | Usb.Task(); |
||
91 | if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING ) { //wait for addressing state |
||
92 | kbd_init(); |
||
93 | Usb.setUsbTaskState( USB_STATE_RUNNING ); |
||
94 | } |
||
95 | if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { //poll the keyboard |
||
96 | kbd_poll(); |
||
97 | } |
||
98 | } |
||
99 | /* Initialize keyboard */ |
||
100 | void kbd_init( void ) |
||
101 | { |
||
102 | byte rcode = 0; //return code |
||
103 | /**/ |
||
104 | /* Initialize data structures */ |
||
105 | ep_record[ 0 ] = *( Usb.getDevTableEntry( 0,0 )); //copy endpoint 0 parameters |
||
106 | ep_record[ 1 ].MaxPktSize = EP_MAXPKTSIZE; |
||
107 | ep_record[ 1 ].Interval = EP_POLL; |
||
108 | ep_record[ 1 ].sndToggle = bmSNDTOG0; |
||
109 | ep_record[ 1 ].rcvToggle = bmRCVTOG0; |
||
110 | Usb.setDevTableEntry( 1, ep_record ); //plug kbd.endpoint parameters to devtable |
||
111 | /* Configure device */ |
||
112 | rcode = Usb.setConf( KBD_ADDR, 0, 1 ); |
||
113 | if( rcode ) { |
||
114 | Serial.print("Error attempting to configure keyboard. Return code :"); |
||
115 | Serial.println( rcode, HEX ); |
||
116 | while(1); //stop |
||
117 | } |
||
118 | /* Set boot protocol */ |
||
119 | rcode = Usb.setProto( KBD_ADDR, 0, 0, 0 ); |
||
120 | if( rcode ) { |
||
121 | Serial.print("Error attempting to configure boot protocol. Return code :"); |
||
122 | Serial.println( rcode, HEX ); |
||
123 | while( 1 ); //stop |
||
124 | } |
||
125 | LCD.print("Keyboard initialized"); |
||
126 | delay(2000); |
||
127 | LCD.clear(); |
||
128 | LCD.home(); |
||
129 | Serial.println("Keyboard initialized"); |
||
130 | } |
||
131 | |||
132 | /* Poll keyboard and print result */ |
||
133 | /* buffer starts at position 2, 0 is modifier key state and 1 is irrelevant */ |
||
134 | void kbd_poll( void ) |
||
135 | { |
||
136 | char i; |
||
137 | static char leds = 0; |
||
138 | byte rcode = 0; //return code |
||
139 | /* poll keyboard */ |
||
140 | rcode = Usb.inTransfer( KBD_ADDR, KBD_EP, 8, buf ); |
||
141 | if( rcode != 0 ) { |
||
142 | return; |
||
143 | }//if ( rcode.. |
||
144 | for( i = 2; i < 8; i++ ) { |
||
145 | if( buf[ i ] == 0 ) { //end of non-empty space |
||
146 | break; |
||
147 | } |
||
148 | if( buf_compare( buf[ i ] ) == false ) { //if new key |
||
149 | switch( buf[ i ] ) { |
||
150 | case CAPSLOCK: |
||
151 | capsLock =! capsLock; |
||
152 | leds = ( capsLock ) ? leds |= bmCAPSLOCK : leds &= ~bmCAPSLOCK; // set or clear bit 1 of LED report byte |
||
153 | break; |
||
154 | case NUMLOCK: |
||
155 | numLock =! numLock; |
||
156 | leds = ( numLock ) ? leds |= bmNUMLOCK : leds &= ~bmNUMLOCK; // set or clear bit 0 of LED report byte |
||
157 | break; |
||
158 | case SCROLLLOCK: |
||
159 | scrollLock =! scrollLock; |
||
160 | leds = ( scrollLock ) ? leds |= bmSCROLLLOCK : leds &= ~bmSCROLLLOCK; // set or clear bit 2 of LED report byte |
||
161 | break; |
||
162 | case DELETE: |
||
163 | LCD.clear(); |
||
164 | LCD.home(); |
||
165 | line = false; |
||
166 | break; |
||
167 | case RETURN: |
||
168 | line =! line; |
||
169 | LCD.setCursor( 0, line ); |
||
170 | break; |
||
171 | default: |
||
172 | //LCD.print("A"); //output |
||
173 | LCD.print( HIDtoA( buf[ i ], buf[ 0 ] )); |
||
174 | Serial.print(HIDtoA( buf[ i ], buf[ 0 ] )); |
||
175 | break; |
||
176 | }//switch( buf[ i ... |
||
177 | rcode = Usb.setReport( KBD_ADDR, 0, 1, KBD_IF, 0x02, 0, &leds ); |
||
178 | if( rcode ) { |
||
179 | Serial.print("Set report error: "); |
||
180 | Serial.println( rcode, HEX ); |
||
181 | }//if( rcode ... |
||
182 | }//if( buf_compare( buf[ i ] ) == false ... |
||
183 | }//for( i = 2... |
||
184 | for( i = 2; i < 8; i++ ) { //copy new buffer to old |
||
185 | old_buf[ i ] = buf[ i ]; |
||
186 | } |
||
187 | } |
||
188 | /* compare byte against bytes in old buffer */ |
||
189 | bool buf_compare( byte data ) |
||
190 | { |
||
191 | char i; |
||
192 | for( i = 2; i < 8; i++ ) { |
||
193 | if( old_buf[ i ] == data ) { |
||
194 | return( true ); |
||
195 | } |
||
196 | } |
||
197 | return( false ); |
||
198 | } |
||
199 | |||
200 | /* HID to ASCII converter. Takes HID keyboard scancode, returns ASCII code */ |
||
201 | byte HIDtoA( byte HIDbyte, byte mod ) |
||
202 | { |
||
203 | /* upper row of the keyboard, numbers and special symbols */ |
||
204 | if( HIDbyte >= 0x1e && HIDbyte <= 0x27 ) { |
||
205 | if(( mod & SHIFT ) || numLock ) { //shift key pressed |
||
206 | switch( HIDbyte ) { |
||
207 | case BANG: return( 0x21 ); |
||
208 | case AT: return( 0x40 ); |
||
209 | case POUND: return( 0x23 ); |
||
210 | case DOLLAR: return( 0x24 ); |
||
211 | case PERCENT: return( 0x25 ); |
||
212 | case CAP: return( 0x5e ); |
||
213 | case AND: return( 0x26 ); |
||
214 | case STAR: return( 0x2a ); |
||
215 | case OPENBKT: return( 0x28 ); |
||
216 | case CLOSEBKT: return( 0x29 ); |
||
217 | }//switch( HIDbyte... |
||
218 | } |
||
219 | else { //numbers |
||
220 | if( HIDbyte == 0x27 ) { //zero |
||
221 | return( 0x30 ); |
||
222 | } |
||
223 | else { |
||
224 | return( HIDbyte + 0x13 ); |
||
225 | } |
||
226 | }//numbers |
||
227 | }//if( HIDbyte >= 0x1e && HIDbyte <= 0x27 |
||
228 | /**/ |
||
229 | /* number pad. Arrows are not supported */ |
||
230 | if(( HIDbyte >= 0x59 && HIDbyte <= 0x61 ) && ( numLock == true )) { // numbers 1-9 |
||
231 | return( HIDbyte - 0x28 ); |
||
232 | } |
||
233 | if(( HIDbyte == 0x62 ) && ( numLock == true )) { //zero |
||
234 | return( 0x30 ); |
||
235 | } |
||
236 | /* Letters a-z */ |
||
237 | if( HIDbyte >= 0x04 && HIDbyte <= 0x1d ) { |
||
238 | if((( capsLock == true ) && ( mod & SHIFT ) == 0 ) || (( capsLock == false ) && ( mod & SHIFT ))) { //upper case |
||
239 | return( HIDbyte + 0x3d ); |
||
240 | } |
||
241 | else { //lower case |
||
242 | return( HIDbyte + 0x5d ); |
||
243 | } |
||
244 | }//if( HIDbyte >= 0x04 && HIDbyte <= 0x1d... |
||
245 | /* Other special symbols */ |
||
246 | if( HIDbyte >= 0x2c && HIDbyte <= 0x38 ) { |
||
247 | switch( HIDbyte ) { |
||
248 | case SPACE: return( 0x20 ); |
||
249 | case HYPHEN: |
||
250 | if(( mod & SHIFT ) == false ) { |
||
251 | return( 0x2d ); |
||
252 | } |
||
253 | else { |
||
254 | return( 0x5f ); |
||
255 | } |
||
256 | case EQUAL: |
||
257 | if(( mod & SHIFT ) == false ) { |
||
258 | return( 0x3d ); |
||
259 | } |
||
260 | else { |
||
261 | return( 0x2b ); |
||
262 | } |
||
263 | case SQBKTOPEN: |
||
264 | if(( mod & SHIFT ) == false ) { |
||
265 | return( 0x5b ); |
||
266 | } |
||
267 | else { |
||
268 | return( 0x7b ); |
||
269 | } |
||
270 | case SQBKTCLOSE: |
||
271 | if(( mod & SHIFT ) == false ) { |
||
272 | return( 0x5d ); |
||
273 | } |
||
274 | else { |
||
275 | return( 0x7d ); |
||
276 | } |
||
277 | case BACKSLASH: |
||
278 | if(( mod & SHIFT ) == false ) { |
||
279 | return( 0x5c ); |
||
280 | } |
||
281 | else { |
||
282 | return( 0x7c ); |
||
283 | } |
||
284 | case SEMICOLON: |
||
285 | if(( mod & SHIFT ) == false ) { |
||
286 | return( 0x3b ); |
||
287 | } |
||
288 | else { |
||
289 | return( 0x3a ); |
||
290 | } |
||
291 | case INVCOMMA: |
||
292 | if(( mod & SHIFT ) == false ) { |
||
293 | return( 0x27 ); |
||
294 | } |
||
295 | else { |
||
296 | return( 0x22 ); |
||
297 | } |
||
298 | case TILDE: |
||
299 | if(( mod & SHIFT ) == false ) { |
||
300 | return( 0x60 ); |
||
301 | } |
||
302 | else { |
||
303 | return( 0x7e ); |
||
304 | } |
||
305 | case COMMA: |
||
306 | if(( mod & SHIFT ) == false ) { |
||
307 | return( 0x2c ); |
||
308 | } |
||
309 | else { |
||
310 | return( 0x3c ); |
||
311 | } |
||
312 | case PERIOD: |
||
313 | if(( mod & SHIFT ) == false ) { |
||
314 | return( 0x2e ); |
||
315 | } |
||
316 | else { |
||
317 | return( 0x3e ); |
||
318 | } |
||
319 | case FRONTSLASH: |
||
320 | if(( mod & SHIFT ) == false ) { |
||
321 | return( 0x2f ); |
||
322 | } |
||
323 | else { |
||
324 | return( 0x3f ); |
||
325 | } |
||
326 | default: |
||
327 | break; |
||
328 | }//switch( HIDbyte.. |
||
329 | }//if( HIDbye >= 0x2d && HIDbyte <= 0x38.. |
||
330 | return( 0 ); |
||
331 | } |
||
332 | |||
333 | |||
334 | |||
335 |