A fully-Android-compatible two joysticks USB driver for LPC1768. The joysticks have 1 hat, 6 buttons, and there are 1P, 2P buttons.
Fork of app-board-Joystick by
Revision 2:84ea6e2fb4b6, committed 2016-12-17
- Comitter:
- Alberto_Wino
- Date:
- Sat Dec 17 13:13:59 2016 +0000
- Parent:
- 1:76c47d2ba442
- Child:
- 3:f1a8ec4659f8
- Commit message:
- Added 2nd-pad-as-buttons configuration.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config.h Sat Dec 17 13:13:59 2016 +0000 @@ -0,0 +1,16 @@ +#pragma once + +// Define only one of the following configurations. + +// This configuration declares one interface, and two reports. This works well +// with SDL, but some applications may fail to detect the second set of buttons +// and hat. +//#define CONFIG_TWO_REPORTS + + +// This configuration declares one interface, one reports. The second joystick +// is declared as four buttons instead of an extra hat. Some applications +// fail to detect more than 16 buttons, or be confused by them. +//#define CONFIG_2ND_PAD_AS_BUTTONS + +#define CONFIG_TWO_INTERFACES \ No newline at end of file
--- a/main.cpp Fri Dec 16 18:17:42 2016 +0000 +++ b/main.cpp Sat Dec 17 13:13:59 2016 +0000 @@ -1,41 +1,63 @@ +#include "config.h" #include "mbed.h" #include "usbhid.h" -#define IGN p5 /* ignore */ +#ifdef CONFIG_TWO_REPORTS BusIn buttonsL ( p17, p16, p15, p20, // 3 top row, bottom-left - p19, p18, p14, IGN, // 2 bottom right, 1p - IGN, IGN, IGN, IGN + p19, p18, p14 // 2 bottom right, 1p ); BusIn buttonsR ( p9, p8, p7, p12, // 3 top row, bottom-left - p11, p10, p6, IGN, // 2 bottom right, 2p - IGN, IGN, IGN, IGN + p11, p10, p6 // 2 bottom right, 2p ); BusIn stickL(p21, p22, p23, p24); BusIn stickR(p28, p26, p27, p29); +#endif + +#ifdef CONFIG_2ND_PAD_AS_BUTTONS +BusIn buttonsL +( + p17, p16, p15, p20, // 3 top row, bottom-left + p19, p18, p14 // 2 bottom right, 1p +); + +BusIn buttonsR +( + p9, p8, p7, p12, // 3 top row, bottom-left + p11, p10, p6, p28, // 2 bottom right, 2p, pad + p26, p27, p29 // pad, pad, pad +); + +BusIn stickL(p21, p22, p23, p24); +#endif USBJoystick joysticks; // left and right pads int main() { - unsigned char stickL_old = 0; - unsigned char stickR_old = 0; - unsigned char buttonsL_old = 0; - unsigned char buttonsR_old = 0; + uint8_t stickL_old = 0; +#ifdef CONFIG_TWO_REPORTS + uint8_t stickR_old = 0; +#endif + uint32_t buttonsL_old = 0; + uint32_t buttonsR_old = 0; while(1) { - const unsigned char stickL_new = stickL.read(); - const unsigned char stickR_new = stickR.read(); - const unsigned long buttonsL_new = buttonsL.read(); - const unsigned long buttonsR_new = buttonsR.read(); + const uint8_t stickL_new = stickL.read(); +#ifdef CONFIG_TWO_REPORTS + const uint8_t stickR_new = stickR.read(); +#endif + const uint32_t buttonsL_new = buttonsL.read(); + const uint32_t buttonsR_new = buttonsR.read(); +#ifdef CONFIG_TWO_REPORTS if ((stickL_old != stickL_new) || (buttonsL_old != buttonsL_new)) { stickL_old = stickL_new; @@ -49,6 +71,20 @@ buttonsR_old = buttonsR_new; joysticks.update(2, stickR_old, buttonsR_old); } +#endif + +#ifdef CONFIG_2ND_PAD_AS_BUTTONS + if ((stickL_old != stickL_new) || (buttonsL_old != buttonsL_new) || (buttonsR_old != buttonsR_new)) + { + const uint32_t buttons = buttonsL_new | (buttonsR_new << 7); + + stickL_old = stickL_new; + buttonsL_old = buttonsL_new; + buttonsR_old = buttonsR_new; + joysticks.update(0, stickL_old, buttons); + } +#endif + wait(0.016666); /* 60 Hz */ } } \ No newline at end of file
--- a/usbhid.cpp Fri Dec 16 18:17:42 2016 +0000 +++ b/usbhid.cpp Sat Dec 17 13:13:59 2016 +0000 @@ -4,9 +4,11 @@ /* Modified by yours truly */ +#include "config.h" #include "mbed.h" #include "usbhid.h" +#ifdef CONFIG_TWO_REPORTS /* Report for 2 arcade joysticks */ static uint8_t report_descriptor_joystick[] = { @@ -89,6 +91,57 @@ 0xc0, // END_COLLECTION -- application }; +#endif + +#ifdef CONFIG_2ND_PAD_AS_BUTTONS +static uint8_t report_descriptor_joystick[] = +{ +0x05, 0x01, // USAGE_PAGE (Generic Desktop) +0x09, 0x05, // USAGE (Gamepad) +0xa1, 0x01, // COLLECTION (Application) + +0xa1, 0x00, // COLLECTION (Physical) +0x15, 0x00, // LOGICAL_MINIMUM (0) +0x25, 0x01, // LOGICAL_MAXIMUM (1) +0x35, 0x00, // PHYSICAL_MINIMUM (0) +0x45, 0x01, // PHYSICAL_MAXIMUM (1) +0x75, 0x01, // REPORT_SIZE (1) +0x95, 0x12, // REPORT_COUNT (18) +0x05, 0x09, // USAGE_PAGE (Button) +0x19, 0x01, // USAGE_MINIMUM (Button 1) +0x29, 0x12, // USAGE_MAXIMUM (Button 18) +0x81, 0x02, // INPUT (Data,Var,Abs) +// does not work, why???????? +0x95, 0x06, // REPORT_COUNT (6) +0x81, 0x01, // INPUT (Cnst,Ary,Abs) +0x05, 0x01, // USAGE_PAGE (Generic Desktop) +0x25, 0x07, // LOGICAL_MAXIMUM (7) +0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315) +0x75, 0x04, // REPORT_SIZE (4) +0x95, 0x01, // REPORT_COUNT (1) +0x65, 0x14, // UNIT (Eng Rot:Angular Pos) +0x09, 0x39, // USAGE (Hat switch) +0x81, 0x42, // INPUT (Data,Var,Abs,Null) +0x65, 0x00, // UNIT (None) +0x95, 0x01, // REPORT_COUNT (1) +0x81, 0x01, // INPUT (Cnst,Ary,Abs) +0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) +0x46, 0xff, 0x00, // PHYSICAL_MAXIMUM (255) + +/* For some reason, this is necessary (though we never put it in the report). */ +0x09, 0x30, // USAGE (X) +0x09, 0x31, // USAGE (Y) +0x75, 0x04, // REPORT_SIZE (4) +0x95, 0x02, // REPORT_COUNT (2) +0x81, 0x02, // INPUT (Data,Var,Abs) + +0xc0, // END_COLLECTION -- physical + +0xc0, // END_COLLECTION -- application +}; + +#endif + /* Endpoint packet sizes */ #define MAX_PACKET_SIZE_EP1 64 @@ -266,7 +319,34 @@ } } -bool USBJoystick::update(unsigned char gamepad_id, unsigned char stick, unsigned char buttons) +/*#define JOYSTICK_UP (1<<0) +#define JOYSTICK_DOWN (1<<1) +#define JOYSTICK_LEFT (1<<2) +#define JOYSTICK_RIGHT (1<<3) + +const uint8_t hat_map[8] = +{ + 0xf, // 0: neutral + 0, // 1: up + 4, // 2: down + 0xf, // 3: n/a (up + down) + 6, // 4: left + 7, // 5: left + up + 4, // 6: left + down + 6, // 7: left (+ up + down) + 2, // 8: right + 1, // 9: right + up + 3, //10: right + down + 2, //11: right (+ up + down) + 0xf, //12: n/a (left + right) + 0, //13: up (+ left + right) + 4, //14: down (+ left + right) + 0 //15: n/a +}; +*/ + + +bool USBJoystick::update(uint8_t gamepad_id, uint8_t stick, uint32_t buttons) { unsigned char hatswitch; if (stick & JOYSTICK_UP) @@ -294,10 +374,20 @@ hatswitch = 0xf; /* Prepare report */ +#ifdef CONFIG_TWO_REPORTS unsigned char report[3]; report[0] = gamepad_id; report[1] = buttons; report[2] = hatswitch; +#endif + +#ifdef CONFIG_2ND_PAD_AS_BUTTONS + unsigned char report[4]; + report[0] = buttons & 0xff; + report[1] = (buttons >> 8) & 0xff; + report[2] = (buttons >> 16) & 0x03; + report[3] = hatswitch; +#endif /* Block if not configured */ while(!configured) ; @@ -305,7 +395,13 @@ /* Send report */ complete = false; disableEvents(); +#ifdef CONFIG_TWO_REPORTS endpointWrite(EP1IN, report, 3); +#endif +#ifdef CONFIG_2ND_PAD_AS_BUTTONS + endpointWrite(EP1IN, report, 4); +#endif + enableEvents(); /* Wait for completion */
--- a/usbhid.h Fri Dec 16 18:17:42 2016 +0000 +++ b/usbhid.h Sat Dec 17 13:13:59 2016 +0000 @@ -28,7 +28,7 @@ { public: USBJoystick(); - bool update(unsigned char gamepad_id, unsigned char stick, unsigned char buttons); + bool update(uint8_t gamepad_id, uint8_t stick, uint32_t buttons); protected: virtual bool requestGetDescriptor(); };