Browse Source

Initial commit

Thomas Buck 3 years ago
commit
f0943834d0
4 changed files with 224 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 38
    0
      Saitek-X52-PPM.ino
  3. 141
    0
      hidjoystickrptparser.cpp
  4. 44
    0
      hidjoystickrptparser.h

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+.DS_Store

+ 38
- 0
Saitek-X52-PPM.ino View File

@@ -0,0 +1,38 @@
1
+#include <hid.h>
2
+#include <hiduniversal.h>
3
+#include <usbhub.h>
4
+
5
+// Satisfy IDE, which only needs to see the include statment in the ino.
6
+#ifdef dobogusinclude
7
+#include <spi4teensy3.h>
8
+#include <SPI.h>
9
+#endif
10
+
11
+#include "hidjoystickrptparser.h"
12
+
13
+USB Usb;
14
+USBHub Hub(&Usb);
15
+HIDUniversal Hid(&Usb);
16
+JoystickEvents JoyEvents;
17
+JoystickReportParser Joy(&JoyEvents);
18
+
19
+void setup() {  
20
+        Serial.begin(115200);
21
+#if !defined(__MIPSEL__)
22
+        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
23
+#endif
24
+        Serial.println("Start");
25
+
26
+        if (Usb.Init() == -1)
27
+                Serial.println("OSC did not start.");
28
+
29
+        delay(200);
30
+
31
+        if (!Hid.SetReportParser(0, &Joy))
32
+                ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
33
+}
34
+
35
+void loop() {
36
+        Usb.Task();
37
+}
38
+

+ 141
- 0
hidjoystickrptparser.cpp View File

@@ -0,0 +1,141 @@
1
+#include "hidjoystickrptparser.h"
2
+
3
+/*
4
+ * Adapted for the Saitek X52 flight controller
5
+ */
6
+
7
+JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
8
+joyEvents(evt), oldHat(0), oldButtons(0), oldMouse(0) {
9
+        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
10
+                oldPad[i] = 0;
11
+}
12
+
13
+void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *bufPart) {
14
+        if (len == 8) {
15
+          // First part of buffer, store and do nothing
16
+          for (uint8_t i = 0; i < 8; i++) {
17
+            buf[i] = bufPart[i];
18
+          }
19
+          return;
20
+        } else {
21
+          // Append second part, then evaluate
22
+          for (uint8_t i = 0; i < len; i++) {
23
+            buf[i + 8] = bufPart[i];
24
+          }
25
+        }
26
+
27
+        /*
28
+        Serial.println("");
29
+        Serial.print("Packet: ");
30
+        for (uint8_t i = 0; i < (8 + len); i++) {
31
+          PrintHex<uint8_t >(buf[i], 0x80);
32
+          Serial.print(" ");
33
+        }
34
+        Serial.println("");
35
+        Serial.println("");
36
+        */
37
+
38
+        // Checking if there are changes in report since the method was last called
39
+        bool match = true;
40
+        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
41
+                if (buf[i] != oldPad[i]) {
42
+                        match = false;
43
+                        break;
44
+                }
45
+
46
+        // Calling Game Pad event handler
47
+        if (!match && joyEvents) {
48
+                buffer.X = buf[0] | ((buf[1] & 0x07) << 8);
49
+                buffer.Y = ((buf[1] & 0xF8) >> 3) | ((buf[2] & 0x3F) << 5);
50
+                buffer.Rz = ((buf[2] & 0xC0) >> 6) | (buf[3] << 2);
51
+                buffer.Z = buf[4];
52
+                buffer.Rx = buf[5];
53
+                buffer.Ry = buf[6];
54
+                buffer.Slider = buf[7];
55
+                
56
+                joyEvents->OnGamePadChanged((const GamePadEventData*)&buffer);
57
+
58
+                for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];
59
+        }
60
+
61
+        // Calling Hat Switch event handler`
62
+        uint8_t hat = (buf[12] & 0xF0) >> 4;
63
+        if (hat != oldHat && joyEvents) {
64
+                joyEvents->OnHatSwitch(hat);
65
+                oldHat = hat;
66
+        }
67
+
68
+        uint64_t buttons = buf[12] & 0x03;
69
+        buttons <<= 8;
70
+        buttons |= buf[11];
71
+        buttons <<= 8;
72
+        buttons |= buf[10];
73
+        buttons <<= 8;
74
+        buttons |= buf[9];
75
+        buttons <<= 8;
76
+        buttons |= buf[8];
77
+
78
+        // Calling Button Event Handler for every button changed
79
+        uint64_t changes = (buttons ^ oldButtons);
80
+        if (changes) {
81
+                for (uint8_t i = 0; i < 34; i++) {
82
+                        uint64_t mask = (1ull << i);
83
+                        if ((mask & changes) && joyEvents) {
84
+                                if (buttons & mask) {
85
+                                        joyEvents->OnButtonDn(i);
86
+                                } else {
87
+                                        joyEvents->OnButtonUp(i);
88
+                                }
89
+                        }
90
+                }
91
+                oldButtons = buttons;
92
+        }
93
+
94
+        if (oldMouse != buf[13] && joyEvents) {
95
+          oldMouse = buf[13];
96
+          joyEvents->OnMouseMoved((buf[13] & 0xF0) >> 4, buf[13] & 0x0F);
97
+        }
98
+}
99
+
100
+void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
101
+        Serial.print("X: ");
102
+        PrintHex<uint16_t > (evt->X, 0x80);
103
+        Serial.print("\tY: ");
104
+        PrintHex<uint16_t > (evt->Y, 0x80);
105
+        Serial.print("\tZ: ");
106
+        PrintHex<uint8_t > (evt->Z, 0x80);
107
+        Serial.print("\tRx: ");
108
+        PrintHex<uint8_t > (evt->Rx, 0x80);
109
+        Serial.print("\tRy: ");
110
+        PrintHex<uint8_t > (evt->Ry, 0x80);
111
+        Serial.print("\tRz: ");
112
+        PrintHex<uint16_t > (evt->Rz, 0x80);
113
+        Serial.print("\tSlider: ");
114
+        PrintHex<uint8_t > (evt->Slider, 0x80);
115
+        Serial.println("");
116
+}
117
+
118
+void JoystickEvents::OnHatSwitch(uint8_t hat) {
119
+        Serial.print("Hat Switch: ");
120
+        PrintHex<uint8_t > (hat, 0x80);
121
+        Serial.println("");
122
+}
123
+
124
+void JoystickEvents::OnButtonUp(uint8_t but_id) {
125
+        Serial.print("Up: ");
126
+        Serial.println(but_id, DEC);
127
+}
128
+
129
+void JoystickEvents::OnButtonDn(uint8_t but_id) {
130
+        Serial.print("Dn: ");
131
+        Serial.println(but_id, DEC);
132
+}
133
+
134
+void JoystickEvents::OnMouseMoved(uint8_t x, uint8_t y) {
135
+        Serial.print("Mouse X: ");
136
+        PrintHex<uint8_t >(x, 0x80);
137
+        Serial.print("\tY: ");
138
+        PrintHex<uint8_t >(y, 0x80);
139
+        Serial.println("");
140
+}
141
+

