commit 3e4a723922f62eadf682c999be4cd84b9295c453 Author: Bill Porter Date: Mon Sep 26 20:19:01 2011 -0500 Added to Git Signed-off-by: Bill Porter diff --git a/PS2X_lib/Examples/PS2X_Example/PS2X_Example.pde b/PS2X_lib/Examples/PS2X_Example/PS2X_Example.pde new file mode 100644 index 0000000..dc7d54f --- /dev/null +++ b/PS2X_lib/Examples/PS2X_Example/PS2X_Example.pde @@ -0,0 +1,182 @@ +#include //for v1.6 + +PS2X ps2x; // create PS2 Controller Class + +//right now, the library does NOT support hot pluggable controllers, meaning +//you must always either restart your Arduino after you conect the controller, +//or call config_gamepad(pins) again after connecting the controller. +int error = 0; +byte type = 0; +byte vibrate = 0; + +void setup(){ + Serial.begin(57600); + + //CHANGES for v1.6 HERE!!! **************PAY ATTENTION************* + + error = ps2x.config_gamepad(13,11,10,12, true, true); //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error + + if(error == 0){ + Serial.println("Found Controller, configured successful"); + Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;"); + Serial.println("holding L1 or R1 will print out the analog stick values."); + Serial.println("Go to www.billporter.info for updates and to report bugs."); + } + + else if(error == 1) + Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips"); + + else if(error == 2) + Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips"); + + else if(error == 3) + Serial.println("Controller refusing to enter Pressures mode, may not support it. "); + + //Serial.print(ps2x.Analog(1), HEX); + + type = ps2x.readType(); + switch(type) { + case 0: + Serial.println("Unknown Controller type"); + break; + case 1: + Serial.println("DualShock Controller Found"); + break; + case 2: + Serial.println("GuitarHero Controller Found"); + break; + } + +} + +void loop(){ + /* You must Read Gamepad to get new values + Read GamePad and set vibration values + ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255) + if you don't enable the rumble, use ps2x.read_gamepad(); with no values + + you should call this at least once a second + */ + + + + if(error == 1) //skip loop if no controller found + return; + + if(type == 2){ //Guitar Hero Controller + + ps2x.read_gamepad(); //read controller + + if(ps2x.ButtonPressed(GREEN_FRET)) + Serial.println("Green Fret Pressed"); + if(ps2x.ButtonPressed(RED_FRET)) + Serial.println("Red Fret Pressed"); + if(ps2x.ButtonPressed(YELLOW_FRET)) + Serial.println("Yellow Fret Pressed"); + if(ps2x.ButtonPressed(BLUE_FRET)) + Serial.println("Blue Fret Pressed"); + if(ps2x.ButtonPressed(ORANGE_FRET)) + Serial.println("Orange Fret Pressed"); + + + if(ps2x.ButtonPressed(STAR_POWER)) + Serial.println("Star Power Command"); + + if(ps2x.Button(UP_STRUM)) //will be TRUE as long as button is pressed + Serial.println("Up Strum"); + if(ps2x.Button(DOWN_STRUM)) + Serial.println("DOWN Strum"); + + + if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed + Serial.println("Start is being held"); + if(ps2x.Button(PSB_SELECT)) + Serial.println("Select is being held"); + + + if(ps2x.Button(ORANGE_FRET)) // print stick value IF TRUE + { + Serial.print("Wammy Bar Position:"); + Serial.println(ps2x.Analog(WHAMMY_BAR), DEC); + } + } + + else { //DualShock Controller + + ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed + + if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed + Serial.println("Start is being held"); + if(ps2x.Button(PSB_SELECT)) + Serial.println("Select is being held"); + + + if(ps2x.Button(PSB_PAD_UP)) { //will be TRUE as long as button is pressed + Serial.print("Up held this hard: "); + Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC); + } + if(ps2x.Button(PSB_PAD_RIGHT)){ + Serial.print("Right held this hard: "); + Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC); + } + if(ps2x.Button(PSB_PAD_LEFT)){ + Serial.print("LEFT held this hard: "); + Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC); + } + if(ps2x.Button(PSB_PAD_DOWN)){ + Serial.print("DOWN held this hard: "); + Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC); + } + + + vibrate = ps2x.Analog(PSAB_BLUE); //this will set the large motor vibrate speed based on + //how hard you press the blue (X) button + + if (ps2x.NewButtonState()) //will be TRUE if any button changes state (on to off, or off to on) + { + + + + if(ps2x.Button(PSB_L3)) + Serial.println("L3 pressed"); + if(ps2x.Button(PSB_R3)) + Serial.println("R3 pressed"); + if(ps2x.Button(PSB_L2)) + Serial.println("L2 pressed"); + if(ps2x.Button(PSB_R2)) + Serial.println("R2 pressed"); + if(ps2x.Button(PSB_GREEN)) + Serial.println("Triangle pressed"); + + } + + + if(ps2x.ButtonPressed(PSB_RED)) //will be TRUE if button was JUST pressed + Serial.println("Circle just pressed"); + + if(ps2x.ButtonReleased(PSB_PINK)) //will be TRUE if button was JUST released + Serial.println("Square just released"); + + if(ps2x.NewButtonState(PSB_BLUE)) //will be TRUE if button was JUST pressed OR released + Serial.println("X just changed"); + + + if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) // print stick values if either is TRUE + { + Serial.print("Stick Values:"); + Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX + Serial.print(","); + Serial.print(ps2x.Analog(PSS_LX), DEC); + Serial.print(","); + Serial.print(ps2x.Analog(PSS_RY), DEC); + Serial.print(","); + Serial.println(ps2x.Analog(PSS_RX), DEC); + } + + + } + + + delay(50); + +} diff --git a/PS2X_lib/PS2X_lib.cpp b/PS2X_lib/PS2X_lib.cpp new file mode 100644 index 0000000..6ecbe9f --- /dev/null +++ b/PS2X_lib/PS2X_lib.cpp @@ -0,0 +1,370 @@ +#include "PS2X_lib.h" +#include +#include +#include +#include +#include "WProgram.h" +#include "pins_arduino.h" + + + +static byte enter_config[]={0x01,0x43,0x00,0x01,0x00}; +static byte set_mode[]={0x01,0x44,0x00,0x01,0x03,0x00,0x00,0x00,0x00}; +static byte set_bytes_large[]={0x01,0x4F,0x00,0xFF,0xFF,0x03,0x00,0x00,0x00}; +static byte exit_config[]={0x01,0x43,0x00,0x00,0x5A,0x5A,0x5A,0x5A,0x5A}; +static byte enable_rumble[]={0x01,0x4D,0x00,0x00,0x01}; +static byte type_read[]={0x01,0x45,0x00,0x5A,0x5A,0x5A,0x5A,0x5A,0x5A}; + +boolean PS2X::NewButtonState() { + return ((last_buttons ^ buttons) > 0); + +} + +boolean PS2X::NewButtonState(unsigned int button) { + return (((last_buttons ^ buttons) & button) > 0); +} + +boolean PS2X::ButtonPressed(unsigned int button) { + return(NewButtonState(button) & Button(button)); +} + +boolean PS2X::ButtonReleased(unsigned int button) { + return((NewButtonState(button)) & ((~last_buttons & button) > 0)); +} + +boolean PS2X::Button(uint16_t button) { + return ((~buttons & button) > 0); +} + +unsigned int PS2X::ButtonDataByte() { + return (~buttons); +} + +byte PS2X::Analog(byte button) { + return PS2data[button]; +} +unsigned char PS2X::_gamepad_shiftinout (char byte) { + uint8_t old_sreg = SREG; // *** KJE *** save away the current state of interrupts + + + unsigned char tmp = 0; + cli(); // *** KJE *** disable for now + for(i=0;i<8;i++) { + + if(CHK(byte,i)) SET(*_cmd_oreg,_cmd_mask); + else CLR(*_cmd_oreg,_cmd_mask); + CLR(*_clk_oreg,_clk_mask); + + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + delayMicroseconds(CTRL_CLK); + cli(); // *** KJE *** + + if(CHK(*_dat_ireg,_dat_mask)) SET(tmp,i); + SET(*_clk_oreg,_clk_mask); + } + SET(*_cmd_oreg,_cmd_mask); + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + delayMicroseconds(CTRL_BYTE_DELAY); + return tmp; +} + +void PS2X::read_gamepad() { + read_gamepad(false, 0x00); +} + + +void PS2X::read_gamepad(boolean motor1, byte motor2) { + double temp = millis() - last_read; + uint8_t old_sreg = SREG; // *** KJE **** save away the current state of interrupts - *** *** KJE *** *** + + if (temp > 1500) //waited to long + reconfig_gamepad(); + + if(temp < read_delay) //waited too short + delay(read_delay - temp); + + + last_buttons = buttons; //store the previous buttons states + + if(motor2 != 0x00) + motor2 = map(motor2,0,255,0x40,0xFF); //noting below 40 will make it spin + + cli(); //*** KJE *** + SET(*_cmd_oreg,_cmd_mask); + SET(*_clk_oreg,_clk_mask); + CLR(*_att_oreg,_att_mask); // low enable joystick + SREG = old_sreg; // *** KJE *** - Interrupts may be enabled again + + delayMicroseconds(CTRL_BYTE_DELAY); + //Send the command to send button and joystick data; + char dword[9] = {0x01,0x42,0,motor1,motor2,0,0,0,0}; + byte dword2[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + + for (int i = 0; i<9; i++) { + PS2data[i] = _gamepad_shiftinout(dword[i]); + } + if(PS2data[1] == 0x79) { //if controller is in full data return mode, get the rest of data + for (int i = 0; i<12; i++) { + PS2data[i+9] = _gamepad_shiftinout(dword2[i]); + } + } + + cli(); + SET(*_att_oreg,_att_mask); // HI disable joystick + SREG = old_sreg; // Interrupts may be enabled again + + #ifdef PS2X_COM_DEBUG + Serial.println("OUT:IN"); + for(int i=0; i<9; i++){ + Serial.print(dword[i], HEX); + Serial.print(":"); + Serial.print(PS2data[i], HEX); + Serial.print(" "); + } + for (int i = 0; i<12; i++) { + Serial.print(dword2[i], HEX); + Serial.print(":"); + Serial.print(PS2data[i+9], HEX); + Serial.print(" "); + } + Serial.println(""); + #endif + + buttons = *(uint16_t*)(PS2data+3); //store as one value for multiple functions + last_read = millis(); +} + +byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat) { + return config_gamepad(clk, cmd, att, dat, false, false); +} + + +byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat, bool pressures, bool rumble) { + + uint8_t old_sreg = SREG; // *** KJE *** save away the current state of interrupts + byte temp[sizeof(type_read)]; + + _clk_mask = maskToBitNum(digitalPinToBitMask(clk)); + _clk_oreg = portOutputRegister(digitalPinToPort(clk)); + _cmd_mask = maskToBitNum(digitalPinToBitMask(cmd)); + _cmd_oreg = portOutputRegister(digitalPinToPort(cmd)); + _att_mask = maskToBitNum(digitalPinToBitMask(att)); + _att_oreg = portOutputRegister(digitalPinToPort(att)); + _dat_mask = maskToBitNum(digitalPinToBitMask(dat)); + _dat_ireg = portInputRegister(digitalPinToPort(dat)); + + + pinMode(clk, OUTPUT); //configure ports + pinMode(att, OUTPUT); + pinMode(cmd, OUTPUT); + pinMode(dat, INPUT); + + digitalWrite(dat, HIGH); //enable pull-up + + cli(); // *** KJE *** disable for now + SET(*_cmd_oreg,_cmd_mask); // SET(*_cmd_oreg,_cmd_mask); + SET(*_clk_oreg,_clk_mask); + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + + //new error checking. First, read gamepad a few times to see if it's talking + read_gamepad(); + read_gamepad(); + + //see if it talked + if(PS2data[1] != 0x41 && PS2data[1] != 0x73 && PS2data[1] != 0x79){ //see if mode came back. If still anything but 41, 73 or 79, then it's not talking + #ifdef PS2X_DEBUG + Serial.println("Controller mode not matched or no controller found"); + Serial.print("Expected 0x41 or 0x73, got "); + Serial.println(PS2data[1], HEX); + #endif + + return 1; //return error code 1 + } + + //try setting mode, increasing delays if need be. + read_delay = 1; + + for(int y = 0; y <= 10; y++) + { + sendCommandString(enter_config, sizeof(enter_config)); //start config run + + //read type + delayMicroseconds(CTRL_BYTE_DELAY); + + cli(); // *** KJE *** disable for now + SET(*_cmd_oreg,_cmd_mask); + SET(*_clk_oreg,_clk_mask); + CLR(*_att_oreg,_att_mask); // low enable joystick + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + + delayMicroseconds(CTRL_BYTE_DELAY); + + for (int i = 0; i<9; i++) { + temp[i] = _gamepad_shiftinout(type_read[i]); + } + + cli(); // *** KJE *** disable for now + SET(*_att_oreg,_att_mask); // HI disable joystick + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + + controller_type = temp[3]; + + sendCommandString(set_mode, sizeof(set_mode)); + if(rumble){ sendCommandString(enable_rumble, sizeof(enable_rumble)); en_Rumble = true; } + if(pressures){ sendCommandString(set_bytes_large, sizeof(set_bytes_large)); en_Pressures = true; } + sendCommandString(exit_config, sizeof(exit_config)); + + read_gamepad(); + + if(pressures){ + if(PS2data[1] == 0x79) + break; + if(PS2data[1] == 0x73) + return 3; + } + + if(PS2data[1] == 0x73) + break; + + if(y == 10){ + #ifdef PS2X_DEBUG + Serial.println("Controller not accepting commands"); + Serial.print("mode stil set at"); + Serial.println(PS2data[1], HEX); + #endif + return 2; //exit function with error + } + + read_delay += 1; //add 1ms to read_delay + } + + return 0; //no error if here +} + + + +void PS2X::sendCommandString(byte string[], byte len) { + + uint8_t old_sreg = SREG; // *** KJE *** save away the current state of interrupts + + #ifdef PS2X_COM_DEBUG + byte temp[len]; + cli(); // *** KJE *** disable for now + CLR(*_att_oreg,_att_mask); // low enable joystick + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + + for (int y=0; y < len; y++) + temp[y] = _gamepad_shiftinout(string[y]); + + cli(); // *** KJE *** disable for now + SET(*_att_oreg,_att_mask); //high disable joystick + SREG = old_sreg; // *** *** KJE *** *** Interrupts may be enabled again + delay(read_delay); //wait a few + + Serial.println("OUT:IN Configure"); + for(int i=0; i +* +******************************************************************/ + + +// $$$$$$$$$$$$ DEBUG ENABLE SECTION $$$$$$$$$$$$$$$$ +// to debug ps2 controller, uncomment these two lines to print out debug to uart + +//#define PS2X_DEBUG +//#define PS2X_COM_DEBUG + + +#ifndef PS2X_lib_h +#define PS2X_lib_h +#include "WProgram.h" + + +#include +#include +#include +#include + +#define CTRL_CLK 4 +#define CTRL_BYTE_DELAY 3 + +//These are our button constants +#define PSB_SELECT 0x0001 +#define PSB_L3 0x0002 +#define PSB_R3 0x0004 +#define PSB_START 0x0008 +#define PSB_PAD_UP 0x0010 +#define PSB_PAD_RIGHT 0x0020 +#define PSB_PAD_DOWN 0x0040 +#define PSB_PAD_LEFT 0x0080 +#define PSB_L2 0x0100 +#define PSB_R2 0x0200 +#define PSB_L1 0x0400 +#define PSB_R1 0x0800 +#define PSB_GREEN 0x1000 +#define PSB_RED 0x2000 +#define PSB_BLUE 0x4000 +#define PSB_PINK 0x8000 +#define PSB_TRIANGLE 0x1000 +#define PSB_CIRCLE 0x2000 +#define PSB_CROSS 0x4000 +#define PSB_SQUARE 0x8000 + +//Guitar button constants +#define GREEN_FRET 0x0200 +#define RED_FRET 0x2000 +#define YELLOW_FRET 0x1000 +#define BLUE_FRET 0x4000 +#define ORANGE_FRET 0x8000 +#define STAR_POWER 0x0100 +#define UP_STRUM 0x0010 +#define DOWN_STRUM 0x0040 +#define WHAMMY_BAR 8 + +//These are stick values +#define PSS_RX 5 +#define PSS_RY 6 +#define PSS_LX 7 +#define PSS_LY 8 + +//These are analog buttons +#define PSAB_PAD_RIGHT 9 +#define PSAB_PAD_UP 11 +#define PSAB_PAD_DOWN 12 +#define PSAB_PAD_LEFT 10 +#define PSAB_L2 19 +#define PSAB_R2 20 +#define PSAB_L1 17 +#define PSAB_R1 18 +#define PSAB_GREEN 13 +#define PSAB_RED 14 +#define PSAB_BLUE 15 +#define PSAB_PINK 16 +#define PSAB_TRIANGLE 13 +#define PSAB_CIRCLE 14 +#define PSAB_CROSS 15 +#define PSAB_SQUARE 16 + + +#define SET(x,y) (x|=(1< +* +******************************************************************/ + + +To install, unzip and place 'PS2X_lib' folder into your 'C:\Users\{user name}\Documents\Arduino\libraries' folder or '{Arduino IDE path}\hardware\libraries" or {Arduino IDE path}\libraries" directory. +Restart the Arduino IDE, and open up the example sketch. + +All uses of the library are in the example sketch. + + +****************IF YOU HAVE PROBLEMS*********************** + +open up the PS2X_lib.h file and change (remove the comment markers) + +// $$$$$$$$$$$$ DEBUG ENABLE SECTION $$$$$$$$$$$$$$$$ +// to debug ps2 controller, uncomment these two lines to print out debug to uart + +//#define PS2X_DEBUG +//#define PS2X_COM_DEBUG + +to + +// $$$$$$$$$$$$ DEBUG ENABLE SECTION $$$$$$$$$$$$$$$$ +// to debug ps2 controller, uncomment these two lines to print out debug to uart + +#define PS2X_DEBUG +#define PS2X_COM_DEBUG + + +to enable debug messages. Save the file, and recompile the example sketch. Open up the terminal +and watch what is written. If the problem is not something obvious, dump the serial output into a comment on my website and I will try +to help you. + + + +Report all bugs and check for updates at: +http://www.billporter.info/?p=240 + + + +Enjoy. \ No newline at end of file