Mindstorms 3rd Party ROBOTC Drivers RobotC
[Home] [Download] [Submit a bug/suggestion] [ROBOTC Forums] [Blog] [Support this project]

mindsensors-ps2ctrl-v4.h

Go to the documentation of this file.
00001 /*!@addtogroup mindsensors
00002  * @{
00003  * @defgroup PSP4 PSP-Nx V4
00004  * Playstation 2 Controller Sensor
00005  * @{
00006  */
00007 
00008 /*
00009  * $Id: mindsensors-ps2ctrl-v4.h 133 2013-03-10 15:15:38Z xander $
00010  */
00011 
00012 #ifndef __PSPV4_H__
00013 #define __PSPV4_H__
00014 /** \file mindsensors-ps2ctrl-v4.h
00015  * \brief Playstation 2 Controller Sensor
00016  *
00017  * mindsensors-ps2ctrl-v4.h provides an API for the Mindsensors PS2 controller sensor
00018  * with referee signal receiver.
00019  *
00020  * Changelog:
00021  * - 0.1: Initial release
00022  *
00023  * Credits:
00024  * - Big thanks to Mindsensors for providing me with the hardware necessary to write and test this.
00025  *
00026  * License: You may use this code as you wish, provided you give credit where its due.
00027  *
00028  * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 3.59 AND HIGHER. 
00029 
00030  * \author Xander Soldaat (xander_at_botbench.com)
00031  * \date 30 July 2012
00032  * \version 0.1
00033  * \example mindsensors-ps2ctrl-v4-test1.c
00034  * \example mindsensors-ps2ctrl-v4-test2.c
00035  */
00036 
00037 #pragma systemFile
00038 
00039 #ifndef __COMMON_H__
00040 #include "common.h"
00041 #endif
00042 
00043 #define PSPV4_I2C_ADDR              0x02    /*!< PSP-Nx V4 I2C device address */
00044 
00045 #define PSPV4_REG_CMD               0x41    /*!< Command register */
00046 
00047 #define PSPV4_CMD_INITIALISE        0x49    /*!< Initialisation command */
00048 
00049 #define PSPV4_REG_BTN_SET_1         0x42    /*!< First button set register */
00050 #define PSPV4_REG_BTN_SET_2         0x43    /*!< Second button set register */
00051 #define PSPV4_REG_JLEFT             0x44    /*!< Left joystick register */
00052 #define PSPV4_REG_JRIGHT            0x46    /*!< Right joystick register */
00053 
00054 #define PSPV4_REG_PRES_JPAD_UP      0x4A    /*!< Joypad up button register */
00055 #define PSPV4_REG_PRES_JPAD_RIGHT   0x4B    /*!< Joypad right button register */
00056 #define PSPV4_REG_PRES_JPAD_DOWN    0x4C    /*!< Joypad down button register */
00057 #define PSPV4_REG_PRES_JPAD_LEFT    0x4D    /*!< Joypad left button register */
00058 #define PSPV4_REG_PRES_BTN_L2       0x4E    /*!< L2 button register */
00059 #define PSPV4_REG_PRES_BTN_R2       0x4F    /*!< R2 button register */
00060 #define PSPV4_REG_PRES_BTN_L1       0x50    /*!< L1 button register */
00061 #define PSPV4_REG_PRES_BTN_R1       0x51    /*!< R1 button register */
00062 #define PSPV4_REG_PRES_BTN_TRIANGLE 0x52    /*!< Triangle button button register */
00063 #define PSPV4_REG_PRES_BTN_SQUARE   0x53    /*!< Square button register */
00064 #define PSPV4_REG_PRES_BTN_CIRCLE   0x54    /*!< Circle button register */
00065 #define PSPV4_REG_PRES_BTN_CROSS    0x55    /*!< Cross button register */
00066 
00067 #define PSPV4_REG_REF_SIGNAL_CODE   0x56    /*!< Referee Signal Code register */
00068 #define PSPV4_REG_REF_TX_TYPE       0x57    /*!< Referee Transmitter Type register */
00069 #define PSPV4_REG_REF_SIGNAL_RAW    0x58    /*!< Referee Signal Raw Value register */
00070 #define PSPV4_REG_REF_SIGNAL_COUNT  0x5C    /*!< Referee Signal Count register */
00071 
00072 #define PSPV4_SIGNAL_FAST_REWIND    0x32    /*!< Referee Signal 'fast rewind' */
00073 #define PSPV4_SIGNAL_FAST_FORWARD   0x34    /*!< Referee Signal 'fast forward' */
00074 #define PSPV4_SIGNAL_PLAY           0x35    /*!< Referee Signal 'play' */
00075 #define PSPV4_SIGNAL_STOP           0x36    /*!< Referee Signal 'stop' */
00076 
00077 tByteArray PSPV4_I2CRequest;     /*!< Array to hold I2C command data */
00078 tByteArray PSPV4_I2CReply;       /*!< Array to hold I2C reply data */
00079 
00080 bool PSPV4initalised[4] = {false, false, false, false};
00081 
00082 typedef struct
00083 {
00084   // computed button states
00085   ubyte   left1Btn;           /*!< L1 button value */
00086   ubyte   left2Btn;           /*!< L2 button value */
00087   ubyte   right1Btn;          /*!< R1 button value */
00088   ubyte   rigth2Btn;          /*!< R2 button value */
00089   ubyte   joypadLeft;         /*!< Joypad left button value */
00090   ubyte   joypadDown;         /*!< Joypad down button value */
00091   ubyte   joypadRight;        /*!< Joypad right button value */
00092   ubyte   joypadUp;           /*!< Joypad up button value */
00093   ubyte   triangleBtn;        /*!< Triangle button button value */
00094   ubyte   squareBtn;          /*!< Square button button value */
00095   ubyte   circleBtn;          /*!< Circle button button value */
00096   ubyte   crossBtn;           /*!< Cross button button value */
00097   ubyte   joystickLeftBtn;    /*!< Left joystick button value */
00098   ubyte   joystickRightBtn;   /*!< Right joystick button value */
00099   ubyte   selectBtn;          /*!< Select button value */
00100   ubyte   startBtn;           /*!< Start button value */
00101   int   joystickLeft_x;       /*!< Left joystick X value, scaled from 0 to 100 */
00102   int   joystickLeft_y;       /*!< Left joystick X value, scaled from 0 to 100 */
00103   int   joystickRight_x;      /*!< Left joystick X value, scaled from 0 to 100 */
00104   int   joystickRight_y;      /*!< Left joystick X value, scaled from 0 to 100 */
00105 } tPSP;
00106 
00107 tPSP pspController;
00108 
00109 
00110 /**
00111  * Initialise the sensor.
00112  *
00113  * Note: This is an internal function and should not be used directly.
00114  * @param link the PSP sensor port
00115  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00116  * @return true if no error occured, false if it did
00117  */
00118 bool _PSPV4init(tSensors link, ubyte address = PSPV4_I2C_ADDR)
00119 {
00120   PSPV4_I2CRequest[0] = 3;                   // Message size
00121   PSPV4_I2CRequest[1] = address ;            // I2C Address
00122   PSPV4_I2CRequest[2] = 0x41;                // Register address
00123   PSPV4_I2CRequest[3] = PSPV4_CMD_INITIALISE; // Register address
00124 
00125   if (!writeI2C(link, PSPV4_I2CRequest))
00126   {
00127     return false;
00128   }
00129 
00130         wait1Msec(100);                         // wait for the dongle to initialize
00131         PSPV4initalised[link] = true;
00132 
00133         return true;
00134 }
00135 
00136 
00137 /**
00138  * Read a byte from the sensor
00139  *
00140  * Note: This is an internal function and should not be used directly.
00141  * @param link the PSP sensor port
00142  * @param reg the register to read
00143  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00144  * @return the ubyte value or 0 if an error occured
00145  */
00146 ubyte _PSPV4readByte (tSensors link, ubyte reg, ubyte address = PSPV4_I2C_ADDR)
00147 {
00148   // Check if the controller has been initialised
00149   if (!PSPV4initalised[link])
00150   {
00151     _PSPV4init(link, address);
00152   }
00153 
00154   memset(PSPV4_I2CRequest, 0, sizeof(PSPV4_I2CRequest));
00155 
00156   PSPV4_I2CRequest[0] = 2;                   // Message size
00157   PSPV4_I2CRequest[1] = address;  // I2C Address
00158   PSPV4_I2CRequest[2] = reg;            // Register address
00159 
00160   if (!writeI2C(link, PSPV4_I2CRequest, PSPV4_I2CReply, 1))
00161     return 0;
00162 
00163   return PSPV4_I2CReply[0];
00164 }
00165 
00166 
00167 /**
00168  * Read the button states.  Use PSPV4readButtonPressure() if you want
00169  * additional pressure values as well.
00170  * @param link the PSP sensor port
00171  * @param controllerState struct to hold all the button and joystick states and values
00172  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00173  * @return true if no error occured, false if it did
00174  */
00175 bool PSPV4readButtons(tSensors link, tPSP &controllerState, ubyte address = PSPV4_I2C_ADDR)
00176 {
00177   ubyte b0;
00178   ubyte b1;
00179 
00180   // Check if the controller has been initialised
00181   if (!PSPV4initalised[link])
00182   {
00183     _PSPV4init(link, address);
00184   }
00185 
00186   memset(PSPV4_I2CRequest, 0, sizeof(PSPV4_I2CRequest));
00187   memset(controllerState, 0, sizeof(controllerState));
00188 
00189   PSPV4_I2CRequest[0] = 2;                   // Message size
00190   PSPV4_I2CRequest[1] = address;             // I2C Address
00191   PSPV4_I2CRequest[2] = PSPV4_REG_BTN_SET_1;      // Register address
00192 
00193   if (!writeI2C(link, PSPV4_I2CRequest, PSPV4_I2CReply, 6))
00194     return false;
00195 
00196         b0 = ~PSPV4_I2CReply[0];
00197         b1 = ~PSPV4_I2CReply[1];
00198 
00199         controllerState.selectBtn         = (b0 >> 0) & 0x01;
00200         controllerState.joystickLeftBtn   = (b0 >> 1) & 0x01;
00201         controllerState.joystickRightBtn  = (b0 >> 2) & 0x01;
00202         controllerState.startBtn          = (b0 >> 3) & 0x01;
00203         controllerState.joypadUp          = (b0 >> 4) & 0x01;
00204         controllerState.joypadRight       = (b0 >> 5) & 0x01;
00205         controllerState.joypadDown        = (b0 >> 6) & 0x01;
00206         controllerState.joypadLeft        = (b0 >> 7) & 0x01;
00207 
00208         controllerState.left2Btn          = (b1 >> 0) & 0x01;
00209         controllerState.rigth2Btn         = (b1 >> 1) & 0x01;
00210         controllerState.left1Btn          = (b1 >> 2) & 0x01;
00211         controllerState.right1Btn         = (b1 >> 3) & 0x01;
00212         controllerState.triangleBtn       = (b1 >> 4) & 0x01;
00213         controllerState.circleBtn         = (b1 >> 5) & 0x01;
00214         controllerState.crossBtn          = (b1 >> 6) & 0x01;
00215         controllerState.squareBtn         = (b1 >> 7) & 0x01;
00216 
00217         controllerState.joystickLeft_x    = (((long)PSPV4_I2CReply[2] - 128) * 100)/128;
00218         controllerState.joystickLeft_y    = (((long)PSPV4_I2CReply[3] - 128) * 100)/128;
00219         controllerState.joystickRight_x   = (((long)PSPV4_I2CReply[4] - 128) * 100)/128;
00220         controllerState.joystickRight_y   = (((long)PSPV4_I2CReply[5] - 128) * 100)/128;
00221 
00222         return true;
00223 }
00224 
00225 
00226 /**
00227  * Read the button states with additional pressure values.  Use PSPV4readButtons() if you don't
00228  * care about how hard someone is pressing a button.
00229  * @param link the PSP sensor port
00230  * @param controllerState struct to hold all the button and joystick states and values
00231  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00232  * @return true if no error occured, false if it did
00233  */
00234 bool PSPV4readButtonPressure(tSensors link, tPSP &controllerState,  ubyte address = PSPV4_I2C_ADDR)
00235 {
00236   // Check if the controller has been initialised
00237   if (!PSPV4initalised[link])
00238   {
00239     _PSPV4init(link, address);
00240   }
00241 
00242   if (!PSPV4readButtons(link, controllerState, address))
00243   {
00244     return false;
00245   }
00246 
00247   memset(PSPV4_I2CRequest, 0, sizeof(PSPV4_I2CRequest));
00248   PSPV4_I2CRequest[0] = 2;                   // Message size
00249   PSPV4_I2CRequest[1] = address;  // I2C Address
00250   PSPV4_I2CRequest[2] = PSPV4_REG_PRES_JPAD_UP;            // Register address
00251 
00252   if (!writeI2C(link, PSPV4_I2CRequest, PSPV4_I2CReply, 12))
00253     return false;
00254 
00255         controllerState.joypadUp          = (PSPV4_I2CReply[0]  * 100) / 255;
00256   controllerState.joypadRight       = (PSPV4_I2CReply[1]  * 100) / 255;
00257   controllerState.joypadDown        = (PSPV4_I2CReply[2]  * 100) / 255;
00258   controllerState.joypadLeft        = (PSPV4_I2CReply[3]  * 100) / 255;
00259 
00260   controllerState.left2Btn          = (PSPV4_I2CReply[4]  * 100) / 255;
00261   controllerState.rigth2Btn         = (PSPV4_I2CReply[5]  * 100) / 255;
00262   controllerState.left1Btn          = (PSPV4_I2CReply[6]  * 100) / 255;
00263   controllerState.right1Btn         = (PSPV4_I2CReply[7]  * 100) / 255;
00264   controllerState.triangleBtn       = (PSPV4_I2CReply[8]  * 100) / 255;
00265   controllerState.circleBtn         = (PSPV4_I2CReply[9]  * 100) / 255;
00266   controllerState.crossBtn          = (PSPV4_I2CReply[10] * 100) / 255;
00267   controllerState.squareBtn         = (PSPV4_I2CReply[11] * 100) / 255;
00268 
00269   return true;
00270 }
00271 
00272 /**
00273  * Read the last command sent by the referee.\n
00274  * Values can be:
00275  * - PSPV4_SIGNAL_FAST_REWIND
00276  * - PSPV4_SIGNAL_FAST_FORWARD
00277  * - PSPV4_SIGNAL_PLAY
00278  * - PSPV4_SIGNAL_STOP
00279  * @param link the PSP sensor port
00280  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00281  * @return true if no error occured, false if it did
00282  */
00283 byte PSPV4readRefSignal(tSensors link, ubyte address = PSPV4_I2C_ADDR)
00284 {
00285   return _PSPV4readByte(link, PSPV4_REG_REF_SIGNAL_CODE, address);
00286 }
00287 
00288 
00289 /**
00290  * Signal Count - increments each time the sensor receives a signal from
00291  * the Referee (rolls over to 0 after 255)
00292  * @param link the PSP sensor port
00293  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00294  * @return true if no error occured, false if it did
00295  */
00296 byte PSPV4readRefSignalCount(tSensors link, ubyte address = PSPV4_I2C_ADDR)
00297 {
00298   return _PSPV4readByte(link, PSPV4_REG_REF_SIGNAL_COUNT, address);
00299 }
00300 
00301 
00302 /**
00303  * Fetch the transmitter type.  Can be used to differentiate between
00304  * various transmitter type (TV remote vs Referee Transmitter)
00305  * @param link the PSP sensor port
00306  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00307  * @return true if no error occured, false if it did
00308  */
00309 byte PSPV4readRefTXType(tSensors link, ubyte address = PSPV4_I2C_ADDR)
00310 {
00311   return _PSPV4readByte(link, PSPV4_REG_REF_TX_TYPE, address);
00312 }
00313 
00314 
00315 /**
00316  * Get the raw data from the receiver.  This is useful if custom commands
00317  * are to be implemented.  Simply map the returned value to a new command.
00318  * @param link the PSP sensor port
00319  * @param address I2C address, optional, defaults to PSPV4_I2C_ADDR
00320  * @return the raw value from the sensor
00321  */
00322 long PSPV4readRawRefTXValue(tSensors link, ubyte address = PSPV4_I2C_ADDR)
00323 {
00324   // Check if the controller has been initialised
00325   if (!PSPV4initalised[link])
00326   {
00327     _PSPV4init(link, address);
00328   }
00329 
00330   memset(PSPV4_I2CRequest, 0, sizeof(PSPV4_I2CRequest));
00331 
00332   PSPV4_I2CRequest[0] = 2;                        // Message size
00333   PSPV4_I2CRequest[1] = address;                  // I2C Address
00334   PSPV4_I2CRequest[2] = PSPV4_REG_REF_SIGNAL_RAW; // Register address
00335 
00336   if (!writeI2C(link, PSPV4_I2CRequest, PSPV4_I2CReply, 4))
00337     return 0;
00338 
00339   return PSPV4_I2CReply[0] + (PSPV4_I2CReply[1]<<8) + (PSPV4_I2CReply[2]<<16) + (PSPV4_I2CReply[3]<<24);
00340 }
00341 
00342 
00343 
00344 #endif // __PSPV4_H__
00345 
00346 /*
00347  * $Id: mindsensors-ps2ctrl-v4.h 133 2013-03-10 15:15:38Z xander $
00348  */
00349 /* @} */
00350 /* @} */