Modification of USB Joystick to work as a Hitbox-like game controller using the F401RE. Works reasonably well under Windows.

Dependencies:   USBDevice mbed

This is a hobby project trying to recreate a Hitbox Controller for fun .

The original code was based off of http://developer.mbed.org/users/wim/notebook/usb-joystick-device/ Slight modifications were made to the USB HID descriptor to up the number of buttons reported to 13.

Currently, this works well under Windows and Linux, but no luck getting it to work with Mac OS X or a PS3 so far.

If anybody has useful information, feel free to contribute. :)

p.s: My thread for hooking up an F401RE board as a USB device is here: http://developer.mbed.org/questions/5364/Cannot-get-the-Nucleo-F401RE-to-work-as-/

p.s.2: Cabling information and <del>pictures</del> will be uploaded in the near future.

p.s.3: 2015-04-20: added support for FRDM-KL25Z board. Due to the better usb functionality, this hitbox now works on Windows, Mac OS X, Linux and PS3 too! (minus the "PS" button...)

Committer:
eimaiosatanas
Date:
Mon Apr 20 14:58:21 2015 +0000
Revision:
2:278b7a590311
Parent:
0:c8e9c90ca7f4
Support for FRDM-KL25Z; ; This board has better usb functionality, no it works on a PS3 too! (..minus the "PS" button...)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eimaiosatanas 0:c8e9c90ca7f4 1 /* USBJoystick.h */
eimaiosatanas 0:c8e9c90ca7f4 2 /* USB device example: Joystick*/
eimaiosatanas 0:c8e9c90ca7f4 3 /* Copyright (c) 2011 ARM Limited. All rights reserved. */
eimaiosatanas 0:c8e9c90ca7f4 4 /* Modified Mouse code for Joystick - WH 2012 */
eimaiosatanas 0:c8e9c90ca7f4 5
eimaiosatanas 0:c8e9c90ca7f4 6 #ifndef USBJOYSTICK_H
eimaiosatanas 0:c8e9c90ca7f4 7 #define USBJOYSTICK_H
eimaiosatanas 0:c8e9c90ca7f4 8
eimaiosatanas 0:c8e9c90ca7f4 9 #include "USBHID.h"
eimaiosatanas 0:c8e9c90ca7f4 10
eimaiosatanas 0:c8e9c90ca7f4 11 #define REPORT_ID_JOYSTICK 4
eimaiosatanas 0:c8e9c90ca7f4 12
eimaiosatanas 0:c8e9c90ca7f4 13 /* Common usage */
eimaiosatanas 0:c8e9c90ca7f4 14 enum JOY_BUTTON {
eimaiosatanas 0:c8e9c90ca7f4 15 JOY_B0 = 1,
eimaiosatanas 0:c8e9c90ca7f4 16 JOY_B1 = 2,
eimaiosatanas 0:c8e9c90ca7f4 17 JOY_B2 = 4,
eimaiosatanas 0:c8e9c90ca7f4 18 JOY_B3 = 8,
eimaiosatanas 0:c8e9c90ca7f4 19 };
eimaiosatanas 0:c8e9c90ca7f4 20
eimaiosatanas 0:c8e9c90ca7f4 21 #if(0)
eimaiosatanas 0:c8e9c90ca7f4 22 enum JOY_HAT {
eimaiosatanas 0:c8e9c90ca7f4 23 JOY_HAT_UP = 0,
eimaiosatanas 0:c8e9c90ca7f4 24 JOY_HAT_RIGHT = 1,
eimaiosatanas 0:c8e9c90ca7f4 25 JOY_HAT_DOWN = 2,
eimaiosatanas 0:c8e9c90ca7f4 26 JOY_HAT_LEFT = 3,
eimaiosatanas 0:c8e9c90ca7f4 27 JOY_HAT_NEUTRAL = 4,
eimaiosatanas 0:c8e9c90ca7f4 28 };
eimaiosatanas 0:c8e9c90ca7f4 29 #else
eimaiosatanas 0:c8e9c90ca7f4 30 enum JOY_HAT {
eimaiosatanas 0:c8e9c90ca7f4 31 JOY_HAT_UP = 0,
eimaiosatanas 0:c8e9c90ca7f4 32 JOY_HAT_UP_RIGHT = 1,
eimaiosatanas 0:c8e9c90ca7f4 33 JOY_HAT_RIGHT = 2,
eimaiosatanas 0:c8e9c90ca7f4 34 JOY_HAT_RIGHT_DOWN = 3,
eimaiosatanas 0:c8e9c90ca7f4 35 JOY_HAT_DOWN = 4,
eimaiosatanas 0:c8e9c90ca7f4 36 JOY_HAT_DOWN_LEFT = 5,
eimaiosatanas 0:c8e9c90ca7f4 37 JOY_HAT_LEFT = 6,
eimaiosatanas 0:c8e9c90ca7f4 38 JOY_HAT_LEFT_UP = 7,
eimaiosatanas 0:c8e9c90ca7f4 39 JOY_HAT_NEUTRAL = 8,
eimaiosatanas 0:c8e9c90ca7f4 40 };
eimaiosatanas 0:c8e9c90ca7f4 41 #endif
eimaiosatanas 0:c8e9c90ca7f4 42
eimaiosatanas 0:c8e9c90ca7f4 43 /* X, Y and T limits */
eimaiosatanas 0:c8e9c90ca7f4 44 /* These values do not directly map to screen pixels */
eimaiosatanas 0:c8e9c90ca7f4 45 /* Zero may be interpreted as meaning 'no movement' */
eimaiosatanas 0:c8e9c90ca7f4 46 #define JX_MIN_ABS (-127) /*!< The maximum value that we can move to the left on the x-axis */
eimaiosatanas 0:c8e9c90ca7f4 47 #define JY_MIN_ABS (-127) /*!< The maximum value that we can move up on the y-axis */
eimaiosatanas 0:c8e9c90ca7f4 48 #define JT_MIN_ABS (-127) /*!< The minimum value for the throttle */
eimaiosatanas 0:c8e9c90ca7f4 49 #define JX_MAX_ABS (127) /*!< The maximum value that we can move to the right on the x-axis */
eimaiosatanas 0:c8e9c90ca7f4 50 #define JY_MAX_ABS (127) /*!< The maximum value that we can move down on the y-axis */
eimaiosatanas 0:c8e9c90ca7f4 51 #define JT_MAX_ABS (127) /*!< The maximum value for the throttle */
eimaiosatanas 0:c8e9c90ca7f4 52
eimaiosatanas 0:c8e9c90ca7f4 53 /**
eimaiosatanas 0:c8e9c90ca7f4 54 *
eimaiosatanas 0:c8e9c90ca7f4 55 * USBJoystick example
eimaiosatanas 0:c8e9c90ca7f4 56 * @code
eimaiosatanas 0:c8e9c90ca7f4 57 * #include "mbed.h"
eimaiosatanas 0:c8e9c90ca7f4 58 * #include "USBJoystick.h"
eimaiosatanas 0:c8e9c90ca7f4 59 *
eimaiosatanas 0:c8e9c90ca7f4 60 * USBJoystick joystick;
eimaiosatanas 0:c8e9c90ca7f4 61 *
eimaiosatanas 0:c8e9c90ca7f4 62 * int main(void)
eimaiosatanas 0:c8e9c90ca7f4 63 * {
eimaiosatanas 0:c8e9c90ca7f4 64 * while (1)
eimaiosatanas 0:c8e9c90ca7f4 65 * {
eimaiosatanas 0:c8e9c90ca7f4 66 * joystick.move(20, 0);
eimaiosatanas 0:c8e9c90ca7f4 67 * wait(0.5);
eimaiosatanas 0:c8e9c90ca7f4 68 * }
eimaiosatanas 0:c8e9c90ca7f4 69 * }
eimaiosatanas 0:c8e9c90ca7f4 70 *
eimaiosatanas 0:c8e9c90ca7f4 71 * @endcode
eimaiosatanas 0:c8e9c90ca7f4 72 *
eimaiosatanas 0:c8e9c90ca7f4 73 *
eimaiosatanas 0:c8e9c90ca7f4 74 * @code
eimaiosatanas 0:c8e9c90ca7f4 75 * #include "mbed.h"
eimaiosatanas 0:c8e9c90ca7f4 76 * #include "USBJoystick.h"
eimaiosatanas 0:c8e9c90ca7f4 77 * #include <math.h>
eimaiosatanas 0:c8e9c90ca7f4 78 *
eimaiosatanas 0:c8e9c90ca7f4 79 * USBJoystick joystick;
eimaiosatanas 0:c8e9c90ca7f4 80 *
eimaiosatanas 0:c8e9c90ca7f4 81 * int main(void)
eimaiosatanas 0:c8e9c90ca7f4 82 * {
eimaiosatanas 0:c8e9c90ca7f4 83 * int16_t i = 0;
eimaiosatanas 0:c8e9c90ca7f4 84 * int16_t throttle = 0;
eimaiosatanas 0:c8e9c90ca7f4 85 * int16_t rudder = 0;
eimaiosatanas 0:c8e9c90ca7f4 86 * int16_t x = 0;
eimaiosatanas 0:c8e9c90ca7f4 87 * int16_t y = 0;
eimaiosatanas 0:c8e9c90ca7f4 88 * int32_t radius = 120;
eimaiosatanas 0:c8e9c90ca7f4 89 * int32_t angle = 0;
eimaiosatanas 0:c8e9c90ca7f4 90 * int8_t button = 0;
eimaiosatanas 0:c8e9c90ca7f4 91 * int8_t hat = 0;
eimaiosatanas 0:c8e9c90ca7f4 92 *
eimaiosatanas 0:c8e9c90ca7f4 93 * while (1) {
eimaiosatanas 0:c8e9c90ca7f4 94 * // Basic Joystick
eimaiosatanas 0:c8e9c90ca7f4 95 * throttle = (i >> 8) & 0xFF; // value -127 .. 128
eimaiosatanas 0:c8e9c90ca7f4 96 * rudder = (i >> 8) & 0xFF; // value -127 .. 128
eimaiosatanas 0:c8e9c90ca7f4 97 * button = (i >> 8) & 0x0F; // value 0 .. 15, one bit per button
eimaiosatanas 0:c8e9c90ca7f4 98 * hat = (i >> 8) & 0x07; // value 0..7 or 8 for neutral
eimaiosatanas 0:c8e9c90ca7f4 99 * i++;
eimaiosatanas 0:c8e9c90ca7f4 100 *
eimaiosatanas 0:c8e9c90ca7f4 101 * x = cos((double)angle*3.14/180.0)*radius; // value -127 .. 128
eimaiosatanas 0:c8e9c90ca7f4 102 * y = sin((double)angle*3.14/180.0)*radius; // value -127 .. 128
eimaiosatanas 0:c8e9c90ca7f4 103 * angle += 3;
eimaiosatanas 0:c8e9c90ca7f4 104 *
eimaiosatanas 0:c8e9c90ca7f4 105 * joystick.update(throttle, rudder, x, y, button, hat);
eimaiosatanas 0:c8e9c90ca7f4 106 *
eimaiosatanas 0:c8e9c90ca7f4 107 * wait(0.001);
eimaiosatanas 0:c8e9c90ca7f4 108 * }
eimaiosatanas 0:c8e9c90ca7f4 109 * }
eimaiosatanas 0:c8e9c90ca7f4 110 * @endcode
eimaiosatanas 0:c8e9c90ca7f4 111 */
eimaiosatanas 0:c8e9c90ca7f4 112
eimaiosatanas 0:c8e9c90ca7f4 113
eimaiosatanas 0:c8e9c90ca7f4 114 class USBJoystick: public USBHID {
eimaiosatanas 0:c8e9c90ca7f4 115 public:
eimaiosatanas 0:c8e9c90ca7f4 116
eimaiosatanas 0:c8e9c90ca7f4 117 /**
eimaiosatanas 0:c8e9c90ca7f4 118 * Constructor
eimaiosatanas 0:c8e9c90ca7f4 119 *
eimaiosatanas 0:c8e9c90ca7f4 120 * @param vendor_id Your vendor_id (default: 0x1234)
eimaiosatanas 0:c8e9c90ca7f4 121 * @param product_id Your product_id (default: 0x0002)
eimaiosatanas 0:c8e9c90ca7f4 122 * @param product_release Your product_release (default: 0x0001)
eimaiosatanas 0:c8e9c90ca7f4 123 */
eimaiosatanas 0:c8e9c90ca7f4 124 USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0100, uint16_t product_release = 0x0001):
eimaiosatanas 0:c8e9c90ca7f4 125 USBHID(0, 0, vendor_id, product_id, product_release, false)
eimaiosatanas 0:c8e9c90ca7f4 126 {
eimaiosatanas 0:c8e9c90ca7f4 127 _init();
eimaiosatanas 0:c8e9c90ca7f4 128 connect();
eimaiosatanas 0:c8e9c90ca7f4 129 };
eimaiosatanas 0:c8e9c90ca7f4 130
eimaiosatanas 0:c8e9c90ca7f4 131 /**
eimaiosatanas 0:c8e9c90ca7f4 132 * Write a state of the mouse
eimaiosatanas 0:c8e9c90ca7f4 133 *
eimaiosatanas 0:c8e9c90ca7f4 134 * @param t throttle position
eimaiosatanas 0:c8e9c90ca7f4 135 * @param r rudder position
eimaiosatanas 0:c8e9c90ca7f4 136 * @param x x-axis position
eimaiosatanas 0:c8e9c90ca7f4 137 * @param y y-axis position
eimaiosatanas 0:c8e9c90ca7f4 138 * @param buttons buttons state
eimaiosatanas 0:c8e9c90ca7f4 139 * @param hat hat state 0 (up), 1 (right, 2 (down), 3 (left) or 4 (neutral)
eimaiosatanas 0:c8e9c90ca7f4 140 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 141 */
eimaiosatanas 0:c8e9c90ca7f4 142 bool update(int16_t t, int16_t r, int16_t x, int16_t y, uint16_t buttons, uint8_t hat);
eimaiosatanas 0:c8e9c90ca7f4 143
eimaiosatanas 0:c8e9c90ca7f4 144 /**
eimaiosatanas 0:c8e9c90ca7f4 145 * Write a state of the mouse
eimaiosatanas 0:c8e9c90ca7f4 146 *
eimaiosatanas 0:c8e9c90ca7f4 147 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 148 */
eimaiosatanas 0:c8e9c90ca7f4 149 bool update();
eimaiosatanas 0:c8e9c90ca7f4 150
eimaiosatanas 0:c8e9c90ca7f4 151 /**
eimaiosatanas 0:c8e9c90ca7f4 152 * Move the throttle position
eimaiosatanas 0:c8e9c90ca7f4 153 *
eimaiosatanas 0:c8e9c90ca7f4 154 * @param t throttle position
eimaiosatanas 0:c8e9c90ca7f4 155 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 156 */
eimaiosatanas 0:c8e9c90ca7f4 157 bool throttle(int16_t t);
eimaiosatanas 0:c8e9c90ca7f4 158
eimaiosatanas 0:c8e9c90ca7f4 159 /**
eimaiosatanas 0:c8e9c90ca7f4 160 * Move the rudder position
eimaiosatanas 0:c8e9c90ca7f4 161 *
eimaiosatanas 0:c8e9c90ca7f4 162 * @param r rudder position
eimaiosatanas 0:c8e9c90ca7f4 163 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 164 */
eimaiosatanas 0:c8e9c90ca7f4 165 bool rudder(int16_t r);
eimaiosatanas 0:c8e9c90ca7f4 166
eimaiosatanas 0:c8e9c90ca7f4 167 /**
eimaiosatanas 0:c8e9c90ca7f4 168 * Move the cursor to (x, y)
eimaiosatanas 0:c8e9c90ca7f4 169 *
eimaiosatanas 0:c8e9c90ca7f4 170 * @param x-axis position
eimaiosatanas 0:c8e9c90ca7f4 171 * @param y-axis position
eimaiosatanas 0:c8e9c90ca7f4 172 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 173 */
eimaiosatanas 0:c8e9c90ca7f4 174 bool move(int16_t x, int16_t y);
eimaiosatanas 0:c8e9c90ca7f4 175
eimaiosatanas 0:c8e9c90ca7f4 176 /**
eimaiosatanas 0:c8e9c90ca7f4 177 * Press one or several buttons
eimaiosatanas 0:c8e9c90ca7f4 178 *
eimaiosatanas 0:c8e9c90ca7f4 179 * @param button button state
eimaiosatanas 0:c8e9c90ca7f4 180 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 181 */
eimaiosatanas 0:c8e9c90ca7f4 182 bool button(uint16_t button);
eimaiosatanas 0:c8e9c90ca7f4 183
eimaiosatanas 0:c8e9c90ca7f4 184 /**
eimaiosatanas 0:c8e9c90ca7f4 185 * Press hat
eimaiosatanas 0:c8e9c90ca7f4 186 *
eimaiosatanas 0:c8e9c90ca7f4 187 * @param hat hat state
eimaiosatanas 0:c8e9c90ca7f4 188 * @returns true if there is no error, false otherwise
eimaiosatanas 0:c8e9c90ca7f4 189 */
eimaiosatanas 0:c8e9c90ca7f4 190 bool hat(uint8_t hat);
eimaiosatanas 0:c8e9c90ca7f4 191
eimaiosatanas 0:c8e9c90ca7f4 192 /*
eimaiosatanas 0:c8e9c90ca7f4 193 * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
eimaiosatanas 0:c8e9c90ca7f4 194 *
eimaiosatanas 0:c8e9c90ca7f4 195 * @returns pointer to the report descriptor
eimaiosatanas 0:c8e9c90ca7f4 196 */
eimaiosatanas 0:c8e9c90ca7f4 197 virtual uint8_t * reportDesc();
eimaiosatanas 0:c8e9c90ca7f4 198
eimaiosatanas 0:c8e9c90ca7f4 199 private:
eimaiosatanas 0:c8e9c90ca7f4 200 int8_t _t;
eimaiosatanas 0:c8e9c90ca7f4 201 int8_t _r;
eimaiosatanas 0:c8e9c90ca7f4 202 int8_t _x;
eimaiosatanas 0:c8e9c90ca7f4 203 int8_t _y;
eimaiosatanas 0:c8e9c90ca7f4 204 uint16_t _button;
eimaiosatanas 0:c8e9c90ca7f4 205 uint8_t _hat;
eimaiosatanas 0:c8e9c90ca7f4 206
eimaiosatanas 0:c8e9c90ca7f4 207 void _init();
eimaiosatanas 0:c8e9c90ca7f4 208 };
eimaiosatanas 0:c8e9c90ca7f4 209
eimaiosatanas 0:c8e9c90ca7f4 210 #endif