mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Added support for the Switch Pro controller via Bluetooth
This commit is contained in:
parent
e94343a49e
commit
13b9047106
9 changed files with 648 additions and 4 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -8,7 +8,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
# find examples -type f -name "*.ino" | rev | cut -d/ -f2- | rev | sort | sed -z 's/\n/, /g'
|
||||
example: [examples/ambx, examples/acm/acm_terminal, examples/adk/adk_barcode, examples/adk/ArduinoBlinkLED, examples/adk/demokit_20, examples/adk/term_test, examples/adk/term_time, examples/Bluetooth/BTHID, examples/Bluetooth/PS3BT, examples/Bluetooth/PS3Multi, examples/Bluetooth/PS3SPP, examples/Bluetooth/PS4BT, examples/Bluetooth/PS5BT, examples/Bluetooth/SPP, examples/Bluetooth/SPPMulti, examples/Bluetooth/Wii, examples/Bluetooth/WiiBalanceBoard, examples/Bluetooth/WiiIRCamera, examples/Bluetooth/WiiMulti, examples/Bluetooth/WiiUProController, examples/board_qc, examples/cdc_XR21B1411/XR_terminal, examples/ftdi/USBFTDILoopback, examples/GPIO/Blink, examples/GPIO/Blink_LowLevel, examples/GPIO/Input, examples/HID/le3dp, examples/HID/scale, examples/HID/SRWS1, examples/HID/t16km, examples/HID/USBHIDBootKbd, examples/HID/USBHIDBootKbdAndMouse, examples/HID/USBHIDBootMouse, examples/HID/USBHID_desc, examples/HID/USBHIDJoystick, examples/HID/USBHIDMultimediaKbd, examples/hub_demo, examples/max_LCD, examples/pl2303/pl2303_gprs_terminal, examples/pl2303/pl2303_gps, examples/pl2303/pl2303_tinygps, examples/pl2303/pl2303_xbee_terminal, examples/PS3USB, examples/PS4USB, examples/PS5USB, examples/PSBuzz, examples/USB_desc, examples/USBH_MIDI/bidirectional_converter, examples/USBH_MIDI/eVY1_sample, examples/USBH_MIDI/USBH_MIDI_dump, examples/USBH_MIDI/USB_MIDI_converter, examples/USBH_MIDI/USB_MIDI_converter_multi, examples/Xbox/XBOXOLD, examples/Xbox/XBOXONE, examples/Xbox/XBOXONESBT, examples/Xbox/XBOXRECV, examples/Xbox/XBOXUSB]
|
||||
example: [examples/ambx, examples/acm/acm_terminal, examples/adk/adk_barcode, examples/adk/ArduinoBlinkLED, examples/adk/demokit_20, examples/adk/term_test, examples/adk/term_time, examples/Bluetooth/BTHID, examples/Bluetooth/PS3BT, examples/Bluetooth/PS3Multi, examples/Bluetooth/PS3SPP, examples/Bluetooth/PS4BT, examples/Bluetooth/PS5BT, examples/Bluetooth/SPP, examples/Bluetooth/SPPMulti, examples/Bluetooth/SwitchPro, examples/Bluetooth/Wii, examples/Bluetooth/WiiBalanceBoard, examples/Bluetooth/WiiIRCamera, examples/Bluetooth/WiiMulti, examples/Bluetooth/WiiUProController, examples/board_qc, examples/cdc_XR21B1411/XR_terminal, examples/ftdi/USBFTDILoopback, examples/GPIO/Blink, examples/GPIO/Blink_LowLevel, examples/GPIO/Input, examples/HID/le3dp, examples/HID/scale, examples/HID/SRWS1, examples/HID/t16km, examples/HID/USBHIDBootKbd, examples/HID/USBHIDBootKbdAndMouse, examples/HID/USBHIDBootMouse, examples/HID/USBHID_desc, examples/HID/USBHIDJoystick, examples/HID/USBHIDMultimediaKbd, examples/hub_demo, examples/max_LCD, examples/pl2303/pl2303_gprs_terminal, examples/pl2303/pl2303_gps, examples/pl2303/pl2303_tinygps, examples/pl2303/pl2303_xbee_terminal, examples/PS3USB, examples/PS4USB, examples/PS5USB, examples/PSBuzz, examples/USB_desc, examples/USBH_MIDI/bidirectional_converter, examples/USBH_MIDI/eVY1_sample, examples/USBH_MIDI/USBH_MIDI_dump, examples/USBH_MIDI/USB_MIDI_converter, examples/USBH_MIDI/USB_MIDI_converter_multi, examples/Xbox/XBOXOLD, examples/Xbox/XBOXONE, examples/Xbox/XBOXONESBT, examples/Xbox/XBOXRECV, examples/Xbox/XBOXUSB]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
|
|
89
SwitchProBT.h
Normal file
89
SwitchProBT.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* Copyright (C) 2021 Kristian Sloth Lauszus. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Kristian Sloth Lauszus
|
||||
Web : https://lauszus.com
|
||||
e-mail : lauszus@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef _switch_pro_bt_h_
|
||||
#define _switch_pro_bt_h_
|
||||
|
||||
#include "BTHID.h"
|
||||
#include "SwitchProParser.h"
|
||||
|
||||
/**
|
||||
* This class implements support for the Switch Pro controller via Bluetooth.
|
||||
* It uses the BTHID class for all the Bluetooth communication.
|
||||
*/
|
||||
class SwitchProBT : public BTHID, public SwitchProParser {
|
||||
public:
|
||||
/**
|
||||
* Constructor for the SwitchProBT class.
|
||||
* @param p Pointer to the BTD class instance.
|
||||
* @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true.
|
||||
* @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
|
||||
*/
|
||||
SwitchProBT(BTD *p, bool pair = false, const char *pin = "0000") :
|
||||
BTHID(p, pair, pin) {
|
||||
SwitchProParser::Reset();
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to check if a Switch Pro controller is connected.
|
||||
* @return Returns true if it is connected.
|
||||
*/
|
||||
bool connected() {
|
||||
return BTHID::connected;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** @name BTHID implementation */
|
||||
/**
|
||||
* Used to parse Bluetooth HID data.
|
||||
* @param len The length of the incoming data.
|
||||
* @param buf Pointer to the data buffer.
|
||||
*/
|
||||
virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) {
|
||||
SwitchProParser::Parse(len, buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when a device is successfully initialized.
|
||||
* Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
|
||||
* This is useful for instance if you want to set the LEDs in a specific way.
|
||||
*/
|
||||
virtual void OnInitBTHID() {
|
||||
SwitchProParser::Reset();
|
||||
|
||||
// Only call this is a user function has not been set
|
||||
if (!pFuncOnInit)
|
||||
setLedOn(LED1); // Turn on the LED1
|
||||
};
|
||||
|
||||
/** Used to reset the different buffers to there default values */
|
||||
virtual void ResetBTHID() {
|
||||
SwitchProParser::Reset();
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
/** @name SwitchProParser implementation */
|
||||
virtual void sendOutputReport(SwitchProOutput *output) {
|
||||
output->reportChanged = false;
|
||||
#if 0
|
||||
// Send the Bluetooth DATA output report on the interrupt channel
|
||||
pBtd->L2CAP_Command(hci_handle, buf, sizeof(buf), interrupt_scid[0], interrupt_scid[1]);
|
||||
#endif
|
||||
};
|
||||
/**@}*/
|
||||
};
|
||||
#endif
|
151
SwitchProParser.cpp
Normal file
151
SwitchProParser.cpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* Copyright (C) 2021 Kristian Sloth Lauszus. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Kristian Sloth Lauszus
|
||||
Web : https://lauszus.com
|
||||
e-mail : lauszus@gmail.com
|
||||
*/
|
||||
|
||||
#include "SwitchProParser.h"
|
||||
|
||||
enum DPADEnum {
|
||||
DPAD_UP = 0x0,
|
||||
DPAD_UP_RIGHT = 0x1,
|
||||
DPAD_RIGHT = 0x2,
|
||||
DPAD_RIGHT_DOWN = 0x3,
|
||||
DPAD_DOWN = 0x4,
|
||||
DPAD_DOWN_LEFT = 0x5,
|
||||
DPAD_LEFT = 0x6,
|
||||
DPAD_LEFT_UP = 0x7,
|
||||
DPAD_OFF = 0x8,
|
||||
};
|
||||
|
||||
// To enable serial debugging see "settings.h"
|
||||
//#define PRINTREPORT // Uncomment to print the report send by the Switch Pro Controller
|
||||
|
||||
int8_t SwitchProParser::getButtonIndexSwitchPro(ButtonEnum b) {
|
||||
const int8_t index = ButtonIndex(b);
|
||||
if ((uint8_t) index >= (sizeof(SWITCH_PRO_BUTTONS) / sizeof(SWITCH_PRO_BUTTONS[0]))) return -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
bool SwitchProParser::checkDpad(ButtonEnum b) {
|
||||
switch (b) {
|
||||
case UP:
|
||||
return switchProData.btn.dpad == DPAD_LEFT_UP || switchProData.btn.dpad == DPAD_UP || switchProData.btn.dpad == DPAD_UP_RIGHT;
|
||||
case RIGHT:
|
||||
return switchProData.btn.dpad == DPAD_UP_RIGHT || switchProData.btn.dpad == DPAD_RIGHT || switchProData.btn.dpad == DPAD_RIGHT_DOWN;
|
||||
case DOWN:
|
||||
return switchProData.btn.dpad == DPAD_RIGHT_DOWN || switchProData.btn.dpad == DPAD_DOWN || switchProData.btn.dpad == DPAD_DOWN_LEFT;
|
||||
case LEFT:
|
||||
return switchProData.btn.dpad == DPAD_DOWN_LEFT || switchProData.btn.dpad == DPAD_LEFT || switchProData.btn.dpad == DPAD_LEFT_UP;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SwitchProParser::getButtonPress(ButtonEnum b) {
|
||||
const int8_t index = getButtonIndexSwitchPro(b); if (index < 0) return 0;
|
||||
if (index <= LEFT) // Dpad
|
||||
return checkDpad(b);
|
||||
else
|
||||
return switchProData.btn.val & (1UL << pgm_read_byte(&SWITCH_PRO_BUTTONS[index]));
|
||||
}
|
||||
|
||||
bool SwitchProParser::getButtonClick(ButtonEnum b) {
|
||||
const int8_t index = getButtonIndexSwitchPro(b); if (index < 0) return 0;
|
||||
uint32_t mask = 1UL << pgm_read_byte(&SWITCH_PRO_BUTTONS[index]);
|
||||
bool click = buttonClickState.val & mask;
|
||||
buttonClickState.val &= ~mask; // Clear "click" event
|
||||
return click;
|
||||
}
|
||||
|
||||
int16_t SwitchProParser::getAnalogHat(AnalogHatEnum a) {
|
||||
return switchProData.hatValue[(uint8_t)a] - 0x7FFF; // Subtract the center value
|
||||
}
|
||||
|
||||
void SwitchProParser::Parse(uint8_t len, uint8_t *buf) {
|
||||
if (len > 1 && buf) {
|
||||
#ifdef PRINTREPORT
|
||||
Notify(PSTR("\r\nLen: "), 0x80); Notify(len, 0x80);
|
||||
Notify(PSTR(", data: "), 0x80);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
D_PrintHex<uint8_t > (buf[i], 0x80);
|
||||
Notify(PSTR(" "), 0x80);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (buf[0] == 0x3F) // Check report ID
|
||||
memcpy(&switchProData, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(switchProData)));
|
||||
else {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(PSTR("\r\nUnknown report id: "), 0x80);
|
||||
D_PrintHex<uint8_t > (buf[0], 0x80);
|
||||
Notify(PSTR(", len: "), 0x80);
|
||||
D_PrintHex<uint8_t > (len, 0x80);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Workaround issue with the controller sending invalid joystick values when it is connected
|
||||
for (uint8_t i = 0; i < sizeof(switchProData.hatValue) / sizeof(switchProData.hatValue[0]); i++) {
|
||||
if (switchProData.hatValue[i] < 1000 || switchProData.hatValue[i] > 0xFFFF - 1000)
|
||||
switchProData.hatValue[i] = 0x7FFF; // Center value
|
||||
}
|
||||
|
||||
if (switchProData.btn.val != oldButtonState.val) { // Check if anything has changed
|
||||
buttonClickState.val = switchProData.btn.val & ~oldButtonState.val; // Update click state variable
|
||||
oldButtonState.val = switchProData.btn.val;
|
||||
|
||||
// The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself
|
||||
uint8_t newDpad = 0;
|
||||
if (checkDpad(UP))
|
||||
newDpad |= 1 << UP;
|
||||
if (checkDpad(RIGHT))
|
||||
newDpad |= 1 << RIGHT;
|
||||
if (checkDpad(DOWN))
|
||||
newDpad |= 1 << DOWN;
|
||||
if (checkDpad(LEFT))
|
||||
newDpad |= 1 << LEFT;
|
||||
if (newDpad != oldDpad) {
|
||||
buttonClickState.dpad = newDpad & ~oldDpad; // Override values
|
||||
oldDpad = newDpad;
|
||||
}
|
||||
}
|
||||
|
||||
message_counter++;
|
||||
}
|
||||
|
||||
if (switchProOutput.reportChanged)
|
||||
sendOutputReport(&switchProOutput); // Send output report
|
||||
}
|
||||
|
||||
void SwitchProParser::Reset() {
|
||||
for (uint8_t i = 0; i < sizeof(switchProData.hatValue) / sizeof(switchProData.hatValue[0]); i++)
|
||||
switchProData.hatValue[i] = 0x7FFF; // Center value
|
||||
switchProData.btn.val = 0;
|
||||
oldButtonState.val = 0;
|
||||
|
||||
switchProData.btn.dpad = DPAD_OFF;
|
||||
oldButtonState.dpad = DPAD_OFF;
|
||||
buttonClickState.dpad = 0;
|
||||
oldDpad = 0;
|
||||
|
||||
#if 0
|
||||
ps5Output.bigRumble = ps5Output.smallRumble = 0;
|
||||
ps5Output.microphoneLed = 0;
|
||||
ps5Output.disableLeds = 0;
|
||||
ps5Output.playerLeds = 0;
|
||||
ps5Output.r = ps5Output.g = ps5Output.b = 0;
|
||||
#endif
|
||||
switchProOutput.reportChanged = false;
|
||||
};
|
271
SwitchProParser.h
Normal file
271
SwitchProParser.h
Normal file
|
@ -0,0 +1,271 @@
|
|||
/* Copyright (C) 2021 Kristian Sloth Lauszus. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Kristian Sloth Lauszus
|
||||
Web : https://lauszus.com
|
||||
e-mail : lauszus@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef _switch_pro_parser_h_
|
||||
#define _switch_pro_parser_h_
|
||||
|
||||
#include "Usb.h"
|
||||
#include "controllerEnums.h"
|
||||
|
||||
/** Buttons on the controller */
|
||||
const uint8_t SWITCH_PRO_BUTTONS[] PROGMEM = {
|
||||
0x10, // UP
|
||||
0x11, // RIGHT
|
||||
0x12, // DOWN
|
||||
0x13, // LEFT
|
||||
|
||||
0x0D, // Capture
|
||||
0x09, // PLUS
|
||||
0x0A, // L3
|
||||
0x0B, // R3
|
||||
|
||||
0x08, // MINUS
|
||||
0x0C, // HOME
|
||||
0, 0, // Skip
|
||||
|
||||
0x00, // B
|
||||
0x01, // A
|
||||
0x03, // X
|
||||
0x02, // Y
|
||||
|
||||
0x04, // L
|
||||
0x05, // R
|
||||
0x06, // ZL
|
||||
0x07, // ZR
|
||||
};
|
||||
|
||||
union SwitchProButtons {
|
||||
struct {
|
||||
uint8_t b : 1;
|
||||
uint8_t a : 1;
|
||||
uint8_t y : 1;
|
||||
uint8_t x : 1;
|
||||
|
||||
uint8_t l : 1;
|
||||
uint8_t r : 1;
|
||||
uint8_t zl : 1;
|
||||
uint8_t zr : 1;
|
||||
|
||||
uint8_t minus : 1;
|
||||
uint8_t plus : 1;
|
||||
uint8_t l3 : 1;
|
||||
uint8_t r3 : 1;
|
||||
|
||||
uint8_t home : 1;
|
||||
uint8_t capture : 1;
|
||||
uint8_t dummy1 : 2;
|
||||
|
||||
uint8_t dpad : 4;
|
||||
uint8_t dummy2 : 4;
|
||||
} __attribute__((packed));
|
||||
uint32_t val : 24;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct SwitchProData {
|
||||
/* Button and joystick values */
|
||||
SwitchProButtons btn; // 0-2 bytes
|
||||
uint16_t hatValue[4]; // 3-10 bytes
|
||||
} __attribute__((packed));
|
||||
|
||||
struct SwitchProOutput {
|
||||
bool reportChanged; // The data is send when data is received from the controller
|
||||
} __attribute__((packed));
|
||||
|
||||
/** This class parses all the data sent by the Switch Pro controller */
|
||||
class SwitchProParser {
|
||||
public:
|
||||
/** Constructor for the SwitchProParser class. */
|
||||
SwitchProParser() {
|
||||
Reset();
|
||||
};
|
||||
|
||||
/** @name Switch Pro Controller functions */
|
||||
/**
|
||||
* getButtonPress(ButtonEnum b) will return true as long as the button is held down.
|
||||
*
|
||||
* While getButtonClick(ButtonEnum b) will only return it once.
|
||||
*
|
||||
* So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
|
||||
* but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
|
||||
* @param b ::ButtonEnum to read.
|
||||
* @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
|
||||
*/
|
||||
bool getButtonPress(ButtonEnum b);
|
||||
bool getButtonClick(ButtonEnum b);
|
||||
/**@}*/
|
||||
/** @name Switch Pro Controller functions */
|
||||
/**
|
||||
* Used to read the analog joystick.
|
||||
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
|
||||
* @return Return the analog value in the range of 0-255.
|
||||
*/
|
||||
int16_t getAnalogHat(AnalogHatEnum a);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Get the angle of the controller calculated using the accelerometer.
|
||||
* @param a Either ::Pitch or ::Roll.
|
||||
* @return Return the angle in the range of 0-360.
|
||||
*/
|
||||
float getAngle(AngleEnum a) {
|
||||
if (a == Pitch)
|
||||
return (atan2f(-ps5Data.accY, -ps5Data.accZ) + PI) * RAD_TO_DEG;
|
||||
else
|
||||
return (atan2f(ps5Data.accX, -ps5Data.accZ) + PI) * RAD_TO_DEG;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to get the raw values from the 3-axis gyroscope and 3-axis accelerometer inside the PS5 controller.
|
||||
* @param s The sensor to read.
|
||||
* @return Returns the raw sensor reading.
|
||||
*/
|
||||
int16_t getSensor(SensorEnum s) {
|
||||
switch(s) {
|
||||
case gX:
|
||||
return ps5Data.gyroX;
|
||||
case gY:
|
||||
return ps5Data.gyroY;
|
||||
case gZ:
|
||||
return ps5Data.gyroZ;
|
||||
case aX:
|
||||
return ps5Data.accX;
|
||||
case aY:
|
||||
return ps5Data.accY;
|
||||
case aZ:
|
||||
return ps5Data.accZ;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Turn both rumble and the LEDs off. */
|
||||
void setAllOff() {
|
||||
setRumbleOff();
|
||||
setLedOff();
|
||||
};
|
||||
|
||||
/** Set rumble off. */
|
||||
void setRumbleOff() {
|
||||
setRumbleOn(0, 0);
|
||||
}
|
||||
|
||||
/** Toggle rumble. */
|
||||
void setRumbleToggle() {
|
||||
// TODO: Implement this
|
||||
switchProOutput.reportChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on rumble.
|
||||
* @param mode Either ::RumbleHigh or ::RumbleLow.
|
||||
*/
|
||||
void setRumbleOn(RumbleEnum mode) {
|
||||
if (mode == RumbleLow)
|
||||
setRumbleOn(0x00, 0xFF);
|
||||
else
|
||||
setRumbleOn(0xFF, 0x00);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on rumble.
|
||||
* @param bigRumble Value for big motor.
|
||||
* @param smallRumble Value for small motor.
|
||||
*/
|
||||
void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
|
||||
// TODO: Implement this
|
||||
(void)bigRumble;
|
||||
(void)smallRumble;
|
||||
switchProOutput.reportChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set LED value without using the ::LEDEnum.
|
||||
* @param value See: ::LEDEnum.
|
||||
*/
|
||||
void setLedRaw(uint8_t value) {
|
||||
// TODO: Implement this
|
||||
(void)value;
|
||||
switchProOutput.reportChanged = true;
|
||||
}
|
||||
|
||||
/** Turn all LEDs off. */
|
||||
void setLedOff() {
|
||||
setLedRaw(0);
|
||||
}
|
||||
/**
|
||||
* Turn the specific ::LEDEnum off.
|
||||
* @param a The ::LEDEnum to turn off.
|
||||
*/
|
||||
void setLedOff(LEDEnum a) {
|
||||
// TODO: Implement this
|
||||
(void)a;
|
||||
switchProOutput.reportChanged = true;
|
||||
}
|
||||
/**
|
||||
* Turn the specific ::LEDEnum on.
|
||||
* @param a The ::LEDEnum to turn on.
|
||||
*/
|
||||
void setLedOn(LEDEnum a) {
|
||||
// TODO: Implement this
|
||||
(void)a;
|
||||
switchProOutput.reportChanged = true;
|
||||
}
|
||||
/**
|
||||
* Toggle the specific ::LEDEnum.
|
||||
* @param a The ::LEDEnum to toggle.
|
||||
*/
|
||||
void setLedToggle(LEDEnum a) {
|
||||
// TODO: Implement this
|
||||
(void)a;
|
||||
switchProOutput.reportChanged = true;
|
||||
}
|
||||
|
||||
/** Get the incoming message count. */
|
||||
uint16_t getMessageCounter(){
|
||||
return message_counter;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Used to parse data sent from the Switch Pro controller.
|
||||
* @param len Length of the data.
|
||||
* @param buf Pointer to the data buffer.
|
||||
*/
|
||||
void Parse(uint8_t len, uint8_t *buf);
|
||||
|
||||
/** Used to reset the different buffers to their default values */
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* Send the output to the Switch Pro controller. This is implemented in SwitchProBT.h and SwitchProUSB.h.
|
||||
* @param output Pointer to SwitchProOutput buffer;
|
||||
*/
|
||||
virtual void sendOutputReport(SwitchProOutput *output) = 0;
|
||||
|
||||
|
||||
private:
|
||||
static int8_t getButtonIndexSwitchPro(ButtonEnum b);
|
||||
bool checkDpad(ButtonEnum b); // Used to check Switch Pro DPAD buttons
|
||||
|
||||
SwitchProData switchProData;
|
||||
SwitchProButtons oldButtonState, buttonClickState;
|
||||
SwitchProOutput switchProOutput;
|
||||
uint8_t oldDpad;
|
||||
uint16_t message_counter = 0;
|
||||
};
|
||||
#endif
|
|
@ -181,6 +181,11 @@ enum ButtonEnum {
|
|||
ZL,
|
||||
ZR,
|
||||
/**@}*/
|
||||
|
||||
/**@{*/
|
||||
/** Switch Pro Controller */
|
||||
CAPTURE,
|
||||
/**@}*/
|
||||
};
|
||||
|
||||
inline constexpr int8_t ButtonIndex(ButtonEnum key) {
|
||||
|
@ -190,7 +195,7 @@ inline constexpr int8_t ButtonIndex(ButtonEnum key) {
|
|||
(key == RIGHT || key == YELLOW) ? 1 :
|
||||
(key == DOWN || key == GREEN) ? 2 :
|
||||
(key == LEFT || key == ORANGE) ? 3 :
|
||||
(key == SELECT || key == SHARE || key == BACK || key == VIEW || key == BLUE || key == CREATE) ? 4 :
|
||||
(key == SELECT || key == SHARE || key == BACK || key == VIEW || key == BLUE || key == CREATE || key == CAPTURE) ? 4 :
|
||||
(key == START || key == OPTIONS || key == MENU || key == PLUS) ? 5 :
|
||||
(key == L3 || key == TWO) ? 6 :
|
||||
(key == R3 || key == ONE) ? 7 :
|
||||
|
|
126
examples/Bluetooth/SwitchPro/SwitchPro.ino
Normal file
126
examples/Bluetooth/SwitchPro/SwitchPro.ino
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
Example sketch for the Switch Pro Bluetooth library - developed by Kristian Sloth Lauszus
|
||||
For more information visit the Github repository: github.com/felis/USB_Host_Shield_2.0 or
|
||||
send me an e-mail: lauszus@gmail.com
|
||||
*/
|
||||
|
||||
#include <SwitchProBT.h>
|
||||
#include <usbhub.h>
|
||||
|
||||
// Satisfy the IDE, which needs to see the include statement in the ino too.
|
||||
#ifdef dobogusinclude
|
||||
#include <spi4teensy3.h>
|
||||
#endif
|
||||
#include <SPI.h>
|
||||
|
||||
USB Usb;
|
||||
//USBHub Hub1(&Usb); // Some dongles have a hub inside
|
||||
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
|
||||
|
||||
/* You can create the instance of the SwitchProBT class in two ways */
|
||||
// This will start an inquiry and then pair with the Switch Pro controller - you only have to do this once
|
||||
// You will need to press the Sync button next to the USB connector to put the controller into pairing mode.
|
||||
SwitchProBT SwitchPro(&Btd, PAIR);
|
||||
|
||||
// After that you can simply create the instance like so and then press a button on the device
|
||||
//SwitchProBT SwitchPro(&Btd);
|
||||
|
||||
uint16_t lastMessageCounter = -1;
|
||||
uint32_t home_timer;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
#if !defined(__MIPSEL__)
|
||||
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
|
||||
#endif
|
||||
if (Usb.Init() == -1) {
|
||||
Serial.print(F("\r\nOSC did not start"));
|
||||
while (1); // Halt
|
||||
}
|
||||
Serial.print(F("\r\nSwitch Pro Bluetooth Library Started"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Usb.Task();
|
||||
|
||||
if (SwitchPro.connected() && lastMessageCounter != SwitchPro.getMessageCounter()) {
|
||||
lastMessageCounter = SwitchPro.getMessageCounter();
|
||||
|
||||
if (SwitchPro.getAnalogHat(LeftHatX) > 5000 || SwitchPro.getAnalogHat(LeftHatX) < -5000 ||
|
||||
SwitchPro.getAnalogHat(LeftHatY) > 5000 || SwitchPro.getAnalogHat(LeftHatY) < -5000 ||
|
||||
SwitchPro.getAnalogHat(RightHatX) > 5000 || SwitchPro.getAnalogHat(RightHatX) < -5000 ||
|
||||
SwitchPro.getAnalogHat(RightHatY) > 5000 || SwitchPro.getAnalogHat(RightHatY) < -5000) {
|
||||
Serial.print(F("\r\nLeftHatX: "));
|
||||
Serial.print(SwitchPro.getAnalogHat(LeftHatX));
|
||||
Serial.print(F("\tLeftHatY: "));
|
||||
Serial.print(SwitchPro.getAnalogHat(LeftHatY));
|
||||
Serial.print(F("\tRightHatX: "));
|
||||
Serial.print(SwitchPro.getAnalogHat(RightHatX));
|
||||
Serial.print(F("\tRightHatY: "));
|
||||
Serial.print(SwitchPro.getAnalogHat(RightHatY));
|
||||
}
|
||||
|
||||
// Hold the HOME button for 1 second to disconnect the controller
|
||||
// This prevents the controller from disconnecting when it is reconnected,
|
||||
// as the HOME button is sent when it reconnects
|
||||
if (SwitchPro.getButtonPress(HOME)) {
|
||||
if (millis() - home_timer > 1000)
|
||||
SwitchPro.disconnect();
|
||||
} else
|
||||
home_timer = millis();
|
||||
|
||||
if (SwitchPro.getButtonClick(HOME))
|
||||
Serial.print(F("\r\nHome"));
|
||||
if (SwitchPro.getButtonClick(CAPTURE))
|
||||
Serial.print(F("\r\nCapture"));
|
||||
if (SwitchPro.getButtonClick(LEFT)) {
|
||||
/*SwitchPro.setLedOff();
|
||||
SwitchPro.setLedOn(LED1);*/
|
||||
Serial.print(F("\r\nLeft"));
|
||||
}
|
||||
if (SwitchPro.getButtonClick(RIGHT)) {
|
||||
/*SwitchPro.setLedOff();
|
||||
SwitchPro.setLedOn(LED3);*/
|
||||
Serial.print(F("\r\nRight"));
|
||||
}
|
||||
if (SwitchPro.getButtonClick(DOWN)) {
|
||||
/*SwitchPro.setLedOff();
|
||||
SwitchPro.setLedOn(LED4);*/
|
||||
Serial.print(F("\r\nDown"));
|
||||
}
|
||||
if (SwitchPro.getButtonClick(UP)) {
|
||||
/*SwitchPro.setLedOff();
|
||||
SwitchPro.setLedOn(LED2);*/
|
||||
Serial.print(F("\r\nUp"));
|
||||
}
|
||||
|
||||
if (SwitchPro.getButtonClick(PLUS))
|
||||
Serial.print(F("\r\nPlus"));
|
||||
if (SwitchPro.getButtonClick(MINUS))
|
||||
Serial.print(F("\r\nMinus"));
|
||||
|
||||
if (SwitchPro.getButtonClick(A))
|
||||
Serial.print(F("\r\nA"));
|
||||
if (SwitchPro.getButtonClick(B)) {
|
||||
//SwitchPro.setRumbleToggle();
|
||||
Serial.print(F("\r\nB"));
|
||||
}
|
||||
if (SwitchPro.getButtonClick(X))
|
||||
Serial.print(F("\r\nX"));
|
||||
if (SwitchPro.getButtonClick(Y))
|
||||
Serial.print(F("\r\nY"));
|
||||
|
||||
if (SwitchPro.getButtonClick(L))
|
||||
Serial.print(F("\r\nL"));
|
||||
if (SwitchPro.getButtonClick(R))
|
||||
Serial.print(F("\r\nR"));
|
||||
if (SwitchPro.getButtonClick(ZL))
|
||||
Serial.print(F("\r\nZL"));
|
||||
if (SwitchPro.getButtonClick(ZR))
|
||||
Serial.print(F("\r\nZR"));
|
||||
if (SwitchPro.getButtonClick(L3))
|
||||
Serial.print(F("\r\nL3"));
|
||||
if (SwitchPro.getButtonClick(R3))
|
||||
Serial.print(F("\r\nR3"));
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ PS4BT KEYWORD1
|
|||
PS4USB KEYWORD1
|
||||
PS5BT KEYWORD1
|
||||
PS5USB KEYWORD1
|
||||
SwitchProBT KEYWORD1
|
||||
|
||||
####################################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
|
@ -317,6 +318,7 @@ TopRight LITERAL1
|
|||
BotRight LITERAL1
|
||||
TopLeft LITERAL1
|
||||
BotLeft LITERAL1
|
||||
CAPTURE LITERAL1
|
||||
|
||||
####################################################
|
||||
# Methods and Functions for the IR Camera
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "USB-Host-Shield-20",
|
||||
"keywords": "usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, ps5, buzz, xbox, wii, mass storage",
|
||||
"keywords": "usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, ps5, buzz, xbox, wii, switch pro, mass storage",
|
||||
"description": "Revision 2.0 of MAX3421E-based USB Host Shield Library",
|
||||
"authors":
|
||||
[
|
||||
|
|
|
@ -3,7 +3,7 @@ version=1.5.0
|
|||
author=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Sloth Lauszus <lauszus@gmail.com>, Andrew Kroll <xxxajk@gmail.com>, Alexei Glushchenko (Circuits@Home) <alex-gl@mail.ru>
|
||||
maintainer=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Sloth Lauszus <lauszus@gmail.com>, Andrew Kroll <xxxajk@gmail.com>
|
||||
sentence=Revision 2.0 of MAX3421E-based USB Host Shield Library.
|
||||
paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS5, PS Buzz, Wii and Xbox controllers.
|
||||
paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS5, PS Buzz, Wii, Switch Pro and Xbox controllers.
|
||||
category=Other
|
||||
url=https://github.com/felis/USB_Host_Shield_2.0
|
||||
architectures=*
|
||||
|
|
Loading…
Reference in a new issue