MHeironimus / ArduinoJoystickLibrary

An Arduino library that adds one or more joysticks to the list of HID devices an Arduino Leonardo or Arduino Micro can support.
GNU Lesser General Public License v3.0
2.1k stars 409 forks source link

Device type is always "Driving" #158

Open MaciejNiklasinski opened 4 years ago

MaciejNiklasinski commented 4 years ago

Description of Issue

Not sure whether that's a bug report or a feature request. So regardless of what constant I will use when initializing the Joystick (JOYSTICK_TYPE_JOYSTICK/JOYSTICK_TYPE_GAMEPAD/JOYSTICK_TYPE_MULTI_AXIS) the created the device will always be of type "Driving". Almost all programs are still able to use it as normal joystick but FSUIPC beta 7, an addon to new Microsoft Flight Simulator which I intended to use to help me to map all the controls, unfortunately, doesn't (It does detect all my 'real' joysticks).

New Bitmap Image (8)

Is that a bug or the JOYSTICKTYPE* constants specifying something else and the intended HID type is "Driving"? If that's not a bug I would like to request a feature, please. I tried to look into the DynamicHID code, I know C# and JavaScript but my understanding of c++ is very slim (as you will see by looking into the attached sketch, I do realize that I follow possibly anti-pattern there but I just wanted something to work quickly and couldn't spend time on learning the language properly) so I can't see what would need to be changed if anything to change the HID type there.

Technical Details

Sketch File that Reproduces Issue


#include <SPI.h>
#include <Joystick.h>

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_MULTI_AXIS, 128, 0);

const byte LATCH = 0;

const uint8_t NUMBER_OF_SHIFT_REGISTERS = 14;                             // Number of daisy-chained shift registers
const uint8_t PINS_PER_CHIP = 8;                                          // Number pins provided by each shift register chip
const uint8_t NUMBER_OF_PINS = NUMBER_OF_SHIFT_REGISTERS * PINS_PER_CHIP; // Number of pins available in all daisy-chained shift registers

const uint8_t NUMBER_OF_ENCODERS = 1;

const uint8_t DEFAULT_PULSE_LENGTH = 3;
const uint8_t ENCODER_CHANGE_MODE_HOLD_LENGTH = 5;

const uint8_t CYCLES_MAX = 100;

static uint8_t cyclesCounter = 0;

enum PinState : uint8_t
{
    STAYED_OPEN,
    STAYED_CLOSE,
    OPENED,
    CLOSED
};

static PinState currentPinsStates[NUMBER_OF_PINS + 1];

static uint8_t pulsedPinsReleaseTimestamps[NUMBER_OF_PINS + 1];

byte shiftRegistersState[NUMBER_OF_SHIFT_REGISTERS];
byte shiftRegistersPreviousState[NUMBER_OF_SHIFT_REGISTERS];

enum InputType : uint8_t
{
    NORMAL_INPUT,                        // Press the button on pin closed, release the button on pin opened
    REVERSED_INPUT,                      // Press the button on pin opened, release the button on pin closed
    NORMAL_PULSE_INPUT,                  // Pulse the button on pin closed
    REVERSED_PULSE_INPUT,                // Pulse the button on pin opened
    NORMAL_AND_REVERSED_PULSE_INPUT,     // Pulse the button on pin opened and closed
    IGNORE_INPUT,                        // Ignore pin being open or closed
    CHANGE_ENCODER_MODE_ON_PRESS_HOLD,   // Change encoder mode when button is released for a ENCODER_CHANGE_MODE_HOLD_LENGTH number of cycles
    CHANGE_ENCODER_MODE_ON_RELEASE_HOLD, // Change encoder mode when button is pressed for a ENCODER_CHANGE_MODE_HOLD_LENGTH number of cycles
};

class InputMapping
{
public:
    InputType _inputType;
    uint8_t _buttonIndex;

    InputMapping()
    {
        _buttonIndex = 0;
        _inputType = 4;
    }

    InputMapping(uint8_t buttonNumber)
    {
        _buttonIndex = buttonNumber - 1;
        _inputType = 0;
    }

    InputMapping(uint8_t buttonNumber, InputType inputType)
    {
        _buttonIndex = buttonNumber - 1;
        _inputType = inputType;
    }
};

