USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
PS4Parser.h
Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #ifndef _ps4parser_h_
19 #define _ps4parser_h_
20 
21 #include "Usb.h"
22 #include "controllerEnums.h"
23 
25 const uint8_t PS4_BUTTONS[] PROGMEM = {
26  UP, // UP
27  RIGHT, // RIGHT
28  DOWN, // DOWN
29  LEFT, // LEFT
30 
31  0x0C, // SHARE
32  0x0D, // OPTIONS
33  0x0E, // L3
34  0x0F, // R3
35 
36  0x0A, // L2
37  0x0B, // R2
38  0x08, // L1
39  0x09, // R1
40 
41  0x07, // TRIANGLE
42  0x06, // CIRCLE
43  0x05, // CROSS
44  0x04, // SQUARE
45 
46  0x10, // PS
47  0x11, // TOUCHPAD
48 };
49 
50 union PS4Buttons {
51  struct {
52  uint8_t dpad : 4;
53  uint8_t square : 1;
54  uint8_t cross : 1;
55  uint8_t circle : 1;
56  uint8_t triangle : 1;
57 
58  uint8_t l1 : 1;
59  uint8_t r1 : 1;
60  uint8_t l2 : 1;
61  uint8_t r2 : 1;
62  uint8_t share : 1;
63  uint8_t options : 1;
64  uint8_t l3 : 1;
65  uint8_t r3 : 1;
66 
67  uint8_t ps : 1;
68  uint8_t touchpad : 1;
69  uint8_t reportCounter : 6;
70  } __attribute__((packed));
71  uint32_t val : 24;
72 } __attribute__((packed));
73 
74 struct touchpadXY {
75  uint8_t dummy; // I can not figure out what this data is for, it seems to change randomly, maybe a timestamp?
76  struct {
77  uint8_t counter : 7; // Increments every time a finger is touching the touchpad
78  uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad
79  uint16_t x : 12;
80  uint16_t y : 12;
81  } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger
82 } __attribute__((packed));
83 
84 struct PS4Status {
85  uint8_t battery : 4;
86  uint8_t usb : 1;
87  uint8_t audio : 1;
88  uint8_t mic : 1;
89  uint8_t unknown : 1; // Extension port?
90 } __attribute__((packed));
91 
92 struct PS4Data {
93  /* Button and joystick values */
94  uint8_t hatValue[4];
96  uint8_t trigger[2];
97 
98  /* Gyro and accelerometer values */
99  uint8_t dummy[3]; // First two looks random, while the third one might be some kind of status - it increments once in a while
100  int16_t gyroY, gyroZ, gyroX;
101  int16_t accX, accZ, accY;
102 
103  uint8_t dummy2[5];
105  uint8_t dummy3[3];
106 
107  /* The rest is data for the touchpad */
108  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.
109  // The last data is read from the last position in the array while the oldest measurement is from the first position.
110  // The first position will also keep it's value after the finger is released, while the other two will set them to zero.
111  // Note that if you read fast enough from the device, then only the first one will contain any data.
112 
113  // The last three bytes are always: 0x00, 0x80, 0x00
114 } __attribute__((packed));
115 
116 struct PS4Output {
117  uint8_t bigRumble, smallRumble; // Rumble
118  uint8_t r, g, b; // RGB
119  uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds)
120  bool reportChanged; // The data is send when data is received from the controller
121 } __attribute__((packed));
122 
123 enum DPADEnum {
124  DPAD_UP = 0x0,
126  DPAD_RIGHT = 0x2,
128  DPAD_DOWN = 0x4,
130  DPAD_LEFT = 0x6,
132  DPAD_OFF = 0x8,
133 };
134 
136 class PS4Parser {
137 public:
140  Reset();
141  };
142 
154  bool getButtonPress(ButtonEnum b);
155  bool getButtonClick(ButtonEnum b);
166  uint8_t getAnalogButton(ButtonEnum b);
167 
173  uint8_t getAnalogHat(AnalogHatEnum a);
174 
183  uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) {
184  return ps4Data.xy[xyId].finger[finger].x;
185  };
186 
195  uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) {
196  return ps4Data.xy[xyId].finger[finger].y;
197  };
198 
207  bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) {
208  return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad
209  };
210 
219  uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) {
220  return ps4Data.xy[xyId].finger[finger].counter;
221  };
222 
228  double getAngle(AngleEnum a) {
229  if (a == Pitch)
230  return (atan2(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
231  else
232  return (atan2(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;
233  };
234 
240  int16_t getSensor(SensorEnum s) {
241  switch(s) {
242  case gX:
243  return ps4Data.gyroX;
244  case gY:
245  return ps4Data.gyroY;
246  case gZ:
247  return ps4Data.gyroZ;
248  case aX:
249  return ps4Data.accX;
250  case aY:
251  return ps4Data.accY;
252  case aZ:
253  return ps4Data.accZ;
254  default:
255  return 0;
256  }
257  };
258 
263  uint8_t getBatteryLevel() {
264  return ps4Data.status.battery;
265  };
266 
271  bool getUsbStatus() {
272  return ps4Data.status.usb;
273  };
274 
279  bool getAudioStatus() {
280  return ps4Data.status.audio;
281  };
282 
287  bool getMicStatus() {
288  return ps4Data.status.mic;
289  };
290 
292  void setAllOff() {
293  setRumbleOff();
294  setLedOff();
295  };
296 
298  void setRumbleOff() {
299  setRumbleOn(0, 0);
300  };
301 
306  void setRumbleOn(RumbleEnum mode) {
307  if (mode == RumbleLow)
308  setRumbleOn(0x00, 0xFF);
309  else
310  setRumbleOn(0xFF, 0x00);
311  };
312 
318  void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
319  ps4Output.bigRumble = bigRumble;
320  ps4Output.smallRumble = smallRumble;
321  ps4Output.reportChanged = true;
322  };
323 
325  void setLedOff() {
326  setLed(0, 0, 0);
327  };
328 
333  void setLed(uint8_t r, uint8_t g, uint8_t b) {
334  ps4Output.r = r;
335  ps4Output.g = g;
336  ps4Output.b = b;
337  ps4Output.reportChanged = true;
338  };
339 
344  void setLed(ColorsEnum color) {
345  setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
346  };
347 
353  void setLedFlash(uint8_t flashOn, uint8_t flashOff) {
354  ps4Output.flashOn = flashOn;
355  ps4Output.flashOff = flashOff;
356  ps4Output.reportChanged = true;
357  };
360 protected:
366  void Parse(uint8_t len, uint8_t *buf);
367 
369  void Reset() {
370  uint8_t i;
371  for (i = 0; i < sizeof(ps4Data.hatValue); i++)
372  ps4Data.hatValue[i] = 127; // Center value
373  ps4Data.btn.val = 0;
374  oldButtonState.val = 0;
375  for (i = 0; i < sizeof(ps4Data.trigger); i++)
376  ps4Data.trigger[i] = 0;
377  for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
378  for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
379  ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
380  }
381 
382  ps4Data.btn.dpad = DPAD_OFF;
383  oldButtonState.dpad = DPAD_OFF;
384  buttonClickState.dpad = 0;
385  oldDpad = 0;
386 
387  ps4Output.bigRumble = ps4Output.smallRumble = 0;
388  ps4Output.r = ps4Output.g = ps4Output.b = 0;
389  ps4Output.flashOn = ps4Output.flashOff = 0;
390  ps4Output.reportChanged = false;
391  };
392 
397  virtual void sendOutputReport(PS4Output *output) = 0;
398 
399 private:
400  bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons
401 
402  PS4Data ps4Data;
403  PS4Buttons oldButtonState, buttonClickState;
404  PS4Output ps4Output;
405  uint8_t oldDpad;
406 };
407 #endif
uint8_t getBatteryLevel()
Definition: PS4Parser.h:263
DPADEnum
Definition: PS4Parser.h:123
void Reset()
Definition: PS4Parser.h:369
uint32_t val
Definition: PS4Parser.h:71
uint16_t getY(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:195
uint8_t r1
Definition: PS4Parser.h:59
PS4Status status
Definition: PS4Parser.h:104
double getAngle(AngleEnum a)
Definition: PS4Parser.h:228
void setLed(uint8_t r, uint8_t g, uint8_t b)
Definition: PS4Parser.h:333
AnalogHatEnum
uint8_t reportCounter
Definition: PS4Parser.h:69
void setLed(ColorsEnum color)
Definition: PS4Parser.h:344
void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble)
Definition: PS4Parser.h:318
uint8_t touching
Definition: PS4Parser.h:78
int16_t getSensor(SensorEnum s)
Definition: PS4Parser.h:240
uint8_t flashOn
Definition: PS4Parser.h:119
uint8_t share
Definition: PS4Parser.h:62
void setRumbleOn(RumbleEnum mode)
Definition: PS4Parser.h:306
uint8_t dummy
Definition: PS4Parser.h:75
uint8_t cross
Definition: PS4Parser.h:54
void setAllOff()
Definition: PS4Parser.h:292
uint8_t l2
Definition: PS4Parser.h:60
RumbleEnum
uint8_t square
Definition: PS4Parser.h:53
bool reportChanged
Definition: PS4Parser.h:120
uint8_t ps
Definition: PS4Parser.h:67
bool isTouching(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:207
uint8_t counter
Definition: PS4Parser.h:77
uint16_t y
Definition: PS4Parser.h:80
struct touchpadXY::@24 finger[2]
const uint8_t PS4_BUTTONS[]
Definition: PS4Parser.h:25
ButtonEnum
uint8_t r
Definition: PS4Parser.h:118
void setRumbleOff()
Definition: PS4Parser.h:298
uint8_t l1
Definition: PS4Parser.h:58
uint8_t smallRumble
Definition: PS4Parser.h:117
uint8_t r3
Definition: PS4Parser.h:65
void setLedOff()
Definition: PS4Parser.h:325
uint8_t dpad
Definition: PS4Parser.h:52
ColorsEnum
int16_t gyroZ
Definition: PS4Parser.h:100
AngleEnum
uint16_t getX(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:183
uint8_t triangle
Definition: PS4Parser.h:56
uint8_t r2
Definition: PS4Parser.h:61
uint8_t getTouchCounter(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:219
uint8_t options
Definition: PS4Parser.h:63
bool getMicStatus()
Definition: PS4Parser.h:287
uint8_t touchpad
Definition: PS4Parser.h:68
uint8_t l3
Definition: PS4Parser.h:64
PS4Buttons btn
Definition: PS4Parser.h:95
SensorEnum
uint8_t circle
Definition: PS4Parser.h:55
uint16_t x
Definition: PS4Parser.h:79
int16_t accZ
Definition: PS4Parser.h:101
void setLedFlash(uint8_t flashOn, uint8_t flashOff)
Definition: PS4Parser.h:353
bool getUsbStatus()
Definition: PS4Parser.h:271
bool getAudioStatus()
Definition: PS4Parser.h:279