Ries Twisk / Mbed 2 deprecated JoyStick

Dependencies:   USBDevice mbed-rtos mbed

Fork of JoyStick by Ries Twisk

main.cpp

Committer:
rvt
Date:
2015-02-10
Revision:
3:0742b0b42ac9
Parent:
2:ae7a31a3c618
Child:
4:2cc58c173de8

File content as of revision 3:0742b0b42ac9:

#include "mbed.h"
#include "USBHID.h"
#include "USBJoystick.h"
#include "LowPassFilter.h"
#include "AnalogInFiltered.h"
#include "SimpleButtonDecoder.h"
#include "rtos.h"

// When set, it will send debug data over USB serial
#define TTY_DEBUG true

// Value that defines when to start sending data this prevents the noise sending loads's of data over HID
#define DATA_CHANGE_TRIGGER 64

// Activity LED for HID data
#define HIDACTIVITYLED LED3

// Number of samples taken before a buttons as set to be pressed. 
// It essentually wait's untel the value is stable enough to be said to be pressed
#define DEBOUNCERUNS 10


// Structure that hold's the dataset of the input's
Mutex analogValueMutex;
struct AnalogData {
    bool button1;
    bool button2;
    bool button3;
    bool button4;
    bool button5;
    long value1;
    long value2;
    long value3;
    long value4;
    long value5;
} analogData;




/**
Debug thread to show some values from the system over USB serial.
Ensure that TTY_DEBUG is defined so that these routines will get activated.
This is what I do to view the values on OSX within a terminal
$ cd /dev
$ ls | grep usbmodem
cu.usbmodemfa1232
tty.usbmodemfa1232
$ screen tty.usbmodemfa1232
*/
const char *byte_to_binary16(int x)
{
    static char b[17];
    b[0] = '\0';

    int z;
    for (z = 32768; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }

    return b;
}
const char *byte_to_binary8(int x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }

    return b;
}

void debug_thread(void const *args)
{
    // Serial port for debug data
    Serial pc(USBTX, USBRX); // tx, rx

    // Make a local copy
    AnalogData localCopy;
    AnalogData previous;
    while (true) {
        // Lock and copy input values
        analogValueMutex.lock();
        memcpy (&localCopy, &analogData, sizeof(AnalogData));
        analogValueMutex.unlock();

        // Send to USB
        pc.printf("\x1B[0;0H");
        pc.printf("Yoke and Pedals!\n\r");
        pc.printf("Analog in p20: %s %d          \n\r",byte_to_binary16((localCopy.value1 + 32768)),localCopy.value1 + 32768);
        pc.printf("Analog in p19: %d  diff: %d    \n\r",localCopy.value2,localCopy.value2-previous.value2);
        pc.printf("Analog in p18: %d  diff: %d    \n\r",localCopy.value3,localCopy.value3-previous.value3);
        pc.printf("Analog in p17: %d  diff: %d    \n\r",localCopy.value4,localCopy.value4-previous.value4);
        pc.printf("Analog in p16: %d  diff: %d    \n\r",localCopy.value5,localCopy.value5-previous.value5);
        pc.printf("Button 1: %d    \n\r",localCopy.button1);
        pc.printf("Button 2: %d    \n\r",localCopy.button2);
        pc.printf("Button 3: %d    \n\r",localCopy.button3);
        pc.printf("Button 4: %d    \n\r",localCopy.button4);
        pc.printf("Button 5: %d    \n\r",localCopy.button5);

        // Make local copy so we can show diff version
        memcpy (&previous, &localCopy, sizeof(AnalogData));
        Thread::wait(1000);
    }
}



