16 bit HID axis operation

  16-bit, adc, arduino, c++, hid

I am having trouble get my Arduino HID Axis controller to read correctly in windows. I am using an older version of this code (https://github.com/MHeironimus/ArduinoJoystickLibrary) which I’m modifying to get rid of everything except the axis’.

#include "Joystick.h"

#if defined(_USING_HID)

#define JOYSTICK_REPORT_ID 0x03
#define JOYSTICK_STATE_SIZE 9

static const uint8_t _hidReportDescriptor[] PROGMEM = {

    // Joystick
    0x05, 0x01,               // USAGE_PAGE (Generic Desktop)
    0x09, 0x04,               // USAGE (Joystick)
    0xa1, 0x01,               // COLLECTION (Application)
    0x85, JOYSTICK_REPORT_ID, //   REPORT_ID (3)

    // 16 bit Throttle and Steering
    0x05, 0x02,               //   USAGE_PAGE (Simulation Controls)
    0x15, 0x00,               //   LOGICAL_MINIMUM (0)
    0x27, 0xff, 0xff, 0x00, 0x00,         //   LOGICAL_MAXIMUM (65535)
    0xA1, 0x00,               //   COLLECTION (Physical)
    0x09, 0xBB,               //     USAGE (Throttle)
    0x09, 0xBA,               //     USAGE (Steering)
    0x75, 0x10,               //     REPORT_SIZE (16)
    0x95, 0x02,               //     REPORT_COUNT (2)
    0x81, 0x02,               //     INPUT (Data,Var,Abs)
    0xc0,                     //   END_COLLECTION

    // Two Hat switches (8 Positions)
    0x05, 0x01,               //   USAGE_PAGE (Generic Desktop)
    0x09, 0x39,               //   USAGE (Hat switch)
    0x15, 0x00,               //   LOGICAL_MINIMUM (0)
    0x25, 0x07,               //   LOGICAL_MAXIMUM (7)
    0x35, 0x00,               //   PHYSICAL_MINIMUM (0)
    0x46, 0x3B, 0x01,         //   PHYSICAL_MAXIMUM (315)
    0x65, 0x14,               //   UNIT (Eng Rot:Angular Pos)
    0x75, 0x04,               //   REPORT_SIZE (4)
    0x95, 0x01,               //   REPORT_COUNT (1)
    0x81, 0x02,               //   INPUT (Data,Var,Abs)

    0x09, 0x39,               //   USAGE (Hat switch)
    0x15, 0x00,               //   LOGICAL_MINIMUM (0)
    0x25, 0x07,               //   LOGICAL_MAXIMUM (7)
    0x35, 0x00,               //   PHYSICAL_MINIMUM (0)
    0x46, 0x3B, 0x01,         //   PHYSICAL_MAXIMUM (315)
    0x65, 0x14,               //   UNIT (Eng Rot:Angular Pos)
    0x75, 0x04,               //   REPORT_SIZE (4)
    0x95, 0x01,               //   REPORT_COUNT (1)
    0x81, 0x02,               //   INPUT (Data,Var,Abs)

    // rx, ry, Axis
    0x05, 0x01,               // Usage Page (Generic Desktop)
    0x09, 0x01,            // Usage (Pointer)
    0x15, 0x00,               //   LOGICAL_MINIMUM (0)
    0x27, 0xff, 0xff, 0x00, 0x00,         //   LOGICAL_MAXIMUM (65535)
    0x75, 0x10,               //   REPORT_SIZE (16)
    0xA1, 0x00,               //   COLLECTION (Physical)
    0x09, 0x33,               //     USAGE (rx)
    0x09, 0x34,               //     USAGE (ry)
    0x95, 0x02,               //     REPORT_COUNT (2)
    0x81, 0x02,               //     INPUT (Data,Var,Abs)
    0xc0,                     //   END_COLLECTION

    0xc0                      // END_COLLECTION
};

Joystick_::Joystick_()
{
    // Setup HID report structure
    static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
    HID().AppendDescriptor(&node);

    // Initalize State
    xAxis = 0;
    yAxis = 0;
    xAxisRotation = 0;
    yAxisRotation = 0;
    buttons = 0;
    throttle = 0;
    rudder = 0;
    hatSwitch[0] = -1;
    hatSwitch[1] = -1;
}

void Joystick_::begin(bool initAutoSendState)
{
    autoSendState = initAutoSendState;
    sendState();
}

void Joystick_::end()
{
}


void Joystick_::setThrottle(uint16_t value)
{
    throttle = value;
    if (autoSendState) sendState();
}
void Joystick_::setRudder(uint16_t value)
{
    rudder = value;
    if (autoSendState) sendState();
}

void Joystick_::setXAxisRotation(uint16_t value)
{
    xAxisRotation = value;
    if (autoSendState) sendState();
}
void Joystick_::setYAxisRotation(uint16_t value)
{
    yAxisRotation = value;
    if (autoSendState) sendState();
}
void Joystick_::setHatSwitch(int8_t hatSwitchIndex, int16_t value)
{
    hatSwitch[hatSwitchIndex % 2] = value;
    if (autoSendState) sendState();
}


void Joystick_::sendState()
{
    uint8_t data[JOYSTICK_STATE_SIZE];


  data[0] = throttle; //lsb
  data[1] = throttle >> 8; //msb
  data[2] = rudder;
  data[3] = rudder >> 8;

    // Calculate hat-switch values
    uint8_t convertedHatSwitch[2];
    for (int hatSwitchIndex = 0; hatSwitchIndex < 2; hatSwitchIndex++)
    {
        if (hatSwitch[hatSwitchIndex] < 0)
        {
            convertedHatSwitch[hatSwitchIndex] = 8;
        }
        else
        {
            convertedHatSwitch[hatSwitchIndex] = (hatSwitch[hatSwitchIndex] % 360) / 45;
        }
    }

    // Pack hat-switch states into a single byte
    data[4] = (convertedHatSwitch[1] << 4) | (B00001111 & convertedHatSwitch[0]);


    data[5] = xAxisRotation;
    data[6] = xAxisRotation >> 8;
    data[7] = yAxisRotation;
    data[8] = yAxisRotation >> 8;

    // HID().SendReport(Report number, array of values in same order as HID descriptor, length)
    HID().SendReport(JOYSTICK_REPORT_ID, data, JOYSTICK_STATE_SIZE);
}

Joystick_ Joystick;

#endif

This is my cpp file

My 16 bit throttle and rudder work perfectly but my rx and ry rotation do not. I also can’t get rid of my hat switches, all the AXIS stop working if i remove the hat switches and set the report size to 7.

I feel I’m not performing the bit shift or masking correctly, or I’m missing some commands to get it to put it together correctly.
Every time I try to remove buttons or axis from the .h file it completely break the controller and windows won’t detect it. But I’m fine with leaving it alone if I can get the cpp file to just the 4 AXIS at 16bit.

I am using a BEETLE LEONARDO USB ATMEGA32U4 DEVELOPMENT BOARD with a ADS1115 over I2C. That was fun get get set up, this is my first Arduino project so I’m super new to this.

Source: Windows Questions C++

LEAVE A COMMENT