Initial

Dependencies:   mbed USBDevice USBJoystick_SIM

main.cpp

Committer:
Cirrus01
Date:
2020-03-25
Revision:
7:6e1b826a62b6
Parent:
6:d3042649530d

File content as of revision 7:6e1b826a62b6:

/* mbed USBJoystick Library Demo
 * 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
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, inclumosig without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUmosiG BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
 
#include "mbed.h"
#include "config.h"
#include "USBJoystick.h"
 
USBJoystick joystick;
 
// Variables for Heartbeat and Status monitoring
DigitalOut heartbeatLED(PA_5);  // 
 
AnalogIn inX(A0);               // X
AnalogIn inY(A1);               // Y
AnalogIn inRudder(A2);          // Rz (Rudder)
AnalogIn inThrottle(A3);        // Slider (Throttle)
AnalogIn inBreaks(A4);          // Z (Breaks)
AnalogIn inFlaps(A5);           // Rx (Flaps)
 
Ticker heartbeat;
Serial pc(USBTX, USBRX); // tx, rx

// Variables for Encoder
DigitalIn a(PC_13);
DigitalIn b(PD_2);

int8_t oldAB = 0; // Remember old encoder values A and B
int8_t stepTab[16] = {0,0,1,0,0,0,0,-1,0,0,0,1,0,0,-1,0}; // Lookup table for encoder steps 1/2
int32_t step = 0;
 
// 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 heartbeat_start()
{
    heartbeatLED = 1;
    heartbeat.attach(&pulse, 0.5);
}
 
void heartbeat_stop()
{
    heartbeat.detach();
}
 
// 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];


 
// 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();
}
 
int8_t readEncoder()
{
    oldAB <<= 2;
    oldAB &= 0x0C;
    oldAB |= (a.read() << 1) | b.read();
    return stepTab[oldAB];
}
 
// read the button input state
uint32_t readButtons()
{
    // start with all buttons off
    uint32_t buttons = 0;
    
    // start encoder result with 0
    int8_t encoder = 0;
    
    // figure the time elapsed since the last scan
    int dt = buttonTimer.read_ms();
    
    // reset the timef for the next scan
    buttonTimer.reset();
    
    // 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;
            //pc.printf("Buttons: %d\n", buttons);
            
        }
    }
    
    encoder = readEncoder();
    if (encoder == -1)
    {
        buttons |= 0x40000000;
    }
    else if (encoder == 1)
    {
        buttons |= 0x80000000;
    }
    
    // return the new button list
    return buttons;
}
 
// 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;
    }
    
    // start the hat timer
    hatTimer.start();
}
 
// 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 time 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++)
    {
        // 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);
        }
        bit <<= 1;
    }
    
    // translate values read to descriptor values
#if HAT4 && !HAT4_8
    if (hat == 0x01)                // 00000001
        hat = JOY_HAT_UP;           // 0
    else if (hat == 0x02)           // 00000010
        hat = JOY_HAT_RIGHT;        // 1
    else if (hat == 0x04)           // 00000100
        hat = JOY_HAT_DOWN;         // 2
    else if (hat == 0x08)           // 00001000
        hat = JOY_HAT_LEFT;         // 3
    else   
        hat = JOY_HAT_NEUTRAL;      // 4
#endif
#if HAT4 && HAT4_8
    if (hat == 0x01)                // 00000001
        hat = JOY_HAT_UP;           // 0
    else if (hat == 0x03)           // 00000011
        hat = JOY_HAT_UP_RIGHT;     // 1
    else if (hat == 0x02)           // 00000010
        hat = JOY_HAT_RIGHT;        // 2
    else if (hat == 0x06)           // 00000110
        hat = JOY_HAT_DOWN_RIGHT;   // 3
    else if (hat == 0x04)           // 00000100
        hat = JOY_HAT_DOWN;         // 4
    else if (hat == 0x0C)           // 00001100
        hat = JOY_HAT_DOWN_LEFT;    // 5
    else if (hat == 0x08)           // 00001000
        hat = JOY_HAT_LEFT;         // 6
    else if (hat == 0x09)           // 00001001
        hat = JOY_HAT_UP_LEFT;      // 7
    else
        hat = JOY_HAT_NEUTRAL;      // 8
#endif
#if HAT8
    if (hat == 0x01)                // 00000001
        hat = JOY_HAT_UP;           // 0
    else if (hat == 0x02)           // 00000010
        hat = JOY_HAT_UP_RIGHT;     // 1
    else if (hat == 0x04)           // 00000100
        hat = JOY_HAT_RIGHT;        // 2
    else if (hat == 0x08)           // 00001000
        hat = JOY_HAT_DOWN_RIGHT;   // 3
    else if (hat == 0x10)           // 00010000
        hat = JOY_HAT_DOWN;         // 4
    else if (hat == 0x20)           // 00100000
        hat = JOY_HAT_DOWN_LEFT;    // 5
    else if (hat == 0x40)           // 01000000
        hat = JOY_HAT_LEFT;         // 6
    else if (hat == 0x80)           // 10000000
        hat = JOY_HAT_UP_LEFT;      // 7
    else
        hat = JOY_HAT_NEUTRAL;      // 8
#endif
    
    // return the new button list
    //pc.printf("Return Hat: %d", hat);
    return hat;
}
 
int main()
{
    int16_t x = 0;
    int16_t y = 0;
    int16_t breaks = 0;
    int16_t flaps = 0;
    int16_t rudder = 0;
    int16_t throttle = 0;
    uint8_t hat = 0;
    uint32_t buttons = 0;
    
 
    const int16_t l = 32767;
    const uint16_t m = 65535;
 
    //pc.printf("Hello World from Joystick!\n\r");
 
    initButtons();
    initHat();
    
    heartbeat_start();
 
    //pc.printf("x, y, breaks, flaps, rudder, throttle, hat, buttons\n\n\r");
 
    while (1) {
 
        x = inX.read() * m - l;
        y = inY.read() * m - l;
        breaks = inBreaks.read() * m - l;
        flaps = inFlaps.read() * m - l;
        rudder = inRudder.read() * m - l;
        throttle = inThrottle.read() * m - l;
        hat = readHat();
        buttons = readButtons();
        
        //pc.printf("%d, %d, %d, %d, %d, %d, %d, %d\n\r", x, y, breaks, flaps, rudder, throttle, hat, buttons);
        //pc.printf("%d, %d\n\r", inX.read(), inY.read());
 
        joystick.update(x, y, breaks, flaps, rudder, throttle, hat, buttons);
        wait(0.01);
    }
 
    //pc.printf("Bye World!\n\r");
}