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:
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?

UserRevisionLine numberNew 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 }