const InputMapping IGNORE_INPUT_MAPPING = {};
const InputMapping CHANGE_ENCODER_MODE_INPUT_MAPPING = {0, CHANGE_ENCODER_MODE_ON_RELEASE_HOLD};

// MAP NON_ENCODER INPUT HERE (Input allocated for pins occupied by encoders will be overriden)
// -------------------------- MAP START ------------------------------------------------------
static InputMapping inputMappings[NUMBER_OF_PINS + 1] = {
    IGNORE_INPUT_MAPPING,                 // pin 0 doesn't exist
    {1, NORMAL_AND_REVERSED_PULSE_INPUT}, // pin 1 -> button 1
    {2},                                  // pin 2 -> button 2
    {3},                                  // pin 3 -> button 3
    {4},                                  // pin 4 -> button 4
    {5},                                  // pin 5 -> button 5
    {6},                                  // pin 6 -> button 6
    {7},                                  // pin 7 -> button 7
    {8},                                  // pin 8 -> button 8
    {9},                                  // pin 9 -> button 9
    {10},                                 // pin 10 -> button 10
    {11},                                 // pin 11 -> button 11
    {12},                                 // pin 12 -> button 12
    {13},                                 // pin 13 -> button 13
    {14},                                 // pin 14 -> button 14
    {15},                                 // pin 15 -> button 15
    {16},                                 // pin 16 -> button 16
    {17},                                 // pin 17 -> button 17
    {18},                                 // pin 18 -> button 18
    {19},                                 // pin 19 -> button 19
    {20},                                 // pin 20 -> button 20
    {21},                                 // pin 21 -> button 21
    {22},                                 // pin 22 -> button 22
    {23},                                 // pin 23 -> button 23
    {24},                                 // pin 24 -> button 24
    {25},                                 // pin 25 -> button 25
    {26},                                 // pin 26 -> button 26
    {27},                                 // pin 27 -> button 27
    {28},                                 // pin 28 -> button 28
    {29},                                 // pin 29 -> button 29
    {30},                                 // pin 30 -> button 30
    {31},                                 // pin 31 -> button 31
    {32},                                 // pin 32 -> button 32
    {33},                                 // pin 33 -> button 33
    {34},                                 // pin 34 -> button 34
    {35},                                 // pin 35 -> button 35
    {36},                                 // pin 36 -> button 36
    {37},                                 // pin 37 -> button 37
    {38},                                 // pin 38 -> button 38
    {39},                                 // pin 39 -> button 39
    {40},                                 // pin 40 -> button 40
    {41},                                 // pin 41 -> button 41
    {42},                                 // pin 42 -> button 42
    {43},                                 // pin 43 -> button 43
    {44},                                 // pin 44 -> button 44
    {45},                                 // pin 45 -> button 45
    {46},                                 // pin 46 -> button 46
    {47},                                 // pin 47 -> button 47
    {48},                                 // pin 48 -> button 48
    {49},                                 // pin 49 -> button 49
    {50},                                 // pin 50 -> button 50
    {51},                                 // pin 51 -> button 51
    {52},                                 // pin 52 -> button 52
    {53},                                 // pin 53 -> button 53
    {54},                                 // pin 54 -> button 54
    {55},                                 // pin 55 -> button 55
    {56},                                 // pin 56 -> button 56
    {57},                                 // pin 57 -> button 57
    {58},                                 // pin 58 -> button 58
    {59},                                 // pin 59 -> button 59
    {60},                                 // pin 60 -> button 60
    {61},                                 // pin 61 -> button 61
    {62},                                 // pin 62 -> button 62
    {63},                                 // pin 63 -> button 63
    {64},                                 // pin 64 -> button 64
    {65},                                 // pin 65 -> button 65
    {66},                                 // pin 66 -> button 66
    {67},                                 // pin 67 -> button 67
    {68},                                 // pin 68 -> button 68
    {69},                                 // pin 69 -> button 69
    {70},                                 // pin 70 -> button 70
    {71},                                 // pin 71 -> button 71
    {72},                                 // pin 72 -> button 72
    {73},                                 // pin 73 -> button 73
    {74},                                 // pin 74 -> button 74
    {75},                                 // pin 75 -> button 75
    {76},                                 // pin 76 -> button 76
    {77},                                 // pin 77 -> button 77
    {78},                                 // pin 78 -> button 78
    {79},                                 // pin 79 -> button 79
    {80},                                 // pin 80 -> button 80
    {81},                                 // pin 81 -> button 81
    {82},                                 // pin 82 -> button 82
    {83},                                 // pin 83 -> button 83
    {84},                                 // pin 84 -> button 84
    {85},                                 // pin 85 -> button 85
    {86},                                 // pin 86 -> button 86
    {87},                                 // pin 87 -> button 87
    {88},                                 // pin 88 -> button 88
    {89},                                 // pin 89 -> button 89
    {90},                                 // pin 90 -> button 90
    {91},                                 // pin 91 -> button 91
    {92},                                 // pin 92 -> button 92
    {93},                                 // pin 93 -> button 93
    {94},                                 // pin 94 -> button 94
    {95},                                 // pin 95 -> button 95
    {96},                                 // pin 96 -> button 96
    {97},                                 // pin 97 -> button 97
    {98},                                 // pin 98 -> button 98
    {99},                                 // pin 99 -> button 99
    {100},                                // pin 100 -> button 100
    {101},                                // pin 101 -> button 101
    {102},                                // pin 102 -> button 102
    {103},                                // pin 103 -> button 103
    {104},                                // pin 104 -> button 104
    {105},                                // pin 105 -> button 105
    {106},                                // pin 106 -> button 106
    {107},                                // pin 107 -> button 107
    {108},                                // pin 108 -> button 108
    {109},                                // pin 109 -> button 109
    {110},                                // pin 110 -> button 110
    {111},                                // pin 111 -> button 111
    {112},                                // pin 112 -> button 112
    //{113},                                // pin 113 -> button 113
    //{114},                                // pin 114 -> button 114
    //{115},                                // pin 115 -> button 115
    //{116},                                // pin 116 -> button 116
    //{117},                                // pin 117 -> button 117
    //{118},                                // pin 118 -> button 118
    //{119},                                // pin 119 -> button 119
    //{120},                                // pin 120 -> button 120
    //{121},                                // pin 121 -> button 121
    //{122},                                // pin 122 -> button 122
    //{123},                                // pin 123 -> button 123
    //{124},                                // pin 124 -> button 124
    //{125},                                // pin 125 -> button 125
    //{126},                                // pin 126 -> button 126
    //{127},                                // pin 127 -> button 127
    //{128},                                // pin 128 -> button 128
};
// -------------------------- MAP ENDS  ------------------------------------------------------

