diff options
Diffstat (limited to 'lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp')
-rw-r--r-- | lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp b/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp new file mode 100644 index 000000000..ca6adce40 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/PS4Parser.cpp | |||
@@ -0,0 +1,116 @@ | |||
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 | // To enable serial debugging see "settings.h" | ||
21 | //#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller | ||
22 | |||
23 | bool PS4Parser::checkDpad(ButtonEnum b) { | ||
24 | switch (b) { | ||
25 | case UP: | ||
26 | return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT; | ||
27 | case RIGHT: | ||
28 | return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN; | ||
29 | case DOWN: | ||
30 | return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT; | ||
31 | case LEFT: | ||
32 | return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP; | ||
33 | default: | ||
34 | return false; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | bool PS4Parser::getButtonPress(ButtonEnum b) { | ||
39 | if (b <= LEFT) // Dpad | ||
40 | return checkDpad(b); | ||
41 | else | ||
42 | return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b])); | ||
43 | } | ||
44 | |||
45 | bool PS4Parser::getButtonClick(ButtonEnum b) { | ||
46 | uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]); | ||
47 | bool click = buttonClickState.val & mask; | ||
48 | buttonClickState.val &= ~mask; // Clear "click" event | ||
49 | return click; | ||
50 | } | ||
51 | |||
52 | uint8_t PS4Parser::getAnalogButton(ButtonEnum b) { | ||
53 | if (b == L2) // These are the only analog buttons on the controller | ||
54 | return ps4Data.trigger[0]; | ||
55 | else if (b == R2) | ||
56 | return ps4Data.trigger[1]; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | uint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) { | ||
61 | return ps4Data.hatValue[(uint8_t)a]; | ||
62 | } | ||
63 | |||
64 | void PS4Parser::Parse(uint8_t len, uint8_t *buf) { | ||
65 | if (len > 1 && buf) { | ||
66 | #ifdef PRINTREPORT | ||
67 | Notify(PSTR("\r\n"), 0x80); | ||
68 | for (uint8_t i = 0; i < len; i++) { | ||
69 | D_PrintHex<uint8_t > (buf[i], 0x80); | ||
70 | Notify(PSTR(" "), 0x80); | ||
71 | } | ||
72 | #endif | ||
73 | |||
74 | if (buf[0] == 0x01) // Check report ID | ||
75 | memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), sizeof(ps4Data))); | ||
76 | else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data | ||
77 | if (len < 4) { | ||
78 | #ifdef DEBUG_USB_HOST | ||
79 | Notify(PSTR("\r\nReport is too short: "), 0x80); | ||
80 | D_PrintHex<uint8_t > (len, 0x80); | ||
81 | #endif | ||
82 | return; | ||
83 | } | ||
84 | memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), sizeof(ps4Data))); | ||
85 | } else { | ||
86 | #ifdef DEBUG_USB_HOST | ||
87 | Notify(PSTR("\r\nUnknown report id: "), 0x80); | ||
88 | D_PrintHex<uint8_t > (buf[0], 0x80); | ||
89 | #endif | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed | ||
94 | buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable | ||
95 | oldButtonState.val = ps4Data.btn.val; | ||
96 | |||
97 | // 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 | ||
98 | uint8_t newDpad = 0; | ||
99 | if (checkDpad(UP)) | ||
100 | newDpad |= 1 << UP; | ||
101 | if (checkDpad(RIGHT)) | ||
102 | newDpad |= 1 << RIGHT; | ||
103 | if (checkDpad(DOWN)) | ||
104 | newDpad |= 1 << DOWN; | ||
105 | if (checkDpad(LEFT)) | ||
106 | newDpad |= 1 << LEFT; | ||
107 | if (newDpad != oldDpad) { | ||
108 | buttonClickState.dpad = newDpad & ~oldDpad; // Override values | ||
109 | oldDpad = newDpad; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (ps4Output.reportChanged) | ||
115 | sendOutputReport(&ps4Output); // Send output report | ||
116 | } | ||