From 9839ec1dfe98931bf7626c9e011eb7fe51fe1f01 Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 19 Feb 2026 15:04:54 -0500 Subject: [PATCH] Add missing axis handling (3+3) and replace constructor bools with bitwise flags Added slider, dial, wheel on page 1, aileron, elevator, alt throttle on page 2. Note: although descriptors and reports appear to be correct, joy.cpl and DIView won't show all values if all enabled. Suspect limitations in Windows. --- src/Joystick.cpp | 165 ++++++++++++++++++++++++++++++----------------- src/Joystick.h | 92 ++++++++++++++++++++++---- 2 files changed, 184 insertions(+), 73 deletions(-) diff --git a/src/Joystick.cpp b/src/Joystick.cpp index c91841c..2daba65 100644 --- a/src/Joystick.cpp +++ b/src/Joystick.cpp @@ -28,35 +28,13 @@ #define JOYSTICK_SIMULATOR_MINIMUM 0 #define JOYSTICK_SIMULATOR_MAXIMUM 65535 -#define JOYSTICK_INCLUDE_X_AXIS B00000001 -#define JOYSTICK_INCLUDE_Y_AXIS B00000010 -#define JOYSTICK_INCLUDE_Z_AXIS B00000100 -#define JOYSTICK_INCLUDE_RX_AXIS B00001000 -#define JOYSTICK_INCLUDE_RY_AXIS B00010000 -#define JOYSTICK_INCLUDE_RZ_AXIS B00100000 - -#define JOYSTICK_INCLUDE_RUDDER B00000001 -#define JOYSTICK_INCLUDE_THROTTLE B00000010 -#define JOYSTICK_INCLUDE_ACCELERATOR B00000100 -#define JOYSTICK_INCLUDE_BRAKE B00001000 -#define JOYSTICK_INCLUDE_STEERING B00010000 - Joystick_::Joystick_( uint8_t hidReportId, uint8_t joystickType, uint8_t buttonCount, uint8_t hatSwitchCount, - bool includeXAxis, - bool includeYAxis, - bool includeZAxis, - bool includeRxAxis, - bool includeRyAxis, - bool includeRzAxis, - bool includeRudder, - bool includeThrottle, - bool includeAccelerator, - bool includeBrake, - bool includeSteering) + uint16_t includeAxis, + uint16_t includeSimulation) { // Set the USB HID Report ID _hidReportId = hidReportId; @@ -64,19 +42,8 @@ Joystick_::Joystick_( // Save Joystick Settings _buttonCount = buttonCount; _hatSwitchCount = hatSwitchCount; - _includeAxisFlags = 0; - _includeAxisFlags |= (includeXAxis ? JOYSTICK_INCLUDE_X_AXIS : 0); - _includeAxisFlags |= (includeYAxis ? JOYSTICK_INCLUDE_Y_AXIS : 0); - _includeAxisFlags |= (includeZAxis ? JOYSTICK_INCLUDE_Z_AXIS : 0); - _includeAxisFlags |= (includeRxAxis ? JOYSTICK_INCLUDE_RX_AXIS : 0); - _includeAxisFlags |= (includeRyAxis ? JOYSTICK_INCLUDE_RY_AXIS : 0); - _includeAxisFlags |= (includeRzAxis ? JOYSTICK_INCLUDE_RZ_AXIS : 0); - _includeSimulatorFlags = 0; - _includeSimulatorFlags |= (includeRudder ? JOYSTICK_INCLUDE_RUDDER : 0); - _includeSimulatorFlags |= (includeThrottle ? JOYSTICK_INCLUDE_THROTTLE : 0); - _includeSimulatorFlags |= (includeAccelerator ? JOYSTICK_INCLUDE_ACCELERATOR : 0); - _includeSimulatorFlags |= (includeBrake ? JOYSTICK_INCLUDE_BRAKE : 0); - _includeSimulatorFlags |= (includeSteering ? JOYSTICK_INCLUDE_STEERING : 0); + _includeAxisFlags = includeAxis; + _includeSimulatorFlags = includeSimulation; // Build Joystick HID Report Description @@ -89,18 +56,17 @@ Joystick_::Joystick_( } // Axis Calculations - uint8_t axisCount = (includeXAxis == true) - + (includeYAxis == true) - + (includeZAxis == true) - + (includeRxAxis == true) - + (includeRyAxis == true) - + (includeRzAxis == true); - - uint8_t simulationCount = (includeRudder == true) - + (includeThrottle == true) - + (includeAccelerator == true) - + (includeBrake == true) - + (includeSteering == true); + uint8_t axisCount = 0; + for (uint16_t ax = _includeAxisFlags; ax != 0; ax >>= 1) + { + axisCount += ax & 1; + } + + uint8_t simulationCount = 0; + for (uint16_t sim = _includeSimulatorFlags; sim != 0; sim >>= 1) + { + simulationCount += sim & 1; + } uint8_t tempHidReportDescriptor[150]; int hidReportDescriptorSize = 0; @@ -316,42 +282,60 @@ Joystick_::Joystick_( tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; - if (includeXAxis == true) { + if (_includeAxisFlags & JOYSTICK_INCLUDE_X_AXIS) { // USAGE (X) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x30; } - if (includeYAxis == true) { + if (_includeAxisFlags & JOYSTICK_INCLUDE_Y_AXIS) { // USAGE (Y) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x31; } - if (includeZAxis == true) { + if (_includeAxisFlags & JOYSTICK_INCLUDE_Z_AXIS) { // USAGE (Z) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x32; } - if (includeRxAxis == true) { + if (_includeAxisFlags & JOYSTICK_INCLUDE_RX_AXIS) { // USAGE (Rx) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x33; } - if (includeRyAxis == true) { + if (_includeAxisFlags & JOYSTICK_INCLUDE_RY_AXIS) { // USAGE (Ry) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x34; } - if (includeRzAxis == true) { + if (_includeAxisFlags & JOYSTICK_INCLUDE_RZ_AXIS) { // USAGE (Rz) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35; } + if (_includeAxisFlags & JOYSTICK_INCLUDE_SLIDER) { + // USAGE (Rx) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x36; + } + + if (_includeAxisFlags & JOYSTICK_INCLUDE_DIAL) { + // USAGE (Ry) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x37; + } + + if (_includeAxisFlags & JOYSTICK_INCLUDE_WHEEL) { + // USAGE (Rz) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x38; + } + // INPUT (Data,Var,Abs) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02; @@ -390,36 +374,54 @@ Joystick_::Joystick_( tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; - if (includeRudder == true) { + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_RUDDER) { // USAGE (Rudder) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0xBA; } - if (includeThrottle == true) { + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_THROTTLE) { // USAGE (Throttle) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0xBB; } - if (includeAccelerator == true) { + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_ACCELERATOR) { // USAGE (Accelerator) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC4; } - if (includeBrake == true) { + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_BRAKE) { // USAGE (Brake) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC5; } - if (includeSteering == true) { + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_STEERING) { // USAGE (Steering) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC8; } + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_AILERON) { + // USAGE (Aileron) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xB0; + } + + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_ELEVATOR) { + // USAGE (Elevator) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xB1; + } + + if (_includeSimulatorFlags & JOYSTICK_INCLUDE_THROTTLE_ALT) { + // USAGE (Alternate throttle) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xB5; + } + // INPUT (Data,Var,Abs) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81; tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02; @@ -462,11 +464,17 @@ Joystick_::Joystick_( _xAxisRotation = 0; _yAxisRotation = 0; _zAxisRotation = 0; + _slider = 0; + _dial = 0; + _wheel = 0; _throttle = 0; _rudder = 0; _accelerator = 0; _brake = 0; _steering = 0; + _aileron = 0; + _elevator = 0; + _throttleAlt = 0; for (int index = 0; index < JOYSTICK_HATSWITCH_COUNT_MAXIMUM; index++) { _hatSwitchValues[index] = JOYSTICK_HATSWITCH_RELEASE; @@ -551,6 +559,22 @@ void Joystick_::setRzAxis(int32_t value) if (_autoSendState) sendState(); } +void Joystick_::setSlider(int32_t value) +{ + _slider = value; + if (_autoSendState) sendState(); +} +void Joystick_::setDial(int32_t value) +{ + _dial = value; + if (_autoSendState) sendState(); +} +void Joystick_::setWheel(int32_t value) +{ + _wheel = value; + if (_autoSendState) sendState(); +} + void Joystick_::setRudder(int32_t value) { _rudder = value; @@ -576,6 +600,21 @@ void Joystick_::setSteering(int32_t value) _steering = value; if (_autoSendState) sendState(); } +void Joystick_::setAileron(int32_t value) +{ + _aileron = value; + if (_autoSendState) sendState(); +} +void Joystick_::setElevator(int32_t value) +{ + _elevator = value; + if (_autoSendState) sendState(); +} +void Joystick_::setAltThrottle(int32_t value) +{ + _throttleAlt = value; + if (_autoSendState) sendState(); +} void Joystick_::setHatSwitch(int8_t hatSwitchIndex, int16_t value) { @@ -668,6 +707,9 @@ void Joystick_::sendState() index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_RX_AXIS, _xAxisRotation, _rxAxisMinimum, _rxAxisMaximum, &(data[index])); index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_RY_AXIS, _yAxisRotation, _ryAxisMinimum, _ryAxisMaximum, &(data[index])); index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_RZ_AXIS, _zAxisRotation, _rzAxisMinimum, _rzAxisMaximum, &(data[index])); + index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_SLIDER, _slider, _sliderMinimum, _sliderMaximum, &(data[index])); + index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_DIAL, _dial, _dialMinimum, _dialMaximum, &(data[index])); + index += buildAndSetAxisValue(_includeAxisFlags & JOYSTICK_INCLUDE_WHEEL, _wheel, _wheelMinimum, _wheelMaximum, &(data[index])); // Set Simulation Values index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_RUDDER, _rudder, _rudderMinimum, _rudderMaximum, &(data[index])); @@ -675,6 +717,9 @@ void Joystick_::sendState() index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_ACCELERATOR, _accelerator, _acceleratorMinimum, _acceleratorMaximum, &(data[index])); index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_BRAKE, _brake, _brakeMinimum, _brakeMaximum, &(data[index])); index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_STEERING, _steering, _steeringMinimum, _steeringMaximum, &(data[index])); + index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_AILERON, _aileron, _aileronMinimum, _aileronMaximum, &(data[index])); + index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_ELEVATOR, _elevator, _elevatorMinimum, _elevatorMaximum, &(data[index])); + index += buildAndSetSimulationValue(_includeSimulatorFlags & JOYSTICK_INCLUDE_THROTTLE_ALT, _throttleAlt, _throttleAltMinimum, _throttleAltMaximum, &(data[index])); DynamicHID().SendReport(_hidReportId, data, _hidReportSize); } diff --git a/src/Joystick.h b/src/Joystick.h index de4900b..b4eaeda 100644 --- a/src/Joystick.h +++ b/src/Joystick.h @@ -55,6 +55,27 @@ #define JOYSTICK_TYPE_GAMEPAD 0x05 #define JOYSTICK_TYPE_MULTI_AXIS 0x08 +#define JOYSTICK_INCLUDE_X_AXIS 0b000000000001 +#define JOYSTICK_INCLUDE_Y_AXIS 0b000000000010 +#define JOYSTICK_INCLUDE_Z_AXIS 0b000000000100 +#define JOYSTICK_INCLUDE_RX_AXIS 0b000000001000 +#define JOYSTICK_INCLUDE_RY_AXIS 0b000000010000 +#define JOYSTICK_INCLUDE_RZ_AXIS 0b000000100000 +#define JOYSTICK_INCLUDE_SLIDER 0b000001000000 +#define JOYSTICK_INCLUDE_DIAL 0b000010000000 +#define JOYSTICK_INCLUDE_WHEEL 0b000100000000 + +#define JOYSTICK_INCLUDE_RUDDER 0b000000000001 +#define JOYSTICK_INCLUDE_THROTTLE 0b000000000010 +#define JOYSTICK_INCLUDE_ACCELERATOR 0b000000000100 +#define JOYSTICK_INCLUDE_BRAKE 0b000000001000 +#define JOYSTICK_INCLUDE_STEERING 0b000000010000 +#define JOYSTICK_INCLUDE_AILERON 0b000000100000 +#define JOYSTICK_INCLUDE_ELEVATOR 0b000001000000 +#define JOYSTICK_INCLUDE_THROTTLE_ALT 0b000010000000 + +#define JOYSTICK_INCLUDE_NONE 0 + class Joystick_ { private: @@ -66,11 +87,17 @@ class Joystick_ int32_t _xAxisRotation; int32_t _yAxisRotation; int32_t _zAxisRotation; + int32_t _slider; + int32_t _dial; + int32_t _wheel; int32_t _throttle; int32_t _rudder; int32_t _accelerator; int32_t _brake; int32_t _steering; + int32_t _aileron; + int32_t _elevator; + int32_t _throttleAlt; int16_t _hatSwitchValues[JOYSTICK_HATSWITCH_COUNT_MAXIMUM]; uint8_t *_buttonValues = NULL; @@ -79,8 +106,8 @@ class Joystick_ uint8_t _buttonCount; uint8_t _buttonValuesArraySize = 0; uint8_t _hatSwitchCount; - uint8_t _includeAxisFlags; - uint8_t _includeSimulatorFlags; + uint16_t _includeAxisFlags; + uint16_t _includeSimulatorFlags; int32_t _xAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM; int32_t _xAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM; int32_t _yAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM; @@ -93,6 +120,12 @@ class Joystick_ int32_t _ryAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM; int32_t _rzAxisMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM; int32_t _rzAxisMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM; + int32_t _sliderMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM; + int32_t _sliderMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM; + int32_t _dialMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM; + int32_t _dialMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM; + int32_t _wheelMinimum = JOYSTICK_DEFAULT_AXIS_MINIMUM; + int32_t _wheelMaximum = JOYSTICK_DEFAULT_AXIS_MAXIMUM; int32_t _rudderMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM; int32_t _rudderMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM; int32_t _throttleMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM; @@ -103,6 +136,12 @@ class Joystick_ int32_t _brakeMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM; int32_t _steeringMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM; int32_t _steeringMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM; + int32_t _aileronMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM; + int32_t _aileronMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM; + int32_t _elevatorMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM; + int32_t _elevatorMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM; + int32_t _throttleAltMinimum = JOYSTICK_DEFAULT_SIMULATOR_MINIMUM; + int32_t _throttleAltMaximum = JOYSTICK_DEFAULT_SIMULATOR_MAXIMUM; uint8_t _hidReportId; uint8_t _hidReportSize; @@ -118,17 +157,8 @@ class Joystick_ uint8_t joystickType = JOYSTICK_TYPE_JOYSTICK, uint8_t buttonCount = JOYSTICK_DEFAULT_BUTTON_COUNT, uint8_t hatSwitchCount = JOYSTICK_DEFAULT_HATSWITCH_COUNT, - bool includeXAxis = true, - bool includeYAxis = true, - bool includeZAxis = true, - bool includeRxAxis = true, - bool includeRyAxis = true, - bool includeRzAxis = true, - bool includeRudder = true, - bool includeThrottle = true, - bool includeAccelerator = true, - bool includeBrake = true, - bool includeSteering = true); + uint16_t includeAxis = 0x3ff, + uint16_t includeSimulation = 0xff); void begin(bool initAutoSendState = true); void end(); @@ -164,6 +194,21 @@ class Joystick_ _rzAxisMinimum = minimum; _rzAxisMaximum = maximum; } + inline void setSliderRange(int32_t minimum, int32_t maximum) + { + _sliderMinimum = minimum; + _sliderMaximum = maximum; + } + inline void setDialRange(int32_t minimum, int32_t maximum) + { + _dialMinimum = minimum; + _dialMaximum = maximum; + } + inline void setWheelRange(int32_t minimum, int32_t maximum) + { + _wheelMinimum = minimum; + _wheelMaximum = maximum; + } inline void setRudderRange(int32_t minimum, int32_t maximum) { _rudderMinimum = minimum; @@ -189,6 +234,21 @@ class Joystick_ _steeringMinimum = minimum; _steeringMaximum = maximum; } + inline void setAileronRange(int32_t minimum, int32_t maximum) + { + _aileronMinimum = minimum; + _aileronMaximum = maximum; + } + inline void setElevatorRange(int32_t minimum, int32_t maximum) + { + _elevatorMinimum = minimum; + _elevatorMaximum = maximum; + } + inline void setAltThrottleRange(int32_t minimum, int32_t maximum) + { + _throttleAltMinimum = minimum; + _throttleAltMaximum = maximum; + } // Set Axis Values void setXAxis(int32_t value); @@ -197,6 +257,9 @@ class Joystick_ void setRxAxis(int32_t value); void setRyAxis(int32_t value); void setRzAxis(int32_t value); + void setSlider(int32_t value); + void setDial(int32_t value); + void setWheel(int32_t value); // Set Simulation Values void setRudder(int32_t value); @@ -204,6 +267,9 @@ class Joystick_ void setAccelerator(int32_t value); void setBrake(int32_t value); void setSteering(int32_t value); + void setAileron(int32_t value); + void setElevator(int32_t value); + void setAltThrottle(int32_t value); void setButton(uint8_t button, uint8_t value); void pressButton(uint8_t button);