USB Host Shield 2.0
Loading...
Searching...
No Matches
SwitchProParser.h
Go to the documentation of this file.
1/* Copyright (C) 2021 Kristian Sloth Lauszus. 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 Sloth Lauszus
14 Web : https://lauszus.com
15 e-mail : lauszus@gmail.com
16 */
17
18#ifndef _switch_pro_parser_h_
19#define _switch_pro_parser_h_
20
21#include "Usb.h"
22#include "controllerEnums.h"
23
26 0x00, // OFF
27 0x01, // LED1
28 0x02, // LED2
29 0x04, // LED3
30 0x08, // LED4
31
32 0x09, // LED5
33 0x0A, // LED6
34 0x0C, // LED7
35 0x0D, // LED8
36 0x0E, // LED9
37 0x0F, // LED10
38};
39
42 0x11, // UP
43 0x12, // RIGHT
44 0x10, // DOWN
45 0x13, // LEFT
46
47 0x0D, // Capture
48 0x09, // PLUS
49 0x0B, // L3
50 0x0A, // R3
51
52 0x08, // MINUS
53 0x0C, // HOME
54 0, 0, // Skip
55
56 0x02, // B
57 0x03, // A
58 0x01, // X
59 0x00, // Y
60
61 0x16, // L
62 0x06, // R
63 0x17, // ZL
64 0x07, // ZR
65};
66
67// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/bluetooth_hid_notes.md#standard-input-report-format
96
101
103 struct {
107
108 /* Button and joystick values */
109 SwitchProButtons btn; // Bytes 3-5
110
111 // Bytes 6-11
116
117 uint8_t vibratorInput; // What is this used for?
118
119 // Bytes 13-48
120 // Three samples of the IMU is sent in one message
121 // See: https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/imu_sensor_notes.md
124
128 uint8_t ledMask; // Higher nibble flashes the LEDs, lower nibble sets them on/off
130
131 // Used to send the reports at the same rate as the controller is sending messages
135 int8_t enableImu; // -1 == Do nothing, 0 == disable IMU, 1 == enable IMU
139
142public:
144 SwitchProParser() : output_sequence_counter(0) {
145 Reset();
146 };
147
169
174 void enableImu(bool enable) {
175 // TODO: Should we just always enable it?
177 }
178
185 if (a == Pitch)
186 return (atan2f(-switchProData.imu[0].accY, -switchProData.imu[0].accZ) + PI) * RAD_TO_DEG;
187 else
188 return (atan2f(switchProData.imu[0].accX, -switchProData.imu[0].accZ) + PI) * RAD_TO_DEG;
189 };
190
197 switch(s) {
198 case gX:
199 return switchProData.imu[0].gyroX;
200 case gY:
201 return switchProData.imu[0].gyroY;
202 case gZ:
203 return switchProData.imu[0].gyroZ;
204 case aX:
205 return switchProData.imu[0].accX;
206 case aY:
207 return switchProData.imu[0].accY;
208 case aZ:
209 return switchProData.imu[0].accZ;
210 default:
211 return 0;
212 }
213 };
214
216 void setAllOff() {
217 setRumbleOff();
218 setLedOff();
220 };
221
224 setRumble(false, false);
225 }
226
231
237 void setRumble(bool leftRumbleOn, bool rightRumbleOn) {
238 switchProOutput.leftRumbleOn = leftRumbleOn;
239 switchProOutput.rightRumbleOn = rightRumbleOn;
240 switchProOutput.ledReportChanged = true; // Set this, so the rumble effect gets changed immediately
241 }
242
247 void setRumbleLeft(bool on) {
249 switchProOutput.ledReportChanged = true; // Set this, so the rumble effect gets changed immediately
250 }
251
256 void setRumbleRight(bool on) {
258 switchProOutput.ledReportChanged = true; // Set this, so the rumble effect gets changed immediately
259 }
260
270
272 void setLedOff() {
273 setLedRaw(0);
274 }
275
284
293
302
308
314
320
323 return message_counter;
324 }
325
332 return switchProData.battery_level >> 1;
333 }
334
339 bool isCharging() {
340 return switchProData.battery_level & 0x01;
341 }
342
343protected:
349 void Parse(uint8_t len, uint8_t *buf);
350
352 void Reset();
353
359 virtual void sendOutputReport(uint8_t *data, uint8_t len) = 0;
360
362 virtual void sendHandshake() {}
363
368 virtual void disableTimeout() {}
369
372
373private:
374 static int8_t getButtonIndexSwitchPro(ButtonEnum b);
375
376 void sendOutputCmd();
377 void sendRumbleOutputReport();
378
379 SwitchProData switchProData;
380 SwitchProButtons oldButtonState, buttonClickState;
381 uint16_t message_counter = 0;
382 uint8_t output_sequence_counter : 4;
383 uint32_t rumble_on_timer = 0;
384};
385#endif
const uint8_t SWITCH_PRO_BUTTONS[]
const uint8_t SWITCH_PRO_LEDS[]
virtual void sendOutputReport(uint8_t *data, uint8_t len)=0
int16_t getAnalogHat(AnalogHatEnum a)
uint8_t getBatteryLevel()
bool getButtonClick(ButtonEnum b)
void setRumble(bool leftRumbleOn, bool rightRumbleOn)
float getAngle(AngleEnum a)
bool getButtonPress(ButtonEnum b)
void setLedOff(LEDEnum a)
void enableImu(bool enable)
int16_t getSensor(SensorEnum s)
void setLedRaw(uint8_t mask)
virtual void disableTimeout()
void setLedToggle(LEDEnum a)
void setLedOn(LEDEnum a)
void setRumbleRight(bool on)
uint16_t getMessageCounter()
virtual void sendHandshake()
void Parse(uint8_t len, uint8_t *buf)
SwitchProOutput switchProOutput
void setRumbleLeft(bool on)
SensorEnum
AnalogHatEnum
LEDEnum
AngleEnum
@ Pitch
ButtonEnum
int16_t accX
int16_t gyroX
int16_t gyroZ
int16_t accZ
int16_t gyroY
int16_t accY
SwitchProButtons btn
uint8_t connection_info
#define pgm_read_byte(addr)