Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

PS3 controller example

  • Loading branch information...
commit f4b30d1b67f2e6a195716e9eea5b2c279d0d3973 1 parent c87f192
unknown authored
Showing with 566 additions and 0 deletions.
  1. +566 −0 examples/PS3LCD.pde
View
566 examples/PS3LCD.pde
@@ -0,0 +1,566 @@
+
+
+/* MAX3421E USB Host controller LCD/PS3 demonstration */
+#include <Spi.h>
+#include <Max3421e.h>
+#include <Usb.h>
+#include <Max_LCD.h>
+#include <MemoryFree.h>
+#include <avr/pgmspace.h>
+
+/*The application will work in reduced host mode, so we can save program and data
+memory space. After verifying the PID and VID we will use known values for the
+configuration values for device, interface, endpoints and HID */
+
+/* PS3 data taken from descriptors */
+#define PS3_ADDR 1
+#define PS3_VID_LO 0x4c // Sony VID
+#define PS3_VID_HI 0x05
+#define PS3_PID_LO 0x68 // Batch Device
+#define PS3_PID_HI 0x02
+#define PS3_CONFIGURATION 1
+#define PS3_IF 0
+#define PS3_NUM_EP 3
+#define EP_MAXPKTSIZE 64
+#define EP_INTERRUPT 0x03
+#define EP_POLL 0x01
+#define CONTROL_EP 0
+#define OUTPUT_EP 1
+#define REPORT_EP 2
+
+
+#define PS3_F4_REPORT_LEN 4
+#define PS3_F5_REPORT_LEN 8
+#define PS3_01_REPORT_LEN 48
+#define HID_REPORT_FEATURE 3
+#define HID_REPORT_OUTPUT 2
+#define PS3_F4_REPORT_ID 0xF4
+#define PS3_01_REPORT_ID 0x01
+#define PS3_F5_REPORT_ID 0xF5
+
+/* Defines for the PS3 Data in the HID Report
+*/
+#define LAnalogX buf[6]
+#define LAnalogY buf[7]
+#define RAnalogX buf[8]
+#define RAnalogY buf[9]
+#define buttons1 buf[2]
+#define buttons2 buf[3]
+#define buttons3 buf[4]
+#define buttonchange ((buttons1 != oldbuttons1) | (buttons2 != oldbuttons2))
+#define buSelect (buttons1 & 0x01)
+#define buLAnalog (buttons1 & 0x02)
+#define buRAnalog (buttons1 & 0x04)
+#define buStart (buttons1 & 0x08)
+#define buUp (buttons1 & 0x10)
+#define buRight (buttons1 & 0x20)
+#define buDown (buttons1 & 0x40)
+#define buLeft (buttons1 & 0x80)
+#define buL2 (buttons2 & 0x01)
+#define buR2 (buttons2 & 0x02)
+#define buL1 (buttons2 & 0x04)
+#define buR1 (buttons2 & 0x08)
+#define buTriangle (buttons2 & 0x10)
+#define buCircle (buttons2 & 0x20)
+#define buCross (buttons2 & 0x40)
+#define buSquare (buttons2 & 0x80)
+#define buPS (buttons3 & 0x01)
+#define AnalogUp buf[14]
+#define AnalogRight buf[15]
+#define AnalogDown buf[16]
+#define AnalogLeft buf[17]
+#define AnalogL2 buf[18]
+#define AnalogR2 buf[19]
+#define AnalogL1 buf[20]
+#define AnalogR1 buf[21]
+#define AnalogTriangle buf[22]
+#define AnalogCircle buf[23]
+#define AnalogCross buf[24]
+#define AnalogSquare buf[25]
+#define AccelX (((unsigned char)buf[42] | (unsigned char)buf[41] << 8)-512)
+#define AccelY (((unsigned char)buf[44] | (unsigned char)buf[43] << 8)-512)
+#define AccelZ (((unsigned char)buf[46] | (unsigned char)buf[45] << 8)-512)
+#define GyroX (((unsigned char)buf[48] | (unsigned char)buf[47] << 8)-512)
+
+
+
+/*Menu screens
+
+*/
+#define Root 0
+#define Basic 1
+#define Buttons 2
+#define Joystick 3
+#define Pressure 4
+#define Accelerometer 5
+#define LED 6
+#define Bdaddr 7
+#define Freememory 8
+
+
+/* Menu Text
+*/
+
+prog_char menutext_0[] PROGMEM = "Select Test";
+prog_char menutext_1[] PROGMEM = "Basic Tests";
+prog_char menutext_2[] PROGMEM = "Buttons Test";
+prog_char menutext_3[] PROGMEM = "Joystick Test";
+prog_char menutext_4[] PROGMEM = "Pressure Test";
+prog_char menutext_5[] PROGMEM = "Motion Test";
+prog_char menutext_6[] PROGMEM = "LED/Rumble Test";
+prog_char menutext_7[] PROGMEM = "Bluetooth Addr";
+prog_char menutext_8[] PROGMEM = "Free Memory";
+
+
+PROGMEM const char *menu_table[] =
+{
+ menutext_0,
+ menutext_1,
+ menutext_2,
+ menutext_3,
+ menutext_4,
+ menutext_5,
+ menutext_6,
+ menutext_7,
+ menutext_8 };
+
+prog_char output_01_report[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff,
+ 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00,
+ 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+prog_char feature_F4_report[] PROGMEM = {0x42, 0x0c, 0x00, 0x00};
+
+EP_RECORD ep_record[ PS3_NUM_EP ]; //endpoint record structure for the PS3 controller
+
+char buf[ 64 ] = { 0 }; //General purpose buffer for usb data
+char oldbuttons1, oldbuttons2;
+char screen, selscreen;
+char lcdbuffer[17];
+unsigned char bdaddr[6];
+char bdcursor;
+char ledrum;
+char lrcursor;
+
+
+void setup();
+void loop();
+
+MAX3421E Max;
+USB Usb;
+Max_LCD LCD;
+
+void setup() {
+ // set up the LCD's number of rows and columns:
+ LCD.begin(16, 2);
+ LCD.home();
+ LCD.print("PS3 Controller");
+ LCD.setCursor(0,1);
+ LCD.print("Wait for connect");
+ Serial.begin( 9600 );
+ Serial.println("PS3 Controller Start");
+ Serial.print("freeMemory() reports ");
+ Serial.println( freeMemory() );
+ Max.powerOn();
+ delay(200);
+}
+
+void loop() {
+
+
+ Max.Task();
+ Usb.Task();
+ if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING ) { //wait for addressing state
+ PS3_init();
+ process_report();
+ Usb.setUsbTaskState( USB_STATE_RUNNING );
+ }
+ if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { //poll the PS3 Controller
+ PS3_poll();
+ }
+}
+/* Initialize PS3 Controller */
+void PS3_init( void )
+{
+ byte rcode = 0; //return code
+ byte i;
+/**/
+
+ /* Initialize data structures for endpoints of device 1*/
+ ep_record[ CONTROL_EP ] = *( Usb.getDevTableEntry( 0,0 )); //copy endpoint 0 parameters
+ ep_record[ OUTPUT_EP ].epAddr = 0x02; // PS3 output endpoint
+ ep_record[ OUTPUT_EP ].Attr = EP_INTERRUPT;
+ ep_record[ OUTPUT_EP ].MaxPktSize = EP_MAXPKTSIZE;
+ ep_record[ OUTPUT_EP ].Interval = EP_POLL;
+ ep_record[ OUTPUT_EP ].sndToggle = bmSNDTOG0;
+ ep_record[ OUTPUT_EP ].rcvToggle = bmRCVTOG0;
+ ep_record[ REPORT_EP ].epAddr = 0x01; // PS3 report endpoint
+ ep_record[ REPORT_EP ].Attr = EP_INTERRUPT;
+ ep_record[ REPORT_EP ].MaxPktSize = EP_MAXPKTSIZE;
+ ep_record[ REPORT_EP ].Interval = EP_POLL;
+ ep_record[ REPORT_EP ].sndToggle = bmSNDTOG0;
+ ep_record[ REPORT_EP ].rcvToggle = bmRCVTOG0;
+
+ Usb.setDevTableEntry( PS3_ADDR, ep_record ); //plug kbd.endpoint parameters to devtable
+
+ /* read the device descriptor and check VID and PID*/
+ rcode = Usb.getDevDescr( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, DEV_DESCR_LEN , buf );
+ if( rcode ) {
+ Serial.print("Error attempting read device descriptor. Return code :");
+ Serial.println( rcode, HEX );
+ while(1); //stop
+ }
+ if((buf[ 8 ] != PS3_VID_LO) || (buf[ 9 ] != PS3_VID_HI) || (buf[ 10 ] != PS3_PID_LO) || (buf[ 11 ] != PS3_PID_HI) ) {
+ Serial.print("Unsupported USB Device");
+ while(1); //stop
+ }
+
+ /* Configure device */
+ rcode = Usb.setConf( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_CONFIGURATION );
+ if( rcode ) {
+ Serial.print("Error attempting to configure PS3 controller. Return code :");
+ Serial.println( rcode, HEX );
+ while(1); //stop
+ }
+
+
+ /* Set the PS3 controller to send reports */
+ for (i=0; i < PS3_F4_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( feature_F4_report + i);
+ rcode = Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_F4_REPORT_LEN, PS3_IF, HID_REPORT_FEATURE, PS3_F4_REPORT_ID , buf );
+ if( rcode ) {
+ Serial.print("Set report error: ");
+ Serial.println( rcode, HEX );
+ while(1); //stop
+
+ }
+
+ /* Set the PS3 controller LED 1 On */
+ for (i=0; i < PS3_01_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( output_01_report + i);
+ rcode = Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_01_REPORT_LEN, PS3_IF, HID_REPORT_OUTPUT, PS3_01_REPORT_ID , buf );
+ if( rcode ) {
+ Serial.print("Set report error: ");
+ Serial.println( rcode, HEX );
+ while(1); //stop
+
+ }
+
+ LCD.print("PS3 initialized");
+ Serial.println("PS3 initialized");
+ delay(200);
+ screen = Root;
+ selscreen = Basic;
+ LCD.clear();
+ LCD.home();
+ LCD.print("Main Menu");
+ LCD.setCursor(0,1);
+ strcpy_P(lcdbuffer, (char*)pgm_read_word(&(menu_table[selscreen])));
+ LCD.print(lcdbuffer);
+
+
+}
+
+/* Poll PS3 and print result */
+
+void PS3_poll( void )
+{
+
+ byte rcode = 0; //return code
+ /* poll PS3 */
+ rcode = Usb.inTransfer(PS3_ADDR, ep_record[ REPORT_EP ].epAddr, PS3_01_REPORT_LEN, buf );
+ if( rcode != 0 ) {
+ return;
+ }
+ process_report();
+ return;
+}
+
+void process_report(void)
+{
+ byte i, j, mask;
+ if(buPS){
+ screen = Root;
+ selscreen = Basic;
+ LCD.clear();
+ LCD.home();
+ LCD.print("Main Menu");
+ LCD.setCursor(0,1);
+ strcpy_P(lcdbuffer, (char*)pgm_read_word(&(menu_table[selscreen])));
+ LCD.print(lcdbuffer);
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+
+ }
+
+ switch (screen){
+
+ case Root:
+ if(buttonchange){
+ if(buDown) selscreen--;
+ else if(buUp | buSelect) selscreen++;
+ else if(buStart) {
+ screen = selscreen;
+ LCD.clear();
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+ break;
+ }
+ else {
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+ break;
+
+ }
+ if (selscreen == 0) selscreen = 1;
+ if (selscreen > 8) selscreen = 1;
+ LCD.clear();
+ LCD.home();
+ LCD.print("Main Menu:");
+ LCD.setCursor(0,1);
+ strcpy_P(lcdbuffer, (char*)pgm_read_word(&(menu_table[selscreen])));
+ LCD.print(lcdbuffer);
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+ }
+ break;
+
+ case Basic:
+ if(buttonchange){
+ LCD.home();
+ if (buL1) LCD.print('X');
+ else LCD.print(' ');
+ LCD.print(" Test L/R");
+ LCD.setCursor(0,1);
+ if (buL2) LCD.print('X');
+ else LCD.print(' ');
+ LCD.print(" Buttons");
+ LCD.setCursor(15,0);
+ if (buR1) LCD.print('X');
+ else LCD.print(' ');
+
+ LCD.setCursor(15,1);
+ if (buR2) LCD.print('X');
+ else LCD.print(' ');
+ }
+
+ break;
+
+ case Buttons:
+ if(buttonchange){
+ LCD.home();
+ LCD.print("0123456789ABCDEF");
+ LCD.setCursor(0,1);
+ mask = 1;
+ for( i = 0; i < 8; i++){
+ if (buttons1 & mask) lcdbuffer[i] = '^';
+ else lcdbuffer[i] = ' ';
+ mask <<= 1;
+ }
+ mask = 1;
+ for( i = 0; i < 8; i++){
+ if (buttons2 & mask) lcdbuffer[i+8] = '^';
+ else lcdbuffer[i+8] = ' ';
+ mask <<= 1;
+ }
+ LCD.print(lcdbuffer);
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+
+ }
+
+ break;
+
+ case Joystick:
+ LCD.home();
+ LCD.print('^');
+ LCD.print((unsigned char)LAnalogY, DEC);
+ LCD.print(" ");
+ LCD.setCursor(8,0);
+ LCD.print('^');
+ LCD.print((unsigned char)RAnalogY, DEC);
+ LCD.print(" ");
+ LCD.setCursor(0,1);
+ LCD.print('>');
+ LCD.print((unsigned char)LAnalogX, DEC);
+ LCD.print(" ");
+ LCD.setCursor(8,1);
+ LCD.print('>');
+ LCD.print((unsigned char)RAnalogX, DEC);
+ LCD.print(" ");
+ break;
+
+ case Pressure:
+ LCD.home();
+ LCD.print((unsigned char)AnalogUp, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogDown, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogLeft, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogRight, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogL1, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogR1, DEC);
+ LCD.print(" ");
+
+ LCD.setCursor(0,1);
+ LCD.print((unsigned char)AnalogCircle, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogTriangle, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogSquare, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogCross, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogL2, DEC);
+ LCD.print(" ");
+ LCD.print((unsigned char)AnalogR2, DEC);
+ LCD.print(" ");
+
+ break;
+
+ case Accelerometer:
+ LCD.home();
+ LCD.print('X');
+ LCD.print(AccelX, DEC);
+ LCD.print(" ");
+ LCD.setCursor(8,0);
+ LCD.print('Y');
+ LCD.print(AccelY, DEC);
+ LCD.print(" ");
+ LCD.setCursor(0,1);
+ LCD.print('Z');
+ LCD.print(AccelZ, DEC);
+ LCD.print(" ");
+ LCD.setCursor(8,1);
+ LCD.print('G');
+ LCD.print(GyroX, DEC);
+ LCD.print(" ");
+ break;
+
+ case LED:
+ if(buttonchange){
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+ if (buRight) lrcursor++;
+ else if (buLeft) lrcursor--;
+ else if (buUp) ledrum |= 1 << lrcursor;
+ else if (buDown) ledrum &= ~(1 << lrcursor);
+ if (lrcursor > 7) lrcursor = 0;
+ if (lrcursor < 0) lrcursor = 7;
+ }
+ LCD.home();
+ LCD.print("1 2 3 4 S W ");
+ LCD.setCursor(0,1);
+ j = 0;
+ for (i=0; i < 6; i++){
+ if(ledrum & 1 << i) lcdbuffer[j] = 'X';
+ else lcdbuffer[j] = ' ';
+ j++; ;
+ lcdbuffer[j] = ' ';
+ j++;
+ }
+ lcdbuffer[j] = 0;
+ LCD.print(lcdbuffer);
+ LCD.setCursor((lrcursor * 2),1);
+ LCD.cursor();
+ /* default buffer values */
+ for (i=0; i < PS3_01_REPORT_LEN; i++) buf[i] = pgm_read_byte_near( output_01_report + i);
+ /* LED setings */
+ buf[9] = (ledrum & 0x0f) << 1;
+ /* rumble settings */
+ if (ledrum & 0x30){
+ buf[1] = buf[3] = 0xfe;
+ if (ledrum & 0x10) buf[4] = 0xff;
+ else buf[2] = 0xff;
+ }
+
+ Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_01_REPORT_LEN, PS3_IF, HID_REPORT_OUTPUT, PS3_01_REPORT_ID , buf );
+
+ delay(100);
+ LCD.noCursor();
+ break;
+
+ case Bdaddr:
+ if(buttonchange){
+ oldbuttons1 = buttons1;
+ oldbuttons2 = buttons2;
+
+ if (buRight) bdcursor++;
+ else if (buLeft) bdcursor--;
+ if (bdcursor > 11) bdcursor = 0;
+ if (bdcursor < 0) bdcursor = 11;
+ if(buUp){
+ if(bdcursor % 2){
+ if ((bdaddr[bdcursor /2] & 0x0f) == 0x0f) bdaddr[bdcursor /2] &= 0xf0;
+ bdaddr[bdcursor / 2] += 0x1;
+ }
+ else{
+ if ((bdaddr[bdcursor /2] & 0xf0) == 0xf0) bdaddr[bdcursor /2] &= 0x0f;
+ bdaddr[bdcursor / 2] += 0x10;
+ }
+
+ }
+ else if (buDown){
+ if(bdcursor % 2){
+ if ((bdaddr[bdcursor /2] & 0x0f) == 0x0) bdaddr[bdcursor /2] |= 0x0f;
+ bdaddr[bdcursor / 2] -= 0x1;
+ }
+ else{
+ if ((bdaddr[bdcursor /2] & 0xf0) == 0x0) bdaddr[bdcursor /2] |= 0xf0;
+ bdaddr[bdcursor / 2] -= 0x10;
+ }
+
+ }
+ if( buCross){
+ buf[0] = 0x01;
+ buf[1] = 0x00;
+ for (i=0; i < 6; i++){
+ buf[i+2] = bdaddr[i];
+ }
+ Serial.println( "bdaddr");
+ Usb.setReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_F5_REPORT_LEN, PS3_IF, HID_REPORT_FEATURE, PS3_F5_REPORT_ID , buf );
+ }
+ }
+ LCD.home();
+ LCD.print("R: ");
+ Usb.getReport( PS3_ADDR, ep_record[ CONTROL_EP ].epAddr, PS3_F5_REPORT_LEN, PS3_IF, HID_REPORT_FEATURE, PS3_F5_REPORT_ID , buf );
+ for( i=0; i < 6; i++){
+ if ((unsigned char)buf[i+2] < 16) LCD.print ('0');
+ LCD.print((unsigned char)buf[i + 2], HEX);
+ }
+
+ LCD.setCursor(0,1);
+ LCD.print("W: ");
+ for( i=0; i < 6; i++){
+ if (bdaddr[i] < 16) LCD.print ('0');
+ LCD.print(bdaddr[i], HEX);
+ }
+ LCD.setCursor(3 + bdcursor ,1);
+ LCD.cursor();
+
+ delay(100);
+ LCD.noCursor();
+ break;
+
+ case Freememory:
+ LCD.home();
+ LCD.print("Free Memory ");
+ LCD.print( freeMemory(), DEC );
+ LCD.setCursor(0,1);
+ break;
+
+ default:
+ break;
+
+ }
+
+ return;
+}
+
+
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.