USB Host Shield 2.0
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 
124 class PS4Parser {
125 public:
128  Reset();
129  };
130 
142  bool getButtonPress(ButtonEnum b);
143  bool getButtonClick(ButtonEnum b);
153  uint8_t getAnalogButton(ButtonEnum b);
154 
160  uint8_t getAnalogHat(AnalogHatEnum a);
161 
170  uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) {
171  return ps4Data.xy[xyId].finger[finger].x;
172  };
173 
182  uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) {
183  return ps4Data.xy[xyId].finger[finger].y;
184  };
185 
194  bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) {
195  return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad
196  };
197 
206  uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) {
207  return ps4Data.xy[xyId].finger[finger].counter;
208  };
209 
215  float getAngle(AngleEnum a) {
216  if (a == Pitch)
217  return (atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
218  else
219  return (atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;
220  };
221 
227  int16_t getSensor(SensorEnum s) {
228  switch(s) {
229  case gX:
230  return ps4Data.gyroX;
231  case gY:
232  return ps4Data.gyroY;
233  case gZ:
234  return ps4Data.gyroZ;
235  case aX:
236  return ps4Data.accX;
237  case aY:
238  return ps4Data.accY;
239  case aZ:
240  return ps4Data.accZ;
241  default:
242  return 0;
243  }
244  };
245 
250  uint8_t getBatteryLevel() {
251  return ps4Data.status.battery;
252  };
253 
258  bool getUsbStatus() {
259  return ps4Data.status.usb;
260  };
261 
266  bool getAudioStatus() {
267  return ps4Data.status.audio;
268  };
269 
274  bool getMicStatus() {
275  return ps4Data.status.mic;
276  };
277 
279  void setAllOff() {
280  setRumbleOff();
281  setLedOff();
282  };
283 
285  void setRumbleOff() {
286  setRumbleOn(0, 0);
287  };
288 
293  void setRumbleOn(RumbleEnum mode) {
294  if (mode == RumbleLow)
295  setRumbleOn(0x00, 0xFF);
296  else
297  setRumbleOn(0xFF, 0x00);
298  };
299 
305  void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
306  ps4Output.bigRumble = bigRumble;
307  ps4Output.smallRumble = smallRumble;
308  ps4Output.reportChanged = true;
309  };
310 
312  void setLedOff() {
313  setLed(0, 0, 0);
314  };
315 
320  void setLed(uint8_t r, uint8_t g, uint8_t b) {
321  ps4Output.r = r;
322  ps4Output.g = g;
323  ps4Output.b = b;
324  ps4Output.reportChanged = true;
325  };
326 
331  void setLed(ColorsEnum color) {
332  setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
333  };
334 
340  void setLedFlash(uint8_t flashOn, uint8_t flashOff) {
341  ps4Output.flashOn = flashOn;
342  ps4Output.flashOff = flashOff;
343  ps4Output.reportChanged = true;
344  };
347 protected:
353  void Parse(uint8_t len, uint8_t *buf);
354 
356  void Reset();
357 
362  virtual void sendOutputReport(PS4Output *output) = 0;
363 
364 private:
365  static int8_t getButtonIndexPS4(ButtonEnum b);
366  bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons
367 
368  PS4Data ps4Data;
369  PS4Buttons oldButtonState, buttonClickState;
370  PS4Output ps4Output;
371  uint8_t oldDpad;
372 };
373 #endif
const uint8_t PS4_BUTTONS[]
Definition: PS4Parser.h:25
uint8_t getTouchCounter(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:206
void Reset()
Definition: PS4Parser.cpp:139
void setLedFlash(uint8_t flashOn, uint8_t flashOff)
Definition: PS4Parser.h:340
int16_t getSensor(SensorEnum s)
Definition: PS4Parser.h:227
void setLed(uint8_t r, uint8_t g, uint8_t b)
Definition: PS4Parser.h:320
void setRumbleOn(RumbleEnum mode)
Definition: PS4Parser.h:293
void setLed(ColorsEnum color)
Definition: PS4Parser.h:331
void Parse(uint8_t len, uint8_t *buf)
Definition: PS4Parser.cpp:85
uint8_t getAnalogButton(ButtonEnum b)
Definition: PS4Parser.cpp:72
bool isTouching(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:194
void setLedOff()
Definition: PS4Parser.h:312
void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble)
Definition: PS4Parser.h:305
virtual void sendOutputReport(PS4Output *output)=0
bool getButtonClick(ButtonEnum b)
Definition: PS4Parser.cpp:64
uint8_t getBatteryLevel()
Definition: PS4Parser.h:250
uint16_t getY(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:182
uint8_t getAnalogHat(AnalogHatEnum a)
Definition: PS4Parser.cpp:81
uint16_t getX(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:170
bool getUsbStatus()
Definition: PS4Parser.h:258
void setRumbleOff()
Definition: PS4Parser.h:285
bool getMicStatus()
Definition: PS4Parser.h:274
bool getButtonPress(ButtonEnum b)
Definition: PS4Parser.cpp:56
void setAllOff()
Definition: PS4Parser.h:279
bool getAudioStatus()
Definition: PS4Parser.h:266
float getAngle(AngleEnum a)
Definition: PS4Parser.h:215
SensorEnum
@ gY
@ gX
@ aX
@ aZ
@ gZ
@ aY
AnalogHatEnum
AngleEnum
@ Pitch
ButtonEnum
@ DOWN
@ UP
@ LEFT
@ RIGHT
ColorsEnum
RumbleEnum
@ RumbleLow
int16_t gyroX
Definition: PS4Parser.h:100
uint8_t dummy2[5]
Definition: PS4Parser.h:103
touchpadXY xy[3]
Definition: PS4Parser.h:108
int16_t gyroY
Definition: PS4Parser.h:100
PS4Status status
Definition: PS4Parser.h:104
PS4Buttons btn
Definition: PS4Parser.h:95
int16_t accZ
Definition: PS4Parser.h:101
int16_t accX
Definition: PS4Parser.h:101
int16_t accY
Definition: PS4Parser.h:101
uint8_t hatValue[4]
Definition: PS4Parser.h:94
uint8_t trigger[2]
Definition: PS4Parser.h:96
int16_t gyroZ
Definition: PS4Parser.h:100
uint8_t dummy3[3]
Definition: PS4Parser.h:105
uint8_t dummy[3]
Definition: PS4Parser.h:99
uint8_t b
Definition: PS4Parser.h:118
uint8_t flashOff
Definition: PS4Parser.h:119
uint8_t flashOn
Definition: PS4Parser.h:119
uint8_t r
Definition: PS4Parser.h:118
uint8_t smallRumble
Definition: PS4Parser.h:117
uint8_t bigRumble
Definition: PS4Parser.h:117
uint8_t g
Definition: PS4Parser.h:118
bool reportChanged
Definition: PS4Parser.h:120
uint8_t mic
Definition: PS4Parser.h:88
uint8_t audio
Definition: PS4Parser.h:87
uint8_t usb
Definition: PS4Parser.h:86
uint8_t unknown
Definition: PS4Parser.h:89
uint8_t battery
Definition: PS4Parser.h:85
uint16_t x
Definition: PS4Parser.h:79
struct touchpadXY::@28 finger[2]
uint8_t touching
Definition: PS4Parser.h:78
uint8_t dummy
Definition: PS4Parser.h:75
uint16_t y
Definition: PS4Parser.h:80
uint8_t counter
Definition: PS4Parser.h:77
uint8_t r3
Definition: PS4Parser.h:65
uint8_t cross
Definition: PS4Parser.h:54
uint8_t options
Definition: PS4Parser.h:63
uint8_t l1
Definition: PS4Parser.h:58
uint8_t r2
Definition: PS4Parser.h:61
uint8_t reportCounter
Definition: PS4Parser.h:69
uint8_t ps
Definition: PS4Parser.h:67
uint8_t triangle
Definition: PS4Parser.h:56
uint8_t touchpad
Definition: PS4Parser.h:68
uint8_t square
Definition: PS4Parser.h:53
uint8_t circle
Definition: PS4Parser.h:55
uint8_t l2
Definition: PS4Parser.h:60
uint8_t dpad
Definition: PS4Parser.h:52
uint32_t val
Definition: PS4Parser.h:71
uint8_t l3
Definition: PS4Parser.h:64
uint8_t r1
Definition: PS4Parser.h:59
uint8_t share
Definition: PS4Parser.h:62