class EncoderInputMapping
{
public:
    InputMapping _clkMapping;
    InputMapping _dataMapping;
    InputMapping _switchMapping;

    bool _placeholder = false;

    EncoderInputMapping()
    {
        _placeholder = true;
    }

    EncoderInputMapping(InputMapping clkMapping, InputMapping dataMapping, InputMapping switchMapping)
    {
        _clkMapping = clkMapping;
        _dataMapping = dataMapping;
        _switchMapping = switchMapping;
    }
};

const EncoderInputMapping MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING = {};

class Encoder
{
public:
    uint8_t _prevNextCode = 0;
    uint16_t _store = 0;
    uint8_t _currentMode = 0;
    uint8_t _clk;
    uint8_t _data;
    uint8_t _switch;
    EncoderInputMapping _encoderInputMapping0;
    EncoderInputMapping _encoderInputMapping1;
    EncoderInputMapping _encoderInputMapping2;
    EncoderInputMapping _encoderInputMapping3;

    Encoder(uint8_t clk, uint8_t data, uint8_t sw, EncoderInputMapping encoderInputMapping0)
    {
        _clk = clk;
        _data = data;
        _switch = sw;
        _encoderInputMapping0 = encoderInputMapping0;
        _encoderInputMapping1 = MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING;
        _encoderInputMapping2 = MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING;
        _encoderInputMapping3 = MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING;
    }

    Encoder(uint8_t clk, uint8_t data, uint8_t sw, EncoderInputMapping encoderInputMapping0, EncoderInputMapping encoderInputMapping1)
    {
        _clk = clk;
        _data = data;
        _switch = sw;
        _encoderInputMapping0 = encoderInputMapping0;
        _encoderInputMapping1 = encoderInputMapping1;
        _encoderInputMapping2 = MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING;
        _encoderInputMapping3 = MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING;
    }

