Skip to content

Commit

Permalink
32 buttons and X,Y,Z and rZ axes are now 16 bit
Browse files Browse the repository at this point in the history
Library now supports 32 buttons
X,Y,Z and rZ axes are now 16 bit int16_t (-32767 to 32767) instead of 8 bit (-127 to 127)

If you're upgrading, remember to account for this when setting your axes values
  • Loading branch information
lemmingDev authored Nov 28, 2020
1 parent ca11af6 commit 3018600
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 78 deletions.
82 changes: 45 additions & 37 deletions BleGamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,37 @@ static const uint8_t _hidReportDescriptor[] = {
USAGE(1), 0x01, // USAGE (Pointer)
COLLECTION(1), 0x00, // COLLECTION (Physical)

// ------------------------------------------------- Buttons (1 to 14)
// ------------------------------------------------- Buttons (1 to 32)
USAGE_PAGE(1), 0x09, // USAGE_PAGE (Button)
USAGE_MINIMUM(1), 0x01, // USAGE_MINIMUM (Button 1)
USAGE_MAXIMUM(1), 0x0e, // USAGE_MAXIMUM (Button 14)
USAGE_MAXIMUM(1), 0x20, // USAGE_MAXIMUM (Button 32)
LOGICAL_MINIMUM(1), 0x00, // LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM(1), 0x01, // LOGICAL_MAXIMUM (1)
REPORT_SIZE(1), 0x01, // REPORT_SIZE (1)
REPORT_COUNT(1), 0x0e, // REPORT_COUNT (14)
HIDINPUT(1), 0x02, // INPUT (Data, Variable, Absolute) ;14 button bits
// ------------------------------------------------- Padding
REPORT_SIZE(1), 0x01, // REPORT_SIZE (1)
REPORT_COUNT(1), 0x02, // REPORT_COUNT (2)
HIDINPUT(1), 0x03, // INPUT (Constant, Variable, Absolute) ;2 bit padding
REPORT_COUNT(1), 0x20, // REPORT_COUNT (32)
HIDINPUT(1), 0x02, // INPUT (Data, Variable, Absolute) ;32 button bits
// ------------------------------------------------- X/Y position, Z/rZ position
USAGE_PAGE(1), 0x01, // USAGE_PAGE (Generic Desktop)
USAGE(1), 0x30, // USAGE (X)
USAGE(1), 0x31, // USAGE (Y)
USAGE(1), 0x32, // USAGE (Z)
USAGE(1), 0x35, // USAGE (rZ)
LOGICAL_MINIMUM(1), 0x81, // LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM(1), 0x7f, // LOGICAL_MAXIMUM (127)
REPORT_SIZE(1), 0x08, // REPORT_SIZE (8)
REPORT_COUNT(1), 0x04, // REPORT_COUNT (4)
HIDINPUT(1), 0x02, // INPUT (Data, Variable, Absolute) ;4 bytes (X,Y,Z,rZ)

USAGE_PAGE(1), 0x01, // USAGE_PAGE (Generic Desktop)
USAGE_PAGE(1), 0x01, // USAGE_PAGE (Generic Desktop)
COLLECTION(1), 0x00, // COLLECTION (Physical)
USAGE(1), 0x30, // USAGE (X)
USAGE(1), 0x31, // USAGE (Y)
USAGE(1), 0x32, // USAGE (Z)
USAGE(1), 0x35, // USAGE (rZ)
0x16, 0x01, 0x80,//LOGICAL_MINIMUM (-32767)
0x26, 0xFF, 0x7F,//LOGICAL_MAXIMUM (32767)
REPORT_SIZE(1), 0x10, // REPORT_SIZE (16)
REPORT_COUNT(1), 0x04, // REPORT_COUNT (4)
HIDINPUT(1), 0x02, // INPUT (Data,Var,Abs)
// ------------------------------------------------- Triggers
USAGE(1), 0x33, // USAGE (rX) Left Trigger
USAGE(1), 0x34, // USAGE (rY) Right Trigger
LOGICAL_MINIMUM(1), 0x81, // LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM(1), 0x7f, // LOGICAL_MAXIMUM (127)
REPORT_SIZE(1), 0x08, // REPORT_SIZE (8)
REPORT_COUNT(1), 0x02, // REPORT_COUNT (2)
HIDINPUT(1), 0x02, // INPUT (Data, Variable, Absolute) ;2 bytes rX, rY

HIDINPUT(1), 0x02, // INPUT (Data, Variable, Absolute) ;4 bytes (X,Y,Z,rZ)
END_COLLECTION(0), // END_COLLECTION

USAGE_PAGE(1), 0x01, // USAGE_PAGE (Generic Desktop)
USAGE(1), 0x39, // USAGE (Hat switch)
USAGE(1), 0x39, // USAGE (Hat switch)
Expand Down Expand Up @@ -92,28 +89,39 @@ void BleGamepad::end(void)
{
}

void BleGamepad::setAxes(signed char x, signed char y, signed char z, signed char rZ, char rX, char rY, signed char hat)
void BleGamepad::setAxes(int16_t x, int16_t y, int16_t z, int16_t rZ, char rX, char rY, signed char hat)
{
if (this->isConnected())
{
uint8_t m[9];
if(x == -32768) { x = -32767; }
if(y == -32768) { y = -32767; }
if(z == -32768) { z = -32767; }
if(rZ == -32768) { rZ = -32767; }

uint8_t m[15];
m[0] = _buttons;
m[1] = (_buttons >> 8);
m[2] = x;
m[3] = y;
m[4] = z;
m[5] = rZ;
m[6] = (signed char)(rX - 128);
m[7] = (signed char)(rY - 128);
m[8] = hat;
if (m[6] == -128) { m[6] = -127; }
if (m[7] == -128) { m[7] = -127; }
m[2] = (_buttons >> 16);
m[3] = (_buttons >> 24);
m[4] = x;
m[5] = (x >> 8);
m[6] = y;
m[7] = (y >> 8);
m[8] = z;
m[9] = (z >> 8);
m[10] = rZ;
m[11] = (rZ >> 8);
m[12] = (signed char)(rX - 128);
m[13] = (signed char)(rY - 128);
m[14] = hat;
if (m[12] == -128) { m[12] = -127; }
if (m[13] == -128) { m[13] = -127; }
this->inputGamepad->setValue(m, sizeof(m));
this->inputGamepad->notify();
}
}

void BleGamepad::buttons(uint16_t b)
void BleGamepad::buttons(uint32_t b)
{
if (b != _buttons)
{
Expand All @@ -122,17 +130,17 @@ void BleGamepad::buttons(uint16_t b)
}
}

void BleGamepad::press(uint16_t b)
void BleGamepad::press(uint32_t b)
{
buttons(_buttons | b);
}

void BleGamepad::release(uint16_t b)
void BleGamepad::release(uint32_t b)
{
buttons(_buttons & ~b);
}

bool BleGamepad::isPressed(uint16_t b)
bool BleGamepad::isPressed(uint32_t b)
{
if ((b & _buttons) > 0)
return true;
Expand Down
28 changes: 23 additions & 5 deletions BleGamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@
#define BUTTON_12 2048
#define BUTTON_13 4096
#define BUTTON_14 8192
#define BUTTON_15 16384
#define BUTTON_16 32768
#define BUTTON_17 65536
#define BUTTON_18 131072
#define BUTTON_19 262144
#define BUTTON_20 524288
#define BUTTON_21 1048576
#define BUTTON_22 2097152
#define BUTTON_23 4194304
#define BUTTON_24 8388608
#define BUTTON_25 16777216
#define BUTTON_26 33554432
#define BUTTON_27 67108864
#define BUTTON_28 134217728
#define BUTTON_29 268435456
#define BUTTON_30 536870912
#define BUTTON_31 1073741824
#define BUTTON_32 2147483648

#define DPAD_CENTERED 0
#define DPAD_UP 1
Expand All @@ -38,17 +56,17 @@ class BleGamepad {
BleConnectionStatus* connectionStatus;
BLEHIDDevice* hid;
BLECharacteristic* inputGamepad;
void buttons(uint16_t b);
void buttons(uint32_t b);
void rawAction(uint8_t msg[], char msgSize);
static void taskServer(void* pvParameter);
public:
BleGamepad(std::string deviceName = "ESP32 BLE Gamepad", std::string deviceManufacturer = "Espressif", uint8_t batteryLevel = 100);
void begin(void);
void end(void);
void setAxes(signed char x, signed char y, signed char z = 0, signed char rZ = 0, char rX = 0, char rY = 0, signed char hat = 0);
void press(uint16_t b = BUTTON_1); // press BUTTON_1 by default
void release(uint16_t b = BUTTON_1); // release BUTTON_1 by default
bool isPressed(uint16_t b = BUTTON_1); // check BUTTON_1 by default
void setAxes(int16_t x, int16_t y, int16_t z = 0, int16_t rZ = 0, char rX = 0, char rY = 0, signed char hat = 0);
void press(uint32_t b = BUTTON_1); // press BUTTON_1 by default
void release(uint32_t b = BUTTON_1); // release BUTTON_1 by default
bool isPressed(uint32_t b = BUTTON_1); // check BUTTON_1 by default
bool isConnected(void);
void setBatteryLevel(uint8_t level);
uint8_t batteryLevel;
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ This library allows you to make the ESP32 act as a Bluetooth Gamepad and control

## Features

- [x] Button press (14 buttons)
- [x] Button release (14 buttons)
- [x] Button press (32 buttons)
- [x] Button release (32 buttons)
- [x] Axes movement (6 axes (x, y, z, rZ, rX, rY) --> (Left Thumb X, Left Thumb Y, Right Thumb X, Right Thumb Y, Left Trigger, Right Trigger)))
- [x] Point of view hat (d-pad)
- [x] Report optional battery level to host (basically works, but it doesn't show up in Android's status bar)
Expand All @@ -30,13 +30,13 @@ This library allows you to make the ESP32 act as a Bluetooth Gamepad and control
* This example turns the ESP32 into a Bluetooth LE gamepad that presses buttons and moves axis
*
* Possible buttons are:
* BUTTON_1 through to BUTTON_14
* BUTTON_1 through to BUTTON_32
*
* Possible DPAD/HAT switch position values are:
* DPAD_CENTERED, DPAD_UP, DPAD_UP_RIGHT, DPAD_RIGHT, DPAD_DOWN_RIGHT,
* DPAD_DOWN, DPAD_DOWN_LEFT, DPAD_LEFT, DPAD_UP_LEFT
*
* bleGamepad.setAxes takes the following signed char parameters for the Left/Right Thumb X/Y, char for the Left/Right Triggers, and hat switch position as above:
* bleGamepad.setAxes takes the following int16_t parameters for the Left/Right Thumb X/Y, char for the Left/Right Triggers, and hat switch position as above:
* (Left Thumb X, Left Thumb Y, Right Thumb X, Right Thumb Y, Left Trigger, Right Trigger, Hat switch position);
*/

Expand All @@ -52,15 +52,15 @@ void setup() {

void loop() {
if(bleGamepad.isConnected()) {
Serial.println("Press buttons 1 and 14. Move all axes to max. Set DPAD to down right.");
Serial.println("Press buttons 1 and 32. Move all axes to max. Set DPAD to down right.");
bleGamepad.press(BUTTON_1);
bleGamepad.press(BUTTON_14);
bleGamepad.setAxes(127, 127, 127, 127, 255, 255, DPAD_DOWN_RIGHT);
bleGamepad.press(BUTTON_32);
bleGamepad.setAxes(32767, 32767, 32767, 32767, 255, 255, DPAD_DOWN_RIGHT);
delay(500);

Serial.println("Release button 1. Move all axes to min. Set DPAD to centred.");
bleGamepad.release(BUTTON_1);
bleGamepad.setAxes(-127, -127, -127, -127, 0, 0, DPAD_CENTERED);
bleGamepad.setAxes(-32767, -32767, -32767, -32767, 0, 0, DPAD_CENTERED);
delay(500);
}
}
Expand Down
21 changes: 12 additions & 9 deletions examples/Gamepad/Gamepad.ino
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,40 @@
* This example turns the ESP32 into a Bluetooth LE gamepad that presses buttons and moves axis
*
* Possible buttons are:
* BUTTON_1 through to BUTTON_14
* BUTTON_1 through to BUTTON_32
*
* Possible DPAD/HAT switch position values are:
* DPAD_CENTERED, DPAD_UP, DPAD_UP_RIGHT, DPAD_RIGHT, DPAD_DOWN_RIGHT,
* DPAD_DOWN, DPAD_DOWN_LEFT, DPAD_LEFT, DPAD_UP_LEFT
*
* bleGamepad.setAxes takes the following signed char parameters for the Left/Right Thumb X/Y, char for the Left/Right Triggers, and hat switch position as above:
* bleGamepad.setAxes takes the following int16_t parameters for the Left/Right Thumb X/Y, char for the Left/Right Triggers, and hat switch position as above:
* (Left Thumb X, Left Thumb Y, Right Thumb X, Right Thumb Y, Left Trigger, Right Trigger, Hat switch position);
*/

#include <BleGamepad.h>

BleGamepad bleGamepad;

void setup() {
void setup()
{
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleGamepad.begin();
}

void loop() {
if(bleGamepad.isConnected()) {
Serial.println("Press buttons 1 and 14. Move all axes to max. Set DPAD to down right.");
void loop()
{
if(bleGamepad.isConnected())
{
Serial.println("Press buttons 1 and 32. Move all axes to max. Set DPAD to down right.");
bleGamepad.press(BUTTON_1);
bleGamepad.press(BUTTON_14);
bleGamepad.setAxes(127, 127, 127, 127, 255, 255, DPAD_DOWN_RIGHT);
bleGamepad.press(BUTTON_32);
bleGamepad.setAxes(32767, 32767, 32767, 32767, 255, 255, DPAD_DOWN_RIGHT);
delay(500);

Serial.println("Release button 1. Move all axes to min. Set DPAD to centred.");
bleGamepad.release(BUTTON_1);
bleGamepad.setAxes(-127, -127, -127, -127, 0, 0, DPAD_CENTERED);
bleGamepad.setAxes(-32767, -32767, -32767, -32767, 0, 0, DPAD_CENTERED);
delay(500);
}
}
4 changes: 2 additions & 2 deletions examples/PotAsAxis/PotAsAxis.ino
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ void loop()
// Calculate the average
potValue = potValue / numberOfPotSamples;

// Map analog reading from 0 ~ 4095 to 127 ~ -127 for use as an axis reading
int adjustedValue = map(potValue, 0, 4095, 127, -127);
// Map analog reading from 0 ~ 4095 to 32737 ~ -32737 for use as an axis reading
int adjustedValue = map(potValue, 0, 4095, 32737, -32737);

// Print readings to serial port
Serial.print("Sent: ");
Expand Down
11 changes: 7 additions & 4 deletions examples/SingleButton/SingleButton.ino
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
* A simple sketch that maps a single pin on the ESP32 to a single button on the controller
*/

#include <BleGamepad.h>
#include <BleGamepad.h> // https://github.com/lemmingDev/ESP32-BLE-Gamepad

BleGamepad bleGamepad;

int previousButton1State = HIGH;

void setup() {
void setup()
{
pinMode(2, INPUT_PULLUP);
bleGamepad.begin();
}

void loop() {
if(bleGamepad.isConnected()) {
void loop()
{
if(bleGamepad.isConnected())
{

int currentButton1State = digitalRead(2);

Expand Down
40 changes: 29 additions & 11 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ BleGamepad KEYWORD1
# Methods and Functions
#######################################

begin KEYWORD2
end KEYWORD2
setAxes KEYWORD2
press KEYWORD2
release KEYWORD2
begin KEYWORD2
end KEYWORD2
setAxes KEYWORD2
press KEYWORD2
release KEYWORD2
isPressed KEYWORD2
isConnected KEYWORD2

Expand All @@ -36,13 +36,31 @@ BUTTON_11 LITERAL1
BUTTON_12 LITERAL1
BUTTON_13 LITERAL1
BUTTON_14 LITERAL1
BUTTON_15 LITERAL1
BUTTON_16 LITERAL1
BUTTON_17 LITERAL1
BUTTON_18 LITERAL1
BUTTON_19 LITERAL1
BUTTON_20 LITERAL1
BUTTON_21 LITERAL1
BUTTON_22 LITERAL1
BUTTON_23 LITERAL1
BUTTON_24 LITERAL1
BUTTON_25 LITERAL1
BUTTON_26 LITERAL1
BUTTON_27 LITERAL1
BUTTON_28 LITERAL1
BUTTON_29 LITERAL1
BUTTON_30 LITERAL1
BUTTON_31 LITERAL1
BUTTON_32 LITERAL1

DPAD_CENTERED LITERAL1
DPAD_UP LITERAL1
DPAD_UP LITERAL1
DPAD_UP_RIGHT LITERAL1
DPAD_RIGHT LITERAL1
DPAD_DOWN_RIGHT LITERAL1
DPAD_DOWN LITERAL1
DPAD_RIGHT LITERAL1
DPAD_DOWN_RIGHT LITERAL1
DPAD_DOWN LITERAL1
DPAD_DOWN_LEFT LITERAL1
DPAD_LEFT LITERAL1
DPAD_UP_LEFT LITERAL1
DPAD_LEFT LITERAL1
DPAD_UP_LEFT LITERAL1
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name=ESP32 BLE Gamepad
version=0.1.3
version=0.1.4
author=lemmingDev
maintainer=lemmingDev
sentence=Bluetooth LE Gamepad library for the ESP32.
paragraph=Bluetooth LE Gamepad library for the ESP32.
category=Communication
url=https://github.com/lemmingDev/ESP32-BLE-Gamepad
architectures=esp32
architectures=esp32

0 comments on commit 3018600

Please sign in to comment.