GamePortAdapter

Dependencies:   mbed-rtos mbed USBDevice USBJoystick

main.cpp

Committer:
obsoleet37
Date:
2017-12-21
Revision:
6:43b59cb5dcd9
Parent:
5:c2e3d6e70d85

File content as of revision 6:43b59cb5dcd9:

#include "mbed.h"
#include "USBMouseKeyboard.h"
#include "USBJoystick.h"
#include "rtos.h"
#include "string.h"

#define min(a, b) (a)<(b) ? (a) : (b)
#define max(a, b) (a)>(b) ? (a) : (b)
#define clamp(val, floor, ceil) min(max(val, floor), ceil)

extern "C" void mbed_reset();

Serial pc(USBTX, USBRX);
//macOS: screen /dev/tty.usbmodem{num} {baud rate}
//Windows: Realterm

class Axis {
    public:
        Axis(PinName pin) : _pin(pin) {
            _t.reset();
            _center = 0;
            _scale = 1.0;
            _pin.rise(this, &Axis::start);
            _pin.fall(this, &Axis::stop);
        }
        
        int8_t read() {
            int val = _t.read_us();
            return val < 1000 ? clamp((val - _center)*_scale, -128, 127) : -128;
        }
        
        int16_t read_raw() {
            return _t.read_us();
        }
        
        void setup(int center, int range) {
            _center = center;
            _scale = 255.0/range;
        }
        
        bool connected() {
            int val = _t.read_us();
            return val == clamp(val, 10, 1000);
        }
    
    private:
        InterruptIn _pin;
        Timer _t;
        int _center;
        float _scale;
        
        void start() {
            _t.reset();
            _t.start();
        }

        void stop() {
            _t.stop();
        }
        
};

Axis x1 = Axis(p15);
Axis y1 = Axis(p16);
Axis x2 = Axis(p17);
Axis y2 = Axis(p18);

volatile int buttons;

DigitalOut trig(p19);

//1st row: necessary garbage, size, mode, reserved, reserved
//2nd row: x1 center, x1 range, y1 center, y1 range, reserved
//3rd row: x2 center, x2 range, y2 center, y2 range, reserved
//following rows: input, min, max, output, value
int bindings[128][5];
/*int bindings[128][5] = {{0xFFFFFFFF, 9, 0, 0, 0},
                      {128, 255, 128, 255, 0},
                      {128, 255, 128, 255, 0},
                      {0, 0, 100, 4, (int)'a'},
                      {0, 400, 1000, 4, (int)'d'},
                      {1, 0, 100, 4, (int)'w'},
                      {1, 400, 1000, 4, (int)'s'},
                      {4, 128, 255, 4, (int)'1'},
                      {5, 128, 255, 4, (int)'2'}};*/
                      
/*int bindings[8][5] = {{0, 0, 1000, 0, 0},
                      {1, 0, 1000, 1, 0},
                      {4, 128, 255, 4, 0x1},
                      {5, 128, 255, 4, 0x2}};*/
                      
LocalFileSystem local("local");

void analog_trig() {
    trig = 0;
    trig = 1;
}


void debug_thread() {
    pc.printf("Beginning Joystick Test...\r\n");
    pc.printf("---------------------------------\r\n");
    
    while(1) {
        pc.printf("Joystick 1 - %d, %d, %X \r\n", x1.read_raw(), y1.read_raw(), buttons&0x3);
        pc.printf("Joystick 2 - %d, %d, %X \r\n", x2.read_raw(), y2.read_raw(), (buttons>>2)&0x3);
        pc.printf("\r\n");
        Thread::wait(500);
    }
}


