From f0e37202e1dc20d6c572ac17c9a6f9c7415e7fba Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 1 Jul 2021 06:03:57 -0400 Subject: [PATCH 1/3] Add SHARE button support to Xbox One wired --- XBOXONE.cpp | 29 +++++++++++++++++++++++------ XBOXONE.h | 7 ++++--- examples/Xbox/XBOXONE/XBOXONE.ino | 2 ++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/XBOXONE.cpp b/XBOXONE.cpp index f84a090f..a3e0994b 100644 --- a/XBOXONE.cpp +++ b/XBOXONE.cpp @@ -348,9 +348,9 @@ void XBOXONE::readReport() { return; } - uint16_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[ButtonIndex(XBOX)]); // Since the XBOX button is separate, save it and add it back in + uint32_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[ButtonIndex(XBOX)]); // Since the XBOX button is separate, save it and add it back in // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons - ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4); + ButtonState = xbox | (((uint32_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint32_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint32_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4) | (((uint32_t)readBuf[22] & 0x01) << ShareButtonIndex); triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); @@ -383,7 +383,16 @@ uint16_t XBOXONE::getButtonPress(ButtonEnum b) { return triggerValue[0]; else if(index == ButtonIndex(R2)) return triggerValue[1]; - return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[index]))); + + uint32_t buttonMask; + // special case, as 'SHARE' from the PS4 has the same index + // as 'BACK' on the Xbox controller, so we treat it separately + if (b == SHARE) { + buttonMask = (1 << ShareButtonIndex); + } else { + buttonMask = (uint32_t) pgm_read_word(&XBOX_BUTTONS[index]); + } + return (bool)(ButtonState & buttonMask); } bool XBOXONE::getButtonClick(ButtonEnum b) { @@ -401,9 +410,17 @@ bool XBOXONE::getButtonClick(ButtonEnum b) { } return false; } - uint16_t button = pgm_read_word(&XBOX_BUTTONS[index]); - bool click = (ButtonClickState & button); - ButtonClickState &= ~button; // Clear "click" event + + uint32_t buttonMask; + // special case, as 'SHARE' from the PS4 has the same index + // as 'BACK' on the Xbox controller, so we treat it separately + if (b == SHARE) { + buttonMask = (1 << ShareButtonIndex); + } else { + buttonMask = pgm_read_word(&XBOX_BUTTONS[index]); + } + bool click = (ButtonClickState & buttonMask); + ButtonClickState &= ~buttonMask; // Clear "click" event return click; } diff --git a/XBOXONE.h b/XBOXONE.h index c89f558c..a1f38b62 100644 --- a/XBOXONE.h +++ b/XBOXONE.h @@ -221,9 +221,10 @@ private: bool bPollEnable; /* Variables to store the buttons */ - uint16_t ButtonState; - uint16_t OldButtonState; - uint16_t ButtonClickState; + static const uint8_t ShareButtonIndex = 16; // bit offset from right + uint32_t ButtonState; + uint32_t OldButtonState; + uint32_t ButtonClickState; int16_t hatValue[4]; uint16_t triggerValue[2]; uint16_t triggerValueOld[2]; diff --git a/examples/Xbox/XBOXONE/XBOXONE.ino b/examples/Xbox/XBOXONE/XBOXONE.ino index b49f4076..92d9bfdc 100644 --- a/examples/Xbox/XBOXONE/XBOXONE.ino +++ b/examples/Xbox/XBOXONE/XBOXONE.ino @@ -93,6 +93,8 @@ void loop() { Serial.println(F("Xbox")); if (Xbox.getButtonClick(SYNC)) Serial.println(F("Sync")); + if (Xbox.getButtonClick(SHARE)) + Serial.println(F("Share")); if (Xbox.getButtonClick(L1)) Serial.println(F("L1")); From 0b3d269f17036afde1b2b6712c8747a6ab129587 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 1 Jul 2021 06:06:37 -0400 Subject: [PATCH 2/3] Add 'ONE' to Xbox One example startup string Making this distinct from the "XBOXUSB" example which has the same string. --- examples/Xbox/XBOXONE/XBOXONE.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Xbox/XBOXONE/XBOXONE.ino b/examples/Xbox/XBOXONE/XBOXONE.ino index 92d9bfdc..196037b5 100644 --- a/examples/Xbox/XBOXONE/XBOXONE.ino +++ b/examples/Xbox/XBOXONE/XBOXONE.ino @@ -21,7 +21,7 @@ void setup() { Serial.print(F("\r\nOSC did not start")); while (1); //halt } - Serial.print(F("\r\nXBOX USB Library Started")); + Serial.print(F("\r\nXBOX ONE USB Library Started")); } void loop() { Usb.Task(); From f98a746c3dfa7f3c9f4bd6889acfbffcac560245 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 1 Jul 2021 06:08:58 -0400 Subject: [PATCH 3/3] Change Xbox One SHARE support to use bools This saves a handful of bytes because we're not using the larger bitfields, and it simplifies the edge case code in the 'get' functions. --- XBOXONE.cpp | 48 +++++++++++++++++++++++++----------------------- XBOXONE.h | 10 ++++++---- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/XBOXONE.cpp b/XBOXONE.cpp index a3e0994b..1acf1af4 100644 --- a/XBOXONE.cpp +++ b/XBOXONE.cpp @@ -348,9 +348,9 @@ void XBOXONE::readReport() { return; } - uint32_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[ButtonIndex(XBOX)]); // Since the XBOX button is separate, save it and add it back in + uint16_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[ButtonIndex(XBOX)]); // Since the XBOX button is separate, save it and add it back in // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons - ButtonState = xbox | (((uint32_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint32_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint32_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4) | (((uint32_t)readBuf[22] & 0x01) << ShareButtonIndex); + ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4); triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); @@ -360,6 +360,11 @@ void XBOXONE::readReport() { hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); + // Read and store share button separately + const bool newShare = (readBuf[22] & 0x01) ? 1 : 0; + shareClicked = ((sharePressed != newShare) && newShare) ? 1 : 0; + sharePressed = newShare; + //Notify(PSTR("\r\nButtonState"), 0x80); //PrintHex(ButtonState, 0x80); @@ -378,24 +383,29 @@ void XBOXONE::readReport() { } uint16_t XBOXONE::getButtonPress(ButtonEnum b) { + // special handling for 'SHARE' button due to index collision with 'BACK', + // since the 'SHARE' value originally came from the PS4 controller and + // the 'SHARE' button was added to Xbox later with the Series S/X controllers + if (b == SHARE) return sharePressed; + const int8_t index = getButtonIndexXbox(b); if (index < 0) return 0; if(index == ButtonIndex(L2)) // These are analog buttons return triggerValue[0]; else if(index == ButtonIndex(R2)) return triggerValue[1]; - - uint32_t buttonMask; - // special case, as 'SHARE' from the PS4 has the same index - // as 'BACK' on the Xbox controller, so we treat it separately - if (b == SHARE) { - buttonMask = (1 << ShareButtonIndex); - } else { - buttonMask = (uint32_t) pgm_read_word(&XBOX_BUTTONS[index]); - } - return (bool)(ButtonState & buttonMask); + return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[index]))); } bool XBOXONE::getButtonClick(ButtonEnum b) { + // special handling for 'SHARE' button, ibid the above + if (b == SHARE) { + if (shareClicked) { + shareClicked = false; + return true; + } + return false; + } + const int8_t index = getButtonIndexXbox(b); if (index < 0) return 0; if(index == ButtonIndex(L2)) { if(L2Clicked) { @@ -410,17 +420,9 @@ bool XBOXONE::getButtonClick(ButtonEnum b) { } return false; } - - uint32_t buttonMask; - // special case, as 'SHARE' from the PS4 has the same index - // as 'BACK' on the Xbox controller, so we treat it separately - if (b == SHARE) { - buttonMask = (1 << ShareButtonIndex); - } else { - buttonMask = pgm_read_word(&XBOX_BUTTONS[index]); - } - bool click = (ButtonClickState & buttonMask); - ButtonClickState &= ~buttonMask; // Clear "click" event + uint16_t button = pgm_read_word(&XBOX_BUTTONS[index]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // Clear "click" event return click; } diff --git a/XBOXONE.h b/XBOXONE.h index a1f38b62..b1c84d63 100644 --- a/XBOXONE.h +++ b/XBOXONE.h @@ -221,10 +221,9 @@ private: bool bPollEnable; /* Variables to store the buttons */ - static const uint8_t ShareButtonIndex = 16; // bit offset from right - uint32_t ButtonState; - uint32_t OldButtonState; - uint32_t ButtonClickState; + uint16_t ButtonState; + uint16_t OldButtonState; + uint16_t ButtonClickState; int16_t hatValue[4]; uint16_t triggerValue[2]; uint16_t triggerValueOld[2]; @@ -232,6 +231,9 @@ private: bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not bool R2Clicked; + bool sharePressed; // This button doesn't fit in the bitfield + bool shareClicked; + uint8_t readBuf[XBOX_ONE_EP_MAXPKTSIZE]; // General purpose buffer for input data uint8_t cmdCounter;