    Encoder(uint8_t clk, uint8_t data, uint8_t sw, EncoderInputMapping encoderInputMapping0, EncoderInputMapping encoderInputMapping1, EncoderInputMapping encoderInputMapping2)
    {
        _clk = clk;
        _data = data;
        _switch = sw;
        _encoderInputMapping0 = encoderInputMapping0;
        _encoderInputMapping1 = encoderInputMapping1;
        _encoderInputMapping2 = encoderInputMapping2;
        _encoderInputMapping3 = MODE_PLACEHOLDER_ENCODER_INPUT_MAPPING;
    }

    Encoder(uint8_t clk, uint8_t data, uint8_t sw, EncoderInputMapping encoderInputMapping0, EncoderInputMapping encoderInputMapping1, EncoderInputMapping encoderInputMapping2, EncoderInputMapping encoderInputMapping3)
    {
        _clk = clk;
        _data = data;
        _switch = sw;
        _encoderInputMapping0 = encoderInputMapping0;
        _encoderInputMapping1 = encoderInputMapping1;
        _encoderInputMapping2 = encoderInputMapping2;
        _encoderInputMapping3 = encoderInputMapping3;
    }

    void releaseOngoingPulseInput()
    {
        if (pulsedPinsReleaseTimestamps[_clk] != 0)
        {
            pulsedPinsReleaseTimestamps[_clk] = 0;
            Joystick.setButton(inputMappings[_clk]._buttonIndex, 0);
        }

        if (pulsedPinsReleaseTimestamps[_data] != 0)
        {
            pulsedPinsReleaseTimestamps[_data] = 0;
            Joystick.setButton(inputMappings[_data]._buttonIndex, 0);
        }
    }
    void changeEncoderMode()
    {
        uint8_t increasedMode = _currentMode + 1;

        if (increasedMode == 5)
            _currentMode = 0;
        else if (increasedMode == 1 && !_encoderInputMapping1._placeholder)
            _currentMode = 1;
        else if (increasedMode == 2 && !_encoderInputMapping2._placeholder)
            _currentMode = 2;
        else if (increasedMode == 3 && !_encoderInputMapping3._placeholder)
            _currentMode = 3;
        else
            _currentMode = 0;
    }

    void allocateInputMappings()
    {

        EncoderInputMapping encoderInputMapping;
        if (_currentMode == 1)
            encoderInputMapping = _encoderInputMapping1;
        else if (_currentMode == 2)
            encoderInputMapping = _encoderInputMapping2;
        else if (_currentMode == 3)
            encoderInputMapping = _encoderInputMapping3;
        else
            encoderInputMapping = _encoderInputMapping0;

        inputMappings[_clk] = encoderInputMapping._clkMapping;
        inputMappings[_data] = encoderInputMapping._dataMapping;
        inputMappings[_switch] = encoderInputMapping._switchMapping;
    }

    void readRotary()
    {
        static int8_t c, val;
        static int8_t rotaryEncoderTable[] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};

        _prevNextCode <<= 2;
        if (currentPinsStates[_data] == CLOSED || currentPinsStates[_data] == STAYED_CLOSE)
            _prevNextCode |= 0x02;
        if (currentPinsStates[_clk] == CLOSED || currentPinsStates[_clk] == STAYED_CLOSE)
            _prevNextCode |= 0x01;
        _prevNextCode &= 0x0f;

        currentPinsStates[_data] = STAYED_OPEN;
        currentPinsStates[_clk] = STAYED_OPEN;

        // If valid then store as 16 bit data.
        if (rotaryEncoderTable[_prevNextCode])
        {
            _store <<= 4;
            _store |= _prevNextCode;
            if ((_store & 0xff) == 0x2b)
                val = -1;
            else if ((_store & 0xff) == 0x17)
                val = 1;
        }
        else
            val = 0;

        if (val)
        {
            c += val;
            if (_prevNextCode == 0x0b)
                currentPinsStates[_data] = CLOSED;

            if (_prevNextCode == 0x07)
                currentPinsStates[_clk] = CLOSED;
        }
    }
};