+ 44
- 0
hidjoystickrptparser.h View File

@@ -0,0 +1,44 @@
1
+#if !defined(__HIDJOYSTICKRPTPARSER_H__)
2
+#define __HIDJOYSTICKRPTPARSER_H__
3
+
4
+#include <hid.h>
5
+
6
+/*
7
+ * Adapted for the Saitek X52 flight controller
8
+ */
9
+
10
+struct GamePadEventData {
11
+        uint16_t X, Y, Rz; // 11bit, 11bit, 10bit
12
+        uint8_t Z, Rx, Ry, Slider;
13
+};
14
+
15
+class JoystickEvents {
16
+public:
17
+        virtual void OnGamePadChanged(const GamePadEventData *evt);
18
+        virtual void OnHatSwitch(uint8_t hat);
19
+        virtual void OnButtonUp(uint8_t but_id);
20
+        virtual void OnButtonDn(uint8_t but_id);
21
+        virtual void OnMouseMoved(uint8_t x, uint8_t y);
22
+};
23
+
24
+#define RPT_GEMEPAD_LEN 8
25
+#define BUFFER_SIZE 16
26
+
27
+class JoystickReportParser : public HIDReportParser {
28
+        JoystickEvents *joyEvents;
29
+
30
+        uint8_t buf[BUFFER_SIZE];
31
+        uint8_t oldPad[RPT_GEMEPAD_LEN];
32
+        uint8_t oldHat;
33
+        uint64_t oldButtons;
34
+        uint8_t oldMouse;
35
+        GamePadEventData buffer;
36
+
37
+public:
38
+        JoystickReportParser(JoystickEvents *evt);
39
+
40
+        virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *bufPart);
41
+};
42
+
43
+#endif // __HIDJOYSTICKRPTPARSER_H__
44
+

Loading…
Cancel
Save