Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1702 - 1
 
2
 
3
/* MAX3421E USB Host controller LCD/PS3 demonstration */
4
#include <Spi.h>
5
#include <Max3421e.h>
6
#include <Usb.h>
7
#include <Max_LCD.h>
8
#include <MemoryFree.h>
9
#include <avr/pgmspace.h>
10
 
11
/*The application will work in reduced host mode, so we can save program and data
12
memory space. After verifying the PID and VID we will use known values for the
13
configuration values for device, interface, endpoints and HID */
14
 
15
/* PS3 data taken from descriptors */
16
#define PS3_ADDR        1
17
#define PS3_VID_LO      0x4c  // Sony VID
18
#define PS3_VID_HI      0x05
19
#define PS3_PID_LO      0x68  // Batch Device
20
#define PS3_PID_HI      0x02
21
#define PS3_CONFIGURATION 1
22
#define PS3_IF          0
23
#define PS3_NUM_EP      3
24
#define EP_MAXPKTSIZE   64
25
#define EP_INTERRUPT    0x03
26
#define EP_POLL         0x01
27
#define CONTROL_EP      0
28
#define OUTPUT_EP       1
29
#define REPORT_EP       2
30
 
31
 
32
#define PS3_F4_REPORT_LEN 4
33
#define PS3_F5_REPORT_LEN 8
34
#define PS3_01_REPORT_LEN 48
35
#define HID_REPORT_FEATURE 3
36
#define HID_REPORT_OUTPUT  2
37
#define PS3_F4_REPORT_ID  0xF4
38
#define PS3_01_REPORT_ID  0x01
39
#define PS3_F5_REPORT_ID 0xF5
40
 
41
/* Defines for the PS3 Data in the HID Report
42
*/
43
#define LAnalogX    buf[6]
44
#define LAnalogY    buf[7]
45
#define RAnalogX    buf[8]
46
#define RAnalogY    buf[9]
47
#define buttons1    buf[2]
48
#define buttons2    buf[3]
49
#define buttons3    buf[4]
50
#define buttonchange ((buttons1 != oldbuttons1) | (buttons2 != oldbuttons2))
51
#define buSelect    (buttons1 & 0x01)
52
#define buLAnalog   (buttons1 & 0x02)
53
#define buRAnalog   (buttons1 & 0x04)
54
#define buStart     (buttons1 & 0x08)
55
#define buUp        (buttons1 & 0x10)
56
#define buRight     (buttons1 & 0x20)
57
#define buDown      (buttons1 & 0x40)
58
#define buLeft      (buttons1 & 0x80)
59
#define buL2        (buttons2 & 0x01)
60
#define buR2        (buttons2 & 0x02)
61
#define buL1        (buttons2 & 0x04)
62
#define buR1        (buttons2 & 0x08)
63
#define buTriangle  (buttons2 & 0x10)
64
#define buCircle    (buttons2 & 0x20)
65
#define buCross     (buttons2 & 0x40)
66
#define buSquare    (buttons2 & 0x80)
67
#define buPS        (buttons3 & 0x01)
68
#define AnalogUp    buf[14]
69
#define AnalogRight buf[15]
70
#define AnalogDown  buf[16]
71
#define AnalogLeft  buf[17]
72
#define AnalogL2    buf[18]
73
#define AnalogR2    buf[19]
74
#define AnalogL1    buf[20]
75
#define AnalogR1    buf[21]
76
#define AnalogTriangle buf[22]
77
#define AnalogCircle buf[23]
78
#define AnalogCross  buf[24]
79
#define AnalogSquare buf[25]
80
#define AccelX      (((unsigned char)buf[42] | (unsigned char)buf[41] << 8)-512)
81
#define AccelY      (((unsigned char)buf[44] | (unsigned char)buf[43] << 8)-512)
82
#define AccelZ      (((unsigned char)buf[46] | (unsigned char)buf[45] << 8)-512)
83
#define GyroX       (((unsigned char)buf[48] | (unsigned char)buf[47] << 8)-512)
84
 
85
 
86
 
87
/*Menu screens
88
 
89
*/
90
#define Root    0
91
#define Basic   1
92
#define Buttons 2
93
#define Joystick 3
94
#define Pressure 4
95
#define Accelerometer 5
96
#define LED 6
97
#define Bdaddr 7
98
#define Freememory 8
99
 
100
 
101
/* Menu Text
102
*/
103
 
