Demo for USBJoystick updated for 32 buttons.

Dependencies:   USBDevice USBJoystick_SIM mbed USBJoystick_2

Dependents:   USBJoystick_2

Fork of USBJoystick_HelloWorld2 by Wim Huiskamp

Files at this revision

API Documentation at this revision

Comitter:
Cirrus01
Date:
Sun Jul 22 10:36:35 2018 +0000
Parent:
0:e43878690c0e
Child:
2:967da2faedcd
Commit message:
Inital

Changed in this revision

USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
USBJoystick.lib Show annotated file Show diff for this revision Revisions of this file
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
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- a/USBDevice.lib	Thu Jan 05 14:23:14 2017 +0000
+++ b/USBDevice.lib	Sun Jul 22 10:36:35 2018 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/USBDevice/#01321bd6ff89
+http://mbed.org/users/mbed_official/code/USBDevice/#53949e6131f6
--- a/USBJoystick.lib	Thu Jan 05 14:23:14 2017 +0000
+++ b/USBJoystick.lib	Sun Jul 22 10:36:35 2018 +0000
@@ -1,1 +1,1 @@
-https://developer.mbed.org/users/wim/code/USBJoystick/#e086541742c3
+https://os.mbed.com/users/Cirrus01/code/USBJoystick_SIM/#92574cf6e9af
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Sun Jul 22 10:36:35 2018 +0000
@@ -0,0 +1,86 @@
+#define TARGET_STM32F4XX
+#define NUM_OF_BUTTONS 32
+#define NUM_OF_HAT_BUTTONS 4
+#define SYSTEM_CLOCK_HZ                 96000000  // 96MHz 
+
+// Joystick button input pin assignments.  
+//
+// You can wire up to 32 GPIO ports to buttons (equipped with 
+// momentary switches).  Connect each switch between the desired 
+// GPIO port and ground (J9 pin 12 or 14).  When the button is pressed, 
+// we'll tell the host PC that the corresponding joystick button is 
+// pressed.  We debounce the keystrokes in software, so you can simply 
+// wire directly to pushbuttons with no additional external hardware.
+//
+// Note that we assign 24 buttons by default, even though the USB
+// joystick interface can handle up to 32 buttons.  VP itself only
+// allows mapping of up to 24 buttons in the preferences dialog 
+// (although it can recognize 32 buttons internally).  If you want 
+// more buttons, you can reassign pins that are assigned by default
+// as LedWiz outputs.  To reassign a pin, find the pin you wish to
+// reassign in the LedWizPortMap array below, and change the pin name 
+// there to NC (for Not Connected).  You can then change one of the
+// "NC" entries below to the reallocated pin name.  The limit is 32
+// buttons total.
+//
+// (If you're using TLC5940 chips to control outputs, many of the
+// GPIO pins that are mapped to LedWiz outputs in the default
+// mapping can be reassigned as keys, since the TLC5940 outputs
+// take over for the GPIO pins.  The exceptions are the pins that
+// are reassigned to control the TLC5940 chips.)
+//
+// Note: PTD1 (pin J2-12) should NOT be assigned as a button input,
+// as this pin is physically connected on the KL25Z to the on-board
+// indicator LED's blue segment.
+
+PinName buttonMap[] = {
+    PB_3,      // button 1
+    PB_5,      // button 2
+    PB_10,     // button 3
+    PC_7,      // button 4
+    PB_6,      // button 5
+    PA_5,      // button 6
+    PB_4,      // button 7
+    PB_13,     // button 8
+    PB_14,     // button 9
+    PB_15,     // button 10
+    PB_1,      // button 11
+    PB_2,      // button 12
+    PC_5,      // button 13
+    PC_6,      // button 14
+    PC_8,      // button 15
+    PC_4,      // button 16
+    NC,        // button 17
+    NC,        // button 18
+    NC,        // button 19
+    NC,        // button 20
+    NC,        // button 21
+    NC,        // button 22
+    NC,        // button 23
+    NC,        // button 24
+    NC,        // button 25
+    NC,        // button 26
+    NC,        // button 27
+    NC,        // button 28
+    NC,        // button 29
+    NC,        // button 30
+    NC,        // button 31
+    NC         // button 32
+};
+
+PinName hatMap[] = {
+    PA_13,      // button 1
+    PA_14,      // button 2
+    PA_15,     // button 3
+    PB_7,      // button 4
+    NC,        // button 5
+    NC,        // button 6
+    NC,        // button 7
+    NC         // button 8
+};
+
+
+// STANDARD ID SETTINGS.  These provide full, transparent LedWiz compatibility.
+const uint16_t USB_VENDOR_ID = 0x1209;      
+const uint16_t USB_PRODUCT_ID = 0xACDE;     
+const uint16_t USB_PRODUCT_VER = 0x0002;     
\ No newline at end of file
--- a/main.cpp	Thu Jan 05 14:23:14 2017 +0000
+++ b/main.cpp	Sun Jul 22 10:36:35 2018 +0000
@@ -2,7 +2,7 @@
  * Copyright (c) 2012, v01:  Initial version, WH,
  *                           Modified USBMouse code ARM Limited.
  *                           (c) 2010-2011 mbed.org, MIT License
