Demo for USBJoystick updated for 32 buttons.

Dependencies:   USBDevice USBJoystick_SIM mbed USBJoystick_2

Dependents:   USBJoystick_2

Fork of USBJoystick_HelloWorld2 by Wim Huiskamp

Revision:
1:b106cf2e99ba
Parent:
0:e43878690c0e
Child:
2:967da2faedcd
--- 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