// MAP ENCODER INPUT HERE
// -------------------------- MAP START ------------------------------------------------------
static Encoder encoders[NUMBER_OF_ENCODERS] = {
    {97, 99, 98, {{1, NORMAL_PULSE_INPUT}, {2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{3, NORMAL_PULSE_INPUT}, {4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{1, 1 + 2, 1 + 1, {{1, NORMAL_PULSE_INPUT}, {2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{3, NORMAL_PULSE_INPUT}, {4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{4, 4 + 2, 4 + 1, {{1, NORMAL_PULSE_INPUT}, {2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{3, NORMAL_PULSE_INPUT}, {4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{7, 7 + 2, 7 + 1, {{1, NORMAL_PULSE_INPUT}, {2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{3, NORMAL_PULSE_INPUT}, {4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{10, 10 + 2, 10 + 1, {{10 + 1, NORMAL_PULSE_INPUT}, {10 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{10 + 3, NORMAL_PULSE_INPUT}, {10 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{13, 13 + 2, 13 + 1, {{13 + 1, NORMAL_PULSE_INPUT}, {13 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{13 + 3, NORMAL_PULSE_INPUT}, {13 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{16, 16 + 2, 16 + 1, {{16 + 1, NORMAL_PULSE_INPUT}, {16 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{16 + 3, NORMAL_PULSE_INPUT}, {16 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{19, 19 + 2, 19 + 1, {{19 + 1, NORMAL_PULSE_INPUT}, {19 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{19 + 3, NORMAL_PULSE_INPUT}, {19 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{22, 22 + 2, 22 + 1, {{22 + 1, NORMAL_PULSE_INPUT}, {22 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{22 + 3, NORMAL_PULSE_INPUT}, {22 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{25, 25 + 2, 25 + 1, {{25 + 1, NORMAL_PULSE_INPUT}, {25 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{25 + 3, NORMAL_PULSE_INPUT}, {25 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{28, 28 + 2, 28 + 1, {{28 + 1, NORMAL_PULSE_INPUT}, {28 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{28 + 3, NORMAL_PULSE_INPUT}, {28 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{31, 31 + 2, 31 + 1, {{31 + 1, NORMAL_PULSE_INPUT}, {31 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{31 + 3, NORMAL_PULSE_INPUT}, {31 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{34, 34 + 2, 34 + 1, {{34 + 1, NORMAL_PULSE_INPUT}, {34 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{34 + 3, NORMAL_PULSE_INPUT}, {34 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{37, 37 + 2, 37 + 1, {{37 + 1, NORMAL_PULSE_INPUT}, {37 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{37 + 3, NORMAL_PULSE_INPUT}, {37 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{40, 40 + 2, 40 + 1, {{40 + 1, NORMAL_PULSE_INPUT}, {40 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{40 + 3, NORMAL_PULSE_INPUT}, {40 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{43, 43 + 2, 43 + 1, {{43 + 1, NORMAL_PULSE_INPUT}, {43 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{43 + 3, NORMAL_PULSE_INPUT}, {43 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{46, 46 + 2, 46 + 1, {{46 + 1, NORMAL_PULSE_INPUT}, {46 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{46 + 3, NORMAL_PULSE_INPUT}, {46 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{49, 49 + 2, 49 + 1, {{49 + 1, NORMAL_PULSE_INPUT}, {49 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{49 + 3, NORMAL_PULSE_INPUT}, {49 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{52, 52 + 2, 52 + 1, {{52 + 1, NORMAL_PULSE_INPUT}, {52 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{52 + 3, NORMAL_PULSE_INPUT}, {52 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{55, 55 + 2, 55 + 1, {{55 + 1, NORMAL_PULSE_INPUT}, {55 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{55 + 3, NORMAL_PULSE_INPUT}, {55 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{58, 58 + 2, 58 + 1, {{58 + 1, NORMAL_PULSE_INPUT}, {58 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{58 + 3, NORMAL_PULSE_INPUT}, {58 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{61, 61 + 2, 61 + 1, {{61 + 1, NORMAL_PULSE_INPUT}, {61 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{61 + 3, NORMAL_PULSE_INPUT}, {61 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{64, 64 + 2, 64 + 1, {{64 + 1, NORMAL_PULSE_INPUT}, {64 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{64 + 3, NORMAL_PULSE_INPUT}, {64 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{67, 67 + 2, 67 + 1, {{67 + 1, NORMAL_PULSE_INPUT}, {67 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{67 + 3, NORMAL_PULSE_INPUT}, {67 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{70, 70 + 2, 70 + 1, {{70 + 1, NORMAL_PULSE_INPUT}, {70 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{70 + 3, NORMAL_PULSE_INPUT}, {70 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{73, 73 + 2, 73 + 1, {{73 + 1, NORMAL_PULSE_INPUT}, {73 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{73 + 3, NORMAL_PULSE_INPUT}, {73 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{76, 76 + 2, 76 + 1, {{76 + 1, NORMAL_PULSE_INPUT}, {76 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{76 + 3, NORMAL_PULSE_INPUT}, {76 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
    //{79, 79 + 2, 79 + 1, {{79 + 1, NORMAL_PULSE_INPUT}, {79 + 2, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}, {{79 + 3, NORMAL_PULSE_INPUT}, {79 + 4, NORMAL_PULSE_INPUT}, CHANGE_ENCODER_MODE_INPUT_MAPPING}},
};
// -------------------------- MAP ENDS  ------------------------------------------------------

void setup()
{
    SPI.begin();
    //Serial.begin(115200);
    //Serial.println ("Begin switch test.");
    pinMode(LATCH, OUTPUT);
    digitalWrite(LATCH, HIGH);
    Joystick.begin();

    for (int encoderIndex = 0; encoderIndex < NUMBER_OF_ENCODERS; encoderIndex++)
        encoders[encoderIndex].allocateInputMappings();
} // end of setup

void loop()
{
    readShitRegisters();
    readRotaryEncoders();
    handlePinsStates();

    if (cyclesCounter == CYCLES_MAX)
        cyclesCounter = 0;
    else
        cyclesCounter = cyclesCounter + 1;
}

void readShitRegisters()
{

    // Pulse the parallel load latch
    digitalWrite(LATCH, LOW);
    digitalWrite(LATCH, HIGH);

    for (uint8_t chipIndex = 0; chipIndex < NUMBER_OF_SHIFT_REGISTERS; chipIndex++)
    {
        shiftRegistersState[chipIndex] = SPI.transfer(0);
        byte mask = 1;
        for (uint8_t pinIndex = 1; pinIndex <= PINS_PER_CHIP; pinIndex++)
        {
            if ((shiftRegistersState[chipIndex] & mask) != (shiftRegistersPreviousState[chipIndex] & mask))
            {
                if (shiftRegistersState[chipIndex] & mask)
                    currentPinsStates[(chipIndex * PINS_PER_CHIP) + pinIndex] = CLOSED;
                else
                    currentPinsStates[(chipIndex * PINS_PER_CHIP) + pinIndex] = OPENED;
            } // end of bit has changed
            else
            {
                if (shiftRegistersState[chipIndex] & mask)
                    currentPinsStates[(chipIndex * PINS_PER_CHIP) + pinIndex] = STAYED_CLOSE;
                else
                    currentPinsStates[(chipIndex * PINS_PER_CHIP) + pinIndex] = STAYED_OPEN;
            }

            mask <<= 1;
        } // end of for each bit
        shiftRegistersPreviousState[chipIndex] = shiftRegistersState[chipIndex];
    }
}

void readRotaryEncoders()
{
    for (uint8_t index = 0; index < NUMBER_OF_ENCODERS; index++)
        encoders[index].readRotary();
}

void handlePinsStates()
{
    for (uint8_t pinIndex = 1; pinIndex <= NUMBER_OF_PINS; pinIndex++)
    {
        if (currentPinsStates[pinIndex] == CLOSED)
        {
            if (inputMappings[pinIndex]._inputType == NORMAL_INPUT)
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 1);
            else if (inputMappings[pinIndex]._inputType == REVERSED_INPUT)
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 0);
            else if (inputMappings[pinIndex]._inputType == NORMAL_PULSE_INPUT || inputMappings[pinIndex]._inputType == NORMAL_AND_REVERSED_PULSE_INPUT)
            {
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 1);
                pulsedPinsReleaseTimestamps[pinIndex] = DEFAULT_PULSE_LENGTH;
            }
            else if (inputMappings[pinIndex]._inputType == CHANGE_ENCODER_MODE_ON_PRESS_HOLD)
            {
                if (pulsedPinsReleaseTimestamps[pinIndex] == 0)
                    pulsedPinsReleaseTimestamps[pinIndex] = ENCODER_CHANGE_MODE_HOLD_LENGTH;
            }
            else if (inputMappings[pinIndex]._inputType == CHANGE_ENCODER_MODE_ON_RELEASE_HOLD)
            {
                if (pulsedPinsReleaseTimestamps[pinIndex] != 0)
                    pulsedPinsReleaseTimestamps[pinIndex] = 0;
            }
        }

        if (currentPinsStates[pinIndex] == OPENED)
        {
            if (inputMappings[pinIndex]._inputType == NORMAL_INPUT)
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 0);
            else if (inputMappings[pinIndex]._inputType == REVERSED_INPUT)
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 1);
            else if (inputMappings[pinIndex]._inputType == REVERSED_PULSE_INPUT || inputMappings[pinIndex]._inputType == NORMAL_AND_REVERSED_PULSE_INPUT)
            {
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 1);
                pulsedPinsReleaseTimestamps[pinIndex] = DEFAULT_PULSE_LENGTH;
            }
            else if (inputMappings[pinIndex]._inputType == CHANGE_ENCODER_MODE_ON_PRESS_HOLD)
            {
                if (pulsedPinsReleaseTimestamps[pinIndex] != 0)
                    pulsedPinsReleaseTimestamps[pinIndex] = 0;
            }
            else if (inputMappings[pinIndex]._inputType == CHANGE_ENCODER_MODE_ON_RELEASE_HOLD)
            {
                if (pulsedPinsReleaseTimestamps[pinIndex] == 0)
                    pulsedPinsReleaseTimestamps[pinIndex] = ENCODER_CHANGE_MODE_HOLD_LENGTH;
            }
        }

        if (cyclesCounter == CYCLES_MAX && pulsedPinsReleaseTimestamps[pinIndex] == 1)
        {
            if (inputMappings[pinIndex]._inputType == NORMAL_PULSE_INPUT || inputMappings[pinIndex]._inputType == REVERSED_PULSE_INPUT || inputMappings[pinIndex]._inputType == NORMAL_AND_REVERSED_PULSE_INPUT)
            {
                Joystick.setButton(inputMappings[pinIndex]._buttonIndex, 0);
            }
            else if (inputMappings[pinIndex]._inputType == CHANGE_ENCODER_MODE_ON_RELEASE_HOLD)
            {
                for (uint8_t encoderIndex = 0; encoderIndex < NUMBER_OF_ENCODERS; encoderIndex++)
                    if (encoders[encoderIndex]._switch == pinIndex)
                    {
                        encoders[encoderIndex].releaseOngoingPulseInput();
                        encoders[encoderIndex].changeEncoderMode();
                        encoders[encoderIndex].allocateInputMappings();
                    }
            }
        }

        if (cyclesCounter == CYCLES_MAX && pulsedPinsReleaseTimestamps[pinIndex] > 0)
            pulsedPinsReleaseTimestamps[pinIndex] = pulsedPinsReleaseTimestamps[pinIndex] - 1;
    }
}

Wiring Details

Any pin wiring details that may be relevant.

Additional context

Add any other context about the problem here.

MHeironimus commented 4 years ago

What program are you using that indicates the joystick's type is "Driving"?

MaciejNiklasinski commented 4 years ago

Ages ago I wrote in C# a vJoy feeder/remapper in which I used SharpDx.DirectInput package to detect all the connected HIDs. I have every reason to believe that it detects the device type correctly because it detects my Thrustmaster Warthog as "Joystick" and my Logitech G29 as "Driving".

sharpDx logic LogitechG29 Thrustmaster

MHeironimus commented 4 years ago

Thanks for the extra information. I'll have to investigate further to see if I can figure out what DirectInput is using to determine the joystick type.

Note to myself: Looks like it may be related to this: https://docs.microsoft.com/en-us/windows/win32/api/dinputd/ns-dinputd-dijoytypeinfo?redirectedfrom=MSDN