104
prog_char menutext_0[] PROGMEM = "Select Test";
105
prog_char menutext_1[] PROGMEM = "Basic Tests";
106
prog_char menutext_2[] PROGMEM = "Buttons Test";
107
prog_char menutext_3[] PROGMEM = "Joystick Test";
108
prog_char menutext_4[] PROGMEM = "Pressure Test";
109
prog_char menutext_5[] PROGMEM = "Motion Test";
110
prog_char menutext_6[] PROGMEM = "LED/Rumble Test";
111
prog_char menutext_7[] PROGMEM = "Bluetooth Addr";
112
prog_char menutext_8[] PROGMEM = "Free Memory";
113
 
114
 
115
PROGMEM const char *menu_table[] =
116
{
117
  menutext_0,
118
  menutext_1,
119
  menutext_2,
120
  menutext_3,
121
  menutext_4,
122
  menutext_5,
123
  menutext_6,
124
  menutext_7,
125
  menutext_8 };
126
 
127
prog_char output_01_report[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128
                                     0x00, 0x02, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff,
129
                                     0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00,
130
                                     0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00,
131
                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132
                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
133
};
134
 
135
prog_char feature_F4_report[] PROGMEM = {0x42, 0x0c, 0x00, 0x00};
136
 
137
EP_RECORD ep_record[ PS3_NUM_EP ];  //endpoint record structure for the PS3 controller
138
 
139
char buf[ 64 ] = { 0 };      //General purpose buffer for usb data
140
char oldbuttons1, oldbuttons2;
141
char screen, selscreen;
142
char lcdbuffer[17];
143
unsigned char bdaddr[6];
144
char bdcursor;
145
char ledrum;
146
char lrcursor;
147
 
148
 
149
void setup();
150
void loop();
151
 
152
MAX3421E Max;
153
USB Usb;
154
Max_LCD LCD;
155
 
156
void setup() {
157
  // set up the LCD's number of rows and columns:
158
  LCD.begin(16, 2);
159
  LCD.home();
160
  LCD.print("PS3 Controller");
161
  LCD.setCursor(0,1);
162
  LCD.print("Wait for connect");
163
  Serial.begin( 9600 );
164
  Serial.println("PS3 Controller Start");
165
  Serial.print("freeMemory() reports ");
166
  Serial.println( freeMemory() );
167
  Max.powerOn();
168
  delay(200);
169
}
170
 
171
void loop() {
172
 
173
 
174
    Max.Task();
175
    Usb.Task();
176
    if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING ) {  //wait for addressing state
177
        PS3_init();
178
        process_report();
179
        Usb.setUsbTaskState( USB_STATE_RUNNING );
180
    }
181
    if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {  //poll the PS3 Controller
182
        PS3_poll();
183
    }
