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.
Dependents: UsbHostMAX3421E_Hello
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) + M_PI) * RAD_TO_DEG; 00218 else 00219 return (atan2f(ps4Data.accX, ps4Data.accZ) + M_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
Generated on Tue Jul 12 2022 18:12:05 by