- *               2016, v02:  Updated USBDevice Lib, Added waitForConnect, Updated 32 bits button 
+ *               2016, v02:  Updated USBDevice Lib, Added waitForConnect, Updated 32 bits button
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,7 @@
  */
 
 #include "mbed.h"
+#include "config.h"
 #include "USBJoystick.h"
 
 //#define LANDTIGER 1
@@ -32,79 +33,331 @@
 USBJoystick joystick;
 
 // Variables for Heartbeat and Status monitoring
-DigitalOut myled1(LED1);
+DigitalOut myled1(LED4);
 DigitalOut myled2(LED2);
 DigitalOut myled3(LED3);
-DigitalOut heartbeatLED(LED4);
+DigitalOut heartbeatLED(LED1);
+
+AnalogIn inX(A0);
+AnalogIn inY(A1);
+AnalogIn inRudder(A2);
+AnalogIn inThrottle(A3);
+AnalogIn inBreaks(A4);
+AnalogIn inFlaps(A5);
 
 Ticker heartbeat;
 Serial pc(USBTX, USBRX); // tx, rx
 
+// number of elements in an array
+#define countof(x) (sizeof(x)/sizeof((x)[0]))
+
+// button input map array
+DigitalIn *buttonDigIn[NUM_OF_BUTTONS];  // config.h
+
+// hat button input map array
+DigitalIn *hatDigIn[NUM_OF_HAT_BUTTONS];  // config.h
+
 // Heartbeat monitor