184
}
185
/* Initialize PS3 Controller */
186
void PS3_init( void )
187
{
188
 byte rcode = 0;  //return code
189
 byte i;
190
/**/
191
 
192
    /* Initialize data structures for endpoints of device 1*/
193
    ep_record[ CONTROL_EP ] = *( Usb.getDevTableEntry( 0,0 ));  //copy endpoint 0 parameters
194
    ep_record[ OUTPUT_EP ].epAddr = 0x02;    // PS3 output endpoint
195
    ep_record[ OUTPUT_EP ].Attr  = EP_INTERRUPT;
196
    ep_record[ OUTPUT_EP ].MaxPktSize = EP_MAXPKTSIZE;
197
    ep_record[ OUTPUT_EP ].Interval  = EP_POLL;
198
    ep_record[ OUTPUT_EP ].sndToggle = bmSNDTOG0;
199
    ep_record[ OUTPUT_EP ].rcvToggle = bmRCVTOG0;
200
    ep_record[ REPORT_EP ].epAddr = 0x01;    // PS3 report endpoint
201
    ep_record[ REPORT_EP ].Attr  = EP_INTERRUPT;
202
    ep_record[ REPORT_EP ].MaxPktSize = EP_MAXPKTSIZE;
203
    ep_record[ REPORT_EP ].Interval  = EP_POLL;
204
    ep_record[ REPORT_EP ].sndToggle = bmSNDTOG0;
205
    ep_record[ REPORT_EP ].rcvToggle = bmRCVTOG0;
206
 
207
    Usb.setDevTableEntry( PS3_ADDR, ep_record );              //plug kbd.endpoint parameters to devtable
208
 
209
    /* read the device descriptor and check VID and PID*/
210
    rcode = Usb.getDevDescr( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, DEV_DESCR_LEN , buf );
211
    if( rcode ) {
212
        Serial.print("Error attempting read device descriptor. Return code :");
213
        Serial.println( rcode, HEX );
214
        while(1);  //stop
215
    }
216
    if((buf[ 8 ] != PS3_VID_LO) || (buf[ 9 ] != PS3_VID_HI) || (buf[ 10 ] != PS3_PID_LO) || (buf[ 11 ] != PS3_PID_HI) ) {
217
        Serial.print("Unsupported USB Device");
218
          while(1);  //stop
219
    }
220
 
221
    /* Configure device */
222
    rcode = Usb.setConf( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_CONFIGURATION );
223
    if( rcode ) {
224
        Serial.print("Error attempting to configure PS3 controller. Return code :");
225
        Serial.println( rcode, HEX );
226
        while(1);  //stop
227
    }
228
 
229
 
230
    /* Set the PS3 controller to send reports */
231
    for (i=0; i < PS3_F4_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( feature_F4_report + i);
232
    rcode = Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_F4_REPORT_LEN,  PS3_IF, HID_REPORT_FEATURE, PS3_F4_REPORT_ID , buf );
233
    if( rcode ) {
234
        Serial.print("Set report error: ");
235
        Serial.println( rcode, HEX );
236
        while(1);  //stop
237
 
238
    }
239
 
240
    /* Set the PS3 controller LED 1 On */
241
    for (i=0; i < PS3_01_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( output_01_report + i);
242
    rcode = Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_01_REPORT_LEN,  PS3_IF, HID_REPORT_OUTPUT, PS3_01_REPORT_ID , buf );
243
    if( rcode ) {
244
        Serial.print("Set report error: ");
245
        Serial.println( rcode, HEX );
246
        while(1);  //stop
247
 
248
    }
249
 
250
    LCD.print("PS3 initialized");
251
    Serial.println("PS3 initialized");
252
    delay(200);
253
    screen = Root;
254
    selscreen = Basic;
255
    LCD.clear();
256
    LCD.home();
257
    LCD.print("Main Menu");
258
    LCD.setCursor(0,1);
259
    strcpy_P(lcdbuffer, (char*)pgm_read_word(&(menu_table[selscreen])));
260
    LCD.print(lcdbuffer);
261
 
262
 
263
}
264
 
265
/* Poll PS3 and print result */
266
 
267
void PS3_poll( void )
268
{
269
 
270
 byte rcode = 0;     //return code
271
    /* poll PS3 */
272
    rcode = Usb.inTransfer(PS3_ADDR, ep_record[ REPORT_EP ].epAddr, PS3_01_REPORT_LEN, buf );
273
    if( rcode != 0 ) {
274
       return;
275
    }
276
    process_report();
277
    return;
278
}
279
 