void keys_mouse_output_thread() {
    USBMouseKeyboard keys_mouse;
    BusIn buttons_raw(p21, p22, p23, p24);
    buttons_raw.mode(PullUp);
    
    int mouse[4];
    int value, trigval;
    
    while(true) {
        memset(mouse, 0, sizeof(mouse));
        buttons = ~buttons_raw&0xF;
        
        for (int i=3; i<bindings[0][1]; i++) {
            //pc.printf("Checking %d: ", i);
            switch (bindings[i][0]) {
                case 0: trigval = x1.read(); break;
                case 1: trigval = y1.read(); break;
                case 2: trigval = x2.read(); break;
                case 3: trigval = y2.read(); break;
                case 4: trigval = (buttons & 0x1)*127; break;
                case 5: trigval = ((buttons>>1) & 0x1)*127; break;
                case 6: trigval = ((buttons>>2) & 0x1)*127; break;
                case 7: trigval = ((buttons>>3) & 0x1)*127; break;
            }
            value = bindings[i][4];
            
            if (trigval >= bindings[i][1] && trigval <= bindings[i][2]) {
                //pc.printf("Triggered : %d, %d, %d\r\n", i, trigval, value);
                switch (bindings[i][3]) {
                    case 0: mouse[0] = trigval/value; break; //Mouse X
                    case 1: mouse[1] = trigval/value; break; //Mouse Y
                    case 2: mouse[2] |= value; break; //Mouse buttons
                    case 3: mouse[3] = trigval/value; break; //Mouse scroll
                    case 4: keys_mouse.keyCode(value); break; //Keypress
                }  
            }
        }
        keys_mouse.update(mouse[0], mouse[1], mouse[2], mouse[3]);
        Thread::wait(15);
    }
}


void joystick_output_thread() {
    USBJoystick joystick;
    BusIn buttons_raw(p21, p22, p23, p24);
    buttons_raw.mode(PullUp);
    
    int joy[6];
    int value, trigval;
    
    while(true) {
        memset(joy, 0, sizeof(joy));
        buttons = ~buttons_raw&0xF;
        
        for (int i=3; i<bindings[0][1]; i++) {
            //pc.printf("Checking %d: ", i);
            switch (bindings[i][0]) {
                case 0: trigval = x1.read(); break;
                case 1: trigval = y1.read(); break;
                case 2: trigval = x2.read(); break;
                case 3: trigval = y2.read(); break;
                case 4: trigval = (buttons & 0x1)*127; break;
                case 5: trigval = ((buttons>>1) & 0x1)*127; break;
                case 6: trigval = ((buttons>>2) & 0x1)*127; break;
                case 7: trigval = ((buttons>>3) & 0x1)*127; break;
            }
            value = bindings[i][4];
            
            if (trigval >= bindings[i][1] && trigval <= bindings[i][2]) {
                //pc.printf("Triggered : %d, %d, %d\r\n", i, trigval, value);
                switch (bindings[i][3]) {
                    case 0: joy[2] = trigval/value; break;//Joy X
                    case 1: joy[3] = trigval/value; break; //Joy Y
                    case 2: joy[0] = trigval/value; break; //Joy throttle
                    case 3: joy[1] = trigval/value; break; //Joy rudder
                    case 4: joy[4] |= value; break; //Joy buttons
                    case 5: joy[5] |= value; break; //Joy hat
                }  
            }
        }
        joystick.update(joy[0], joy[1], joy[2], joy[3], joy[4], joy[5]);
        Thread::wait(15);
    }
}


int main() {
    
    //Load bindings from file
    FILE *bf = fopen("/local/bindings", "rb");
    fread(bindings, 5*sizeof(int), 1, bf);
    fread(bindings[1], 5*sizeof(int), bindings[0][1]-1, bf);
    fclose(bf);
    
    x1.setup(bindings[1][0], bindings[1][1]);
    y1.setup(bindings[1][2], bindings[1][3]);
    x2.setup(bindings[2][0], bindings[2][1]);
    y2.setup(bindings[2][2], bindings[2][3]);
    
    //Thread analogThread(analog_thread);
    Ticker analog_ticker;
    analog_ticker.attach(&analog_trig, 0.05);
    
    Thread outputThread;
    //Thread::wait(100);
    switch(bindings[0][2]) {
        case 0: outputThread.start(keys_mouse_output_thread); break;
        case 1: outputThread.start(joystick_output_thread); break;
    }
    
    Thread debugThread(debug_thread);
    
    while(1) Thread::yield();
}