A fully-Android-compatible two joysticks USB driver for LPC1768. The joysticks have 1 hat, 6 buttons, and there are 1P, 2P buttons.

Dependencies:   mbed

Fork of app-board-Joystick by Chris Styles

Files at this revision

API Documentation at this revision

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

config.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
usbhid.cpp Show annotated file Show diff for this revision Revisions of this file
usbhid.h Show annotated file Show diff for this revision Revisions of this file
--- /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();
 };