-void pulse() {
-  heartbeatLED = !heartbeatLED;
+void pulse()
+{
+    heartbeatLED = !heartbeatLED;
+}
+
+void heartbeat_start()
+{
+    heartbeatLED=1;
+    heartbeat.attach(&pulse, 0.5);
+}
+
+void heartbeat_stop()
+{
+    heartbeat.detach();
 }
 
-void heartbeat_start() {
-  heartbeatLED=1;
-  heartbeat.attach(&pulse, 0.5);
-}
+// button state
+struct ButtonState
+{
+    // current on/off state
+    int pressed;
+    
+    // Sticky time remaining for current state.  When a
+    // state transition occurs, we set this to a debounce
+    // period.  Future state transitions will be ignored
+    // until the debounce time elapses.
+    int bt;
+} buttonState[NUM_OF_BUTTONS];
 
-void heartbeat_stop() {
-  heartbeat.detach();
+// timer for button reports
+static Timer buttonTimer;
+
+// initialize the button inputs
+void initButtons()
+{
+    // create the digital inputs
+    for (int i = 0 ; i < countof(buttonDigIn) ; ++i)
+    {
+        if (i < countof(buttonMap) && buttonMap[i] != NC)
+            buttonDigIn[i] = new DigitalIn(buttonMap[i]);
+        else
+            buttonDigIn[i] = 0;
+    }
+    
+    // start the button timer
+    buttonTimer.start();
 }
 
 
-int main() {
-  uint16_t i = 0;
-  int16_t throttle = 0;
-  int16_t rudder = 0;    
-  int16_t x = 0;
-  int16_t y = 0;
-  int32_t radius = 120;
-  int32_t angle = 0;
-  uint8_t tmp = 0;
-  uint32_t buttons = 0;    
-  uint8_t hat = 0;    
+// read the button input state
+uint32_t readButtons()
+{
+    // start with all buttons off
+    uint32_t buttons = 0;
+    
+    // figure the time elapsed since the last scan
+    int dt = buttonTimer.read_ms();
+    
+    // reset the timef for the next scan
+    buttonTimer.reset();
     
-  pc.printf("Hello World from Joystick!\n\r");
+    // scan the button list
+    uint32_t bit = 1;
+    DigitalIn **di = buttonDigIn;
+    ButtonState *bs = buttonState;
+    for (int i = 0 ; i < countof(buttonDigIn) ; ++i, ++di, ++bs, bit <<= 1)
+    {
+        // read this button
+        if (*di != 0)
+        {
+            // deduct the elapsed time since the last update
+            // from the button's remaining sticky time
+            bs->bt -= dt;
+            if (bs->bt < 0)
+                bs->bt = 0;
+            
+            // If the sticky time has elapsed, note the new physical
+            // state of the button.  If we still have sticky time
+            // remaining, ignore the physical state; the last state
+            // change persists until the sticky time elapses so that
+            // we smooth out any "bounce" (electrical transients that
+            // occur when the switch contact is opened or closed).
+            if (bs->bt == 0)
+            {
+                // get the new physical state
+                int pressed = !(*di)->read();
+                
+                // update the button's logical state if this is a change
+                if (pressed != bs->pressed)
+                {
+                    // store the new state
+                    bs->pressed = pressed;
+                    
+                    // start a new sticky period for debouncing this
+                    // state change
+                    bs->bt = 10;
+                }
+            }
+            
+            // if it's pressed, OR its bit into the state
+            if (bs->pressed)
+                buttons |= bit;
+        }
+    }
+    
+    // return the new button list
+    return buttons;
+}
 
-  heartbeat_start();
+// hat state
+struct HatState
+{
+    // current on/off state
+    int pressed;
+    
+    // Sticky time remaining for current state.  When a
+    // state transition occurs, we set this to a debounce
+    // period.  Future state transitions will be ignored
+    // until the debounce time elapses.
+    int ht;
+} hatState[NUM_OF_HAT_BUTTONS];
+
+// timer for hat reports
+static Timer hatTimer;
+
+// initialize the hat inputs
+void initHat()
+{
+    // create the digital inputs
+    for (int i = 0 ; i < countof(hatDigIn) ; ++i)
+    {
+        if (i < countof(hatMap) && hatMap[i] != NC)
+            hatDigIn[i] = new DigitalIn(hatMap[i]);
+        else
+            hatDigIn[i] = 0;
+    }
+}
 
-  while (1) {
-    // Basic Joystick
-    throttle = (i >> 8) & 0xFF; // value -127 .. 128
-    rudder = (i >> 8) & 0xFF;   // value -127 .. 128        
+// read the hat button input state
+uint8_t readHat()
+{
+    // start with all buttons off
+    uint8_t hat = 0;
+    
+    // figure the time elapsed since the last scan
+    int dt = hatTimer.read_ms();
+    
+    // reset the timef for the next scan
+    hatTimer.reset();
+    
+    // scan the button list
+    uint8_t bit = 1;
+    DigitalIn **di = hatDigIn;
+    HatState *hs = hatState;
+    for (int i = 0 ; i < countof(hatDigIn) ; ++i, ++di, ++hs, bit <<= 1)
+    {
+        // read this button
+        if (*di != 0)
+        {
+            // deduct the elapsed time since the last update
+            // from the button's remaining sticky time
+            hs->ht -= dt;
+            if (hs->ht < 0)
+                hs->ht = 0;
+            
+            // If the sticky time has elapsed, note the new physical
+            // state of the button.  If we still have sticky time
+            // remaining, ignore the physical state; the last state
+            // change persists until the sticky time elapses so that
+            // we smooth out any "bounce" (electrical transients that
+            // occur when the switch contact is opened or closed).
+            if (hs->ht == 0)
+            {
+                // get the new physical state
+                int pressed = !(*di)->read();
+                
+                // update the button's logical state if this is a change
+                if (pressed != hs->pressed)
+                {
+                    // store the new state
+                    hs->pressed = pressed;
+                    
+                    // start a new sticky period for debouncing this
+                    // state change
+                    hs->ht = 10;
+                }
+            }
+            
+            // if it's pressed, OR its bit into the state
+            if (hs->pressed)
+                hat |= bit;
+                pc.printf("Hat: %d\n", hat);
+        }
+    }
+    
+    // return the new button list
+    //pc.printf("Hat: %d", hat);
+    return hat;
+}
 
-#if (BUTTONS4 == 1)        
-    buttons = (i >> 8) & 0x0F;   // value    0 ..  15, one bit per button     
-#endif        
-#if (BUTTONS8 == 1)        
-    buttons = (i >> 8) & 0xFF;   // value    0 .. 255, one bit per button     
-#endif        
-#if (BUTTONS32 == 1)        
-    tmp     = (i >> 8) & 0xFF;   // value    0 .. 255, one bit per button     
-    buttons =           (( tmp <<  0) & 0x000000FF);
-    buttons = buttons | ((~tmp <<  8) & 0x0000FF00);
-    buttons = buttons | (( tmp << 16) & 0x00FF0000);
-    buttons = buttons | ((~tmp << 24) & 0xFF000000);
-#endif        
+int main()
+{
+    //uint16_t i = 0;
+    int16_t throttle = 0;
+    int16_t rudder = 0;
+    int16_t breaks = 0;
+    int16_t flaps = 0;
+    int16_t x = 0;
+    int16_t y = 0;
+    //int32_t radius = 120;
+    //int32_t angle = 0;
+    //uint8_t tmp = 0;
+    //uint32_t tmp = 1;
+    uint32_t buttons = 0;
+    uint8_t hat = 0;
+
+    pc.printf("Hello World from Joystick!\n\r");
+
+    initButtons();
+    initHat();
+    
+    heartbeat_start();
 
-#if (HAT4 == 1)        
-    hat    = (i >> 8) & 0x03;   // value 0, 1, 2, 3 or 4 for neutral 
+    while (1) {
+        // Basic Joystick
+        // throttle = (i >> 8) & 0xFF; // value -127 .. 128
+        // rudder = (i >> 8) & 0xFF;   // value -127 .. 128
+        // breaks = (i >> 8) & 0xFF;   // value 0 .. 255
+        // flaps = (i >> 8) & 0xFF;   // value 0 .. 255
+
+/*
+#if (BUTTONS4 == 1)
+        buttons = (i >> 8) & 0x0F;   // value    0 ..  15, one bit per button
+#endif
+#if (BUTTONS8 == 1)
+        buttons = (i >> 8) & 0xFF;   // value    0 .. 255, one bit per button
+#endif
+#if (BUTTONS32 == 1)
+        //tmp     = (i >> 8) & 0xFF;   // value    0 .. 255, one bit per button
+        //buttons =           (( tmp <<  0) & 0x000000FF);
+        //buttons = buttons | ((~tmp <<  8) & 0x0000FF00);
+        //buttons = buttons | (( tmp << 16) & 0x00FF0000);
+        //buttons = buttons | ((~tmp << 24) & 0xFF000000);//
+        buttons = tmp;
+        tmp += 1;
+        pc.printf("Tmp: %u\n", tmp);
+#endif
+
+#if (HAT4 == 1)
+        hat    = (i >> 8) & 0x03;   // value 0, 1, 2, 3 or 4 for neutral
 #endif
 #if (HAT8 == 1)
-    hat    = (i >> 8) & 0x07;   // value 0..7 or 8 for neutral
-#endif        
-    i++;        
+        hat    = (i >> 8) & 0x07;   // value 0..7 or 8 for neutral
+#endif
+        i++;
+
+        //x = cos((double)angle*3.14/180.0)*radius;  // value -127 .. 128
+        //y = sin((double)angle*3.14/180.0)*radius;  // value -127 .. 128
+        //angle += 3;
+*/        
+
+        buttons = readButtons();
+        hat = readHat();
+        //pc.printf("Hat: %d\n", hat);
         
-    x = cos((double)angle*3.14/180.0)*radius;  // value -127 .. 128
-    y = sin((double)angle*3.14/180.0)*radius;  // value -127 .. 128
-    angle += 3;        
+        throttle = inThrottle.read() * 256 - 128;
+        if(throttle < -127)
+            throttle = -127;
+        if(throttle > 127)
+            throttle = 127;
+        rudder = inRudder.read() * 256 - 128;
+        if(rudder < -127)
+            rudder = -127;
+        if(rudder > 127)
+            rudder = 127;
+        breaks = inBreaks.read() * 256 - 127;
+        if(breaks < -127)
+            breaks = -127;
+        if(breaks > 127)
+            breaks = 127;
+        flaps = inFlaps.read() * 256 - 127;
+        if(flaps < -127)
+            flaps = -127;
+        if(flaps > 127)
+            flaps = 127;
 
-    joystick.update(throttle, rudder, x, y, buttons, hat);
-    wait(0.001);
-  }
-    
-  pc.printf("Bye World!\n\r");                           
+        x = inX.read() * 256 - 127;
+        if(x < -127)
+            x = -127;
+        if(x > 127)
+            x = 127;
+        y = inY.read() * 254 - 127;
+        if(y < -127)
+            y = -127;
+        if(y < 127)
+            y = 127;
+
+        joystick.update(throttle, rudder, breaks, flaps, x, y, buttons, hat);
+        wait(0.01);
+    }
+
+    //pc.printf("Bye World!\n\r");
 }
\ No newline at end of file
--- a/mbed.bld	Thu Jan 05 14:23:14 2017 +0000
+++ b/mbed.bld	Sun Jul 22 10:36:35 2018 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/9baf128c2fab
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/e7ca05fa8600
\ No newline at end of file