Modification of USB Joystick to work as a Hitbox-like game controller using the F401RE. Works reasonably well under Windows.
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...)
main.cpp@2:278b7a590311, 2015-04-20 (annotated)
- Committer:
- eimaiosatanas
- Date:
- Mon Apr 20 14:58:21 2015 +0000
- Revision:
- 2:278b7a590311
- Parent:
- 1:6b3335ac3862
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?
User | Revision | Line number | New contents of line |
---|---|---|---|
eimaiosatanas | 0:c8e9c90ca7f4 | 1 | #include "mbed.h" |
eimaiosatanas | 0:c8e9c90ca7f4 | 2 | #include "USBJoystick.h" |
eimaiosatanas | 0:c8e9c90ca7f4 | 3 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 4 | USBJoystick joystick; |
eimaiosatanas | 0:c8e9c90ca7f4 | 5 | // Variables for Heartbeat and Status monitoring |
eimaiosatanas | 0:c8e9c90ca7f4 | 6 | DigitalOut myled1(LED1); |
eimaiosatanas | 0:c8e9c90ca7f4 | 7 | DigitalOut myled2(LED2); |
eimaiosatanas | 0:c8e9c90ca7f4 | 8 | DigitalOut myled3(LED3); |
eimaiosatanas | 0:c8e9c90ca7f4 | 9 | DigitalOut heartbeatLED(LED4); |
eimaiosatanas | 0:c8e9c90ca7f4 | 10 | #define IN_UP PC_0 |
eimaiosatanas | 0:c8e9c90ca7f4 | 11 | #define IN_RIGHT PC_1 |
eimaiosatanas | 0:c8e9c90ca7f4 | 12 | #define IN_DOWN PB_0 |
eimaiosatanas | 0:c8e9c90ca7f4 | 13 | #define IN_LEFT PA_4 |
eimaiosatanas | 0:c8e9c90ca7f4 | 14 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 15 | #define UP 0x01 |
eimaiosatanas | 0:c8e9c90ca7f4 | 16 | #define RIGHT 0x02 |
eimaiosatanas | 0:c8e9c90ca7f4 | 17 | #define DOWN 0x04 |
eimaiosatanas | 0:c8e9c90ca7f4 | 18 | #define LEFT 0x08 |
eimaiosatanas | 2:278b7a590311 | 19 | #ifdef TARGET_STM32F4 |
eimaiosatanas | 0:c8e9c90ca7f4 | 20 | BusIn hatin(PC_0, PC_1, PB_0, PA_4); |
eimaiosatanas | 0:c8e9c90ca7f4 | 21 | BusIn buttonin(PH_0, PA_15, PB_7, PH_1, PC_3, PC_2, PC_15, PC_14, PA_13, PA_14); |
eimaiosatanas | 0:c8e9c90ca7f4 | 22 | DigitalIn psbutton(PC_12); |
eimaiosatanas | 2:278b7a590311 | 23 | #endif |
eimaiosatanas | 2:278b7a590311 | 24 | #ifdef TARGET_KL25Z |
eimaiosatanas | 2:278b7a590311 | 25 | BusIn hatin(PTC1, PTC2, PTB3, PTB2); |
eimaiosatanas | 2:278b7a590311 | 26 | BusIn buttonin(PTE30, PTE29, PTE23, PTE22, PTE21, PTE20, PTE5, PTE4, PTE3, PTE2); |
eimaiosatanas | 2:278b7a590311 | 27 | DigitalIn psbutton(PTB8); |
eimaiosatanas | 2:278b7a590311 | 28 | DigitalOut extraGround(PTD3); |
eimaiosatanas | 2:278b7a590311 | 29 | #endif |
eimaiosatanas | 2:278b7a590311 | 30 | |
eimaiosatanas | 1:6b3335ac3862 | 31 | //Ticker heartbeat; |
eimaiosatanas | 0:c8e9c90ca7f4 | 32 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 33 | // Heartbeat monitor |
eimaiosatanas | 1:6b3335ac3862 | 34 | /* |
eimaiosatanas | 0:c8e9c90ca7f4 | 35 | void pulse() { |
eimaiosatanas | 0:c8e9c90ca7f4 | 36 | heartbeatLED = !heartbeatLED; |
eimaiosatanas | 0:c8e9c90ca7f4 | 37 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 38 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 39 | void heartbeat_start() { |
eimaiosatanas | 0:c8e9c90ca7f4 | 40 | heartbeat.attach(&pulse, 0.5); |
eimaiosatanas | 0:c8e9c90ca7f4 | 41 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 42 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 43 | void heartbeat_stop() { |
eimaiosatanas | 0:c8e9c90ca7f4 | 44 | heartbeat.detach(); |
eimaiosatanas | 0:c8e9c90ca7f4 | 45 | } |
eimaiosatanas | 1:6b3335ac3862 | 46 | */ |
eimaiosatanas | 0:c8e9c90ca7f4 | 47 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 48 | int main() { |
eimaiosatanas | 0:c8e9c90ca7f4 | 49 | hatin.mode(PullUp); |
eimaiosatanas | 0:c8e9c90ca7f4 | 50 | buttonin.mode(PullUp); |
eimaiosatanas | 0:c8e9c90ca7f4 | 51 | psbutton.mode(PullUp); |
eimaiosatanas | 2:278b7a590311 | 52 | #ifdef TARGET_KL25Z |
eimaiosatanas | 2:278b7a590311 | 53 | extraGround.write(0); |
eimaiosatanas | 2:278b7a590311 | 54 | #endif |
eimaiosatanas | 1:6b3335ac3862 | 55 | heartbeatLED = 0; |
eimaiosatanas | 1:6b3335ac3862 | 56 | #define UPDATEINTERVAL 0.002 |
eimaiosatanas | 1:6b3335ac3862 | 57 | int i = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 58 | int16_t throttle = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 59 | int16_t rudder = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 60 | int16_t x = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 61 | int16_t y = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 62 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 63 | int16_t button = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 64 | int8_t hat = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 65 | int8_t hat_reverse = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 66 | int8_t isUp = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 67 | int8_t isDown = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 68 | int8_t isLeft = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 69 | int8_t isRight = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 70 | int16_t ps = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 71 | |
eimaiosatanas | 1:6b3335ac3862 | 72 | //heartbeat_start(); |
eimaiosatanas | 0:c8e9c90ca7f4 | 73 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 74 | while (1) { |
eimaiosatanas | 0:c8e9c90ca7f4 | 75 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 76 | throttle = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 77 | rudder = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 78 | x = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 79 | y = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 80 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 81 | button = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 82 | button = ( ~buttonin) & 0x03ff; |
eimaiosatanas | 0:c8e9c90ca7f4 | 83 | ps = (psbutton)? 0 : 1; |
eimaiosatanas | 0:c8e9c90ca7f4 | 84 | button |= ( ps << 12); |
eimaiosatanas | 0:c8e9c90ca7f4 | 85 | hat_reverse = (~hatin) & 0x0F ; |
eimaiosatanas | 0:c8e9c90ca7f4 | 86 | isUp = isDown = isLeft = isRight = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 87 | if (hat_reverse & DOWN){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 88 | isDown = 1; |
eimaiosatanas | 0:c8e9c90ca7f4 | 89 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 90 | if (hat_reverse & UP){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 91 | isUp =1; |
eimaiosatanas | 0:c8e9c90ca7f4 | 92 | isDown = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 93 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 94 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 95 | if (hat_reverse & RIGHT){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 96 | isRight = 1; |
eimaiosatanas | 0:c8e9c90ca7f4 | 97 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 98 | if (hat_reverse & LEFT){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 99 | isLeft = 1; |
eimaiosatanas | 0:c8e9c90ca7f4 | 100 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 101 | if (isLeft && isRight){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 102 | isLeft = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 103 | isRight = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 104 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 105 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 106 | if (isUp && isLeft) { |
eimaiosatanas | 0:c8e9c90ca7f4 | 107 | hat = 7; |
eimaiosatanas | 0:c8e9c90ca7f4 | 108 | } else if (isUp && isRight){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 109 | hat = 1; |
eimaiosatanas | 0:c8e9c90ca7f4 | 110 | } else if (isDown && isLeft){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 111 | hat = 5; |
eimaiosatanas | 0:c8e9c90ca7f4 | 112 | } else if (isDown && isRight){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 113 | hat = 3; |
eimaiosatanas | 0:c8e9c90ca7f4 | 114 | } else if (isUp){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 115 | hat = 0; |
eimaiosatanas | 0:c8e9c90ca7f4 | 116 | } else if (isDown){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 117 | hat = 4; |
eimaiosatanas | 0:c8e9c90ca7f4 | 118 | } else if (isRight){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 119 | hat = 2; |
eimaiosatanas | 0:c8e9c90ca7f4 | 120 | } else if (isLeft){ |
eimaiosatanas | 0:c8e9c90ca7f4 | 121 | hat = 6; |
eimaiosatanas | 0:c8e9c90ca7f4 | 122 | } else { |
eimaiosatanas | 0:c8e9c90ca7f4 | 123 | hat = 9; |
eimaiosatanas | 0:c8e9c90ca7f4 | 124 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 125 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 126 | joystick.update(throttle, rudder, x, y, button, hat); |
eimaiosatanas | 1:6b3335ac3862 | 127 | i = (i + 1) % 500 ; |
eimaiosatanas | 1:6b3335ac3862 | 128 | if (i == 0){ |
eimaiosatanas | 1:6b3335ac3862 | 129 | heartbeatLED = !heartbeatLED; |
eimaiosatanas | 1:6b3335ac3862 | 130 | } |
eimaiosatanas | 1:6b3335ac3862 | 131 | wait(UPDATEINTERVAL); |
eimaiosatanas | 0:c8e9c90ca7f4 | 132 | } |
eimaiosatanas | 0:c8e9c90ca7f4 | 133 | |
eimaiosatanas | 0:c8e9c90ca7f4 | 134 | } |