Added support for the Playstation Buzz controllers

See #71
This commit is contained in:
Kristian Lauszus 2014-06-29 18:05:50 +02:00
parent 5776195523
commit 25117ab926
6 changed files with 362 additions and 3 deletions

82
PSBuzz.cpp Normal file
View file

@ -0,0 +1,82 @@
/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. 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 Lauszus, TKJ Electronics
Web : http://www.tkjelectronics.com
e-mail : kristianl@tkjelectronics.com
*/
#include "PSBuzz.h"
// To enable serial debugging see "settings.h"
//#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers
void PSBuzz::ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 0 && buf) {
#ifdef PRINTREPORT
Notify(PSTR("\r\n"), 0x80);
for (uint8_t i = 0; i < len; i++) {
D_PrintHex<uint8_t > (buf[i], 0x80);
Notify(PSTR(" "), 0x80);
}
#endif
memcpy(&psbuzzButtons, buf + 2, min(len - 2, sizeof(psbuzzButtons)));
if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed
buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable
oldButtonState.val = psbuzzButtons.val;
}
}
};
uint8_t PSBuzz::OnInitSuccessful() {
if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) {
Reset();
if (pFuncOnInit)
pFuncOnInit(); // Call the user function
else
setLedOnAll(); // Turn the LED on, on all four controllers
};
return 0;
};
bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) {
return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
};
bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) {
uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
bool click = buttonClickState.val & mask;
buttonClickState.val &= ~mask; // Clear "click" event
return click;
};
// Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c
void PSBuzz::setLedRaw(bool value, uint8_t controller) {
ledState[controller] = value; // Save value for next time it is called
uint8_t buf[7];
buf[0] = 0x00;
buf[1] = ledState[0] ? 0xFF : 0x00;
buf[2] = ledState[1] ? 0xFF : 0x00;
buf[3] = ledState[2] ? 0xFF : 0x00;
buf[4] = ledState[3] ? 0xFF : 0x00;
buf[5] = 0x00;
buf[6] = 0x00;
PSBuzz_Command(buf, sizeof(buf));
};
void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) {
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
};

185
PSBuzz.h Normal file
View file

@ -0,0 +1,185 @@
/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. 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 Lauszus, TKJ Electronics
Web : http://www.tkjelectronics.com
e-mail : kristianl@tkjelectronics.com
*/
#ifndef _psbuzz_h_
#define _psbuzz_h_
#include "hiduniversal.h"
#include "controllerEnums.h"
#define PSBUZZ_VID 0x054C // Sony Corporation
#define PSBUZZ_PID 0x1000 // PS Buzz Controller
/** Struct used to easily read the different buttons on the controllers */
union PSBUZZButtons {
struct {
uint8_t red : 1;
uint8_t yellow : 1;
uint8_t green : 1;
uint8_t orange : 1;
uint8_t blue : 1;
} __attribute__((packed)) btn[4];
uint32_t val : 20;
} __attribute__((packed));
/**
* This class implements support for the PS Buzz controllers via USB.
* It uses the HIDUniversal class for all the USB communication.
*/
class PSBuzz : public HIDUniversal {
public:
/**
* Constructor for the PSBuzz class.
* @param p Pointer to the USB class instance.
*/
PSBuzz(USB *p) :
HIDUniversal(p) {
Reset();
};
/**
* Used to check if a PS Buzz controller is connected.
* @return Returns true if it is connected.
*/
bool connected() {
return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID;
};
/**
* Used to call your own function when the device is successfully initialized.
* @param funcOnInit Function to call.
*/
void attachOnInit(void (*funcOnInit)(void)) {
pFuncOnInit = funcOnInit;
};
/** @name PS Buzzer 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.
* @param controller The controller to read from. Default to 0.
* @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, uint8_t controller = 0);
bool getButtonClick(ButtonEnum b, uint8_t controller = 0);
/**@}*/
/** @name PS Buzzer Controller functions */
/**
* Set LED value without using ::LEDEnum.
* @param value See: ::LEDEnum.
*/
/**
* Set LED values directly.
* @param value Used to set whenever the LED should be on or off
* @param controller The controller to control. Defaults to 0.
*/
void setLedRaw(bool value, uint8_t controller = 0);
/** Turn all LEDs off. */
void setLedOffAll() {
for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
ledState[i] = false; // Just an easy way to set all four off at the same time
setLedRaw(false); // Turn the LED off, on all four controllers
};
/**
* Turn the LED off on a specific controller.
* @param controller The controller to turn off. Defaults to 0.
*/
void setLedOff(uint8_t controller = 0) {
setLedRaw(false, controller);
};
/** Turn all LEDs on. */
void setLedOnAll() {
for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
ledState[i] = true; // Just an easy way to set all four off at the same time
setLedRaw(true); // Turn the LED on, on all four controllers
};
/**
* Turn the LED on on a specific controller.
* @param controller The controller to turn off. Defaults to 0.
*/
void setLedOn(uint8_t controller = 0) {
setLedRaw(true, controller);
};
/**
* Toggle the LED on a specific controller.
* @param controller The controller to turn off. Defaults to 0.
*/
void setLedToggle(uint8_t controller = 0) {
setLedRaw(!ledState[controller], controller);
};
/**@}*/
protected:
/** @name HIDUniversal implementation */
/**
* Used to parse USB HID data.
* @param hid Pointer to the HID class.
* @param is_rpt_id Only used for Hubs.
* @param len The length of the incoming data.
* @param buf Pointer to the data buffer.
*/
virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *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 uint8_t OnInitSuccessful();
/**@}*/
/** Used to reset the different buffers to their default values */
void Reset() {
psbuzzButtons.val = 0;
oldButtonState.val = 0;
buttonClickState.val = 0;
for (uint8_t i = 0; i < sizeof(ledState); i++)
ledState[i] = 0;
};
/** @name USBDeviceConfig implementation */
/**
* Used by the USB core to check what this driver support.
* @param vid The device's VID.
* @param pid The device's PID.
* @return Returns true if the device's VID and PID matches this driver.
*/
virtual boolean VIDPIDOK(uint16_t vid, uint16_t pid) {
return (vid == PSBUZZ_VID && pid == PSBUZZ_PID);
};
/**@}*/
private:
void (*pFuncOnInit)(void); // Pointer to function called in onInit()
void PSBuzz_Command(uint8_t *data, uint16_t nbytes);
PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState;
bool ledState[4];
};
#endif

