USB Host Shield 2.0
PS4Parser.cpp
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 #include "PS4Parser.h"
19 
20 enum DPADEnum {
21  DPAD_UP = 0x0,
23  DPAD_RIGHT = 0x2,
25  DPAD_DOWN = 0x4,
27  DPAD_LEFT = 0x6,
28  DPAD_LEFT_UP = 0x7,
29  DPAD_OFF = 0x8,
30 };
31 
32 // To enable serial debugging see "settings.h"
33 //#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller
34 
35 bool PS4Parser::checkDpad(ButtonEnum b) {
36  switch (b) {
37  case UP:
38  return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT;
39  case RIGHT:
40  return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN;
41  case DOWN:
42  return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT;
43  case LEFT:
44  return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP;
45  default:
46  return false;
47  }
48 }
49 
51  if (b <= LEFT) // Dpad
52  return checkDpad(b);
53  else
54  return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]));
55 }
56 
58  uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);
59  bool click = buttonClickState.val & mask;
60  buttonClickState.val &= ~mask; // Clear "click" event
61  return click;
62 }
63 
65  if (b == L2) // These are the only analog buttons on the controller
66  return ps4Data.trigger[0];
67  else if (b == R2)
68  return ps4Data.trigger[1];
69  return 0;
70 }
71 
73  return ps4Data.hatValue[(uint8_t)a];
74 }
75 
76 void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
77  if (len > 1 && buf) {
78 #ifdef PRINTREPORT
79  Notify(PSTR("\r\n"), 0x80);
80  for (uint8_t i = 0; i < len; i++) {
81  D_PrintHex<uint8_t > (buf[i], 0x80);
82  Notify(PSTR(" "), 0x80);
83  }
84 #endif
85 
86  if (buf[0] == 0x01) // Check report ID
87  memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps4Data)));
88  else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
89  if (len < 4) {
90 #ifdef DEBUG_USB_HOST
91  Notify(PSTR("\r\nReport is too short: "), 0x80);
92  D_PrintHex<uint8_t > (len, 0x80);
93 #endif
94  return;
95  }
96  memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), MFK_CASTUINT8T sizeof(ps4Data)));
97  } else {
98 #ifdef DEBUG_USB_HOST
99  Notify(PSTR("\r\nUnknown report id: "), 0x80);
100  D_PrintHex<uint8_t > (buf[0], 0x80);
101 #endif
102  return;
103  }
104 
105  if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed
106  buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable
107  oldButtonState.val = ps4Data.btn.val;
108 
109  // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself
110  uint8_t newDpad = 0;
111  if (checkDpad(UP))
112  newDpad |= 1 << UP;
113  if (checkDpad(RIGHT))
114  newDpad |= 1 << RIGHT;
115  if (checkDpad(DOWN))
116  newDpad |= 1 << DOWN;
117  if (checkDpad(LEFT))
118  newDpad |= 1 << LEFT;
119  if (newDpad != oldDpad) {
120  buttonClickState.dpad = newDpad & ~oldDpad; // Override values
121  oldDpad = newDpad;
122  }
123  }
124  }
125 
126  if (ps4Output.reportChanged)
127  sendOutputReport(&ps4Output); // Send output report
128 }
129 
131  uint8_t i;
132  for (i = 0; i < sizeof(ps4Data.hatValue); i++)
133  ps4Data.hatValue[i] = 127; // Center value
134  ps4Data.btn.val = 0;
135  oldButtonState.val = 0;
136  for (i = 0; i < sizeof(ps4Data.trigger); i++)
137  ps4Data.trigger[i] = 0;
138  for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
139  for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
140  ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
141  }
142 
143  ps4Data.btn.dpad = DPAD_OFF;
144  oldButtonState.dpad = DPAD_OFF;
145  buttonClickState.dpad = 0;
146  oldDpad = 0;
147 
148  ps4Output.bigRumble = ps4Output.smallRumble = 0;
149  ps4Output.r = ps4Output.g = ps4Output.b = 0;
150  ps4Output.flashOn = ps4Output.flashOff = 0;
151  ps4Output.reportChanged = false;
152 };
153 
void Reset()
Definition: PS4Parser.cpp:130
uint32_t val
Definition: PS4Parser.h:71
uint8_t hatValue[4]
Definition: PS4Parser.h:94
uint8_t b
Definition: PS4Parser.h:118
bool getButtonPress(ButtonEnum b)
Definition: PS4Parser.cpp:50
AnalogHatEnum
DPADEnum
Definition: PS4Parser.cpp:20
uint8_t touching
Definition: PS4Parser.h:78
uint8_t flashOn
Definition: PS4Parser.h:119
struct touchpadXY::@28 finger[2]
#define pgm_read_byte(addr)
#define Notify(...)
Definition: message.h:51
uint8_t g
Definition: PS4Parser.h:118
bool reportChanged
Definition: PS4Parser.h:120
void Parse(uint8_t len, uint8_t *buf)
Definition: PS4Parser.cpp:76
uint8_t trigger[2]
Definition: PS4Parser.h:96
const uint8_t PS4_BUTTONS[]
Definition: PS4Parser.h:25
ButtonEnum
uint8_t r
Definition: PS4Parser.h:118
uint8_t bigRumble
Definition: PS4Parser.h:117
virtual void sendOutputReport(PS4Output *output)=0
uint8_t flashOff
Definition: PS4Parser.h:119
uint8_t smallRumble
Definition: PS4Parser.h:117
#define PSTR(str)
#define MFK_CASTUINT8T
Definition: settings.h:194
uint8_t dpad
Definition: PS4Parser.h:52
touchpadXY xy[3]
Definition: PS4Parser.h:108
uint8_t getAnalogButton(ButtonEnum b)
Definition: PS4Parser.cpp:64
PS4Buttons btn
Definition: PS4Parser.h:95
bool getButtonClick(ButtonEnum b)
Definition: PS4Parser.cpp:57
uint8_t getAnalogHat(AnalogHatEnum a)
Definition: PS4Parser.cpp:72