280
void process_report(void)
281
{
282
  byte i, j, mask;
283
  if(buPS){
284
    screen = Root;
285
    selscreen = Basic;
286
    LCD.clear();
287
    LCD.home();
288
    LCD.print("Main Menu");
289
    LCD.setCursor(0,1);
290
    strcpy_P(lcdbuffer, (char*)pgm_read_word(&(menu_table[selscreen])));
291
    LCD.print(lcdbuffer);
292
    oldbuttons1 = buttons1;
293
    oldbuttons2 = buttons2;
294
 
295
  }
296
 
297
  switch (screen){
298
 
299
    case Root:
300
      if(buttonchange){
301
        if(buDown) selscreen--;
302
        else if(buUp | buSelect) selscreen++;
303
        else if(buStart) {
304
          screen = selscreen;
305
          LCD.clear();
306
          oldbuttons1 = buttons1;
307
          oldbuttons2 = buttons2;
308
          break;
309
        }
310
        else {
311
          oldbuttons1 = buttons1;
312
          oldbuttons2 = buttons2;
313
          break;
314
 
315
        }
316
        if (selscreen == 0) selscreen = 1;
317
        if (selscreen > 8) selscreen = 1;
318
        LCD.clear();
319
        LCD.home();
320
        LCD.print("Main Menu:");
321
        LCD.setCursor(0,1);
322
        strcpy_P(lcdbuffer, (char*)pgm_read_word(&(menu_table[selscreen])));
323
        LCD.print(lcdbuffer);
324
        oldbuttons1 = buttons1;
325
        oldbuttons2 = buttons2;
326
      }
327
      break;
328
 
329
    case Basic:
330
      if(buttonchange){
331
        LCD.home();
332
        if (buL1) LCD.print('X');
333
        else LCD.print(' ');
334
        LCD.print("  Test L/R");
335
        LCD.setCursor(0,1);
336
        if (buL2) LCD.print('X');
337
        else LCD.print(' ');
338
        LCD.print("  Buttons");
339
        LCD.setCursor(15,0);
340
        if (buR1) LCD.print('X');
341
        else LCD.print(' ');
342
 
343
        LCD.setCursor(15,1);
344
        if (buR2) LCD.print('X');
345
        else LCD.print(' ');
346
      }
347
 
348
      break;
349
 
350
    case Buttons:
351
      if(buttonchange){
352
        LCD.home();
353
        LCD.print("0123456789ABCDEF");
354
        LCD.setCursor(0,1);
355
        mask = 1;
356
        for( i = 0; i < 8; i++){
357
          if (buttons1 & mask) lcdbuffer[i] = '^';
358
          else lcdbuffer[i] = ' ';
359
          mask <<= 1;
360
        }
361
        mask = 1;
362
        for( i = 0; i < 8; i++){
363
          if (buttons2 & mask) lcdbuffer[i+8] = '^';
364
          else lcdbuffer[i+8] = ' ';
365
          mask <<= 1;
366
        }
367
        LCD.print(lcdbuffer);
368
        oldbuttons1 = buttons1;
369
        oldbuttons2 = buttons2;
370
 
371
      }
372
 
373
      break;
374
 
375
    case Joystick:
376
      LCD.home();
377
      LCD.print('^');
378
      LCD.print((unsigned char)LAnalogY, DEC);
379
      LCD.print("  ");
380
      LCD.setCursor(8,0);
381
      LCD.print('^');
382
      LCD.print((unsigned char)RAnalogY, DEC);
383
      LCD.print("  ");
384
      LCD.setCursor(0,1);
385
      LCD.print('>');
386
      LCD.print((unsigned char)LAnalogX, DEC);
387
      LCD.print("  ");
388
      LCD.setCursor(8,1);
389
      LCD.print('>');
390
      LCD.print((unsigned char)RAnalogX, DEC);
391
      LCD.print("  ");
392
      break;
393
 
394
    case Pressure:
395
      LCD.home();
396
      LCD.print((unsigned char)AnalogUp, DEC);
397
      LCD.print(" ");
398
      LCD.print((unsigned char)AnalogDown, DEC);
399
      LCD.print(" ");
400
      LCD.print((unsigned char)AnalogLeft, DEC);
401
      LCD.print(" ");
402
      LCD.print((unsigned char)AnalogRight, DEC);
403
      LCD.print(" ");
404
      LCD.print((unsigned char)AnalogL1, DEC);
405
      LCD.print(" ");
406
      LCD.print((unsigned char)AnalogR1, DEC);
407
      LCD.print("      ");
408
 
409
      LCD.setCursor(0,1);
410
      LCD.print((unsigned char)AnalogCircle, DEC);
411
      LCD.print(" ");
412
      LCD.print((unsigned char)AnalogTriangle, DEC);
413
      LCD.print(" ");
414
      LCD.print((unsigned char)AnalogSquare, DEC);
415
      LCD.print(" ");
416
      LCD.print((unsigned char)AnalogCross, DEC);
417
      LCD.print(" ");
418
      LCD.print((unsigned char)AnalogL2, DEC);
419
      LCD.print(" ");
420
      LCD.print((unsigned char)AnalogR2, DEC);
421
      LCD.print("      ");
422
 
423
      break;
424
 
425
    case Accelerometer:
426
      LCD.home();
427
      LCD.print('X');
428
      LCD.print(AccelX, DEC);
429
      LCD.print("  ");
430
      LCD.setCursor(8,0);
431
      LCD.print('Y');
432
      LCD.print(AccelY, DEC);
433
      LCD.print("  ");
434
      LCD.setCursor(0,1);
435
      LCD.print('Z');
436
      LCD.print(AccelZ, DEC);
437
      LCD.print("  ");
438
      LCD.setCursor(8,1);
439
      LCD.print('G');
440
      LCD.print(GyroX, DEC);
441
      LCD.print("  ");
442
      break;
443
 
444
    case LED:
445
      if(buttonchange){
446
        oldbuttons1 = buttons1;
447
        oldbuttons2 = buttons2;
448
        if (buRight) lrcursor++;
449
        else if (buLeft) lrcursor--;
450
        else if (buUp) ledrum |= 1 << lrcursor;
451
        else if (buDown) ledrum &= ~(1 << lrcursor);
452
        if (lrcursor > 7) lrcursor = 0;
453
        if (lrcursor < 0) lrcursor = 7;
454
      }
455
      LCD.home();
456
      LCD.print("1 2 3 4 S W ");
457
      LCD.setCursor(0,1);
458
      j = 0;
459
      for (i=0; i < 6; i++){
460
        if(ledrum & 1 << i) lcdbuffer[j] = 'X';
461
        else lcdbuffer[j] = ' ';
462
        j++; ;
463
        lcdbuffer[j] = ' ';
464
        j++;
465
      }
466
      lcdbuffer[j] = 0;
467
      LCD.print(lcdbuffer);
468
      LCD.setCursor((lrcursor * 2),1);
469
      LCD.cursor();
470
      /* default buffer values */
471
      for (i=0; i < PS3_01_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( output_01_report + i);
472
      /* LED setings */
473
      buf[9] = (ledrum & 0x0f) << 1;
474
      /* rumble settings */
475
      if (ledrum & 0x30){
476
        buf[1] = buf[3] = 0xfe;
477
        if (ledrum & 0x10) buf[4] = 0xff;
478
        else buf[2] = 0xff;
479
      }
480
 
481
      Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_01_REPORT_LEN,  PS3_IF, HID_REPORT_OUTPUT, PS3_01_REPORT_ID , buf );
482
 
483
      delay(100);
484
      LCD.noCursor();
485
      break;
486
 
487
    case Bdaddr:
488
      if(buttonchange){
489
        oldbuttons1 = buttons1;
490
        oldbuttons2 = buttons2;
491
 
492
        if (buRight) bdcursor++;
493
        else if (buLeft) bdcursor--;
494
        if (bdcursor > 11) bdcursor = 0;
495
        if (bdcursor < 0) bdcursor = 11;
496
        if(buUp){
497
          if(bdcursor % 2){
498
            if ((bdaddr[bdcursor /2] & 0x0f) == 0x0f) bdaddr[bdcursor /2] &= 0xf0;
499
            bdaddr[bdcursor / 2] += 0x1;
500
          }
501
          else{
502
            if ((bdaddr[bdcursor /2] & 0xf0) == 0xf0) bdaddr[bdcursor /2] &= 0x0f;
503
            bdaddr[bdcursor / 2] += 0x10;
504
          }
505
 
506
        }
507
        else if (buDown){
508
          if(bdcursor % 2){
509
            if ((bdaddr[bdcursor /2] & 0x0f) == 0x0) bdaddr[bdcursor /2] |= 0x0f;
510
            bdaddr[bdcursor / 2] -= 0x1;
511
          }
512
          else{
513
            if ((bdaddr[bdcursor /2] & 0xf0) == 0x0) bdaddr[bdcursor /2] |= 0xf0;
514
            bdaddr[bdcursor / 2] -= 0x10;
515
          }
516
 
517
         }
518
         if( buCross){
519
           buf[0] = 0x01;
520
           buf[1] = 0x00;
521
           for (i=0; i < 6; i++){
522
             buf[i+2] = bdaddr[i];
523
           }
524
          Serial.println( "bdaddr");
525
          Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_F5_REPORT_LEN,  PS3_IF, HID_REPORT_FEATURE, PS3_F5_REPORT_ID , buf );
526
        }
527
      }
528
      LCD.home();
529
      LCD.print("R: ");
530
      Usb.getReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_F5_REPORT_LEN,  PS3_IF, HID_REPORT_FEATURE, PS3_F5_REPORT_ID , buf );
531
      for( i=0; i < 6; i++){
532
        if ((unsigned char)buf[i+2] < 16) LCD.print ('0');
533
        LCD.print((unsigned char)buf[i + 2], HEX);
534
      }
535
 
536
      LCD.setCursor(0,1);
537
      LCD.print("W: ");
538
      for( i=0; i < 6; i++){
539
        if (bdaddr[i] < 16) LCD.print ('0');
540
        LCD.print(bdaddr[i], HEX);
541
      }
542
      LCD.setCursor(3 + bdcursor ,1);
543
      LCD.cursor();
544
 
545
      delay(100);
546
      LCD.noCursor();
547
      break;
548
 
549
    case Freememory:
550
      LCD.home();
551
      LCD.print("Free Memory ");
552
      LCD.print( freeMemory(), DEC );
553
      LCD.setCursor(0,1);
554
      break;
555
 
556
    default:
557
      break;
558
 
559
  }
560
 
561
  return;
562
}
563
 
564
 
565
 
566