1
+ /*
2
+ Joystick.cpp
3
+
4
+ Copyright (c) 2015, Matthew Heironimus
5
+
6
+ This library is free software; you can redistribute it and/or
7
+ modify it under the terms of the GNU Lesser General Public
8
+ License as published by the Free Software Foundation; either
9
+ version 2.1 of the License, or (at your option) any later version.
10
+
11
+ This library is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public
17
+ License along with this library; if not, write to the Free Software
18
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ #include " Joystick.h"
22
+
23
+ #if defined(_USING_HID)
24
+
25
+ #define JOYSTICK_REPORT_ID 0x03
26
+ #define JOYSTICK_STATE_SIZE 13
27
+
28
+ static const uint8_t _hidReportDescriptor[] PROGMEM = {
29
+
30
+ // Joystick
31
+ 0x05 , 0x01 , // USAGE_PAGE (Generic Desktop)
32
+ 0x09 , 0x04 , // USAGE (Joystick)
33
+ 0xa1 , 0x01 , // COLLECTION (Application)
34
+ 0x85 , JOYSTICK_REPORT_ID, // REPORT_ID (3)
35
+
36
+ // 32 Buttons
37
+ 0x05 , 0x09 , // USAGE_PAGE (Button)
38
+ 0x19 , 0x01 , // USAGE_MINIMUM (Button 1)
39
+ 0x29 , 0x20 , // USAGE_MAXIMUM (Button 32)
40
+ 0x15 , 0x00 , // LOGICAL_MINIMUM (0)
41
+ 0x25 , 0x01 , // LOGICAL_MAXIMUM (1)
42
+ 0x75 , 0x01 , // REPORT_SIZE (1)
43
+ 0x95 , 0x20 , // REPORT_COUNT (32)
44
+ 0x55 , 0x00 , // UNIT_EXPONENT (0)
45
+ 0x65 , 0x00 , // UNIT (None)
46
+ 0x81 , 0x02 , // INPUT (Data,Var,Abs)
47
+
48
+ // 8 bit Throttle and Steering
49
+ 0x05 , 0x02 , // USAGE_PAGE (Simulation Controls)
50
+ 0x15 , 0x00 , // LOGICAL_MINIMUM (0)
51
+ 0x26 , 0xff , 0x00 , // LOGICAL_MAXIMUM (255)
52
+ 0xA1 , 0x00 , // COLLECTION (Physical)
53
+ 0x09 , 0xBB , // USAGE (Throttle)
54
+ 0x09 , 0xBA , // USAGE (Steering)
55
+ 0x75 , 0x08 , // REPORT_SIZE (8)
56
+ 0x95 , 0x02 , // REPORT_COUNT (2)
57
+ 0x81 , 0x02 , // INPUT (Data,Var,Abs)
58
+ 0xc0 , // END_COLLECTION
59
+
60
+ // Two Hat switches (8 Positions)
61
+ 0x05 , 0x01 , // USAGE_PAGE (Generic Desktop)
62
+ 0x09 , 0x39 , // USAGE (Hat switch)
63
+ 0x15 , 0x00 , // LOGICAL_MINIMUM (0)
64
+ 0x25 , 0x07 , // LOGICAL_MAXIMUM (7)
65
+ 0x35 , 0x00 , // PHYSICAL_MINIMUM (0)
66
+ 0x46 , 0x3B , 0x01 , // PHYSICAL_MAXIMUM (315)
67
+ 0x65 , 0x14 , // UNIT (Eng Rot:Angular Pos)
68
+ 0x75 , 0x04 , // REPORT_SIZE (4)
69
+ 0x95 , 0x01 , // REPORT_COUNT (1)
70
+ 0x81 , 0x02 , // INPUT (Data,Var,Abs)
71
+
72
+ 0x09 , 0x39 , // USAGE (Hat switch)
73
+ 0x15 , 0x00 , // LOGICAL_MINIMUM (0)
74
+ 0x25 , 0x07 , // LOGICAL_MAXIMUM (7)
75
+ 0x35 , 0x00 , // PHYSICAL_MINIMUM (0)
76
+ 0x46 , 0x3B , 0x01 , // PHYSICAL_MAXIMUM (315)
77
+ 0x65 , 0x14 , // UNIT (Eng Rot:Angular Pos)
78
+ 0x75 , 0x04 , // REPORT_SIZE (4)
79
+ 0x95 , 0x01 , // REPORT_COUNT (1)
80
+ 0x81 , 0x02 , // INPUT (Data,Var,Abs)
81
+
82
+ // X, Y, and Z Axis
83
+ 0x15 , 0x00 , // LOGICAL_MINIMUM (0)
84
+ 0x26 , 0xff , 0x00 , // LOGICAL_MAXIMUM (255)
85
+ 0x75 , 0x08 , // REPORT_SIZE (8)
86
+ 0x09 , 0x01 , // USAGE (Pointer)
87
+ 0xA1 , 0x00 , // COLLECTION (Physical)
88
+ 0x09 , 0x30 , // USAGE (x)
89
+ 0x09 , 0x31 , // USAGE (y)
90
+ 0x09 , 0x32 , // USAGE (z)
91
+ 0x09 , 0x33 , // USAGE (rx)
92
+ 0x09 , 0x34 , // USAGE (ry)
93
+ 0x09 , 0x35 , // USAGE (rz)
94
+ 0x95 , 0x06 , // REPORT_COUNT (6)
95
+ 0x81 , 0x02 , // INPUT (Data,Var,Abs)
96
+ 0xc0 , // END_COLLECTION
97
+
98
+ 0xc0 // END_COLLECTION
99
+ };
100
+
101
+ Joystick_::Joystick_ ()
102
+ {
103
+ // Setup HID report structure
104
+ static HIDSubDescriptor node (_hidReportDescriptor, sizeof (_hidReportDescriptor));
105
+ HID ().AppendDescriptor (&node);
106
+
107
+ // Initalize State
108
+ xAxis = 0 ;
109
+ yAxis = 0 ;
110
+ zAxis = 0 ;
111
+ xAxisRotation = 0 ;
112
+ yAxisRotation = 0 ;
113
+ zAxisRotation = 0 ;
114
+ buttons = 0 ;
115
+ throttle = 0 ;
116
+ rudder = 0 ;
117
+ hatSwitch[0 ] = -1 ;
118
+ hatSwitch[1 ] = -1 ;
119
+ }
120
+
121
+ void Joystick_::begin (bool initAutoSendState)
122
+ {
123
+ autoSendState = initAutoSendState;
124
+ sendState ();
125
+ }
126
+
127
+ void Joystick_::end ()
128
+ {
129
+ }
130
+
131
+ void Joystick_::setButton (uint8_t button, uint8_t value)
132
+ {
133
+ if (value == 0 )
134
+ {
135
+ releaseButton (button);
136
+ }
137
+ else
138
+ {
139
+ pressButton (button);
140
+ }
141
+ }
142
+ void Joystick_::pressButton (uint8_t button)
143
+ {
144
+ bitSet (buttons, button);
145
+ if (autoSendState) sendState ();
146
+ }
147
+ void Joystick_::releaseButton (uint8_t button)
148
+ {
149
+ bitClear (buttons, button);
150
+ if (autoSendState) sendState ();
151
+ }
152
+
153
+ void Joystick_::setThrottle (uint8_t value)
154
+ {
155
+ throttle = value;
156
+ if (autoSendState) sendState ();
157
+ }
158
+ void Joystick_::setRudder (uint8_t value)
159
+ {
160
+ rudder = value;
161
+ if (autoSendState) sendState ();
162
+ }
163
+
164
+ void Joystick_::setXAxis (int8_t value)
165
+ {
166
+ xAxis = value;
167
+ if (autoSendState) sendState ();
168
+ }
169
+ void Joystick_::setYAxis (int8_t value)
170
+ {
171
+ yAxis = value;
172
+ if (autoSendState) sendState ();
173
+ }
174
+ void Joystick_::setZAxis (int8_t value)
175
+ {
176
+ zAxis = value;
177
+ if (autoSendState) sendState ();
178
+ }
179
+
180
+ void Joystick_::setXAxisRotation (int16_t value)
181
+ {
182
+ xAxisRotation = value;
183
+ if (autoSendState) sendState ();
184
+ }
185
+ void Joystick_::setYAxisRotation (int16_t value)
186
+ {
187
+ yAxisRotation = value;
188
+ if (autoSendState) sendState ();
189
+ }
190
+ void Joystick_::setZAxisRotation (int16_t value)
191
+ {
192
+ zAxisRotation = value;
193
+ if (autoSendState) sendState ();
194
+ }
195
+
196
+ void Joystick_::setHatSwitch (int8_t hatSwitchIndex, int16_t value)
197
+ {
198
+ hatSwitch[hatSwitchIndex % 2 ] = value;
199
+ if (autoSendState) sendState ();
200
+ }
201
+
202
+ void Joystick_::sendState ()
203
+ {
204
+ uint8_t data[JOYSTICK_STATE_SIZE];
205
+ uint32_t buttonTmp = buttons;
206
+
207
+ // Split 32 bit button-state into 4 bytes
208
+ data[0 ] = buttonTmp & 0xFF ;
209
+ buttonTmp >>= 8 ;
210
+ data[1 ] = buttonTmp & 0xFF ;
211
+ buttonTmp >>= 8 ;
212
+ data[2 ] = buttonTmp & 0xFF ;
213
+ buttonTmp >>= 8 ;
214
+ data[3 ] = buttonTmp & 0xFF ;
215
+
216
+ data[4 ] = throttle;
217
+ data[5 ] = rudder;
218
+
219
+ // Calculate hat-switch values
220
+ uint8_t convertedHatSwitch[2 ];
221
+ for (int hatSwitchIndex = 0 ; hatSwitchIndex < 2 ; hatSwitchIndex++)
222
+ {
223
+ if (hatSwitch[hatSwitchIndex] < 0 )
224
+ {
225
+ convertedHatSwitch[hatSwitchIndex] = 8 ;
226
+ }
227
+ else
228
+ {
229
+ convertedHatSwitch[hatSwitchIndex] = (hatSwitch[hatSwitchIndex] % 360 ) / 45 ;
230
+ }
231
+ }
232
+
233
+ // Pack hat-switch states into a single byte
234
+ data[6 ] = (convertedHatSwitch[1 ] << 4 ) | (B00001111 & convertedHatSwitch[0 ]);
235
+
236
+ data[7 ] = xAxis + 127 ;
237
+ data[8 ] = yAxis + 127 ;
238
+ data[9 ] = zAxis + 127 ;
239
+
240
+ data[10 ] = (xAxisRotation % 360 ) * 0.708 ;
241
+ data[11 ] = (yAxisRotation % 360 ) * 0.708 ;
242
+ data[12 ] = (zAxisRotation % 360 ) * 0.708 ;
243
+
244
+ // HID().SendReport(Report number, array of values in same order as HID descriptor, length)
245
+ HID ().SendReport (JOYSTICK_REPORT_ID, data, JOYSTICK_STATE_SIZE);
246
+ }
247
+
248
+ Joystick_ Joystick;
249
+
250
+ #endif
0 commit comments