HID Joystick - For use with X-Plane or other programs that can read HID JoySticks

Dependencies:   USBDevice mbed-rtos mbed

Fork of JoyStick by Ries Twisk

This is a simple Joystick HID that I use for xplane and a home build yoke + paddels, see this forum with the look and feel of it : http://forums.x-plane.org/index.php?showtopic=70041

The analog input are filtered with a LowPass IIR filter and the digital input's will be derived from the analog input and de-bounced.

The analog values are read at a 1Khz interval and to ensure we don't push the USB stack to much at a maximum rate of 20 updates/sec HID data is send over USB only if any values where changed. The JoyStick will send 16Bit analog values as opposite of 8 bit values that are normally used to increase accuracy of the whole system. This is well noticeable within x-plane!

The JoyStick uses the JoyStick copied from Wim Huiskamp and modified to suite my needs and the MBED RTOS libraries for reading analog inputs, sending debug data over USB and sending HID data, 3 threads in total.

Committer:
rvt
Date:
Wed Jun 22 12:50:16 2016 +0000
Revision:
5:a0bb17c379ce
Parent:
4:2cc58c173de8
Latest

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rvt 0:33bc88c4ab31 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
rvt 0:33bc88c4ab31 2 * Modified Mouse code for Joystick - WH 2012
rvt 0:33bc88c4ab31 3 *
rvt 0:33bc88c4ab31 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
rvt 0:33bc88c4ab31 5 * and associated documentation files (the "Software"), to deal in the Software without
rvt 0:33bc88c4ab31 6 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
rvt 0:33bc88c4ab31 7 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
rvt 0:33bc88c4ab31 8 * Software is furnished to do so, subject to the following conditions:
rvt 0:33bc88c4ab31 9 *
rvt 0:33bc88c4ab31 10 * The above copyright notice and this permission notice shall be included in all copies or
rvt 0:33bc88c4ab31 11 * substantial portions of the Software.
rvt 0:33bc88c4ab31 12 *
rvt 0:33bc88c4ab31 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
rvt 0:33bc88c4ab31 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
rvt 0:33bc88c4ab31 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
rvt 0:33bc88c4ab31 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
rvt 0:33bc88c4ab31 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
rvt 0:33bc88c4ab31 18 */
rvt 0:33bc88c4ab31 19
rvt 0:33bc88c4ab31 20 #include "stdint.h"
rvt 0:33bc88c4ab31 21 #include "USBJoystick.h"
rvt 0:33bc88c4ab31 22
rvt 4:2cc58c173de8 23 bool USBJoystick::update(int16_t t, int16_t r, int16_t x, int16_t y, uint32_t button) {
rvt 0:33bc88c4ab31 24 _t = t;
rvt 0:33bc88c4ab31 25 _r = r;
rvt 0:33bc88c4ab31 26 _x = x;
rvt 0:33bc88c4ab31 27 _y = y;
rvt 0:33bc88c4ab31 28 _button = button;
rvt 0:33bc88c4ab31 29
rvt 4:2cc58c173de8 30 return USBJoystick::update();
rvt 0:33bc88c4ab31 31 }
rvt 0:33bc88c4ab31 32
rvt 0:33bc88c4ab31 33 bool USBJoystick::update() {
rvt 0:33bc88c4ab31 34 HID_REPORT report;
rvt 0:33bc88c4ab31 35
rvt 0:33bc88c4ab31 36 // Fill the report according to the Joystick Descriptor
rvt 0:33bc88c4ab31 37 report.data[0] = _t & 0xff;
rvt 0:33bc88c4ab31 38 report.data[1] = (_t >> 8) & 0xff;
rvt 0:33bc88c4ab31 39 report.data[2] = _r & 0xff;
rvt 0:33bc88c4ab31 40 report.data[3] = (_r >> 8) & 0xff;
rvt 0:33bc88c4ab31 41 report.data[4] = _x & 0xff;
rvt 0:33bc88c4ab31 42 report.data[5] = (_x >> 8) & 0xff;
rvt 0:33bc88c4ab31 43 report.data[6] = _y & 0xff;
rvt 0:33bc88c4ab31 44 report.data[7] = (_y >> 8) & 0xff;
rvt 4:2cc58c173de8 45 report.data[8] = (_button >> 24) & 0xff;
rvt 4:2cc58c173de8 46 report.data[9] = (_button >> 16) & 0xff;
rvt 4:2cc58c173de8 47 report.data[10] = (_button >> 8) & 0xff;
rvt 4:2cc58c173de8 48 report.data[11] = _button & 0xff;
rvt 4:2cc58c173de8 49 report.length = 12;
rvt 0:33bc88c4ab31 50
rvt 0:33bc88c4ab31 51 return send(&report);
rvt 0:33bc88c4ab31 52 }
rvt 0:33bc88c4ab31 53
rvt 0:33bc88c4ab31 54 bool USBJoystick::throttle(int16_t t) {
rvt 0:33bc88c4ab31 55 _t = t;
rvt 0:33bc88c4ab31 56 return update();
rvt 0:33bc88c4ab31 57 }
rvt 0:33bc88c4ab31 58
rvt 0:33bc88c4ab31 59 bool USBJoystick::rudder(int16_t r) {
rvt 0:33bc88c4ab31 60 _r = r;
rvt 0:33bc88c4ab31 61 return update();
rvt 0:33bc88c4ab31 62 }
rvt 0:33bc88c4ab31 63
rvt 0:33bc88c4ab31 64 bool USBJoystick::move(int16_t x, int16_t y) {
rvt 0:33bc88c4ab31 65 _x = x;
rvt 0:33bc88c4ab31 66 _y = y;
rvt 0:33bc88c4ab31 67 return update();
rvt 0:33bc88c4ab31 68 }
rvt 0:33bc88c4ab31 69
rvt 4:2cc58c173de8 70 bool USBJoystick::button(uint32_t button) {
rvt 0:33bc88c4ab31 71 _button = button;
rvt 0:33bc88c4ab31 72 return update();
rvt 0:33bc88c4ab31 73 }
rvt 0:33bc88c4ab31 74
rvt 0:33bc88c4ab31 75
rvt 0:33bc88c4ab31 76 void USBJoystick::_init() {
rvt 0:33bc88c4ab31 77
rvt 0:33bc88c4ab31 78 _t = 0;
rvt 0:33bc88c4ab31 79 _r = 0;
rvt 0:33bc88c4ab31 80 _x = 0;
rvt 0:33bc88c4ab31 81 _y = 0;
rvt 4:2cc58c173de8 82 _button = 0x00000000;
rvt 0:33bc88c4ab31 83 }
rvt 0:33bc88c4ab31 84
rvt 0:33bc88c4ab31 85
rvt 0:33bc88c4ab31 86 uint8_t * USBJoystick::reportDesc() {
rvt 0:33bc88c4ab31 87 static uint8_t reportDescriptor[] = {
rvt 0:33bc88c4ab31 88
rvt 0:33bc88c4ab31 89 USAGE_PAGE(1), 0x01, // Generic Desktop
rvt 0:33bc88c4ab31 90 LOGICAL_MINIMUM(1), 0x00, // Logical_Minimum (0)
rvt 0:33bc88c4ab31 91 USAGE(1), 0x04, // Usage (Joystick)
rvt 0:33bc88c4ab31 92 COLLECTION(1), 0x01, // Application
rvt 0:33bc88c4ab31 93
rvt 0:33bc88c4ab31 94 USAGE_PAGE(1), 0x02, // Simulation Controls
rvt 0:33bc88c4ab31 95 USAGE(1), 0xBB, // Throttle
rvt 0:33bc88c4ab31 96 USAGE(1), 0xBA, // Rudder
rvt 0:33bc88c4ab31 97 LOGICAL_MINIMUM(2), 0x01, 0x80, // -32767
rvt 0:33bc88c4ab31 98 LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
rvt 0:33bc88c4ab31 99 REPORT_SIZE(1), 0x10,
rvt 0:33bc88c4ab31 100 REPORT_COUNT(1), 0x02,
rvt 0:33bc88c4ab31 101 INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 102
rvt 0:33bc88c4ab31 103 USAGE_PAGE(1), 0x01, // Generic Desktop
rvt 0:33bc88c4ab31 104 USAGE(1), 0x01, // Usage (Pointer)
rvt 0:33bc88c4ab31 105 COLLECTION(1), 0x00, // Physical
rvt 0:33bc88c4ab31 106 USAGE(1), 0x30, // X
rvt 0:33bc88c4ab31 107 USAGE(1), 0x31, // Y
rvt 0:33bc88c4ab31 108 // 8 bit values
rvt 0:33bc88c4ab31 109 // LOGICAL_MINIMUM(1), 0x81, // -127
rvt 0:33bc88c4ab31 110 // LOGICAL_MAXIMUM(1), 0x7f, // 127
rvt 0:33bc88c4ab31 111 // REPORT_SIZE(1), 0x08,
rvt 0:33bc88c4ab31 112 // REPORT_COUNT(1), 0x02,
rvt 0:33bc88c4ab31 113 // INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 114 // 16 bit values
rvt 0:33bc88c4ab31 115 LOGICAL_MINIMUM(2), 0x01, 0x80, // -32767
rvt 0:33bc88c4ab31 116 LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
rvt 0:33bc88c4ab31 117 REPORT_SIZE(1), 0x10,
rvt 0:33bc88c4ab31 118 REPORT_COUNT(1), 0x02,
rvt 0:33bc88c4ab31 119 INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 120
rvt 0:33bc88c4ab31 121
rvt 0:33bc88c4ab31 122 END_COLLECTION(0),
rvt 0:33bc88c4ab31 123 // 4 Position Hat Switch
rvt 0:33bc88c4ab31 124 // USAGE(1), 0x39, // Usage (Hat switch)
rvt 0:33bc88c4ab31 125 // LOGICAL_MINIMUM(1), 0x00, // 0
rvt 0:33bc88c4ab31 126 // LOGICAL_MAXIMUM(1), 0x03, // 3
rvt 0:33bc88c4ab31 127 // PHYSICAL_MINIMUM(1), 0x00, // Physical_Minimum (0)
rvt 0:33bc88c4ab31 128 // PHYSICAL_MAXIMUM(2), 0x0E, 0x01, // Physical_Maximum (270)
rvt 0:33bc88c4ab31 129 // UNIT(1), 0x14, // Unit (Eng Rot:Angular Pos)
rvt 0:33bc88c4ab31 130 // REPORT_SIZE(1), 0x04,
rvt 0:33bc88c4ab31 131 // REPORT_COUNT(1), 0x01,
rvt 0:33bc88c4ab31 132 // INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 133 // 8 Position Hat Switch
rvt 2:ae7a31a3c618 134 // USAGE(1), 0x39, // Usage (Hat switch)
rvt 2:ae7a31a3c618 135 // LOGICAL_MINIMUM(1), 0x00, // 0
rvt 2:ae7a31a3c618 136 // LOGICAL_MAXIMUM(1), 0x07, // 7
rvt 2:ae7a31a3c618 137 // PHYSICAL_MINIMUM(1), 0x00, // Physical_Minimum (0)
rvt 2:ae7a31a3c618 138 // PHYSICAL_MAXIMUM(2), 0x3B, 0x01, // Physical_Maximum (315)
rvt 2:ae7a31a3c618 139 // UNIT(1), 0x14, // Unit (Eng Rot:Angular Pos)
rvt 2:ae7a31a3c618 140 // REPORT_SIZE(1), 0x04,
rvt 2:ae7a31a3c618 141 // REPORT_COUNT(1), 0x01,
rvt 2:ae7a31a3c618 142 // INPUT(1), 0x02, // Data, Variable, Absolute
rvt 2:ae7a31a3c618 143
rvt 2:ae7a31a3c618 144 // Buttons
rvt 0:33bc88c4ab31 145 USAGE_PAGE(1), 0x09, // Buttons
rvt 0:33bc88c4ab31 146 USAGE_MINIMUM(1), 0x01, // 1
rvt 4:2cc58c173de8 147 USAGE_MAXIMUM(1), 0x20, // 32
rvt 0:33bc88c4ab31 148 LOGICAL_MINIMUM(1), 0x00, // 0
rvt 0:33bc88c4ab31 149 LOGICAL_MAXIMUM(1), 0x01, // 1
rvt 0:33bc88c4ab31 150 REPORT_SIZE(1), 0x01,
rvt 4:2cc58c173de8 151 REPORT_COUNT(1), 0x20, // 32
rvt 0:33bc88c4ab31 152 UNIT_EXPONENT(1), 0x00, // Unit_Exponent (0)
rvt 0:33bc88c4ab31 153 UNIT(1), 0x00, // Unit (None)
rvt 0:33bc88c4ab31 154 INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 155 END_COLLECTION(0)
rvt 0:33bc88c4ab31 156
rvt 0:33bc88c4ab31 157 };
rvt 0:33bc88c4ab31 158
rvt 0:33bc88c4ab31 159 reportLength = sizeof(reportDescriptor);
rvt 0:33bc88c4ab31 160 return reportDescriptor;
rvt 0:33bc88c4ab31 161 }
rvt 0:33bc88c4ab31 162
rvt 0:33bc88c4ab31 163