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:
Fri Aug 30 01:37:49 2013 +0000
Revision:
2:ae7a31a3c618
Parent:
0:33bc88c4ab31
Child:
4:2cc58c173de8
Better PushButton handling

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 2:ae7a31a3c618 23 bool USBJoystick::update(int16_t t, int16_t r, int16_t x, int16_t y, uint8_t button) {
rvt 0:33bc88c4ab31 24 HID_REPORT report;
rvt 0:33bc88c4ab31 25 _t = t;
rvt 0:33bc88c4ab31 26 _r = r;
rvt 0:33bc88c4ab31 27 _x = x;
rvt 0:33bc88c4ab31 28 _y = y;
rvt 0:33bc88c4ab31 29 _button = button;
rvt 0:33bc88c4ab31 30
rvt 0:33bc88c4ab31 31 // Fill the report according to the Joystick Descriptor
rvt 0:33bc88c4ab31 32 report.data[0] = _t & 0xff;
rvt 0:33bc88c4ab31 33 report.data[1] = (_t >> 8) & 0xff;
rvt 0:33bc88c4ab31 34 report.data[2] = _r & 0xff;
rvt 0:33bc88c4ab31 35 report.data[3] = (_r >> 8) & 0xff;
rvt 0:33bc88c4ab31 36 report.data[4] = _x & 0xff;
rvt 0:33bc88c4ab31 37 report.data[5] = (_x >> 8) & 0xff;
rvt 0:33bc88c4ab31 38 report.data[6] = _y & 0xff;
rvt 0:33bc88c4ab31 39 report.data[7] = (_y >> 8) & 0xff;
rvt 2:ae7a31a3c618 40 report.data[8] = (_button & 0xff);
rvt 0:33bc88c4ab31 41 report.length = 9;
rvt 0:33bc88c4ab31 42
rvt 0:33bc88c4ab31 43 return send(&report);
rvt 0:33bc88c4ab31 44 }
rvt 0:33bc88c4ab31 45
rvt 0:33bc88c4ab31 46 bool USBJoystick::update() {
rvt 0:33bc88c4ab31 47 HID_REPORT report;
rvt 0:33bc88c4ab31 48
rvt 0:33bc88c4ab31 49 // Fill the report according to the Joystick Descriptor
rvt 0:33bc88c4ab31 50 report.data[0] = _t & 0xff;
rvt 0:33bc88c4ab31 51 report.data[1] = (_t >> 8) & 0xff;
rvt 0:33bc88c4ab31 52 report.data[2] = _r & 0xff;
rvt 0:33bc88c4ab31 53 report.data[3] = (_r >> 8) & 0xff;
rvt 0:33bc88c4ab31 54 report.data[4] = _x & 0xff;
rvt 0:33bc88c4ab31 55 report.data[5] = (_x >> 8) & 0xff;
rvt 0:33bc88c4ab31 56 report.data[6] = _y & 0xff;
rvt 0:33bc88c4ab31 57 report.data[7] = (_y >> 8) & 0xff;
rvt 2:ae7a31a3c618 58 report.data[8] = (_button & 0xff);
rvt 0:33bc88c4ab31 59 report.length = 9;
rvt 0:33bc88c4ab31 60
rvt 0:33bc88c4ab31 61 return send(&report);
rvt 0:33bc88c4ab31 62 }
rvt 0:33bc88c4ab31 63
rvt 0:33bc88c4ab31 64 bool USBJoystick::throttle(int16_t t) {
rvt 0:33bc88c4ab31 65 _t = t;
rvt 0:33bc88c4ab31 66 return update();
rvt 0:33bc88c4ab31 67 }
rvt 0:33bc88c4ab31 68
rvt 0:33bc88c4ab31 69 bool USBJoystick::rudder(int16_t r) {
rvt 0:33bc88c4ab31 70 _r = r;
rvt 0:33bc88c4ab31 71 return update();
rvt 0:33bc88c4ab31 72 }
rvt 0:33bc88c4ab31 73
rvt 0:33bc88c4ab31 74 bool USBJoystick::move(int16_t x, int16_t y) {
rvt 0:33bc88c4ab31 75 _x = x;
rvt 0:33bc88c4ab31 76 _y = y;
rvt 0:33bc88c4ab31 77 return update();
rvt 0:33bc88c4ab31 78 }
rvt 0:33bc88c4ab31 79
rvt 0:33bc88c4ab31 80 bool USBJoystick::button(uint8_t button) {
rvt 0:33bc88c4ab31 81 _button = button;
rvt 0:33bc88c4ab31 82 return update();
rvt 0:33bc88c4ab31 83 }
rvt 0:33bc88c4ab31 84
rvt 0:33bc88c4ab31 85
rvt 0:33bc88c4ab31 86 void USBJoystick::_init() {
rvt 0:33bc88c4ab31 87
rvt 0:33bc88c4ab31 88 _t = 0;
rvt 0:33bc88c4ab31 89 _r = 0;
rvt 0:33bc88c4ab31 90 _x = 0;
rvt 0:33bc88c4ab31 91 _y = 0;
rvt 0:33bc88c4ab31 92 _button = 0x00;
rvt 0:33bc88c4ab31 93 }
rvt 0:33bc88c4ab31 94
rvt 0:33bc88c4ab31 95
rvt 0:33bc88c4ab31 96 uint8_t * USBJoystick::reportDesc() {
rvt 0:33bc88c4ab31 97 static uint8_t reportDescriptor[] = {
rvt 0:33bc88c4ab31 98
rvt 0:33bc88c4ab31 99 USAGE_PAGE(1), 0x01, // Generic Desktop
rvt 0:33bc88c4ab31 100 LOGICAL_MINIMUM(1), 0x00, // Logical_Minimum (0)
rvt 0:33bc88c4ab31 101 USAGE(1), 0x04, // Usage (Joystick)
rvt 0:33bc88c4ab31 102 COLLECTION(1), 0x01, // Application
rvt 0:33bc88c4ab31 103
rvt 0:33bc88c4ab31 104 USAGE_PAGE(1), 0x02, // Simulation Controls
rvt 0:33bc88c4ab31 105 USAGE(1), 0xBB, // Throttle
rvt 0:33bc88c4ab31 106 USAGE(1), 0xBA, // Rudder
rvt 0:33bc88c4ab31 107 LOGICAL_MINIMUM(2), 0x01, 0x80, // -32767
rvt 0:33bc88c4ab31 108 LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
rvt 0:33bc88c4ab31 109 REPORT_SIZE(1), 0x10,
rvt 0:33bc88c4ab31 110 REPORT_COUNT(1), 0x02,
rvt 0:33bc88c4ab31 111 INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 112
rvt 0:33bc88c4ab31 113 USAGE_PAGE(1), 0x01, // Generic Desktop
rvt 0:33bc88c4ab31 114 USAGE(1), 0x01, // Usage (Pointer)
rvt 0:33bc88c4ab31 115 COLLECTION(1), 0x00, // Physical
rvt 0:33bc88c4ab31 116 USAGE(1), 0x30, // X
rvt 0:33bc88c4ab31 117 USAGE(1), 0x31, // Y
rvt 0:33bc88c4ab31 118 // 8 bit values
rvt 0:33bc88c4ab31 119 // LOGICAL_MINIMUM(1), 0x81, // -127
rvt 0:33bc88c4ab31 120 // LOGICAL_MAXIMUM(1), 0x7f, // 127
rvt 0:33bc88c4ab31 121 // REPORT_SIZE(1), 0x08,
rvt 0:33bc88c4ab31 122 // REPORT_COUNT(1), 0x02,
rvt 0:33bc88c4ab31 123 // INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 124 // 16 bit values
rvt 0:33bc88c4ab31 125 LOGICAL_MINIMUM(2), 0x01, 0x80, // -32767
rvt 0:33bc88c4ab31 126 LOGICAL_MAXIMUM(2), 0xff, 0x7f, // 32767
rvt 0:33bc88c4ab31 127 REPORT_SIZE(1), 0x10,
rvt 0:33bc88c4ab31 128 REPORT_COUNT(1), 0x02,
rvt 0:33bc88c4ab31 129 INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 130
rvt 0:33bc88c4ab31 131
rvt 0:33bc88c4ab31 132 END_COLLECTION(0),
rvt 0:33bc88c4ab31 133 // 4 Position Hat Switch
rvt 0:33bc88c4ab31 134 // USAGE(1), 0x39, // Usage (Hat switch)
rvt 0:33bc88c4ab31 135 // LOGICAL_MINIMUM(1), 0x00, // 0
rvt 0:33bc88c4ab31 136 // LOGICAL_MAXIMUM(1), 0x03, // 3
rvt 0:33bc88c4ab31 137 // PHYSICAL_MINIMUM(1), 0x00, // Physical_Minimum (0)
rvt 0:33bc88c4ab31 138 // PHYSICAL_MAXIMUM(2), 0x0E, 0x01, // Physical_Maximum (270)
rvt 0:33bc88c4ab31 139 // UNIT(1), 0x14, // Unit (Eng Rot:Angular Pos)
rvt 0:33bc88c4ab31 140 // REPORT_SIZE(1), 0x04,
rvt 0:33bc88c4ab31 141 // REPORT_COUNT(1), 0x01,
rvt 0:33bc88c4ab31 142 // INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 143 // 8 Position Hat Switch
rvt 2:ae7a31a3c618 144 // USAGE(1), 0x39, // Usage (Hat switch)
rvt 2:ae7a31a3c618 145 // LOGICAL_MINIMUM(1), 0x00, // 0
rvt 2:ae7a31a3c618 146 // LOGICAL_MAXIMUM(1), 0x07, // 7
rvt 2:ae7a31a3c618 147 // PHYSICAL_MINIMUM(1), 0x00, // Physical_Minimum (0)
rvt 2:ae7a31a3c618 148 // PHYSICAL_MAXIMUM(2), 0x3B, 0x01, // Physical_Maximum (315)
rvt 2:ae7a31a3c618 149 // UNIT(1), 0x14, // Unit (Eng Rot:Angular Pos)
rvt 2:ae7a31a3c618 150 // REPORT_SIZE(1), 0x04,
rvt 2:ae7a31a3c618 151 // REPORT_COUNT(1), 0x01,
rvt 2:ae7a31a3c618 152 // INPUT(1), 0x02, // Data, Variable, Absolute
rvt 2:ae7a31a3c618 153
rvt 2:ae7a31a3c618 154 // Buttons
rvt 0:33bc88c4ab31 155 USAGE_PAGE(1), 0x09, // Buttons
rvt 0:33bc88c4ab31 156 USAGE_MINIMUM(1), 0x01, // 1
rvt 2:ae7a31a3c618 157 USAGE_MAXIMUM(1), 0x08, // 4
rvt 0:33bc88c4ab31 158 LOGICAL_MINIMUM(1), 0x00, // 0
rvt 0:33bc88c4ab31 159 LOGICAL_MAXIMUM(1), 0x01, // 1
rvt 0:33bc88c4ab31 160 REPORT_SIZE(1), 0x01,
rvt 2:ae7a31a3c618 161 REPORT_COUNT(1), 0x08,
rvt 0:33bc88c4ab31 162 UNIT_EXPONENT(1), 0x00, // Unit_Exponent (0)
rvt 0:33bc88c4ab31 163 UNIT(1), 0x00, // Unit (None)
rvt 0:33bc88c4ab31 164 INPUT(1), 0x02, // Data, Variable, Absolute
rvt 0:33bc88c4ab31 165 END_COLLECTION(0)
rvt 0:33bc88c4ab31 166
rvt 0:33bc88c4ab31 167 };
rvt 0:33bc88c4ab31 168
rvt 0:33bc88c4ab31 169 reportLength = sizeof(reportDescriptor);
rvt 0:33bc88c4ab31 170 return reportDescriptor;
rvt 0:33bc88c4ab31 171 }
rvt 0:33bc88c4ab31 172
rvt 0:33bc88c4ab31 173