From 0065833f00e0738bb99d0ee5ed7b631643662b94 Mon Sep 17 00:00:00 2001 From: lemmingDev Date: Sat, 1 Feb 2025 21:51:44 +0900 Subject: [PATCH] Add gyroscope, accelerometer and fix left thumbstick in config --- BleGamepad.cpp | 279 +++++++++++++++++- BleGamepad.h | 13 +- BleGamepadConfiguration.cpp | 22 +- BleGamepadConfiguration.h | 20 +- .../MotionController/MotionController.ino | 145 +++++++++ keywords.txt | 275 ++++++++--------- library.properties | 2 +- 7 files changed, 599 insertions(+), 157 deletions(-) create mode 100644 examples/MotionController/MotionController.ino diff --git a/BleGamepad.cpp b/BleGamepad.cpp index e2b734e..8697d38 100644 --- a/BleGamepad.cpp +++ b/BleGamepad.cpp @@ -33,13 +33,16 @@ uint8_t tempHidReportDescriptor[150]; int hidReportDescriptorSize = 0; uint8_t reportSize = 0; uint8_t numOfButtonBytes = 0; -uint16_t vid; -uint16_t pid; -uint16_t guidVersion; -uint16_t axesMin; -uint16_t axesMax; -uint16_t simulationMin; -uint16_t simulationMax; +static uint16_t vid; +static uint16_t pid; +static uint16_t guidVersion; +static int16_t axesMin; +static int16_t axesMax; +static int16_t simulationMin; +static int16_t simulationMax; +static int16_t motionMin; +static int16_t motionMax; + std::string modelNumber; std::string softwareRevision; std::string serialNumber; @@ -68,6 +71,12 @@ BleGamepad::BleGamepad(std::string deviceName, std::string deviceManufacturer, u _hat2(0), _hat3(0), _hat4(0), + _gX(0), + _gY(0), + _gZ(0), + _aX(0), + _aY(0), + _aZ(0), hid(0) { this->resetButtons(); @@ -139,8 +148,19 @@ void BleGamepad::begin(BleGamepadConfiguration *config) { numOfSpecialButtonBytes++; } + + uint8_t numOfMotionBytes = 0; + if (configuration.getIncludeAccelerometer()) + { + numOfMotionBytes += 6; + } + + if (configuration.getIncludeGyroscope()) + { + numOfMotionBytes += 6; + } - reportSize = numOfButtonBytes + numOfSpecialButtonBytes + numOfAxisBytes + numOfSimulationBytes + configuration.getHatSwitchCount(); + reportSize = numOfButtonBytes + numOfSpecialButtonBytes + numOfAxisBytes + numOfSimulationBytes + numOfMotionBytes + configuration.getHatSwitchCount(); // USAGE_PAGE (Generic Desktop) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05; @@ -341,8 +361,8 @@ void BleGamepad::begin(BleGamepadConfiguration *config) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; // USAGE (Pointer) - tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; - tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; // LOGICAL_MINIMUM (-32767) tempHidReportDescriptor[hidReportDescriptorSize++] = 0x16; @@ -519,6 +539,123 @@ void BleGamepad::begin(BleGamepadConfiguration *config) tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0; } // Simulation Controls + + + // Gyroscope + if (configuration.getIncludeGyroscope()) + { + // COLLECTION (Physical) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; + + // USAGE_PAGE (Generic Desktop) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; + + // USAGE (Gyroscope - Rotational X - Rx) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x33; + + // USAGE (Rotational - Rotational Y - Ry) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x34; + + // USAGE (Rotational - Rotational Z - Rz) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35; + + // LOGICAL_MINIMUM (-32767) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x16; + tempHidReportDescriptor[hidReportDescriptorSize++] = lowByte(configuration.getMotionMin()); + tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getMotionMin()); + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; // Use these two lines for 0 min + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; // Use these two lines for -32767 min + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x80; + + // LOGICAL_MAXIMUM (+32767) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x26; + tempHidReportDescriptor[hidReportDescriptorSize++] = lowByte(configuration.getMotionMax()); + tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getMotionMax()); + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for 255 max + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for +32767 max + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x7F; + + // REPORT_SIZE (16) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x10; + + // REPORT_COUNT (3) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x03; + + // INPUT (Data,Var,Abs) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02; + + // END_COLLECTION (Physical) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0; + + } //Gyroscope + + // Accelerometer + if (configuration.getIncludeAccelerometer()) + { + // COLLECTION (Physical) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; + + // USAGE_PAGE (Generic Desktop) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; + + // USAGE (Accelerometer - Vector X - Vx) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x40; + + // USAGE (Accelerometer - Vector Y - Vy) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x41; + + // USAGE (Accelerometer - Vector Z - Vz) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x42; + + // LOGICAL_MINIMUM (-32767) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x16; + tempHidReportDescriptor[hidReportDescriptorSize++] = lowByte(configuration.getMotionMin()); + tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getMotionMin()); + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; // Use these two lines for 0 min + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; // Use these two lines for -32767 min + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x80; + + // LOGICAL_MAXIMUM (+32767) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x26; + tempHidReportDescriptor[hidReportDescriptorSize++] = lowByte(configuration.getMotionMax()); + tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getMotionMax()); + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for 255 max + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for +32767 max + //tempHidReportDescriptor[hidReportDescriptorSize++] = 0x7F; + + // REPORT_SIZE (16) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x10; + + // REPORT_COUNT (3) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x03; + + // INPUT (Data,Var,Abs) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81; + tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02; + + // END_COLLECTION (Physical) + tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0; + + } //Accelerometer if (configuration.getHatSwitchCount() > 0) { @@ -573,7 +710,8 @@ void BleGamepad::begin(BleGamepadConfiguration *config) // END_COLLECTION (Physical) tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0; - } + } // Hat Switches + if (configuration.getEnableOutputReport()) { @@ -837,6 +975,26 @@ void BleGamepad::sendReport(void) m[currentReportIndex++] = (_steering >> 8); } + if (configuration.getIncludeGyroscope()) + { + m[currentReportIndex++] = _gX; + m[currentReportIndex++] = (_gX >> 8); + m[currentReportIndex++] = _gY; + m[currentReportIndex++] = (_gY >> 8); + m[currentReportIndex++] = _gZ; + m[currentReportIndex++] = (_gZ >> 8); + } + + if (configuration.getIncludeAccelerometer()) + { + m[currentReportIndex++] = _aX; + m[currentReportIndex++] = (_aX >> 8); + m[currentReportIndex++] = _aY; + m[currentReportIndex++] = (_aY >> 8); + m[currentReportIndex++] = _aZ; + m[currentReportIndex++] = (_aZ >> 8); + } + if (configuration.getHatSwitchCount() > 0) { signed char hats[4]; @@ -851,9 +1009,17 @@ void BleGamepad::sendReport(void) m[currentReportIndex++] = hats[currentHatIndex]; } } - + this->inputGamepad->setValue(m, sizeof(m)); this->inputGamepad->notify(); + + // Testing + //Serial.println("HID Report"); + //for (int i = 0; i < sizeof(m); i++) + //{ + // Serial.printf("%02x", m[i]); + // Serial.println(); + //} } } @@ -1587,6 +1753,90 @@ void BleGamepad::setTXPowerLevel(int8_t level) NimBLEDevice::setPower(powerLevel); // The only valid values are: -12, -9, -6, -3, 0, 3, 6 and 9 } +void BleGamepad::setGyroscope(int16_t gX, int16_t gY, int16_t gZ) +{ + if (gX == -32768) + { + gX = -32767; + } + + if (gY == -32768) + { + gY = -32767; + } + + if (gY == -32768) + { + gY = -32767; + } + + _gX = gX; + _gY = gY; + _gZ = gZ; + + if (configuration.getAutoReport()) + { + sendReport(); + } +} + +void BleGamepad::setAccelerometer(int16_t aX, int16_t aY, int16_t aZ) +{ + _aX = aX; + _aY = aY; + _aZ = aZ; + + if (configuration.getAutoReport()) + { + sendReport(); + } +} + +void BleGamepad::setMotionControls(int16_t gX, int16_t gY, int16_t gZ, int16_t aX, int16_t aY, int16_t aZ) +{ + if (gX == -32768) + { + gX = -32767; + } + + if (gY == -32768) + { + gY = -32767; + } + + if (gZ == -32768) + { + gZ = -32767; + } + + if (aX == -32768) + { + aX = -32767; + } + + if (aY == -32768) + { + aY = -32767; + } + + if (aZ == -32768) + { + aZ = -32767; + } + + _gX = gX; + _gY = gY; + _gZ = gZ; + _aX = aX; + _aY = aY; + _aZ = aZ; + + if (configuration.getAutoReport()) + { + sendReport(); + } +} + void BleGamepad::taskServer(void *pvParameter) { @@ -1657,8 +1907,11 @@ void BleGamepad::taskServer(void *pvParameter) // Testing //for (int i = 0; i < hidReportDescriptorSize; i++) + //{ // Serial.printf("%02x", customHidReportDescriptor[i]); - + // Serial.println(); + //} + BleGamepadInstance->hid->setReportMap((uint8_t *)customHidReportDescriptor, hidReportDescriptorSize); BleGamepadInstance->hid->startServices(); diff --git a/BleGamepad.h b/BleGamepad.h index ba3b272..96c5518 100644 --- a/BleGamepad.h +++ b/BleGamepad.h @@ -34,6 +34,12 @@ class BleGamepad int16_t _hat2; int16_t _hat3; int16_t _hat4; + int16_t _gX; + int16_t _gY; + int16_t _gZ; + int16_t _aX; + int16_t _aY; + int16_t _aZ; //BleGamepadConfiguration configuration; @@ -109,8 +115,8 @@ class BleGamepad bool isConnected(void); void resetButtons(); void setBatteryLevel(uint8_t level); - void setTXPowerLevel(int8_t level = 9); - int8_t getTXPowerLevel(); + void setTXPowerLevel(int8_t level = 9); + int8_t getTXPowerLevel(); uint8_t batteryLevel; std::string deviceManufacturer; std::string deviceName; @@ -124,6 +130,9 @@ class BleGamepad NimBLEConnInfo getPeerInfo(); String getDeviceName(); String getDeviceManufacturer(); + void setGyroscope(int16_t gX = 0, int16_t gY = 0, int16_t gZ = 0); + void setAccelerometer(int16_t aX = 0, int16_t aY = 0, int16_t aZ = 0); + void setMotionControls(int16_t gX = 0, int16_t gY = 0, int16_t gZ = 0, int16_t aX = 0, int16_t aY = 0, int16_t aZ = 0); protected: diff --git a/BleGamepadConfiguration.cpp b/BleGamepadConfiguration.cpp index bddcc32..f3939cd 100644 --- a/BleGamepadConfiguration.cpp +++ b/BleGamepadConfiguration.cpp @@ -8,6 +8,8 @@ BleGamepadConfiguration::BleGamepadConfiguration() : _controllerType(CONTROLLER_ _whichSpecialButtons{false, false, false, false, false, false, false, false}, _whichAxes{true, true, true, true, true, true, true, true}, _whichSimulationControls{false, false, false, false, false}, + _includeGyroscope(false), + _includeAccelerometer(false), _vid(0xe502), _pid(0xbbab), _guidVersion(0x0110), @@ -15,14 +17,16 @@ BleGamepadConfiguration::BleGamepadConfiguration() : _controllerType(CONTROLLER_ _axesMax(0x7FFF), _simulationMin(0x0000), _simulationMax(0x7FFF), + _motionMin(0x0000), + _motionMax(0x7FFF), _modelNumber("1.0.0"), _softwareRevision("1.0.0"), _serialNumber("0123456789"), - _firmwareRevision("0.7.0"), + _firmwareRevision("0.7.1"), _hardwareRevision("1.0.0"), _enableOutputReport(false), _outputReportLength(64), - _powerLevel(9) + _powerLevel(9) { } @@ -88,6 +92,8 @@ int16_t BleGamepadConfiguration::getAxesMin(){ return _axesMin; } int16_t BleGamepadConfiguration::getAxesMax(){ return _axesMax; } int16_t BleGamepadConfiguration::getSimulationMin(){ return _simulationMin; } int16_t BleGamepadConfiguration::getSimulationMax(){ return _simulationMax; } +int16_t BleGamepadConfiguration::getMotionMin(){ return _motionMin; } +int16_t BleGamepadConfiguration::getMotionMax(){ return _motionMax; } uint8_t BleGamepadConfiguration::getControllerType() { return _controllerType; } uint8_t BleGamepadConfiguration::getHidReportId() { return _hidReportId; } uint16_t BleGamepadConfiguration::getButtonCount() { return _buttonCount; } @@ -117,6 +123,8 @@ bool BleGamepadConfiguration::getIncludeAccelerator() { return _whichSimulationC bool BleGamepadConfiguration::getIncludeBrake() { return _whichSimulationControls[BRAKE]; } bool BleGamepadConfiguration::getIncludeSteering() { return _whichSimulationControls[STEERING]; } const bool *BleGamepadConfiguration::getWhichSimulationControls() const { return _whichSimulationControls; } +bool BleGamepadConfiguration::getIncludeGyroscope() { return _includeGyroscope; } +bool BleGamepadConfiguration::getIncludeAccelerometer() { return _includeAccelerometer; } char *BleGamepadConfiguration::getModelNumber(){ return _modelNumber; } char *BleGamepadConfiguration::getSoftwareRevision(){ return _softwareRevision; } char *BleGamepadConfiguration::getSerialNumber(){ return _serialNumber; } @@ -138,14 +146,14 @@ void BleGamepadConfiguration::setWhichSpecialButtons(bool start, bool select, bo _whichSpecialButtons[VOLUME_MUTE_BUTTON] = volumeMute; } -void BleGamepadConfiguration::setWhichAxes(bool xAxis, bool yAxis, bool zAxis, bool rxAxis, bool ryAxis, bool rzAxis, bool slider1, bool slider2) +void BleGamepadConfiguration::setWhichAxes(bool xAxis, bool yAxis, bool zAxis, bool rzAxis, bool rxAxis, bool ryAxis, bool slider1, bool slider2) { _whichAxes[X_AXIS] = xAxis; _whichAxes[Y_AXIS] = yAxis; _whichAxes[Z_AXIS] = zAxis; + _whichAxes[RZ_AXIS] = rzAxis; _whichAxes[RX_AXIS] = rxAxis; _whichAxes[RY_AXIS] = ryAxis; - _whichAxes[RZ_AXIS] = rzAxis; _whichAxes[SLIDER1] = slider1; _whichAxes[SLIDER2] = slider2; } @@ -175,9 +183,9 @@ void BleGamepadConfiguration::setIncludeVolumeMute(bool value) { _whichSpecialBu void BleGamepadConfiguration::setIncludeXAxis(bool value) { _whichAxes[X_AXIS] = value; } void BleGamepadConfiguration::setIncludeYAxis(bool value) { _whichAxes[Y_AXIS] = value; } void BleGamepadConfiguration::setIncludeZAxis(bool value) { _whichAxes[Z_AXIS] = value; } +void BleGamepadConfiguration::setIncludeRzAxis(bool value) { _whichAxes[RZ_AXIS] = value; } void BleGamepadConfiguration::setIncludeRxAxis(bool value) { _whichAxes[RX_AXIS] = value; } void BleGamepadConfiguration::setIncludeRyAxis(bool value) { _whichAxes[RY_AXIS] = value; } -void BleGamepadConfiguration::setIncludeRzAxis(bool value) { _whichAxes[RZ_AXIS] = value; } void BleGamepadConfiguration::setIncludeSlider1(bool value) { _whichAxes[SLIDER1] = value; } void BleGamepadConfiguration::setIncludeSlider2(bool value) { _whichAxes[SLIDER2] = value; } void BleGamepadConfiguration::setIncludeRudder(bool value) { _whichSimulationControls[RUDDER] = value; } @@ -185,6 +193,8 @@ void BleGamepadConfiguration::setIncludeThrottle(bool value) { _whichSimulationC void BleGamepadConfiguration::setIncludeAccelerator(bool value) { _whichSimulationControls[ACCELERATOR] = value; } void BleGamepadConfiguration::setIncludeBrake(bool value) { _whichSimulationControls[BRAKE] = value; } void BleGamepadConfiguration::setIncludeSteering(bool value) { _whichSimulationControls[STEERING] = value; } +void BleGamepadConfiguration::setIncludeGyroscope(bool value) { _includeGyroscope = value; } +void BleGamepadConfiguration::setIncludeAccelerometer(bool value) { _includeAccelerometer = value; } void BleGamepadConfiguration::setVid(uint16_t value) { _vid = value; } void BleGamepadConfiguration::setPid(uint16_t value) { _pid = value; } void BleGamepadConfiguration::setGuidVersion(uint16_t value) { _guidVersion = value; } @@ -192,6 +202,8 @@ void BleGamepadConfiguration::setAxesMin(int16_t value) { _axesMin = value; } void BleGamepadConfiguration::setAxesMax(int16_t value) { _axesMax = value; } void BleGamepadConfiguration::setSimulationMin(int16_t value) { _simulationMin = value; } void BleGamepadConfiguration::setSimulationMax(int16_t value) { _simulationMax = value; } +void BleGamepadConfiguration::setMotionMin(int16_t value) { _motionMin = value; } +void BleGamepadConfiguration::setMotionMax(int16_t value) { _motionMax = value; } void BleGamepadConfiguration::setModelNumber(char *value) { _modelNumber = value; } void BleGamepadConfiguration::setSoftwareRevision(char *value) { _softwareRevision = value; } void BleGamepadConfiguration::setSerialNumber(char *value) { _serialNumber = value; } diff --git a/BleGamepadConfiguration.h b/BleGamepadConfiguration.h index bf97836..d8e86dd 100644 --- a/BleGamepadConfiguration.h +++ b/BleGamepadConfiguration.h @@ -217,6 +217,8 @@ class BleGamepadConfiguration int16_t _axesMax; int16_t _simulationMin; int16_t _simulationMax; + int16_t _motionMin; + int16_t _motionMax; char *_modelNumber; char *_softwareRevision; char *_serialNumber; @@ -224,7 +226,9 @@ class BleGamepadConfiguration char *_hardwareRevision; bool _enableOutputReport; uint16_t _outputReportLength; - int8_t _powerLevel; + int8_t _powerLevel; + bool _includeGyroscope; + bool _includeAccelerometer; public: BleGamepadConfiguration(); @@ -270,6 +274,8 @@ class BleGamepadConfiguration int16_t getAxesMax(); int16_t getSimulationMin(); int16_t getSimulationMax(); + int16_t getMotionMin(); + int16_t getMotionMax(); char *getModelNumber(); char *getSoftwareRevision(); char *getSerialNumber(); @@ -277,7 +283,9 @@ class BleGamepadConfiguration char *getHardwareRevision(); bool getEnableOutputReport(); uint16_t getOutputReportLength(); - int8_t getTXPowerLevel(); + int8_t getTXPowerLevel(); + bool getIncludeAccelerometer(); + bool getIncludeGyroscope(); void setControllerType(uint8_t controllerType); void setAutoReport(bool value); @@ -301,7 +309,7 @@ class BleGamepadConfiguration void setIncludeRzAxis(bool value); void setIncludeSlider1(bool value); void setIncludeSlider2(bool value); - void setWhichAxes(bool xAxis, bool yAxis, bool zAxis, bool rxAxis, bool ryAxis, bool rzAxis, bool slider1, bool slider2); + void setWhichAxes(bool xAxis, bool yAxis, bool zAxis, bool rzAxis, bool rxAxis, bool ryAxis, bool slider1, bool slider2); void setIncludeRudder(bool value); void setIncludeThrottle(bool value); void setIncludeAccelerator(bool value); @@ -315,6 +323,8 @@ class BleGamepadConfiguration void setAxesMax(int16_t value); void setSimulationMin(int16_t value); void setSimulationMax(int16_t value); + void setMotionMin(int16_t value); + void setMotionMax(int16_t value); void setModelNumber(char *value); void setSoftwareRevision(char *value); void setSerialNumber(char *value); @@ -322,7 +332,9 @@ class BleGamepadConfiguration void setHardwareRevision(char *value); void setEnableOutputReport(bool value); void setOutputReportLength(uint16_t value); - void setTXPowerLevel(int8_t value); + void setTXPowerLevel(int8_t value); + void setIncludeGyroscope(bool value); + void setIncludeAccelerometer(bool value); }; #endif diff --git a/examples/MotionController/MotionController.ino b/examples/MotionController/MotionController.ino new file mode 100644 index 0000000..973c2de --- /dev/null +++ b/examples/MotionController/MotionController.ino @@ -0,0 +1,145 @@ +/* + Motion controller test + + USB HID specification can only support 8 axes, plus hat (shows as 9th axis in online testers), + so Please don't add more than that + + So, if you have left thumbstick (X, Y -> 2 axes), then add gyroscope (Rx, Ry, Rz -> 3 axes) and + accelerometer (rX, rY, rZ -> 3 axes), then you're already at 8 + + Windows joy.cpl will show the gyroscope data as X Rotation, Y Rotation and Z Rotation + Windows joy.cpl will not show the accelerometer data, but you can see it using online + tools such as https://hardwaretester.com/gamepad + + This HID descriptor uses the correct HID usage IDs for gyroscope (33, 34, 35 -> Rotation -> Rx, Ry, Rz) and + accelerometer (40, 41, 42 -> Vector -> Vx, Vy, Vz) + https://www.usb.org/sites/default/files/hut1_6.pdf + + Unfortunately, Windows and other OSs don't usually know exactly what their intent is and may not + map them exactly how you think + + Controllers such as PS3/4 Dual Shock use custom HID reports and drivers to get around this + +*/ + +#include +#include + +#define numOfButtons 10 +#define numOfHatSwitches 0 +#define enableX false +#define enableY false +#define enableZ false +#define enableRX false +#define enableRY false +#define enableRZ false +#define enableSlider1 false +#define enableSlider2 false + +int16_t motionMin = 0x8000; // -32767 --> Some non-Windows operating systems and web based gamepad testers don't like min axis set below 0, so 0 is set by default +int16_t motionCenter = 0x00; +//int16_t motionMin = 0x00; // Set motionulation minimum axes to zero. +//int16_t motionCenter = 0x3FFF; +int16_t motionMax = 0x7FFF; // 32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal +int16_t stepAmount = 0xFF; // 255 +uint16_t delayAmount = 25; + +BleGamepad bleGamepad("BLE Motion Controller", "lemmingDev", 100); + +void setup() +{ + Serial.begin(115200); + Serial.println("Starting BLE work!"); + + // Setup controller with 10 buttons, gyroscope and accelerometer + BleGamepadConfiguration bleGamepadConfig; + bleGamepadConfig.setAutoReport(false); + bleGamepadConfig.setControllerType(CONTROLLER_TYPE_GAMEPAD); // CONTROLLER_TYPE_JOYSTICK, CONTROLLER_TYPE_GAMEPAD (DEFAULT), CONTROLLER_TYPE_MULTI_AXIS + bleGamepadConfig.setButtonCount(numOfButtons); + bleGamepadConfig.setWhichAxes(enableX, enableY, enableZ, enableRX, enableRY, enableRZ, enableSlider1, enableSlider2); // Can also be done per-axis individually. All are true by default + bleGamepadConfig.setHatSwitchCount(numOfHatSwitches); // 1 by default + bleGamepadConfig.setIncludeGyroscope(true); + bleGamepadConfig.setIncludeAccelerometer(true); + bleGamepadConfig.setMotionMin(motionMin); + bleGamepadConfig.setMotionMax(motionMax); + + bleGamepad.begin(&bleGamepadConfig); + // Changing bleGamepadConfig after the begin function has no effect, unless you call the begin function again + + // Set gyroscope and accelerometer to center (first 3 are gyroscope, last 3 are accelerometer) + bleGamepad.setMotionControls(motionCenter, motionCenter, motionCenter, motionCenter, motionCenter, motionCenter); + + bleGamepad.sendReport(); +} + +void loop() +{ + if (bleGamepad.isConnected()) + { + // BUTTONS + Serial.println("Press all buttons one by one"); + for (int i = 1; i <= numOfButtons; i += 1) + { + bleGamepad.press(i); + bleGamepad.sendReport(); + delay(100); + bleGamepad.release(i); + bleGamepad.sendReport(); + delay(25); + } + + // GYROSCOPE + Serial.println("Move all 3 gyroscope axes from center to min"); + for (int i = motionCenter; i > motionMin; i -= stepAmount) + { + bleGamepad.setGyroscope(i, i, i); + bleGamepad.sendReport(); + delay(delayAmount); + } + + Serial.println("Move all 3 gyroscope axes from min to max"); + for (int i = motionMin; i < motionMax; i += stepAmount) + { + bleGamepad.setGyroscope(i, i, i); + bleGamepad.sendReport(); + delay(delayAmount); + } + + Serial.println("Move all 3 gyroscope axes from max to center"); + for (int i = motionMax; i > motionCenter; i -= stepAmount) + { + bleGamepad.setGyroscope(i, i, i); + bleGamepad.sendReport(); + delay(delayAmount); + } + bleGamepad.setGyroscope(motionCenter); + bleGamepad.sendReport(); + + // ACCELEROMETER + Serial.println("Move all 3 accelerometer axes from center to min"); + for (int i = motionCenter; i > motionMin; i -= stepAmount) + { + bleGamepad.setAccelerometer(i, i, i); + bleGamepad.sendReport(); + delay(delayAmount); + } + + Serial.println("Move all 3 accelerometer axes from min to max"); + for (int i = motionMin; i < motionMax; i += stepAmount) + { + bleGamepad.setAccelerometer(i, i, i); + bleGamepad.sendReport(); + delay(delayAmount); + } + + Serial.println("Move all 3 accelerometer axes from max to center"); + for (int i = motionMax; i > motionCenter; i -= stepAmount) + { + bleGamepad.setAccelerometer(i, i, i); + bleGamepad.sendReport(); + delay(delayAmount); + } + bleGamepad.setAccelerometer(motionCenter); + bleGamepad.sendReport(); + } +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index 2ba7544..1acd436 100644 --- a/keywords.txt +++ b/keywords.txt @@ -18,148 +18,159 @@ press KEYWORD2 release KEYWORD2 isPressed KEYWORD2 isConnected KEYWORD2 -setLeftThumb KEYWORD2 +setLeftThumb KEYWORD2 setRightThumb KEYWORD2 -setLeftTrigger KEYWORD2 -setRightTrigger KEYWORD2 -setHat KEYWORD2 +setLeftTrigger KEYWORD2 +setRightTrigger KEYWORD2 +setHat KEYWORD2 setHat1 KEYWORD2 setHat2 KEYWORD2 setHat3 KEYWORD2 setHat4 KEYWORD2 setHats KEYWORD2 -setX KEYWORD2 -setY KEYWORD2 -setZ KEYWORD2 -setRZ KEYWORD2 -setRX KEYWORD2 -setRY KEYWORD2 -setSlider1 KEYWORD2 -setSlider2 KEYWORD2 -setSlider KEYWORD2 -setSliders KEYWORD2 +setX KEYWORD2 +setY KEYWORD2 +setZ KEYWORD2 +setRZ KEYWORD2 +setRX KEYWORD2 +setRY KEYWORD2 +setSlider1 KEYWORD2 +setSlider2 KEYWORD2 +setSlider KEYWORD2 +setSliders KEYWORD2 setRudder KEYWORD2 setThrottle KEYWORD2 -setAccelerator KEYWORD2 -setBrake KEYWORD2 -setSteering KEYWORD2 +setAccelerator KEYWORD2 +setBrake KEYWORD2 +setSteering KEYWORD2 setSimulationControls KEYWORD2 setControllerType KEYWORD2 -setAutoReport KEYWORD2 -setHidReportId KEYWORD2 -sendReport KEYWORD2 -setButtonCount KEYWORD2 -setHatSwitchCount KEYWORD2 -setIncludeStart KEYWORD2 -setIncludeSelect KEYWORD2 -setIncludeMenu KEYWORD2 -setIncludeHome KEYWORD2 -setIncludeBack KEYWORD2 -setIncludeVolumeInc KEYWORD2 -setIncludeVolumeDec KEYWORD2 -setIncludeVolumeMute KEYWORD2 -setWhichSpecialButtons KEYWORD2 -setIncludeXAxis KEYWORD2 -setIncludeYAxis KEYWORD2 -setIncludeZAxis KEYWORD2 -setIncludeRxAxis KEYWORD2 -setIncludeRyAxis KEYWORD2 -setIncludeRzAxis KEYWORD2 -setIncludeSlider1 KEYWORD2 -setIncludeSlider2 KEYWORD2 -setWhichAxes KEYWORD2 -setIncludeRudder KEYWORD2 -setIncludeThrottle KEYWORD2 -setIncludeAccelerator KEYWORD2 -setIncludeBrake KEYWORD2 -setIncludeSteering KEYWORD2 -setWhichSimulationControls KEYWORD2 -resetButtons KEYWORD2 -setBatteryLevel KEYWORD2 -pressSpecialButton KEYWORD2 -releaseSpecialButton KEYWORD2 -pressStart KEYWORD2 -releaseStart KEYWORD2 -pressSelect KEYWORD2 -releaseSelect KEYWORD2 -pressMenu KEYWORD2 -releaseMenu KEYWORD2 -pressHome KEYWORD2 -releaseHome KEYWORD2 -pressBack KEYWORD2 -releaseBack KEYWORD2 -pressVolumeInc KEYWORD2 -releaseVolumeInc KEYWORD2 -pressVolumeDec KEYWORD2 -releaseVolumeDec KEYWORD2 -pressVolumeMute KEYWORD2 -releaseVolumeMute KEYWORD2 -getControllerType KEYWORD2 -getHidReportId KEYWORD2 -getButtonCount KEYWORD2 -getTotalSpecialButtonCount KEYWORD2 -getDesktopSpecialButtonCount KEYWORD2 -getConsumerSpecialButtonCount KEYWORD2 -getHatSwitchCount KEYWORD2 -getAxisCount KEYWORD2 -getSimulationCount KEYWORD2 -getAutoReport KEYWORD2 -getIncludeStart KEYWORD2 -getIncludeSelect KEYWORD2 -getIncludeMenu KEYWORD2 -getIncludeHome KEYWORD2 -getIncludeBack KEYWORD2 -getIncludeVolumeInc KEYWORD2 -getIncludeVolumeDec KEYWORD2 -getIncludeVolumeMute KEYWORD2 -getWhichSpecialButtons KEYWORD2 -getIncludeXAxis KEYWORD2 -getIncludeYAxis KEYWORD2 -getIncludeZAxis KEYWORD2 -getIncludeRxAxis KEYWORD2 -getIncludeRyAxis KEYWORD2 -getIncludeRzAxis KEYWORD2 -getIncludeSlider1 KEYWORD2 -getIncludeSlider2 KEYWORD2 -getWhichAxes KEYWORD2 -getIncludeRudder KEYWORD2 -getIncludeThrottle KEYWORD2 -getIncludeAccelerator KEYWORD2 -getIncludeBrake KEYWORD2 -getIncludeSteering KEYWORD2 -getWhichSimulationControls KEYWORD2 -getVid KEYWORD2 -getPid KEYWORD2 -getGuidVersion KEYWORD2 -getAxesMin KEYWORD2 -getAxesMax KEYWORD2 -getSimulationMin KEYWORD2 -getSimulationMax KEYWORD2 -getModelNumber KEYWORD2 -getSoftwareRevision KEYWORD2 -getSerialNumber KEYWORD2 -getFirmwareRevision KEYWORD2 -getHardwareRevision KEYWORD2 -setVid KEYWORD2 -setPid KEYWORD2 -setGuidVersion KEYWORD2 -setAxesMin KEYWORD2 -setAxesMax KEYWORD2 -setSimulationMin KEYWORD2 -setSimulationMax KEYWORD2 -setModelNumber KEYWORD2 -setSoftwareRevision KEYWORD2 -setSerialNumber KEYWORD2 -setFirmwareRevision KEYWORD2 -setHardwareRevision KEYWORD2 -deleteBond KEYWORD2 -deleteAllBonds KEYWORD2 -enterPairingMode KEYWORD2 -getPeerInfo KEYWORD2 -getDeviceName KEYWORD2 -getDeviceManufacturer KEYWORD2 -getTXPowerLevel KEYWORD2 -setTXPowerLevel KEYWORD2 +setAutoReport KEYWORD2 +setHidReportId KEYWORD2 +sendReport KEYWORD2 +setButtonCount KEYWORD2 +setHatSwitchCount KEYWORD2 +setIncludeStart KEYWORD2 +setIncludeSelect KEYWORD2 +setIncludeMenu KEYWORD2 +setIncludeHome KEYWORD2 +setIncludeBack KEYWORD2 +setIncludeVolumeInc EYWORD2 +setIncludeVolumeDec KEYWORD2 +setIncludeVolumeMute KEYWORD2 +setWhichSpecialButtons KEYWORD2 +setIncludeXAxis KEYWORD2 +setIncludeYAxis KEYWORD2 +setIncludeZAxis KEYWORD2 +setIncludeRxAxis KEYWORD2 +setIncludeRyAxis KEYWORD2 +setIncludeRzAxis KEYWORD2 +setIncludeSlider1 KEYWORD2 +setIncludeSlider2 KEYWORD2 +setWhichAxes KEYWORD2 +setIncludeRudder KEYWORD2 +setIncludeThrottle KEYWORD2 +setIncludeAccelerator KEYWORD2 +setIncludeBrake KEYWORD2 +setIncludeSteering KEYWORD2 +setIncludeGyroscope KEYWORD2 +setIncludeAccelerometer KEYWORD2 +setWhichSimulationControls KEYWORD2 +resetButtons KEYWORD2 +setBatteryLevel KEYWORD2 +pressSpecialButton KEYWORD2 +releaseSpecialButton KEYWORD2 +pressStart KEYWORD2 +releaseStart KEYWORD2 +pressSelect KEYWORD2 +releaseSelect KEYWORD2 +pressMenu KEYWORD2 +releaseMenu KEYWORD2 +pressHome KEYWORD2 +releaseHome KEYWORD2 +pressBack KEYWORD2 +releaseBack KEYWORD2 +pressVolumeInc KEYWORD2 +releaseVolumeInc KEYWORD2 +pressVolumeDec KEYWORD2 +releaseVolumeDec KEYWORD2 +pressVolumeMute KEYWORD2 +releaseVolumeMute KEYWORD2 +getControllerType KEYWORD2 +getHidReportId KEYWORD2 +getButtonCount KEYWORD2 +getTotalSpecialButtonCount KEYWORD2 +getDesktopSpecialButtonCount KEYWORD2 +getConsumerSpecialButtonCount KEYWORD2 +getHatSwitchCount KEYWORD2 +getAxisCount KEYWORD2 +getSimulationCount KEYWORD2 +getAutoReport KEYWORD2 +getIncludeStart KEYWORD2 +getIncludeSelect KEYWORD2 +getIncludeMenu KEYWORD2 +getIncludeHome KEYWORD2 +getIncludeBack KEYWORD2 +getIncludeVolumeInc KEYWORD2 +getIncludeVolumeDec KEYWORD2 +getIncludeVolumeMute KEYWORD2 +getWhichSpecialButtons KEYWORD2 +getIncludeXAxis KEYWORD2 +getIncludeYAxis KEYWORD2 +getIncludeZAxis KEYWORD2 +getIncludeRxAxis KEYWORD2 +getIncludeRyAxis KEYWORD2 +getIncludeRzAxis KEYWORD2 +getIncludeSlider1 KEYWORD2 +getIncludeSlider2 KEYWORD2 +getWhichAxes KEYWORD2 +getIncludeRudder KEYWORD2 +getIncludeThrottle KEYWORD2 +getIncludeAccelerator KEYWORD2 +getIncludeBrake KEYWORD2 +getIncludeSteering KEYWORD2 +getIncludeAccelerometer KEYWORD2 +getIncludeGyroscope KEYWORD2 +getWhichSimulationControls KEYWORD2 +getVid KEYWORD2 +getPid KEYWORD2 +getGuidVersion KEYWORD2 +getAxesMin KEYWORD2 +getAxesMax KEYWORD2 +getSimulationMin KEYWORD2 +getSimulationMax KEYWORD2 +getMotionMin KEYWORD2 +getMotionMax KEYWORD2 +getModelNumber KEYWORD2 +getSoftwareRevision KEYWORD2 +getSerialNumber KEYWORD2 +getFirmwareRevision KEYWORD2 +getHardwareRevision KEYWORD2 +setVid KEYWORD2 +setPid KEYWORD2 +setGuidVersion KEYWORD2 +setAxesMin KEYWORD2 +setAxesMax KEYWORD2 +setSimulationMin KEYWORD2 +setSimulationMax KEYWORD2 +setMotionMin KEYWORD2 +setMotionMax KEYWORD2 +setModelNumber KEYWORD2 +setSoftwareRevision KEYWORD2 +setSerialNumber KEYWORD2 +setFirmwareRevision KEYWORD2 +setHardwareRevision KEYWORD2 +deleteBond KEYWORD2 +deleteAllBonds KEYWORD2 +enterPairingMode KEYWORD2 +getPeerInfo KEYWORD2 +getDeviceName KEYWORD2 +getDeviceManufacturer KEYWORD2 +getTXPowerLevel KEYWORD2 +setTXPowerLevel KEYWORD2 +setGyroscope KEYWORD2 +setAccelerometer KEYWORD2 +setMotionControls KEYWORD2 ####################################### # Constants diff --git a/library.properties b/library.properties index 9ad5134..9466ef8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESP32-BLE-Gamepad -version=0.7.0 +version=0.7.1 author=lemmingDev maintainer=lemmingDev sentence=Bluetooth LE Gamepad library for the ESP32.