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