void hid_thread(void const *args)
{
    //USB HID JoyStick
    USBJoystick joystick;

    // Activity led for HID data transmissions
    DigitalOut hIDActivity(HIDACTIVITYLED);
    
    // Locla copy of analog data
    AnalogData localCopy;

    uint8_t buttons=0;
    while (true) {


        // Wait for analog in to have some data
        hIDActivity=false;
        Thread::signal_wait(0x1);
        hIDActivity=true;

        // Make a local copy of the data
        analogValueMutex.lock();
        memcpy (&localCopy, &analogData, sizeof(AnalogData));
        analogValueMutex.unlock();

        buttons=0;
        if (localCopy.button1==true) {
            buttons=buttons | 0x01;
        }
        if (localCopy.button2) {
            buttons=buttons | 0x02;
        }
        if (localCopy.button3) {
            buttons=buttons | 0x04;
        }
        if (localCopy.button4) {
            buttons=buttons | 0x08;
        }
        if (localCopy.button5) {
            buttons=buttons | 0x10;
        }

        // Update joystick's info
        joystick.update(
            localCopy.value2,
            localCopy.value3,
            localCopy.value4,
            localCopy.value5,
            buttons);

        // Wait 50 ms to send a other USB update
        Thread::wait(50);
    }
}



int main()
{
    analogData.value1=0;
    analogData.value2=0;
    analogData.value3=0;
    analogData.value4=0;
    analogData.value5=0;

    if (TTY_DEBUG) {
        Thread _debugThread(debug_thread);
    }    
    Thread _hid_thread(hid_thread);

    // Initialise moving average filters
    LowPassFilter lowPassFilter1(new AnalogFilterInterface(),0.5f);   // The close the alpha value is to 1, the lower the cut-off frequency
    LowPassFilter lowPassFilter2(new AnalogFilterInterface(),0.95f);
    LowPassFilter lowPassFilter3(new AnalogFilterInterface(),0.95f);
    LowPassFilter lowPassFilter4(new AnalogFilterInterface(),0.95f);
    LowPassFilter lowPassFilter5(new AnalogFilterInterface(),0.95f);

    // Initialise analog input and tell it what fulters to use
    AnalogInFiltered ai1(&lowPassFilter1, p20, DATA_CHANGE_TRIGGER*4);
    AnalogInFiltered ai2(&lowPassFilter2, p19, DATA_CHANGE_TRIGGER);
    AnalogInFiltered ai3(&lowPassFilter3, p18, DATA_CHANGE_TRIGGER);
    AnalogInFiltered ai4(&lowPassFilter4, p17, DATA_CHANGE_TRIGGER);
    AnalogInFiltered ai5(&lowPassFilter5, p16, DATA_CHANGE_TRIGGER);
    
    SimpleButtonDecoder but1(&ai1, 49300, DEBOUNCERUNS);
    SimpleButtonDecoder but2(&ai1, 46800, DEBOUNCERUNS);
    SimpleButtonDecoder but3(&ai1, 43650, DEBOUNCERUNS);
    SimpleButtonDecoder but4(&ai1, 32500, DEBOUNCERUNS);
    SimpleButtonDecoder but5(&ai1, 39100, DEBOUNCERUNS);

    while (true) {
        // Measure analog in's
        ai1.measure();
        ai2.measure();
        ai3.measure();
        ai4.measure();
        ai5.measure();
        
        but1.process();
        but2.process();
        but3.process();
        but4.process();
        but5.process();

        // test of any of the values have been changed, so we only update when data was actually changed
        if (
                false
                || ai2.getIsChanged()
                || ai3.getIsChanged()
                || ai4.getIsChanged()
//                || ai5.getIsChanged()
                || but1.getIsChanged()
                || but2.getIsChanged()
                || but3.getIsChanged()
                || but4.getIsChanged()
                || but5.getIsChanged()
           ) {
            // Copy analog data to global data
            analogValueMutex.lock();
            analogData.button1 = but1.getIsPressed();
            analogData.button2 = but2.getIsPressed();
            analogData.button3 = but3.getIsPressed();
            analogData.button4 = but4.getIsPressed();
            analogData.button5 = but5.getIsPressed();
            analogData.value1 = ai1.getData();
            analogData.value2 = ai2.getData();
            analogData.value3 = ai3.getData();
            analogData.value4 = ai4.getData();
            analogData.value5 = ai5.getData();
            analogValueMutex.unlock();

            // Signal that data has been changed
            _hid_thread.signal_set(0x1);
        }
        Thread::wait(1);
    }
}