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);
154  uint8_t getAnalogButton(ButtonEnum b);
155 
161  uint8_t getAnalogHat(AnalogHatEnum a);
162 
171  uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) {
172  return ps4Data.xy[xyId].finger[finger].x;
173  };
174 
183  uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) {
184  return ps4Data.xy[xyId].finger[finger].y;
185  };
186 
195  bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) {
196  return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad
197  };
198 
207  uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) {
208  return ps4Data.xy[xyId].finger[finger].counter;
209  };
210 
216  float getAngle(AngleEnum a) {
217  if (a == Pitch)
218  return (atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
219  else
220  return (atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;
221  };
222 
228  int16_t getSensor(SensorEnum s) {
229  switch(s) {
230  case gX:
231  return ps4Data.gyroX;
232  case gY:
233  return ps4Data.gyroY;
234  case gZ:
235  return ps4Data.gyroZ;
236  case aX:
237  return ps4Data.accX;
238  case aY:
239  return ps4Data.accY;
240  case aZ:
241  return ps4Data.accZ;
242  default:
243  return 0;
244  }
245  };
246 
251  uint8_t getBatteryLevel() {
252  return ps4Data.status.battery;
253  };
254 
259  bool getUsbStatus() {
260  return ps4Data.status.usb;
261  };
262 
267  bool getAudioStatus() {
268  return ps4Data.status.audio;
269  };
270 
275  bool getMicStatus() {
276  return ps4Data.status.mic;
277  };
278 
280  void setAllOff() {
281  setRumbleOff();
282  setLedOff();
283  };
284 
286  void setRumbleOff() {
287  setRumbleOn(0, 0);
288  };
289 
294  void setRumbleOn(RumbleEnum mode) {
295  if (mode == RumbleLow)
296  setRumbleOn(0x00, 0xFF);
297  else
298  setRumbleOn(0xFF, 0x00);
299  };
300 
306  void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
307  ps4Output.bigRumble = bigRumble;
308  ps4Output.smallRumble = smallRumble;
309  ps4Output.reportChanged = true;
310  };
311 
313  void setLedOff() {
314  setLed(0, 0, 0);
315  };
316 
321  void setLed(uint8_t r, uint8_t g, uint8_t b) {
322  ps4Output.r = r;
323  ps4Output.g = g;
324  ps4Output.b = b;
325  ps4Output.reportChanged = true;
326  };
327 
332  void setLed(ColorsEnum color) {
333  setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
334  };
335 
341  void setLedFlash(uint8_t flashOn, uint8_t flashOff) {
342  ps4Output.flashOn = flashOn;
343  ps4Output.flashOff = flashOff;
344  ps4Output.reportChanged = true;
345  };
348 protected:
354  void Parse(uint8_t len, uint8_t *buf);
355 
357  void Reset();
358 
363  virtual void sendOutputReport(PS4Output *output) = 0;
364 
365 private:
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
uint8_t getBatteryLevel()
Definition: PS4Parser.h:251
uint32_t val
Definition: PS4Parser.h:71
uint16_t getY(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:183
uint8_t r1
Definition: PS4Parser.h:59
PS4Status status
Definition: PS4Parser.h:104
void setLed(uint8_t r, uint8_t g, uint8_t b)
Definition: PS4Parser.h:321
AnalogHatEnum
uint8_t reportCounter
Definition: PS4Parser.h:69
void setLed(ColorsEnum color)
Definition: PS4Parser.h:332
void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble)
Definition: PS4Parser.h:306
int16_t getSensor(SensorEnum s)
Definition: PS4Parser.h:228
uint8_t flashOn
Definition: PS4Parser.h:119
uint8_t share
Definition: PS4Parser.h:62
void setRumbleOn(RumbleEnum mode)
Definition: PS4Parser.h:294
uint8_t dummy
Definition: PS4Parser.h:75
uint8_t cross
Definition: PS4Parser.h:54
void setAllOff()
Definition: PS4Parser.h:280
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:195
const uint8_t PS4_BUTTONS[]
Definition: PS4Parser.h:25
ButtonEnum
uint8_t r
Definition: PS4Parser.h:118
void setRumbleOff()
Definition: PS4Parser.h:286
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:313
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:171
uint8_t triangle
Definition: PS4Parser.h:56
uint8_t r2
Definition: PS4Parser.h:61
float getAngle(AngleEnum a)
Definition: PS4Parser.h:216
uint8_t getTouchCounter(uint8_t finger=0, uint8_t xyId=0)
Definition: PS4Parser.h:207
uint8_t options
Definition: PS4Parser.h:63
bool getMicStatus()
Definition: PS4Parser.h:275
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
int16_t accZ
Definition: PS4Parser.h:101
void setLedFlash(uint8_t flashOn, uint8_t flashOff)
Definition: PS4Parser.h:341
bool getUsbStatus()
Definition: PS4Parser.h:259
bool getAudioStatus()
Definition: PS4Parser.h:267