Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PS4Parser.h
00001 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Kristian Lauszus, TKJ Electronics 00014 Web : http://www.tkjelectronics.com 00015 e-mail : kristianl@tkjelectronics.com 00016 */ 00017 00018 #ifndef _ps4parser_h_ 00019 #define _ps4parser_h_ 00020 00021 #include "Usb.h" 00022 #include "controllerEnums.h" 00023 00024 /** Buttons on the controller */ 00025 const uint8_t PS4_BUTTONS[] PROGMEM = { 00026 UP, // UP 00027 RIGHT, // RIGHT 00028 DOWN, // DOWN 00029 LEFT, // LEFT 00030 00031 0x0C, // SHARE 00032 0x0D, // OPTIONS 00033 0x0E, // L3 00034 0x0F, // R3 00035 00036 0x0A, // L2 00037 0x0B, // R2 00038 0x08, // L1 00039 0x09, // R1 00040 00041 0x07, // TRIANGLE 00042 0x06, // CIRCLE 00043 0x05, // CROSS 00044 0x04, // SQUARE 00045 00046 0x10, // PS 00047 0x11, // TOUCHPAD 00048 }; 00049 00050 union PS4Buttons { 00051 struct { 00052 uint8_t dpad : 4; 00053 uint8_t square : 1; 00054 uint8_t cross : 1; 00055 uint8_t circle : 1; 00056 uint8_t triangle : 1; 00057 00058 uint8_t l1 : 1; 00059 uint8_t r1 : 1; 00060 uint8_t l2 : 1; 00061 uint8_t r2 : 1; 00062 uint8_t share : 1; 00063 uint8_t options : 1; 00064 uint8_t l3 : 1; 00065 uint8_t r3 : 1; 00066 00067 uint8_t ps : 1; 00068 uint8_t touchpad : 1; 00069 uint8_t reportCounter : 6; 00070 } __attribute__((packed)); 00071 uint32_t val : 24; 00072 } __attribute__((packed)); 00073 00074 struct touchpadXY { 00075 uint8_t dummy; // I can not figure out what this data is for, it seems to change randomly, maybe a timestamp? 00076 struct { 00077 uint8_t counter : 7; // Increments every time a finger is touching the touchpad 00078 uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad 00079 uint16_t x : 12; 00080 uint16_t y : 12; 00081 } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger 00082 } __attribute__((packed)); 00083 00084 struct PS4Status { 00085 uint8_t battery : 4; 00086 uint8_t usb : 1; 00087 uint8_t audio : 1; 00088 uint8_t mic : 1; 00089 uint8_t unknown : 1; // Extension port? 00090 } __attribute__((packed)); 00091 00092 struct PS4Data { 00093 /* Button and joystick values */ 00094 uint8_t hatValue[4]; 00095 PS4Buttons btn; 00096 uint8_t trigger[2]; 00097 00098 /* Gyro and accelerometer values */ 00099 uint8_t dummy[3]; // First two looks random, while the third one might be some kind of status - it increments once in a while 00100 int16_t gyroY, gyroZ, gyroX; 00101 int16_t accX, accZ, accY; 00102 00103 uint8_t dummy2[5]; 00104 PS4Status status; 00105 uint8_t dummy3[3]; 00106 00107 /* The rest is data for the touchpad */ 00108 touchpadXY xy[3]; // It looks like it sends out three coordinates each time, this might be because the microcontroller inside the PS4 controller is much faster than the Bluetooth connection. 00109 // The last data is read from the last position in the array while the oldest measurement is from the first position. 00110 // The first position will also keep it's value after the finger is released, while the other two will set them to zero. 00111 // Note that if you read fast enough from the device, then only the first one will contain any data. 00112 00113 // The last three bytes are always: 0x00, 0x80, 0x00 00114 } __attribute__((packed)); 00115 00116 struct PS4Output { 00117 uint8_t bigRumble, smallRumble; // Rumble 00118 uint8_t r, g, b; // RGB 00119 uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds) 00120 bool reportChanged; // The data is send when data is received from the controller 00121 } __attribute__((packed)); 00122 00123 /** This class parses all the data sent by the PS4 controller */ 00124 class PS4Parser { 00125 public: 00126 /** Constructor for the PS4Parser class. */ 00127 PS4Parser() { 00128 Reset(); 00129 }; 00130 00131 /** @name PS4 Controller functions */ 00132 /** 00133 * getButtonPress(ButtonEnum b) will return true as long as the button is held down. 00134 * 00135 * While getButtonClick(ButtonEnum b) will only return it once. 00136 * 00137 * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b), 00138 * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b). 00139 * @param b ::ButtonEnum to read. 00140 * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press. 00141 */ 00142 bool getButtonPress(ButtonEnum b); 00143 bool getButtonClick(ButtonEnum b); 00144 /**@}*/ 00145 /** @name PS4 Controller functions */ 00146 /** 00147 * Used to get the analog value from button presses. 00148 * @param b The ::ButtonEnum to read. 00149 * The supported buttons are: 00150 * ::L2 and ::R2. 00151 * @return Analog value in the range of 0-255. 00152 */ 00153 uint8_t getAnalogButton(ButtonEnum b); 00154 00155 /** 00156 * Used to read the analog joystick. 00157 * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. 00158 * @return Return the analog value in the range of 0-255. 00159 */ 00160 uint8_t getAnalogHat(AnalogHatEnum a); 00161 00162 /** 00163 * Get the x-coordinate of the touchpad. Position 0 is in the top left. 00164 * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. 00165 * @param xyId The controller sends out three packets with the same structure. 00166 * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. 00167 * For that reason it will be set to 0 if the argument is omitted. 00168 * @return Returns the x-coordinate of the finger. 00169 */ 00170 uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) { 00171 return ps4Data.xy[xyId].finger[finger].x; 00172 }; 00173 00174 /** 00175 * Get the y-coordinate of the touchpad. Position 0 is in the top left. 00176 * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. 00177 * @param xyId The controller sends out three packets with the same structure. 00178 * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. 00179 * For that reason it will be set to 0 if the argument is omitted. 00180 * @return Returns the y-coordinate of the finger. 00181 */ 00182 uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) { 00183 return ps4Data.xy[xyId].finger[finger].y; 00184 }; 00185 00186 /** 00187 * Returns whenever the user is toucing the touchpad. 00188 * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. 00189 * @param xyId The controller sends out three packets with the same structure. 00190 * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. 00191 * For that reason it will be set to 0 if the argument is omitted. 00192 * @return Returns true if the specific finger is touching the touchpad. 00193 */ 00194 bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) { 00195 return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad 00196 }; 00197 00198 /** 00199 * This counter increments every time a finger touches the touchpad. 00200 * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used. 00201 * @param xyId The controller sends out three packets with the same structure. 00202 * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one. 00203 * For that reason it will be set to 0 if the argument is omitted. 00204 * @return Return the value of the counter, note that it is only a 7-bit value. 00205 */ 00206 uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) { 00207 return ps4Data.xy[xyId].finger[finger].counter; 00208 }; 00209 00210 /** 00211 * Get the angle of the controller calculated using the accelerometer. 00212 * @param a Either ::Pitch or ::Roll. 00213 * @return Return the angle in the range of 0-360. 00214 */ 00215 float getAngle(AngleEnum a) { 00216 if (a == Pitch) 00217 return (atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG; 00218 else 00219 return (atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG; 00220 }; 00221 00222 /** 00223 * Used to get the raw values from the 3-axis gyroscope and 3-axis accelerometer inside the PS4 controller. 00224 * @param s The sensor to read. 00225 * @return Returns the raw sensor reading. 00226 */ 00227 int16_t getSensor(SensorEnum s) { 00228 switch(s) { 00229 case gX: 00230 return ps4Data.gyroX; 00231 case gY: 00232 return ps4Data.gyroY; 00233 case gZ: 00234 return ps4Data.gyroZ; 00235 case aX: 00236 return ps4Data.accX; 00237 case aY: 00238 return ps4Data.accY; 00239 case aZ: 00240 return ps4Data.accZ; 00241 default: 00242 return 0; 00243 } 00244 }; 00245 00246 /** 00247 * Return the battery level of the PS4 controller. 00248 * @return The battery level in the range 0-15. 00249 */ 00250 uint8_t getBatteryLevel() { 00251 return ps4Data.status.battery; 00252 }; 00253 00254 /** 00255 * Use this to check if an USB cable is connected to the PS4 controller. 00256 * @return Returns true if an USB cable is connected. 00257 */ 00258 bool getUsbStatus() { 00259 return ps4Data.status.usb; 00260 }; 00261 00262 /** 00263 * Use this to check if an audio jack cable is connected to the PS4 controller. 00264 * @return Returns true if an audio jack cable is connected. 00265 */ 00266 bool getAudioStatus() { 00267 return ps4Data.status.audio; 00268 }; 00269 00270 /** 00271 * Use this to check if a microphone is connected to the PS4 controller. 00272 * @return Returns true if a microphone is connected. 00273 */ 00274 bool getMicStatus() { 00275 return ps4Data.status.mic; 00276 }; 00277 00278 /** Turn both rumble and the LEDs off. */ 00279 void setAllOff() { 00280 setRumbleOff(); 00281 setLedOff(); 00282 }; 00283 00284 /** Set rumble off. */ 00285 void setRumbleOff() { 00286 setRumbleOn(0, 0); 00287 }; 00288 00289 /** 00290 * Turn on rumble. 00291 * @param mode Either ::RumbleHigh or ::RumbleLow. 00292 */ 00293 void setRumbleOn(RumbleEnum mode) { 00294 if (mode == RumbleLow) 00295 setRumbleOn(0x00, 0xFF); 00296 else 00297 setRumbleOn(0xFF, 0x00); 00298 }; 00299 00300 /** 00301 * Turn on rumble. 00302 * @param bigRumble Value for big motor. 00303 * @param smallRumble Value for small motor. 00304 */ 00305 void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) { 00306 ps4Output.bigRumble = bigRumble; 00307 ps4Output.smallRumble = smallRumble; 00308 ps4Output.reportChanged = true; 00309 }; 00310 00311 /** Turn all LEDs off. */ 00312 void setLedOff() { 00313 setLed(0, 0, 0); 00314 }; 00315 00316 /** 00317 * Use this to set the color using RGB values. 00318 * @param r,g,b RGB value. 00319 */ 00320 void setLed(uint8_t r, uint8_t g, uint8_t b) { 00321 ps4Output.r = r; 00322 ps4Output.g = g; 00323 ps4Output.b = b; 00324 ps4Output.reportChanged = true; 00325 }; 00326 00327 /** 00328 * Use this to set the color using the predefined colors in ::ColorsEnum. 00329 * @param color The desired color. 00330 */ 00331 void setLed(ColorsEnum color) { 00332 setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); 00333 }; 00334 00335 /** 00336 * Set the LEDs flash time. 00337 * @param flashOn Time to flash bright (255 = 2.5 seconds). 00338 * @param flashOff Time to flash dark (255 = 2.5 seconds). 00339 */ 00340 void setLedFlash(uint8_t flashOn, uint8_t flashOff) { 00341 ps4Output.flashOn = flashOn; 00342 ps4Output.flashOff = flashOff; 00343 ps4Output.reportChanged = true; 00344 }; 00345 /**@}*/ 00346 00347 protected: 00348 /** 00349 * Used to parse data sent from the PS4 controller. 00350 * @param len Length of the data. 00351 * @param buf Pointer to the data buffer. 00352 */ 00353 void Parse(uint8_t len, uint8_t *buf); 00354 00355 /** Used to reset the different buffers to their default values */ 00356 void Reset(); 00357 00358 /** 00359 * Send the output to the PS4 controller. This is implemented in PS4BT.h and PS4USB.h. 00360 * @param output Pointer to PS4Output buffer; 00361 */ 00362 virtual void sendOutputReport(PS4Output *output) = 0; 00363 00364 private: 00365 bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons 00366 00367 PS4Data ps4Data; 00368 PS4Buttons oldButtonState, buttonClickState; 00369 PS4Output ps4Output; 00370 uint8_t oldDpad; 00371 }; 00372 #endif 00373
Generated on Thu Jul 14 2022 08:33:41 by
1.7.2