View file

@ -22,7 +22,7 @@ For more information about the hardware see the [Hardware Manual](http://www.cir
* __Alexei Glushchenko, Circuits@Home__ - <alex-gl@mail.ru>
* Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries
* __Kristian Lauszus, TKJ Electronics__ - <kristianl@tkjelectronics.com>
* Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), and [Xbox](#xbox-library) libraries
* Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), [Xbox](#xbox-library), and [PSBuzz](#ps-buzz-library) libraries
* __Andrew Kroll__ - <xxxajk@gmail.com>
* Major contributor to mass storage code
@ -240,6 +240,17 @@ All the information about the Wii controllers are from these sites:
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus>
* The old library created by _Tomoyuki Tanaka_: <https://github.com/moyuchin/WiiRemote_on_Arduino> also helped a lot.
### [PS Buzz Library](PSBuzz.cpp)
This library implements support for the Playstation Buzz controllers via USB.
It is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off.
More information about the controller can be found at the following sites:
* http://www.developerfusion.com/article/84338/making-usb-c-friendly/
* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c
# FAQ
> When I plug my device into the USB connector nothing happens?

View file

@ -137,6 +137,14 @@ enum ButtonEnum {
BLACK = 8, // Available on the original Xbox controller
WHITE = 9, // Available on the original Xbox controller
/**@}*/
/** PS Buzz controllers */
RED = 0,
YELLOW = 1,
GREEN = 2,
ORANGE = 3,
BLUE = 4,
/**@}*/
};
/** Joysticks on the PS3 and Xbox controllers. */

View file

@ -0,0 +1,46 @@
/*
Example sketch for the Playstation Buzz library - developed by Kristian Lauszus
For more information visit my blog: http://blog.tkjelectronics.dk/ or
send me an e-mail: kristianl@tkjelectronics.com
*/
#include <PSBuzz.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
USB Usb;
PSBuzz Buzz(&Usb);
void setup() {
Serial.begin(115200);
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while (1); // Halt
}
Serial.println(F("\r\nPS Buzz Library Started"));
}
void loop() {
Usb.Task();
if (Buzz.connected()) {
for (uint8_t i = 0; i < 4; i++) {
if (Buzz.getButtonClick(RED, i)) {
Buzz.setLedToggle(i); // Toggle the LED
Serial.println(F("RED"));
}
if (Buzz.getButtonClick(YELLOW, i))
Serial.println(F("YELLOW"));
if (Buzz.getButtonClick(GREEN, i))
Serial.println(F("GREEN"));
if (Buzz.getButtonClick(ORANGE, i))
Serial.println(F("ORANGE"));
if (Buzz.getButtonClick(BLUE, i))
Serial.println(F("BLUE"));
}
}
}

View file

@ -318,7 +318,7 @@ getIRy4 KEYWORD2
getIRs4 KEYWORD2
####################################################
# Syntax Coloring Map For RFCOMM/SPP Library
# Syntax Coloring Map For BTHID Library
####################################################
####################################################
@ -332,3 +332,30 @@ BTHID KEYWORD1
####################################################
SetReportParser KEYWORD2
setProtocolMode KEYWORD2
####################################################
# Syntax Coloring Map For PS Buzz Library
####################################################
####################################################
# Datatypes (KEYWORD1)
####################################################
PSBuzz KEYWORD1
####################################################
# Methods and Functions (KEYWORD2)
####################################################
setLedOnAll KEYWORD2
setLedOffAll KEYWORD2
####################################################
# Constants and enums (LITERAL1)
####################################################
RED LITERAL1
YELLOW LITERAL1
GREEN LITERAL1
ORANGE LITERAL1
BLUE LITERAL1